@Override
 public void handle(HttpExchange t) throws IOException {
   if (RemoteUtil.deny(t)) {
     throw new IOException("Access denied");
   }
   String id = RemoteUtil.getId("thumb/", t);
   LOGGER.trace("web thumb req " + id);
   if (id.contains("logo")) {
     RemoteUtil.sendLogo(t);
     return;
   }
   RootFolder root = parent.getRoot(RemoteUtil.userName(t), t);
   if (root == null) {
     LOGGER.debug("weird root in thumb req");
     throw new IOException("Unknown root");
   }
   final DLNAResource r = root.getDLNAResource(id, root.getDefaultRenderer());
   if (r == null) {
     // another error
     LOGGER.debug("media unknown");
     throw new IOException("Bad id");
   }
   InputStream in;
   if (!configuration.isShowCodeThumbs() && !r.isCodeValid(r)) {
     // we shouldn't show the thumbs for coded objects
     // unless the code is entered
     in = r.getGenericThumbnailInputStream(null);
   } else {
     r.checkThumbnail();
     in = r.getThumbnailInputStream();
   }
   Headers hdr = t.getResponseHeaders();
   hdr.add("Content-Type", r.getThumbnailContentType());
   hdr.add("Accept-Ranges", "bytes");
   hdr.add("Connection", "keep-alive");
   t.sendResponseHeaders(200, in.available());
   OutputStream os = t.getResponseBody();
   LOGGER.trace("input is {} output is {}", in, os);
   RemoteUtil.dump(in, os);
 }
  @Override
  public void handle(HttpExchange t) throws IOException {
    if (RemoteUtil.deny(t)) {
      throw new IOException("Access denied");
    }
    RootFolder root = parent.getRoot(RemoteUtil.userName(t), t);
    if (root == null) {
      throw new IOException("Unknown root");
    }
    Headers h = t.getRequestHeaders();
    for (String h1 : h.keySet()) {
      LOGGER.debug("key " + h1 + "=" + h.get(h1));
    }
    String id = RemoteUtil.getId(path, t);
    id = RemoteUtil.strip(id);
    RendererConfiguration r = render;
    if (render == null) {
      r = root.getDefaultRenderer();
    }
    DLNAResource dlna = root.getDLNAResource(id, r);
    if (dlna == null) {
      // another error
      LOGGER.debug("media unkonwn");
      throw new IOException("Bad id");
    }
    if (!dlna.isCodeValid(dlna)) {
      LOGGER.debug("coded object with invalid code");
      throw new IOException("Bad code");
    }
    DLNAMediaSubtitle sid = null;
    long len = dlna.length();
    Range range = RemoteUtil.parseRange(t.getRequestHeaders(), len);
    String mime = root.getDefaultRenderer().getMimeType(dlna.mimeType());
    // DLNAResource dlna = res.get(0);
    WebRender render = (WebRender) r;
    DLNAMediaInfo m = dlna.getMedia();
    if (m == null) {
      m = new DLNAMediaInfo();
      dlna.setMedia(m);
    }
    if (mime.equals(FormatConfiguration.MIMETYPE_AUTO) && m.getMimeType() != null) {
      mime = m.getMimeType();
    }
    int code = 200;
    dlna.setDefaultRenderer(r);
    if (dlna.getFormat().isVideo()) {
      if (flash) {
        mime = "video/flash";
      } else if (!RemoteUtil.directmime(mime) || RemoteUtil.transMp4(mime, m)) {
        mime = render != null ? render.getVideoMimeType() : RemoteUtil.transMime();
        if (FileUtil.isUrl(dlna.getSystemName())) {
          dlna.setPlayer(new FFmpegWebVideo());
        } else {
          dlna.setPlayer(new FFMpegVideo());
        }
        // code = 206;
      }
      if (PMS.getConfiguration().getWebSubs()
          && dlna.getMediaSubtitle() != null
          && dlna.getMediaSubtitle().isExternal()) {
        // fetched on the side
        sid = dlna.getMediaSubtitle();
        dlna.setMediaSubtitle(null);
      }
    }

    if (!RemoteUtil.directmime(mime) && dlna.getFormat().isAudio()) {
      dlna.setPlayer(new FFmpegAudio());
      code = 206;
    }

    m.setMimeType(mime);
    LOGGER.debug("dumping media " + mime + " " + dlna);
    InputStream in = dlna.getInputStream(range, root.getDefaultRenderer());
    Headers hdr = t.getResponseHeaders();
    hdr.add("Content-Type", mime);
    hdr.add("Accept-Ranges", "bytes");
    if (range != null) {
      long end = range.asByteRange().getEnd();
      long start = range.asByteRange().getStart();
      String rStr = start + "-" + end + "/*";
      hdr.add("Content-Range", "bytes " + rStr);
      if (start != 0) {
        code = 206;
      }
    }
    hdr.add("Server", PMS.get().getServerName());
    hdr.add("Connection", "keep-alive");
    t.sendResponseHeaders(code, 0);
    OutputStream os = t.getResponseBody();
    render.start(dlna);
    if (sid != null) {
      dlna.setMediaSubtitle(sid);
    }
    RemoteUtil.dump(in, os, render);
  }