Esempio n. 1
0
 private void updateStack(ParserInput parserInput, Stack stack, String stackName) {
   if (stack.empty()) {
     parserInput.getTempParams().remove(stackName);
   } else {
     parserInput.getTempParams().put(stackName, stack);
   }
 }
Esempio n. 2
0
 private String linkHtml(
     ParserInput parserInput,
     ParserOutput parserOutput,
     int mode,
     String link,
     String text,
     String punctuation,
     boolean numberedCaption)
     throws ParserException {
   if (link.toLowerCase().startsWith("mailto://")) {
     // fix bad mailto syntax
     link = "mailto:" + link.substring("mailto://".length());
   }
   String caption = link;
   if (!StringUtils.isBlank(text)) {
     // pass a parameter via the parserInput to prevent nested links from being generated
     parserInput.getTempParams().put(HTML_LINK_CAPTION, true);
     caption = JFlexParserUtil.parseFragment(parserInput, parserOutput, text, mode);
     parserInput.getTempParams().remove(HTML_LINK_CAPTION);
   } else if (numberedCaption) {
     // set the caption of the form "[1]"
     int counter = 1;
     if (parserInput.getTempParams().get(HTML_LINK_CAPTION_COUNTER) != null) {
       counter = (Integer) parserInput.getTempParams().get(HTML_LINK_CAPTION_COUNTER);
     }
     parserInput.getTempParams().put(HTML_LINK_CAPTION_COUNTER, counter + 1);
     caption = "[" + counter + "]";
   }
   return LinkUtil.buildExternalLinkHtml(link, "externallink", caption) + punctuation;
 }
Esempio n. 3
0
 /**
  * Retrieve the content of a topic from the cache, or if it is not yet in the cache then add it to
  * the cache.
  *
  * @param context The servlet context for the topic being retrieved. May be <code>null</code> if
  *     the <code>cook</code> parameter is set to <code>false</code>.
  * @param locale The locale for the topic being retrieved. May be <code>null</code> if the <code>
  *     cook</code> parameter is set to <code>false</code>.
  * @param virtualWiki The virtual wiki for the topic being retrieved.
  * @param topicName The name of the topic being retrieved.
  * @param cook A parameter indicating whether or not the content should be parsed before it is
  *     added to the cache. Stylesheet content (CSS) is not parsed, but most other content is
  *     parsed.
  * @return The parsed or unparsed (depending on the <code>cook</code> parameter) topic content.
  */
 protected static String cachedContent(
     String context, Locale locale, String virtualWiki, String topicName, boolean cook) {
   String content = null;
   String key = WikiCache.key(virtualWiki, topicName);
   Element cacheElement = WikiCache.retrieveFromCache(WikiBase.CACHE_PARSED_TOPIC_CONTENT, key);
   if (cacheElement != null) {
     content = (String) cacheElement.getObjectValue();
     return (content == null) ? null : new String(content);
   }
   try {
     Topic topic = WikiBase.getDataHandler().lookupTopic(virtualWiki, topicName, false, null);
     content = topic.getTopicContent();
     if (cook) {
       ParserInput parserInput = new ParserInput();
       parserInput.setContext(context);
       parserInput.setLocale(locale);
       parserInput.setVirtualWiki(virtualWiki);
       parserInput.setTopicName(topicName);
       content = Utilities.parse(parserInput, null, content);
     }
     WikiCache.addToCache(WikiBase.CACHE_PARSED_TOPIC_CONTENT, key, content);
   } catch (Exception e) {
     logger.warning("error getting cached page " + virtualWiki + " / " + topicName, e);
     return null;
   }
   return content;
 }
  private static String getContent(final WikiPage wikiPage) {
    try {
      final ParserInput input = new ParserInput();
      input.setWikiUser(null);
      input.setAllowSectionEdit(false);
      input.setDepth(2);
      input.setContext("");
      input.setLocale(Locale.ENGLISH);
      input.setTopicName("dummy");
      input.setUserIpAddress("0.0.0.0");
      input.setDataHandler(DUMMY_DATA_HANDLER);
      input.setVirtualWiki("/olat");

      final AbstractParser parser = new JFlexParser(input);
      final ParserDocument parsedDoc = parser.parseHTML(wikiPage.getContent());
      final String parsedContent = parsedDoc.getContent();
      final String filteredContent =
          FilterFactory.getHtmlTagAndDescapingFilter().filter(parsedContent);
      return filteredContent;
    } catch (final Exception e) {
      e.printStackTrace();
      log.error("", e);
      return wikiPage.getContent();
    }
  }
