# HG changeset patch
# User František Kučera <franta-hg@frantovo.cz>
# Date 1320534485 -3600
# Node ID 4ddc1020a15433ca42b20db9bfced6aaa03b4234
# Parent  e5bfc969d41fd5e0fd11c38a560d9da86dbd83eb
Podpora Markdown syntaxe
na začátek odesílané zprávy stačí přidat:
#!markdown
a zpráva se pak prožene Markdown procesorem (spouštěno přes sudo pod jiným uživatelem)
a pak teprve přes standardní XSL transformaci.

1) Vytvořit uživatele a skupinu markdown

2) Do /etc/sudoers přidat:
Cmnd_Alias  MARKDOWN = /usr/bin/markdown
%markdown ALL = (%markdown) NOPASSWD : MARKDOWN

3) Uivatele, pod kterým běží NNTP démon, přidat do skupiny markdown

diff -r e5bfc969d41f -r 4ddc1020a154 helpers/mimeXhtmlPart.xsl
--- a/helpers/mimeXhtmlPart.xsl	Sat Nov 05 00:06:09 2011 +0100
+++ b/helpers/mimeXhtmlPart.xsl	Sun Nov 06 00:08:05 2011 +0100
@@ -130,6 +130,7 @@
 		</blockquote>
 	</xsl:template>
 	
+	
 	<!-- Tučné písmo -->
 	<xsl:template match="h:b">
 		<strong>
@@ -137,6 +138,7 @@
 		</strong>
 	</xsl:template>
 	
+	
 	<!-- Skloněné písmo -->
 	<xsl:template match="h:i">
 		<em>
@@ -145,6 +147,12 @@
 	</xsl:template>
 	
 	
+	<!-- Markdown dává do pre ještě code – to ale nepotřebujeme, stačí nám pre a v něm rovnou text -->
+	<xsl:template match="h:pre[h:code]">
+		<pre><xsl:apply-templates select="h:code/node()"/></pre>
+	</xsl:template>
+	
+	
 	<!--
 		Další povolené značky (jejich případné atributy zahodíme).
 		Ostatní elementy odfiltrujeme (zbude z nich jen text). 
diff -r e5bfc969d41f -r 4ddc1020a154 src/org/sonews/storage/DrupalMessage.java
--- a/src/org/sonews/storage/DrupalMessage.java	Sat Nov 05 00:06:09 2011 +0100
+++ b/src/org/sonews/storage/DrupalMessage.java	Sun Nov 06 00:08:05 2011 +0100
@@ -71,6 +71,11 @@
  */
 public class DrupalMessage extends MimeMessage {
 
+	/**
+	 * If body of message posted by user through NNTP starts with this text,
+	 * it will be treated as formated text in Markdown syntax.
+	 */
+	private static final String MARKDOWN_HEADER = "#!markdown\r\n";
 	private static final Logger log = Logger.getLogger(DrupalMessage.class.getName());
 	private static final String MESSAGE_ID_HEADER = "Message-ID";
 	private static final String CRLF = "\r\n";
@@ -266,6 +271,33 @@
 	}
 
 	/**
+	 * Converts markdown to XHTML.
+	 * @param markdown text in Markdown syntax
+	 * @return XHTML document (with html/body elements)
+	 * @throws StorageBackendException when markdown proces returned any errors 
+	 * (other exceptions are thrown when afterwards XHTML validation fails).
+	 */
+	private String readXhtmlTextMarkdown(String markdown) throws TransformerException, IOException, ParserConfigurationException, SAXException, StorageBackendException {
+		Runtime r = Runtime.getRuntime();
+		Process p = r.exec(new String[]{"sudo", "-u", "markdown", "/usr/bin/markdown"});
+
+		PrintStream processInput = new PrintStream(p.getOutputStream());
+		processInput.print(markdown);
+		processInput.close();
+
+		String errors = streamToString(p.getErrorStream());
+		String htmlFragment = streamToString(p.getInputStream());
+
+		if (errors.length() == 0) {
+			String htmlDocument = makeSimpleXHTML(htmlFragment);
+			String xhtmlDocument = readXhtmlText(htmlDocument, null, -1, null, null, null);
+			return xhtmlDocument;
+		} else {
+			throw new StorageBackendException("Error while transforming Markdown to XHTML: " + errors);
+		}
+	}
+
+	/**
 	 * Does not parse XML works just with text.
 	 * @param body XHTML fragment that should be put between &lt;body&gt; and &lt;/body&gt;
 	 * @return simple XHTML document (body wrapped in html and body tags)
@@ -503,13 +535,21 @@
 		try {
 			Object c = getContent();
 			if (isMimeType("text/plain") && c instanceof String) {
-				String xhtml = readXhtmlText(
-						(String) c,
-						getSubject(),
-						getParentID(),
-						null,
-						null,
-						null);
+				String inputText = (String) c;
+				String xhtml;
+
+				if (inputText.startsWith(MARKDOWN_HEADER)) {
+					xhtml = readXhtmlTextMarkdown(inputText.substring(MARKDOWN_HEADER.length()));
+				} else {
+
+					xhtml = readXhtmlText(
+							inputText,
+							getSubject(),
+							getParentID(),
+							null,
+							null,
+							null);
+				}
 				return makeFragmentXHTML(xhtml);
 			} else {
 				throw new StorageBackendException("Only text/plain messages are supported for now – post it as plain text please.");