public void updateShare(HttpServletRequest request, HttpServletResponse response)
      throws Exception {
    try {
      request = wrapRequest(request);
      User user = securityService.getCurrentUser(request);
      int id = ServletRequestUtils.getRequiredIntParameter(request, "id");

      Share share = shareService.getShareById(id);
      if (share == null) {
        error(request, response, ErrorCode.NOT_FOUND, "Shared media not found.");
        return;
      }
      if (!user.isAdminRole() && !share.getUsername().equals(user.getUsername())) {
        error(
            request, response, ErrorCode.NOT_AUTHORIZED, "Not authorized to modify shared media.");
        return;
      }

      share.setDescription(request.getParameter("description"));
      String expiresString = request.getParameter("expires");
      if (expiresString != null) {
        long expires = Long.parseLong(expiresString);
        share.setExpires(expires == 0L ? null : new Date(expires));
      }
      shareService.updateShare(share);
      XMLBuilder builder = createXMLBuilder(request, response, true).endAll();
      response.getWriter().print(builder);

    } catch (ServletRequestBindingException x) {
      error(request, response, ErrorCode.MISSING_PARAMETER, getErrorMessage(x));
    } catch (Exception x) {
      LOG.warn("Error in REST API.", x);
      error(request, response, ErrorCode.GENERIC, getErrorMessage(x));
    }
  }
  public void deleteShare(HttpServletRequest request, HttpServletResponse response)
      throws Exception {
    try {
      request = wrapRequest(request);
      User user = securityService.getCurrentUser(request);
      int id = ServletRequestUtils.getRequiredIntParameter(request, "id");

      Share share = shareService.getShareById(id);
      if (share == null) {
        error(request, response, ErrorCode.NOT_FOUND, "Shared media not found.");
        return;
      }
      if (!user.isAdminRole() && !share.getUsername().equals(user.getUsername())) {
        error(
            request, response, ErrorCode.NOT_AUTHORIZED, "Not authorized to delete shared media.");
        return;
      }

      shareService.deleteShare(id);
      XMLBuilder builder = createXMLBuilder(request, response, true).endAll();
      response.getWriter().print(builder);

    } catch (ServletRequestBindingException x) {
      error(request, response, ErrorCode.MISSING_PARAMETER, getErrorMessage(x));
    } catch (Exception x) {
      LOG.warn("Error in REST API.", x);
      error(request, response, ErrorCode.GENERIC, getErrorMessage(x));
    }
  }
  public void createShare(HttpServletRequest request, HttpServletResponse response)
      throws Exception {
    request = wrapRequest(request);
    Player player = playerService.getPlayer(request, response);

    User user = securityService.getCurrentUser(request);
    if (!user.isShareRole()) {
      error(
          request,
          response,
          ErrorCode.NOT_AUTHORIZED,
          user.getUsername() + " is not authorized to share media.");
      return;
    }

    XMLBuilder builder = createXMLBuilder(request, response, true);

    try {

      List<MediaFile> files = new ArrayList<MediaFile>();
      for (String id : ServletRequestUtils.getRequiredStringParameters(request, "id")) {
        MediaFile file = mediaFileService.getMediaFile(NumberUtils.toInt(id));
        files.add(file);
      }

      // TODO: Update api.jsp

      Share share = shareService.createShare(request, files);
      share.setDescription(request.getParameter("description"));
      long expires = ServletRequestUtils.getLongParameter(request, "expires", 0L);
      if (expires != 0) {
        share.setExpires(new Date(expires));
      }
      shareService.updateShare(share);

      builder.add("shares", false);
      builder.add("share", createAttributesForShare(share), false);

      for (MediaFile mediaFile : shareService.getSharedFiles(share.getId())) {
        File coverArt = mediaFileService.getCoverArt(mediaFile);
        AttributeSet attributes =
            restBrowseController.createAttributesForMediaFile(player, coverArt, mediaFile);
        builder.add("entry", attributes, true);
      }

      builder.endAll();
      response.getWriter().print(builder);

    } catch (ServletRequestBindingException x) {
      error(request, response, ErrorCode.MISSING_PARAMETER, getErrorMessage(x));
    } catch (Exception x) {
      LOG.warn("Error in REST API.", x);
      error(request, response, ErrorCode.GENERIC, getErrorMessage(x));
    }
  }
 private List<ShareInfo> getShareInfos(HttpServletRequest request) {
   List<ShareInfo> result = new ArrayList<ShareInfo>();
   User user = securityService.getCurrentUser(request);
   for (Share share : shareService.getSharesForUser(user)) {
     List<MediaFile> files = shareService.getSharedFiles(share.getId());
     if (!files.isEmpty()) {
       MediaFile file = files.get(0);
       result.add(
           new ShareInfo(share, file.isDirectory() ? file : mediaFileService.getParentOf(file)));
     }
   }
   return result;
 }
  private String handleParameters(HttpServletRequest request) {
    User user = securityService.getCurrentUser(request);
    for (Share share : shareService.getSharesForUser(user)) {
      int id = share.getId();

      String description = getParameter(request, "description", id);
      boolean delete = getParameter(request, "delete", id) != null;
      String expireIn = getParameter(request, "expireIn", id);

      if (delete) {
        shareService.deleteShare(id);
      } else {
        if (expireIn != null) {
          share.setExpires(parseExpireIn(expireIn));
        }
        share.setDescription(description);
        shareService.updateShare(share);
      }
    }

    return null;
  }
  public void getShares(HttpServletRequest request, HttpServletResponse response) throws Exception {
    request = wrapRequest(request);
    Player player = playerService.getPlayer(request, response);

    User user = securityService.getCurrentUser(request);
    XMLBuilder builder = createXMLBuilder(request, response, true);

    builder.add("shares", false);
    for (Share share : shareService.getSharesForUser(user)) {
      builder.add("share", createAttributesForShare(share), false);

      for (MediaFile mediaFile : shareService.getSharedFiles(share.getId())) {
        File coverArt = mediaFileService.getCoverArt(mediaFile);
        AttributeSet attributes =
            restBrowseController.createAttributesForMediaFile(player, coverArt, mediaFile);
        builder.add("entry", attributes, true);
      }

      builder.end();
    }
    builder.endAll();
    response.getWriter().print(builder);
  }
  private List<Attribute> createAttributesForShare(Share share) {
    List<Attribute> attributes = new ArrayList<Attribute>();

    attributes.add(new Attribute("id", share.getId()));
    attributes.add(new Attribute("url", shareService.getShareUrl(share)));
    attributes.add(new Attribute("username", share.getUsername()));
    attributes.add(new Attribute("created", StringUtil.toISO8601(share.getCreated())));
    attributes.add(new Attribute("visitCount", share.getVisitCount()));
    attributes.add(new Attribute("description", share.getDescription()));
    attributes.add(new Attribute("expires", StringUtil.toISO8601(share.getExpires())));
    attributes.add(new Attribute("lastVisited", StringUtil.toISO8601(share.getLastVisited())));

    return attributes;
  }
  @Override
  protected ModelAndView handleRequestInternal(
      HttpServletRequest request, HttpServletResponse response) throws Exception {

    Map<String, Object> map = new HashMap<String, Object>();

    String pathInfo = request.getPathInfo();

    if (pathInfo == null || !pathInfo.startsWith("/")) {
      response.sendError(HttpServletResponse.SC_NOT_FOUND);
      return null;
    }

    Share share = shareService.getShareByName(pathInfo.substring(1));

    if (share != null && share.getExpires() != null && share.getExpires().before(new Date())) {
      share = null;
    }

    if (share != null) {
      share.setLastVisited(new Date());
      share.setVisitCount(share.getVisitCount() + 1);
      shareService.updateShare(share);
    }

    Player player = playerService.getGuestPlayer(request);

    map.put("share", share);
    map.put("entries", getEntries(share, player));
    map.put("redirectUrl", settingsService.getUrlRedirectUrl());
    map.put("player", player.getId());

    ModelAndView result = super.handleRequestInternal(request, response);
    result.addObject("model", map);
    return result;
  }
  private List<Entry> getEntries(Share share, Player player) throws IOException {
    List<Entry> result = new ArrayList<Entry>();
    List<MusicFolder> musicFolders = settingsService.getMusicFoldersForUser(player.getUsername());

    if (share != null) {
      for (MediaFile file : shareService.getSharedFiles(share.getId(), musicFolders)) {
        if (file.getFile().exists()) {
          if (file.isDirectory()) {
            for (MediaFile child : mediaFileService.getChildrenOf(file, true, false, true)) {
              result.add(createEntry(child, player));
            }
          } else {
            result.add(createEntry(file, player));
          }
        }
      }
    }
    return result;
  }
  @Override
  protected ModelAndView handleRequestInternal(
      HttpServletRequest request, HttpServletResponse response) throws Exception {

    Map<String, Object> map = new HashMap<String, Object>();

    if (isFormSubmission(request)) {
      String error = handleParameters(request);
      map.put("error", error);
      map.put("toast", true);
    }

    ModelAndView result = super.handleRequestInternal(request, response);
    map.put("shareBaseUrl", shareService.getShareBaseUrl());
    map.put("shareInfos", getShareInfos(request));
    map.put("user", securityService.getCurrentUser(request));

    result.addObject("model", map);
    return result;
  }