Commit 5acc9e4e authored by  JosephK's avatar JosephK

Typo mails

parent 8b730f73
/*
* Copyright [2015] [wisemapping]
*
* Licensed under WiseMapping Public License, Version 1.0 (the "License").
* It is basically the Apache License, Version 2.0 (the "License") plus the
* "powered by wisemapping" text requirement on every single page;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the license at
*
* http://www.wisemapping.org/license
*
* 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 com.wisemapping.exporter;
import com.wisemapping.importer.VersionNumber;
import org.apache.batik.parser.AWTTransformProducer;
import org.apache.batik.parser.ParseException;
import org.apache.batik.parser.TransformListParser;
import org.apache.batik.transcoder.Transcoder;
import org.apache.batik.transcoder.TranscoderException;
import org.apache.batik.transcoder.TranscoderInput;
import org.apache.batik.transcoder.TranscoderOutput;
import org.apache.batik.transcoder.image.ImageTranscoder;
import org.apache.batik.transcoder.image.JPEGTranscoder;
import org.apache.batik.transcoder.image.PNGTranscoder;
import org.apache.fop.svg.PDFTranscoder;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.w3c.dom.*;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import sun.misc.BASE64Encoder;
import javax.servlet.ServletContext;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.xpath.*;
import java.awt.geom.AffineTransform;
import java.io.*;
import java.util.regex.Pattern;
public class ExporterFactory {
private static final String GROUP_NODE_NAME = "g";
private static final String IMAGE_NODE_NAME = "image";
public static final int MANGING = 50;
public static final String UTF_8_CHARSET_NAME = "UTF-8";
private File baseImgDir;
public ExporterFactory(@NotNull final ServletContext servletContext) throws ParserConfigurationException {
this.baseImgDir = new File(servletContext.getRealPath("/"));
}
public ExporterFactory(@NotNull final File baseImgDir) throws ParserConfigurationException {
this.baseImgDir = baseImgDir;
}
public void export(@NotNull ExportProperties properties, @Nullable String xml, @NotNull OutputStream output, @Nullable String mapSvg) throws ExportException, IOException, TranscoderException {
final ExportFormat format = properties.getFormat();
switch (format) {
case PNG: {
// Create a JPEG transcoder
final Transcoder transcoder = new PNGTranscoder();
final ExportProperties.ImageProperties imageProperties =
(ExportProperties.ImageProperties) properties;
final ExportProperties.ImageProperties.Size size = imageProperties.getSize();
transcoder.addTranscodingHint(ImageTranscoder.KEY_WIDTH, size.getWidth());
// Create the transcoder input.
final String svgString = normalizeSvg(mapSvg);
final TranscoderInput input = new TranscoderInput(new CharArrayReader(svgString.toCharArray()));
TranscoderOutput trascoderOutput = new TranscoderOutput(output);
// Save the image.
transcoder.transcode(input, trascoderOutput);
break;
}
case JPG: {
// Create a JPEG transcoder
final Transcoder transcoder = new JPEGTranscoder();
transcoder.addTranscodingHint(JPEGTranscoder.KEY_QUALITY, new Float(.99));
final ExportProperties.ImageProperties imageProperties =
(ExportProperties.ImageProperties) properties;
final ExportProperties.ImageProperties.Size size = imageProperties.getSize();
transcoder.addTranscodingHint(ImageTranscoder.KEY_WIDTH, size.getWidth());
// Create the transcoder input.
final String svgString = normalizeSvg(mapSvg);
final TranscoderInput input = new TranscoderInput(new CharArrayReader(svgString.toCharArray()));
TranscoderOutput trascoderOutput = new TranscoderOutput(output);
// Save the image.
transcoder.transcode(input, trascoderOutput);
break;
}
case PDF: {
// Create a JPEG transcoder
final Transcoder transcoder = new PDFTranscoder();
// Create the transcoder input.
final String svgString = normalizeSvg(mapSvg);
final TranscoderInput input = new TranscoderInput(new CharArrayReader(svgString.toCharArray()));
TranscoderOutput trascoderOutput = new TranscoderOutput(output);
// Save the image.
transcoder.transcode(input, trascoderOutput);
break;
}
case SVG: {
final String svgString = normalizeSvg(mapSvg);
output.write(svgString.getBytes(UTF_8_CHARSET_NAME));
break;
}
case TEXT: {
final Exporter exporter = XSLTExporter.create(XSLTExporter.Type.TEXT);
exporter.export(xml.getBytes(UTF_8_CHARSET_NAME), output);
break;
}
case OPEN_OFFICE_WRITER: {
final Exporter exporter = XSLTExporter.create(XSLTExporter.Type.OPEN_OFFICE);
exporter.export(xml.getBytes(UTF_8_CHARSET_NAME), output);
break;
}
case MICROSOFT_EXCEL: {
final Exporter exporter = XSLTExporter.create(XSLTExporter.Type.MICROSOFT_EXCEL);
exporter.export(xml.getBytes(UTF_8_CHARSET_NAME), output);
break;
}
case FREEMIND: {
final FreemindExporter exporter = new FreemindExporter();
exporter.setVersion(new VersionNumber(properties.getVersion()));
exporter.export(xml.getBytes(UTF_8_CHARSET_NAME), output);
break;
}
case MINDJET: {
final Exporter exporter = XSLTExporter.create(XSLTExporter.Type.MINDJET);
exporter.export(xml.getBytes(UTF_8_CHARSET_NAME), output);
break;
}
default:
throw new UnsupportedOperationException("Export method not supported.");
}
}
private String normalizeSvg(@NotNull String svgXml) throws ExportException {
try {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
final DocumentBuilder documentBuilder = factory.newDocumentBuilder();
if (!svgXml.contains("xmlns:xlink=\"http://www.w3.org/1999/xlink\"")) {
svgXml = svgXml.replaceFirst("<svg ", "<svg xmlns = \"http://www.w3.org/2000/svg\" xmlns:xlink = \"http://www.w3.org/1999/xlink\" ");
}
// Hacks for some legacy cases ....
svgXml = svgXml.replaceAll("NaN,", "0");
svgXml = svgXml.replaceAll(",NaN", "0");
// Bratik do not manage nbsp properly.
svgXml = svgXml.replaceAll(Pattern.quote("&nbsp;"), " ");
Document document;
try {
final Reader in = new CharArrayReader(svgXml.toCharArray());
final InputSource is = new InputSource(in);
document = documentBuilder.parse(is);
} catch (SAXException e) {
// It must be a corrupted SVG format. Try to hack it and try again ...
svgXml = svgXml.replaceAll("<image([^>]+)>", "<image$1/>");
svgXml = svgXml.replaceAll("\u001B", "");
final Reader in = new CharArrayReader(svgXml.toCharArray());
final InputSource is = new InputSource(in);
document = documentBuilder.parse(is);
}
resizeSVG(document);
final Node child = document.getFirstChild();
inlineImages(document, (Element) child);
return domToString(document);
} catch (ParserConfigurationException | TransformerException | SAXException | IOException e) {
throw new ExportException(e);
}
}
private static String domToString(@NotNull Document document) throws TransformerException {
DOMSource domSource = new DOMSource(document);
// Create a string writer
final CharArrayWriter result = new CharArrayWriter();
// Create the stream stream for the transform
StreamResult stream = new StreamResult(result);
// Create a Transformer to serialize the document
TransformerFactory tFactory = TransformerFactory.newInstance();
Transformer transformer = tFactory.newTransformer();
transformer.setOutputProperty("indent", "yes");
// Transform the document to the stream stream
transformer.transform(domSource, stream);
return result.toString();
}
private void inlineImages(@NotNull Document document, @NotNull Element element) {
final NodeList list = element.getChildNodes();
for (int i = 0; i < list.getLength(); i++) {
final Node node = list.item(i);
// find all groups
if (GROUP_NODE_NAME.equals(node.getNodeName())) {
// Must continue looking ....
inlineImages(document, (Element) node);
} else if (IMAGE_NODE_NAME.equals(node.getNodeName())) {
Element elem = (Element) node;
final String imgUrl = fixHref(elem);
if (!imgUrl.isEmpty() && (!imgUrl.startsWith("image/png;base64") || !imgUrl.startsWith("data:image/png;base64"))) {
elem.removeAttribute("href");
InputStream fis = null;
// Obtains file name ...
try {
final File iconFile = iconFile(imgUrl);
final ByteArrayOutputStream bos = new ByteArrayOutputStream();
fis = new FileInputStream(iconFile);
BASE64Encoder encoder = new BASE64Encoder();
encoder.encode(fis, bos);
elem.setAttribute("xlink:href", "data:image/png;base64," + bos.toString("8859_1"));
elem.appendChild(document.createTextNode(" "));
} catch (IOException e) {
e.printStackTrace();
} finally {
close(fis);
}
}
}
}
}
@NotNull
private String fixHref(@NotNull Element elem) {
// Fix href attribute ...
// Hack for IE: If the image is a external URL, embeed it...
String result = elem.getAttribute("href");
if (result.isEmpty()) {
// Bug WISE-422: This seems to be a bug in Safari. For some reason, img add prefixed with NS1
// <image NS1:href="icons/sign_help.png"
// Also: Remove replace "xlink:href" to href to uniform ...
final NamedNodeMap attributes = elem.getAttributes();
for (int i = 0; i < attributes.getLength(); i++) {
final Node node = attributes.item(i);
String nodeName = node.getNodeName();
if(nodeName.contains(":href")){
elem.removeAttribute(nodeName);
result = node.getNodeValue();
}
}
elem.setAttribute("href", result);
}
return result;
}
private File iconFile(@NotNull final String imgUrl) throws IOException {
int index = imgUrl.lastIndexOf("/");
final String iconName = imgUrl.substring(index + 1);
final File iconsDir = new File(baseImgDir, "icons");
File result = new File(iconsDir, iconName);
if (!result.exists()) {
// It's not a icon, must be a note, attach image ...
final File legacyIconsDir = new File(baseImgDir, "images");
result = new File(legacyIconsDir, iconName);
}
if (!result.exists()) {
final File legacyIconsDir = new File(iconsDir, "legacy");
result = new File(legacyIconsDir, iconName);
}
if (!result.exists() || result.isDirectory()) {
throw new IOException("Icon could not be found:" + imgUrl);
}
return result;
}
private void close(Closeable fis) {
if (fis != null) {
try {
fis.close();
} catch (IOException e) {
// Ignore ...
}
}
}
private static void resizeSVG(@NotNull Document document) throws ExportException {
try {
XPathFactory xPathfactory = XPathFactory.newInstance();
XPath xpath = xPathfactory.newXPath();
XPathExpression expr = xpath.compile("/svg/g/rect");
NodeList nl = (NodeList) expr.evaluate(document, XPathConstants.NODESET);
final int length = nl.getLength();
double maxX = 0, minX = 0, minY = 0, maxY = 0;
for (int i = 0; i < length; i++) {
final Element rectElem = (Element) nl.item(i);
final Element gElem = (Element) rectElem.getParentNode();
final TransformListParser p = new TransformListParser();
final AWTTransformProducer tp = new AWTTransformProducer();
p.setTransformListHandler(tp);
p.parse(gElem.getAttribute("transform"));
final AffineTransform transform = tp.getAffineTransform();
double yPos = transform.getTranslateY();
if (yPos > 0) {
yPos += Double.parseDouble(rectElem.getAttribute("height"));
}
maxY = maxY < yPos ? yPos : maxY;
minY = minY > yPos ? yPos : minY;
double xPos = transform.getTranslateX();
if (xPos > 0) {
xPos += Double.parseDouble(rectElem.getAttribute("width"));
}
maxX = maxX < xPos ? xPos : maxX;
minX = minX > xPos ? xPos : minX;
}
// Add some extra margin ...
maxX += MANGING;
minX += -MANGING;
maxY += MANGING;
minY += -MANGING;
// Calculate dimentions ...
final double width = maxX + Math.abs(minX);
final double height = maxY + Math.abs(minY);
// Finally, update centers ...
final Element svgNode = (Element) document.getFirstChild();
svgNode.setAttribute("viewBox", minX + " " + minY + " " + width + " " + height);
svgNode.setAttribute("width", Double.toString(width));
svgNode.setAttribute("height", Double.toString(height));
svgNode.setAttribute("preserveAspectRatio", "xMinYMin");
} catch (XPathExpressionException | ParseException | NumberFormatException | DOMException e) {
throw new ExportException(e);
}
}
private static String[] getTransformUnit(NamedNodeMap groupAttributes) {
final String value = groupAttributes.getNamedItem("transform").getNodeValue();
final int pos = value.indexOf("translate");
final int initTranslate = value.indexOf("(", pos);
final int endTranslate = value.indexOf(")", pos);
final String transate = value.substring(initTranslate + 1, endTranslate);
return transate.contains(",") ? transate.split(",") : transate.split(" ");
}
}
......@@ -83,7 +83,7 @@ final public class NotificationService {
final String mailSubject = "[Framindmap] Votre nouveau mot de passe";
final String messageTitle = "Votre nouveau mot de passe a &eacute;t&eacute; cr&eacute;&eacute;";
final String messageBody =
"<p>Quelqu'un, probablement vous, a demand&eacute; &agrave; r&eacuteinitialiser le mot de passe de votre compte Framindmap. </p>\n" +
"<p>Quelqu&rsquo;un, probablement vous, a demand&eacute; &agrave; r&eacuteinitialiser le mot de passe de votre compte Framindmap. </p>\n" +
"<p><strong>Voici votre nouveau mot de passe&nbsp;: " + temporalPassword + "</strong></p>\n" +
"<p>Vous pouvez vous connecter en cliquant <a href=\"" + getBaseUrl() + "/c/login\">sur ce lien</a>. Nous vous encourageons fortement &agrave; changer ce mot de passe le plus rapidement possible.</p>";
......@@ -94,16 +94,16 @@ final public class NotificationService {
final String mailSubject = "[Framindmap] Votre mot de passe a été modifié";
final String messageTitle = "Votre nouveau mot de passe a bien &eacute;t&eacute; modifi&eacute; correctement";
final String messageBody =
"<p>Ceci est juste un mail de confirmation que votre mot de passe a bien &eacute;t&eacute; chang&eacute;. Aucune action suppl&eacute;mentaire n'est requise.</p>";
"<p>Ceci est juste un mail de confirmation que votre mot de passe a bien &eacute;t&eacute; chang&eacute;. Aucune action suppl&eacute;mentaire n&rsquo;est requise.</p>";
sendTemplateMail(user, mailSubject, messageTitle, messageBody);
}
public void newAccountCreated(@NotNull User user) {
final String mailSubject = "Bienvenue dans Framindmap !";
final String messageTitle = "Votre compte a &eacute;t&eacute; cr&eacute;&eacute; avec succ&eagrave;s";
final String messageTitle = "Votre compte a &eacute;t&eacute; cr&eacute;&eacute; avec succ&egrave;s";
final String messageBody =
"<p>Merci de l'int&eacute;r&ecirc;t que vous portez &agrave; Framindmap. Si vous avez des remarques ou id&eacute;es d'am&eacute;lioration, envoyez nous un email sur <a href=\"https://contact.framasoft.org/#framindmap\">contact.framasoft.org</a>.</p>";
"<p>Merci de l&rsquo;int&eacute;r&ecirc;t que vous portez &agrave; Framindmap. Si vous avez des remarques ou id&eacute;es d&rsquo;am&eacute;lioration, envoyez nous un email sur <a href=\"https://contact.framasoft.org/#framindmap\">contact.framasoft.org</a>.</p>";
sendTemplateMail(user, mailSubject, messageTitle, messageBody);
}
......
......@@ -19,22 +19,22 @@
</table>
</div>
<div style="font-size: 13px; background-color: #FFF; padding: 10px 0; min-height: 100px">
<p>Bonjour ${firstName}&nbsp;:</p>
<p>Bonjour ${firstName},</p>
<p>
${messageBody}
</p>
<p>Cordialement,<br/>
L'&eacute;quipe Framasoft<br/>
L&rsquo;&eacute;quipe Framasoft<br/>
</p>
<p>--<br />"La route est longue, mais la voie est libre..."<br/>
<p>--<br />«&nbsp;La route est longue, mais la voie est libre...&nbsp;»<br/>
Framasoft ne vit que par vos dons (d&eacute;ductibles des imp&ocirc;ts).<br />
Merci d'avance pour votre soutien <a href="https://soutenir.framasoft.org">https://soutenir.framasoft.org</a>.</p>
Merci d&rsquo;avance pour votre soutien <a href="https://soutenir.framasoft.org">https://soutenir.framasoft.org</a>.</p>
</div>
</div>
<p style="font-size: 13px;font-family: Arial, sans-serif">Important&nbsp;: Ne r&eacute;pondez pas &agrave; ce mail. Si vous avez besoin d'aide ou pensez avoir re&ccedil;u ce mail par erreur, <a href="http://contact.framasoft.org">contactez-nous</a>.
<p style="font-size: 13px;font-family: Arial, sans-serif">Important&nbsp;: Ne r&eacute;pondez pas &agrave; ce mail. Si vous avez besoin d&rsquo;aide ou pensez avoir re&ccedil;u ce mail par erreur, <a href="https://contact.framasoft.org/#framindmap">contactez-nous</a>.
</p>
</body>
</html>
\ No newline at end of file
......@@ -9,25 +9,25 @@
</p>
<p>
Si vous avez re&ccedil;u ce mail par erreur, vous n'avez rien &agrave; faire pour supprimer votre compte.
Votre compte ne sera tout simplement pas activ&eacute; et vous ne recevrez pas d'autre email de notre part.
Votre compte ne sera tout simplement pas activ&eacute; et vous ne recevrez pas d&rsquo;autre email de notre part.
</p>
<p>
Si vous ne parvenez pas &agrave; cliquer sur le lien ci-dessus,
copiez et coller l'URL dans la barre d'adresse de votre navigateur web.
copiez et coller l&rsquo;URL dans la barre d&rsquo;adresse de votre navigateur web.
</p>
<p>
Si vous avez des questions relatives &agrave; l'utilisation de votre compte, <a href="https://contact.framasoft.org/#framindmap">contactez-nous</a>.
Si vous avez des questions relatives &agrave; l&rsquo;utilisation de votre compte, <a href="https://contact.framasoft.org/#framindmap">contactez-nous</a>.
</p>
<p>
Cordialement,<br/>
L'&eacute;quipe Framasoft.
L&rsquo;&eacute;quipe Framasoft.
</p>
<p>--<br />"La route est longue, mais la voie est libre..."<br/>
<p>--<br />«&nbsp;La route est longue, mais la voie est libre...&nbsp;»<br/>
Framasoft ne vit que par vos dons (d&eacute;ductibles des imp&ocirc;ts).<br />
Merci d'avance pour votre soutien <a href="https://soutenir.framasoft.org">https://soutenir.framasoft.org</a>.</p>
Merci d&rsquo;avance pour votre soutien <a href="https://soutenir.framasoft.org">https://soutenir.framasoft.org</a>.</p>
</body>
</html>
......@@ -26,19 +26,19 @@
#end
<p>Cliquez sur le lien suivant pour ouvrir la carte mentale&nbsp;: <a href="${mapEditUrl}">${mindmap.title}</a></p>
<p>Si vous n'avez pas de compte sur Framindmap, vous pouvez cr&eacute;er un compte gratuitement et librement.</p>
<p>Si vous n&rsquo;avez pas de compte sur Framindmap, vous pouvez cr&eacute;er un compte gratuitement et librement.</p>
<p>Cordialement,<br/>
L'&eacute;quipe Framasoft<br/>
L&rsquo;&eacute;quipe Framasoft<br/>
</p>
<p>--<br />"La route est longue, mais la voie est libre..."<br/>
<p>--<br />«&nbsp;La route est longue, mais la voie est libre...&nbsp;»<br/>
Framasoft ne vit que par vos dons (d&eacute;ductibles des imp&ocirc;ts).<br />
Merci d'avance pour votre soutien <a href="https://soutenir.framasoft.org">https://soutenir.framasoft.org</a>.</p>
Merci d&rsquo;avance pour votre soutien <a href="https://soutenir.framasoft.org">https://soutenir.framasoft.org</a>.</p>
</div>
</div>
<p style="font-size: 13px;font-family: Arial, sans-serif">Important&nbsp;: Ne r&eacute;pondez pas &agrave; ce mail. Si vous avez besoin d'aide ou pensez avoir re&ccedil;u ce mail par erreur, <a href="https://contact.framasoft.org/#framindmap">contactez-nous</a>.
<p style="font-size: 13px;font-family: Arial, sans-serif">Important&nbsp;: Ne r&eacute;pondez pas &agrave; ce mail. Si vous avez besoin d&rsquo;aide ou pensez avoir re&ccedil;u ce mail par erreur, <a href="https://contact.framasoft.org/#framindmap">contactez-nous</a>.
</p>
</body>
</html>
\ No newline at end of file
......@@ -7,7 +7,7 @@
<spring:message code="EXPORT_DETAILS"/>
</div>
<div class="alert alert-warning" role="alert">
Contrairement à ce qui est indiqué dans le tutoriel vidéo, <b>les exports en pdf ou en jpg/png ne fonctionnent pas</b> sur cette version de Wisemapping. Nous les avons donc désactivés. Si une version plus récente du logiciel corrige ce bug, nous les proposerons à nouveau.
Contrairement à ce qui est indiqué dans le tutoriel vidéo, <b>les exports en pdf ou en jpg/png ne fonctionnent pas</b> sur cette version de Wisemapping. Nous les avons donc désactivés.
</div>
<form method="GET" class="form-horizontal" action="c/restful/maps/${mindmap.id}"
enctype="application/x-www-form-urlencoded" id="dialogMainForm">
......@@ -75,9 +75,9 @@
</label>-->
</fieldset>
</form>
<div id="exportInfo" style="margin-top: 19px;">
<!--<div id="exportInfo" style="margin-top: 19px;">
<span class="label label-danger">Warning</span> <spring:message code="EXPORT_FORMAT_RESTRICTIONS"/>
</div>
</div>-->
</div>
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment