Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bug #13916-master: fixing embedded images referenced in the email content that were not processed when the email content was extracted. #1316

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
import org.silverpeas.core.util.StringUtil;
import org.silverpeas.core.util.WebEncodeHelper;
import org.silverpeas.core.util.file.FileRepositoryManager;
import org.silverpeas.core.util.file.FileUtil;
import org.silverpeas.core.util.logging.SilverLogger;

import javax.mail.Message;
Expand All @@ -49,9 +50,15 @@
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import java.util.stream.Stream;

import static java.util.Optional.ofNullable;
import static org.apache.commons.io.FilenameUtils.getExtension;
import static org.silverpeas.core.util.StringUtil.isNotDefined;

public class EMLExtractor implements MailExtractor {

Expand Down Expand Up @@ -159,28 +166,46 @@ private String processMailPart(Part part, List<MailAttachment> attachments) thro
Multipart mContent = (Multipart) content;
return processMultipart(mContent, attachments);
} else if (attachments != null) {
String fileName = getFileName(part);
if (fileName != null) {
MailAttachment attachment = new MailAttachment(fileName);
String dir = FileRepositoryManager.getTemporaryPath() + "mail" + System
.currentTimeMillis();
File file = new File(dir, fileName);
FileUtils.copyInputStreamToFile(part.getInputStream(), file);
attachment.setPath(file.getAbsolutePath());
attachment.setSize(file.length());
attachments.add(attachment);
}
processMailAttachmentPart(part, attachments);
}
} else {
if (part.getContentType().indexOf(MimeTypes.HTML_MIME_TYPE) >= 0) {
if (part.getContentType().contains(MimeTypes.HTML_MIME_TYPE)) {
return (String) part.getContent();
} else if (part.getContentType().indexOf(MimeTypes.PLAIN_TEXT_MIME_TYPE) >= 0) {
} else if (part.getContentType().contains(MimeTypes.PLAIN_TEXT_MIME_TYPE)) {
return WebEncodeHelper.javaStringToHtmlParagraphe((String) part.getContent());
}
}
return "";
}

private void processMailAttachmentPart(final Part part, final List<MailAttachment> attachments)
throws MessagingException, IOException {
final String contentID = getContentID(part);
String fileName = getFileName(part);
if (fileName == null && contentID != null) {
fileName = contentID.replaceAll("[<>]", "");
}
if (fileName != null) {
MailAttachment attachment = new MailAttachment(fileName);
String dir = FileRepositoryManager.getTemporaryPath() + "mail" + System.currentTimeMillis();
File file = new File(dir, fileName);
FileUtils.copyInputStreamToFile(part.getInputStream(), file);
if (isNotDefined(getExtension(fileName))) {
final String fileExtension = new ContentType(
FileUtil.getMimeType(file.getAbsolutePath())).getSubType();
final String fileNameWithExtension = fileName + "." + fileExtension;
final File fileWithExtension = new File(dir, fileNameWithExtension);
Files.move(file.toPath(), fileWithExtension.toPath());

Check failure

Code scanning / SonarCloud

I/O function calls should not be vulnerable to path injection attacks

<!--SONAR_ISSUE_KEY:AYz4XWhOgMjQ58YLgl5O-->Change this code to not construct the path from user-controlled data. <p>See more on <a href="https://sonarcloud.io/project/issues?id=Silverpeas_Silverpeas-Core2&issues=AYz4XWhOgMjQ58YLgl5O&open=AYz4XWhOgMjQ58YLgl5O&pullRequest=1316">SonarCloud</a></p>
file = fileWithExtension;
attachment.setName(fileNameWithExtension);
}
attachment.setPath(file.getAbsolutePath());
attachment.setSize(file.length());
attachment.setContentID(contentID);
attachments.add(attachment);
}
}