Esempio n. 5
0
 private Stack retrieveStack(ParserInput parserInput, String stackName) {
   Stack stack = (Stack) parserInput.getTempParams().get(stackName);
   if (stack == null) {
     stack = new Stack();
     parserInput.getTempParams().put(stackName, stack);
   }
   return stack;
 }
Esempio n. 6
0
 private String updateToc(ParserInput parserInput, String name, String text, int level) {
   String output = "";
   if (parserInput.getTableOfContents().getStatus() == TableOfContents.STATUS_TOC_UNINITIALIZED) {
     output += "__TOC__";
   }
   parserInput.getTableOfContents().addEntry(name, text, level);
   return output;
 }
Esempio n. 7
0
 /**
  * During parsing the reference objects will be stored as a temporary array. This method parses
  * that array and returns the reference objects.
  *
  * @param parserInput The current ParserInput object for the topic that is being parsed.
  * @return A list of reference objects (never <code>null</code>) for the current topic that is
  *     being parsed.
  */
 protected static List<WikiReference> retrieveReferences(ParserInput parserInput) {
   List<WikiReference> references =
       (List<WikiReference>) parserInput.getTempParams().get(WikiReferenceTag.REFERENCES_PARAM);
   if (references == null) {
     references = new ArrayList<WikiReference>();
     parserInput.getTempParams().put(WikiReferenceTag.REFERENCES_PARAM, references);
   }
   return references;
 }
Esempio n. 8
0
  @Override
  public void appendInterWikiLink(String namespace, String title, String topicDescription) {
    String hrefLink = getInterwikiMap().get(namespace.toLowerCase());
    if (hrefLink != null) {
      String virtualWiki = fParserInput.getVirtualWiki();
      WikiLink wikiLink =
          LinkUtil.parseWikiLink(
              virtualWiki, namespace + Namespace.SEPARATOR + title + "|" + topicDescription);
      String destination = wikiLink.getDestination();
      destination =
          destination.substring(
              wikiLink.getNamespace().getLabel(virtualWiki).length()
                  + Namespace.SEPARATOR.length());
      hrefLink = hrefLink.replace("${title}", Utilities.encodeAndEscapeTopicName(title));
      TagNode aTagNode = new TagNode("a");
      aTagNode.addAttribute("href", hrefLink, true);
      aTagNode.addAttribute("class", "interwiki", false);

      pushNode(aTagNode);
      WikipediaParser.parseRecursive(topicDescription.trim(), this, false, true);
      popNode();

    } else {
      append(new ContentToken(topicDescription));
    }
  }
Esempio n. 9
0
 private String buildSectionEditLink(ParserInput parserInput, int section) throws ParserException {
   if (!parserInput.getAllowSectionEdit()) {
     return "";
   }
   if (parserInput.getLocale() == null) {
     logger.info(
         "Unable to build section edit links for "
             + parserInput.getTopicName()
             + " - locale is empty");
     return "";
   }
   // FIXME - template inclusion causes section edits to break, so disable for now
   Integer inclusion = (Integer) parserInput.getTempParam(TemplateTag.TEMPLATE_INCLUSION);
   boolean disallowInclusion = (inclusion != null && inclusion > 0);
   if (disallowInclusion) {
     return "";
   }
   String url = "";
   try {
     url =
         LinkUtil.buildEditLinkUrl(
             parserInput.getContext(),
             parserInput.getVirtualWiki(),
             parserInput.getTopicName(),
             null,
             section);
   } catch (DataAccessException e) {
     logger.error(
         "Failure while building link for topic "
             + parserInput.getVirtualWiki()
             + " / "
             + parserInput.getTopicName(),
         e);
   }
   // arguments are edit link URL and edit label text
   Object[] args = new Object[2];
   args[0] = url;
   args[1] = Utilities.formatMessage("common.sectionedit", parserInput.getLocale());
   try {
     return WikiUtil.formatFromTemplate(TEMPLATE_HEADER_EDIT_LINK, args);
   } catch (IOException e) {
     throw new ParserException(e);
   }
 }
