Fix content type header for error pages
[MonkeyD.git] / src / utils.c
blobd1795ca4c1ca33fb91f135b1324c0e0f8032b097
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 "str.h"
51 #include "config.h"
52 #include "chars.h"
53 #include "socket.h"
54 #include "clock.h"
56 int SendFile(int socket, struct client_request *cr, struct request *sr)
58 long int nbytes = 0;
60 nbytes = sendfile(socket, sr->fd_file, &sr->bytes_offset,
61 sr->bytes_to_send);
63 if (nbytes > 0 && sr->loop == 0) {
64 mk_socket_set_cork_flag(socket, TCP_CORK_OFF);
67 if (nbytes == -1) {
68 fprintf(stderr, "error from sendfile: %s\n", strerror(errno));
69 return -1;
71 else {
72 sr->bytes_to_send -= nbytes;
75 sr->loop++;
76 return sr->bytes_to_send;
79 /* Devuelve la fecha para enviarla
80 en el header */
81 mk_pointer PutDate_string(time_t date)
83 int n, size = 32;
84 mk_pointer date_gmt;
85 struct tm *gmt_tm;
87 mk_pointer_reset(&date_gmt);
89 if (date == 0) {
90 if ((date = time(NULL)) == -1) {
91 return date_gmt;
95 date_gmt.data = mk_mem_malloc(size);
96 gmt_tm = (struct tm *) gmtime(&date);
97 n = strftime(date_gmt.data, size - 1, GMT_DATEFORMAT, gmt_tm);
98 date_gmt.data[n] = '\0';
99 date_gmt.len = n;
101 return date_gmt;
104 time_t PutDate_unix(char *date)
106 time_t new_unix_time;
107 struct tm t_data;
109 if (!strptime(date, GMT_DATEFORMAT, (struct tm *) &t_data)) {
110 return -1;
113 new_unix_time = mktime((struct tm *) &t_data);
115 return (new_unix_time);
118 int mk_buffer_cat(mk_pointer * p, char *buf1, int len1, char *buf2, int len2)
120 /* alloc space */
121 p->data = (char *) mk_mem_malloc(len1 + len2 + 1);
123 /* copy data */
124 memcpy(p->data, buf1, len1);
125 memcpy(p->data + len1, buf2, len2);
126 p->data[len1 + len2] = '\0';
128 /* assign len */
129 p->len = len1 + len2;
131 return 0;
134 char *m_build_buffer(char **buffer, unsigned long *len, const char *format,
135 ...)
137 va_list ap;
138 int length;
139 char *ptr;
140 static size_t _mem_alloc = 64;
141 size_t alloc = 0;
143 /* *buffer *must* be an empty/NULL buffer */
145 *buffer = (char *) mk_mem_malloc(_mem_alloc);
146 if (!*buffer) {
147 return NULL;
149 alloc = _mem_alloc;
151 va_start(ap, format);
152 length = vsnprintf(*buffer, alloc, format, ap);
154 if (length >= alloc) {
155 ptr = realloc(*buffer, length + 1);
156 if (!ptr) {
157 va_end(ap);
158 return NULL;
160 *buffer = ptr;
161 alloc = length + 1;
162 length = vsnprintf(*buffer, alloc, format, ap);
164 va_end(ap);
166 if (length < 0) {
167 return NULL;
170 ptr = *buffer;
171 ptr[length] = '\0';
172 *len = length;
174 return *buffer;
177 /* Run current process in background mode (daemon, evil Monkey >:) */
178 int mk_utils_set_daemon()
180 switch (fork()) {
181 case 0:
182 break;
183 case -1:
184 exit(1);
185 break; /* Error */
186 default:
187 exit(0); /* Success */
190 setsid(); /* Create new session */
191 fclose(stdin); /* close screen outputs */
192 fclose(stderr);
193 fclose(stdout);
195 return 0;
198 /* If the URI contains hexa format characters it will return
199 * convert the Hexa values to ASCII character
201 char *mk_utils_hexuri_to_ascii(mk_pointer uri)
204 int i, hex_result, aux_char;
205 int buf_idx = 0;
206 char *buf;
207 char hex[3];
209 if ((i = mk_string_char_search(uri.data, '%', uri.len)) < 0) {
210 return NULL;
213 buf = mk_mem_malloc_z(uri.len);
216 if (i > 0) {
217 strncpy(buf, uri.data, i);
218 buf_idx = i;
221 while (i < uri.len) {
222 if (uri.data[i] == '%' && i + 2 < uri.len) {
223 memset(hex, '\0', sizeof(hex));
224 strncpy(hex, uri.data + i + 1, 2);
225 hex[2] = '\0';
227 if ((hex_result = hex2int(hex)) <= 127) {
228 buf[buf_idx] = toascii(hex_result);
230 else {
231 if ((aux_char = get_char(hex_result)) != -1) {
232 buf[buf_idx] = aux_char;
234 else {
235 mk_mem_free(buf);
236 return NULL;
239 i += 2;
241 else {
242 buf[buf_idx] = uri.data[i];
244 i++;
245 buf_idx++;
247 buf[buf_idx] = '\0';
249 return buf;
252 mk_pointer mk_utils_int2mkp(int n)
254 mk_pointer p;
255 char *buf;
256 unsigned long len;
258 buf = mk_mem_malloc(MK_UTILS_INT2MKP_BUFFER_LEN);
259 len = snprintf(buf, MK_UTILS_INT2MKP_BUFFER_LEN, "%i\r\n", n);
261 p.data = buf;
262 p.len = len;
264 return p;
267 #ifdef TRACE
268 #include <sys/time.h>
269 void mk_utils_trace(const char *component, int color, const char *function,
270 char *file, int line, const char* format, ...)
272 va_list args;
273 char *color_function = NULL;
274 char *color_fileline = NULL;
276 struct timeval tv;
277 struct timezone tz;
279 gettimeofday(&tv, &tz);
281 /* Switch message color */
282 switch(color) {
283 case MK_TRACE_CORE:
284 color_function = ANSI_YELLOW;
285 color_fileline = ANSI_WHITE;
286 break;
287 case MK_TRACE_PLUGIN:
288 color_function = ANSI_BLUE;
289 color_fileline = ANSI_WHITE;
290 break;
293 va_start( args, format );
295 fprintf(stderr, "~ %s%2i.%i%s %s%s[%s%s%s%s%s|%s:%i%s] %s%s():%s ",
296 ANSI_CYAN, (int) (tv.tv_sec - monkey_init_time), (int) tv.tv_usec, ANSI_RESET,
297 ANSI_MAGENTA, ANSI_BOLD,
298 ANSI_RESET, ANSI_BOLD, ANSI_GREEN, component, color_fileline, file,
299 line, ANSI_MAGENTA,
300 color_function, function, ANSI_RED);
301 vfprintf( stderr, format, args );
302 va_end( args );
303 fprintf( stderr, "%s\n", ANSI_RESET);
305 #endif