/**
 *================================================================================
 * THIS SOFTWARE IS PROVIDED BY JAVAZOOM "AS IS".
 * JAVAZOOM DISCLAIMS ANY OTHER WARRANTIES, EXPRESS OR IMPLIED, INCLUDING, BUT NOT
 * LIMITED TO, ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
 * PURPOSE AND NONINFRINGEMENT.
 *================================================================================
 */
package javazoom.download;

import java.io.IOException;
import java.util.Properties;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import javazoom.download.util.Debug;
import javazoom.download.util.Keys;

/**
 * This class implements a servlet to download files through DownloadImpl.
 */
public class DownloadServlet extends HttpServlet
{

  private DownloadImpl downloader = null;

  /**
   * Initializes DownloadServlet.
   * <br>
   * Instanciates DownloadBean with scope application.<br>
   * Instanciates DownloadImpl.<br>
   * @throws ServletException
   */
  public void init() throws ServletException
  {
    String configfile = getInitParameter("configfile");
    String configPath = getInitParameter("configpath");
    if (configPath == null) configPath = (getServletContext().getRealPath("/WEB-INF"));
    try
    {
      if ((configfile == null) || (configPath == null))
      {
        if (configfile == null) Debug.getInstance().trace(Debug.PANIC,getClass().getName()+": Please setup configfile init parameter in web.xml");
        if (configPath == null) Debug.getInstance().trace(Debug.PANIC,getClass().getName()+": Please setup configpath init parameter in web.xml");
      }
      else downloader = new DownloadImpl(configPath,configfile);
    }
    catch (Exception ex)
    {
      ex.printStackTrace();
    }
  }

  /**
   * Processes HTTP Get.
   * @param request incoming user's request.
   * @param response user's response
   * @throws ServletException
   * @throws IOException
   */
  public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
  {
    performDownload(request, response);
  }

  /**
   * Processes HTTP Post.
   * @param request incoming user's request.
   * @param response user's response
   * @throws ServletException
   * @throws IOException
   */
  public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
  {
    performDownload(request, response);
  }

  /**
   * Processes the download.
   * @param request HttpRequest from browser
   * @param response HttpResponse sent to browser
   * @throws ServletException
   * @throws IOException
   */
  public void performDownload(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
  {
    String filename = request.getParameter(Keys.FILENAMEPARAMETER);
    String uid = request.getParameter(Keys.IDPARAMETER);
    String custom = request.getParameter(Keys.CUSTOMPARAMETER);
    if (filename == null) filename = request.getPathInfo();
    if ((filename != null) && (!filename.equals("")))
    {
      String securedfilename = filename;
      if (Keys.SECUREFILENAME == true) securedfilename = checkFilename(filename);
      if (securedfilename.startsWith("/")) securedfilename = securedfilename.substring(1,securedfilename.length());
      Properties props = new Properties();
      String wwwauth = request.getHeader("Authorization");
      String remoteaddr = request.getRemoteAddr();
      if (wwwauth != null) props.setProperty("Authorization",wwwauth);
      if (remoteaddr != null) props.setProperty("RemoteAddr",remoteaddr);
      if (custom == null) custom = "";
      props.setProperty("customfield",custom);
      if (uid == null) uid = "";
      props.setProperty("uid",uid);
      if (downloader != null)
      {
        try
        {
          downloader.process(securedfilename, props, response);
        }
        catch (IOException ex)
        {
          Debug.getInstance().trace(Debug.INFO,getClass().getName()+" Download Error : "+ex.getMessage());
        }
      }
      else response.sendError(HttpServletResponse.SC_NO_CONTENT);
    }
  }

  /**
   * Removes UnSafe characters in URL (for instance %2E%2E/ means ../)
   * An Download4J malicious user could try to download files outside the downloadRoot.
   * @param filename from URL
   * @return securedFilename
   */
  public String checkFilename(String filename)
  {
    String securedFilename = filename;
    securedFilename = securedFilename.trim();
    if (Keys.BLACKLIST != null)
    {
		for (int i=0;i<Keys.BLACKLIST.length;i++)
		{
		  securedFilename = removeAllStringsAs(securedFilename,Keys.BLACKLIST[i]);
		}
    }
    return securedFilename;
  }

  /**
   * Removes unexpected String.
   * @param str
   * @param rem
   * @return
   */
  private String removeAllStringsAs(String str,String rem)
  {
    String ret = str;
    int ind = -1;
    while ((ind = ret.indexOf(rem)) != -1)
    {
      if (ind == 0)
      {
        ret = ret.substring(rem.length(),ret.length());
      }
      else
      {
        String leftchunk = ret.substring(0,ind-1);
        String rightchunk = ret.substring(ind+(rem.length()),ret.length());
        ret = leftchunk+rightchunk;
      }
    }
    return ret;
  }

  /**
   * Clean up resources.
   */
  public void destroy()
  {
  }
}