remove some codes for scheduling
[IRC.git] / Robust / src / Benchmarks / Jhttpp2 / Java / Jhttpp2ClientInputStream.java
1 /* Written and copyright 2001-2003 Benjamin Kohl.\r
2  * Distributed under the GNU General Public License; see the README file.\r
3  * This code comes with NO WARRANTY.\r
4  */\r
5 \r
6 import java.io.IOException;\r
7 import java.io.InputStream;\r
8 import java.io.BufferedInputStream;\r
9 import java.net.InetAddress;\r
10 import java.net.UnknownHostException;\r
11 \r
12 \r
13 /**\r
14         File: Jhttpp2BufferedFilterStream.java\r
15         @author Benjamin Kohl\r
16 */\r
17 public class Jhttpp2ClientInputStream extends BufferedInputStream {\r
18         private boolean filter;\r
19         private String buf;\r
20         private int lread;\r
21         /**\r
22          * The length of the header (with body, if one)\r
23          */\r
24         private int header_length;\r
25         /**\r
26          * The length of the (optional) body of the actual request\r
27          */\r
28         private int content_len;\r
29         /**\r
30          * This is set to true with requests with bodies, like "POST"\r
31          */\r
32         private boolean body;\r
33         private static Jhttpp2Server server;\r
34         private Jhttpp2HTTPSession connection;\r
35         private InetAddress remote_host;\r
36         private String remote_host_name;\r
37         private String errordescription;\r
38         private int statuscode;\r
39 \r
40         public String url;\r
41         public String method;\r
42         public int remote_port;\r
43         public int post_data_len;\r
44     public boolean ssl;\r
45 \r
46         public int getHeaderLength() {\r
47           return header_length;\r
48         }\r
49 \r
50         public InetAddress getRemoteHost() { return remote_host; }\r
51         public String getRemoteHostName() { return remote_host_name; }\r
52 \r
53     private void init() {\r
54         lread = 0;\r
55         header_length = 0;\r
56         content_len = 0;\r
57         ssl = false;\r
58         body = false;\r
59         remote_port = 0;\r
60         post_data_len = 0;\r
61     }\r
62 \r
63     public Jhttpp2ClientInputStream(Jhttpp2Server server,Jhttpp2HTTPSession connection,InputStream a) {\r
64         super(a);\r
65         init();\r
66         this.server = server;\r
67         this.connection=connection;\r
68     }\r
69         /**\r
70          * Handler for the actual HTTP request\r
71      * @exception IOException\r
72          */\r
73     public int read(byte[] a) {\r
74         statuscode = connection.SC_OK;\r
75         if (ssl) return super.read(a);\r
76         boolean cookies_enabled=server.enableCookiesByDefault();\r
77         String rq="";\r
78         header_length=0;\r
79         post_data_len = 0;\r
80         content_len = 0;\r
81         boolean start_line=true;\r
82         buf = getLine(); // reads the first line\r
83         if (buf==null)\r
84             return -2;\r
85         boolean cnt=true;\r
86         while (lread>2&&cnt) {\r
87             if (start_line) {\r
88                 start_line = false;\r
89                 int methodID = server.getHttpMethod(buf);\r
90                 if (methodID==-1) {\r
91                     statuscode = connection.SC_NOT_SUPPORTED;\r
92                 } else {\r
93                     if (methodID==2) {\r
94                         ssl = true;\r
95                     }\r
96                     InetAddress host = parseRequest(buf,methodID);\r
97                     \r
98                     if (statuscode == connection.SC_OK) {\r
99                         if (!server.use_proxy && !ssl) {\r
100                             /* creates a new request without the hostname */\r
101                             buf = method + " " + url + " " + server.getHttpVersion() + "\r\n";\r
102                             lread = buf.length();\r
103                         }\r
104                         if ((server.use_proxy && connection.notConnected()) || !host.equals(remote_host)) {\r
105                             if (server.debug) server.writeLog("read_f: STATE_CONNECT_TO_NEW_HOST");\r
106                             statuscode = connection.SC_CONNECTING_TO_HOST;\r
107                             remote_host = host;\r
108                         }\r
109                         /* -------------------------\r
110                          * url blocking (only "GET" method)\r
111                          * -------------------------*/\r
112                         if (server.block_urls && methodID==0 && statuscode!=connection.SC_FILE_REQUEST) {\r
113                             if (server.debug) System.printString("Searching match...");\r
114                             Jhttpp2URLMatch match=server.findMatch(this.remote_host_name+url);\r
115                             if (match!=null){\r
116                                 if (server.debug) System.printString("Match found!");\r
117                                 cookies_enabled=match.getCookiesEnabled();\r
118                                 if (match.getActionIndex()==-1) cnt=false; else {\r
119                                     OnURLAction action=(OnURLAction)server.getURLActions().elementAt(match.getActionIndex());\r
120                                     if (action.onAccesssDeny()) {\r
121                                         statuscode=connection.SC_URL_BLOCKED;\r
122                                         if (action.onAccessDenyWithCustomText()) errordescription=action.getCustomErrorText();\r
123                                     } else if (action.onAccessRedirect()) {\r
124                                         statuscode=connection.SC_MOVED_PERMANENTLY;\r
125                                         errordescription=action.newLocation();\r
126                                     }\r
127                                 }\r
128                             }//end if match!=null)\r
129                         } //end if (server.block...\r
130                     }\r
131                 }\r
132             } else { // end if(startline)\r
133                 /*-----------------------------------------------\r
134                  * Content-Length parsing\r
135                  *-----------------------------------------------*/\r
136                 if(server.startsWith(buf.toUpperCase(),"CONTENT-LENGTH")) {\r
137                     String clen=buf.substring(16);\r
138                     if (clen.indexOf("\r")!=-1) clen=clen.substring(0,clen.indexOf("\r"));\r
139                     else if(clen.indexOf("\n")!=-1) clen=clen.substring(0,clen.indexOf("\n"));\r
140                     content_len=Integer.parseInt(clen);\r
141                     if (server.debug) server.writeLog("read_f: content_len: " + content_len);\r
142                     if (!ssl) body=true; // Note: in HTTP/1.1 any method can have a body, not only "POST"\r
143                 }\r
144                 else if (server.startsWith(buf,"Proxy-Connection:")) {\r
145                     if (!server.use_proxy) buf=null;\r
146                     else {\r
147                         buf="Proxy-Connection: Keep-Alive\r\n";\r
148                         lread=buf.length();\r
149                     }\r
150                 }\r
151                 /*-----------------------------------------------\r
152                  * cookie crunch section\r
153                  *-----------------------------------------------*/\r
154                 else if(server.startsWith(buf,"Cookie:")) {\r
155                     if (!cookies_enabled) buf=null;\r
156                 }\r
157                 /*------------------------------------------------\r
158                  * Http-Header filtering section\r
159                  *------------------------------------------------*/\r
160                 else if (server.filter_http) {\r
161                     if(server.startsWith(buf,"Referer:")) {// removes "Referer"\r
162                         buf=null;\r
163                     } else if(server.startsWith(buf,"User-Agent")) // changes User-Agent\r
164                         {\r
165                             buf="User-Agent: " + server.getUserAgent() + "\r\n";\r
166                             lread=buf.length();\r
167                         }\r
168                 }\r
169             }\r
170             if (buf!=null) {\r
171                 rq+=buf;\r
172                 if (server.debug) server.writeLog(buf);\r
173                 header_length+=lread;\r
174             }\r
175             buf=getLine();\r
176             if (buf==null)\r
177                 return -2;\r
178         }\r
179         rq+=buf; //adds last line (should be an empty line) to the header String\r
180         header_length+=lread;\r
181         \r
182         if (header_length==0) {\r
183             if (server.debug) server.writeLog("header_length=0, setting status to SC_CONNECTION_CLOSED (buggy request)");\r
184             statuscode=connection.SC_CONNECTION_CLOSED;\r
185         }\r
186         \r
187         for (int i=0;i<header_length;i++) a[i]=(byte)rq.charAt(i);\r
188         \r
189         if(body) {// read the body, if "Content-Length" given\r
190             post_data_len = 0;\r
191             while(post_data_len < content_len)  {\r
192                 a[header_length + post_data_len]=(byte)read(); // writes data into the array\r
193                 post_data_len ++;\r
194             }\r
195             header_length += content_len; // add the body-length to the header-length\r
196             body = false;\r
197         }\r
198         if (statuscode==connection.SC_OK) {\r
199             return header_length;\r
200         } else {\r
201             return -1;\r
202         }\r
203     }\r
204     /**\r
205      * reads a line\r
206      * @exception IOException\r
207      */\r
208     public String getLine()\r
209     {\r
210         int l=0; String line=""; lread=0;\r
211         boolean cnt=true;\r
212         while(l!='\n'&&cnt) {\r
213             l=read();\r
214             if (l!=-1) {\r
215                 line+=(char)l;\r
216                 lread++;\r
217             } else {\r
218                 cnt=false;\r
219                 if (!line.equals(""))\r
220                     return null;\r
221             }\r
222         }\r
223         return line;\r
224     }\r
225         /**\r
226         * Parser for the first (!) line from the HTTP request<BR>\r
227         * Sets up the URL, method and remote hostname.\r
228         * @return an InetAddress for the hostname, null on errors with a statuscode!=SC_OK\r
229         */\r
230         public InetAddress parseRequest(String a,int method_index)  {\r
231             if (server.debug) \r
232                 server.writeLog(a);\r
233             String f; \r
234             int pos; \r
235             url="";\r
236             if (ssl) {\r
237                 f = a.substring(8);\r
238             } else {\r
239                 method = a.substring(0,a.indexOf(" ")); //first word in the line\r
240                 pos = a.indexOf(":"); // locate first :\r
241                 if (pos == -1) { // occours with "GET / HTTP/1.1"\r
242                     url = a.substring(a.indexOf(" ")+1,a.lastIndexOf(" "));\r
243                     if (method_index == 0) { // method_index==0 --> GET\r
244                         if (url.indexOf(server.WEB_CONFIG_FILE) != -1) {\r
245                             statuscode = connection.SC_CONFIG_RQ;\r
246                         } else { \r
247                             statuscode = connection.SC_FILE_REQUEST;\r
248                         }\r
249                     } else {\r
250                         if (method_index == 1 && url.indexOf(server.WEB_CONFIG_FILE) != -1) { // allow "POST" for admin log in\r
251                             statuscode = connection.SC_CONFIG_RQ;\r
252                         } else {\r
253                             statuscode=connection.SC_INTERNAL_SERVER_ERROR;\r
254                             errordescription="This WWW proxy supports only the \"GET\" method while acting as webserver.";\r
255                         }\r
256                     }\r
257                     return null;\r
258                 }\r
259                 f = a.substring(pos+3); //removes "http://"\r
260             }\r
261             pos=f.indexOf(" "); // locate space, should be the space before "HTTP/1.1"\r
262             if (pos==-1) { // buggy request\r
263                 statuscode=connection.SC_CLIENT_ERROR;\r
264                 errordescription="Your browser sent an invalid request: \""+ a + "\"";\r
265                 return null;\r
266             }\r
267             f = f.substring(0,pos); //removes all after space\r
268             // if the url contains a space... it's not our mistake...(url's must never contain a space character)\r
269             pos=f.indexOf("/"); // locate the first slash\r
270             if (pos!=-1) {\r
271                 url=f.substring(pos); // saves path without hostname\r
272                 f=f.substring(0,pos); // reduce string to the hostname\r
273             }\r
274             else url="/"; // occurs with this request: "GET http://localhost HTTP/1.1"\r
275             pos = f.indexOf(":"); // check for the portnumber\r
276             if (pos!=-1) {\r
277                 String l_port =f.substring(pos+1);\r
278                 if (l_port.indexOf(" ")!=-1)\r
279                     l_port=l_port.substring(0,l_port.indexOf(" "));\r
280                 int i_port=80;\r
281                 //BCD\r
282                 i_port = Integer.parseInt(l_port);\r
283                 f = f.substring(0,pos);\r
284                 remote_port=i_port;\r
285             } else\r
286                 remote_port = 80;\r
287             remote_host_name = f;\r
288             InetAddress address = null;\r
289             if (server.log_access) \r
290                 server.logAccess(method + " " + getFullURL());\r
291 \r
292             address = InetAddress.getByName(f);\r
293 \r
294             if (remote_port == server.port && address.equals(InetAddress.getLocalHost())) {\r
295                 if (url.indexOf(server.WEB_CONFIG_FILE) != -1 && (method_index == 0 || method_index == 1))\r
296                     statuscode = connection.SC_CONFIG_RQ;\r
297                 else if (method_index > 0 ) {\r
298                     statuscode=connection.SC_INTERNAL_SERVER_ERROR;\r
299                     errordescription="This WWW proxy supports only the \"GET\" method while acting as webserver.";\r
300                 } else\r
301                     statuscode = connection.SC_FILE_REQUEST;\r
302             }\r
303             return address;\r
304         }\r
305         /**\r
306         * @return boolean whether the actual connection was established with the CONNECT method.\r
307         * @since 0.2.21\r
308         */\r
309         public boolean isTunnel() {\r
310           return ssl;\r
311         }\r
312     /**\r
313      * @return the full qualified URL of the actual request.\r
314      * @since 0.4.0\r
315      */\r
316     public String getFullURL() {\r
317         String sh="";\r
318         if (ssl)\r
319             sh="s";\r
320         if (remote_port!=80)\r
321                 return "http" + sh + "://" + getRemoteHostName()\r
322                 + ":" + remote_port + url;\r
323         else\r
324                 return "http" + sh + "://" + getRemoteHostName()\r
325                     + url;\r
326     }\r
327     /**\r
328      * @return status-code for the actual request\r
329      * @since 0.3.5\r
330      */\r
331         public int getStatusCode()\r
332         {\r
333                 return statuscode;\r
334         }\r
335         /**\r
336         * @return the (optional) error-description for this request\r
337         */\r
338         public String getErrorDescription()\r
339         {\r
340                 return errordescription;\r
341         }\r
342 }\r