예제 #1
0
  /**
   * Generates a drop-down combobox for a true/false option suitable for adding to an existing form.
   * Its first element is the "select" element, so any Javascript attributes can be added to the
   * output.
   *
   * @param value The current value of the option. This will be selected.
   * @param fullName The full name of the option, used to name the drop-down.
   * @param disabled Whether the drop-down should be disabled.
   * @return An HTMLNode of a "select" with an "option" child for localized "true" and "false", with
   *     the current value selected.
   */
  public static HTMLNode addBooleanComboBox(boolean value, String fullName, boolean disabled) {
    HTMLNode result;

    if (disabled) {
      result =
          new HTMLNode(
              "select", //
              new String[] {"name", "disabled"}, //
              new String[] {fullName, "disabled"});
    } else {
      result = new HTMLNode("select", "name", fullName);
    }

    if (value) {
      result.addChild(
          "option",
          new String[] {"value", "selected"},
          new String[] {"true", "selected"},
          l10n("true"));
      result.addChild("option", "value", "false", l10n("false"));
    } else {
      result.addChild("option", "value", "true", l10n("true"));
      result.addChild(
          "option",
          new String[] {"value", "selected"},
          new String[] {"false", "selected"},
          l10n("false"));
    }

    return result;
  }
예제 #2
0
  /**
   * Generates a drop-down combobox for the given enumerable option suitable for adding to an
   * existing form. Its first element is the "select" element, so any Javascript attributes can be
   * added to the output.
   *
   * @param value The currently applied value of the option.
   * @param o The option, used to list all values.
   * @param fullName The full name of the option, used to name the drop-down.
   * @param disabled Whether the drop-down should be disabled.
   * @return An HTMLNode of a "select" with "option" children for each of the possible values. If
   *     the value specified in value is one of the options, it will be selected.
   */
  public static HTMLNode addComboBox(
      String value, EnumerableOptionCallback o, String fullName, boolean disabled) {
    HTMLNode result;

    if (disabled) {
      result =
          new HTMLNode(
              "select", //
              new String[] {"name", "disabled"}, //
              new String[] {fullName, "disabled"});
    } else {
      result = new HTMLNode("select", "name", fullName);
    }

    for (String possibleValue : o.getPossibleValues()) {
      if (possibleValue.equals(value)) {
        result.addChild(
            "option",
            new String[] {"value", "selected"},
            new String[] {possibleValue, "selected"},
            possibleValue);
      } else {
        result.addChild("option", "value", possibleValue, possibleValue);
      }
    }

    return result;
  }
예제 #3
0
  @Override
  public HTMLNode getHTMLText() {
    HTMLNode alertNode = new HTMLNode("div");
    alertNode.addChild(
        "p",
        l10n(
            "header",
            new String[] {"from", "composed", "sent", "received"},
            new String[] {
              sourceNodeName,
              DateFormat.getInstance().format(new Date(composedTime)),
              DateFormat.getInstance().format(new Date(sentTime)),
              DateFormat.getInstance().format(new Date(receivedTime))
            }));
    String[] lines = messageText.split("\n");
    for (int i = 0, c = lines.length; i < c; i++) {
      alertNode.addChild("#", lines[i]);
      if (i != lines.length - 1) alertNode.addChild("br");
    }

    DarknetPeerNode pn = (DarknetPeerNode) peerRef.get();
    if (pn != null)
      alertNode
          .addChild("p")
          .addChild("a", "href", "/send_n2ntm/?peernode_hashcode=" + pn.hashCode(), l10n("reply"));
    return alertNode;
  }
예제 #4
0
  public void make() {
    if (request.isPartSet("confirm")) {
      wot.deleteIdentity(mIdentity);

      /* TODO: Show the OwnIdentities page instead! Use the trick which Freetalk does for inlining pages */
      HTMLNode box =
          addContentBox(l10n().getString("DeleteOwnIdentityPage.IdentityDeleted.Header"));
      box.addChild("#", l10n().getString("DeleteOwnIdentityPage.IdentityDeleted.Text"));
    } else makeConfirmation();
  }
예제 #5
0
    @Override
    public HTMLNode getHTMLText() {
      HTMLNode alertNode = new HTMLNode("div");
      alertNode.addChild("#", l10n("needRestart"));

      if (node.isUsingWrapper()) {
        alertNode.addChild("br");
        HTMLNode restartForm =
            alertNode
                .addChild(
                    "form",
                    new String[] {"action", "method", "enctype", "id", "accept-charset"},
                    new String[] {"/", "post", "multipart/form-data", "restartForm", "utf-8"})
                .addChild("div");
        restartForm.addChild(
            "input",
            new String[] {"type", "name", "value"},
            new String[] {"hidden", "formPassword", formPassword});
        restartForm.addChild("div");
        restartForm.addChild(
            "input", //
            new String[] {"type", "name"}, //
            new String[] {"hidden", "restart"});
        restartForm.addChild(
            "input", //
            new String[] {"type", "name", "value"}, //
            new String[] {"submit", "restart2", l10n("restartNode")});
      }

      return alertNode;
    }
 private HTMLNode getSetTrustCell(Identity trustee) {
   HTMLNode cell = new HTMLNode("td");
   // There can be multiple checkboxes with the same name in HTML, however Fred does not support
   // it...
   cell.addChild(
       new HTMLNode(
           "input",
           new String[] {"type", "name", "value"},
           new String[] {"checkbox", "SetTrustOf" + trustee.getID(), trustee.getID()}));
   return cell;
 }
  /** Makes a form where the user can enter the requestURI of an Identity he knows. */
  private void makeAddIdentityForm() {

    // TODO Add trust value and comment fields and make them mandatory
    // The user should only add an identity he trusts
    HTMLNode addBoxContent =
        addContentBox(l10n().getString("KnownIdentitiesPage.AddIdentity.Header"));

    HTMLNode createForm = pr.addFormChild(addBoxContent, uri.toString(), "AddIdentity");

    createForm.addChild(
        "span",
        new String[] {"title", "style"},
        new String[] {
          l10n().getString("KnownIdentitiesPage.AddIdentity.IdentityURI.Tooltip"),
          "border-bottom: 1px dotted; cursor: help;"
        },
        l10n().getString("KnownIdentitiesPage.AddIdentity.IdentityURI") + ": ");

    createForm.addChild(
        "input", new String[] {"type", "name", "size"}, new String[] {"text", "IdentityURI", "70"});
    createForm.addChild("br");

    createForm.addChild(
        "input",
        new String[] {"type", "name", "value"},
        new String[] {"hidden", "SetTrust", "true"});
    createForm.addChild(
        "input",
        new String[] {"type", "name", "value"},
        new String[] {"hidden", "SetTrustOf", "void"});

    createForm
        .addChild("span", l10n().getString("KnownIdentitiesPage.AddIdentity.Trust") + ": ")
        .addChild(
            "input",
            new String[] {"type", "name", "size", "value"},
            new String[] {"text", "Value", "4", ""});

    createForm
        .addChild("span", " " + l10n().getString("KnownIdentitiesPage.AddIdentity.Comment") + ": ")
        .addChild(
            "input",
            new String[] {"type", "name", "size", "value"},
            new String[] {"text", "Comment", "20", ""});

    createForm.addChild("br");

    createForm.addChild(
        "input",
        new String[] {"type", "name", "value"},
        new String[] {
          "submit", "AddIdentity", l10n().getString("KnownIdentitiesPage.AddIdentity.AddButton")
        });
  }
예제 #8
0
  private HTMLNode addMessageBank(HTMLNode parent, MessageBank messageBank, String folderName) {
    // First add this message bank
    HTMLNode folderDiv = parent.addChild("div", "class", "folder");
    HTMLNode folderPara = folderDiv.addChild("p");
    folderPara.addChild("a", "href", InboxToadlet.getFolderPath(folderName), messageBank.getName());

    // Then add all the children recursively
    for (MessageBank child : messageBank.listSubFolders()) {
      addMessageBank(folderDiv, child, folderName + "." + child.getName());
    }

    return folderDiv;
  }
  public void make() throws RedirectException {
    if (mOwnIdentity == null) {
      throw new RedirectException(logIn);
    }

    makeBreadcrumbs();

    boolean subscribe = mRequest.isPartSet("Subscribe");
    boolean unsubscribe = mRequest.isPartSet("Unsubscribe");

    if ((subscribe ^ unsubscribe) && mRequest.getMethod().equals("POST")) {
      String boardName =
          mRequest.getPartAsStringFailsafe("BoardName", Board.MAX_BOARDNAME_TEXT_LENGTH);

      try {
        MessageManager messageManager = mFreetalk.getMessageManager();

        if (subscribe) {
          SubscribedBoard board = messageManager.subscribeToBoard(mOwnIdentity, boardName);

          HTMLNode successBox =
              addContentBox(l10n().getString("SelectBoardsPage.SubscriptionSucceededBox.Header"));
          l10n()
              .addL10nSubstitution(
                  successBox.addChild("div"),
                  "SelectBoardsPage.SubscriptionSucceededBox.Text",
                  new String[] {"link", "boardname"},
                  new HTMLNode[] {
                    HTMLNode.link(BoardPage.getURI(board)), HTMLNode.text(board.getName())
                  });
        } else if (unsubscribe) {
          messageManager.unsubscribeFromBoard(mOwnIdentity, boardName);

          HTMLNode successBox =
              addContentBox(l10n().getString("SelectBoardsPage.UnsubscriptionSucceededBox.Header"));
          l10n()
              .addL10nSubstitution(
                  successBox.addChild("div"),
                  "SelectBoardsPage.UnsubscriptionSucceededBox.Text",
                  new String[] {"boardname"},
                  new HTMLNode[] {HTMLNode.text(boardName)});
        }
      } catch (Exception e) {
        HTMLNode alertBox =
            addAlertBox(
                subscribe
                    ? l10n().getString("SelectBoardsPage.SubscribeFailed")
                    : l10n().getString("SelectBoardsPage.UnsubscribeFailed"));
        alertBox.addChild("div", e.getMessage());

        Logger.error(this, subscribe ? "subscribe failed" : "unsubscribe failed", e);
      }
    }

    makeBoardsList();
  }
