git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1896899 13f79535-47bb-0310-9956-ffa450edef68tags/REL_5_2_1
// http://forums.gradle.org/gradle/topics/jacoco_related_failure_in_multiproject_build | // http://forums.gradle.org/gradle/topics/jacoco_related_failure_in_multiproject_build | ||||
systemProperties['user.dir'] = workingDir | systemProperties['user.dir'] = workingDir | ||||
systemProperties['java.io.tmpdir'] = 'build' | |||||
systemProperties['java.io.tmpdir'] = 'build' | |||||
systemProperties['POI.testdata.path'] = '../test-data' | systemProperties['POI.testdata.path'] = '../test-data' | ||||
binDistZip.dependsOn 'zipJavadocs', ':poi-ooxml-lite:jar' | binDistZip.dependsOn 'zipJavadocs', ':poi-ooxml-lite:jar' | ||||
binDistTar.dependsOn 'zipJavadocs', ':poi-ooxml-lite:jar' | binDistTar.dependsOn 'zipJavadocs', ':poi-ooxml-lite:jar' | ||||
task soLinkCheck() { | |||||
doLast { | |||||
def path = ant.path { | |||||
fileset(dir: '.', includes: '**/*.java') { | |||||
exclude(name: 'build.gradle') | |||||
contains(text: 'stackoverflow.com') | |||||
} | |||||
} | |||||
path.list().each { | |||||
println it | |||||
} | |||||
if (path.size() > 0) { | |||||
// #65796 - minimize notifications about non-asf open source | |||||
throw new GradleException('License issue found - conceal the link and contradict any findings m(') | |||||
} | |||||
} | |||||
} | |||||
var srcDep = [ | var srcDep = [ | ||||
':poi:cacheJava9', | ':poi:cacheJava9', | ||||
':poi:cacheTest9', | ':poi:cacheTest9', | ||||
srcDistTar.dependsOn srcDep | srcDistTar.dependsOn srcDep | ||||
srcDistZip.dependsOn srcDep | srcDistZip.dependsOn srcDep | ||||
rat.dependsOn srcDep | |||||
soLinkCheck.dependsOn srcDep | |||||
rat.dependsOn soLinkCheck | |||||
task fixDistDir { | task fixDistDir { | ||||
doLast { | doLast { |
series2.setTitle(series[1], chart.setSheetTitle(series[1], COLUMN_SPEAKERS)); | series2.setTitle(series[1], chart.setSheetTitle(series[1], COLUMN_SPEAKERS)); | ||||
chart.plot(bar); | chart.plot(bar); | ||||
chart.setTitleText(chartTitle); // https://stackoverflow.com/questions/30532612 | |||||
chart.setTitleText(chartTitle); | |||||
// chart.setTitleOverlay(overlay); | // chart.setTitleOverlay(overlay); | ||||
// adjust font size for readability | // adjust font size for readability |
import org.apache.poi.xssf.usermodel.XSSFSheet; | import org.apache.poi.xssf.usermodel.XSSFSheet; | ||||
import org.apache.poi.xssf.usermodel.XSSFWorkbook; | import org.apache.poi.xssf.usermodel.XSSFWorkbook; | ||||
// original contributions by Axel Richter on https://stackoverflow.com/questions/47065690 | |||||
// additional title formatting from https://stackoverflow.com/questions/50418856 | |||||
// and legend positioning from https://stackoverflow.com/questions/49615379 | |||||
// this would probably be an answer for https://stackoverflow.com/questions/36447925 too | |||||
public final class BarAndLineChart { | public final class BarAndLineChart { | ||||
private static final int NUM_OF_ROWS = 7; | private static final int NUM_OF_ROWS = 7; |
// Use a category axis for the bottom axis. | // Use a category axis for the bottom axis. | ||||
XDDFCategoryAxis bottomAxis = chart.createCategoryAxis(AxisPosition.BOTTOM); | XDDFCategoryAxis bottomAxis = chart.createCategoryAxis(AxisPosition.BOTTOM); | ||||
bottomAxis.setTitle("x"); // https://stackoverflow.com/questions/32010765 | |||||
bottomAxis.setTitle("x"); | |||||
XDDFValueAxis leftAxis = chart.createValueAxis(AxisPosition.LEFT); | XDDFValueAxis leftAxis = chart.createValueAxis(AxisPosition.LEFT); | ||||
leftAxis.setTitle("f(x)"); | leftAxis.setTitle("f(x)"); | ||||
leftAxis.setCrosses(AxisCrosses.AUTO_ZERO); | leftAxis.setCrosses(AxisCrosses.AUTO_ZERO); | ||||
XDDFChartData data = chart.createData(ChartTypes.BAR, bottomAxis, leftAxis); | XDDFChartData data = chart.createData(ChartTypes.BAR, bottomAxis, leftAxis); | ||||
XDDFChartData.Series series1 = data.addSeries(xs, ys1); | XDDFChartData.Series series1 = data.addSeries(xs, ys1); | ||||
series1.setTitle("2x", null); // https://stackoverflow.com/questions/21855842 | |||||
series1.setTitle("2x", null); | |||||
XDDFChartData.Series series2 = data.addSeries(xs, ys2); | XDDFChartData.Series series2 = data.addSeries(xs, ys2); | ||||
series2.setTitle("3x", null); | series2.setTitle("3x", null); | ||||
chart.plot(data); | chart.plot(data); |
import org.apache.poi.xssf.usermodel.XSSFWorkbook; | import org.apache.poi.xssf.usermodel.XSSFWorkbook; | ||||
/** | /** | ||||
* This example is based on original contributions by Axel Richter on StackOverflow. | |||||
* This example is based on original contributions by Axel Richter | |||||
* | * | ||||
* <em>Note from original author</em>: | * <em>Note from original author</em>: | ||||
* This only works for Excel since OpenOffice or LibreOffice Calc is not able having series having literal numeric values set. | * This only works for Excel since OpenOffice or LibreOffice Calc is not able having series having literal numeric values set. | ||||
* | |||||
* @see <a href="https://stackoverflow.com/questions/50772989/">Create target marker in a bar chart with openxmlformats</a> | |||||
* @see <a href="https://stackoverflow.com/questions/50873700/">Change axis color and font of the chart in openxmlformats</a> | |||||
* @see <a href="https://stackoverflow.com/questions/51530552/">Change colors of line chart Apache POI</a> | |||||
*/ | */ | ||||
public final class ExcelChartWithTargetLine { | public final class ExcelChartWithTargetLine { | ||||
private ExcelChartWithTargetLine() {} | private ExcelChartWithTargetLine() {} | ||||
leftValues.crossAxis(barCategories); | leftValues.crossAxis(barCategories); | ||||
barCategories.crossAxis(leftValues); | barCategories.crossAxis(leftValues); | ||||
// from https://stackoverflow.com/questions/50873700/ | |||||
// colored major grid lines | // colored major grid lines | ||||
leftValues.getOrAddMajorGridProperties().setLineProperties(solidTomato); | leftValues.getOrAddMajorGridProperties().setLineProperties(solidTomato); | ||||
//colored axis line | //colored axis line | ||||
} | } | ||||
// from https://stackoverflow.com/questions/51530552/ | |||||
// customize the chart | // customize the chart | ||||
// do not auto delete the title | // do not auto delete the title |
// Use a category axis for the bottom axis. | // Use a category axis for the bottom axis. | ||||
XDDFCategoryAxis bottomAxis = chart.createCategoryAxis(AxisPosition.BOTTOM); | XDDFCategoryAxis bottomAxis = chart.createCategoryAxis(AxisPosition.BOTTOM); | ||||
bottomAxis.setTitle("x"); // https://stackoverflow.com/questions/32010765 | |||||
bottomAxis.setTitle("x"); | |||||
XDDFValueAxis leftAxis = chart.createValueAxis(AxisPosition.LEFT); | XDDFValueAxis leftAxis = chart.createValueAxis(AxisPosition.LEFT); | ||||
leftAxis.setTitle("f(x)"); | leftAxis.setTitle("f(x)"); | ||||
leftAxis.setCrosses(AxisCrosses.AUTO_ZERO); | leftAxis.setCrosses(AxisCrosses.AUTO_ZERO); | ||||
XDDFLineChartData data = (XDDFLineChartData) chart.createData(ChartTypes.LINE, bottomAxis, leftAxis); | XDDFLineChartData data = (XDDFLineChartData) chart.createData(ChartTypes.LINE, bottomAxis, leftAxis); | ||||
XDDFLineChartData.Series series1 = (XDDFLineChartData.Series) data.addSeries(xs, ys1); | XDDFLineChartData.Series series1 = (XDDFLineChartData.Series) data.addSeries(xs, ys1); | ||||
series1.setTitle("2x", null); // https://stackoverflow.com/questions/21855842 | |||||
series1.setSmooth(false); // https://stackoverflow.com/questions/29014848 | |||||
series1.setMarkerStyle(MarkerStyle.STAR); // https://stackoverflow.com/questions/39636138 | |||||
series1.setTitle("2x", null); | |||||
series1.setSmooth(false); | |||||
series1.setMarkerStyle(MarkerStyle.STAR); | |||||
XDDFLineChartData.Series series2 = (XDDFLineChartData.Series) data.addSeries(xs, ys2); | XDDFLineChartData.Series series2 = (XDDFLineChartData.Series) data.addSeries(xs, ys2); | ||||
series2.setTitle("3x", null); | series2.setTitle("3x", null); | ||||
series2.setSmooth(true); | series2.setSmooth(true); | ||||
series2.setMarkerSize((short) 6); | series2.setMarkerSize((short) 6); | ||||
series2.setMarkerStyle(MarkerStyle.TRIANGLE); // https://stackoverflow.com/questions/39636138 | |||||
series2.setMarkerStyle(MarkerStyle.TRIANGLE); | |||||
chart.plot(data); | chart.plot(data); | ||||
// if your series have missing values like https://stackoverflow.com/questions/29014848 | |||||
// if your series have missing values | |||||
// chart.displayBlanksAs(DisplayBlanks.GAP); | // chart.displayBlanksAs(DisplayBlanks.GAP); | ||||
// https://stackoverflow.com/questions/24676460 | |||||
solidLineSeries(data, 0, PresetColor.CHARTREUSE); | solidLineSeries(data, 0, PresetColor.CHARTREUSE); | ||||
solidLineSeries(data, 1, PresetColor.TURQUOISE); | solidLineSeries(data, 1, PresetColor.TURQUOISE); | ||||
legend.setPosition(LegendPosition.TOP_RIGHT); | legend.setPosition(LegendPosition.TOP_RIGHT); | ||||
XDDFValueAxis bottomAxis = chart.createValueAxis(AxisPosition.BOTTOM); | XDDFValueAxis bottomAxis = chart.createValueAxis(AxisPosition.BOTTOM); | ||||
bottomAxis.setTitle("x"); // https://stackoverflow.com/questions/32010765 | |||||
bottomAxis.setTitle("x"); | |||||
XDDFValueAxis leftAxis = chart.createValueAxis(AxisPosition.LEFT); | XDDFValueAxis leftAxis = chart.createValueAxis(AxisPosition.LEFT); | ||||
leftAxis.setTitle("f(x)"); | leftAxis.setTitle("f(x)"); | ||||
leftAxis.setCrosses(AxisCrosses.AUTO_ZERO); | leftAxis.setCrosses(AxisCrosses.AUTO_ZERO); | ||||
XDDFScatterChartData data = (XDDFScatterChartData) chart.createData(ChartTypes.SCATTER, bottomAxis, leftAxis); | XDDFScatterChartData data = (XDDFScatterChartData) chart.createData(ChartTypes.SCATTER, bottomAxis, leftAxis); | ||||
XDDFScatterChartData.Series series1 = (XDDFScatterChartData.Series) data.addSeries(xs, ys1); | XDDFScatterChartData.Series series1 = (XDDFScatterChartData.Series) data.addSeries(xs, ys1); | ||||
series1.setTitle("2x", null); // https://stackoverflow.com/questions/21855842 | |||||
series1.setSmooth(false); // https://stackoverflow.com/questions/39636138 | |||||
series1.setTitle("2x", null); | |||||
series1.setSmooth(false); | |||||
XDDFScatterChartData.Series series2 = (XDDFScatterChartData.Series) data.addSeries(xs, ys2); | XDDFScatterChartData.Series series2 = (XDDFScatterChartData.Series) data.addSeries(xs, ys2); | ||||
series2.setTitle("3x", null); | series2.setTitle("3x", null); | ||||
chart.plot(data); | chart.plot(data); |
series2.setTitle(series[1], chart.setSheetTitle(series[1], 1)); | series2.setTitle(series[1], chart.setSheetTitle(series[1], 1)); | ||||
chart.plot(bar); | chart.plot(bar); | ||||
chart.setTitleText(chartTitle); // https://stackoverflow.com/questions/30532612 | |||||
chart.setTitleText(chartTitle); | |||||
chart.setTitleOverlay(false); | chart.setTitleOverlay(false); | ||||
} | } | ||||
trans.setOutputProperty(OutputKeys.ENCODING, "UTF-8"); | trans.setOutputProperty(OutputKeys.ENCODING, "UTF-8"); | ||||
// don't indent xml documents, the indent will cause errors in calculating the xml signature | // don't indent xml documents, the indent will cause errors in calculating the xml signature | ||||
// because of different handling of linebreaks in Windows/Unix | // because of different handling of linebreaks in Windows/Unix | ||||
// see https://stackoverflow.com/questions/36063375 | |||||
trans.setOutputProperty(OutputKeys.INDENT, "no"); | trans.setOutputProperty(OutputKeys.INDENT, "no"); | ||||
trans.setOutputProperty(OutputKeys.STANDALONE, "yes"); | trans.setOutputProperty(OutputKeys.STANDALONE, "yes"); | ||||
trans.transform(xmlSource, outputTarget); | trans.transform(xmlSource, outputTarget); |
public void init() throws GeneralSecurityException { | public void init() throws GeneralSecurityException { | ||||
if (isMSCapi(key)) { | if (isMSCapi(key)) { | ||||
// see https://stackoverflow.com/questions/39196145 for problems with SunMSCAPI | |||||
// and why we can't sign the calculated digest | |||||
// SunMSCAPI can't be used to sign the calculated digest | |||||
throw new EncryptedDocumentException( | throw new EncryptedDocumentException( | ||||
"Windows keystore entries can't be signed with the "+algo+" hash. Please "+ | "Windows keystore entries can't be signed with the "+algo+" hash. Please "+ | ||||
"use one digest algorithm of sha1 / sha256 / sha384 / sha512."); | "use one digest algorithm of sha1 / sha256 / sha384 / sha512."); |
if (part.getPartName().toString().endsWith(".rels")) { | if (part.getPartName().toString().endsWith(".rels")) { | ||||
// although xmlsec has an option to ignore line breaks, currently this | // although xmlsec has an option to ignore line breaks, currently this | ||||
// only affects .rels files, so we only modify these | // only affects .rels files, so we only modify these | ||||
// http://stackoverflow.com/questions/4728300 | |||||
try (UnsynchronizedByteArrayOutputStream bos = new UnsynchronizedByteArrayOutputStream()) { | try (UnsynchronizedByteArrayOutputStream bos = new UnsynchronizedByteArrayOutputStream()) { | ||||
for (int ch; (ch = dataStream.read()) != -1; ) { | for (int ch; (ch = dataStream.read()) != -1; ) { | ||||
if (ch == 10 || ch == 13) continue; | if (ch == 10 || ch == 13) continue; |
* and converts it to another XML document. | * and converts it to another XML document. | ||||
* | * | ||||
* @see <a href="https://www.ecma-international.org/activities/Office%20Open%20XML%20Formats/Draft%20ECMA-376%203rd%20edition,%20March%202011/Office%20Open%20XML%20Part%202%20-%20Open%20Packaging%20Conventions.pdf">13.2.4.24 Relationships Transform Algorithm</a> | * @see <a href="https://www.ecma-international.org/activities/Office%20Open%20XML%20Formats/Draft%20ECMA-376%203rd%20edition,%20March%202011/Office%20Open%20XML%20Part%202%20-%20Open%20Packaging%20Conventions.pdf">13.2.4.24 Relationships Transform Algorithm</a> | ||||
* @see <a href="https://stackoverflow.com/questions/36063375">XML Relationship Transform Algorithm</a> | |||||
*/ | */ | ||||
public Data transform(Data data, XMLCryptoContext context) throws TransformException { | public Data transform(Data data, XMLCryptoContext context) throws TransformException { | ||||
LOG.atDebug().log("transform(data,context)"); | LOG.atDebug().log("transform(data,context)"); |
* Taken (with permission) from https://gist.github.com/msteiger/4509119, | * Taken (with permission) from https://gist.github.com/msteiger/4509119, | ||||
* including the fixes that are discussed in the comments | * including the fixes that are discussed in the comments | ||||
* | * | ||||
* @see <a href="https://stackoverflow.com/questions/14258206/">Gradient paints not working in Apache Batik's svggen</a> | |||||
* @see <a href="https://issues.apache.org/jira/browse/BATIK-1032">BATIK-1032</a> | * @see <a href="https://issues.apache.org/jira/browse/BATIK-1032">BATIK-1032</a> | ||||
*/ | */ | ||||
@Internal | @Internal |
} | } | ||||
public KeyCertPair addEntryFromPEM(File pemFile, String keyPass) throws IOException, CertificateException, KeyStoreException { | public KeyCertPair addEntryFromPEM(File pemFile, String keyPass) throws IOException, CertificateException, KeyStoreException { | ||||
// see https://stackoverflow.com/questions/11787571/how-to-read-pem-file-to-get-private-and-public-key | |||||
PrivateKey key = null; | PrivateKey key = null; | ||||
X509Certificate x509 = null; | X509Certificate x509 = null; | ||||
/** | /** | ||||
* Ensure we can encrypt a package that is missing the Core | * Ensure we can encrypt a package that is missing the Core | ||||
* Properties, eg one from dodgy versions of Jasper Reports | * Properties, eg one from dodgy versions of Jasper Reports | ||||
* See https://github.com/nestoru/xlsxenc/ and | |||||
* http://stackoverflow.com/questions/28593223 | |||||
* See https://github.com/nestoru/xlsxenc/ | |||||
*/ | */ | ||||
@Test | @Test | ||||
void encryptPackageWithoutCoreProperties() throws Exception { | void encryptPackageWithoutCoreProperties() throws Exception { | ||||
aehHeader.setHashAlgorithm(HashAlgorithm.sha1); | aehHeader.setHashAlgorithm(HashAlgorithm.sha1); | ||||
AgileEncryptionVerifier aehVerifier = (AgileEncryptionVerifier)eiNew.getVerifier(); | AgileEncryptionVerifier aehVerifier = (AgileEncryptionVerifier)eiNew.getVerifier(); | ||||
// this cast might look strange - if the setters would be public, it will become obsolete | |||||
// see http://stackoverflow.com/questions/5637650/overriding-protected-methods-in-java | |||||
((EncryptionVerifier)aehVerifier).setCipherAlgorithm(CipherAlgorithm.aes256); | |||||
aehVerifier.setCipherAlgorithm(CipherAlgorithm.aes256); | |||||
aehVerifier.setHashAlgorithm(HashAlgorithm.sha512); | aehVerifier.setHashAlgorithm(HashAlgorithm.sha512); | ||||
Encryptor enc = eiNew.getEncryptor(); | Encryptor enc = eiNew.getEncryptor(); | ||||
@Test | @Test | ||||
void smallFile() throws IOException, GeneralSecurityException { | void smallFile() throws IOException, GeneralSecurityException { | ||||
// see https://stackoverflow.com/questions/61463301 | |||||
final int tinyFileSize = 80_000_000; | final int tinyFileSize = 80_000_000; | ||||
final String pass = "s3cr3t"; | final String pass = "s3cr3t"; | ||||
private void setFont(TextBox<?,?> tb, String fontFamily, FontGroup fontGroup) { | private void setFont(TextBox<?,?> tb, String fontFamily, FontGroup fontGroup) { | ||||
// TODO: set east asian font family - MS Office uses "MS Mincho" or "MS Gothic" as a fallback | // TODO: set east asian font family - MS Office uses "MS Mincho" or "MS Gothic" as a fallback | ||||
// see https://stackoverflow.com/questions/26063828 for good explanation about the font metrics | |||||
// differences on different environments | |||||
for (TextParagraph<?,?,? extends TextRun> p : tb.getTextParagraphs()) { | for (TextParagraph<?,?,? extends TextRun> p : tb.getTextParagraphs()) { | ||||
for (TextRun r : p.getTextRuns()) { | for (TextRun r : p.getTextRuns()) { | ||||
r.setFontFamily(fontFamily, fontGroup); | r.setFontFamily(fontFamily, fontGroup); |
} | } | ||||
} | } | ||||
/** | |||||
* See https://stackoverflow.com/questions/44407111/apache-poi-cant-format-filled-cells-as-numeric | |||||
*/ | |||||
@Test | @Test | ||||
void testNumericCellsInTable() throws IOException { | void testNumericCellsInTable() throws IOException { | ||||
try (XSSFWorkbook wb = new XSSFWorkbook()) { | try (XSSFWorkbook wb = new XSSFWorkbook()) { |
Color inter = DrawPaint.SCRGB2RGB(r,g,b); | Color inter = DrawPaint.SCRGB2RGB(r,g,b); | ||||
return new Color(inter.getRed(), inter.getGreen(), inter.getBlue(), a); | return new Color(inter.getRed(), inter.getGreen(), inter.getBlue(), a); | ||||
} | } | ||||
/* | |||||
private Color interpolateColorsHSL(final double factor) { | |||||
final double[] hslStart = DrawPaint.RGB2HSL(startColor); | |||||
final double[] hslStop = DrawPaint.RGB2HSL(endColor); | |||||
BiFunction<Number,Number,Double> linearInter = (start, stop) -> | |||||
start.doubleValue()+(stop.doubleValue()-start.doubleValue())*factor; | |||||
double alpha = linearInter.apply(startColor.getAlpha(),endColor.getAlpha()); | |||||
double sat = linearInter.apply(hslStart[1],hslStop[1]); | |||||
double lum = linearInter.apply(hslStart[2],hslStop[2]); | |||||
// find closest match - decide if need to go clockwise or counter-clockwise | |||||
// https://stackoverflow.com/questions/1416560/hsl-interpolation | |||||
double hueMidCW = (hslStart[0]+hslStop[0])/2.; | |||||
double hueMidCCW = (hslStart[0]+hslStop[0]+360.)/2.; | |||||
Function<Double,Double> hueDelta = (hue) -> | |||||
Math.min(Math.abs(hslStart[0]-hue), Math.abs(hslStop[0]-hue)); | |||||
double hslDiff; | |||||
if (hueDelta.apply(hueMidCW) > hueDelta.apply(hueMidCCW)) { | |||||
hslDiff = (hslStart[0] < hslStop[0]) ? hslStop[0]-hslStart[0] : (360-hslStart[0])+hslStop[0]; | |||||
} else { | |||||
hslDiff = (hslStart[0] < hslStop[0]) ? -hslStart[0]-(360-hslStop[0]) : -(hslStart[0]-hslStop[0]); | |||||
} | |||||
double hue = (hslStart[0]+hslDiff*factor)%360.; | |||||
return DrawPaint.HSL2RGB(hue, sat, lum, alpha/255.); | |||||
} */ | |||||
} | } | ||||
/** The EmfPlusPathGradientBrushData object specifies a path gradient for a graphics brush. */ | /** The EmfPlusPathGradientBrushData object specifies a path gradient for a graphics brush. */ |
// TODO: fix font height calculation | // TODO: fix font height calculation | ||||
// the height is given as font size + ascent + descent | // the height is given as font size + ascent + descent | ||||
// as an approximation we reduce the height by a static factor | // as an approximation we reduce the height by a static factor | ||||
// | |||||
// see https://stackoverflow.com/a/26564924/2066598 on to get the font size from the cell height | |||||
return fontHeight*3/4; | return fontHeight*3/4; | ||||
} | } | ||||
} | } |
// desx is not supported. Not sure, if it can be simulated by des3 somehow | // desx is not supported. Not sure, if it can be simulated by des3 somehow | ||||
des3(null, "DESede", -1, 192, new int[]{192}, 8, 32, "3DES", false), | des3(null, "DESede", -1, 192, new int[]{192}, 8, 32, "3DES", false), | ||||
// need bouncycastle provider for this one ... | // need bouncycastle provider for this one ... | ||||
// see http://stackoverflow.com/questions/4436397/3des-des-encryption-using-the-jce-generating-an-acceptable-key | |||||
des3_112(null, "DESede", -1, 128, new int[]{128}, 8, 32, "3DES_112", true), | des3_112(null, "DESede", -1, 128, new int[]{128}, 8, 32, "3DES_112", true), | ||||
// only for digital signatures | // only for digital signatures | ||||
rsa(null, "RSA", -1, 1024, new int[]{1024, 2048, 3072, 4096}, -1, -1, "", false); | rsa(null, "RSA", -1, 1024, new int[]{1024, 2048, 3072, 4096}, -1, -1, "", false); | ||||
public final int encryptedVerifierHashLength; | public final int encryptedVerifierHashLength; | ||||
public final String xmlId; | public final String xmlId; | ||||
public final boolean needsBouncyCastle; | public final boolean needsBouncyCastle; | ||||
CipherAlgorithm(CipherProvider provider, String jceId, int ecmaId, int defaultKeySize, int[] allowedKeySize, int blockSize, int encryptedVerifierHashLength, String xmlId, boolean needsBouncyCastle) { | CipherAlgorithm(CipherProvider provider, String jceId, int ecmaId, int defaultKeySize, int[] allowedKeySize, int blockSize, int encryptedVerifierHashLength, String xmlId, boolean needsBouncyCastle) { | ||||
this.provider = provider; | this.provider = provider; | ||||
this.jceId = jceId; | this.jceId = jceId; | ||||
} | } | ||||
throw new EncryptedDocumentException("cipher algorithm " + ecmaId + " not found"); | throw new EncryptedDocumentException("cipher algorithm " + ecmaId + " not found"); | ||||
} | } | ||||
public static CipherAlgorithm fromXmlId(String xmlId, int keySize) { | public static CipherAlgorithm fromXmlId(String xmlId, int keySize) { | ||||
for (CipherAlgorithm ca : CipherAlgorithm.values()) { | for (CipherAlgorithm ca : CipherAlgorithm.values()) { | ||||
if (!ca.xmlId.equals(xmlId)) continue; | if (!ca.xmlId.equals(xmlId)) continue; |
} | } | ||||
// limit wrong calculated ole entries - (bug #57080) | // limit wrong calculated ole entries - (bug #57080) | ||||
// standard encryption always uses aes encoding, so blockSize is always 16 | // standard encryption always uses aes encoding, so blockSize is always 16 | ||||
// http://stackoverflow.com/questions/3283787/size-of-data-after-aes-encryption | |||||
int blockSize = getEncryptionInfo().getHeader().getCipherAlgorithm().blockSize; | int blockSize = getEncryptionInfo().getHeader().getCipherAlgorithm().blockSize; | ||||
long cipherLen = (_length/blockSize + 1) * blockSize; | long cipherLen = (_length/blockSize + 1) * blockSize; | ||||
Cipher cipher = getCipher(getSecretKey()); | Cipher cipher = getCipher(getSecretKey()); |
// therefore we need to keep the list of mapped buffers and do some ugly reflection to try to | // therefore we need to keep the list of mapped buffers and do some ugly reflection to try to | ||||
// clean the buffer during close(). | // clean the buffer during close(). | ||||
// See https://bz.apache.org/bugzilla/show_bug.cgi?id=58480, | // See https://bz.apache.org/bugzilla/show_bug.cgi?id=58480, | ||||
// http://stackoverflow.com/questions/3602783/file-access-synchronized-on-java-object and | |||||
// http://bugs.java.com/view_bug.do?bug_id=4724038 for related discussions | |||||
// https://stackoverflow.com/questions/36077641/java-when-does-direct-buffer-released | |||||
private final IdentityHashMap<ByteBuffer,ByteBuffer> buffersToClean = new IdentityHashMap<>(); | private final IdentityHashMap<ByteBuffer,ByteBuffer> buffersToClean = new IdentityHashMap<>(); | ||||
public FileBackedDataSource(File file) throws FileNotFoundException { | public FileBackedDataSource(File file) throws FileNotFoundException { |
* | * | ||||
* @return String with mapped codepoints | * @return String with mapped codepoints | ||||
* | * | ||||
* @see <a href="http://stackoverflow.com/questions/8692095">Drawing exotic fonts in a java applet</a> | |||||
* @see StringUtil#mapMsCodepointString(String) | * @see StringUtil#mapMsCodepointString(String) | ||||
*/ | */ | ||||
String mapFontCharset(Graphics2D graphics, FontInfo fontInfo, String text); | String mapFontCharset(Graphics2D graphics, FontInfo fontInfo, String text); |
* | * | ||||
* @see <a href="https://msdn.microsoft.com/en-us/library/dd560821%28v=office.12%29.aspx">Using Office Open XML to Customize Document Formatting in the 2007 Office System</a> | * @see <a href="https://msdn.microsoft.com/en-us/library/dd560821%28v=office.12%29.aspx">Using Office Open XML to Customize Document Formatting in the 2007 Office System</a> | ||||
* @see <a href="https://social.msdn.microsoft.com/Forums/office/en-US/040e0a1f-dbfe-4ce5-826b-38b4b6f6d3f7/saturation-modulation-satmod">saturation modulation (satMod)</a> | * @see <a href="https://social.msdn.microsoft.com/Forums/office/en-US/040e0a1f-dbfe-4ce5-826b-38b4b6f6d3f7/saturation-modulation-satmod">saturation modulation (satMod)</a> | ||||
* @see <a href="http://stackoverflow.com/questions/6754127/office-open-xml-satmod-results-in-more-than-100-saturation">Office Open XML satMod results in more than 100% saturation</a> | |||||
*/ | */ | ||||
public static Color applyColorTransform(ColorStyle color){ | public static Color applyColorTransform(ColorStyle color){ | ||||
// TODO: The colors don't match 100% the results of Powerpoint, maybe because we still | // TODO: The colors don't match 100% the results of Powerpoint, maybe because we still |
double l = layout.getLeading(); | double l = layout.getLeading(); | ||||
if (l == 0) { | if (l == 0) { | ||||
// see https://stackoverflow.com/questions/925147 | |||||
// we use a 115% value instead of the 120% proposed one, as this seems to be closer to LO/OO | // we use a 115% value instead of the 120% proposed one, as this seems to be closer to LO/OO | ||||
l = (layout.getAscent()+layout.getDescent())*0.15; | l = (layout.getAscent()+layout.getDescent())*0.15; | ||||
} | } |
private static long lastLog; | private static long lastLog; | ||||
// DocumentBuilderFactory.newDocumentBuilder is thread-safe | // DocumentBuilderFactory.newDocumentBuilder is thread-safe | ||||
// see https://stackoverflow.com/questions/12455602/is-documentbuilder-thread-safe | |||||
private static final DocumentBuilderFactory documentBuilderFactory = getDocumentBuilderFactory(); | private static final DocumentBuilderFactory documentBuilderFactory = getDocumentBuilderFactory(); | ||||
private static final SAXParserFactory saxFactory = getSaxParserFactory(); | private static final SAXParserFactory saxFactory = getSaxParserFactory(); |
* | * | ||||
* This will verify at the end of the test if the object is actually removed by the | * This will verify at the end of the test if the object is actually removed by the | ||||
* garbage collector or if it lingers in memory for some reason. | * garbage collector or if it lingers in memory for some reason. | ||||
* | |||||
* Idea taken from http://stackoverflow.com/a/7410460/411846 | |||||
*/ | */ | ||||
public class MemoryLeakVerifier { | public class MemoryLeakVerifier { | ||||
private static final int MAX_GC_ITERATIONS = 50; | private static final int MAX_GC_ITERATIONS = 50; |