001/*
002 *  Download.java
003 *  $Id: Download.java 1226 2018-03-03 06:21:05Z tgutwin $
004 *  $HeadURL$
005 *  $Revision$
006 *  $LastChangedDate: 2018-03-02 22:21:05 -0800 (Fri, 02 Mar 2018) $
007 *  $LastChangedBy: tgutwin $
008 *  Copyright (c) 2002-2005 Tom B. Gutwin P.Eng.
009 *
010 *  This program is free software; you can redistribute it and/or
011 *  modify it under the terms of the GNU General Public License
012 *  as published by the Free Software Foundation; either version 2
013 *  of the License, or any later version.
014 *
015 *  This program is distributed in the hope that it will be useful,
016 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
017 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
018 *  GNU General Public License for more details.
019 *
020 *  You should have received a copy of the GNU General Public License
021 *  along with this program; if not, write to the Free Software
022 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
023 */
024package ca.bc.webarts.servlet;
025
026import ca.bc.webarts.widgets.AstroVersion;
027
028import ca.bc.webarts.tools.Log;
029import com.oreilly.servlet.ParameterParser;
030
031import com.oreilly.servlet.ServletUtils;
032
033import java.io.BufferedOutputStream;
034import java.io.IOException;
035import java.io.File;
036import java.io.FileNotFoundException;
037import java.io.FileWriter;
038import java.net.InetAddress;
039import java.net.UnknownHostException;
040import java.util.*;
041import javax.activation.*;
042import javax.mail.*;
043import javax.mail.internet.*;
044
045import javax.servlet.*;
046import javax.servlet.http.*;
047
048
049/**
050 *  This is a servlet that provides Logged downloading of a resource.
051 *  http://www.webarts.bc.ca/Download?resource=http://hobbes.nmsu.edu/pub/java/mmedia/AutoUpdate_jOggPlayer110b.zip
052 *  <p>
053 *
054 *  For more information on servlets, see <a
055 *  href="http://java.sun.com/products/java-server/servlets/index.html">
056 *  http://java.sun.com/products/java-server/servlets/index.html</a>
057 *
058 * @author     tgutwin
059 * @created    July 17, 2002
060 */
061public class Download extends HttpServlet
062{
063  // implements SingleThreadModel
064
065  /*
066   *  <!-- configure Download Servlet with init parameters -->
067   *  <servlet servlet-name='Download' servlet-class='ca.bc.webarts.servlet.Download'>
068   *  <init-param info='A tool to download a resource and log its download.'/>
069   *  <init-param serverUrl='Aurora1.webarts.bc.ca'/>
070   *  <init-param serverPort='80'/>
071   *  <init-param downloadLogFilename='log/downloadLog.txt'/>
072   *  </servlet>
073   *  <servlet-mapping url-pattern='/Download' servlet-name='Download'/>
074   */
075  /**  Description of the Field */
076  private final static String SYSTEM_FILE_SEPERATOR = File.separator;
077  /**  Version String.  */
078  private final static String SERVLET_VERSION = "a0.4";
079
080  /**  Build String. (yymmddhhss)  */
081  private final static String BUILD_TAG = "0503051701";
082
083  /**  Description of the Field */
084  private static Calendar calendar_ = Calendar.getInstance();
085
086  /**  This servers name.  */
087  private static String webServerHostName_ = "";
088  /**  Log File Name.  */
089  private final static String DEFAULT_LOG_FILE =
090      SYSTEM_FILE_SEPERATOR +
091      "var" +
092      SYSTEM_FILE_SEPERATOR +
093      "log" +
094      SYSTEM_FILE_SEPERATOR +
095      calendar_.get(calendar_.YEAR) + "-" +
096      calendar_.get(calendar_.DAY_OF_YEAR) + "_" +
097      "DownloadLoggerLog.txt";
098
099  /**  Download Log File Name.  */
100  private final static String DEFAULT_DOWNLOAD_LOG_FILE =
101      SYSTEM_FILE_SEPERATOR +
102      "var" +
103      SYSTEM_FILE_SEPERATOR +
104      "log" +
105      SYSTEM_FILE_SEPERATOR +
106      calendar_.get(calendar_.YEAR) + "-" +
107      calendar_.get(calendar_.DAY_OF_YEAR) + "_" +
108      "DownloadLog.txt";
109
110  /**  Description of the Field */
111  String title_ = "";
112  /**  The url to the resource to download. */
113  String downloadUrl_ = "";
114  /**
115    *  This gets assigned if a Subversion repository based file is requested:
116    *  it will hold the URL for the repo.
117    **/
118  String svnRepoURL_ = "";
119  /**  This gets assigned if a Subversion repository based file is requested:
120    *  it will hold the sub dir to visit to retrieve the file. */
121  String svnDir_ = "";
122  /**  This gets assigned if a Subversion repository based file is requested:
123    *  it will hold the file to retrieve. */
124  String svnFile_ = "";
125  /**  This gets assigned if a Subversion repository based file is requested:
126    *  it will hold the revision number for the file to retrieve. */
127  String svnFileRev_ = "";
128  /**  This gets assigned if a Subversion repository based file is requested:
129    *  to be gzipped. */
130  boolean svnFileGzip_ = false;
131  /**
132   *  The html header string (&lt;head&gt;) that is included on all folder view
133   *  pages. It is the place where any javascript fuction are included.
134   */
135  String scriptHead_ =
136      "<HEAD>\n" +
137      "<META HTTP-EQUIV=\"Content-Type\" " +
138      "CONTENT=\"text/html;CHARSET=iso-8859-1\">\n" +
139      "<META HTTP-EQUIV=\"refresh\" content=\"1;URL=" +
140      downloadUrl_ + "\">" +
141      "<TITLE>" + title_ + "</TITLE>\n" +
142      "<SCRIPT LANGUAGE=\"JavaScript\">\n" +
143      "<!-- Begin\nvar compose_window = null;\n" +
144      "function NewWindow(mypage, myname, w, h, scroll)\n{\n  " +
145      "  var winl = (screen.width - w) / 2;\n  " +
146      "  var wint = (screen.height - h) / 2;\n  " +
147      "  winprops = 'height='+h+',width='+w+',top='+wint+',left='+winl+'," +
148      "  scrollbars='+scroll+',resizable'\n  " +
149      "  win = window.open('', myname, winprops)\n  compose_window = win;\n  " +
150      "  win.document.open();\n  win.document.clear;\n  " +
151      "  win.document.write(mypage)\n  " +
152      "  if (parseInt(navigator.appVersion) >= 4) {\n" +
153      "    win.window.focus();\n" +
154      "  }\n  " +
155      "}\n\n" +
156      "//  End -->\n" +
157      "</script>\n" +
158      "</HEAD>\n";
159
160  /**  Body Content.  */
161  String bodyContent_ = "<BODY>" +
162      "" +
163      "</BODY>";
164
165  /**  The default download log filename */
166  String initDownloadLogFilename_ = DEFAULT_DOWNLOAD_LOG_FILE;
167
168  /**  Description of the Field */
169  File downloadLogFile_ = null;
170
171  /**  The debug logger.  */
172  private static Log log = null;
173  // new Log(Log.CONSOLE, Log.FULL);
174
175
176  /**
177   *  This method handles the "GET" submission and goes and gets the
178   *  download file.
179   *
180   * @param  req                   Description of the Parameter
181   * @param  res                   Description of the Parameter
182   * @exception  ServletException  Description of the Exception
183   * @exception  IOException       Description of the Exception
184   */
185  public void doGet(HttpServletRequest req, HttpServletResponse res)
186    throws ServletException, IOException
187  {
188    final String methodName = "doGet";
189    log.startMethod(methodName);
190    // get the session
191    //HttpSession ssn = req.getSession(true);
192    ParameterParser parser = new ParameterParser(req);
193
194    String logFileName = parser.getStringParameter("logfile", DEFAULT_LOG_FILE);
195    if (log == null)
196    {
197      System.out.println("TBGDEBUG: Creating Log File:" + logFileName);
198      log = Log.createLog(Log.FULL, logFileName);
199    }
200    downloadUrl_ = parser.getStringParameter("resource", "");
201    svnRepoURL_ = parser.getStringParameter("repo", "");
202    svnDir_ = parser.getStringParameter("dir", "");
203    svnFile_ = parser.getStringParameter("file", "");
204    svnFileRev_ = parser.getStringParameter("rev", "");
205    svnFileGzip_ = parser.getBooleanParameter("gzip", false);
206
207    log("DEBUG: DownloadLogFile: "+downloadLogFile_);
208    if (!downloadUrl_.equals(""))
209    {
210      doDownload(req, res);
211    }
212    else if (!svnRepoURL_.equals("") &&
213             !svnDir_.equals("") &&
214             !svnFile_.equals(""))
215    {
216      streamSVNBytes(req, res, svnFileGzip_);
217    }
218    else
219    {
220      ServletOutputStream out = res.getOutputStream();
221      res.setContentType("text/html");
222      out.println("<html>\n");
223      out.println("<head>\n");
224      out.println("<META HTTP-EQUIV=\"refresh\" content=\"2;URL=\"javascript:history.go(-2);\">\n");
225      out.println("</head>\n");
226      out.println("<body>\n");
227      out.println("Incorrect Download parameters:<br />");
228      out.println("  resource = "+downloadUrl_+"<br />");
229      out.println("  repo     = "+svnRepoURL_+"<br />");
230      out.println("  dir      = "+svnDir_+"<br />");
231      out.println("  file     = "+svnFile_+"<br />");
232      out.println("");
233      out.println("\n</body>\n</html>");
234    }
235
236    log.endMethod();
237  }
238
239
240  /**
241   *  Gets the ServletInfo attribute of the JavaMailServlet object
242   *
243   * @return    The ServletInfo value
244   */
245  public String getServletInfo()
246  {
247    final String methodName = "getServletInfo";
248    log.startMethod(methodName);
249
250    log.endMethod();
251    return "WebARTS Design download servlet. Version:" + SERVLET_VERSION +
252        "  Build:" + BUILD_TAG;
253  }
254
255
256  /**
257   * The one time servlet init stuff goes here.
258   **/
259  public void init()
260  {
261    System.out.println("Initializing webarts.servlet.Download");
262
263    // First get our Debug Logger running
264    String initDebugLog = getInitParameter("debugLogFilename").trim();
265    if (initDebugLog == null ||
266        initDebugLog.equals(""))
267    {
268      initDebugLog = DEFAULT_LOG_FILE;
269    }
270    if (log == null)
271    {
272      System.out.println("TBGDEBUG: Creating Log File: " + initDebugLog);
273      log = Log.createLog(Log.FULL, initDebugLog);
274    }
275
276    // Now on with the Servlet Init
277    final String methodName = "init";
278    log.startMethod(methodName);
279    String initServer = getInitParameter("serverUrl");
280    String initServerPort = getInitParameter("serverPort");
281    initDownloadLogFilename_ = getInitParameter("downloadLogFilename").trim();
282    String portNum = "";
283
284    if (initDownloadLogFilename_ == null ||
285        initDownloadLogFilename_.equals(""))
286    {
287      initDownloadLogFilename_ = DEFAULT_DOWNLOAD_LOG_FILE;
288      //downloadLogFile_ = new File(initDownloadLogFilename_);
289    }
290    if (initServerPort != null && !initServerPort.equals(""))
291    {
292      portNum = ":" + initServerPort;
293    }
294    if (initServer != null && !initServer.equals(""))
295    {
296      webServerHostName_ = initServer + portNum;
297    }
298    else
299    {
300      try
301      {
302        webServerHostName_ = InetAddress.getLocalHost().getHostName();
303      }
304      catch (UnknownHostException ex)
305      {
306        webServerHostName_ = "localhost";
307      }
308    }
309
310    log.debug("Download Logging File = "+initDownloadLogFilename_);
311    log.endMethod();
312  }
313
314
315  /**  Override to close the Log * */
316  public void destroy()
317  {
318    super.destroy();
319    final String methodName = "destroy";
320    if (log != null)
321    {
322      log.startMethod(methodName);
323      log.endMethod();
324      log.close();
325    }
326  }
327
328
329  /**
330   *  This method handles the "POST" submission.
331   *
332   * @param  req                   Description of Parameter
333   * @param  res                   Description of Parameter
334   * @exception  ServletException  Description of Exception
335   * @exception  IOException       Description of Exception
336   */
337  public void doPost(HttpServletRequest req, HttpServletResponse res)
338    throws ServletException, IOException
339  {
340    final String methodName = "doPost";
341    log.startMethod(methodName);
342    log.endMethod();
343  }
344
345
346  /**
347   *  This method goes and performs the actual download of a resource file.
348   *
349   * @param  req                   Description of Parameter
350   * @param  res                   Description of Parameter
351   * @exception  ServletException  Description of Exception
352   * @exception  IOException       Description of Exception
353   */
354  private void doDownload(HttpServletRequest req, HttpServletResponse res)
355               throws ServletException, IOException
356  {
357    final String methodName = "doDownload";
358    log.startMethod(methodName);
359
360    log.debug("Attempting download of " + downloadUrl_);
361    ServletOutputStream out = res.getOutputStream();
362    res.setContentType("text/html");
363    out.println("<html>\n");
364    out.println(getHead());
365    out.println(getDownloadBody());
366    out.println("</html>");
367
368    logTheDownload(req, downloadUrl_);
369
370    log.endMethod();
371  }
372
373
374  /**
375   *  This method goes and performs the download/streaming of the svn file.
376   *
377   * @param  req                   Description of Parameter
378   * @param  res                   Description of Parameter
379   * @exception  ServletException  Description of Exception
380   * @exception  IOException       Description of Exception
381   */
382  private void streamSVNBytes(HttpServletRequest req, HttpServletResponse res, boolean compressGzip)
383               throws ServletException, IOException
384  {
385    final String methodName = "streamSVNBytes";
386    log.startMethod(methodName);
387
388    AstroVersion astroVersion = new AstroVersion();
389    if (!svnDir_.endsWith("/")) svnDir_ = svnDir_+"/";
390    String svnResource = svnRepoURL_+svnDir_+svnFile_;
391    log.debug("Attempting Subversion stream of " + svnResource);
392    ServletOutputStream out = res.getOutputStream();
393    // Get the "Accepting-Encoding" header from the HTTP request.
394    // Note that request is an HttpServletRequest instance
395    String encoding = req.getHeader("Accept-Encoding");
396    boolean supportsGzip =false;
397    // Now, check to see if the browser supports the GZIP compression
398    if (encoding != null)
399    {
400      if (encoding.toLowerCase().indexOf("gzip") > -1)
401        supportsGzip = true;
402    }
403    java.io.OutputStream outStream = null;
404    if (compressGzip || supportsGzip)
405    {
406      outStream = new java.util.zip.GZIPOutputStream(out);
407    }
408    else
409    {
410      outStream = new BufferedOutputStream(out);
411    }
412    try
413    {
414      byte[] revCatBytes = astroVersion.getFileBytes(svnRepoURL_,
415                                                     svnDir_+svnFile_,
416                                                     svnFileRev_ );
417      String mimeType = astroVersion.getMimeType(svnFile_);
418      int bytesToSend = revCatBytes.length;
419      if (compressGzip)
420        res.setContentType("application/x-gzip");
421      else
422      {
423        if(supportsGzip)
424          res.setHeader("Content-Encoding", "gzip");
425        res.setContentType(mimeType);
426      }
427      outStream.write(revCatBytes, 0, revCatBytes.length);
428    }
429    catch (IOException ioEx)
430    {
431      ioEx.printStackTrace();
432      res.setContentType("text/html");
433      out.println("<html>\n");
434      out.println(getHead());
435      out.println("Sorry, Problems reading the file: "+svnFile_);
436      out.println("</html>");
437    }
438    catch (Exception ex)
439    {
440      ex.printStackTrace();
441      res.setContentType("text/html");
442      out.println("<html>\n");
443      out.println(getHead());
444      out.println("Sorry, Problems getting file info: "+svnFile_);
445      out.println("</html>");
446
447    }
448    finally
449    {
450      if (outStream != null) outStream.close();
451    }
452
453    logTheDownload(req, svnResource);
454
455    log.endMethod();
456  }
457
458
459  /**
460   *  Writes the log info to the file
461   *
462   * @param  req          Description of the Parameter
463   * @param  downloadUrl  Description of the Parameter
464   */
465  private void logTheDownload(HttpServletRequest req, String downloadUrl)
466  {
467    final String methodName = "logTheDownload";
468    log.startMethod(methodName);
469    try
470    {
471      /*
472      Sat Mar 05 21:56:30 PST 2005: svn://aurora1/open/trunk/www/astroVersion/images/barg8.png:
473      warp2.webarts.bc.ca (10.0.0.252): Host=www.webarts.bc.ca, User-Agent=Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20041107 Firefox/1.0,
474      */
475      /*
476      209.89.88.215 - - [21/Feb/2005:00:00:14 -0800] "GET /favicon.ico HTTP/1.0" 404 1224 "-" "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.5) Gecko/20041107 Firefox/1.0"
477      */
478      // Instantiate the Log File Writer
479      FileWriter fo = new FileWriter(initDownloadLogFilename_, true);
480
481      // Get all the required client/request info that will be logged
482      java.util.Enumeration headerNamesEnum = req.getHeaderNames();
483      String currName = "";
484      String currIp = req.getRemoteAddr();
485      InetAddress inetAddr = InetAddress.getByName(currIp);
486      String currHostname = inetAddr.getHostName();
487
488      // Build the Log Entry
489      StringBuffer logEntry = new StringBuffer();
490      logEntry.append(currIp + " - - ");
491      logEntry.append("["+(new java.util.Date()).toString() + "] ");
492      logEntry.append("\"GET "+downloadUrl + " HTTP/1.0\" 200 9999 ");
493
494      while (headerNamesEnum.hasMoreElements())
495      {
496        currName = (String) headerNamesEnum.nextElement();
497        if (currName.equals("User-Agent") ||
498            currName.equals("Referer")) // host is also valid
499        {
500          //logEntry.append(currName);
501          //logEntry.append("=");
502          logEntry.append(" \""+req.getHeader(currName));
503          logEntry.append("\"");
504        }
505      }
506      logEntry.append("\n");
507      currName = logEntry.toString();
508      fo.write(currName);
509      fo.close();
510      fo = null;
511    }
512    catch (java.io.FileNotFoundException fnfe)
513    {
514      log.minor("Download Log File Not Found. " + initDownloadLogFilename_);
515    }
516    catch (java.io.IOException ioe)
517    {
518      log.minor("Log File IO Exception. " + initDownloadLogFilename_);
519    }
520
521    log.endMethod();
522  }
523
524
525  /**
526   *  Gets the head attribute of the Download object
527   *
528   * @return    The head value
529   */
530  private String getHead()
531  {
532    return "<HEAD>\n" +
533        "<META HTTP-EQUIV=\"Content-Type\" " +
534        "CONTENT=\"text/html;CHARSET=iso-8859-1\">\n" +
535        "<META HTTP-EQUIV=\"refresh\" content=\"1;URL=" +
536        downloadUrl_ + "\">" +
537        "<TITLE>" + title_ + "</TITLE>\n" +
538        "<SCRIPT LANGUAGE=\"JavaScript\">\n" +
539        "<!-- Begin\nvar compose_window = null;\n" +
540        "function NewWindow(mypage, myname, w, h, scroll)\n{\n  " +
541        "  var winl = (screen.width - w) / 2;\n  " +
542        "  var wint = (screen.height - h) / 2;\n  " +
543        "  winprops = 'height='+h+',width='+w+',top='+wint+',left='+winl+'," +
544        "  scrollbars='+scroll+',resizable'\n  " +
545        "  win = window.open('', myname, winprops)\n  compose_window = win;\n  " +
546        "  win.document.open();\n  win.document.clear;\n  " +
547        "  win.document.write(mypage)\n  " +
548        "  if (parseInt(navigator.appVersion) >= 4) {\n" +
549        "    win.window.focus();\n" +
550        "  }\n  " +
551        "}\n\n" +
552        "//  End -->\n" +
553        "</script>\n" +
554        "</HEAD>\n";
555  }
556
557
558  /**
559   *  Gets the body attribute of the Download object
560   *
561   * @return    The body value
562   */
563  private String getDownloadBody()
564  {
565    return "<BODY>" +
566        "You should automatically start the download of the file:<BR>" +
567        "<A href=\"" + downloadUrl_ + "\">" + downloadUrl_ + "</A>" +
568        "<p><b><a href=\"javascript:history.go(-1)\">&laquo;Back to Previous Window</a>" +
569        "</b>\n</body>";
570  }
571}
572