private boolean isTextPart(Part part) throws MessagingException {
String disposition = part.getDisposition();
if (!Part.ATTACHMENT.equals(disposition) && !Part.INLINE.equals(disposition)) {
Expand Down Expand Up @@ -220,4 +245,12 @@ private String getFileName(Part part) throws MessagingException {
}
return fileName;
}

private String getContentID(Part part) throws MessagingException {
return ofNullable(part.getHeader("Content-ID"))
.stream()
.flatMap(Stream::of)
.findFirst()
.orElse(null);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ public class MailAttachment {
private String name;
private String path;
private long size;
private String contentID;

public MailAttachment(String name) {
this.name = name;
Expand Down Expand Up @@ -57,4 +58,11 @@ public long getSize() {
return size;
}

public String getContentID() {
return contentID;
}

public void setContentID(final String contentID) {
this.contentID = contentID;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ public final class AttachmentDetail implements Serializable {
private String xmlForm = null;
@XmlElement(name = "xmlModel")
private XMLModelContentType xmlModelContentType = null;
private String mailContentID = null;

public AttachmentDetail() {
}
Expand Down Expand Up @@ -245,4 +246,12 @@ public void setOriginalPath(String originalPath) {
public String getOriginalPath() {
return originalPath;
}

public String getMailContentID() {
return mailContentID;
}

public void setMailContentID(final String mailContentID) {
this.mailContentID = mailContentID;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
import org.silverpeas.core.contribution.attachment.model.SimpleDocumentPK;
import org.silverpeas.core.importexport.form.FormTemplateImportExport;
import org.silverpeas.core.importexport.form.XMLModelContentType;
import org.silverpeas.core.util.Pair;
import org.silverpeas.core.util.ResourceLocator;
import org.silverpeas.core.util.SettingBundle;
import org.silverpeas.core.util.StringUtil;
Expand Down Expand Up @@ -71,8 +72,10 @@ public AttachmentImportExport(final UserDetail user) {
this.user = user;
}

public List<AttachmentDetail> importAttachments(String pubId, String componentId,
List<AttachmentDetail> attachments, boolean indexIt) throws FileNotFoundException {
public List<Pair<AttachmentDetail, SimpleDocument>> importAttachments(String pubId,
String componentId, List<AttachmentDetail> attachments, boolean indexIt) {
final List<Pair<AttachmentDetail, SimpleDocument>> createdDocuments = new ArrayList<>(
attachments.size());
FormTemplateImportExport xmlIE = null;
for (AttachmentDetail attDetail : attachments) {
attDetail.setAuthor(this.user.getId());
Expand All @@ -83,7 +86,8 @@ public List<AttachmentDetail> importAttachments(String pubId, String componentId
}
// Store xml content
try (final InputStream input = getAttachmentContent(attDetail)) {
this.addAttachmentToPublication(pubId, componentId, attDetail, input, indexIt);
createdDocuments.add(Pair.of(attDetail,
this.addAttachmentToPublication(pubId, componentId, attDetail, input, indexIt)));
if (xmlContent != null) {
if (xmlIE == null) {
xmlIE = new FormTemplateImportExport();
Expand All @@ -104,7 +108,7 @@ public List<AttachmentDetail> importAttachments(String pubId, String componentId
}
}
}
return attachments;
return createdDocuments;
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@
import org.silverpeas.core.pdc.pdc.model.ClassifyPosition;
import org.silverpeas.core.util.Charsets;
import org.silverpeas.core.util.CollectionUtil;
import org.silverpeas.core.util.Pair;
import org.silverpeas.core.util.StringUtil;
import org.silverpeas.core.util.WAAttributeValuePair;
import org.silverpeas.core.util.error.SilverpeasTransverseErrorUtil;
Expand Down Expand Up @@ -747,29 +748,28 @@ public void processImport(List<PublicationType> publicationTypes, ImportSettings
}
}

List<AttachmentDetail> copiedAttachments;
final List<Pair<AttachmentDetail, SimpleDocument>> importedDocuments;
if (ImportExportHelper.isVersioningUsed(componentInst)) {
copiedAttachments = attachmentsSizeOk;
versioningIE.importDocuments(pubDetail.getId(), componentId, attachmentsSizeOk,
pubDetail.isIndexable());
importedDocuments = versioningIE.importDocuments(pubDetail.getId(), componentId,
attachmentsSizeOk, pubDetail.isIndexable());
} else {
// Ajout des attachments
copiedAttachments = attachmentIE
importedDocuments = attachmentIE
.importAttachments(pubDetail.getId(), componentId, attachmentsSizeOk,
pubDetail.isIndexable());
if (copiedAttachments.size() != attachmentsSizeOk.size()) {
unitReport.setError(UnitReport.ERROR_NOT_EXISTS_OR_INACCESSIBLE_FILE);
}
}
if (importedDocuments.size() != attachmentsSizeOk.size()) {
unitReport.setError(UnitReport.ERROR_NOT_EXISTS_OR_INACCESSIBLE_FILE);
}
reportManager.
addNumberOfFilesProcessed(copiedAttachments.size());
addNumberOfFilesProcessed(importedDocuments.size());
reportManager
.addNumberOfFilesNotImported(attachments.size() - copiedAttachments.size());
.addNumberOfFilesNotImported(attachments.size() - importedDocuments.size());

// On additionne la taille des fichiers importés au niveau du rapport
for (AttachmentDetail attdetail : copiedAttachments) {
reportManager.addImportedFileSize(attdetail.getSize(), componentId);
}
importedDocuments.stream()
.map(Pair::getFirst)
.forEach(d -> reportManager.addImportedFileSize(d.getSize(), componentId));
}
if (CollectionUtil.isNotEmpty(documents)) {
// Get number of versions
Expand Down
Loading