Security Plugin: set http status for URL rule match
[MonkeyD.git] / src / utils.c
blob707fc265d1c46271edfe8ac4b7deb0e96e0cfb5f
1 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 /* Monkey HTTP Daemon
4 * ------------------
5 * Copyright (C) 2001-2010, Eduardo Silva P. <edsiper@gmail.com>
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
22 #define _GNU_SOURCE
23 #include <fcntl.h>
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <unistd.h>
27 #include <assert.h>
28 #include <errno.h>
29 #include <limits.h>
31 #include <ctype.h>
32 #include <stdio.h>
33 #include <stdarg.h>
34 #include <stdlib.h>
35 #include <errno.h>
36 #include <string.h>
37 #include <sys/types.h>
38 #include <sys/socket.h>
39 #include <sys/stat.h>
41 #include <unistd.h>
42 #include <signal.h>
43 #include <sys/sendfile.h>
45 #include <time.h>
47 #include "monkey.h"
48 #include "memory.h"
49 #include "utils.h"
50 #include "file.h"
51 #include "str.h"
52 #include "config.h"
53 #include "chars.h"
54 #include "socket.h"
55 #include "clock.h"
56 #include "user.h"
57 #include "cache.h"
59 /* Date helpers */
60 const char *mk_date_wd[7] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
61 const char *mk_date_ym[12] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul",
62 "Aug", "Sep", "Oct", "Nov", "Dec"};
64 /* This function given a unix time, set in a mk_pointer
65 * the date in the RFC1123 format like:
67 * Wed, 23 Jun 2010 22:32:01 GMT
69 * it also adds a 'CRLF' at the end
71 int mk_utils_utime2gmt(mk_pointer **p, time_t date)
73 int size = 31;
74 unsigned int year;
75 char *buf=0;
76 struct tm *gtm;
78 if (date == 0) {
79 if ((date = time(NULL)) == -1) {
80 return -1;
84 /* Convert unix time to struct tm */
85 gtm = (struct tm *) gmtime(&date);
86 if (!gtm) {
87 return -1;
90 /* struct tm -> tm_year counts number of years after 1900 */
91 year = gtm->tm_year + 1900;
93 /* Compose template */
94 buf = (*p)->data;
96 /* Week day */
97 *buf++ = mk_date_wd[gtm->tm_wday][0];
98 *buf++ = mk_date_wd[gtm->tm_wday][1];
99 *buf++ = mk_date_wd[gtm->tm_wday][2];
100 *buf++ = ',';
101 *buf++ = ' ';
103 /* Day of the month */
104 *buf++ = ('0' + (gtm->tm_mday / 10));
105 *buf++ = ('0' + (gtm->tm_mday % 10));
106 *buf++ = ' ';
108 /* Year month */
109 *buf++ = mk_date_ym[gtm->tm_mon][0];
110 *buf++ = mk_date_ym[gtm->tm_mon][1];
111 *buf++ = mk_date_ym[gtm->tm_mon][2];
112 *buf++ = ' ';
114 /* Year */
115 *buf++ = ('0' + (year / 1000) % 10);
116 *buf++ = ('0' + (year / 100) % 10);
117 *buf++ = ('0' + (year / 10) % 10);
118 *buf++ = ('0' + (year % 10));
119 *buf++ = ' ';
121 /* Hour */
122 *buf++ = ('0' + (gtm->tm_hour / 10));
123 *buf++ = ('0' + (gtm->tm_hour % 10));
124 *buf++ = ':';
126 /* Minutes */
127 *buf++ = ('0' + (gtm->tm_min / 10));
128 *buf++ = ('0' + (gtm->tm_min % 10));
129 *buf++ = ':';
131 /* Seconds */
132 *buf++ = ('0' + (gtm->tm_sec / 10));
133 *buf++ = ('0' + (gtm->tm_sec % 10));
134 *buf++ = ' ';
136 /* GMT Time zone + CRLF */
137 *buf++ = 'G';
138 *buf++ = 'M';
139 *buf++ = 'T';
140 *buf++ = '\r';
141 *buf++ = '\n';
142 *buf++ = '\0';
144 /* Set mk_pointer data len */
145 (*p)->len = size;
147 return 0;
150 time_t PutDate_unix(char *date)
152 time_t new_unix_time;
153 struct tm t_data;
155 if (!strptime(date, GMT_DATEFORMAT, (struct tm *) &t_data)) {
156 return -1;
159 new_unix_time = mktime((struct tm *) &t_data);
161 return (new_unix_time);
164 int mk_buffer_cat(mk_pointer *p, char *buf1, int len1, char *buf2, int len2)
166 /* Validate lengths */
167 if (len1 < 0 || len2 < 0) {
168 return -1;
171 /* alloc space */
172 p->data = (char *) mk_mem_malloc(len1 + len2 + 1);
174 /* copy data */
175 memcpy(p->data, buf1, len1);
176 memcpy(p->data + len1, buf2, len2);
177 p->data[len1 + len2] = '\0';
179 /* assign len */
180 p->len = len1 + len2;
182 return 0;
185 /* Run current process in background mode (daemon, evil Monkey >:) */
186 int mk_utils_set_daemon()
188 switch (fork()) {
189 case 0:
190 break;
191 case -1:
192 exit(1);
193 break; /* Error */
194 default:
195 exit(0); /* Success */
198 setsid(); /* Create new session */
199 fclose(stderr);
200 fclose(stdout);
202 return 0;
205 /* If the URI contains hexa format characters it will return
206 * convert the Hexa values to ASCII character
208 char *mk_utils_hexuri_to_ascii(mk_pointer uri)
211 int i, hex_result, aux_char;
212 int buf_idx = 0;
213 char *buf;
214 char hex[3];
216 if ((i = mk_string_char_search(uri.data, '%', uri.len)) < 0) {
217 return NULL;
220 buf = mk_mem_malloc_z(uri.len);
223 if (i > 0) {
224 strncpy(buf, uri.data, i);
225 buf_idx = i;
228 while (i < uri.len) {
229 if (uri.data[i] == '%' && i + 2 < uri.len) {
230 memset(hex, '\0', sizeof(hex));
231 strncpy(hex, uri.data + i + 1, 2);
232 hex[2] = '\0';
234 if ((hex_result = hex2int(hex)) <= 127) {
235 buf[buf_idx] = toascii(hex_result);
237 else {
238 if ((aux_char = get_char(hex_result)) != -1) {
239 buf[buf_idx] = aux_char;
241 else {
242 mk_mem_free(buf);
243 return NULL;
246 i += 2;
248 else {
249 buf[buf_idx] = uri.data[i];
251 i++;
252 buf_idx++;
254 buf[buf_idx] = '\0';
256 return buf;
259 #ifdef TRACE
260 #include <sys/time.h>
261 void mk_utils_trace(const char *component, int color, const char *function,
262 char *file, int line, const char* format, ...)
264 va_list args;
265 char *color_function = NULL;
266 char *color_fileline = NULL;
268 struct timeval tv;
269 struct timezone tz;
271 if (envtrace) {
272 if (!strstr(envtrace, file)) {
273 return;
277 /* Mutex lock */
278 pthread_mutex_lock(&mutex_trace);
280 gettimeofday(&tv, &tz);
282 /* Switch message color */
283 switch(color) {
284 case MK_TRACE_CORE:
285 color_function = ANSI_YELLOW;
286 color_fileline = ANSI_WHITE;
287 break;
288 case MK_TRACE_PLUGIN:
289 color_function = ANSI_BLUE;
290 color_fileline = ANSI_WHITE;
291 break;
294 va_start( args, format );
296 fprintf(stderr, "~ %s%2i.%i%s %s%s[%s%s%s%s%s|%s:%i%s] %s%s():%s ",
297 ANSI_CYAN, (int) (tv.tv_sec - monkey_init_time), (int) tv.tv_usec, ANSI_RESET,
298 ANSI_MAGENTA, ANSI_BOLD,
299 ANSI_RESET, ANSI_BOLD, ANSI_GREEN, component, color_fileline, file,
300 line, ANSI_MAGENTA,
301 color_function, function, ANSI_RED);
302 vfprintf( stderr, format, args );
303 va_end( args );
304 fprintf( stderr, "%s\n", ANSI_RESET);
306 /* Mutex unlock */
307 pthread_mutex_unlock(&mutex_trace);
310 #endif
312 /* Get SOMAXCONN value. Based on sysctl manpage */
313 int mk_utils_get_somaxconn()
315 /* sysctl() is deprecated in some systems, you can notice that with some system
316 * messages as:
318 * '(warning: process `monkey' used the deprecated sysctl system call...'
320 * In order to avoid that problem, this function will check the proc filesystem,
321 * if it still fails, we will use the default value defined for somaxconn for years...
323 int somaxconn = 128;
324 char buf[16];
325 FILE *f;
327 f = fopen("/proc/sys/net/core/somaxconn", "r");
328 if(f && fgets(buf, 16, f)) {
329 somaxconn = atoi(buf);
330 fclose(f);
333 return somaxconn;
336 /* Write Monkey's PID */
337 int mk_utils_register_pid()
339 FILE *pid_file;
341 remove(config->pid_file_path);
342 config->pid_status = VAR_OFF;
344 if ((pid_file = fopen(config->pid_file_path, "w")) == NULL) {
345 puts("Error: I can't log pid of monkey");
346 exit(1);
349 fprintf(pid_file, "%i", getpid());
350 fclose(pid_file);
351 config->pid_status = VAR_ON;
353 return 0;
356 /* Remove PID file */
357 int mk_utils_remove_pid()
359 mk_user_undo_uidgid();
360 return remove(config->pid_file_path);