Merge remote-tracking branch 'upstream/develop' into collaborative

This commit is contained in:
Richard Cordovano 2015-09-09 10:14:29 -04:00
commit 1e5d66332a
3 changed files with 128 additions and 69 deletions

View File

@ -146,7 +146,7 @@ class SevenZipExtractor {
* @param abstractFile The AbstractFilw whose mimetype is to be determined.
*
* @return This method returns true if the file format is currently
* supported. Else it returns false.
* supported. Else it returns false.
*/
boolean isSevenZipExtractionSupported(AbstractFile abstractFile) {
try {
@ -180,7 +180,7 @@ class SevenZipExtractor {
*
* More heuristics to be added here
*
* @param archiveName the parent archive
* @param archiveName the parent archive
* @param archiveFileItem the archive item
*
* @return true if potential zip bomb, false otherwise
@ -279,7 +279,7 @@ class SevenZipExtractor {
* Unpack the file to local folder and return a list of derived files
*
* @param pipelineContext current ingest context
* @param archiveFile file to unpack
* @param archiveFile file to unpack
*
* @return list of unpacked derived files
*/
@ -502,7 +502,10 @@ class SevenZipExtractor {
SevenZipExtractor.UnpackStream unpackStream = null;
if (!isDir) {
try {
unpackStream = new SevenZipExtractor.UnpackStream(localAbsPath, freeDiskSpace, size == null);
if (size != null)
unpackStream = new SevenZipExtractor.KnownSizeUnpackStream(localAbsPath, size);
else
unpackStream = new SevenZipExtractor.UnknownSizeUnpackStream(localAbsPath, freeDiskSpace);
item.extractSlow(unpackStream);
} catch (Exception e) {
//could be something unexpected with this file, move on
@ -510,22 +513,14 @@ class SevenZipExtractor {
} finally {
if (unpackStream != null) {
//record derived data in unode, to be traversed later after unpacking the archive
if (size != null) {
// unpackedNode.bytesWritten will not be set in
// this case. Use 'size' which has been set
// previously.
unpackedNode.addDerivedInfo(size, !isDir,
0L, createtime, accesstime, modtime, localRelPath);
} else {
// since size is unknown, use
// unpackStream.getNumberOfBytesWritten() to get
// the size.
unpackedNode.addDerivedInfo(unpackStream.getNumberOfBytesWritten(), !isDir,
0L, createtime, accesstime, modtime, localRelPath);
}
unpackedNode.addDerivedInfo(unpackStream.getSize(), !isDir,
0L, createtime, accesstime, modtime, localRelPath);
unpackStream.close();
}
}
} else { // this is a directory, size is always 0
unpackedNode.addDerivedInfo(0, !isDir,
0L, createtime, accesstime, modtime, localRelPath);
}
//update units for progress bar
@ -615,18 +610,12 @@ class SevenZipExtractor {
/**
* Stream used to unpack the archive to local file
*/
private static class UnpackStream implements ISequentialOutStream {
private abstract static class UnpackStream implements ISequentialOutStream {
private OutputStream output;
private String localAbsPath;
private long freeDiskSpace;
private boolean sizeUnknown = false;
private boolean outOfSpace = false;
private long bytesWritten = 0;
UnpackStream(String localAbsPath, long freeDiskSpace, boolean sizeUnknown) {
this.sizeUnknown = sizeUnknown;
this.freeDiskSpace = freeDiskSpace;
UnpackStream(String localAbsPath) {
this.localAbsPath = localAbsPath;
try {
output = new BufferedOutputStream(new FileOutputStream(localAbsPath));
@ -636,41 +625,14 @@ class SevenZipExtractor {
}
public long getNumberOfBytesWritten() {
return this.bytesWritten;
public abstract long getSize();
OutputStream getOutput() {
return output;
}
@Override
public int write(byte[] bytes) throws SevenZipException {
try {
if (!sizeUnknown) {
output.write(bytes);
} else {
// If the content size is unknown, cautiously write to disk.
// Write only if byte array is less than 80% of the current
// free disk space.
if (freeDiskSpace == IngestMonitor.DISK_FREE_SPACE_UNKNOWN || bytes.length < 0.8 * freeDiskSpace) {
output.write(bytes);
// NOTE: this method is called multiple times for a
// single extractSlow() call. Update bytesWritten and
// freeDiskSpace after every write operation.
this.bytesWritten += bytes.length;
this.freeDiskSpace -= bytes.length;
} else {
this.outOfSpace = true;
logger.log(Level.INFO, NbBundle.getMessage(
SevenZipExtractor.class,
"EmbeddedFileExtractorIngestModule.ArchiveExtractor.UnpackStream.write.noSpace.msg"));
throw new SevenZipException(
NbBundle.getMessage(SevenZipExtractor.class, "EmbeddedFileExtractorIngestModule.ArchiveExtractor.UnpackStream.write.noSpace.msg"));
}
}
} catch (IOException ex) {
throw new SevenZipException(
NbBundle.getMessage(SevenZipExtractor.class, "EmbeddedFileExtractorIngestModule.ArchiveExtractor.UnpackStream.write.exception.msg",
localAbsPath), ex);
}
return bytes.length;
String getLocalAbsPath() {
return localAbsPath;
}
public void close() {
@ -678,9 +640,6 @@ class SevenZipExtractor {
try {
output.flush();
output.close();
if (this.outOfSpace) {
Files.delete(Paths.get(this.localAbsPath));
}
} catch (IOException e) {
logger.log(Level.SEVERE, "Error closing unpack stream for file: {0}", localAbsPath); //NON-NLS
}
@ -688,6 +647,100 @@ class SevenZipExtractor {
}
}
/**
* Stream used to unpack the archive of unknown size to local file
*/
private static class UnknownSizeUnpackStream extends UnpackStream {
private long freeDiskSpace;
private boolean outOfSpace = false;
private long bytesWritten = 0;
UnknownSizeUnpackStream(String localAbsPath, long freeDiskSpace) {
super(localAbsPath);
this.freeDiskSpace = freeDiskSpace;
}
@Override
public long getSize() {
return this.bytesWritten;
}
@Override
public int write(byte[] bytes) throws SevenZipException {
try {
// If the content size is unknown, cautiously write to disk.
// Write only if byte array is less than 80% of the current
// free disk space.
if (freeDiskSpace == IngestMonitor.DISK_FREE_SPACE_UNKNOWN || bytes.length < 0.8 * freeDiskSpace) {
getOutput().write(bytes);
// NOTE: this method is called multiple times for a
// single extractSlow() call. Update bytesWritten and
// freeDiskSpace after every write operation.
this.bytesWritten += bytes.length;
this.freeDiskSpace -= bytes.length;
} else {
this.outOfSpace = true;
logger.log(Level.INFO, NbBundle.getMessage(
SevenZipExtractor.class,
"EmbeddedFileExtractorIngestModule.ArchiveExtractor.UnpackStream.write.noSpace.msg"));
throw new SevenZipException(
NbBundle.getMessage(SevenZipExtractor.class, "EmbeddedFileExtractorIngestModule.ArchiveExtractor.UnpackStream.write.noSpace.msg"));
}
} catch (IOException ex) {
throw new SevenZipException(
NbBundle.getMessage(SevenZipExtractor.class, "EmbeddedFileExtractorIngestModule.ArchiveExtractor.UnpackStream.write.exception.msg",
getLocalAbsPath()), ex);
}
return bytes.length;
}
@Override
public void close() {
if (getOutput() != null) {
try {
getOutput().flush();
getOutput().close();
if (this.outOfSpace) {
Files.delete(Paths.get(getLocalAbsPath()));
}
} catch (IOException e) {
logger.log(Level.SEVERE, "Error closing unpack stream for file: {0}", getLocalAbsPath()); //NON-NLS
}
}
}
}
/**
* Stream used to unpack the archive of known size to local file
*/
private static class KnownSizeUnpackStream extends UnpackStream {
private long size;
KnownSizeUnpackStream(String localAbsPath, long size) {
super(localAbsPath);
this.size = size;
}
@Override
public long getSize() {
return this.size;
}
@Override
public int write(byte[] bytes) throws SevenZipException {
try {
getOutput().write(bytes);
} catch (IOException ex) {
throw new SevenZipException(
NbBundle.getMessage(SevenZipExtractor.class, "EmbeddedFileExtractorIngestModule.ArchiveExtractor.UnpackStream.write.exception.msg",
getLocalAbsPath()), ex);
}
return bytes.length;
}
}
/**
* Representation of the files in the archive. Used to track of local tree
* file hierarchy, archive depth, and files created to easily and reliably
@ -702,8 +755,8 @@ class SevenZipExtractor {
/**
*
* @param localPathRoot Path in module output folder that files will be
* saved to
* @param archiveFile Archive file being extracted
* saved to
* @param archiveFile Archive file being extracted
* @param fileManager
*/
UnpackedTree(String localPathRoot, AbstractFile archiveFile) {
@ -962,7 +1015,7 @@ class SevenZipExtractor {
/**
* Add a new archive to track of depth
*
* @param parent parent archive or null
* @param parent parent archive or null
* @param objectId object id of the new archive
*
* @return the archive added

View File

@ -552,7 +552,7 @@ SORT_MEMBER_DOCS = YES
# this will also influence the order of the classes in the class list.
# The default value is: NO.
SORT_BRIEF_DOCS = NO
SORT_BRIEF_DOCS = YES
# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the
# (brief and detailed) documentation of class members so that constructors and
@ -564,14 +564,14 @@ SORT_BRIEF_DOCS = NO
# detailed member documentation.
# The default value is: NO.
SORT_MEMBERS_CTORS_1ST = NO
SORT_MEMBERS_CTORS_1ST = YES
# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy
# of group names into alphabetical order. If set to NO the group names will
# appear in their defined order.
# The default value is: NO.
SORT_GROUP_NAMES = NO
SORT_GROUP_NAMES = YES
# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by
# fully-qualified names, including namespaces. If set to NO, the class list will

View File

@ -256,10 +256,16 @@ class PstParser {
int bufferSize = 8176;
byte[] buffer = new byte[bufferSize];
int count = attachmentStream.read(buffer);
if(count == -1) {
throw new IOException("attachmentStream invalid (read() fails). File "+attach.getLongFilename()+ " skipped");
}
while (count == bufferSize) {
out.write(buffer);
count = attachmentStream.read(buffer);
}
byte[] endBuffer = new byte[count];
System.arraycopy(buffer, 0, endBuffer, 0, count);
out.write(endBuffer);