# HG changeset patch # User František Kučera <franta-hg@frantovo.cz> # Date 1340472141 -7200 # Node ID eea9c4713045bdbe5fa8b8ecff2f81c5d4fb6407 # Parent 4b3ba32f613c74b9dab9b205185113b0d88ea3b2 #20 Skriptování: podpora výstupu ve formátu XML (musí být validní) diff -r 4b3ba32f613c -r eea9c4713045 vstup/skriptování.xml --- a/vstup/skriptování.xml Sat Jun 23 18:00:41 2012 +0200 +++ b/vstup/skriptování.xml Sat Jun 23 19:22:21 2012 +0200 @@ -8,30 +8,51 @@ <p> Na stránkách můžeme používat skripty. - Spouští se při generování a jejich standardní výstup se vloží do stránky. - Třeba doprostřed ostavce nebo do jiného elementu. + Spouští se při generování a jejich standardní výstup se vloží do stránky. + Třeba doprostřed textu ostavce nebo do jiného elementu. </p> <p> Příklad: - Tyto stránky byly vygenerované v systému <m:skript jazyk="bash">uname -o</m:skript>. + <em> + Tyto stránky byly vygenerované v systému + <span title="tento text pochází ze skriptu"><m:skript jazyk="bash">uname -o</m:skript></span>. + </em> + </p> + + <p> + Díky skriptování můžeme stránky obohatit o prakticky libovolný obsah. + Tato funkce ale může být nebezpečná – pokud byste spustili generátor na stránkách, + které psal někdo nedůvěryhodný a vložil do nich škodlivý kód. + Proto je skriptování ve výchozím stavu vypnuté – je potřeba ho povolit v souboru <code>web.conf</code>. + </p> + + <h2>Podporované jazyky</h2> + <p> + V současnosti jsou podporované tyto jazyky: </p> - <p> - V současnosti jsou podporované tyto jazyky: - </p> - - <pre><m:skript jazyk="perl"><![CDATA[ + <table> + <thead> + <tr> + <td>Jazyk</td> + <td>Interpret</td> + </tr> + </thead> + <tbody> + <m:skript jazyk="perl" výstup="xml"><![CDATA[ use strict; -open(JAVA, "<", "šablona/funkce/src/cz/frantovo/xmlWebGenerator/makra/Skriptování.java") or die $!; +open(JAVA, "<", $ENV{"XWG_SKRIPTOVANI_JAVA"}) or die $!; while (<JAVA>) { #i.put("bash", "/bin/bash"); if (/podporovanýJazyk\.put\("(\w+)",\s*"(.*)"\);/) { - print "$1\n"; + print "<tr><td><code>$1</code></td><td><code>$2</code></td></tr>\n"; } } - ]]></m:skript></pre> + ]]></m:skript> + </tbody> + </table> <h2>Perl</h2> <p>Jazyky použité nebo citované na této stránce:</p> @@ -76,12 +97,28 @@ Ve skriptech máme dostupné následující proměnné prostředí: </p> - <ul> - <li><code>XWG_STRANKA_URI</code> – URI aktuálně zpracovávané stránky</li> - <li><code>XWG_STRANKA_SOUBOR</code> – absolutní cesta k souboru</li> - <li><code>XWG_STRANKA_NADPIS</code> – nadpis stránky</li> - <li><code>XWG_STRANKA_PEREX</code> – perex stránky</li> - </ul> + <table> + <thead> + <tr> + <td>Proměnná</td> + <td>Význam</td> + </tr> + </thead> + <tbody> + <m:skript jazyk="perl" výstup="xml"><![CDATA[ +use strict; + +open(JAVA, "<", $ENV{"XWG_SKRIPTOVANI_JAVA"}) or die $!; + +while (<JAVA>) { +#i.put("bash", "/bin/bash"); + if (/"(.*)=".*\/\/\s+env:(.*)/) { + print "<tr><td><code>$1</code></td><td>$2</td></tr>\n"; + } +} + ]]></m:skript> + </tbody> + </table> <p> Kód: diff -r 4b3ba32f613c -r eea9c4713045 šablona/funkce/src/cz/frantovo/xmlWebGenerator/makra/Skriptování.java --- a/šablona/funkce/src/cz/frantovo/xmlWebGenerator/makra/Skriptování.java Sat Jun 23 18:00:41 2012 +0200 +++ b/šablona/funkce/src/cz/frantovo/xmlWebGenerator/makra/Skriptování.java Sat Jun 23 19:22:21 2012 +0200 @@ -18,12 +18,16 @@ package cz.frantovo.xmlWebGenerator.makra; import static cz.frantovo.xmlWebGenerator.NástrojeCLI.načtiProud; +import java.io.ByteArrayInputStream; import java.io.File; import java.io.PrintStream; import java.net.URI; import java.util.Collections; import java.util.HashMap; import java.util.Map; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import org.w3c.dom.Document; /** * Provedeme skript a do stránky vložíme jeho výstup. @@ -53,12 +57,13 @@ * * @param skript program k vykonání * @param jazyk programovací jazyk + * @param výstupníFormát text (výchozí) | xml (v tom případě kontrolujeme validitu) * @param uriStránky URI aktuálně generované stránky → proměnná prostředí * @param nadpisStránky nadpis stránky → proměnná prostředí * @param perexStránky perex stránky → proměnná prostředí * @return výstup příkazu */ - public static String interpretuj(String skript, String jazyk, String uriStránky, String nadpisStránky, String perexStránky) { + public static String interpretuj(String skript, String jazyk, String výstupníFormát, String uriStránky, String nadpisStránky, String perexStránky) { try { System.err.println("\tInterpretuji skript v jazyce: " + jazyk); String interpret = interpreti.get(jazyk); @@ -76,19 +81,20 @@ ps.print(skript); ps.close(); - f.setExecutable(true); String[] prostředí = new String[]{ "LANG=" + System.getenv("LANG"), "USER=" + System.getenv("USER"), - "XWG_STRANKA_URI=" + uriStránky, - "XWG_STRANKA_SOUBOR=" + (new File(new URI(uriStránky)).getAbsolutePath()), - "XWG_STRANKA_NADPIS=" + nadpisStránky, - "XWG_STRANKA_PEREX=" + perexStránky + "XWG_SKRIPTOVANI_JAVA=" + "šablona" + File.separator + "funkce" + File.separator + "src" + File.separator + Skriptování.class.getName().replaceAll("\\.", File.separator) + ".java", + "XWG_STRANKA_URI=" + uriStránky, // env:URI aktuálně zpracovávané stránky + "XWG_STRANKA_SOUBOR=" + (new File(new URI(uriStránky)).getAbsolutePath()), // env:absolutní cesta k souboru + "XWG_STRANKA_NADPIS=" + nadpisStránky, // env:nadpis stránky + "XWG_STRANKA_PEREX=" + perexStránky // env:perex stránky }; + f.setExecutable(true); Runtime r = Runtime.getRuntime(); Process p = r.exec(new String[]{f.getAbsolutePath()}, prostředí); @@ -97,19 +103,15 @@ p.waitFor(); - /** - * TODO: podporovat zvláštní návratový kód, kterým skript řekne, - * že výstupem je XML a má se vložit jako fragment do dokumentu, - * ne jako prostý text. - */ if (p.exitValue() == 0) { if (chyby.length() > 0) { - System.err.println("--- Cyhbový výstup skriptu -----"); + System.err.println("--- Chybový výstup skriptu -----"); System.err.println(chyby); System.err.println("--------------------------------"); + System.err.println("Nicméně skript skončil úspěšně, takže pokračujeme dál."); } - return výsledek.trim(); + return připravVýstup(výsledek, výstupníFormát); } else { System.err.println("--- Standardní výstup skriptu: -----"); System.err.println(výsledek); @@ -128,4 +130,35 @@ return null; } } + + private static String připravVýstup(String výsledek, String formát) { + if ("xml".equals(formát)) { + if (zkontrolujXml(výsledek)) { + return výsledek.trim(); + } else { + System.err.println("Chyba v XML generovaném skriptem:"); + System.err.println(výsledek); + return null; + } + } else { + return výsledek.trim(); + } + } + + /** + * @param xml fragment XML vygenerovaný skriptem + * @return true v případě, že výstup je validním fragmentem XML + */ + private static boolean zkontrolujXml(String xml) { + try { + DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); + DocumentBuilder db = dbf.newDocumentBuilder(); + xml = "<xml>" + xml + "</xml>"; + Document d = db.parse(new ByteArrayInputStream(xml.getBytes())); + return true; + } catch (Exception e) { + e.printStackTrace(System.err); + return false; + } + } } diff -r 4b3ba32f613c -r eea9c4713045 šablona/makra/skriptování.xsl --- a/šablona/makra/skriptování.xsl Sat Jun 23 18:00:41 2012 +0200 +++ b/šablona/makra/skriptování.xsl Sat Jun 23 19:22:21 2012 +0200 @@ -30,6 +30,7 @@ Provedeme skript zadaný v těle elementu a jeho výstup vložíme do stránky. * @jazyk programovací jazyk, např. bash, perl, php + @výstup formát výstupu skriptu: text (výchozí) | xml (musí být validním fragmentem XML) @src skript uložený v souboru místo v těle elementu --> <xsl:template match="m:skript"> @@ -39,7 +40,28 @@ - nastavení z web.conf (zákaz nebo ignorace skriptů) - podpora vkládání fragmentů XML, ne jen prostého textu --> - <xsl:value-of select="j:interpretuj(text(), @jazyk, document-uri(/), //s:stránka/s:nadpis/text(), //s:stránka/s:perex/text())"/> + + <xsl:variable name="výstupSkriptu" select="j:interpretuj( + text(), + @jazyk, + @výstup, + document-uri(/), + //s:stránka/s:nadpis/text(), + //s:stránka/s:perex/text() + )"/> + <xsl:choose> + <xsl:when test="$výstupSkriptu"> + <xsl:choose> + <xsl:when test="@výstup = 'xml'"><xsl:value-of select="$výstupSkriptu" disable-output-escaping="yes"/></xsl:when> + <xsl:otherwise><xsl:value-of select="$výstupSkriptu"/></xsl:otherwise> + </xsl:choose> + </xsl:when> + <xsl:otherwise> + <xsl:message terminate="yes">Při interpretaci skriptu došlo k chybě.</xsl:message> + </xsl:otherwise> + </xsl:choose> + + </xsl:template> </xsl:stylesheet>