001// License: GPL. For details, see LICENSE file.
002package org.openstreetmap.josm.tools;
003
004import java.io.BufferedReader;
005import java.io.IOException;
006import java.net.URL;
007
008import org.openstreetmap.josm.Main;
009import org.openstreetmap.josm.tools.LanguageInfo.LocaleType;
010
011/**
012 * Read a trac-wiki page.
013 *
014 * @author imi
015 */
016public class WikiReader {
017
018    private final String baseurl;
019
020    /**
021     * Constructs a new {@code WikiReader} for the given base URL.
022     * @param baseurl The wiki base URL
023     */
024    public WikiReader(String baseurl) {
025        this.baseurl = baseurl;
026    }
027
028    /**
029     * Constructs a new {@code WikiReader}.
030     */
031    public WikiReader() {
032        this.baseurl = Main.pref.get("help.baseurl", Main.getJOSMWebsite());
033    }
034
035    /**
036     * Read the page specified by the url and return the content.
037     *
038     * If the url is within the baseurl path, parse it as an trac wikipage and replace relative
039     * pathes etc..
040     *
041     * @throws IOException Throws, if the page could not be loaded.
042     */
043    public String read(String url) throws IOException {
044        URL u = new URL(url);
045        try (BufferedReader in = Utils.openURLReader(u)) {
046            if (url.startsWith(baseurl) && !url.endsWith("?format=txt"))
047                return readFromTrac(in, u);
048            return readNormal(in);
049        }
050    }
051
052    public String readLang(String text) throws IOException {
053        String languageCode;
054        String res = "";
055
056        languageCode = LanguageInfo.getWikiLanguagePrefix(LocaleType.DEFAULTNOTENGLISH);
057        if(languageCode != null) {
058            res = readLang(new URL(baseurl + "/wiki/" + languageCode + text));
059        }
060
061        if(res.isEmpty()) {
062            languageCode = LanguageInfo.getWikiLanguagePrefix(LocaleType.BASELANGUAGE);
063            if(languageCode != null) {
064                res = readLang(new URL(baseurl + "/wiki/" + languageCode + text));
065            }
066        }
067
068        if(res.isEmpty()) {
069            languageCode = LanguageInfo.getWikiLanguagePrefix(LocaleType.ENGLISH);
070            if(languageCode != null) {
071                res = readLang(new URL(baseurl + "/wiki/" + languageCode + text));
072            }
073        }
074
075        if(res.isEmpty()) {
076            throw new IOException(text + " does not exist");
077        } else {
078            return res;
079        }
080    }
081
082    private String readLang(URL url) throws IOException {
083        try (BufferedReader in = Utils.openURLReader(url)) {
084            return readFromTrac(in, url);
085        } catch (IOException e) {
086            Main.addNetworkError(url, Utils.getRootCause(e));
087            throw e;
088        }
089    }
090
091    private String readNormal(BufferedReader in) throws IOException {
092        StringBuilder b = new StringBuilder();
093        for (String line = in.readLine(); line != null; line = in.readLine()) {
094            if (!line.contains("[[TranslatedPages]]")) {
095                b.append(line.replaceAll(" />", ">")).append("\n");
096            }
097        }
098        return "<html>" + b + "</html>";
099    }
100
101    protected String readFromTrac(BufferedReader in, URL url) throws IOException {
102        boolean inside = false;
103        boolean transl = false;
104        boolean skip = false;
105        String b = "";
106        String full = "";
107        for (String line = in.readLine(); line != null; line = in.readLine()) {
108            full += line;
109            if (line.contains("<div id=\"searchable\">")) {
110                inside = true;
111            } else if (line.contains("<div class=\"wiki-toc trac-nav\"")) {
112                transl = true;
113            } else if (line.contains("<div class=\"wikipage searchable\">")) {
114                inside = true;
115            } else if (line.contains("<div class=\"buttons\">")) {
116                inside = false;
117            } else if (line.contains("<h3>Attachments</h3>")) {
118                inside = false;
119            } else if (line.contains("<div id=\"attachments\">")) {
120                inside = false;
121            } else if (line.contains("<div class=\"trac-modifiedby\">")) {
122                skip = true;
123            }
124            if (inside && !transl && !skip) {
125                // add a border="0" attribute to images, otherwise the internal help browser
126                // will render a thick  border around images inside an <a> element
127                b += line.replaceAll("<img ", "<img border=\"0\" ")
128                         .replaceAll("<span class=\"icon\">.</span>", "")
129                         .replaceAll("href=\"/", "href=\"" + baseurl + "/")
130                         .replaceAll(" />", ">")
131                         + "\n";
132            } else if (transl && line.contains("</div>")) {
133                transl = false;
134            }
135            if (line.contains("</div>")) {
136                skip = false;
137            }
138        }
139        if (b.indexOf("      Describe ") >= 0
140        || b.indexOf(" does not exist. You can create it here.</p>") >= 0)
141            return "";
142        if(b.isEmpty())
143            b = full;
144        return "<html><base href=\""+url.toExternalForm() +"\"> " + b + "</html>";
145    }
146}