예제 #10
0
  @Override
  HTTPResponse makeWebPageGet(URI uri, HTTPRequest req, ToadletContext ctx, PageNode page) {
    HTMLNode pageNode = page.outer;
    HTMLNode contentNode = page.content;

    HTMLNode container = contentNode.addChild("div", "class", "container");

    // Add the list of folders
    HTMLNode folderList = container.addChild("div", "class", "folderlist");

    String identity = loginManager.getSession(ctx).getUserID();
    FreemailAccount account = accountManager.getAccount(identity);
    MessageBank topLevelMessageBank = account.getMessageBank();
    addMessageBank(folderList, topLevelMessageBank, "inbox");

    // Add the message
    String folderName = req.getParam("folder", "inbox");
    MessageBank messageBank = MessageBankTools.getMessageBank(account, folderName);

    int messageUid;
    try {
      messageUid = Integer.parseInt(req.getParam("uid"));
    } catch (NumberFormatException e) {
      Logger.error(this, "Got invalid uid: " + req.getParam("uid"));
      messageUid = 0;
    }
    MailMessage msg = MessageBankTools.getMessage(messageBank, messageUid);

    if (msg == null) {
      /* FIXME: L10n */
      HTMLNode infobox = addErrorbox(container, "Message doesn't exist");
      infobox.addChild("p", "The message you requested doesn't exist");
      return new GenericHTMLResponse(ctx, 200, "OK", pageNode.generate());
    }

    HTMLNode messageNode = container.addChild("div", "class", "message");

    addMessageButtons(ctx, messageNode, folderName, messageUid);
    addMessageHeaders(messageNode, msg);
    addMessageContents(messageNode, msg);

    // Mark message as read
    if (!msg.flags.get("\\seen")) {
      msg.flags.set("\\seen", true);
      msg.storeFlags();
    }

    return new GenericHTMLResponse(ctx, 200, "OK", pageNode.generate());
  }
예제 #11
0
  private void addMessageContents(HTMLNode messageNode, MailMessage message) {
    HTMLNode messageContents =
        messageNode.addChild("div", "class", "message-content").addChild("p");

    try {
      BufferedReader body = message.getBodyReader();
      try {
        String line = body.readLine();
        boolean added = false;
        while (line != null) {
          if (added) messageContents.addChild("br");
          messageContents.addChild("#", line);
          added = true;
          line = body.readLine();
        }
      } finally {
        body.close();
      }
    } catch (IOException e) {
      // TODO: Better error message
      messageContents.removeChildren();
      HTMLNode errorBox = addErrorbox(messageContents, "Couldn't read message");
      errorBox.addChild("p", "Couldn't read the message: " + e);
      return;
    }
  }
예제 #12
0
  private void makeConfirmation() {
    HTMLNode box =
        addContentBox(l10n().getString("DeleteOwnIdentityPage.DeleteIdentityBox.Header"));

    box.addChild(
        new HTMLNode(
            "p",
            l10n()
                .getString(
                    "DeleteOwnIdentityPage.DeleteIdentityBox.Text1",
                    "nickname",
                    mIdentity.getNickname())));
    box.addChild(
        new HTMLNode("p", l10n().getString("DeleteOwnIdentityPage.DeleteIdentityBox.Text2")));

    HTMLNode confirmForm = pr.addFormChild(box, uri, "DeleteIdentity");

    confirmForm.addChild(
        "input",
        new String[] {"type", "name", "value"},
        new String[] {"hidden", "page", "DeleteIdentity"});
    confirmForm.addChild(
        "input",
        new String[] {"type", "name", "value"},
        new String[] {"hidden", "id", mIdentity.getID()});
    confirmForm.addChild(
        "input",
        new String[] {"type", "name", "value"},
        new String[] {
          "submit",
          "confirm",
          l10n().getString("DeleteOwnIdentityPage.DeleteIdentityBox.ConfirmButton")
        });
  }
  /**
   * Returns an {@link HTMLNode} representation of a {@link TermPageEntry} for display in a browser
   *
   * @param entry
   * @param newestVersion if set, the result is shown in full brightness, if unset the result is
   *     greyed out
   */
  private HTMLNode termPageEntryNode(TermPageEntry entry, boolean newestVersion) {
    FreenetURI uri = entry.page;
    String showtitle = entry.title;
    String showurl = uri.toShortString();
    if (showtitle == null || showtitle.trim().length() == 0) {
      showtitle = showurl;
    }
    String realurl = "/" + uri.toString();
    HTMLNode pageNode =
        new HTMLNode("div", new String[] {"class", "style"}, new String[] {"result-entry", ""});
    pageNode.addChild(
        "a",
        new String[] {"href", "class", "title"},
        new String[] {
          realurl,
          (newestVersion ? "result-title-new" : "result-title-old"),
          (entry.rel > 0) ? "Relevance : " + (entry.rel * 100) + "%" : "Relevance unknown"
        },
        showtitle);
    // create usk url
    if (uri.isSSKForUSK()) {
      String realuskurl = "/" + uri.uskForSSK().toString();
      pageNode.addChild(
          "a",
          new String[] {"href", "class", "title"},
          new String[] {
            realuskurl,
            (newestVersion ? "result-uskbutton-new" : "result-uskbutton-old"),
            realuskurl
          },
          "[ USK ]");
    }
    pageNode.addChild("br");
    pageNode.addChild(
        "a",
        new String[] {"href", "class", "title"},
        new String[] {
          realurl, (newestVersion ? "result-url-new" : "result-url-old"), uri.toString()
        },
        showurl);

    return pageNode;
  }
  private HTMLNode getReceivedTrustCell(OwnIdentity truster, Identity trustee)
      throws DuplicateTrustException {

    String trustValue = "";
    String trustComment = "";
    Trust trust;

    try {
      trust = mWebOfTrust.getTrust(truster, trustee);
      trustValue = String.valueOf(trust.getValue());
      trustComment = trust.getComment();
    } catch (NotTrustedException e) {
    }

    HTMLNode cell = new HTMLNode("td");
    if (trustValue.length() > 0) {
      cell.addAttribute(
          "style",
          "background-color:"
              + KnownIdentitiesPage.getTrustColor(Integer.parseInt(trustValue))
              + ";");
    }

    // Trust value input field
    cell.addChild(
        "input",
        new String[] {"type", "name", "size", "maxlength", "value"},
        new String[] {"text", "Value" + trustee.getID(), "4", "4", trustValue});

    // Trust comment input field
    cell.addChild(
        "input",
        new String[] {"type", "name", "size", "maxlength", "value"},
        new String[] {
          "text",
          "Comment" + trustee.getID(),
          "50",
          Integer.toString(Trust.MAX_TRUST_COMMENT_LENGTH),
          trustComment
        });

    return cell;
  }
  @Override
  public HTMLNode getHTMLText() {

    UpdateThingy ut = createUpdateThingy();

    HTMLNode alertNode = new HTMLNode("div");

    alertNode.addChild("#", ut.firstBit);

    if (ut.formText != null) {
      alertNode
          .addChild("form", new String[] {"action", "method"}, new String[] {"/", "post"})
          .addChild(
              "input",
              new String[] {"type", "name", "value"},
              new String[] {"submit", "update", ut.formText});
    }

    return alertNode;
  }
예제 #16
0
  private void addMessageButtons(ToadletContext ctx, HTMLNode parent, String folderName, int uid) {
    HTMLNode buttonBox = parent.addChild("div", "class", "message-buttons");

    // Add reply button
    HTMLNode replyForm = ctx.addFormChild(buttonBox, NewMessageToadlet.getPath(), "reply");
    replyForm.addChild(
        "input",
        new String[] {"type", "name", "value"},
        new String[] {"hidden", "folder", folderName});
    replyForm.addChild(
        "input",
        new String[] {"type", "name", "value"},
        new String[] {"hidden", "message", "" + uid});

    String replyText = FreemailL10n.getString("Freemail.MessageToadlet.reply");
    replyForm.addChild(
        "input",
        new String[] {"type", "name", "value"},
        new String[] {"submit", "reply", replyText});
  }