Esempio n. 10
0
 @Override
 public boolean isTemplateTopic() {
   String topicName = fParserInput.getTopicName();
   int index = topicName.indexOf(':');
   if (index > 0) {
     String namespace = topicName.substring(0, index);
     if (isTemplateNamespace(namespace)) {
       return true;
     }
   }
   return false;
 }
Esempio n. 11
0
 /**
  * Parse a raw Wiki link of the form "[[link|text]]", and return a WikiLink object representing
  * the link.
  *
  * @param parserInput Input configuration settings for this parser instance.
  * @param raw The raw Wiki link text.
  * @return A WikiLink object that represents the link.
  */
 protected static WikiLink parseWikiLink(
     ParserInput parserInput, ParserOutput parserOutput, String raw) throws ParserException {
   if (StringUtils.isBlank(raw)) {
     return new WikiLink();
   }
   raw = raw.trim();
   String suffix = ((!raw.endsWith("]]")) ? raw.substring(raw.lastIndexOf("]]") + 2) : null);
   // for performance reasons use String methods rather than regex
   // private static final Pattern WIKI_LINK_PATTERN =
   // Pattern.compile("\\[\\[\\s*(\\:\\s*)?\\s*(.+?)(\\s*\\|\\s*(.+))?\\s*\\]\\]([a-z]*)");
   raw = raw.substring(raw.indexOf("[[") + 2, raw.lastIndexOf("]]")).trim();
   // parse in case there is a template or magic word - [[{{PAGENAME}}]]
   raw = JFlexParserUtil.parseFragment(parserInput, parserOutput, raw, JFlexParser.MODE_TEMPLATE);
   boolean colon = false;
   if (raw.startsWith(":")) {
     colon = true;
     raw = raw.substring(1).trim();
   }
   String text = null;
   int pos = raw.indexOf('|');
   if (pos != -1 && pos != (raw.length() - 1)) {
     text = raw.substring(pos + 1).trim();
     raw = raw.substring(0, pos).trim();
   }
   String virtualWiki = parserInput.getVirtualWiki();
   WikiLink wikiLink = LinkUtil.parseWikiLink(virtualWiki, raw);
   if (!colon && wikiLink.getNamespace().getId().equals(Namespace.CATEGORY_ID)) {
     // do not set default text for categories
     wikiLink.setText(null);
   }
   if (wikiLink.getVirtualWiki() != null
       && !StringUtils.equals(wikiLink.getVirtualWiki().getName(), virtualWiki)
       && StringUtils.isBlank(wikiLink.getDestination())) {
     // use the root topic name as the destination
     wikiLink.setDestination(wikiLink.getVirtualWiki().getRootTopicName());
     if (StringUtils.isBlank(wikiLink.getText())) {
       wikiLink.setText(wikiLink.getVirtualWiki().getName() + Namespace.SEPARATOR);
     }
   }
   if (wikiLink.getInterwiki() != null
       && StringUtils.isBlank(wikiLink.getDestination())
       && StringUtils.isBlank(wikiLink.getText())) {
     wikiLink.setText(wikiLink.getInterwiki().getInterwikiPrefix() + Namespace.SEPARATOR);
   }
   wikiLink.setColon(colon);
   if (text != null) {
     wikiLink.setText(text);
   }
   if (!StringUtils.isBlank(suffix)) {
     wikiLink.setText(wikiLink.getText() + suffix);
   }
   return wikiLink;
 }
