Skip to content

Commit 5f4b8e2

Browse files
Federico FrascarelliiText-CI
authored andcommitted
fix issue in pdfTokenizer, if minus char '-' is found after '.' in a real number then omitt everything after the '.' char. following the adobe reader rule
DEVSIX-2674
1 parent 6fdb7b1 commit 5f4b8e2

File tree

4 files changed

+170
-3
lines changed

4 files changed

+170
-3
lines changed

io/src/main/java/com/itextpdf/io/source/PdfTokenizer.java

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -454,12 +454,31 @@ public boolean nextToken() throws java.io.IOException {
454454
// as we need to know that fact only in case if there are any minuses.
455455
ch = file.read();
456456
}
457-
while (ch != -1 && ((ch >= '0' && ch <= '9') || ch == '.')) {
458-
if (ch == '.')
459-
isReal = true;
457+
while (ch >= '0' && ch <= '9') {
460458
outBuf.append(ch);
461459
ch = file.read();
462460
}
461+
462+
if ( ch == '.'){
463+
isReal = true;
464+
outBuf.append(ch);
465+
ch = file.read();
466+
467+
//verify if there is minus after '.'
468+
//In that case just ignore minus chars and everything after as Adobe Reader does
469+
int numberOfMinusesAfterDot = 0;
470+
if (ch == '-') {
471+
numberOfMinusesAfterDot++;
472+
ch = file.read();
473+
}
474+
while (ch >= '0' && ch <= '9') {
475+
if (numberOfMinusesAfterDot == 0) {
476+
outBuf.append(ch);
477+
}
478+
ch = file.read();
479+
}
480+
}
481+
463482
if (numberOfMinuses > 1 && !isReal) {
464483
// Numbers of integer type and with more than one minus before them
465484
// are interpreted by Acrobat as zero.
Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
/*
2+
This file is part of the iText (R) project.
3+
Copyright (c) 1998-2019 iText Group NV
4+
Authors: iText Software.
5+
6+
This program is free software; you can redistribute it and/or modify
7+
it under the terms of the GNU Affero General Public License version 3
8+
as published by the Free Software Foundation with the addition of the
9+
following permission added to Section 15 as permitted in Section 7(a):
10+
FOR ANY PART OF THE COVERED WORK IN WHICH THE COPYRIGHT IS OWNED BY
11+
ITEXT GROUP. ITEXT GROUP DISCLAIMS THE WARRANTY OF NON INFRINGEMENT
12+
OF THIRD PARTY RIGHTS
13+
14+
This program is distributed in the hope that it will be useful, but
15+
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
16+
or FITNESS FOR A PARTICULAR PURPOSE.
17+
See the GNU Affero General Public License for more details.
18+
You should have received a copy of the GNU Affero General Public License
19+
along with this program; if not, see http://www.gnu.org/licenses or write to
20+
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21+
Boston, MA, 02110-1301 USA, or download the license from the following URL:
22+
http://itextpdf.com/terms-of-use/
23+
24+
The interactive user interfaces in modified source and object code versions
25+
of this program must display Appropriate Legal Notices, as required under
26+
Section 5 of the GNU Affero General Public License.
27+
28+
In accordance with Section 7(b) of the GNU Affero General Public License,
29+
a covered work must retain the producer line in every PDF that is created
30+
or manipulated using iText.
31+
32+
You can be released from the requirements of the license by purchasing
33+
a commercial license. Buying such a license is mandatory as soon as you
34+
develop commercial activities involving the iText software without
35+
disclosing the source code of your own applications.
36+
These activities include: offering paid services to customers as an ASP,
37+
serving PDFs on the fly in a web application, shipping iText with a closed
38+
source product.
39+
40+
For more information, please contact iText Software Corp. at this
41+
42+
*/
43+
package com.itextpdf.kernel.pdf;
44+
45+
import com.itextpdf.kernel.utils.CompareTool;
46+
import com.itextpdf.test.ExtendedITextTest;
47+
import com.itextpdf.test.annotations.type.IntegrationTest;
48+
import org.junit.Assert;
49+
import org.junit.BeforeClass;
50+
import org.junit.Test;
51+
import org.junit.experimental.categories.Category;
52+
import org.xml.sax.SAXException;
53+
54+
import javax.xml.parsers.ParserConfigurationException;
55+
import java.io.IOException;
56+
import java.util.Arrays;
57+
58+
import static org.junit.Assert.assertTrue;
59+
60+
@Category(IntegrationTest.class)
61+
public class PdfDictionaryTokenizerTest extends ExtendedITextTest {
62+
63+
public static final String sourceFolder = "./src/test/resources/com/itextpdf/kernel/pdf/PdfDictionaryTokenizerTest/";
64+
public static final String destinationFolder = "./target/test/com/itextpdf/kernel/pdf/PdfDictionaryTokenizerTest/";
65+
66+
@BeforeClass
67+
public static void beforeClass() {
68+
createOrClearDestinationFolder(destinationFolder);
69+
}
70+
71+
@Test
72+
public void readerTurnsCorrectlyNotWellFormattedValueInDictionary_01() throws IOException, InterruptedException, ParserConfigurationException, SAXException {
73+
74+
String inPath = sourceFolder + "documentWithMalformedNumberOnDictionary.pdf";
75+
String EXPECTED="-12.";
76+
77+
/*
78+
The following is the content included in the pdf file
79+
80+
<</Ascent 800
81+
/CapHeight 700
82+
/Descent -200
83+
/Flags 32
84+
/FontBBox[-631 -462 1632 1230]
85+
/FontFamily(FreeSans)
86+
/FontFile2 8 0 R
87+
/FontName/XVVAXW+FreeSans
88+
/FontWeight 400
89+
/ItalicAngle -12.-23
90+
/StemV 80
91+
/Type/FontDescriptor>>
92+
*/
93+
94+
// ItalicAngle -12.-23 turns into -12.
95+
96+
String result = getItalicAngleValue(inPath);
97+
Assert.assertEquals(EXPECTED, result);
98+
}
99+
100+
@Test
101+
public void readerTurnsCorrectlyNotWellFormattedValueInDictionary_02() throws IOException, InterruptedException, ParserConfigurationException, SAXException {
102+
103+
String inPath = sourceFolder + "documentWithMalformedNumberOnDictionary2.pdf";
104+
String EXPECTED="-12.";
105+
106+
/*
107+
The following is the content included in the pdf file
108+
109+
<</Ascent 800
110+
/CapHeight 700
111+
/Descent -200
112+
/Flags 32
113+
/FontBBox[-631 -462 1632 1230]
114+
/FontFamily(FreeSans)
115+
/FontFile2 8 0 R
116+
/FontName/XVVAXW+FreeSans
117+
/FontWeight 400
118+
/StemV 80
119+
/Type/FontDescriptor
120+
/ItalicAngle -12.-23>>
121+
*/
122+
123+
// ItalicAngle -12.-23 turns into -12.
124+
125+
String result = getItalicAngleValue(inPath);
126+
Assert.assertEquals(EXPECTED, result);
127+
}
128+
129+
private String getItalicAngleValue(String inPath) throws IOException {
130+
String result = "";
131+
PdfReader pdfR = new PdfReader(inPath);
132+
PdfDocument attachmentPDF = new PdfDocument(pdfR);
133+
int max = attachmentPDF.getNumberOfPdfObjects();
134+
for (int i=0;i<max;i++){
135+
PdfObject obj = attachmentPDF.getPdfObject(i);
136+
if (obj!=null ){
137+
PdfDictionary pdfDict = (PdfDictionary) obj;
138+
PdfObject x = pdfDict.get(PdfName.Type);
139+
if(x!=null && x.equals(PdfName.FontDescriptor)){
140+
PdfObject italicAngle = pdfDict.get(PdfName.ItalicAngle);
141+
result = italicAngle.toString();
142+
}
143+
}
144+
}
145+
attachmentPDF.close();
146+
return result;
147+
}
148+
}

0 commit comments

Comments
 (0)