예제 #17
0
  public void handleMethodGET(URI uri, HTTPRequest request, ToadletContext ctx)
      throws ToadletContextClosedException, IOException {

    PageNode page = ctx.getPageMaker().getPageNode("Redirect to Decoded link", ctx);
    HTMLNode pageNode = page.outer;
    HTMLNode contentNode = page.content;

    if (ctx.isAllowedFullAccess()) contentNode.addChild(ctx.getAlertManager().createSummary());

    final String requestPath = request.getPath().substring(path().length());

    // Without this it'll try to look in the current directory which will be /decode and won't work.
    String keyToFetch = "/" + requestPath;

    // This is for when a browser can't handle 301s, should very rarely (never?) be seen.
    ctx.getPageMaker()
        .getInfobox("infobox-warning", "Decode Link", contentNode, "decode-not-redirected", true)
        .addChild("a", "href", keyToFetch, "Click Here to be re-directed");

    this.writeHTMLReply(
        ctx, 301, "Moved Permanently\nLocation: " + keyToFetch, pageNode.generate());
  }
 @Override
 public HTMLNode getHTMLText() {
   HTMLNode alertNode = new HTMLNode("div");
   alertNode.addChild("a", "href", "/" + uri).addChild("#", uri.toShortString());
   if (description != null && description.length() != 0) {
     String[] lines = description.split("\n");
     alertNode.addChild("br");
     alertNode.addChild("br");
     alertNode.addChild("#", l10n("fileDescription"));
     alertNode.addChild("br");
     for (int i = 0; i < lines.length; i++) {
       alertNode.addChild("#", lines[i]);
       if (i != lines.length - 1) alertNode.addChild("br");
     }
   }
   return alertNode;
 }
예제 #19
0
  public void handleMethodGET(URI uri, HTTPRequest req, ToadletContext ctx)
      throws ToadletContextClosedException, IOException, RedirectException {
    // If we don't disconnect we will have pipelining issues
    ctx.forceDisconnect();

    String path = uri.getPath();
    if (path.startsWith(StaticToadlet.ROOT_URL) && staticToadlet != null)
      staticToadlet.handleMethodGET(uri, req, ctx);
    else {
      String desc = NodeL10n.getBase().getString("StartupToadlet.title");
      PageNode page = ctx.getPageMaker().getPageNode(desc, false, ctx);
      HTMLNode pageNode = page.outer;
      HTMLNode headNode = page.headNode;
      headNode.addChild(
          "meta", new String[] {"http-equiv", "content"}, new String[] {"refresh", "20; url="});
      HTMLNode contentNode = page.content;

      if (!isPRNGReady) {
        HTMLNode prngInfoboxContent =
            ctx.getPageMaker()
                .getInfobox(
                    "infobox-error",
                    NodeL10n.getBase().getString("StartupToadlet.entropyErrorTitle"),
                    contentNode,
                    null,
                    true);
        prngInfoboxContent.addChild(
            "#", NodeL10n.getBase().getString("StartupToadlet.entropyErrorContent"));
      }

      HTMLNode infoboxContent =
          ctx.getPageMaker().getInfobox("infobox-error", desc, contentNode, null, true);
      infoboxContent.addChild("#", NodeL10n.getBase().getString("StartupToadlet.isStartingUp"));

      WelcomeToadlet.maybeDisplayWrapperLogfile(ctx, contentNode);

      // TODO: send a Retry-After header ?
      writeHTMLReply(ctx, 503, desc, pageNode.generate());
    }
  }
  /**
   * Gets a list of links to the pages of the known identities list. Will look like this: 1 to 5...
   * currentPage-5 to currentPage+5 ... lastPage-5 to lastPage
   *
   * @param currentPage The currently displayed page, counting from 0.
   * @param identityCount Total amount of identities in the result set. This is used to compute the
   *     page count. TODO: Optimization: When using lazy database query evaluation, the amount of
   *     identities will not be computed until we have processed the whole database query. So the
   *     computation of this parameter is expensive then and we should get rid of it. The link to
   *     the last page should be "Last" instead of a numeric label then. Bugtracker entry:
   *     https://bugs.freenetproject.org/view.php?id=6245
   */
  private HTMLNode getKnownIdentitiesListPageLinks(final int currentPage, final int identityCount) {
    final int pageCount = getPageCount(identityCount);
    final int lastPage = pageCount - 1;

    HTMLNode div = new HTMLNode("div");

    if (pageCount == 1) return div;

    int lastDisplayedLink = -1;

    // Display links to first 5 pages excluding the current page.
    for (int i = 0; i < currentPage; ) {
      div.addChild(getSingleKnownIdentitiesListPageLink(currentPage, i));
      lastDisplayedLink = i;

      ++i;

      if (i >= 5) { // Display 5 links at most
        if (i
            < currentPage
                - 5) // The next loop displays links starting from currentPage-5. If our next link
          // wouldn't fall into that range, add dots.
          div.addChild("#", "...");
        break;
      }
    }

    // Display 5 links before and after current page, excluding last page.
    for (int i = Math.max(currentPage - 5, lastDisplayedLink + 1); i < lastPage; ) {
      div.addChild(getSingleKnownIdentitiesListPageLink(currentPage, i));
      lastDisplayedLink = i;

      ++i;

      if (i > currentPage + 5) {
        if (i != lastPage) // If the next link would not have been the lastPage, add "..." for the
          // missing pages in between
          div.addChild("#", "...");
        break;
      }
    }

    // Display last page
    if (lastDisplayedLink != lastPage)
      div.addChild(getSingleKnownIdentitiesListPageLink(currentPage, lastPage));

    return div;
  }
예제 #21
0
  private HTMLNode createUriBox(
      PluginContext pCtx,
      String uri,
      int hexWidth,
      boolean automf,
      boolean deep,
      List<String> errors) {
    InfoboxNode box = pCtx.pageMaker.getInfobox("Explore a freenet key");
    HTMLNode browseBox = box.outer;
    HTMLNode browseContent = box.content;

    if (hexWidth < 1 || hexWidth > 1024) {
      errors.add("Hex display columns out of range. (1-1024). Set to 32 (default).");
      hexWidth = 32;
    }
    browseContent.addChild(
        "#", "Display the top level chunk as hexprint or list the content of a manifest");
    HTMLNode browseForm = pCtx.pluginRespirator.addFormChild(browseContent, path(), "uriForm");
    browseForm.addChild("#", "Freenetkey to explore: \u00a0 ");
    if (uri != null)
      browseForm.addChild(
          "input",
          new String[] {"type", "name", "size", "value"},
          new String[] {"text", Globals.PARAM_URI, "70", uri});
    else
      browseForm.addChild(
          "input",
          new String[] {"type", "name", "size"},
          new String[] {"text", Globals.PARAM_URI, "70"});
    browseForm.addChild("#", "\u00a0");
    browseForm.addChild(
        "input",
        new String[] {"type", "name", "value"},
        new String[] {"submit", "debug", "Explore!"});
    browseForm.addChild("br");
    if (automf)
      browseForm.addChild(
          "input",
          new String[] {"type", "name", "value", "checked"},
          new String[] {"checkbox", "automf", "ok", "checked"});
    else
      browseForm.addChild(
          "input",
          new String[] {"type", "name", "value"},
          new String[] {"checkbox", "automf", "ok"});
    browseForm.addChild("#", "\u00a0auto open as manifest if possible\u00a0");
    if (deep)
      browseForm.addChild(
          "input",
          new String[] {"type", "name", "value", "checked"},
          new String[] {"checkbox", Globals.PARAM_RECURSIVE, "ok", "checked"});
    else
      browseForm.addChild(
          "input",
          new String[] {"type", "name", "value"},
          new String[] {"checkbox", Globals.PARAM_RECURSIVE, "ok"});
    browseForm.addChild(
        "#",
        "\u00a0parse manifest recursive (include multilevel metadata/subcontainers)\u00a0\u00a0");
    browseForm.addChild("#", "Hex display columns:\u00a0");
    browseForm.addChild(
        "input",
        new String[] {"type", "name", "size", "value"},
        new String[] {"text", PARAM_HEXWIDTH, "3", Integer.toString(hexWidth)});
    return browseBox;
  }
