Fix directory validation after handler
[MonkeyD.git] / src / cgi.c
blobab7d23f2ea1d547b8dc1ff8faadcb83a3f9a3308
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
3 /* Monkey HTTP Daemon
4 * ------------------
5 * Copyright (C) 2001-2009, Eduardo Silva P.
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU Library General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 #include <pthread.h>
24 #include <sys/types.h>
25 #include <unistd.h>
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <signal.h>
30 #include <sys/stat.h>
31 #include <sys/socket.h>
32 #include <sys/wait.h>
34 #include <string.h>
36 #include "monkey.h"
37 #include "http.h"
38 #include "http_status.h"
39 #include "cgi.h"
40 #include "method.h"
41 #include "str.h"
42 #include "memory.h"
43 #include "utils.h"
44 #include "config.h"
45 #include "support.h"
46 #include "logfile.h"
47 #include "socket.h"
48 #include "header.h"
49 #include "iov.h"
51 struct palm *mk_palm_get_handler(mk_pointer *file)
53 struct palm *p;
54 int j, len;
56 j = len = file->len;
58 /* looking for extension */
59 while(file->data[j]!='.' && j>=0)
60 j--;
62 if(j==0){
63 return NULL;
66 p = palms;
67 while(p)
69 if(strcasecmp(file->data+j+1, p->ext)==0)
71 return p;
73 p = p->next;
76 return NULL;
79 char *mk_palm_check_request(struct client_request *cr, struct request *sr)
81 int sock, ret, n=0, total=0;
82 char *buf;
83 int len = 50024;
84 struct palm *p;
85 struct mk_iov *iov;
87 p = mk_palm_get_handler(&sr->real_path);
88 if(!p)
90 return NULL;
93 sock = mk_socket_create();
94 ret = mk_socket_connect(sock, p->host, p->port);
96 iov = mk_palm_create_env(cr, sr);
98 mk_socket_set_tcp_nodelay(sock);
99 mk_socket_set_cork_flag(sock, TCP_CORK_ON);
100 mk_iov_send(sock, iov, MK_IOV_SEND_TO_SOCKET);
102 n = write(sock, "\r\n\r\n", 2);
104 mk_socket_set_cork_flag(sock, TCP_CORK_OFF);
106 buf = mk_mem_malloc_z(len);
107 do {
108 n=read(sock, buf+total, len);
109 total+=n;
110 }while(n>0);
112 return (char *)buf;
115 struct mk_iov *mk_palm_create_env(struct client_request *cr,
116 struct request *sr)
118 struct mk_iov *iov;
120 iov = mk_iov_create(100, 0);
122 mk_iov_add_entry(iov, sr->real_path.data,
123 sr->real_path.len,
124 mk_crlf,
125 MK_IOV_NOT_FREE_BUF);
127 mk_iov_add_entry(iov, mk_cgi_document_root.data,
128 mk_cgi_document_root.len,
129 mk_iov_equal,
130 MK_IOV_NOT_FREE_BUF);
133 mk_iov_add_entry(iov, sr->host_conf->documentroot.data,
134 sr->host_conf->documentroot.len, mk_iov_crlf,
135 MK_IOV_NOT_FREE_BUF);
138 if(sr->method == HTTP_METHOD_POST && sr->content_length>0){
139 /* FIX Content length:
140 mk_palm_iov_add_header(iov, mk_cgi_content_length,
141 sr->content_length);
143 mk_palm_iov_add_header(iov, mk_cgi_content_type,
144 sr->content_type);
148 //mk_palm_iov_add_header(iov, mk_cgi_server_addr, config->server_addr);
149 mk_palm_iov_add_header(iov, mk_cgi_server_name, sr->host);
150 mk_palm_iov_add_header(iov, mk_cgi_server_protocol, mk_monkey_protocol);
151 mk_palm_iov_add_header(iov, mk_cgi_server_software,
152 config->server_software);
153 // mk_palm_iov_add_header(iov, mk_cgi_server_signature,
154 // sr->host_conf->host_signature);
156 if(sr->user_agent.data)
157 mk_palm_iov_add_header(iov, mk_cgi_http_user_agent,
158 sr->user_agent);
160 if(sr->accept.data)
161 mk_palm_iov_add_header(iov, mk_cgi_http_accept, sr->accept);
163 if(sr->accept_charset.data)
164 mk_palm_iov_add_header(iov, mk_cgi_http_accept_charset,
165 sr->accept_charset);
167 if(sr->accept_encoding.data)
168 mk_palm_iov_add_header(iov, mk_cgi_http_accept_encoding,
169 sr->accept_encoding);
171 if(sr->accept_language.data)
172 mk_palm_iov_add_header(iov, mk_cgi_http_accept_language,
173 sr->accept_language);
175 if(sr->host.data)
176 mk_palm_iov_add_header(iov, mk_cgi_http_host, sr->host);
178 if(sr->cookies.data)
179 mk_palm_iov_add_header(iov, mk_cgi_http_cookie, sr->cookies);
181 if(sr->referer.data)
182 mk_palm_iov_add_header(iov, mk_cgi_http_referer, sr->referer);
184 // mk_palm_iov_add_header(iov, mk_cgi_server_port, mk_monkey_port);
185 mk_palm_iov_add_header(iov, mk_cgi_gateway_interface, mk_cgi_version);
186 mk_palm_iov_add_header(iov, mk_cgi_remote_addr, cr->ip);
187 mk_palm_iov_add_header(iov, mk_cgi_request_uri, sr->uri);
188 //mk_palm_iov_add_header(iov, mk_cgi_request_method, sr->method);
189 mk_palm_iov_add_header(iov, mk_cgi_script_name, sr->uri);
192 /* real path is not an mk_pointer */
193 mk_palm_iov_add_header(iov, mk_cgi_script_filename, sr->real_path);
194 //mk_palm_iov_add_header(iov, mk_cgi_remote_port, cr->port);
195 mk_palm_iov_add_header(iov, mk_cgi_query_string, sr->query_string);
196 //mk_palm_iov_add_header(iov, mk_cgi_post_vars, sr->post_variables);
198 /* CRLF */
199 mk_iov_add_entry(iov, mk_crlf.data, mk_crlf.len,
200 mk_iov_none, MK_IOV_NOT_FREE_BUF);
201 return iov;
204 void mk_palm_iov_add_header(struct mk_iov *iov,
205 mk_pointer header, mk_pointer value)
207 mk_iov_add_entry(iov, header.data, header.len,
208 mk_iov_equal, MK_IOV_NOT_FREE_BUF);
209 mk_iov_add_entry(iov, value.data, value.len,
210 mk_iov_crlf, MK_IOV_NOT_FREE_BUF);
213 int mk_palm_send_response(struct client_request *cr, struct request *sr,
214 char *buf)
216 int len;
217 int i;
218 long n;
219 char *s;
220 char *status_msg = "Status: ";
222 len = 8;
223 if(strncasecmp(buf, status_msg, len)==0)
225 i = mk_string_search(buf+len, " ");
226 s = mk_string_copy_substr(buf, len, len+i);
227 sr->headers->status = atoi(s);
228 i = mk_string_search(buf, mk_crlf.data) + mk_crlf.len;
230 else{
231 i = 0;
232 sr->headers->status = M_HTTP_OK;
235 sr->headers->cgi = SH_CGI;
236 sr->headers->content_length = 0;
238 mk_socket_set_cork_flag(cr->socket, TCP_CORK_ON);
239 mk_header_send(cr->socket, cr, sr, sr->log);
240 n = write(cr->socket, buf+i, strlen(buf+i));
241 return 0;
244 void mk_palm_set_env()
246 mk_pointer_set(&mk_cgi_document_root, MK_CGI_DOCUMENT_ROOT);
247 mk_pointer_set(&mk_cgi_content_length, MK_CGI_CONTENT_LENGTH);
248 mk_pointer_set(&mk_cgi_content_type, MK_CGI_CONTENT_TYPE);
249 mk_pointer_set(&mk_cgi_server_addr, MK_CGI_SERVER_ADDR);
250 mk_pointer_set(&mk_cgi_server_name, MK_CGI_SERVER_NAME);
251 mk_pointer_set(&mk_cgi_server_protocol, MK_CGI_SERVER_PROTOCOL);
252 mk_pointer_set(&mk_cgi_server_software, MK_CGI_SERVER_SOFTWARE);
253 mk_pointer_set(&mk_cgi_server_signature, MK_CGI_SERVER_SIGNATURE);
254 mk_pointer_set(&mk_cgi_http_user_agent, MK_CGI_HTTP_USER_AGENT);
255 mk_pointer_set(&mk_cgi_http_accept, MK_CGI_HTTP_ACCEPT);
256 mk_pointer_set(&mk_cgi_http_accept_charset, MK_CGI_HTTP_ACCEPT_CHARSET);
257 mk_pointer_set(&mk_cgi_http_accept_encoding, MK_CGI_HTTP_ACCEPT_ENCODING);
258 mk_pointer_set(&mk_cgi_http_accept_language, MK_CGI_HTTP_ACCEPT_LANGUAGE);
259 mk_pointer_set(&mk_cgi_http_host, MK_CGI_HTTP_HOST);
260 mk_pointer_set(&mk_cgi_http_cookie, MK_CGI_HTTP_COOKIE);
261 mk_pointer_set(&mk_cgi_http_referer, MK_CGI_HTTP_REFERER);
262 mk_pointer_set(&mk_cgi_server_port, MK_CGI_SERVER_PORT);
263 mk_pointer_set(&mk_cgi_cgi_version, MK_CGI_CGI_VERSION);
264 mk_pointer_set(&mk_cgi_gateway_interface, MK_CGI_GATEWAY_INTERFACE);
265 mk_pointer_set(&mk_cgi_remote_addr, MK_CGI_REMOTE_ADDR);
266 mk_pointer_set(&mk_cgi_request_uri, MK_CGI_REQUEST_URI);
267 mk_pointer_set(&mk_cgi_request_method, MK_CGI_REQUEST_METHOD);
268 mk_pointer_set(&mk_cgi_script_name, MK_CGI_SCRIPT_NAME);
269 mk_pointer_set(&mk_cgi_script_filename, MK_CGI_SCRIPT_FILENAME);
270 mk_pointer_set(&mk_cgi_remote_port, MK_CGI_REMOTE_PORT);
271 mk_pointer_set(&mk_cgi_query_string, MK_CGI_QUERY_STRING);
272 mk_pointer_set(&mk_cgi_post_vars, MK_CGI_POST_VARS);