Author: kmorin Date: 2014-11-17 15:30:51 +0000 (Mon, 17 Nov 2014) New Revision: 690 Url: http://forge.codelutin.com/projects/faxtomail/repository/revisions/690 Log: add license headers + refactoring + add email content attachment in archive import Modified: trunk/faxtomail-service/pom.xml trunk/faxtomail-service/src/license/THIRD-PARTY.properties trunk/faxtomail-service/src/main/java/com/franciaflex/faxtomail/services/service/EmailService.java trunk/faxtomail-service/src/main/java/com/franciaflex/faxtomail/services/service/EmailServiceImpl.java trunk/faxtomail-service/src/main/java/com/franciaflex/faxtomail/services/service/imports/ArchiveImportResult.java trunk/faxtomail-service/src/main/java/com/franciaflex/faxtomail/services/service/imports/InvalidArchiveImportBeanException.java trunk/faxtomail-service/src/main/resources/i18n/faxtomail-service_fr_FR.properties trunk/faxtomail-ui-web/pom.xml trunk/faxtomail-ui-web/src/main/java/com/franciaflex/faxtomail/web/FaxToMailExecuteAndWaitInterceptor.java trunk/faxtomail-ui-web/src/main/java/com/franciaflex/faxtomail/web/HasUploadedFile.java trunk/faxtomail-ui-web/src/main/java/com/franciaflex/faxtomail/web/action/DemandDetailAction.java trunk/faxtomail-ui-web/src/main/java/com/franciaflex/faxtomail/web/action/SearchAction.java trunk/faxtomail-ui-web/src/main/java/com/franciaflex/faxtomail/web/job/MailFilterJob.java trunk/faxtomail-ui-web/src/main/webapp/WEB-INF/content/admin/import-archive-wait.jsp trunk/faxtomail-ui-web/src/main/webapp/WEB-INF/content/demand-detail.jsp trunk/faxtomail-ui-web/src/main/webapp/WEB-INF/content/search-input.jsp trunk/faxtomail-ui-web/src/main/webapp/css/demand-detail.css trunk/faxtomail-ui-web/src/main/webapp/js/demand-detail.js Modified: trunk/faxtomail-service/pom.xml =================================================================== --- trunk/faxtomail-service/pom.xml 2014-11-17 13:46:57 UTC (rev 689) +++ trunk/faxtomail-service/pom.xml 2014-11-17 15:30:51 UTC (rev 690) @@ -191,11 +191,27 @@ <groupId>com.github.spullara.mustache.java</groupId> <artifactId>compiler</artifactId> </dependency> - + <dependency> <groupId>org.xhtmlrenderer</groupId> <artifactId>flying-saucer-pdf-itext5</artifactId> </dependency> + + <dependency> + <groupId>com.google.code.gson</groupId> + <artifactId>gson</artifactId> + </dependency> + + <dependency> + <groupId>gui.ava</groupId> + <artifactId>html2image</artifactId> + </dependency> + + <dependency> + <groupId>com.itextpdf</groupId> + <artifactId>itextpdf</artifactId> + </dependency> + </dependencies> <build> Modified: trunk/faxtomail-service/src/license/THIRD-PARTY.properties =================================================================== --- trunk/faxtomail-service/src/license/THIRD-PARTY.properties 2014-11-17 13:46:57 UTC (rev 689) +++ trunk/faxtomail-service/src/license/THIRD-PARTY.properties 2014-11-17 15:30:51 UTC (rev 690) @@ -12,7 +12,11 @@ # - Eclipse Distribution License (EDL), Version 1.0 # - Eclipse Public License (EPL), Version 1.0 # - Eclipse Public License, Version 1.0 +# - GNU Affero General Public License v3 +# - GNU General Public License version 2 (GPLv2) # - GNU General Public License, Version 2 with the Classpath Exception +# - GNU Lesser General Public License (LGPL), version 2.1 +# - GNU Lesser General Public License version 2.1 (LGPLv2.1) # - GNU Lesser General Public License, Version 2.1 # - GNU Library or Lesser General Public License # - GPLv2+CE @@ -28,10 +32,12 @@ # - Public Domain # - The Apache Software License, Version 2.0 # - The H2 License, Version 1.0 +# - UnboundID LDAP SDK Free Use License #------------------------------------------------------------------------------- # Please fill the missing licenses for dependencies : # # -#Fri Apr 25 11:47:01 CEST 2014 +#Mon Nov 17 16:20:10 CET 2014 commons-primitives--commons-primitives--1.0=The Apache Software License, Version 2.0 dom4j--dom4j--1.6.1=BSD License +gui.ava--html2image--2.0.1=GNU Lesser General Public License, Version 2.1 Modified: trunk/faxtomail-service/src/main/java/com/franciaflex/faxtomail/services/service/EmailService.java =================================================================== --- trunk/faxtomail-service/src/main/java/com/franciaflex/faxtomail/services/service/EmailService.java 2014-11-17 13:46:57 UTC (rev 689) +++ trunk/faxtomail-service/src/main/java/com/franciaflex/faxtomail/services/service/EmailService.java 2014-11-17 15:30:51 UTC (rev 690) @@ -34,10 +34,13 @@ import java.util.Set; import javax.mail.MessagingException; +import javax.mail.Part; import com.franciaflex.faxtomail.persistence.entities.EmailFilter; +import com.franciaflex.faxtomail.persistence.entities.ExtensionCommand; import com.franciaflex.faxtomail.persistence.entities.SearchFilter; import com.franciaflex.faxtomail.services.service.imports.ArchiveImportResult; +import com.itextpdf.text.DocumentException; import org.apache.commons.mail.EmailException; import org.nuiton.util.pagination.PaginationParameter; import org.nuiton.util.pagination.PaginationResult; @@ -139,4 +142,46 @@ * @param attachmentBase base folder containing attachment listed in csv file */ ArchiveImportResult importArchive(InputStream is, File attachmentBase); + + /** + * Decompose a multipart part. + * - sets the email content if the part contains a text bodypart + * - adds attachments to the email + * + * @param part the part to decompose + * @throws Exception + */ + String decomposeMultipartEmail(List<Attachment> attachments, Part part) throws Exception; + + /** + * Retourne un input stream sur une piece jointe convertie ou pas. + * + * @param attachment to convert + * @return attachment + * @throws IOException + */ + Attachment convertIfNecessary(Attachment attachment) throws IOException; + + /** + * Convert attachment to pdf. + * + * @param attachment attachment to convert + * @param extensionCommand command + * @return + * @throws IOException + */ + Attachment convertToPdf(Attachment attachment, ExtensionCommand extensionCommand) throws IOException; + + Attachment convertTextToPdf(String content, String name) throws IOException, DocumentException; + + /** + * Convert html content to image. + * + * @param attachments attachment content to link content to + * @param content html content + * @param name result attachment name + * @return image attachment or {@code null} if content can't be converted + * @throws IOException + */ + Attachment convertHTMLToPdf(List<Attachment> attachments, String content, String name) throws IOException; } Modified: trunk/faxtomail-service/src/main/java/com/franciaflex/faxtomail/services/service/EmailServiceImpl.java =================================================================== --- trunk/faxtomail-service/src/main/java/com/franciaflex/faxtomail/services/service/EmailServiceImpl.java 2014-11-17 13:46:57 UTC (rev 689) +++ trunk/faxtomail-service/src/main/java/com/franciaflex/faxtomail/services/service/EmailServiceImpl.java 2014-11-17 15:30:51 UTC (rev 690) @@ -37,6 +37,7 @@ import java.io.StringWriter; import java.io.UnsupportedEncodingException; import java.io.Writer; +import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import java.sql.Connection; import java.sql.ResultSet; @@ -58,10 +59,16 @@ import java.util.Set; import java.util.TreeMap; import java.util.UUID; +import java.util.regex.Pattern; +import javax.activation.DataHandler; import javax.activation.DataSource; import javax.activation.FileDataSource; import javax.mail.MessagingException; +import javax.mail.Part; +import javax.mail.internet.MimeBodyPart; +import javax.mail.internet.MimeMultipart; +import javax.mail.internet.MimeUtility; import com.franciaflex.faxtomail.persistence.entities.Email; import com.franciaflex.faxtomail.services.service.imports.ArchiveImportExportBean; @@ -71,10 +78,17 @@ import com.google.common.base.Optional; import com.google.common.collect.Collections2; import com.google.common.collect.Iterables; +import com.itextpdf.text.Document; +import com.itextpdf.text.DocumentException; +import com.itextpdf.text.PageSize; +import com.itextpdf.text.Paragraph; +import com.itextpdf.text.pdf.PdfWriter; +import gui.ava.html.Html2Image; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.collections4.IteratorUtils; import org.apache.commons.collections4.Predicate; import org.apache.commons.io.FileUtils; +import org.apache.commons.io.FilenameUtils; import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.lang3.BooleanUtils; @@ -98,6 +112,7 @@ import org.nuiton.topia.persistence.support.TopiaHibernateSupport; import org.nuiton.topia.persistence.support.TopiaSqlSupport; import org.nuiton.topia.persistence.support.TopiaSqlWork; +import org.nuiton.util.StringUtil; import org.nuiton.util.beans.Binder; import org.nuiton.util.beans.BinderFactory; import org.nuiton.util.pagination.PaginationParameter; @@ -1648,6 +1663,25 @@ // email.addHistory(history); + try { + Attachment contentAttachment = convertTextToPdf(email.getOriginalEmail(), + t("faxtomail.email.content.attachment.plainfileName")); + + AttachmentFile contentAttachmentFile = contentAttachment.getOriginalFile(); + contentAttachmentFile.setTopiaId(getTopiaId(AttachmentFile.class, contentAttachmentFile)); + statelessSession.insert(contentAttachmentFile); + + contentAttachment.setEmail(email); + contentAttachment.setTopiaId(getTopiaId(Attachment.class, contentAttachment)); + statelessSession.insert(contentAttachment); + + } catch (IOException | DocumentException e) { + if (log.isErrorEnabled()) { + log.error("error while creating email content attachment", e); + } + } + + // manage attachments if (archiveBean.getAttachmentPaths() != null) { Iterable<String> itAttachmentPaths = Splitter.on(',').omitEmptyStrings().trimResults().split(archiveBean.getAttachmentPaths()); @@ -1665,6 +1699,7 @@ Attachment attachment = attachmentDao.newInstance(); attachment.setEmail(email); + attachment.setTopiaId(getTopiaId(Attachment.class, attachment)); AttachmentFile attachmentFile = attachmentFileDao.newInstance(); attachmentFile.setFilename(attFile.getName()); @@ -1679,8 +1714,15 @@ statelessSession.insert(attachmentFile); attachment.setOriginalFile(attachmentFile); + try { + convertIfNecessary(attachment); - attachment.setTopiaId(getTopiaId(Attachment.class, attachment)); + } catch (IOException e) { + if (log.isErrorEnabled()) { + log.error("error while converting attachment", e); + } + } + statelessSession.insert(attachment); // email.addAttachment(attachment); @@ -1773,4 +1815,281 @@ long result = emailDao.forDemandStatusEquals(DemandStatus.ARCHIVED).count(); return result; } + + @Override + public String decomposeMultipartEmail(List<Attachment> attachments, Part part) throws Exception { + String result = null; + + + DataSource dataSource = part.getDataHandler().getDataSource(); + MimeMultipart mimeMultipart = new MimeMultipart(dataSource); + int multiPartCount = mimeMultipart.getCount(); + + for (int j = 0; j < multiPartCount; j++) { + MimeBodyPart bp = (MimeBodyPart) mimeMultipart.getBodyPart(j); + + // if it is a text part, then this is the email content + String disposition = bp.getDisposition(); + if (bp.isMimeType("text/*") && !Part.ATTACHMENT.equals(disposition)) { + + Charset charset = FaxToMailServiceUtils.getCharset(bp); + String content = IOUtils.toString(bp.getInputStream(), charset); + + if (bp.isMimeType("text/plain")) { + Attachment attachment = convertTextToPdf(content, t("faxtomail.email.content.attachment.plainfileName")); + attachments.add(attachment); + + } else { + result = content; + } + + // if it is multipart part, decompose it + } else if (bp.isMimeType("multipart/*")) { + String htmlContent = decomposeMultipartEmail(attachments, bp); + if (htmlContent != null) { + result = htmlContent; + } + + // else, this is an attachment + } else { + String fileName = bp.getFileName(); + + // parse Content-ID (content identifier in html mail content) + String[] headers = bp.getHeader("Content-ID"); + String contentID = null; + if (headers != null) { + contentID = headers[0]; + contentID = contentID.replaceFirst("^<(.*)>$", "$1"); + } + + // remove the guillemets between the id + + if (fileName == null && contentID == null) { + break; + } else if (fileName == null) { + fileName = contentID; + } + + try { + fileName = MimeUtility.decodeText(fileName); + if (log.isDebugEnabled()) { + log.debug("FileName : " + fileName + ", Content-ID : " + contentID); + } + } catch (UnsupportedEncodingException ex) { + // don't care, use filename raw value + if (log.isWarnEnabled()) { + log.warn("Can't debug email file name", ex); + } + } + + DataHandler dh = bp.getDataHandler(); + + // create new attachment + Attachment attachment = new AttachmentImpl(); + attachment.setAddedByUser(false); + AttachmentFile attachmentFile = getAttachmentFileFromStream(dh.getInputStream()); + attachmentFile.setFilename(fileName); + attachment.setOriginalFile(attachmentFile); + attachment.setContentId(contentID); + + // convert attachment if defined by admin + convertIfNecessary(attachment); + + // save attachment + attachments.add(attachment); + } + } + return result; + } + + @Override + public Attachment convertIfNecessary(Attachment attachment) throws IOException { + + // get file extension + String filename = attachment.getOriginalFileName(); + String extension = FilenameUtils.getExtension(filename); + + if (StringUtils.isNotBlank(extension)) { + ExtensionCommand command = getConfigurationService().getExtensionCommand(extension); + + // si une extension est configurée avec une commande non vide + if (command != null && StringUtils.isNotBlank(command.getConvertToPdfCommand())) { + attachment = convertToPdf(attachment, command); + } + } + return attachment; + } + + @Override + public Attachment convertToPdf(Attachment attachment, ExtensionCommand extensionCommand) throws IOException { + + // get file extension + String filename = attachment.getOriginalFileName(); + String basename = FilenameUtils.getBaseName(filename); + String extension = FilenameUtils.getExtension(filename); + + // copy file to temp file + File file = File.createTempFile("faxtomail-" + basename, "." + extension); + file.deleteOnExit(); + // on creer un nouveau nom de fichier ou seulement le nom de l'extension change + // cela permet de fonctionner avec openoffice par exemple où il n'est pas possible + // de specifier le nom du fichier de sortie + String fullname = StringUtils.removeEnd(file.getAbsolutePath(), "." + extension); + File outfile = new File(fullname + ".pdf"); + outfile.deleteOnExit(); + FileUtils.writeByteArrayToFile(file, attachment.getOriginalFile().getContent()); + + // get process command + String command = extensionCommand.getConvertToPdfCommand(); + String[] args = StringUtil.split(command, " "); + List<String> comArgs = new ArrayList<String>(); + for (String arg : args) { + String localArg = arg; + localArg = localArg.replace("%f", file.getAbsolutePath()); + localArg = localArg.replace("%o", outfile.getAbsolutePath()); + comArgs.add(localArg); + } + ProcessBuilder pb = new ProcessBuilder(comArgs); + // run process + if (log.isDebugEnabled()) { + log.debug("Convert attachment with command : " + comArgs); + } + try { + Process process = pb.start(); + process.waitFor(); + + // read output to save into attachment + byte[] outContent = FileUtils.readFileToByteArray(outfile); + + // on va dire que normalement un pdf ca fait plus de 1 octet + if (outContent.length >= 1) { + AttachmentFile editedFile = new AttachmentFileImpl(); + editedFile.setContent(outContent); + editedFile.setFilename(basename + "-converted.pdf"); + attachment.setEditedFile(editedFile); + } else if (log.isWarnEnabled()) { + log.warn("Can't convert extension to pdf (content is empty)"); + } + + } catch (IOException e) { + if (log.isErrorEnabled()) { + log.error("Cannot run convert command", e); + } + } catch (InterruptedException e) { + if (log.isErrorEnabled()) { + log.error("Cannot run convert command", e); + } + } + + // cleanup + file.delete(); + outfile.delete(); + + return attachment; + } + + @Override + public Attachment convertTextToPdf(String content, String name) throws IOException, DocumentException { + //File target = File.createTempFile("faxtomail-", ".tmp"); + //target.deleteOnExit(); + + Document document = new Document(); + //FileOutputStream fos = new FileOutputStream(target); + ByteArrayOutputStream os = new ByteArrayOutputStream(); + PdfWriter writer = PdfWriter.getInstance(document, os); + writer.open(); + + document.setPageSize(PageSize.A4); + document.open(); + + document.add(new Paragraph(content)); + + document.close(); + writer.close(); + + // convert content to blob + AttachmentFile attachmentFileNew = new AttachmentFileImpl(); + attachmentFileNew.setContent(os.toByteArray()); + attachmentFileNew.setFilename(name + ".pdf"); + + Attachment attachment = new AttachmentImpl(); + attachment.setOriginalFile(attachmentFileNew); + attachment.setOriginalFileName(name + ".pdf"); + attachment.setAddedByUser(false); + + //target.delete(); + + return attachment; + } + + @Override + public Attachment convertHTMLToPdf(List<Attachment> attachments, String content, String name) throws IOException { + Attachment result = null; + ByteArrayOutputStream os = new ByteArrayOutputStream(); + Collection<File> fileToDelete = new ArrayList<File>(); + try { + content = content.replaceAll("<meta (.*?)>(</meta>)?", ""); + + for (Attachment attachment : attachments) { + String key = attachment.getContentId(); + if (key == null) { + key = attachment.getOriginalFileName(); + } + + // get file content + AttachmentFile attachmentFile = attachment.getOriginalFile(); + File file = attachmentFile.getFile(); + fileToDelete.add(file); + + // replace the inline attachments with the extracted attachment file url + // match les patterns: + // <td background="cid:bg.gif" height="52"> + // <img border=0 src="cid:bg.gif" /> + // <img src='cid:5e9ef859-ea65-4f9b-a9fa-30d4a2c5837c' + content = content.replaceAll("(\\w+)=([\"'])cid:" + Pattern.quote(key) + "([\"'])", "$1=$2file://" + file.getAbsolutePath() + "$3"); + + if (log.isDebugEnabled()) { + log.debug("Mapping attachment id " + key + " to file " + file.getAbsolutePath()); + } + } + + Html2Image image = Html2Image.fromHtml(content); + //ImageRenderer imageRenderer = image.getImageRenderer(); + //imageRenderer.saveImage(os, true); + org.w3c.dom.Document doc = image.getParser().getDocument(); + + // convert to pdf + ITextRenderer renderer = new ITextRenderer(); + renderer.setDocument(doc, null); + renderer.layout(); + renderer.createPDF(os); + + // convert content to blob + AttachmentFile attachmentFileNew = new AttachmentFileImpl(); + attachmentFileNew.setContent(os.toByteArray()); + attachmentFileNew.setFilename(name + ".pdf"); + + result = new AttachmentImpl(); + result.setOriginalFile(attachmentFileNew); + result.setOriginalFileName(name + ".pdf"); + result.setAddedByUser(false); + + } catch (OutOfMemoryError er) { + // certains mails (spam) très compliqué ne peuvent pas être convertit en images + if (log.isWarnEnabled()) { + log.warn("Can't convert html content to pdf", er); + } + } catch (DocumentException ex) { + if (log.isWarnEnabled()) { + log.warn("Can't convert html content to pdf", ex); + } + } finally { + // on supprime les fichiers avant le delete on exit pour eviter que le disque ne se remplissent trop vite + for (File file : fileToDelete) { + file.delete(); + } + } + + return result; + } } Modified: trunk/faxtomail-service/src/main/java/com/franciaflex/faxtomail/services/service/imports/ArchiveImportResult.java =================================================================== --- trunk/faxtomail-service/src/main/java/com/franciaflex/faxtomail/services/service/imports/ArchiveImportResult.java 2014-11-17 13:46:57 UTC (rev 689) +++ trunk/faxtomail-service/src/main/java/com/franciaflex/faxtomail/services/service/imports/ArchiveImportResult.java 2014-11-17 15:30:51 UTC (rev 690) @@ -1,5 +1,29 @@ package com.franciaflex.faxtomail.services.service.imports; +/* + * #%L + * FaxToMail :: Service + * $Id:$ + * $HeadURL:$ + * %% + * Copyright (C) 2014 Mac-Groupe, Code Lutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/gpl-3.0.html>. + * #L% + */ + import java.io.File; /** Modified: trunk/faxtomail-service/src/main/java/com/franciaflex/faxtomail/services/service/imports/InvalidArchiveImportBeanException.java =================================================================== --- trunk/faxtomail-service/src/main/java/com/franciaflex/faxtomail/services/service/imports/InvalidArchiveImportBeanException.java 2014-11-17 13:46:57 UTC (rev 689) +++ trunk/faxtomail-service/src/main/java/com/franciaflex/faxtomail/services/service/imports/InvalidArchiveImportBeanException.java 2014-11-17 15:30:51 UTC (rev 690) @@ -1,5 +1,29 @@ package com.franciaflex.faxtomail.services.service.imports; +/* + * #%L + * FaxToMail :: Service + * $Id:$ + * $HeadURL:$ + * %% + * Copyright (C) 2014 Mac-Groupe, Code Lutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/gpl-3.0.html>. + * #L% + */ + /** * @author Kevin Morin (Code Lutin) * @since 1.1 Modified: trunk/faxtomail-service/src/main/resources/i18n/faxtomail-service_fr_FR.properties =================================================================== --- trunk/faxtomail-service/src/main/resources/i18n/faxtomail-service_fr_FR.properties 2014-11-17 13:46:57 UTC (rev 689) +++ trunk/faxtomail-service/src/main/resources/i18n/faxtomail-service_fr_FR.properties 2014-11-17 15:30:51 UTC (rev 690) @@ -3,6 +3,7 @@ faxtomail.archives.import.error.persistence=Erreur technique de persistence faxtomail.archives.import.error.readingAttachmentFile=Erreur lors de la lecture de la PJ %s faxtomail.attachment.demand.filename=Détail de la demande +faxtomail.email.content.attachment.plainfileName= faxtomail.email.projectReference.default=Votre demande du %s faxtomail.service.email.save.clientCode.error=Impossible de trouver le client %s \! faxtomail.validator.error.email.clientCode.required= Modified: trunk/faxtomail-ui-web/pom.xml =================================================================== --- trunk/faxtomail-ui-web/pom.xml 2014-11-17 13:46:57 UTC (rev 689) +++ trunk/faxtomail-ui-web/pom.xml 2014-11-17 15:30:51 UTC (rev 690) @@ -284,22 +284,6 @@ </dependency> <dependency> - <groupId>com.itextpdf</groupId> - <artifactId>itextpdf</artifactId> - </dependency> - - <dependency> - <groupId>org.xhtmlrenderer</groupId> - <artifactId>flying-saucer-pdf-itext5</artifactId> - <scope>compile</scope> - </dependency> - - <dependency> - <groupId>gui.ava</groupId> - <artifactId>html2image</artifactId> - </dependency> - - <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> </dependency> Modified: trunk/faxtomail-ui-web/src/main/java/com/franciaflex/faxtomail/web/FaxToMailExecuteAndWaitInterceptor.java =================================================================== --- trunk/faxtomail-ui-web/src/main/java/com/franciaflex/faxtomail/web/FaxToMailExecuteAndWaitInterceptor.java 2014-11-17 13:46:57 UTC (rev 689) +++ trunk/faxtomail-ui-web/src/main/java/com/franciaflex/faxtomail/web/FaxToMailExecuteAndWaitInterceptor.java 2014-11-17 15:30:51 UTC (rev 690) @@ -1,5 +1,29 @@ package com.franciaflex.faxtomail.web; +/* + * #%L + * FaxToMail :: Web + * $Id:$ + * $HeadURL:$ + * %% + * Copyright (C) 2014 Mac-Groupe, Code Lutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/gpl-3.0.html>. + * #L% + */ + import com.opensymphony.xwork2.ActionInvocation; import org.apache.commons.io.FileUtils; import org.apache.struts2.interceptor.BackgroundProcess; Modified: trunk/faxtomail-ui-web/src/main/java/com/franciaflex/faxtomail/web/HasUploadedFile.java =================================================================== --- trunk/faxtomail-ui-web/src/main/java/com/franciaflex/faxtomail/web/HasUploadedFile.java 2014-11-17 13:46:57 UTC (rev 689) +++ trunk/faxtomail-ui-web/src/main/java/com/franciaflex/faxtomail/web/HasUploadedFile.java 2014-11-17 15:30:51 UTC (rev 690) @@ -1,5 +1,29 @@ package com.franciaflex.faxtomail.web; +/* + * #%L + * FaxToMail :: Web + * $Id:$ + * $HeadURL:$ + * %% + * Copyright (C) 2014 Mac-Groupe, Code Lutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/gpl-3.0.html>. + * #L% + */ + import java.io.File; /** Modified: trunk/faxtomail-ui-web/src/main/java/com/franciaflex/faxtomail/web/action/DemandDetailAction.java =================================================================== --- trunk/faxtomail-ui-web/src/main/java/com/franciaflex/faxtomail/web/action/DemandDetailAction.java 2014-11-17 13:46:57 UTC (rev 689) +++ trunk/faxtomail-ui-web/src/main/java/com/franciaflex/faxtomail/web/action/DemandDetailAction.java 2014-11-17 15:30:51 UTC (rev 690) @@ -1,5 +1,29 @@ package com.franciaflex.faxtomail.web.action; +/* + * #%L + * FaxToMail :: Web + * $Id:$ + * $HeadURL:$ + * %% + * Copyright (C) 2014 Mac-Groupe, Code Lutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/gpl-3.0.html>. + * #L% + */ + import com.franciaflex.faxtomail.persistence.entities.Attachment; import com.franciaflex.faxtomail.persistence.entities.AttachmentFile; import com.franciaflex.faxtomail.persistence.entities.AttachmentFileImpl; Modified: trunk/faxtomail-ui-web/src/main/java/com/franciaflex/faxtomail/web/action/SearchAction.java =================================================================== --- trunk/faxtomail-ui-web/src/main/java/com/franciaflex/faxtomail/web/action/SearchAction.java 2014-11-17 13:46:57 UTC (rev 689) +++ trunk/faxtomail-ui-web/src/main/java/com/franciaflex/faxtomail/web/action/SearchAction.java 2014-11-17 15:30:51 UTC (rev 690) @@ -1,5 +1,29 @@ package com.franciaflex.faxtomail.web.action; +/* + * #%L + * FaxToMail :: Web + * $Id:$ + * $HeadURL:$ + * %% + * Copyright (C) 2014 Mac-Groupe, Code Lutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/gpl-3.0.html>. + * #L% + */ + import com.franciaflex.faxtomail.persistence.entities.Attachment; import com.franciaflex.faxtomail.persistence.entities.Client; import com.franciaflex.faxtomail.persistence.entities.Email; Modified: trunk/faxtomail-ui-web/src/main/java/com/franciaflex/faxtomail/web/job/MailFilterJob.java =================================================================== --- trunk/faxtomail-ui-web/src/main/java/com/franciaflex/faxtomail/web/job/MailFilterJob.java 2014-11-17 13:46:57 UTC (rev 689) +++ trunk/faxtomail-ui-web/src/main/java/com/franciaflex/faxtomail/web/job/MailFilterJob.java 2014-11-17 15:30:51 UTC (rev 690) @@ -466,12 +466,12 @@ if (message.isMimeType("multipart/*")) { // manage boundary id - String htmlContent = decomposeMultipartEmail(attachments, message, email, emailService); + String htmlContent = emailService.decomposeMultipartEmail(attachments, message); if (htmlContent != null) { if (log.isDebugEnabled()) { log.debug("Converting html content to pdf : " + message.getSubject()); } - Attachment attachment = convertHTMLToPdf(attachments, htmlContent, t("faxtomail.email.content.attachment.htmlfileName")); + Attachment attachment = emailService.convertHTMLToPdf(attachments, htmlContent, t("faxtomail.email.content.attachment.htmlfileName")); if (attachment != null) { //remove text plain attachement if exists, to avoid having twice the mail content in the attachments String plainTextFileName = t("faxtomail.email.content.attachment.plainfileName") + ".pdf"; @@ -487,7 +487,7 @@ } else { // convertit le contenu texte en PDF String content = IOUtils.toString(message.getInputStream(), charset); - Attachment attachment = convertTextToPdf(content, t("faxtomail.email.content.attachment.plainfileName")); + Attachment attachment = emailService.convertTextToPdf(content, t("faxtomail.email.content.attachment.plainfileName")); attachments.add(0, attachment); } @@ -537,310 +537,4 @@ } } - /** - * Decompose a multipart part. - * - sets the email content if the part contains a text bodypart - * - adds attachments to the email - * - * @param part the part to decompose - * @param email the email object to fill with the attachments or content - * @param emailService email service - * @throws Exception - */ - protected String decomposeMultipartEmail(List<Attachment> attachments, Part part, Email email, EmailService emailService) throws Exception { - String result = null; - - - DataSource dataSource = part.getDataHandler().getDataSource(); - MimeMultipart mimeMultipart = new MimeMultipart(dataSource); - int multiPartCount = mimeMultipart.getCount(); - - for (int j = 0; j < multiPartCount; j++) { - MimeBodyPart bp = (MimeBodyPart) mimeMultipart.getBodyPart(j); - - // if it is a text part, then this is the email content - String disposition = bp.getDisposition(); - if (bp.isMimeType("text/*") && !Part.ATTACHMENT.equals(disposition)) { - - Charset charset = FaxToMailServiceUtils.getCharset(bp); - String content = IOUtils.toString(bp.getInputStream(), charset); - - if (bp.isMimeType("text/plain")) { - Attachment attachment = convertTextToPdf(content, t("faxtomail.email.content.attachment.plainfileName")); - attachments.add(attachment); - - } else { - result = content; - } - - // if it is multipart part, decompose it - } else if (bp.isMimeType("multipart/*")) { - String htmlContent = decomposeMultipartEmail(attachments, bp, email, emailService); - if (htmlContent != null) { - result = htmlContent; - } - - // else, this is an attachment - } else { - String fileName = bp.getFileName(); - - // parse Content-ID (content identifier in html mail content) - String[] headers = bp.getHeader("Content-ID"); - String contentID = null; - if (headers != null) { - contentID = headers[0]; - contentID = contentID.replaceFirst("^<(.*)>$", "$1"); - } - - // remove the guillemets between the id - - if (fileName == null && contentID == null) { - break; - } else if (fileName == null) { - fileName = contentID; - } - - try { - fileName = MimeUtility.decodeText(fileName); - if (log.isDebugEnabled()) { - log.debug("FileName : " + fileName + ", Content-ID : " + contentID); - } - } catch (UnsupportedEncodingException ex) { - // don't care, use filename raw value - if (log.isWarnEnabled()) { - log.warn("Can't debug email file name", ex); - } - } - - DataHandler dh = bp.getDataHandler(); - - // create new attachment - Attachment attachment = new AttachmentImpl(); - attachment.setAddedByUser(false); - AttachmentFile attachmentFile = emailService.getAttachmentFileFromStream(dh.getInputStream()); - attachmentFile.setFilename(fileName); - attachment.setOriginalFile(attachmentFile); - attachment.setContentId(contentID); - - // convert attachment if defined by admin - convertIfNecessary(attachment); - - // save attachment - attachments.add(attachment); - } - } - return result; - } - - /** - * Retourne un input stream sur une piece jointe convertie ou pas. - * - * @param attachment to convert - * @return attachment - * @throws IOException - */ - protected Attachment convertIfNecessary(Attachment attachment) throws IOException { - - // get file extension - String filename = attachment.getOriginalFileName(); - String extension = FilenameUtils.getExtension(filename); - - if (StringUtils.isNotBlank(extension)) { - ExtensionCommand command = configurationService.getExtensionCommand(extension); - - // si une extension est configurée avec une commande non vide - if (command != null && StringUtils.isNotBlank(command.getConvertToPdfCommand())) { - attachment = convertToPdf(attachment, command); - } - } - return attachment; - } - - /** - * Convert attachment to pdf. - * - * @param attachment attachment to convert - * @param extensionCommand command - * @return - * @throws IOException - */ - protected Attachment convertToPdf(Attachment attachment, ExtensionCommand extensionCommand) throws IOException { - - // get file extension - String filename = attachment.getOriginalFileName(); - String basename = FilenameUtils.getBaseName(filename); - String extension = FilenameUtils.getExtension(filename); - - // copy file to temp file - File file = File.createTempFile("faxtomail-" + basename, "." + extension); - file.deleteOnExit(); - // on creer un nouveau nom de fichier ou seulement le nom de l'extension change - // cela permet de fonctionner avec openoffice par exemple où il n'est pas possible - // de specifier le nom du fichier de sortie - String fullname = StringUtils.removeEnd(file.getAbsolutePath(), "." + extension); - File outfile = new File(fullname + ".pdf"); - outfile.deleteOnExit(); - FileUtils.writeByteArrayToFile(file, attachment.getOriginalFile().getContent()); - - // get process command - String command = extensionCommand.getConvertToPdfCommand(); - String[] args = StringUtil.split(command, " "); - List<String> comArgs = new ArrayList<String>(); - for (String arg : args) { - String localArg = arg; - localArg = localArg.replace("%f", file.getAbsolutePath()); - localArg = localArg.replace("%o", outfile.getAbsolutePath()); - comArgs.add(localArg); - } - ProcessBuilder pb = new ProcessBuilder(comArgs); - // run process - if (log.isDebugEnabled()) { - log.debug("Convert attachment with command : " + comArgs); - } - try { - Process process = pb.start(); - process.waitFor(); - - // read output to save into attachment - byte[] outContent = FileUtils.readFileToByteArray(outfile); - - // on va dire que normalement un pdf ca fait plus de 1 octet - if (outContent.length >= 1) { - AttachmentFile editedFile = new AttachmentFileImpl(); - editedFile.setContent(outContent); - editedFile.setFilename(basename + "-converted.pdf"); - attachment.setEditedFile(editedFile); - } else if (log.isWarnEnabled()) { - log.warn("Can't convert extension to pdf (content is empty)"); - } - - } catch (IOException e) { - if (log.isErrorEnabled()) { - log.error("Cannot run convert command", e); - } - } catch (InterruptedException e) { - if (log.isErrorEnabled()) { - log.error("Cannot run convert command", e); - } - } - - // cleanup - file.delete(); - outfile.delete(); - - return attachment; - } - - protected Attachment convertTextToPdf(String content, String name) throws IOException, DocumentException { - //File target = File.createTempFile("faxtomail-", ".tmp"); - //target.deleteOnExit(); - - Document document = new Document(); - //FileOutputStream fos = new FileOutputStream(target); - ByteArrayOutputStream os = new ByteArrayOutputStream(); - PdfWriter writer = PdfWriter.getInstance(document, os); - writer.open(); - - document.setPageSize(PageSize.A4); - document.open(); - - document.add(new Paragraph(content)); - - document.close(); - writer.close(); - - // convert content to blob - AttachmentFile attachmentFileNew = new AttachmentFileImpl(); - attachmentFileNew.setContent(os.toByteArray()); - attachmentFileNew.setFilename(name + ".pdf"); - - Attachment attachment = new AttachmentImpl(); - attachment.setOriginalFile(attachmentFileNew); - attachment.setOriginalFileName(name + ".pdf"); - attachment.setAddedByUser(false); - - //target.delete(); - - return attachment; - } - - /** - * Convert html content to image. - * - * @param attachments attachment content to link content to - * @param content html content - * @param name result attachment name - * @return image attachment or {@code null} if content can't be converted - * @throws IOException - */ - protected Attachment convertHTMLToPdf(List<Attachment> attachments, String content, String name) throws IOException { - - - Attachment result = null; - ByteArrayOutputStream os = new ByteArrayOutputStream(); - Collection<File> fileToDelete = new ArrayList<File>(); - try { - content = content.replaceAll("<meta (.*?)>(</meta>)?", ""); - - for (Attachment attachment : attachments) { - String key = attachment.getContentId(); - if (key == null) { - key = attachment.getOriginalFileName(); - } - - // get file content - AttachmentFile attachmentFile = attachment.getOriginalFile(); - File file = attachmentFile.getFile(); - fileToDelete.add(file); - - // replace the inline attachments with the extracted attachment file url - // match les patterns: - // <td background="cid:bg.gif" height="52"> - // <img border=0 src="cid:bg.gif" /> - // <img src='cid:5e9ef859-ea65-4f9b-a9fa-30d4a2c5837c' - content = content.replaceAll("(\\w+)=([\"'])cid:" + Pattern.quote(key) + "([\"'])", "$1=$2file://" + file.getAbsolutePath() + "$3"); - - if (log.isDebugEnabled()) { - log.debug("Mapping attachment id " + key + " to file " + file.getAbsolutePath()); - } - } - - Html2Image image = Html2Image.fromHtml(content); - //ImageRenderer imageRenderer = image.getImageRenderer(); - //imageRenderer.saveImage(os, true); - org.w3c.dom.Document doc = image.getParser().getDocument(); - - // convert to pdf - ITextRenderer renderer = new ITextRenderer(); - renderer.setDocument(doc, null); - renderer.layout(); - renderer.createPDF(os); - - // convert content to blob - AttachmentFile attachmentFileNew = new AttachmentFileImpl(); - attachmentFileNew.setContent(os.toByteArray()); - attachmentFileNew.setFilename(name + ".pdf"); - - result = new AttachmentImpl(); - result.setOriginalFile(attachmentFileNew); - result.setOriginalFileName(name + ".pdf"); - result.setAddedByUser(false); - } catch (OutOfMemoryError er) { - // certains mails (spam) très compliqué ne peuvent pas être convertit en images - if (log.isWarnEnabled()) { - log.warn("Can't convert html content to pdf", er); - } - } catch (DocumentException ex) { - if (log.isWarnEnabled()) { - log.warn("Can't convert html content to pdf", ex); - } - } finally { - // on supprime les fichiers avant le delete on exit pour eviter que le disque ne se remplissent trop vite - for (File file : fileToDelete) { - file.delete(); - } - } - - return result; - } } Modified: trunk/faxtomail-ui-web/src/main/webapp/WEB-INF/content/admin/import-archive-wait.jsp =================================================================== --- trunk/faxtomail-ui-web/src/main/webapp/WEB-INF/content/admin/import-archive-wait.jsp 2014-11-17 13:46:57 UTC (rev 689) +++ trunk/faxtomail-ui-web/src/main/webapp/WEB-INF/content/admin/import-archive-wait.jsp 2014-11-17 15:30:51 UTC (rev 690) @@ -1,3 +1,26 @@ +<%-- + #%L + FaxToMail :: Web + $Id:$ + $HeadURL:$ + %% + Copyright (C) 2014 Mac-Groupe, Code Lutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public + License along with this program. If not, see + <http://www.gnu.org/licenses/gpl-3.0.html>. + #L% + --%> <%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%> <!DOCTYPE html> <%@taglib uri="/struts-tags" prefix="s" %> Modified: trunk/faxtomail-ui-web/src/main/webapp/WEB-INF/content/demand-detail.jsp =================================================================== --- trunk/faxtomail-ui-web/src/main/webapp/WEB-INF/content/demand-detail.jsp 2014-11-17 13:46:57 UTC (rev 689) +++ trunk/faxtomail-ui-web/src/main/webapp/WEB-INF/content/demand-detail.jsp 2014-11-17 15:30:51 UTC (rev 690) @@ -1,3 +1,26 @@ +<%-- + #%L + FaxToMail :: Web + $Id:$ + $HeadURL:$ + %% + Copyright (C) 2014 Mac-Groupe, Code Lutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public + License along with this program. If not, see + <http://www.gnu.org/licenses/gpl-3.0.html>. + #L% + --%> <%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%> <!DOCTYPE html> <%@taglib uri="/struts-tags" prefix="s" %> Modified: trunk/faxtomail-ui-web/src/main/webapp/WEB-INF/content/search-input.jsp =================================================================== --- trunk/faxtomail-ui-web/src/main/webapp/WEB-INF/content/search-input.jsp 2014-11-17 13:46:57 UTC (rev 689) +++ trunk/faxtomail-ui-web/src/main/webapp/WEB-INF/content/search-input.jsp 2014-11-17 15:30:51 UTC (rev 690) @@ -1,3 +1,26 @@ +<%-- + #%L + FaxToMail :: Web + $Id:$ + $HeadURL:$ + %% + Copyright (C) 2014 Mac-Groupe, Code Lutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public + License along with this program. If not, see + <http://www.gnu.org/licenses/gpl-3.0.html>. + #L% + --%> <%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%> <!DOCTYPE html> <%@taglib uri="/struts-tags" prefix="s" %> Modified: trunk/faxtomail-ui-web/src/main/webapp/css/demand-detail.css =================================================================== --- trunk/faxtomail-ui-web/src/main/webapp/css/demand-detail.css 2014-11-17 13:46:57 UTC (rev 689) +++ trunk/faxtomail-ui-web/src/main/webapp/css/demand-detail.css 2014-11-17 15:30:51 UTC (rev 690) @@ -1,3 +1,26 @@ +/* + * #%L + * FaxToMail :: Web + * $Id:$ + * $HeadURL:$ + * %% + * Copyright (C) 2014 Mac-Groupe, Code Lutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/gpl-3.0.html>. + * #L% + */ .float-right { float: right; } Modified: trunk/faxtomail-ui-web/src/main/webapp/js/demand-detail.js =================================================================== --- trunk/faxtomail-ui-web/src/main/webapp/js/demand-detail.js 2014-11-17 13:46:57 UTC (rev 689) +++ trunk/faxtomail-ui-web/src/main/webapp/js/demand-detail.js 2014-11-17 15:30:51 UTC (rev 690) @@ -1,3 +1,26 @@ +/* + * #%L + * FaxToMail :: Web + * $Id:$ + * $HeadURL:$ + * %% + * Copyright (C) 2014 Mac-Groupe, Code Lutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/gpl-3.0.html>. + * #L% + */ var DemandDetailModule = angular.module('DemandDetailModule', ['FaxToMail', 'ngSanitize']); DemandDetailModule.controller('DemandDetailController', ['$scope', 'DemandDetailData',