// we aren't really going to show any directories, just display our shared media
  private String listDirectory(String strUri, java.io.File f) {

    Uri uri = Uri.parse(strUri);

    int startIdx = 0;
    int length = 10;

    // String heading = "Directory " + uri;
    String heading = "CameraV Web Share";
    StringBuilder msg =
        new StringBuilder(
            "<html><head><title>"
                + heading
                + "</title>"
                + "<link rel=\"stylesheet\" type=\"text/css\" href=\"/style.css\"/>"
                + "</head><body><h2>"
                + heading
                + "</h2>");

    if (mListMedia != null && mListMedia.size() > 0) {

      if (mListMedia.size() > 0) {
        msg.append("<section class=\"files\">");
        for (int i = startIdx; i < (startIdx + length) && i < mListMedia.size(); i++) {

          IMedia media = mListMedia.get(i);

          String pathMedia = media._id;

          StringBuffer desc = new StringBuffer();
          desc.append("<b>").append(media.dcimEntry.fileAsset.name).append("</b><br/><br/>");
          try {
            desc.append("<pre>").append(media.buildSummary(mContext, null)).append("</pre>");

          } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
          } catch (InstantiationException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
          } catch (IllegalAccessException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
          }

          msg.append("<div class=\"thumbnailBorder\">");

          msg.append("<a href=\"")
              .append(encodeUri(pathMedia))
              .append("\"><img src=\"")
              .append(encodeUri(pathMedia + ".thumb"))
              .append("\"/></a><br/>");

          msg.append("<a href=\"").append(encodeUri(pathMedia)).append("\">Download Media</a>");
          msg.append(" | ");
          msg.append("<a href=\"")
              .append(encodeUri(pathMedia + ".j3m"))
              .append("\">Download J3M</a> ");
          msg.append(" | ");
          msg.append("<a href=\"")
              .append(encodeUri(pathMedia + ".csv"))
              .append("\">Download CSV</a>");
          msg.append("<br/><br/>");

          File curFile = new File(pathMedia);
          long len = curFile.length();
          msg.append("<div class=\"desc\">");
          msg.append(desc).append(" (");
          if (len < 1024) {
            msg.append(len).append(" bytes");
          } else if (len < 1024 * 1024) {
            msg.append(len / 1024).append(".").append(len % 1024 / 10 % 100).append(" KB");
          } else {
            msg.append(len / (1024 * 1024))
                .append(".")
                .append(len % (1024 * 1024) / 10 % 100)
                .append(" MB");
          }
          msg.append(")</div></div>");
        }

        msg.append("</section>");
      }
    }

    msg.append("</body></html>");
    return msg.toString();
  }
  private Response respond(Map<String, String> headers, String uri) {

    // Remove URL arguments
    uri = uri.trim().replace(File.separatorChar, '/');
    if (uri.indexOf('?') >= 0) {
      uri = uri.substring(0, uri.indexOf('?'));
    }

    // Prohibit getting out of current directory
    if (uri.startsWith("src/main") || uri.endsWith("src/main") || uri.contains("../")) {
      return createResponse(
          Response.Status.FORBIDDEN,
          NanoHTTPD.MIME_PLAINTEXT,
          "FORBIDDEN: Won't serve ../ for security reasons.");
    }

    // Browsers get confused without '/' after the directory, send a redirect.
    java.io.File f = null;

    if (uri.length() > 0) {
      String[] uriParts = uri.split("\\.");

      String mediaId = uriParts[0].substring(1);
      IMedia media = getMediaFile(mediaId);

      if (media != null) {
        if (uriParts.length == 1) {
          if (media.dcimEntry.fileAsset.source == Storage.Type.IOCIPHER)
            f = new info.guardianproject.iocipher.File(media.dcimEntry.fileAsset.path);
          else // if file system
          f = new java.io.File(media.dcimEntry.fileAsset.path);
        } else if (uriParts[1].equals("thumb")) {
          if (media.dcimEntry.fileAsset.source == Storage.Type.IOCIPHER)
            f = new info.guardianproject.iocipher.File(media.dcimEntry.thumbnail.path);
          else // if file system
          f = new java.io.File(media.dcimEntry.thumbnail.path);
        } else if (uriParts[1].equals("j3m")) {
          String j3m;
          try {
            j3m = media.buildJ3M(mContext, false, null);

            String mime = "text/plain";
            InputStream is = new StringBufferInputStream(j3m);
            Response res = createResponse(Response.Status.OK, mime, is);
            res.addHeader("Content-Length", "" + j3m.length());
            return res;

          } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
          } catch (InstantiationException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
          } catch (IllegalAccessException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
          }

        } else if (uriParts[1].equals("csv")) {
          String j3m;
          try {
            j3m = media.buildCSV(mContext, null);

            String mime = "text/plain";
            InputStream is = new StringBufferInputStream(j3m);
            Response res = createResponse(Response.Status.OK, mime, is);
            res.addHeader("Content-Length", "" + j3m.length());
            return res;

          } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
          } catch (InstantiationException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
          } catch (IllegalAccessException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
          }
        }

      } else {
        boolean canServeUri = false;
        File homeDir = null;
        List<File> roots = getRootDirs();
        for (int i = 0; !canServeUri && i < roots.size(); i++) {
          homeDir = roots.get(i);
          canServeUri = canServeUri(uri, homeDir);
        }
        if (!canServeUri) {
          return createResponse(
              Response.Status.NOT_FOUND, NanoHTTPD.MIME_PLAINTEXT, "Error 404, file not found.");
        }

        f = new info.guardianproject.iocipher.File(homeDir, uri);
      }
    } else {
      boolean canServeUri = false;
      File homeDir = null;
      List<File> roots = getRootDirs();
      for (int i = 0; !canServeUri && i < roots.size(); i++) {
        homeDir = roots.get(i);
        canServeUri = canServeUri(uri, homeDir);
      }
      if (!canServeUri) {
        return createResponse(
            Response.Status.NOT_FOUND, NanoHTTPD.MIME_PLAINTEXT, "Error 404, file not found.");
      }

      f = new info.guardianproject.iocipher.File(homeDir, uri);
    }

    if (f.isDirectory() && !uri.endsWith("/")) {
      uri += "/";
      Response res =
          createResponse(
              Response.Status.REDIRECT,
              NanoHTTPD.MIME_HTML,
              "<html><body>Redirected: <a href=\"" + uri + "\">" + uri + "</a></body></html>");
      res.addHeader("Location", uri);
      return res;
    }

    if (f.isDirectory()) {
      // First look for index files (index.html, index.htm, etc) and if none found, list the
      // directory if readable.
      String indexFile = findIndexFileInDirectory(f);
      if (indexFile == null) {
        if (f.canRead()) {
          // No index file, list the directory if it is readable
          return createResponse(Response.Status.OK, NanoHTTPD.MIME_HTML, listDirectory(uri, f));
        } else {
          return createResponse(
              Response.Status.FORBIDDEN,
              NanoHTTPD.MIME_PLAINTEXT,
              "FORBIDDEN: No directory listing.");
        }
      } else {
        return respond(headers, uri + indexFile);
      }
    }

    String mimeTypeForFile = getMimeTypeForFile(uri);
    WebServerPlugin plugin = mimeTypeHandlers.get(mimeTypeForFile);
    Response response = null;
    if (plugin != null) {
      response = plugin.serveFile(uri, headers, f, mimeTypeForFile);
      if (response != null && response instanceof InternalRewrite) {
        InternalRewrite rewrite = (InternalRewrite) response;
        return respond(rewrite.getHeaders(), rewrite.getUri());
      }
    } else {
      response = serveFile(uri, headers, f, mimeTypeForFile);
    }
    return response != null
        ? response
        : createResponse(
            Response.Status.NOT_FOUND, NanoHTTPD.MIME_PLAINTEXT, "Error 404, file not found.");
  }