예제 #22
0
  private void makeMainPage(
      ToadletContext ctx,
      List<String> errors,
      String key,
      int hexWidth,
      boolean automf,
      boolean deep,
      boolean ml)
      throws ToadletContextClosedException, IOException, RedirectException, URISyntaxException {
    PageNode page = pluginContext.pageMaker.getPageNode(i18n("KeyExplorer.PageTitle"), ctx);
    HTMLNode pageNode = page.outer;
    HTMLNode contentNode = page.content;

    byte[] data = null;
    GetResult getresult = null;
    String extraParams = "&hexwidth=" + hexWidth;
    if (automf) {
      extraParams += "&automf=checked";
    }
    if (deep) {
      extraParams += "&deep=checked";
    }
    if (ml) {
      extraParams += "&ml=checked";
    }
    FreenetURI furi = null;
    FreenetURI retryUri = null;

    try {
      if (key != null && (key.trim().length() > 0)) {
        furi =
            URISanitizer.sanitizeURI(
                errors,
                key,
                false,
                URISanitizer.Options.NOMETASTRINGS,
                URISanitizer.Options.SSKFORUSK);
        retryUri = furi;
        if (ml) { // multilevel is requestet
          Metadata tempMD =
              KeyExplorerUtils.simpleManifestGet(pluginContext.pluginRespirator, furi);
          FetchResult tempResult =
              KeyExplorerUtils.splitGet(pluginContext.pluginRespirator, tempMD);
          getresult = new GetResult(tempResult.asBucket(), true);
          data = tempResult.asByteArray();
        } else { // normal get
          getresult = KeyExplorerUtils.simpleGet(pluginContext.pluginRespirator, furi);
          data = BucketTools.toByteArray(getresult.getData());
        }
      }
    } catch (MalformedURLException e) {
      errors.add("MalformedURL: " + key);
    } catch (IOException e) {
      Logger.error(this, "500", e);
      errors.add("IO Error: " + e.getMessage());
    } catch (MetadataParseException e) {
      errors.add("Metadata Parse Error: " + e.getMessage());
    } catch (FetchException e) {
      errors.add("Get failed (" + e.mode + "): " + e.getMessage());
    } catch (KeyListenerConstructionException e) {
      Logger.error(this, "Hu?", e);
      errors.add("Internal Error: " + e.getMessage());
    } finally {
      if (getresult != null) getresult.free();
    }

    HTMLNode uriBox =
        createUriBox(
            pluginContext,
            ((furi == null) ? null : furi.toString(false, false)),
            hexWidth,
            automf,
            deep,
            errors);

    if (errors.size() > 0) {
      contentNode.addChild(createErrorBox(errors, path(), retryUri, extraParams));
      errors.clear();
    }

    contentNode.addChild(uriBox);

    if (data != null) {
      Metadata md = null;

      if (getresult.isMetaData()) {
        try {
          md = Metadata.construct(data);
        } catch (MetadataParseException e) {
          errors.add("Metadata parse error: " + e.getMessage());
        }
        if (md != null) {
          if (automf && md.isArchiveManifest()) {
            if (md.getArchiveType() == ARCHIVE_TYPE.TAR) {
              writeTemporaryRedirect(
                  ctx,
                  "",
                  KeyUtilsPlugin.PLUGIN_URI
                      + "/Site/?mftype=TARmanifest&key="
                      + furi
                      + extraParams);
              return;
            } else if (md.getArchiveType() == ARCHIVE_TYPE.ZIP) {
              writeTemporaryRedirect(
                  ctx,
                  "",
                  KeyUtilsPlugin.PLUGIN_URI
                      + "/Site/?mftype=ZIPmanifest&key="
                      + furi
                      + extraParams);
              return;
            } else {
              errors.add("Unknown Archive Type: " + md.getArchiveType().name());
            }
          }
          if (automf && md.isSimpleManifest()) {
            writeTemporaryRedirect(
                ctx,
                "",
                KeyUtilsPlugin.PLUGIN_URI
                    + "/Site/?mftype=simplemanifest&key="
                    + furi
                    + extraParams);
            return;
          }
        }
      }

      String title = "Key: " + furi.toString(false, false);
      if (getresult.isMetaData()) title = title + "\u00a0(MetaData)";
      HTMLNode dataBox2 = pluginContext.pageMaker.getInfobox("#", title, contentNode);

      dataBox2.addChild("%", "<pre lang=\"en\" style=\"font-family: monospace;\">\n");
      dataBox2.addChild("#", hexDump(data, hexWidth));
      dataBox2.addChild("%", "\n</pre>");

      if (getresult.isMetaData()) {
        if (md != null) {
          HTMLNode metaBox =
              pluginContext.pageMaker.getInfobox("#", "Decomposed metadata", contentNode);

          metaBox.addChild("#", "Metadata version " + Short.toString(md.getParsedVersion()));
          metaBox.addChild("br");
          metaBox.addChild("#", "Document type:\u00a0");
          if (md.isSimpleRedirect()) {
            metaBox.addChild("#", "SimpleRedirect");
          } else if (md.isSimpleManifest()) {
            metaBox.addChild("#", "SimpleManifest");
          } else if (md.isArchiveInternalRedirect()) {
            metaBox.addChild("#", "ArchiveInternalRedirect");
          } else if (md.isArchiveMetadataRedirect()) {
            metaBox.addChild("#", "ArchiveMetadataRedirect");
          } else if (md.isArchiveManifest()) {
            metaBox.addChild("#", "ArchiveManifest");
          } else if (md.isMultiLevelMetadata()) {
            metaBox.addChild("#", "MultiLevelMetadata");
          } else if (md.isSymbolicShortlink()) {
            metaBox.addChild("#", "SymbolicShortlink");
          } else {
            metaBox.addChild("#", "<Unknown document type>");
          }
          metaBox.addChild("br");

          final String MIMEType = md.getMIMEType();
          if (MIMEType != null) {
            metaBox.addChild("#", "MIME Type: " + MIMEType);
            metaBox.addChild("br");
          }

          if (md.haveFlags()) {
            metaBox.addChild("#", "Flags:\u00a0");
            boolean isFirst = true;

            if (md.isSplitfile()) {
              metaBox.addChild("#", "SplitFile");
              isFirst = false;
            }
            if (md.isCompressed()) {
              if (isFirst) isFirst = false;
              else metaBox.addChild("#", "\u00a0");
              metaBox.addChild("#", "Compressed (" + md.getCompressionCodec().name + ")");
            }
            if (md.hasTopData()) {
              if (isFirst) isFirst = false;
              else metaBox.addChild("#", "\u00a0");
              metaBox.addChild("#", "HasTopData");
            }
            if (isFirst) metaBox.addChild("#", "<No flag set>");
          }
          metaBox.addChild("br");

          if (md.isCompressed()) {
            metaBox.addChild("#", "Decompressed size: " + md.uncompressedDataLength() + " bytes.");
          } else {
            metaBox.addChild("#", "Uncompressed");
          }

          metaBox.addChild("br");

          if (md.topCompatibilityMode != 0) {
            metaBox.addChild("#", "Compatibility mode: " + md.getTopCompatibilityMode().toString());
            metaBox.addChild("br");
          }

          if (md.hasTopData()) {
            metaBox.addChild("#", "Top Block Data:");
            metaBox.addChild("br");
            metaBox.addChild(
                "#", "\u00a0\u00a0DontCompress: " + Boolean.toString(md.topDontCompress));
            metaBox.addChild("br");
            metaBox.addChild(
                "#",
                "\u00a0\u00a0Compressed size: " + Long.toString(md.topCompressedSize) + " bytes.");
            metaBox.addChild("br");
            metaBox.addChild(
                "#", "\u00a0\u00a0Decompressed Size: " + Long.toString(md.topSize) + " bytes.");
            metaBox.addChild("br");
            metaBox.addChild(
                "#",
                "\u00a0\u00a0Blocks: "
                    + Integer.toString(md.topBlocksRequired)
                    + " required, "
                    + Integer.toString(md.topBlocksTotal)
                    + " total.");
            metaBox.addChild("br");
          }
          final HashResult[] hashes = md.getHashes();
          if (hashes != null && hashes.length > 0) {
            metaBox.addChild("#", "Hashes:");
            metaBox.addChild("br");
            for (final HashResult hash : hashes) {
              metaBox.addChild(
                  "#", "\u00a0\u00a0" + hash.type.name() + ": " + HexUtil.bytesToHex(hash.result));
              metaBox.addChild("br");
            }
          }

          if (md.isSplitfile()) {
            metaBox.addChild("#", "Splitfile size\u00a0=\u00a0" + md.dataLength() + " bytes.");
            metaBox.addChild("br");

            byte[] splitfileCryptoKey = md.getCustomSplitfileKey();
            if (splitfileCryptoKey != null) {
              metaBox.addChild(
                  "#", "Splitfile CryptoKey\u00a0=\u00a0" + HexUtil.bytesToHex(splitfileCryptoKey));
              metaBox.addChild("br");
            }
          }

          metaBox.addChild("#", "Options:");
          metaBox.addChild("br");

          if (md.isSimpleManifest()) {
            metaBox.addChild(
                new HTMLNode(
                    "a",
                    "href",
                    KeyUtilsPlugin.PLUGIN_URI
                        + "/Site/?mftype=simplemanifest&key="
                        + furi
                        + extraParams,
                    "reopen as manifest"));
            metaBox.addChild("br");
          }
          if (md.isArchiveManifest()) {
            metaBox.addChild(
                new HTMLNode(
                    "a",
                    "href",
                    KeyUtilsPlugin.PLUGIN_URI
                        + "/Site/?mftype="
                        + md.getArchiveType().name()
                        + "manifest&key="
                        + furi
                        + extraParams,
                    "reopen as manifest"));
            metaBox.addChild("br");
          }
          if (md.isMultiLevelMetadata()) {
            if (ml)
              metaBox.addChild(
                  new HTMLNode(
                      "a",
                      "href",
                      KeyUtilsPlugin.PLUGIN_URI + "/?key=" + furi + extraParams,
                      "explore multilevel"));
            else
              metaBox.addChild(
                  new HTMLNode(
                      "a",
                      "href",
                      KeyUtilsPlugin.PLUGIN_URI + "/?ml=checked&key=" + furi + extraParams,
                      "explore multilevel"));
            metaBox.addChild("br");
          }

          FreenetURI uri = md.getSingleTarget();
          if (uri != null) {
            String sfrUri = uri.toString(false, false);
            metaBox.addChild("#", sfrUri);
            metaBox.addChild("#", "\u00a0");
            metaBox.addChild(new HTMLNode("a", "href", "/?key=" + sfrUri, "open"));
            metaBox.addChild("#", "\u00a0");
            metaBox.addChild(
                new HTMLNode(
                    "a",
                    "href",
                    KeyUtilsPlugin.PLUGIN_URI + "/?key=" + sfrUri + extraParams,
                    "explore"));
          } else {
            metaBox.addChild(new HTMLNode("a", "href", "/?key=" + furi, "reopen normal"));
          }
          metaBox.addChild("br");

          if ((uri == null) && md.isSplitfile()) {
            metaBox.addChild(
                new HTMLNode(
                    "a",
                    "href",
                    KeyUtilsPlugin.PLUGIN_URI + "/Split?key=" + furi.toString(false, false),
                    "reopen as splitfile"));
            metaBox.addChild("br");
            metaBox.addChild(
                new HTMLNode(
                    "a",
                    "href",
                    KeyUtilsPlugin.PLUGIN_URI
                        + "/Download?action=splitdownload&key="
                        + furi.toString(false, false),
                    "split-download"));
            metaBox.addChild("br");
          }
        }
      }
      if (errors.size() > 0) contentNode.addChild(createErrorBox(errors));
    }
    contentNode.addChild(Utils.makeDonateFooter(_intl));
    writeHTMLReply(ctx, 200, "OK", pageNode.generate());
  }