Esempio n. 12
0
  @Override
  public void appendInternalLink(
      String topic,
      String hashSection,
      String topicDescription,
      String cssClass,
      boolean parseRecursive) {
    try {
      String virtualWiki = fParserInput.getVirtualWiki();
      WikiLink wikiLink;
      if (hashSection != null) {
        wikiLink = LinkUtil.parseWikiLink(virtualWiki, topic + "#" + hashSection);
      } else {
        wikiLink = LinkUtil.parseWikiLink(virtualWiki, topic);
      }
      String destination = wikiLink.getDestination();
      String section = wikiLink.getSection();
      String query = wikiLink.getQuery();
      String href = buildTopicUrlNoEdit(fContextPath, virtualWiki, destination, section, query);
      String style = "";
      if (StringUtils.isBlank(topic) && !StringUtils.isBlank(section)) {
        // do not check existence for section links
      } else {
        String articleName = topic.replace('_', ' ');
        if (LinkUtil.isExistingArticle(virtualWiki, articleName) == null) {
          style = "edit";
          href = LinkUtil.buildEditLinkUrl(fContextPath, virtualWiki, topic, query, -1);
        }
      }
      WPATag aTagNode = new WPATag();
      aTagNode.addAttribute("href", href, true);
      aTagNode.addAttribute("class", style, true);
      aTagNode.addObjectAttribute("wikilink", topic);

      pushNode(aTagNode);
      if (parseRecursive) {
        WikipediaParser.parseRecursive(topicDescription.trim(), this, false, true);
      } else {
        aTagNode.addChild(new ContentToken(topicDescription));
      }
      popNode();
    } catch (DataAccessException e1) {
      e1.printStackTrace();
      append(new ContentToken(topicDescription));
    }
  }
Esempio n. 13
0
 @Override
 public String getRawWikiContent(
     String namespace, String topicName, Map<String, String> templateParameters) {
   String result = super.getRawWikiContent(namespace, topicName, templateParameters);
   if (result != null) {
     return result;
   }
   try {
     topicName = topicName.replaceAll("_", " ");
     Topic topic =
         WikiBase.getDataHandler()
             .lookupTopic(fParserInput.getVirtualWiki(), namespace + ':' + topicName, false, null);
     if (topic == null) {
       return null;
     }
     return topic.getTopicContent();
   } catch (Exception e) {
     e.printStackTrace();
   }
   return result;
 }
Esempio n. 14
0
  @Override
  public void buildEditLinkUrl(int section) {
    if (fParserInput.getAllowSectionEdit()) {
      TagNode divTagNode = new TagNode("div");
      divTagNode.addAttribute("style", "font-size:90%;float:right;margin-left:5px;", false);
      divTagNode.addChild(new ContentToken("["));
      append(divTagNode);

      String url = "";
      try {
        // Use correct section number.
        // Bliki starts with offset 0 so it must be "section+1"
        url =
            LinkUtil.buildEditLinkUrl(
                fParserInput.getContext(),
                fParserInput.getVirtualWiki(),
                fParserInput.getTopicName(),
                null,
                section + 1);
      } catch (Exception e) {
        logger.error(
            "Failure while building link for topic "
                + fParserInput.getVirtualWiki()
                + " / "
                + fParserInput.getTopicName(),
            e);
      }
      TagNode aTagNode = new TagNode("a");
      aTagNode.addAttribute("href", url, false);
      aTagNode.addChild(
          new ContentToken(
              Utilities.formatMessage("common.sectionedit", fParserInput.getLocale())));
      divTagNode.addChild(aTagNode);
      divTagNode.addChild(new ContentToken("]"));
    }
  }
