private DbxClient requireDbxClient(
      HttpServletRequest request, HttpServletResponse response, User user)
      throws IOException, ServletException {
    if (user.dropboxAccessToken == null) {
      common.pageSoftError(
          response,
          "This page requires a user whose has linked to their Dropbox account.  Current user hasn't linked us to their Dropbox account.");
      return null;
    }

    return new DbxClient(
        common.getRequestConfig(request), user.dropboxAccessToken, common.dbxAppInfo.host);
  }
  public void doBrowse(HttpServletRequest request, HttpServletResponse response)
      throws IOException, ServletException {
    if (!common.checkGet(request, response)) return;
    User user = common.getLoggedInUser(request);
    if (user == null) {
      common.pageSoftError(response, "Can't do /browse.  Nobody is logged in.");
      return;
    }

    DbxClient dbxClient = requireDbxClient(request, response, user);
    if (dbxClient == null) return;

    // Make sure the path starts with '/'.  There are probably other checks we can perform...
    String path = request.getParameter("path");
    if (path == null) {
      path = "/";
    } else {
      String pathError = DbxPath.findError(path);
      if (pathError != null) {
        response.sendError(400, "Invalid path: " + jq(path) + ": " + pathError);
        return;
      }
    }

    // Get the folder listing from Dropbox.
    DbxEntry.WithChildren listing;
    try {
      listing = dbxClient.getMetadataWithChildren(path);
    } catch (DbxException ex) {
      common.handleDbxException(response, user, ex, "getMetadataWithChildren(" + jq(path) + ")");
      return;
    }

    if (listing == null) {
      response.sendError(400, "Path doesn't exist on Dropbox: " + jq(path));
    }

    FormProtection fp = FormProtection.start(response);

    response.setContentType("text/html");
    response.setCharacterEncoding("utf-8");
    PrintWriter out = new PrintWriter(new OutputStreamWriter(response.getOutputStream(), UTF8));

    out.println("<html>");
    out.println("<head><title>" + escapeHtml4(path) + "- Web File Browser</title></head>");
    out.println("<body>");
    fp.insertAntiRedressHtml(out);

    out.println("<h2>Path: " + escapeHtml4(path) + "</h2>");

    if (listing == null) {
      out.println("<p>Nothing here...</p>");
    }
    // Folder
    else if (listing.entry instanceof DbxEntry.Folder) {
      // Upload form
      out.println("<form action='/upload' method='post' enctype='multipart/form-data'>");
      fp.insertAntiCsrfFormField(out);
      out.println("<label for='file'>Upload file:</label> <input name='file' type='file'/>");
      out.println("<input type='submit' value='Upload'/>");
      out.println(
          "<input name='targetFolder' type='hidden' value='"
              + escapeHtml4(listing.entry.path)
              + "'/>");
      out.println("</form>");
      // Listing of folder contents.
      out.println("<ul>");
      for (DbxEntry child : listing.children) {
        out.println(
            "  <li><a href='/browse?path="
                + escapeHtml4(child.path)
                + "'>"
                + escapeHtml4(child.name)
                + "</a></li>");
      }
      out.println("</ul>");
    }
    // File
    else {
      DbxEntry.File f = (DbxEntry.File) listing.entry;
      out.println("<pre>");
      out.print(escapeHtml4(f.toStringMultiline()));
      out.println("</pre>");
    }

    out.println("</body>");
    out.println("</html>");

    out.flush();
  }