git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1768744 13f79535-47bb-0310-9956-ffa450edef68tags/REL_3_16_BETA1
@@ -0,0 +1,147 @@ | |||
/* | |||
* ==================================================================== | |||
* 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. | |||
* ==================================================================== | |||
*/ | |||
package org.apache.poi.crypt.examples; | |||
import java.io.File; | |||
import java.io.FileOutputStream; | |||
import java.io.FilterOutputStream; | |||
import java.io.IOException; | |||
import java.io.InputStream; | |||
import java.security.GeneralSecurityException; | |||
import java.security.SecureRandom; | |||
import java.util.Enumeration; | |||
import java.util.zip.ZipEntry; | |||
import java.util.zip.ZipException; | |||
import java.util.zip.ZipFile; | |||
import java.util.zip.ZipInputStream; | |||
import java.util.zip.ZipOutputStream; | |||
import javax.crypto.Cipher; | |||
import javax.crypto.CipherInputStream; | |||
import javax.crypto.CipherOutputStream; | |||
import javax.crypto.spec.SecretKeySpec; | |||
import org.apache.poi.openxml4j.util.ZipEntrySource; | |||
import org.apache.poi.poifs.crypt.ChainingMode; | |||
import org.apache.poi.poifs.crypt.CipherAlgorithm; | |||
import org.apache.poi.poifs.crypt.CryptoFunctions; | |||
import org.apache.poi.util.IOUtils; | |||
import org.apache.poi.util.TempFile; | |||
/** | |||
* An example <code>ZipEntrySource</code> that has encrypted temp files to ensure that | |||
* sensitive data is not stored in raw format on disk. | |||
*/ | |||
public class AesZipFileZipEntrySource implements ZipEntrySource { | |||
final File tmpFile; | |||
final ZipFile zipFile; | |||
final Cipher ci; | |||
boolean closed; | |||
public AesZipFileZipEntrySource(File tmpFile, Cipher ci) throws IOException { | |||
this.tmpFile = tmpFile; | |||
this.zipFile = new ZipFile(tmpFile); | |||
this.ci = ci; | |||
this.closed = false; | |||
} | |||
/** | |||
* Note: the file sizes are rounded up to the next cipher block size, | |||
* so don't rely on file sizes of these custom encrypted zip file entries! | |||
*/ | |||
@Override | |||
public Enumeration<? extends ZipEntry> getEntries() { | |||
return zipFile.entries(); | |||
} | |||
@Override | |||
public InputStream getInputStream(ZipEntry entry) throws IOException { | |||
InputStream is = zipFile.getInputStream(entry); | |||
return new CipherInputStream(is, ci); | |||
} | |||
@Override | |||
public void close() throws IOException { | |||
if(!closed) { | |||
zipFile.close(); | |||
tmpFile.delete(); | |||
} | |||
closed = true; | |||
} | |||
@Override | |||
public boolean isClosed() { | |||
return closed; | |||
} | |||
public static AesZipFileZipEntrySource createZipEntrySource(InputStream is) throws IOException, GeneralSecurityException { | |||
// generate session key | |||
SecureRandom sr = new SecureRandom(); | |||
byte[] ivBytes = new byte[16], keyBytes = new byte[16]; | |||
sr.nextBytes(ivBytes); | |||
sr.nextBytes(keyBytes); | |||
final File tmpFile = TempFile.createTempFile("protectedXlsx", ".zip"); | |||
copyToFile(is, tmpFile, CipherAlgorithm.aes128, keyBytes, ivBytes); | |||
IOUtils.closeQuietly(is); | |||
return fileToSource(tmpFile, CipherAlgorithm.aes128, keyBytes, ivBytes); | |||
} | |||
private static void copyToFile(InputStream is, File tmpFile, CipherAlgorithm cipherAlgorithm, byte keyBytes[], byte ivBytes[]) throws IOException, GeneralSecurityException { | |||
SecretKeySpec skeySpec = new SecretKeySpec(keyBytes, cipherAlgorithm.jceId); | |||
Cipher ciEnc = CryptoFunctions.getCipher(skeySpec, cipherAlgorithm, ChainingMode.cbc, ivBytes, Cipher.ENCRYPT_MODE, "PKCS5Padding"); | |||
ZipInputStream zis = new ZipInputStream(is); | |||
FileOutputStream fos = new FileOutputStream(tmpFile); | |||
ZipOutputStream zos = new ZipOutputStream(fos); | |||
ZipEntry ze; | |||
while ((ze = zis.getNextEntry()) != null) { | |||
// the cipher output stream pads the data, therefore we can't reuse the ZipEntry with set sizes | |||
// as those will be validated upon close() | |||
ZipEntry zeNew = new ZipEntry(ze.getName()); | |||
zeNew.setComment(ze.getComment()); | |||
zeNew.setExtra(ze.getExtra()); | |||
zeNew.setTime(ze.getTime()); | |||
// zeNew.setMethod(ze.getMethod()); | |||
zos.putNextEntry(zeNew); | |||
FilterOutputStream fos2 = new FilterOutputStream(zos){ | |||
// don't close underlying ZipOutputStream | |||
@Override | |||
public void close() {} | |||
}; | |||
CipherOutputStream cos = new CipherOutputStream(fos2, ciEnc); | |||
IOUtils.copy(zis, cos); | |||
cos.close(); | |||
fos2.close(); | |||
zos.closeEntry(); | |||
zis.closeEntry(); | |||
} | |||
zos.close(); | |||
fos.close(); | |||
zis.close(); | |||
} | |||
private static AesZipFileZipEntrySource fileToSource(File tmpFile, CipherAlgorithm cipherAlgorithm, byte keyBytes[], byte ivBytes[]) throws ZipException, IOException { | |||
SecretKeySpec skeySpec = new SecretKeySpec(keyBytes, cipherAlgorithm.jceId); | |||
Cipher ciDec = CryptoFunctions.getCipher(skeySpec, cipherAlgorithm, ChainingMode.cbc, ivBytes, Cipher.DECRYPT_MODE, "PKCS5Padding"); | |||
return new AesZipFileZipEntrySource(tmpFile, ciDec); | |||
} | |||
} |
@@ -0,0 +1,72 @@ | |||
/* | |||
* ==================================================================== | |||
* 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. | |||
* ==================================================================== | |||
*/ | |||
package org.apache.poi.crypt.examples; | |||
import java.io.File; | |||
import java.io.FileInputStream; | |||
import java.io.FileOutputStream; | |||
import java.io.IOException; | |||
import java.io.InputStream; | |||
import java.io.OutputStream; | |||
import java.security.SecureRandom; | |||
import javax.crypto.Cipher; | |||
import javax.crypto.CipherInputStream; | |||
import javax.crypto.CipherOutputStream; | |||
import javax.crypto.spec.SecretKeySpec; | |||
import org.apache.poi.poifs.crypt.ChainingMode; | |||
import org.apache.poi.poifs.crypt.CipherAlgorithm; | |||
import org.apache.poi.poifs.crypt.CryptoFunctions; | |||
import org.apache.poi.util.TempFile; | |||
/** | |||
* EncryptedTempData can be used to buffer binary data in a secure way, by using encrypted temp files. | |||
*/ | |||
public class EncryptedTempData { | |||
final static CipherAlgorithm cipherAlgorithm = CipherAlgorithm.aes128; | |||
final SecretKeySpec skeySpec; | |||
final byte[] ivBytes; | |||
final File tempFile; | |||
public EncryptedTempData() throws IOException { | |||
SecureRandom sr = new SecureRandom(); | |||
ivBytes = new byte[16]; | |||
byte[] keyBytes = new byte[16]; | |||
sr.nextBytes(ivBytes); | |||
sr.nextBytes(keyBytes); | |||
skeySpec = new SecretKeySpec(keyBytes, cipherAlgorithm.jceId); | |||
tempFile = TempFile.createTempFile("poi-temp-data", ".tmp"); | |||
} | |||
public OutputStream getOutputStream() throws IOException { | |||
Cipher ciEnc = CryptoFunctions.getCipher(skeySpec, cipherAlgorithm, ChainingMode.cbc, ivBytes, Cipher.ENCRYPT_MODE, null); | |||
return new CipherOutputStream(new FileOutputStream(tempFile), ciEnc); | |||
} | |||
public InputStream getInputStream() throws IOException { | |||
Cipher ciDec = CryptoFunctions.getCipher(skeySpec, cipherAlgorithm, ChainingMode.cbc, ivBytes, Cipher.DECRYPT_MODE, null); | |||
return new CipherInputStream(new FileInputStream(tempFile), ciDec); | |||
} | |||
public void dispose() { | |||
tempFile.delete(); | |||
} | |||
} |
@@ -0,0 +1,43 @@ | |||
/* | |||
* ==================================================================== | |||
* 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. | |||
* ==================================================================== | |||
*/ | |||
package org.apache.poi.crypt.examples; | |||
import java.io.InputStream; | |||
import org.apache.poi.poifs.crypt.Decryptor; | |||
import org.apache.poi.poifs.crypt.EncryptionInfo; | |||
import org.apache.poi.poifs.filesystem.POIFSFileSystem; | |||
import org.apache.poi.util.IOUtils; | |||
public class EncryptionUtils { | |||
public static InputStream decrypt(final InputStream inputStream, final String pwd) throws Exception { | |||
try { | |||
POIFSFileSystem fs = new POIFSFileSystem(inputStream); | |||
EncryptionInfo info = new EncryptionInfo(fs); | |||
Decryptor d = Decryptor.getInstance(info); | |||
if (!d.verifyPassword(pwd)) { | |||
throw new RuntimeException("incorrect password"); | |||
} | |||
return d.getDataStream(fs); | |||
} finally { | |||
IOUtils.closeQuietly(inputStream); | |||
} | |||
} | |||
} |
@@ -0,0 +1,43 @@ | |||
/* | |||
* ==================================================================== | |||
* 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. | |||
* ==================================================================== | |||
*/ | |||
package org.apache.poi.examples.util; | |||
import java.io.File; | |||
import java.io.IOException; | |||
import org.apache.poi.util.TempFile; | |||
public class TempFileUtils { | |||
public static void checkTempFiles() throws IOException { | |||
String tmpDir = System.getProperty(TempFile.JAVA_IO_TMPDIR) + "/poifiles"; | |||
File tempDir = new File(tmpDir); | |||
if(tempDir.exists()) { | |||
String[] tempFiles = tempDir.list(); | |||
if(tempFiles.length > 0) { | |||
System.out.println("found files in poi temp dir " + tempDir.getAbsolutePath()); | |||
for(String filename : tempDir.list()) { | |||
System.out.println("file: " + filename); | |||
} | |||
} | |||
} else { | |||
System.out.println("unable to find poi temp dir"); | |||
} | |||
} | |||
} |
@@ -0,0 +1,88 @@ | |||
/* | |||
* ==================================================================== | |||
* 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. | |||
* ==================================================================== | |||
*/ | |||
package org.apache.poi.xssf.eventusermodel.examples; | |||
import java.io.FileInputStream; | |||
import java.io.InputStream; | |||
import org.apache.poi.crypt.examples.AesZipFileZipEntrySource; | |||
import org.apache.poi.crypt.examples.EncryptionUtils; | |||
import org.apache.poi.examples.util.TempFileUtils; | |||
import org.apache.poi.openxml4j.opc.OPCPackage; | |||
import org.apache.poi.util.IOUtils; | |||
import org.apache.poi.xssf.eventusermodel.XSSFReader; | |||
import org.apache.poi.xssf.eventusermodel.XSSFReader.SheetIterator; | |||
/** | |||
* An example that loads a password protected workbook and counts the sheets. | |||
* The example highlights how to do this in streaming way. | |||
* <p><ul> | |||
* <li>The example demonstrates that all temp files are removed. | |||
* <li><code>AesZipFileZipEntrySource</code> is used to ensure that temp files are encrypted. | |||
* </ul><p> | |||
*/ | |||
public class LoadPasswordProtectedXlsxStreaming { | |||
public static void main(String[] args) { | |||
try { | |||
if(args.length != 2) { | |||
throw new Exception("Expected 2 params: filename and password"); | |||
} | |||
TempFileUtils.checkTempFiles(); | |||
String filename = args[0]; | |||
String password = args[1]; | |||
FileInputStream fis = new FileInputStream(filename); | |||
try { | |||
InputStream unencryptedStream = EncryptionUtils.decrypt(fis, password); | |||
try { | |||
printSheetCount(unencryptedStream); | |||
} finally { | |||
IOUtils.closeQuietly(unencryptedStream); | |||
} | |||
} finally { | |||
IOUtils.closeQuietly(fis); | |||
} | |||
TempFileUtils.checkTempFiles(); | |||
} catch(Throwable t) { | |||
t.printStackTrace(); | |||
} | |||
} | |||
public static void printSheetCount(final InputStream inputStream) throws Exception { | |||
AesZipFileZipEntrySource source = AesZipFileZipEntrySource.createZipEntrySource(inputStream); | |||
try { | |||
OPCPackage pkg = OPCPackage.open(source); | |||
try { | |||
XSSFReader reader = new XSSFReader(pkg); | |||
SheetIterator iter = (SheetIterator)reader.getSheetsData(); | |||
int count = 0; | |||
while(iter.hasNext()) { | |||
iter.next(); | |||
count++; | |||
} | |||
System.out.println("sheet count: " + count); | |||
} finally { | |||
IOUtils.closeQuietly(pkg); | |||
} | |||
} finally { | |||
IOUtils.closeQuietly(source); | |||
} | |||
} | |||
} |
@@ -0,0 +1,113 @@ | |||
/* | |||
* ==================================================================== | |||
* 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. | |||
* ==================================================================== | |||
*/ | |||
package org.apache.poi.xssf.streaming.examples; | |||
import java.io.FileInputStream; | |||
import java.io.FileOutputStream; | |||
import java.io.IOException; | |||
import java.io.InputStream; | |||
import java.io.OutputStream; | |||
import java.security.GeneralSecurityException; | |||
import java.security.SecureRandom; | |||
import javax.crypto.Cipher; | |||
import javax.crypto.CipherInputStream; | |||
import javax.crypto.CipherOutputStream; | |||
import javax.crypto.spec.SecretKeySpec; | |||
import org.apache.poi.crypt.examples.AesZipFileZipEntrySource; | |||
import org.apache.poi.crypt.examples.EncryptedTempData; | |||
import org.apache.poi.openxml4j.util.ZipEntrySource; | |||
import org.apache.poi.poifs.crypt.ChainingMode; | |||
import org.apache.poi.poifs.crypt.CipherAlgorithm; | |||
import org.apache.poi.poifs.crypt.CryptoFunctions; | |||
import org.apache.poi.util.IOUtils; | |||
import org.apache.poi.xssf.streaming.SXSSFWorkbook; | |||
import org.apache.poi.xssf.streaming.SheetDataWriter; | |||
public class SXSSFWorkbookWithCustomZipEntrySource extends SXSSFWorkbook { | |||
public SXSSFWorkbookWithCustomZipEntrySource() { | |||
super(20); | |||
setCompressTempFiles(true); | |||
} | |||
@Override | |||
public void write(OutputStream stream) throws IOException { | |||
flushSheets(); | |||
EncryptedTempData tempData = new EncryptedTempData(); | |||
ZipEntrySource source = null; | |||
try { | |||
OutputStream os = tempData.getOutputStream(); | |||
try { | |||
getXSSFWorkbook().write(os); | |||
} finally { | |||
IOUtils.closeQuietly(os); | |||
} | |||
// provide ZipEntrySource to poi which decrypts on the fly | |||
source = AesZipFileZipEntrySource.createZipEntrySource(tempData.getInputStream()); | |||
injectData(source, stream); | |||
} catch (GeneralSecurityException e) { | |||
throw new IOException(e); | |||
} finally { | |||
tempData.dispose(); | |||
IOUtils.closeQuietly(source); | |||
} | |||
} | |||
@Override | |||
protected SheetDataWriter createSheetDataWriter() throws IOException { | |||
return new SheetDataWriterWithDecorator(); | |||
} | |||
static class SheetDataWriterWithDecorator extends SheetDataWriter { | |||
final static CipherAlgorithm cipherAlgorithm = CipherAlgorithm.aes128; | |||
SecretKeySpec skeySpec; | |||
byte[] ivBytes; | |||
public SheetDataWriterWithDecorator() throws IOException { | |||
super(); | |||
} | |||
void init() { | |||
if(skeySpec == null) { | |||
SecureRandom sr = new SecureRandom(); | |||
ivBytes = new byte[16]; | |||
byte[] keyBytes = new byte[16]; | |||
sr.nextBytes(ivBytes); | |||
sr.nextBytes(keyBytes); | |||
skeySpec = new SecretKeySpec(keyBytes, cipherAlgorithm.jceId); | |||
} | |||
} | |||
@Override | |||
protected OutputStream decorateOutputStream(FileOutputStream fos) { | |||
init(); | |||
Cipher ciEnc = CryptoFunctions.getCipher(skeySpec, cipherAlgorithm, ChainingMode.cbc, ivBytes, Cipher.ENCRYPT_MODE, "PKCS5Padding"); | |||
return new CipherOutputStream(fos, ciEnc); | |||
} | |||
@Override | |||
protected InputStream decorateInputStream(FileInputStream fis) { | |||
Cipher ciDec = CryptoFunctions.getCipher(skeySpec, cipherAlgorithm, ChainingMode.cbc, ivBytes, Cipher.DECRYPT_MODE, "PKCS5Padding"); | |||
return new CipherInputStream(fis, ciDec); | |||
} | |||
} | |||
} |
@@ -0,0 +1,112 @@ | |||
/* | |||
* ==================================================================== | |||
* 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. | |||
* ==================================================================== | |||
*/ | |||
package org.apache.poi.xssf.streaming.examples; | |||
import java.io.FileOutputStream; | |||
import java.io.IOException; | |||
import java.io.InputStream; | |||
import java.security.GeneralSecurityException; | |||
import org.apache.poi.crypt.examples.EncryptedTempData; | |||
import org.apache.poi.examples.util.TempFileUtils; | |||
import org.apache.poi.openxml4j.exceptions.InvalidFormatException; | |||
import org.apache.poi.openxml4j.opc.OPCPackage; | |||
import org.apache.poi.poifs.crypt.EncryptionInfo; | |||
import org.apache.poi.poifs.crypt.EncryptionMode; | |||
import org.apache.poi.poifs.crypt.Encryptor; | |||
import org.apache.poi.poifs.filesystem.POIFSFileSystem; | |||
import org.apache.poi.util.IOUtils; | |||
import org.apache.poi.xssf.streaming.SXSSFCell; | |||
import org.apache.poi.xssf.streaming.SXSSFRow; | |||
import org.apache.poi.xssf.streaming.SXSSFSheet; | |||
/** | |||
* An example that outputs a simple generated workbook that is password protected. | |||
* The example highlights how to do this in streaming way. | |||
* <p><ul> | |||
* <li>The example demonstrates that all temp files are removed. | |||
* <li><code>SXSSFWorkbookWithCustomZipEntrySource</code> extends SXSSFWorkbook to ensure temp files are encrypted. | |||
* </ul><p> | |||
*/ | |||
public class SavePasswordProtectedXlsx { | |||
public static void main(String[] args) { | |||
try { | |||
if(args.length != 2) { | |||
throw new Exception("Expected 2 params: filename and password"); | |||
} | |||
TempFileUtils.checkTempFiles(); | |||
String filename = args[0]; | |||
String password = args[1]; | |||
SXSSFWorkbookWithCustomZipEntrySource wb = new SXSSFWorkbookWithCustomZipEntrySource(); | |||
try { | |||
for(int i = 0; i < 10; i++) { | |||
SXSSFSheet sheet = wb.createSheet("Sheet" + i); | |||
for(int r = 0; r < 1000; r++) { | |||
SXSSFRow row = sheet.createRow(r); | |||
for(int c = 0; c < 100; c++) { | |||
SXSSFCell cell = row.createCell(c); | |||
cell.setCellValue("abcd"); | |||
} | |||
} | |||
} | |||
EncryptedTempData tempData = new EncryptedTempData(); | |||
try { | |||
wb.write(tempData.getOutputStream()); | |||
save(tempData.getInputStream(), filename, password); | |||
System.out.println("Saved " + filename); | |||
} finally { | |||
tempData.dispose(); | |||
} | |||
} finally { | |||
wb.close(); | |||
wb.dispose(); | |||
} | |||
TempFileUtils.checkTempFiles(); | |||
} catch(Throwable t) { | |||
t.printStackTrace(); | |||
} | |||
} | |||
public static void save(final InputStream inputStream, final String filename, final String pwd) | |||
throws InvalidFormatException, IOException, GeneralSecurityException { | |||
try { | |||
POIFSFileSystem fs = new POIFSFileSystem(); | |||
EncryptionInfo info = new EncryptionInfo(EncryptionMode.agile); | |||
Encryptor enc = Encryptor.getInstance(info); | |||
enc.confirmPassword(pwd); | |||
OPCPackage opc = OPCPackage.open(inputStream); | |||
try { | |||
FileOutputStream fos = new FileOutputStream(filename); | |||
try { | |||
opc.save(enc.getDataStream(fs)); | |||
fs.writeFilesystem(fos); | |||
} finally { | |||
IOUtils.closeQuietly(fos); | |||
} | |||
} finally { | |||
IOUtils.closeQuietly(opc); | |||
} | |||
} finally { | |||
IOUtils.closeQuietly(inputStream); | |||
} | |||
} | |||
} |
@@ -0,0 +1,85 @@ | |||
/* | |||
* ==================================================================== | |||
* 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. | |||
* ==================================================================== | |||
*/ | |||
package org.apache.poi.xssf.usermodel.examples; | |||
import java.io.FileInputStream; | |||
import java.io.InputStream; | |||
import org.apache.poi.crypt.examples.AesZipFileZipEntrySource; | |||
import org.apache.poi.crypt.examples.EncryptionUtils; | |||
import org.apache.poi.examples.util.TempFileUtils; | |||
import org.apache.poi.openxml4j.opc.OPCPackage; | |||
import org.apache.poi.util.IOUtils; | |||
import org.apache.poi.xssf.usermodel.XSSFWorkbook; | |||
/** | |||
* An example that loads a password protected workbook and counts the sheets. | |||
* <p><ul> | |||
* <li>The example demonstrates that all temp files are removed. | |||
* <li><code>AesZipFileZipEntrySource</code> is used to ensure that temp files are encrypted. | |||
* </ul><p> | |||
*/ | |||
public class LoadPasswordProtectedXlsx { | |||
public static void main(String[] args) { | |||
try { | |||
if(args.length != 2) { | |||
throw new Exception("Expected 2 params: filename and password"); | |||
} | |||
TempFileUtils.checkTempFiles(); | |||
String filename = args[0]; | |||
String password = args[1]; | |||
FileInputStream fis = new FileInputStream(filename); | |||
try { | |||
InputStream unencryptedStream = EncryptionUtils.decrypt(fis, password); | |||
try { | |||
printSheetCount(unencryptedStream); | |||
} finally { | |||
IOUtils.closeQuietly(unencryptedStream); | |||
} | |||
} finally { | |||
IOUtils.closeQuietly(fis); | |||
} | |||
TempFileUtils.checkTempFiles(); | |||
} catch(Throwable t) { | |||
t.printStackTrace(); | |||
} | |||
} | |||
public static void printSheetCount(final InputStream inputStream) throws Exception { | |||
AesZipFileZipEntrySource source = AesZipFileZipEntrySource.createZipEntrySource(inputStream); | |||
try { | |||
OPCPackage pkg = OPCPackage.open(source); | |||
try { | |||
XSSFWorkbook workbook = new XSSFWorkbook(pkg); | |||
try { | |||
System.out.println("sheet count: " + workbook.getNumberOfSheets()); | |||
} finally { | |||
IOUtils.closeQuietly(workbook); | |||
} | |||
} finally { | |||
IOUtils.closeQuietly(pkg); | |||
} | |||
} finally { | |||
IOUtils.closeQuietly(source); | |||
} | |||
} | |||
} |