Esempio n. 15
0
 private void save(HttpServletRequest request, ModelAndView next, WikiPageInfo pageInfo)
     throws Exception {
   String topicName = JAMWikiServlet.getTopicFromRequest(request);
   String virtualWiki = JAMWikiServlet.getVirtualWikiFromURI(request);
   Topic topic = loadTopic(virtualWiki, topicName);
   TopicVersion lastTopicVersion =
       WikiBase.getHandler().lookupLastTopicVersion(virtualWiki, topicName);
   if (lastTopicVersion != null
       && lastTopicVersion.getTopicVersionId()
           != retrieveLastTopicVersionId(request, virtualWiki, topicName)) {
     // someone else has edited the topic more recently
     resolve(request, next, pageInfo);
     return;
   }
   String contents = request.getParameter("contents");
   if (StringUtils.hasText(request.getParameter("section"))) {
     // load section of topic
     int section = (new Integer(request.getParameter("section"))).intValue();
     ParserDocument parserDocument =
         Utilities.parseSplice(request, virtualWiki, topicName, section, contents);
     contents = parserDocument.getContent();
   }
   if (contents == null) {
     logger.warning("The topic " + topicName + " has no content");
     throw new WikiException(new WikiMessage("edit.exception.nocontent", topicName));
   }
   if (lastTopicVersion != null && lastTopicVersion.getVersionContent().equals(contents)) {
     viewTopic(request, next, pageInfo, topicName);
     return;
   }
   // parse for signatures and other syntax that should not be saved in raw form
   WikiUser user = Utilities.currentUser(request);
   ParserInput parserInput = new ParserInput();
   parserInput.setContext(request.getContextPath());
   parserInput.setLocale(request.getLocale());
   parserInput.setWikiUser(user);
   parserInput.setTopicName(topicName);
   parserInput.setUserIpAddress(request.getRemoteAddr());
   parserInput.setVirtualWiki(virtualWiki);
   ParserDocument parserDocument = Utilities.parseSave(parserInput, contents);
   contents = parserDocument.getContent();
   topic.setTopicContent(contents);
   if (StringUtils.hasText(parserDocument.getRedirect())) {
     // set up a redirect
     topic.setRedirectTo(parserDocument.getRedirect());
     topic.setTopicType(Topic.TYPE_REDIRECT);
   } else if (topic.getTopicType() == Topic.TYPE_REDIRECT) {
     // no longer a redirect
     topic.setRedirectTo(null);
     topic.setTopicType(Topic.TYPE_ARTICLE);
   }
   TopicVersion topicVersion =
       new TopicVersion(
           user, request.getRemoteAddr(), request.getParameter("editComment"), contents);
   if (request.getParameter("minorEdit") != null) {
     topicVersion.setEditType(TopicVersion.EDIT_MINOR);
   }
   WikiBase.getHandler().writeTopic(topic, topicVersion, parserDocument);
   // a save request has been made
   JAMWikiServlet.removeCachedContents();
   viewTopic(request, next, pageInfo, topicName);
 }
