client/ftpd/src/se/lu/thep/coreftpd/webserver/ReadInputStreamSTDERR.java

Code
Comments
Other
Rev Date Author Line
741 10 Oct 06 olle 1 /*
1652 22 May 07 gregory 2  $Id$
741 10 Oct 06 olle 3
1916 31 Aug 07 jari 4  Copyright (C) 2006 Olle Mansson
1916 31 Aug 07 jari 5  Copyright (C) 2007 Gregory Vincic
741 10 Oct 06 olle 6
1652 22 May 07 gregory 7  This file is part of Proteios.
1652 22 May 07 gregory 8  Available at http://www.proteios.org/
741 10 Oct 06 olle 9
1652 22 May 07 gregory 10  Proteios is free software; you can redistribute it and/or modify it
1652 22 May 07 gregory 11  under the terms of the GNU General Public License as published by
1652 22 May 07 gregory 12  the Free Software Foundation; either version 2 of the License, or
1652 22 May 07 gregory 13  (at your option) any later version.
741 10 Oct 06 olle 14
1652 22 May 07 gregory 15  Proteios is distributed in the hope that it will be useful, but
1652 22 May 07 gregory 16  WITHOUT ANY WARRANTY; without even the implied warranty of
1652 22 May 07 gregory 17  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
1652 22 May 07 gregory 18  General Public License for more details.
741 10 Oct 06 olle 19
1652 22 May 07 gregory 20  You should have received a copy of the GNU General Public License
1652 22 May 07 gregory 21  along with this program; if not, write to the Free Software
1652 22 May 07 gregory 22  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
1652 22 May 07 gregory 23  02111-1307, USA.
1652 22 May 07 gregory 24  */
741 10 Oct 06 olle 25
741 10 Oct 06 olle 26 //  Xerver Free Web Server
741 10 Oct 06 olle 27 //  Copyright (C) 2002-2005 Omid Rouhani
741 10 Oct 06 olle 28 //
741 10 Oct 06 olle 29 //
741 10 Oct 06 olle 30 //  This program is free software; you can redistribute it and/or
741 10 Oct 06 olle 31 //  modify it under the terms of the GNU General Public License
741 10 Oct 06 olle 32 //  as published by the Free Software Foundation; either version 2
741 10 Oct 06 olle 33 //  of the License, or (at your option) any later version.
741 10 Oct 06 olle 34 //
741 10 Oct 06 olle 35 //  This program is distributed in the hope that it will be useful,
741 10 Oct 06 olle 36 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
741 10 Oct 06 olle 37 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
741 10 Oct 06 olle 38 //  GNU General Public License for more details.
741 10 Oct 06 olle 39 //
741 10 Oct 06 olle 40 //  You should have received a copy of the GNU General Public License
741 10 Oct 06 olle 41 //  along with this program; if not, write to the Free Software
741 10 Oct 06 olle 42 //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
741 10 Oct 06 olle 43 //
741 10 Oct 06 olle 44 //
741 10 Oct 06 olle 45 //  #############################################################
741 10 Oct 06 olle 46 //  ##  YOU CAN CONTACT THE AUTHOR (OMID ROUHANI) AT:          ##
741 10 Oct 06 olle 47 //  ##  HTTP://WWW.JAVASCRIPT.NU/XERVER/                       ##
741 10 Oct 06 olle 48 //  ##                                                         ##
741 10 Oct 06 olle 49 //  ##  IF YOUR SOFTWARE IS NOT RELEASED UNDER THE             ##
741 10 Oct 06 olle 50 //  ##  GNU GENERAL PUBLIC LICENSE (GPL),                      ##
741 10 Oct 06 olle 51 //  ##  PLEASE DO NOT COPY ANYTHING FROM THIS SOURCE CODE!!!   ##
741 10 Oct 06 olle 52 //  ##                                                         ##
741 10 Oct 06 olle 53 //  ##  FOR FULL LICENSE, PLEASE READ "XERVER LICENSE".        ##
741 10 Oct 06 olle 54 //  #############################################################
741 10 Oct 06 olle 55
1652 22 May 07 gregory 56 package se.lu.thep.coreftpd.webserver;
741 10 Oct 06 olle 57
791 23 Oct 06 olle 58 import se.lu.thep.coreftpd.common.MyInteger;
741 10 Oct 06 olle 59 import java.io.DataOutputStream;
741 10 Oct 06 olle 60 import java.io.InputStream;
741 10 Oct 06 olle 61 import java.io.OutputStream;
741 10 Oct 06 olle 62 import java.text.DateFormat;
741 10 Oct 06 olle 63 import java.util.Date;
741 10 Oct 06 olle 64
741 10 Oct 06 olle 65 /**
1652 22 May 07 gregory 66  * 
1652 22 May 07 gregory 67  * <B>About this class:</B> <BR>
1652 22 May 07 gregory 68  * This class reads the STDERR from a script and sends it to the browser. <BR>
741 10 Oct 06 olle 69  * <BR>
1652 22 May 07 gregory 70  * 
1652 22 May 07 gregory 71  * <B>How to use:</B> <BR>
1652 22 May 07 gregory 72  * <CODE>(new ReadInputStreamSTDERR(InputStream argIs, OutputStream argOs,
1652 22 May 07 gregory 73  * String argScriptLocation, NewConnection argTheNewConnection)).start();</CODE>
741 10 Oct 06 olle 74  * <BR>
741 10 Oct 06 olle 75  * <BR>
1652 22 May 07 gregory 76  * 
1652 22 May 07 gregory 77  * <B>More info:</B> <BR>
1652 22 May 07 gregory 78  * <CODE>argIs</CODE> = STDERR from a script. <BR>
741 10 Oct 06 olle 79  * <CODE>argOs</CODE> = Everything written to this will be sent to browser.
741 10 Oct 06 olle 80  * <BR>
1652 22 May 07 gregory 81  * <CODE>argScriptLocation</CODE> = Location of script as browser path
1652 22 May 07 gregory 82  * ("http://server.com/dir1/dir2/file.pl" ==> "/dir1/dir2/") <BR>
1652 22 May 07 gregory 83  * <CODE>argTheNewConnection</CODE> = this shall be the <CODE>NewConnection</CODE>
1652 22 May 07 gregory 84  * that belongs to the specific request that started RunScript. We need this to
1652 22 May 07 gregory 85  * change the value off <CODE>s_errorStatus</CODE> to "500 Internal Server
1652 22 May 07 gregory 86  * Error" and to run <CODE>addThisHitToLog()</CODE>. <BR>
741 10 Oct 06 olle 87  * <BR>
1652 22 May 07 gregory 88  * 
1652 22 May 07 gregory 89  * <B>IMPORTANT:</B> <CODE>argOs</CODE> will be closed ("<CODE>argOs.close()</CODE>")
1652 22 May 07 gregory 90  * by <CODE>ReadInputStreamSTDERR</CODE> if (and only if) there is data in
1652 22 May 07 gregory 91  * <CODE>argIs</CODE> (the script has caused an error).
1652 22 May 07 gregory 92  * 
741 10 Oct 06 olle 93  * @author <a href="http://www.JavaScript.nu/xerver/" TARGET="_top">Omid Rouhani</a>
741 10 Oct 06 olle 94  * @version 1.0
741 10 Oct 06 olle 95  */
741 10 Oct 06 olle 96
1652 22 May 07 gregory 97 final public class ReadInputStreamSTDERR extends ReadInputStream {
741 10 Oct 06 olle 98   private DataOutputStream os;
1652 22 May 07 gregory 99
1652 22 May 07 gregory 100   private final DateFormat df_dateFormat = DateFormat.getDateTimeInstance(
1652 22 May 07 gregory 101       DateFormat.LONG, DateFormat.LONG);
1652 22 May 07 gregory 102
741 10 Oct 06 olle 103   private String s_scriptLocation;
1652 22 May 07 gregory 104
741 10 Oct 06 olle 105   private NewConnection NC_theNewConnection;
1652 22 May 07 gregory 106
1652 22 May 07 gregory 107   public boolean b_hasSentData = false; // This must be public! Set this to
1652 22 May 07 gregory 108                       // true if data is found in STDERR,
1652 22 May 07 gregory 109                       // so that ReadInputStreamSTDOUT
1652 22 May 07 gregory 110                       // won't close the outputstream
1652 22 May 07 gregory 111
741 10 Oct 06 olle 112   private MyInteger whoShallRespond;
1652 22 May 07 gregory 113
741 10 Oct 06 olle 114   RunScript rs_theRunScript;
741 10 Oct 06 olle 115
1652 22 May 07 gregory 116   public ReadInputStreamSTDERR() // now we can Extend ReadInputStream without
1652 22 May 07 gregory 117                   // problem
741 10 Oct 06 olle 118   {
741 10 Oct 06 olle 119   }
741 10 Oct 06 olle 120
1652 22 May 07 gregory 121   public ReadInputStreamSTDERR(InputStream argIs, OutputStream argOs,
1652 22 May 07 gregory 122       String argScriptLocation, NewConnection argTheNewConnection,
1652 22 May 07 gregory 123       MyInteger argWhoShallRespond, RunScript argTheRunScript) {
1652 22 May 07 gregory 124     whoShallRespond = argWhoShallRespond;
1652 22 May 07 gregory 125     currentMode = INPUT_MODE;
1652 22 May 07 gregory 126     is = argIs;
1652 22 May 07 gregory 127     os = (DataOutputStream) argOs;
1652 22 May 07 gregory 128     s_scriptLocation = argScriptLocation;
1652 22 May 07 gregory 129     NC_theNewConnection = argTheNewConnection;
1652 22 May 07 gregory 130     rs_theRunScript = argTheRunScript;
741 10 Oct 06 olle 131   }
741 10 Oct 06 olle 132
2386 14 Nov 07 gregory 133   @Override
1652 22 May 07 gregory 134   public void sendDataInputMode() {
1652 22 May 07 gregory 135     try {
741 10 Oct 06 olle 136       int n;
1652 22 May 07 gregory 137       byte[] buffer = new byte[8192];
1652 22 May 07 gregory 138       boolean b_waitForData = true; // We use this to be able to check
1652 22 May 07 gregory 139                       // for data in the InputStream
1652 22 May 07 gregory 140                       // twice. If we don't find anything
1652 22 May 07 gregory 141                       // the first time we check, we check
1652 22 May 07 gregory 142                       // another time a few milliseconds
1652 22 May 07 gregory 143                       // later
1652 22 May 07 gregory 144       while (b_waitForData) {
1652 22 May 07 gregory 145         b_waitForData = false;
1652 22 May 07 gregory 146         while ((n = is.read(buffer)) != -1) {
1652 22 May 07 gregory 147           b_waitForData = true; // Do the loop only
1652 22 May 07 gregory 148           if (!b_hasSentData) {
1652 22 May 07 gregory 149             b_hasSentData = true;
741 10 Oct 06 olle 150             sendHTMLBeforeError();
741 10 Oct 06 olle 151           }
741 10 Oct 06 olle 152
1652 22 May 07 gregory 153           if (whoShallRespond.getValue() != RESPOND_STDOUT) {
1652 22 May 07 gregory 154             NewConnection.totalNumberOfBytesDownloaded += n;
1652 22 May 07 gregory 155             os.write(buffer, 0, n);
1652 22 May 07 gregory 156           } else {
1652 22 May 07 gregory 157             break; // If STDOUT is being sent right now, then we
1652 22 May 07 gregory 158                 // stop here and don't send STDERR
741 10 Oct 06 olle 159           }
1652 22 May 07 gregory 160           sleep(25); // Don't remove: without this it might happen
1652 22 May 07 gregory 161                 // that we don't read the complete output (or
1652 22 May 07 gregory 162                 // any output) from the process.
741 10 Oct 06 olle 163         }
741 10 Oct 06 olle 164         yield();
1652 22 May 07 gregory 165         sleep(75); // Don't remove: without this it might happen that
1652 22 May 07 gregory 166               // we don't read the complete output (or any output)
1652 22 May 07 gregory 167               // from the process.
741 10 Oct 06 olle 168       }
741 10 Oct 06 olle 169
1652 22 May 07 gregory 170       if (b_hasSentData) // Only send data if data has been sent to the
1652 22 May 07 gregory 171                 // stream
741 10 Oct 06 olle 172         sendHTMLAfterError();
741 10 Oct 06 olle 173
1652 22 May 07 gregory 174     } catch (Exception e) {
1652 22 May 07 gregory 175       exceptionOccured(e);
1652 22 May 07 gregory 176       if (b_showErrors)
1652 22 May 07 gregory 177         System.out
1652 22 May 07 gregory 178             .println("An error has occured @ sendDataInputMode:\n"
1652 22 May 07 gregory 179                 + e.getMessage());
1652 22 May 07 gregory 180     }
741 10 Oct 06 olle 181   }
741 10 Oct 06 olle 182
1652 22 May 07 gregory 183   private void sendHTMLBeforeError() {
741 10 Oct 06 olle 184     try {
1652 22 May 07 gregory 185       if (whoShallRespond.getValue() != RESPOND_STDOUT) {
1652 22 May 07 gregory 186         whoShallRespond.setValue(RESPOND_STDERR); // This will make
1652 22 May 07 gregory 187                               // sure so no STDERR
1652 22 May 07 gregory 188                               // is sent to the
1652 22 May 07 gregory 189                               // browser (a
1652 22 May 07 gregory 190                               // reference of
1652 22 May 07 gregory 191                               // "B_hasGotAResponse"
1652 22 May 07 gregory 192                               // is also at
1652 22 May 07 gregory 193                               // ReadInputStreamSTDERR,
1652 22 May 07 gregory 194                               // which will
1652 22 May 07 gregory 195                               // "block" it from
1652 22 May 07 gregory 196                               // sending data now)
741 10 Oct 06 olle 197
1652 22 May 07 gregory 198         NC_theNewConnection.s_errorStatus = "500 Internal Server Error";
741 10 Oct 06 olle 199         NC_theNewConnection.addThisHitToLog();
741 10 Oct 06 olle 200
1652 22 May 07 gregory 201         os
1652 22 May 07 gregory 202             .writeBytes(""
1652 22 May 07 gregory 203                 // +"HTTP/1.1 500 Internal Server Error \r\n"
1652 22 May 07 gregory 204                 + "HTTP/1.1 200 OK\r\n" // NOTE!! We are sending
1652 22 May 07 gregory 205                             // a "200 OK", so that
1652 22 May 07 gregory 206                             // Internet Explorers
1652 22 May 07 gregory 207                             // default "500 Internal
1652 22 May 07 gregory 208                             // Server Error" shall
1652 22 May 07 gregory 209                             // not be shown. This is
1652 22 May 07 gregory 210                             // actually not correct
1652 22 May 07 gregory 211                             // according to the
1652 22 May 07 gregory 212                             // HTTP-protocoll, but
1652 22 May 07 gregory 213                             // this make the user
1652 22 May 07 gregory 214                             // see a correct and
1652 22 May 07 gregory 215                             // helpful 500-error
1652 22 May 07 gregory 216                             // page.
1652 22 May 07 gregory 217                 + "Date: "
1652 22 May 07 gregory 218                 + df_dateFormat.format(new Date())
1652 22 May 07 gregory 219                 + "\r\n"
1652 22 May 07 gregory 220                 + "Server: "
1652 22 May 07 gregory 221                 + XerverKernel.getXerverName()
1652 22 May 07 gregory 222                 + "\r\n"
1652 22 May 07 gregory 223                 + "Connection: close\r\n"
1652 22 May 07 gregory 224                 + "Location: "
1652 22 May 07 gregory 225                 + s_scriptLocation
1652 22 May 07 gregory 226                 + "\r\n"
1652 22 May 07 gregory 227                 + "Content-Type: text/html\r\n\r\n"
1652 22 May 07 gregory 228                 + ""
1652 22 May 07 gregory 229                 + "<HTML>"
1652 22 May 07 gregory 230                 + "<HEAD>"
1652 22 May 07 gregory 231                 + "<TITLE>Error: 500 Internal Server Error</TITLE>"
1652 22 May 07 gregory 232                 + "</HEAD>"
1652 22 May 07 gregory 233                 + "<BODY BGCOLOR=\"white\" TEXT=\"black\">"
1652 22 May 07 gregory 234                 + "<TABLE BORDER=0 WIDTH=500 CELLPADDING=0 CELLSPACING=0>"
1652 22 May 07 gregory 235                 + "<TR><TD>"
1652 22 May 07 gregory 236                 + "<FONT FACE=\"arial,verdana\">"
1652 22 May 07 gregory 237                 + "<CENTER><H2>Error: 500 Internal Server Error</H2></CENTER>"
1652 22 May 07 gregory 238                 + "</FONT>"
1652 22 May 07 gregory 239                 + "<P>"
1652 22 May 07 gregory 240                 + "<FONT SIZE=\"-1\" FACE=\"arial,verdana\">"
1652 22 May 07 gregory 241                 + "An error occured when the script was executed."
1652 22 May 07 gregory 242                 + "<BR>"
1652 22 May 07 gregory 243                 + "The error output is:"
1652 22 May 07 gregory 244                 + "</FONT>"
1652 22 May 07 gregory 245                 + "<BR>"
1652 22 May 07 gregory 246                 + "<BR>"
1652 22 May 07 gregory 247                 + "<CENTER>"
1652 22 May 07 gregory 248                 + "<TABLE BORDER=1 CELLPADDING=2 CELLSPACING=0 BGCOLOR=\"#cccccc\">"
1652 22 May 07 gregory 249                 + "<TR><TD>" + "<PRE>");
741 10 Oct 06 olle 250       }
1652 22 May 07 gregory 251     } catch (Exception e) {
1652 22 May 07 gregory 252       exceptionOccured(e);
1652 22 May 07 gregory 253       if (b_showErrors)
1652 22 May 07 gregory 254         System.out
1652 22 May 07 gregory 255             .println("An error has occured @ sendHTMLBeforeError\n"
1652 22 May 07 gregory 256                 + e);
1652 22 May 07 gregory 257     }
741 10 Oct 06 olle 258
741 10 Oct 06 olle 259   }
741 10 Oct 06 olle 260
1652 22 May 07 gregory 261   private void sendHTMLAfterError() {
741 10 Oct 06 olle 262     try {
1652 22 May 07 gregory 263       if (whoShallRespond.getValue() == RESPOND_STDERR) {
1652 22 May 07 gregory 264         os
1652 22 May 07 gregory 265             .writeBytes(""
1652 22 May 07 gregory 266                 + "</PRE>"
1652 22 May 07 gregory 267                 + "</TD></TR>"
1652 22 May 07 gregory 268                 + "</TABLE>"
1652 22 May 07 gregory 269                 + "<BR>"
1652 22 May 07 gregory 270                 + "<BR>"
1652 22 May 07 gregory 271                 + "<BR>"
1652 22 May 07 gregory 272                 + "<HR>"
1652 22 May 07 gregory 273                 + "<FONT SIZE=\"-1\" FACE=\"arial,verdana\">"
1652 22 May 07 gregory 274                 + "<CENTER><A HREF=\"http://www.JavaScript.nu/xerver/\">Hosted by Xerver</A></CENTER>"
1652 22 May 07 gregory 275                 + "</FONT>" + "</TD></TR>" + "</TABLE>"
1652 22 May 07 gregory 276                 + "</BODY>" + "</HTML>");
741 10 Oct 06 olle 277
741 10 Oct 06 olle 278         yield();
1652 22 May 07 gregory 279         sleep(125); // Be safe, don't close before all data has been
1652 22 May 07 gregory 280               // sent
741 10 Oct 06 olle 281
741 10 Oct 06 olle 282         os.flush();
1652 22 May 07 gregory 283         os.close(); // os MUST be closed, or the browser will wait for
1652 22 May 07 gregory 284               // more data. (with netscape: the stop-button will
1652 22 May 07 gregory 285               // be "clickable" as the browser waits for the
1652 22 May 07 gregory 286               // server to write more data or to close the
1652 22 May 07 gregory 287               // connection (we close the connection with this
1652 22 May 07 gregory 288               // line).
741 10 Oct 06 olle 289       }
1652 22 May 07 gregory 290     } catch (Exception e) {
1652 22 May 07 gregory 291       exceptionOccured(e);
1652 22 May 07 gregory 292       if (b_showErrors)
1652 22 May 07 gregory 293         System.out
1652 22 May 07 gregory 294             .println("An error has occured @ sendHTMLAfterError\n"
1652 22 May 07 gregory 295                 + e);
1652 22 May 07 gregory 296     }
741 10 Oct 06 olle 297   }
741 10 Oct 06 olle 298
1652 22 May 07 gregory 299   private void exceptionOccured(Exception e) {
741 10 Oct 06 olle 300     rs_theRunScript.killProcess();
741 10 Oct 06 olle 301   }
741 10 Oct 06 olle 302 }