ups
[MonkeyD.git] / src / method.c
blobcb2ba51f48d002ead11238e2e183b57314995299
1 /* Monkey HTTP Daemon
2 * ------------------
3 * Copyright (C) 2001-2008, Eduardo Silva P.
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU Library General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 #include <stdio.h>
21 #include <sys/types.h>
22 #include <sys/stat.h>
23 #include <sys/socket.h>
24 #include <sys/wait.h>
25 #include <netinet/in.h>
26 #include <stdlib.h>
27 #include <unistd.h>
28 #include <string.h>
29 #include <time.h>
31 #include "monkey.h"
33 #include "str.h"
34 #include "memory.h"
35 #include "http.h"
36 #include "http_status.h"
37 #include "header.h"
38 #include "socket.h"
39 #include "logfile.h"
40 #include "config.h"
41 #include "utils.h"
42 #include "file.h"
43 /* POST METHOD */
44 int M_METHOD_Post(struct client_request *cr, struct request *s_request)
47 char *tmp;
48 char buffer[MAX_REQUEST_BODY];
49 int content_length_post=0;
51 if(!(tmp=Request_Find_Variable(s_request->body, RH_CONTENT_LENGTH))){
52 Request_Error(M_CLIENT_LENGHT_REQUIRED, cr, s_request,0,s_request->log);
53 return -1;
56 content_length_post = (int) atoi(tmp);
57 mk_mem_free(tmp);
59 if(content_length_post<=0 || content_length_post >=MAX_REQUEST_BODY){
60 Request_Error(M_CLIENT_BAD_REQUEST, cr, s_request, 0, s_request->log);
61 return -1;
64 if(!(tmp = Request_Find_Variable(s_request->body, RH_CONTENT_TYPE))){
65 Request_Error(M_CLIENT_BAD_REQUEST, cr, s_request, 0, s_request->log);
66 return -1;
69 s_request->content_type = tmp;
71 if(s_request->post_variables==NULL || strlen(s_request->post_variables)<=4) {
72 s_request->post_variables=NULL;
73 return -1;
76 if(strlen(s_request->post_variables) < content_length_post){
77 content_length_post=strlen(buffer);
80 s_request->content_length=content_length_post;
82 return 0;
86 /* Reuturn the POST variables sent in the request */
87 char *M_Get_POST_Vars(char *request, int index, char *strend)
89 int i=index;
90 int length, length_string_end;
91 int last_byte = 1;
93 length = strlen(request);
94 length_string_end = strlen(strend);
95 if(length_string_end == 2)
97 last_byte = 0;
100 for(i=index; i<=length; i++)
102 if(strncmp(request+i, strend, length_string_end)==0)
104 break;
107 return mk_string_copy_substr(request, index, i-last_byte);
111 /* Send_Header , envia las cabeceras principales */
112 int M_METHOD_send_headers(int fd, struct client_request *cr,
113 struct request *sr, struct log_info *s_log)
115 int fd_status=0;
116 unsigned long len=0;
117 char *buffer=0;
118 struct header_values *sh;
119 struct mk_iov *iov;
120 char *date=0;
122 sh = sr->headers;
124 iov = mk_iov_create(50);
126 /* Status Code */
127 switch(sh->status){
128 case M_HTTP_OK:
129 mk_iov_add_entry(iov, RESP_HTTP_OK, LEN_RESP_HTTP_OK,
130 MK_IOV_BREAK_LINE, MK_IOV_NOT_FREE_BUF);
131 break;
133 case M_HTTP_PARTIAL:
134 mk_iov_add_entry(iov, RESP_HTTP_PARTIAL,
135 LEN_RESP_HTTP_PARTIAL,
136 MK_IOV_BREAK_LINE,
137 MK_IOV_NOT_FREE_BUF);
138 break;
140 case M_REDIR_MOVED:
141 s_log->status=S_LOG_OFF;
142 mk_iov_add_entry(iov, RESP_REDIR_MOVED,
143 LEN_RESP_REDIR_MOVED,
144 MK_IOV_BREAK_LINE,
145 MK_IOV_NOT_FREE_BUF);
146 break;
148 case M_REDIR_MOVED_T:
149 s_log->status=S_LOG_ON;
150 mk_iov_add_entry(iov, RESP_REDIR_MOVED_T,
151 LEN_RESP_REDIR_MOVED_T,
152 MK_IOV_BREAK_LINE,
153 MK_IOV_NOT_FREE_BUF);
154 break;
156 case M_NOT_MODIFIED:
157 s_log->status=S_LOG_OFF;
158 mk_iov_add_entry(iov, RESP_NOT_MODIFIED,
159 LEN_RESP_NOT_MODIFIED,
160 MK_IOV_BREAK_LINE,
161 MK_IOV_NOT_FREE_BUF);
162 break;
164 case M_CLIENT_BAD_REQUEST:
165 mk_iov_add_entry(iov, RESP_CLIENT_BAD_REQUEST,
166 LEN_RESP_CLIENT_BAD_REQUEST,
167 MK_IOV_BREAK_LINE,
168 MK_IOV_NOT_FREE_BUF);
169 break;
171 case M_CLIENT_FORBIDDEN:
172 mk_iov_add_entry(iov, RESP_CLIENT_FORBIDDEN,
173 LEN_RESP_CLIENT_FORBIDDEN,
174 MK_IOV_BREAK_LINE,
175 MK_IOV_NOT_FREE_BUF);
176 break;
178 case M_CLIENT_NOT_FOUND:
179 mk_iov_add_entry(iov, RESP_CLIENT_NOT_FOUND,
180 LEN_RESP_CLIENT_NOT_FOUND,
181 MK_IOV_BREAK_LINE,
182 MK_IOV_NOT_FREE_BUF);
183 break;
185 case M_CLIENT_METHOD_NOT_ALLOWED:
186 mk_iov_add_entry(iov, RESP_CLIENT_METHOD_NOT_ALLOWED,
187 LEN_RESP_CLIENT_METHOD_NOT_ALLOWED,
188 MK_IOV_BREAK_LINE,
189 MK_IOV_NOT_FREE_BUF);
190 break;
192 case M_CLIENT_REQUEST_TIMEOUT:
193 mk_iov_add_entry(iov, RESP_CLIENT_REQUEST_TIMEOUT,
194 LEN_RESP_CLIENT_REQUEST_TIMEOUT,
195 MK_IOV_BREAK_LINE,
196 MK_IOV_NOT_FREE_BUF);
197 s_log->status=S_LOG_OFF;
198 break;
200 case M_CLIENT_LENGHT_REQUIRED:
201 mk_iov_add_entry(iov, RESP_CLIENT_LENGTH_REQUIRED,
202 LEN_RESP_CLIENT_LENGTH_REQUIRED,
203 MK_IOV_BREAK_LINE,
204 MK_IOV_NOT_FREE_BUF);
205 break;
207 case M_SERVER_INTERNAL_ERROR:
208 mk_iov_add_entry(iov, RESP_SERVER_INTERNAL_ERROR,
209 LEN_RESP_SERVER_INTERNAL_ERROR,
210 MK_IOV_BREAK_LINE,
211 MK_IOV_NOT_FREE_BUF);
212 break;
214 case M_SERVER_HTTP_VERSION_UNSUP:
215 mk_iov_add_entry(iov, RESP_SERVER_HTTP_VERSION_UNSUP,
216 LEN_RESP_SERVER_HTTP_VERSION_UNSUP,
217 MK_IOV_BREAK_LINE,
218 MK_IOV_NOT_FREE_BUF);
219 break;
222 if(sh->status!=0){
223 s_log->final_response = sh->status;
226 if(fd_status<0){
227 mk_iov_free(iov);
228 return -1;
231 /* Informacion del server */
232 mk_iov_add_entry(iov, sr->host_conf->header_host_signature,
233 strlen(sr->host_conf->header_host_signature),
234 MK_IOV_BREAK_LINE, MK_IOV_NOT_FREE_BUF);
236 /* Fecha */
237 date = PutDate_string(0);
238 m_build_buffer(&buffer, &len, "Date: %s", date);
239 mk_iov_add_entry(iov, buffer, len,
240 MK_IOV_BREAK_LINE, MK_IOV_FREE_BUF);
241 mk_mem_free(date);
243 /* Location */
244 if(sh->location!=NULL)
246 m_build_buffer(
247 &buffer,
248 &len,
249 "Location: %s",
250 sh->location);
252 mk_iov_add_entry(iov, buffer, len,
253 MK_IOV_BREAK_LINE, MK_IOV_FREE_BUF);
256 /* Last-Modified */
257 if(sh->last_modified!=NULL){
258 m_build_buffer(
259 &buffer,
260 &len,
261 "%s %s",
262 RH_LAST_MODIFIED,
263 sh->last_modified);
264 mk_iov_add_entry(iov, buffer, len,
265 MK_IOV_BREAK_LINE, MK_IOV_FREE_BUF);
268 /* Connection */
269 if(cr->counter_connections<config->max_keep_alive_request && config->keep_alive==VAR_ON){
270 m_build_buffer(
271 &buffer,
272 &len,
273 "Keep-Alive: timeout=%i, max=%i",
274 config->keep_alive_timeout,
275 config->max_keep_alive_request-cr->counter_connections);
276 mk_iov_add_entry(iov, buffer, len,
277 MK_IOV_BREAK_LINE, MK_IOV_FREE_BUF);
279 m_build_buffer(
280 &buffer,
281 &len,
282 "Connection: Keep-Alive");
283 mk_iov_add_entry(iov, buffer, len,
284 MK_IOV_BREAK_LINE, MK_IOV_FREE_BUF);
286 else{
287 m_build_buffer(
288 &buffer,
289 &len,
290 "Connection: close");
291 mk_iov_add_entry(iov, buffer, len,
292 MK_IOV_BREAK_LINE, MK_IOV_FREE_BUF);
295 /* Tipo de contenido de la informacion */
296 if(sh->content_type!=NULL){
297 m_build_buffer(
298 &buffer,
299 &len,
300 "Content-Type: %s",
301 sh->content_type);
302 mk_iov_add_entry(iov, buffer, len,
303 MK_IOV_BREAK_LINE, MK_IOV_FREE_BUF);
306 /* Ranges */
307 m_build_buffer(
308 &buffer,
309 &len,
310 "Accept-Ranges: bytes",
311 sh->content_type);
312 mk_iov_add_entry(iov, buffer, len,
313 MK_IOV_BREAK_LINE, MK_IOV_FREE_BUF);
315 //printf("\n->sh->cl: %i", sh->content_length);
316 //fflush(stdout);
318 /* TamaƱo total de la informacion a enviar */
319 if((sh->content_length!=0 &&
320 (sh->ranges[0]>=0 || sh->ranges[1]>=0)) &&
321 config->resume==VAR_ON){
322 long int length;
324 /* yyy- */
325 if(sh->ranges[0]>=0 && sh->ranges[1]==-1){
326 length = (unsigned int) ( sh->content_length - sh->ranges[0] );
327 m_build_buffer(
328 &buffer,
329 &len,
330 "%s %i",
331 RH_CONTENT_LENGTH,
332 length);
333 mk_iov_add_entry(iov, buffer, len,
334 MK_IOV_BREAK_LINE, MK_IOV_FREE_BUF);
336 m_build_buffer(
337 &buffer,
338 &len,
339 "%s bytes %d-%d/%d",
340 RH_CONTENT_RANGE,
341 sh->ranges[0],
342 (sh->content_length - 1),
343 sh->content_length);
344 mk_iov_add_entry(iov, buffer, len,
345 MK_IOV_BREAK_LINE, MK_IOV_FREE_BUF);
348 /* yyy-xxx */
349 if(sh->ranges[0]>=0 && sh->ranges[1]>=0){
350 length = (unsigned int) abs(sh->ranges[1] - sh->ranges[0]) + 1;
351 m_build_buffer(
352 &buffer,
353 &len,
354 "%s %d",
355 RH_CONTENT_LENGTH,
356 length);
357 mk_iov_add_entry(iov, buffer, len,
358 MK_IOV_BREAK_LINE, MK_IOV_FREE_BUF);
360 m_build_buffer(
361 &buffer,
362 &len,
363 "%s bytes %d-%d/%d",
364 RH_CONTENT_RANGE,
365 sh->ranges[0],
366 sh->ranges[1],
367 sh->content_length);
369 mk_iov_add_entry(iov, buffer, len,
370 MK_IOV_BREAK_LINE, MK_IOV_FREE_BUF);
372 /* -xxx */
373 if(sh->ranges[0]==-1 && sh->ranges[1]>=0){
374 m_build_buffer(
375 &buffer,
376 &len,
377 "%s %d",
378 RH_CONTENT_LENGTH,
379 sh->ranges[1]);
380 mk_iov_add_entry(iov, buffer, len,
381 MK_IOV_BREAK_LINE, MK_IOV_FREE_BUF);
383 m_build_buffer(
384 &buffer,
385 &len,
386 "%s bytes %d-%d/%d",
387 RH_CONTENT_RANGE,
388 (sh->content_length - sh->ranges[1]),
389 (sh->content_length - 1),
390 sh->content_length);
391 mk_iov_add_entry(iov, buffer, len,
392 MK_IOV_BREAK_LINE, MK_IOV_FREE_BUF);
395 else if(sh->content_length>=0)
397 m_build_buffer(
398 &buffer,
399 &len,
400 "%s %d",
401 RH_CONTENT_LENGTH,
402 sh->content_length);
403 mk_iov_add_entry(iov, buffer, len,
404 MK_IOV_BREAK_LINE, MK_IOV_FREE_BUF);
406 else if(sh->status==M_REDIR_MOVED)
408 m_build_buffer(
409 &buffer,
410 &len,
411 "%s %d",
412 RH_CONTENT_LENGTH,
413 sh->content_length);
414 mk_iov_add_entry(iov, buffer, len,
415 MK_IOV_BREAK_LINE, MK_IOV_FREE_BUF);
418 if(sh->cgi==SH_NOCGI)
420 mk_iov_add_separator(iov, MK_IOV_BREAK_LINE);
422 mk_socket_set_cork_flag(fd, TCP_CORK_ON);
423 mk_iov_send(fd, iov);
424 mk_iov_free(iov);
425 return 0;