Esempio n. 16
0
 /** Functionality to handle the "Save" button being clicked. */
 private void save(HttpServletRequest request, ModelAndView next, WikiPageInfo pageInfo)
     throws Exception {
   String topicName = WikiUtil.getTopicFromRequest(request);
   String virtualWiki = pageInfo.getVirtualWikiName();
   Topic topic = loadTopic(virtualWiki, topicName);
   Topic lastTopic = WikiBase.getDataHandler().lookupTopic(virtualWiki, topicName, false, null);
   if (lastTopic != null
       && !lastTopic.getCurrentVersionId().equals(retrieveLastTopicVersionId(request, topic))) {
     // someone else has edited the topic more recently
     resolve(request, next, pageInfo);
     return;
   }
   String contents = request.getParameter("contents");
   String sectionName = "";
   if (!StringUtils.isBlank(request.getParameter("section"))) {
     // load section of topic
     int section = Integer.valueOf(request.getParameter("section"));
     ParserOutput parserOutput = new ParserOutput();
     String[] spliceResult =
         ParserUtil.parseSplice(
             parserOutput,
             request.getContextPath(),
             request.getLocale(),
             virtualWiki,
             topicName,
             section,
             contents);
     contents = spliceResult[1];
     sectionName = parserOutput.getSectionName();
   }
   if (contents == null) {
     logger.warning("The topic " + topicName + " has no content");
     throw new WikiException(new WikiMessage("edit.exception.nocontent", topicName));
   }
   // strip line feeds
   contents = StringUtils.remove(contents, '\r');
   String lastTopicContent =
       (lastTopic != null) ? StringUtils.remove(lastTopic.getTopicContent(), '\r') : "";
   if (lastTopic != null && StringUtils.equals(lastTopicContent, contents)) {
     // topic hasn't changed. redirect to prevent user from refreshing and re-submitting
     ServletUtil.redirect(next, virtualWiki, topic.getName());
     return;
   }
   String editComment = request.getParameter("editComment");
   if (handleSpam(request, next, topicName, contents, editComment)) {
     this.loadEdit(request, next, pageInfo, contents, virtualWiki, topicName, false);
     return;
   }
   // parse for signatures and other syntax that should not be saved in raw form
   WikiUser user = ServletUtil.currentWikiUser();
   ParserInput parserInput = new ParserInput();
   parserInput.setContext(request.getContextPath());
   parserInput.setLocale(request.getLocale());
   parserInput.setWikiUser(user);
   parserInput.setTopicName(topicName);
   parserInput.setUserDisplay(ServletUtil.getIpAddress(request));
   parserInput.setVirtualWiki(virtualWiki);
   ParserOutput parserOutput = ParserUtil.parseMetadata(parserInput, contents);
   // parse signatures and other values that need to be updated prior to saving
   contents = ParserUtil.parseMinimal(parserInput, contents);
   topic.setTopicContent(contents);
   if (!StringUtils.isBlank(parserOutput.getRedirect())) {
     // set up a redirect
     topic.setRedirectTo(parserOutput.getRedirect());
     topic.setTopicType(TopicType.REDIRECT);
   } else if (topic.getTopicType() == TopicType.REDIRECT) {
     // no longer a redirect
     topic.setRedirectTo(null);
     topic.setTopicType(TopicType.ARTICLE);
   }
   int charactersChanged = StringUtils.length(contents) - StringUtils.length(lastTopicContent);
   TopicVersion topicVersion =
       new TopicVersion(
           user, ServletUtil.getIpAddress(request), editComment, contents, charactersChanged);
   if (request.getParameter("minorEdit") != null) {
     topicVersion.setEditType(TopicVersion.EDIT_MINOR);
   }
   WikiBase.getDataHandler()
       .writeTopic(topic, topicVersion, parserOutput.getCategories(), parserOutput.getLinks());
   // update watchlist
   WikiUserDetailsImpl userDetails = ServletUtil.currentUserDetails();
   if (!userDetails.hasRole(Role.ROLE_ANONYMOUS)) {
     Watchlist watchlist = ServletUtil.currentWatchlist(request, virtualWiki);
     boolean watchTopic = (request.getParameter("watchTopic") != null);
     if (watchlist.containsTopic(topicName) != watchTopic) {
       WikiBase.getDataHandler()
           .writeWatchlistEntry(watchlist, virtualWiki, topicName, user.getUserId());
     }
   }
   // redirect to prevent user from refreshing and re-submitting
   String target = topic.getName();
   if (!StringUtils.isBlank(sectionName)) {
     target += "#" + sectionName;
   }
   ServletUtil.redirect(next, virtualWiki, target);
 }