예제 #23
0
  /** {@inheritDoc} */
  @Override
  public Response handleRequest(FreenetRequest request, Response response) throws IOException {
    String redirectTarget = getRedirectTarget(request);
    if (redirectTarget != null) {
      return new RedirectResponse(redirectTarget);
    }

    if (isFullAccessOnly() && !request.getToadletContext().isAllowedFullAccess()) {
      return response
          .setStatusCode(401)
          .setStatusText("Not authorized")
          .setContentType("text/html");
    }
    ToadletContext toadletContext = request.getToadletContext();
    if (request.getMethod() == Method.POST) {
      /* require form password. */
      String formPassword = request.getHttpRequest().getPartAsStringFailsafe("formPassword", 32);
      if (!formPassword.equals(toadletContext.getContainer().getFormPassword())) {
        return new RedirectResponse(invalidFormPasswordRedirectTarget);
      }
    }
    PageMaker pageMaker = toadletContext.getPageMaker();
    PageNode pageNode = pageMaker.getPageNode(getPageTitle(request), toadletContext);
    for (String styleSheet : getStyleSheets()) {
      pageNode.addCustomStyleSheet(styleSheet);
    }
    for (Map<String, String> linkNodeParameters : getAdditionalLinkNodes(request)) {
      HTMLNode linkNode = pageNode.headNode.addChild("link");
      for (Entry<String, String> parameter : linkNodeParameters.entrySet()) {
        linkNode.addAttribute(parameter.getKey(), parameter.getValue());
      }
    }
    String shortcutIcon = getShortcutIcon();
    if (shortcutIcon != null) {
      pageNode.addForwardLink("icon", shortcutIcon);
    }

    TemplateContext templateContext = templateContextFactory.createTemplateContext();
    templateContext.mergeContext(template.getInitialContext());
    try {
      long start = System.nanoTime();
      processTemplate(request, templateContext);
      long finish = System.nanoTime();
      logger.log(
          Level.FINEST, "Template was rendered in " + ((finish - start) / 1000) / 1000.0 + "ms.");
    } catch (RedirectException re1) {
      return new RedirectResponse(re1.getTarget());
    }

    StringWriter stringWriter = new StringWriter();
    template.render(templateContext, stringWriter);
    pageNode.content.addChild("%", stringWriter.toString());

    postProcess(request, templateContext);

    return response
        .setStatusCode(200)
        .setStatusText("OK")
        .setContentType("text/html")
        .write(pageNode.outer.generate());
  }
  public void make() {
    String threadSubject = "";
    String threadText = "";

    if ((mRequest.isPartSet("CreateThread") || mRequest.isPartSet("CreatePreview"))
        && mRequest.getMethod().equals("POST")) {
      HashSet<Board> boards = new HashSet<Board>();
      boards.add(mBoard);

      try {
        threadSubject =
            mRequest.getPartAsStringFailsafe(
                "ThreadSubject", Message.MAX_MESSAGE_TITLE_TEXT_LENGTH * 2);
        threadText =
            mRequest.getPartAsStringFailsafe("ThreadText", Message.MAX_MESSAGE_TEXT_LENGTH * 2);

        if (threadSubject.length() > Message.MAX_MESSAGE_TITLE_TEXT_LENGTH)
          throw new Exception(
              l10n()
                  .getString(
                      "Common.Message.Subject.TooLong",
                      "limit",
                      Integer.toString(Message.MAX_MESSAGE_TITLE_TEXT_LENGTH)));

        if (threadText.length() > Message.MAX_MESSAGE_TEXT_LENGTH)
          throw new Exception(
              l10n()
                  .getString(
                      "Common.Message.Text.TooLong",
                      "limit",
                      Integer.toString(Message.MAX_MESSAGE_TEXT_LENGTH)));

        if (mRequest.isPartSet("CreatePreview")) {
          mContentNode.addChild(
              PreviewPane.createPreviewPane(mPM, l10n(), threadSubject, threadText));
          makeNewThreadPage(threadSubject, threadText);
        } else {
          mFreetalk
              .getMessageManager()
              .postMessage(
                  null, null, boards, mBoard, mOwnIdentity, threadSubject, null, threadText, null);

          HTMLNode successBox =
              addContentBox(l10n().getString("NewThreadPage.ThreadCreated.Header"));
          successBox.addChild("p", l10n().getString("NewThreadPage.ThreadCreated.Text"));
          HTMLNode aChild = successBox.addChild("#");
          l10n()
              .addL10nSubstitution(
                  aChild,
                  "NewThreadPage.ThreadCreated.BackToBoard",
                  new String[] {"link", "boardname", "/link"},
                  new String[] {
                    // TODO: Use BoardPage.getURI(mBoard) here?
                    "<a href=\""
                        + Freetalk.PLUGIN_URI
                        + "/showBoard?identity="
                        + mOwnIdentity.getID()
                        + "&name="
                        + mBoard.getName()
                        + "\">",
                    mBoard.getName(),
                    "</a>"
                  });
        }
      } catch (Exception e) {
        HTMLNode alertBox = addAlertBox(l10n().getString("NewThreadPage.ThreadFailed.Header"));
        alertBox.addChild("div", e.getMessage());

        makeNewThreadPage(threadSubject, threadText);
      }
      return;
    } else makeNewThreadPage(threadSubject, threadText);
  }
  /** Generate node of page results from this generator */
  private void generatePageEntryNode() {
    pageEntryNode = new HTMLNode("div", "id", "results");

    int results = 0;
    // Loop to separate results into SSK groups

    if (groupmap != null) { // Produce grouped list of pages
      SortedSet<TermPageGroupEntry> groupSet = new TreeSet(RelevanceComparator.comparator);
      groupSet.addAll(groupmap.values());

      // Loop over keys
      Iterator<TermPageGroupEntry> it2 = groupSet.iterator();
      while (it2.hasNext()) {
        TermPageGroupEntry group = it2.next();
        String keybase = group.subj;
        SortedMap<Long, SortedSet<TermPageEntry>> siteMap = group.getEditions();
        HTMLNode siteNode = pageEntryNode.addChild("div", "style", "padding-bottom: 6px;");
        // Create a block for old versions of this SSK
        HTMLNode siteBlockOldOuter =
            siteNode.addChild(
                "div",
                new String[] {"id", "style"},
                new String[] {"result-hiddenblock-" + keybase, (!showold ? "display:none" : "")});
        // put title on block if it has more than one version in it
        if (siteMap.size() > 1)
          siteBlockOldOuter
              .addChild(
                  "a",
                  new String[] {"onClick", "name"},
                  new String[] {"toggleResult('" + keybase + "')", keybase})
              .addChild("h3", "class", "result-grouptitle", keybase.replaceAll("\\b.*/(.*)", "$1"));
        // inner block for old versions to be hidden
        HTMLNode oldEditionContainer =
            siteBlockOldOuter.addChild(
                "div",
                new String[] {"class", "style"},
                new String[] {"result-hideblock", "border-left: thick black;"});
        // Loop over all editions in this site
        Iterator<Long> it3 = siteMap.keySet().iterator();
        while (it3.hasNext()) {
          long version = it3.next();
          boolean newestVersion = !it3.hasNext();
          if (newestVersion) // put older versions in block, newest outside block
          oldEditionContainer = siteNode;
          HTMLNode versionCell;
          HTMLNode versionNode;
          if (siteMap.get(version).size() > 1 || siteMap.size() > 1) {
            // table for this version
            versionNode =
                oldEditionContainer.addChild(
                    "table", new String[] {"class"}, new String[] {"librarian-result"});
            HTMLNode grouptitle =
                versionNode
                    .addChild("tr")
                    .addChild("td", new String[] {"padding", "colspan"}, new String[] {"0", "3"});
            grouptitle.addChild(
                "h4",
                "class",
                (newestVersion ? "result-editiontitle-new" : "result-editiontitle-old"),
                keybase.replaceAll("\\b.*/(.*)", "$1") + (version >= 0 ? "-" + version : ""));
            // Put link to show hidden older versions block if necessary
            if (newestVersion && !showold && js && siteMap.size() > 1)
              grouptitle.addChild(
                  "a",
                  new String[] {"href", "onClick"},
                  new String[] {"#" + keybase, "toggleResult('" + keybase + "')"},
                  "       [" + (siteMap.size() - 1) + " older matching versions]");
            HTMLNode versionrow = versionNode.addChild("tr");
            versionrow.addChild("td", "width", "8px");
            // draw black line down the side of the version
            versionrow.addChild("td", new String[] {"class"}, new String[] {"sskeditionbracket"});

            versionCell = versionrow.addChild("td", "style", "padding-left:15px");
          } else versionCell = oldEditionContainer;
          // loop over each result in this version
          Iterator<TermPageEntry> it4 = siteMap.get(version).iterator();
          while (it4.hasNext()) {
            versionCell.addChild(termPageEntryNode(it4.next(), newestVersion));
            results++;
          }
        }
      }
    } else { // Just produce sorted list of results
      for (Iterator<Entry<TermPageEntry, Boolean>> it = pageset.entrySet().iterator();
          it.hasNext(); ) {
        Entry<TermPageEntry, Boolean> entry = it.next();
        TermPageEntry termPageEntry = entry.getKey();
        boolean newestVersion = entry.getValue();
        pageEntryNode.addChild("div").addChild(termPageEntryNode(termPageEntry, newestVersion));
        results++;
      }
    }
    pageEntryNode
        .addChild("p")
        .addChild("span", "class", "librarian-summary-found", "Found " + results + " results");
  }