Esempio n. 17
0
 /**
  * Utility method used when viewing a topic.
  *
  * @param request The current servlet request object.
  * @param next The current Spring ModelAndView object.
  * @param pageInfo The current WikiPageInfo object, which contains information needed for
  *     rendering the final JSP page.
  * @param pageTitle The title of the page being rendered.
  * @param topic The Topic object for the topic being displayed.
  * @param sectionEdit Set to <code>true</code> if edit links should be displayed for each section
  *     of the topic.
  * @throws Exception Thrown if any error occurs during processing.
  */
 protected static void viewTopic(
     HttpServletRequest request,
     ModelAndView next,
     WikiPageInfo pageInfo,
     WikiMessage pageTitle,
     Topic topic,
     boolean sectionEdit)
     throws Exception {
   // FIXME - what should the default be for topics that don't exist?
   if (topic == null) {
     throw new WikiException(new WikiMessage("common.exception.notopic"));
   }
   WikiUtil.validateTopicName(topic.getName());
   if (topic.getTopicType() == Topic.TYPE_REDIRECT
       && (request.getParameter("redirect") == null
           || !request.getParameter("redirect").equalsIgnoreCase("no"))) {
     Topic child = Utilities.findRedirectedTopic(topic, 0);
     if (!child.getName().equals(topic.getName())) {
       pageInfo.setRedirectName(topic.getName());
       pageTitle = new WikiMessage("topic.title", child.getName());
       topic = child;
     }
   }
   String virtualWiki = topic.getVirtualWiki();
   String topicName = topic.getName();
   WikiUser user = Utilities.currentUser();
   if (sectionEdit && !ServletUtil.isEditable(virtualWiki, topicName, user)) {
     sectionEdit = false;
   }
   ParserInput parserInput = new ParserInput();
   parserInput.setContext(request.getContextPath());
   parserInput.setLocale(request.getLocale());
   parserInput.setWikiUser(user);
   parserInput.setTopicName(topicName);
   parserInput.setUserIpAddress(request.getRemoteAddr());
   parserInput.setVirtualWiki(virtualWiki);
   parserInput.setAllowSectionEdit(sectionEdit);
   ParserDocument parserDocument = new ParserDocument();
   String content = Utilities.parse(parserInput, parserDocument, topic.getTopicContent());
   // FIXME - the null check should be unnecessary
   if (parserDocument != null && parserDocument.getCategories().size() > 0) {
     LinkedHashMap categories = new LinkedHashMap();
     for (Iterator iterator = parserDocument.getCategories().keySet().iterator();
         iterator.hasNext(); ) {
       String key = (String) iterator.next();
       String value =
           key.substring(
               NamespaceHandler.NAMESPACE_CATEGORY.length()
                   + NamespaceHandler.NAMESPACE_SEPARATOR.length());
       categories.put(key, value);
     }
     next.addObject("categories", categories);
   }
   topic.setTopicContent(content);
   if (topic.getTopicType() == Topic.TYPE_CATEGORY) {
     loadCategoryContent(next, virtualWiki, topic.getName());
   }
   if (topic.getTopicType() == Topic.TYPE_IMAGE || topic.getTopicType() == Topic.TYPE_FILE) {
     Collection fileVersions =
         WikiBase.getDataHandler().getAllWikiFileVersions(virtualWiki, topicName, true);
     for (Iterator iterator = fileVersions.iterator(); iterator.hasNext(); ) {
       // update version urls to include web root path
       WikiFileVersion fileVersion = (WikiFileVersion) iterator.next();
       String url =
           FilenameUtils.normalize(
               Environment.getValue(Environment.PROP_FILE_DIR_RELATIVE_PATH)
                   + "/"
                   + fileVersion.getUrl());
       url = FilenameUtils.separatorsToUnix(url);
       fileVersion.setUrl(url);
     }
     next.addObject("fileVersions", fileVersions);
     if (topic.getTopicType() == Topic.TYPE_IMAGE) {
       next.addObject("topicImage", new Boolean(true));
     } else {
       next.addObject("topicFile", new Boolean(true));
     }
   }
   pageInfo.setSpecial(false);
   pageInfo.setTopicName(topicName);
   next.addObject(ServletUtil.PARAMETER_TOPIC_OBJECT, topic);
   if (pageTitle != null) {
     pageInfo.setPageTitle(pageTitle);
   }
 }