예제 #26
0
  private void addMessageHeaders(HTMLNode messageNode, MailMessage message) {
    HTMLNode headerBox = messageNode.addChild("div", "class", "message-headers");

    try {
      message.readHeaders();
    } catch (IOException e) {
      /* FIXME: L10n */
      Logger.error(this, "Caugth IOException reading headers for " + message);
      headerBox.addChild("p", "There was a problem reading the message headers");
      return;
    }

    HTMLNode fromPara = headerBox.addChild("p");
    fromPara.addChild("strong", "From:");
    try {
      String from = MailMessage.decodeHeader(message.getFirstHeader("from"));
      if (from == null) {
        from = FreemailL10n.getString("Freemail.MessageToadlet.fromMissing");
      }

      fromPara.addChild("#", " " + from);
    } catch (UnsupportedEncodingException e1) {
      fromPara.addChild("#", " " + message.getFirstHeader("from"));
    }

    for (String header : new String[] {"To", "CC", "BCC"}) {
      for (String recipient : message.getHeadersByName(header)) {
        HTMLNode toPara = headerBox.addChild("p");
        toPara.addChild("strong", header + ":");
        try {
          toPara.addChild("#", " " + MailMessage.decodeHeader(recipient));
        } catch (UnsupportedEncodingException e) {
          toPara.addChild("#", " " + recipient);
        }
      }
    }

    HTMLNode subjectPara = headerBox.addChild("p");
    subjectPara.addChild("strong", "Subject:");

    String subject;
    try {
      subject = message.getSubject();
    } catch (UnsupportedEncodingException e) {
      subject = message.getFirstHeader("subject");
    }
    if ((subject == null) || (subject.equals(""))) {
      subject = FreemailL10n.getString("Freemail.Web.Common.defaultSubject");
    }
    subjectPara.addChild("#", " " + subject);

    HTMLNode datePara = headerBox.addChild("p");
    datePara.addChild("strong", FreemailL10n.getString("Freemail.MessageToadlet.date"));
    datePara.addChild(
        "#",
        " "
            + getMessageDateAsString(
                message, FreemailL10n.getString("Freemail.MessageToadlet.dateMissing")));
  }
  private void makeBoardsList() {
    HTMLNode boardsBox = addContentBox(l10n().getString("SelectBoardsPage.SelectBoardsBox.Header"));

    boardsBox.addChild("p", l10n().getString("SelectBoardsPage.SelectBoardsBox.Text"));

    HTMLNode buttonRow = boardsBox.addChild("div", "class", "button-row");

    HTMLNode buttonDiv = buttonRow.addChild("div", "class", "button-row-button");
    HTMLNode newBoardForm =
        addFormChild(buttonDiv, Freetalk.PLUGIN_URI + "/NewBoard", "NewBoardPage");
    newBoardForm.addChild(
        "input",
        new String[] {"type", "name", "value"},
        new String[] {"hidden", "OwnIdentityID", mOwnIdentity.getID()});
    newBoardForm.addChild(
        "input",
        new String[] {"type", "name", "value"},
        new String[] {"submit", "submit", l10n().getString("SelectBoardsPage.NewBoardButton")});

    buttonDiv = buttonRow.addChild("div", "class", "button-row-button");
    HTMLNode deleteEmptyBoardsForm =
        addFormChild(buttonDiv, Freetalk.PLUGIN_URI + "/DeleteEmptyBoards", "DeleteEmptyBoards");
    deleteEmptyBoardsForm.addChild(
        "input",
        new String[] {"type", "name", "value"},
        new String[] {"hidden", "OwnIdentityID", mOwnIdentity.getID()});
    deleteEmptyBoardsForm.addChild(
        "input",
        new String[] {"type", "name", "value"},
        new String[] {
          "submit",
          "submit",
          l10n().getString("SelectBoardsPage.SelectBoardsBox.DeleteEmptyBoardsButton")
        });

    // Clear margins after button row. TODO: Refactoring: Move to CSS
    boardsBox.addChild("div", "style", "clear: both;");

    HTMLNode boardsTable = boardsBox.addChild("table", "border", "0");
    HTMLNode row = boardsTable.addChild("tr");
    row.addChild("th", l10n().getString("SelectBoardsPage.BoardTableHeader.Language"));
    row.addChild("th", l10n().getString("SelectBoardsPage.BoardTableHeader.Name"));
    row.addChild("th", l10n().getString("SelectBoardsPage.BoardTableHeader.Description"));
    row.addChild("th", l10n().getString("SelectBoardsPage.BoardTableHeader.FirstSeen"));
    row.addChild("th", l10n().getString("SelectBoardsPage.BoardTableHeader.LatestMessage"));
    row.addChild("th", l10n().getString("SelectBoardsPage.BoardTableHeader.Messages"));
    row.addChild("th", l10n().getString("SelectBoardsPage.BoardTableHeader.Subscribe"));
    row.addChild("th", l10n().getString("SelectBoardsPage.BoardTableHeader.Unsubscribe"));

    DateFormat dateFormat = DateFormat.getInstance();

    MessageManager messageManager = mFreetalk.getMessageManager();

    synchronized (messageManager) {
      for (final Board board : messageManager.boardIteratorSortedByName()) {
        row = boardsTable.addChild("tr", "id", board.getName());

        // Language

        row.addChild(
            "td", new String[] {"align"}, new String[] {"left"}, board.getLanguage().referenceName);

        // Name

        HTMLNode nameCell = row.addChild("th", new String[] {"align"}, new String[] {"left"});

        // .addChild(new HTMLNode("a", "href", Freetalk.PLUGIN_URI + "/SubscribeToBoard?identity=" +
        // mOwnIdentity.getID() + "&name=" + board.getName(),
        //		board.getName()));

        // Description
        row.addChild(
            "td",
            new String[] {"align"},
            new String[] {"left"},
            board.getDescription(mOwnIdentity));

        // First seen
        row.addChild(
            "td",
            new String[] {"align"},
            new String[] {"center"},
            dateFormat.format(board.getFirstSeenDate()));

        // Latest message
        HTMLNode latestMessageCell =
            row.addChild("td", new String[] {"align"}, new String[] {"center"});

        // Message count
        HTMLNode messageCountCell =
            row.addChild("td", new String[] {"align"}, new String[] {"center"});

        HTMLNode subscribeCell =
            row.addChild("td", new String[] {"align"}, new String[] {"center"});
        HTMLNode unsubscribeCell =
            row.addChild("td", new String[] {"align"}, new String[] {"center"});

        try {
          SubscribedBoard subscribedBoard =
              messageManager.getSubscription(mOwnIdentity, board.getName());

          // We are subscribed to that board so we can display some more information.

          nameCell.addChild(new HTMLNode("a", "href", BoardPage.getURI(board), board.getName()));

          try {
            latestMessageCell.addChild(
                "#", dateFormat.format(subscribedBoard.getLatestMessage().getMessageDate()));
          } catch (NoSuchMessageException e) {
            latestMessageCell.addChild("#", "-");
          }

          messageCountCell.addChild("#", Integer.toString(subscribedBoard.messageCount()));

          HTMLNode unsubscribeForm =
              addFormChild(
                  unsubscribeCell,
                  Freetalk.PLUGIN_URI + "/SelectBoards" + "#" + board.getName(),
                  "Unsubscribe");
          unsubscribeForm.addChild(
              "input",
              new String[] {"type", "name", "value"},
              new String[] {"hidden", "OwnIdentityID", mOwnIdentity.getID()});
          unsubscribeForm.addChild(
              "input",
              new String[] {"type", "name", "value"},
              new String[] {"hidden", "BoardName", board.getName()});
          unsubscribeForm.addChild(
              "input",
              new String[] {"type", "name", "value"},
              new String[] {
                "submit",
                "Unsubscribe",
                l10n().getString("SelectBoardsPage.BoardTable.UnsubscribeButton")
              });
        } catch (NoSuchBoardException e) {
          // We are not subscribed to that board so we cannot fill all cells with information.

          nameCell.addChild(
              new HTMLNode("a", "href", NotFetchedMessagesPage.getURI(board), board.getName()));

          latestMessageCell.addChild("#", "-");
          messageCountCell.addChild(
              "#",
              l10n().getString("Common.EstimationPrefix")
                  + " "
                  + messageManager.getDownloadableMessageCount(board));

          HTMLNode subscribeForm =
              addFormChild(
                  subscribeCell,
                  Freetalk.PLUGIN_URI + "/SelectBoards" + "#" + board.getName(),
                  "Subscribe");
          subscribeForm.addChild(
              "input",
              new String[] {"type", "name", "value"},
              new String[] {"hidden", "OwnIdentityID", mOwnIdentity.getID()});
          subscribeForm.addChild(
              "input",
              new String[] {"type", "name", "value"},
              new String[] {"hidden", "BoardName", board.getName()});
          subscribeForm.addChild(
              "input",
              new String[] {"type", "name", "value"},
              new String[] {
                "submit",
                "Subscribe",
                l10n().getString("SelectBoardsPage.BoardTable.SubscribeButton")
              });
        }
      }
    }
  }
  /** Makes the list of Identities known by the tree owner. */
  private void makeKnownIdentitiesList() {

    String nickFilter = mRequest.getPartAsStringFailsafe("nickfilter", 100).trim();
    String sortBy =
        mRequest.isPartSet("sortby")
            ? mRequest.getPartAsStringFailsafe("sortby", 100).trim()
            : "Nickname";
    String sortType =
        mRequest.isPartSet("sorttype")
            ? mRequest.getPartAsStringFailsafe("sorttype", 100).trim()
            : "Ascending";

    int page =
        mRequest.isPartSet("page")
            ? Integer.parseInt(
                mRequest.getPartAsStringFailsafe(
                    "page", Integer.toString(Integer.MAX_VALUE).length()))
            : 0;
    page = page - 1; // What we get passed is the user-friendly page number counting from 1, not 0.
    page = Math.max(0, page); // In case no page part was set, it would be -1

    HTMLNode knownIdentitiesBox =
        addContentBox(l10n().getString("KnownIdentitiesPage.KnownIdentities.Header"));
    knownIdentitiesBox =
        pr.addFormChild(knownIdentitiesBox, uri.toString(), "Filters").addChild("p");
    knownIdentitiesBox.addChild(
        "input",
        new String[] {"type", "name", "value"},
        new String[] {"hidden", "page", Integer.toString(page + 1)});

    InfoboxNode filtersBoxNode =
        getContentBox(l10n().getString("KnownIdentitiesPage.FiltersAndSorting.Header"));

    { // Filters box
      knownIdentitiesBox.addChild(filtersBoxNode.outer);
      HTMLNode filtersBox = filtersBoxNode.content;
      filtersBox.addChild(
          "#",
          l10n().getString("KnownIdentitiesPage.FiltersAndSorting.ShowOnlyNicksContaining")
              + " : ");
      filtersBox.addChild(
          "input",
          new String[] {"type", "size", "name", "value"},
          new String[] {"text", "15", "nickfilter", nickFilter});

      filtersBox.addChild(
          "#",
          " " + l10n().getString("KnownIdentitiesPage.FiltersAndSorting.SortIdentitiesBy") + " : ");
      HTMLNode option =
          filtersBox.addChild(
              "select", new String[] {"name", "id"}, new String[] {"sortby", "sortby"});
      TreeMap<String, String> options = new TreeMap<String, String>();
      options.put(
          SortBy.Edition.toString(),
          l10n().getString("KnownIdentitiesPage.FiltersAndSorting.SortIdentitiesBy.Edition"));
      options.put(
          SortBy.Nickname.toString(),
          l10n().getString("KnownIdentitiesPage.FiltersAndSorting.SortIdentitiesBy.Nickname"));
      options.put(
          SortBy.Score.toString(),
          l10n().getString("KnownIdentitiesPage.FiltersAndSorting.SortIdentitiesBy.Score"));
      options.put(
          SortBy.LocalTrust.toString(),
          l10n().getString("KnownIdentitiesPage.FiltersAndSorting.SortIdentitiesBy.LocalTrust"));
      for (String e : options.keySet()) {
        HTMLNode newOption = option.addChild("option", "value", e, options.get(e));
        if (e.equals(sortBy)) {
          newOption.addAttribute("selected", "selected");
        }
      }

      option =
          filtersBox.addChild(
              "select", new String[] {"name", "id"}, new String[] {"sorttype", "sorttype"});
      options = new TreeMap<String, String>();
      options.put(
          "Ascending",
          l10n().getString("KnownIdentitiesPage.FiltersAndSorting.SortIdentitiesBy.Ascending"));
      options.put(
          "Descending",
          l10n().getString("KnownIdentitiesPage.FiltersAndSorting.SortIdentitiesBy.Descending"));
      for (String e : options.keySet()) {
        HTMLNode newOption = option.addChild("option", "value", e, options.get(e));
        if (e.equals(sortType)) {
          newOption.addAttribute("selected", "selected");
        }
      }

      filtersBox.addChild(
          "input",
          new String[] {"type", "value"},
          new String[] {
            "submit",
            l10n().getString("KnownIdentitiesPage.FiltersAndSorting.SortIdentitiesBy.SubmitButton")
          });
    }

    // Display the list of known identities
    HTMLNode identitiesTable = knownIdentitiesBox.addChild("table", "border", "0");
    identitiesTable.addChild(getKnownIdentitiesListTableHeader());

    WebOfTrust.SortOrder sortInstruction = WebOfTrust.SortOrder.valueOf("By" + sortBy + sortType);

    synchronized (mWebOfTrust) {
      long currentTime = CurrentTimeUTC.getInMillis();
      int indexOfFirstIdentity = page * IDENTITIES_PER_PAGE;

      // Re-query it instead of using mLoggedInOwnIdentity because mLoggedInOwnIdentity is a
      // clone() and thus will not work with database queries on the WebOfTrust.
      // TODO: Performance: This can be removed once the TODO at
      // WebPageImpl.getLoggedInOwnIdentityFromHTTPSession() of not cloning the
      // OwnIdentity has been been resolved.
      final OwnIdentity ownId;
      try {
        ownId = mWebOfTrust.getOwnIdentityByID(mLoggedInOwnIdentity.getID());
      } catch (UnknownIdentityException e) {
        new ErrorPage(mToadlet, mRequest, mContext, e).addToPage(this);
        return;
      }

      ObjectSet<Identity> allIdentities =
          mWebOfTrust.getAllIdentitiesFilteredAndSorted(ownId, nickFilter, sortInstruction);

      Iterator<Identity> identities;
      try {
        identities = allIdentities.listIterator(indexOfFirstIdentity);
      } catch (IndexOutOfBoundsException e) {
        // The user supplied a higher page index than there are pages. This can happen when the
        // user changes the search filters while not being on the first page.
        // We fall back to displaying the last page.
        // Notice: We intentionally do not prevent listIterator() from throwing by checking
        // the index for validity before calling listIterator(). This is because we would need
        // to call allIdentities.size() to check the index. This would force the database to
        // compute the full result set even though we only need the results up to the current
        // page if we are not on the last page.
        page = getPageCount(allIdentities.size()) - 1;
        indexOfFirstIdentity = page * IDENTITIES_PER_PAGE;

        // TODO: Performance: Don't re-query this from the database once the issue which caused
        // this workaround is fixed: https://bugs.freenetproject.org/view.php?id=6646
        allIdentities =
            mWebOfTrust.getAllIdentitiesFilteredAndSorted(ownId, nickFilter, sortInstruction);

        identities = allIdentities.listIterator(indexOfFirstIdentity);
      }

      for (int displayed = 0;
          displayed < IDENTITIES_PER_PAGE && identities.hasNext();
          ++displayed) {
        final Identity id = identities.next();

        if (id == ownId) continue;

        HTMLNode row = identitiesTable.addChild("tr");

        // NickName
        HTMLNode nameLink =
            row.addChild(
                    "td",
                    new String[] {"title", "style"},
                    new String[] {id.getRequestURI().toString(), "cursor: help;"})
                .addChild("a", "href", IdentityPage.getURI(mWebInterface, id.getID()).toString());

        String nickName = id.getNickname();

        if (nickName != null) {
          nameLink.addChild("#", nickName + "@" + id.getID().substring(0, 5) + "...");
        } else
          nameLink
              .addChild("span", "class", "alert-error")
              .addChild(
                  "#",
                  l10n()
                      .getString(
                          "KnownIdentitiesPage.KnownIdentities.Table.NicknameNotDownloadedYet"));

        // Added date
        row.addChild(
            "td",
            CommonWebUtils.formatTimeDelta(currentTime - id.getAddedDate().getTime(), l10n()));

        // Last fetched date
        Date lastFetched = id.getLastFetchedDate();
        if (!lastFetched.equals(new Date(0)))
          row.addChild(
              "td", CommonWebUtils.formatTimeDelta(currentTime - lastFetched.getTime(), l10n()));
        else row.addChild("td", l10n().getString("Common.Never"));

        // Publish TrustList
        row.addChild(
            "td",
            new String[] {"align"},
            new String[] {"center"},
            id.doesPublishTrustList()
                ? l10n().getString("Common.Yes")
                : l10n().getString("Common.No"));

        // Score
        try {
          final Score score = mWebOfTrust.getScore(ownId, id);
          final int scoreValue = score.getScore();
          final int rank = score.getRank();

          row.addChild(
              "td",
              new String[] {"align", "style"},
              new String[] {
                "center", "background-color:" + KnownIdentitiesPage.getTrustColor(scoreValue) + ";"
              },
              Integer.toString(scoreValue)
                  + " ("
                  + (rank != Integer.MAX_VALUE
                      ? rank
                      : l10n().getString("KnownIdentitiesPage.KnownIdentities.Table.InfiniteRank"))
                  + ")");
        } catch (NotInTrustTreeException e) {
          // This only happen with identities added manually by the user
          row.addChild("td", l10n().getString("KnownIdentitiesPage.KnownIdentities.Table.NoScore"));
        }

        // Own Trust
        row.addChild(getReceivedTrustCell(ownId, id));

        // Checkbox
        row.addChild(getSetTrustCell(id));

        // Nb Trusters
        // TODO: Do a direct link to the received-trusts part of the linked page
        HTMLNode trustersCell = row.addChild("td", new String[] {"align"}, new String[] {"center"});
        trustersCell.addChild(
            new HTMLNode(
                "a",
                "href",
                IdentityPage.getURI(mWebInterface, id.getID()).toString(),
                Long.toString(mWebOfTrust.getReceivedTrusts(id).size())));

        // Nb Trustees
        // TODO: Do a direct link to the given-trusts part of the linked page
        HTMLNode trusteesCell = row.addChild("td", new String[] {"align"}, new String[] {"center"});
        trusteesCell.addChild(
            new HTMLNode(
                "a",
                "href",
                IdentityPage.getURI(mWebInterface, id.getID()).toString(),
                Long.toString(mWebOfTrust.getGivenTrusts(id).size())));

        // TODO: Show in advanced mode only once someone finally fixes the "Switch to advanced mode"
        // link on FProxy to work on ALL pages.

        row.addChild("td", "align", "center", Long.toString(id.getEdition()));

        row.addChild("td", "align", "center", Long.toString(id.getLatestEditionHint()));
      }
      identitiesTable.addChild(getKnownIdentitiesListTableHeader());
      knownIdentitiesBox.addChild(getKnownIdentitiesListPageLinks(page, allIdentities.size()));
    }
  }
  @Override
  public void make(final boolean mayWrite) {
    if (mLoggedInOwnIdentity.isRestoreInProgress()) {
      makeRestoreInProgressWarning();
      return;
    }

    final boolean addIdentity = mRequest.isPartSet("AddIdentity");

    if (mayWrite && addIdentity) {
      try {
        mWebOfTrust.addIdentity(mRequest.getPartAsStringFailsafe("IdentityURI", 1024));
        HTMLNode successBox =
            addContentBox(l10n().getString("KnownIdentitiesPage.AddIdentity.Success.Header"));
        successBox.addChild("#", l10n().getString("KnownIdentitiesPage.AddIdentity.Success.Text"));
      } catch (Exception e) {
        addErrorBox(l10n().getString("KnownIdentitiesPage.AddIdentity.Failed"), e);
      }
    }

    if (mayWrite && mRequest.isPartSet("SetTrust")) {
      for (String part : mRequest.getParts()) {
        if (!part.startsWith("SetTrustOf")) continue;

        final String trusteeID;
        final String value;
        final String comment;

        try {
          if (addIdentity) { // Add a single identity and set its trust value
            trusteeID =
                IdentityID.constructAndValidateFromURI(
                        new FreenetURI(mRequest.getPartAsStringFailsafe("IdentityURI", 1024)))
                    .toString();
            value = mRequest.getPartAsStringFailsafe("Value", 4).trim();
            comment =
                mRequest.getPartAsStringFailsafe("Comment", Trust.MAX_TRUST_COMMENT_LENGTH + 1);
          } else { // Change multiple trust values via the known-identities-list
            trusteeID = mRequest.getPartAsStringFailsafe(part, 128);
            value = mRequest.getPartAsStringFailsafe("Value" + trusteeID, 4).trim();
            comment =
                mRequest.getPartAsStringFailsafe(
                    "Comment" + trusteeID, Trust.MAX_TRUST_COMMENT_LENGTH + 1);
          }

          if (value.equals("")) mWebOfTrust.removeTrust(mLoggedInOwnIdentity.getID(), trusteeID);
          else {
            mWebOfTrust.setTrust(
                mLoggedInOwnIdentity.getID(), trusteeID,
                Byte.parseByte(value), comment);
          }

          if (addIdentity && (value.equals("") || Byte.parseByte(value) < 0)) {
            addErrorBox(
                l10n().getString("KnownIdentitiesPage.AddIdentity.NoTrustWarning.Header"),
                l10n().getString("KnownIdentitiesPage.AddIdentity.NoTrustWarning.Text"));
          }
        } catch (NumberFormatException e) {
          addErrorBox(
              l10n().getString("KnownIdentitiesPage.SetTrust.Failed"),
              l10n().getString("Trust.InvalidValue"));
        } catch (InvalidParameterException e) {
          addErrorBox(l10n().getString("KnownIdentitiesPage.SetTrust.Failed"), e.getMessage());
        } catch (Exception e) {
          addErrorBox(l10n().getString("KnownIdentitiesPage.SetTrust.Failed"), e);
        }
      }
    }

    makeKnownIdentitiesList();
    makeAddIdentityForm(); // Put this after makeKnownIdentitiesList() so clicking through pages of
    // the known identities list doesn't involve scrolling.
  }
  private HTMLNode getKnownIdentitiesListTableHeader() {
    HTMLNode row = new HTMLNode("tr");
    row.addChild(
        "th", l10n().getString("KnownIdentitiesPage.KnownIdentities.TableHeader.Nickname"));
    row.addChild("th", l10n().getString("KnownIdentitiesPage.KnownIdentities.TableHeader.Added"));
    row.addChild("th", l10n().getString("KnownIdentitiesPage.KnownIdentities.TableHeader.Fetched"));
    row.addChild(
        "th",
        l10n().getString("KnownIdentitiesPage.KnownIdentities.TableHeader.PublishesTrustlist"));
    row.addChild(
        "th", l10n().getString("KnownIdentitiesPage.KnownIdentities.TableHeader.ScoreAndRank"));
    row.addChild(
        "th", l10n().getString("KnownIdentitiesPage.KnownIdentities.TableHeader.TrustAndComment"));
    row.addChild("th")
        .addChild(
            new HTMLNode(
                "input",
                new String[] {"type", "name", "value"},
                new String[] {
                  "submit",
                  "SetTrust",
                  l10n().getString("KnownIdentitiesPage.KnownIdentities.Table.UpdateTrustButton")
                }));
    row.addChild(
        "th", l10n().getString("KnownIdentitiesPage.KnownIdentities.TableHeader.Trusters"));
    row.addChild(
        "th", l10n().getString("KnownIdentitiesPage.KnownIdentities.TableHeader.Trustees"));
    row.addChild("th", l10n().getString("KnownIdentitiesPage.KnownIdentities.TableHeader.Edition"));
    row.addChild(
        "th", l10n().getString("KnownIdentitiesPage.KnownIdentities.TableHeader.EditionHint"));

    return row;
  }