1
#include "../include/config.h"
2
#include "../include/common.h"
5
* This file holds random utility functions shared by cgi's and
8
extern int date_format;
10
/* fix the problem with strtok() skipping empty options between tokens */
11
char *my_strtok(char *buffer, char *tokens) {
12
char *token_position = NULL;
13
char *sequence_head = NULL;
14
static char *my_strtok_buffer = NULL;
15
static char *original_my_strtok_buffer = NULL;
18
my_free(original_my_strtok_buffer);
19
if((my_strtok_buffer = (char *)strdup(buffer)) == NULL)
21
original_my_strtok_buffer = my_strtok_buffer;
24
sequence_head = my_strtok_buffer;
26
if(sequence_head[0] == '\x0')
29
token_position = strchr(my_strtok_buffer, tokens[0]);
31
if(token_position == NULL) {
32
my_strtok_buffer = strchr(my_strtok_buffer, '\x0');
36
token_position[0] = '\x0';
37
my_strtok_buffer = token_position + 1;
42
/* fixes compiler problems under Solaris, since strsep() isn't included */
43
/* this code is taken from the glibc source */
44
char *my_strsep(char **stringp, const char *delim) {
51
/* A frequent case is when the delimiter string contains only one
52
* character. Here we don't need to call the expensive `strpbrk'
53
* function and instead work using `strchr'. */
54
if(delim[0] == '\0' || delim[1] == '\0') {
57
if(ch == '\0' || begin[0] == '\0')
63
end = strchr(begin + 1, ch);
67
/* find the end of the token. */
68
end = strpbrk(begin, delim);
72
/* terminate the token and set *STRINGP past NUL character. */
77
/* no more delimiters; this is the last token. */
83
/* open a file read-only via mmap() */
84
mmapfile *mmap_fopen(char *filename) {
85
mmapfile *new_mmapfile = NULL;
87
void *mmap_buf = NULL;
90
unsigned long file_size = 0L;
96
if((new_mmapfile = (mmapfile *) malloc(sizeof(mmapfile))) == NULL)
100
if((fd = open(filename, mode)) == -1) {
101
my_free(new_mmapfile);
106
if((fstat(fd, &statbuf)) == -1) {
108
my_free(new_mmapfile);
113
file_size = (unsigned long)statbuf.st_size;
115
/* only mmap() if we have a file greater than 0 bytes */
118
/* mmap() the file - allocate one extra byte for processing zero-byte files */
120
(void *)mmap(0, file_size, PROT_READ, MAP_PRIVATE, fd,
123
my_free(new_mmapfile);
130
/* populate struct info for later use */
131
new_mmapfile->path = (char *)strdup(filename);
132
new_mmapfile->fd = fd;
133
new_mmapfile->file_size = (unsigned long)file_size;
134
new_mmapfile->current_position = 0L;
135
new_mmapfile->current_line = 0L;
136
new_mmapfile->mmap_buf = mmap_buf;
141
/* close a file originally opened via mmap() */
142
int mmap_fclose(mmapfile * temp_mmapfile) {
144
if(temp_mmapfile == NULL)
147
/* un-mmap() the file */
148
if(temp_mmapfile->file_size > 0L)
149
munmap(temp_mmapfile->mmap_buf, temp_mmapfile->file_size);
152
close(temp_mmapfile->fd);
155
my_free(temp_mmapfile->path);
156
my_free(temp_mmapfile);
161
/* gets one line of input from an mmap()'ed file */
162
char *mmap_fgets(mmapfile * temp_mmapfile) {
164
unsigned long x = 0L;
167
if(temp_mmapfile == NULL)
170
/* size of file is 0 bytes */
171
if(temp_mmapfile->file_size == 0L)
174
/* we've reached the end of the file */
175
if(temp_mmapfile->current_position >= temp_mmapfile->file_size)
178
/* find the end of the string (or buffer) */
179
for(x = temp_mmapfile->current_position; x < temp_mmapfile->file_size;
181
if(*((char *)(temp_mmapfile->mmap_buf) + x) == '\n') {
187
/* calculate length of line we just read */
188
len = (int)(x - temp_mmapfile->current_position);
190
/* allocate memory for the new line */
191
if((buf = (char *)malloc(len + 1)) == NULL)
194
/* copy string to newly allocated memory and terminate the string */
196
((char *)(temp_mmapfile->mmap_buf) +
197
temp_mmapfile->current_position), len);
200
/* update the current position */
201
temp_mmapfile->current_position = x;
203
/* increment the current line */
204
temp_mmapfile->current_line++;
209
/* gets one line of input from an mmap()'ed file (may be contained on more than one line in the source file) */
210
char *mmap_fgets_multiline(mmapfile * temp_mmapfile) {
212
char *tempbuf = NULL;
213
char *stripped = NULL;
218
if(temp_mmapfile == NULL)
225
if((tempbuf = mmap_fgets(temp_mmapfile)) == NULL)
229
len = strlen(tempbuf);
230
if((buf = (char *)malloc(len + 1)) == NULL)
232
memcpy(buf, tempbuf, len);
236
/* strip leading white space from continuation lines */
238
while(*stripped == ' ' || *stripped == '\t')
240
len = strlen(stripped);
243
(char *)realloc(buf, len + len2 + 1)) == NULL)
245
strcat(buf, stripped);
253
/* handle Windows/DOS CR/LF */
254
if(len >= 2 && buf[len - 2] == '\r')
257
else if(len >= 1 && buf[len - 1] == '\n')
262
/* two backslashes found. unescape first backslash first and break */
263
if(end >= 1 && buf[end - 1] == '\\' && buf[end] == '\\') {
265
buf[end + 1] = '\x0';
269
/* one backslash found. continue reading the next line */
270
else if(end > 0 && buf[end] == '\\')
273
/* no continuation marker was found, so break */
283
/* strip newline, carriage return, and tab characters from beginning and end of a string */
284
void strip(char *buffer) {
288
if(buffer == NULL || buffer[0] == '\x0')
291
/* strip end of string */
292
len = (int)strlen(buffer);
293
for(x = len - 1; x >= 0; x--) {
305
/* if we stripped all of it, just return */
309
/* save last position for later... */
312
/* strip beginning of string (by shifting) */
313
/* NOTE: this is very expensive to do, so avoid it whenever possible */
326
/* new length of the string after we stripped the end */
329
/* shift chars towards beginning of string to remove leading whitespace */
330
for(z = x; z < len; z++)
331
buffer[z - x] = buffer[z];
332
buffer[len - x] = '\x0';
336
/**************************************************
337
*************** HASH FUNCTIONS *******************
338
**************************************************/
339
/* dual hash function */
340
int hashfunc(const char *name1, const char *name2, int hashslots) {
341
unsigned int i, result;
346
for(i = 0; i < strlen(name1); i++)
350
for(i = 0; i < strlen(name2); i++)
353
result = result % hashslots;
358
/* dual hash data comparison */
359
int compare_hashdata(const char *val1a, const char *val1b, const char *val2a,
363
/* NOTE: If hash calculation changes, update the compare_strings() function! */
365
/* check first name */
366
if(val1a == NULL && val2a == NULL)
368
else if(val1a == NULL)
370
else if(val2a == NULL)
373
result = strcmp(val1a, val2a);
375
/* check second name if necessary */
377
if(val1b == NULL && val2b == NULL)
379
else if(val1b == NULL)
381
else if(val2b == NULL)
384
result = strcmp(val1b, val2b);
390
* given a date/time in time_t format, produce a corresponding
391
* date/time string, including timezone
393
void get_datetime_string(time_t * raw_time, char *buffer, int buffer_length,
396
struct tm *tm_ptr, tm_s;
403
char *weekdays[7] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
405
"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sept",
415
if(type == HTTP_DATE_TIME)
416
tm_ptr = gmtime_r(&t, &tm_s);
418
tm_ptr = localtime_r(&t, &tm_s);
420
hour = tm_ptr->tm_hour;
421
minute = tm_ptr->tm_min;
422
second = tm_ptr->tm_sec;
423
month = tm_ptr->tm_mon + 1;
424
day = tm_ptr->tm_mday;
425
year = tm_ptr->tm_year + 1900;
428
tzone = (char *)(tm_ptr->tm_zone);
430
tzone = (tm_ptr->tm_isdst) ? tzname[1] : tzname[0];
433
/* ctime() style date/time */
434
if(type == LONG_DATE_TIME)
435
snprintf(buffer, buffer_length, "%s %s %d %02d:%02d:%02d %s %d",
436
weekdays[tm_ptr->tm_wday], months[tm_ptr->tm_mon], day,
437
hour, minute, second, tzone, year);
439
/* short date/time */
440
else if(type == SHORT_DATE_TIME) {
441
if(date_format == DATE_FORMAT_EURO)
442
snprintf(buffer, buffer_length,
443
"%02d-%02d-%04d %02d:%02d:%02d", day, month,
444
year, hour, minute, second);
445
else if(date_format == DATE_FORMAT_ISO8601
446
|| date_format == DATE_FORMAT_STRICT_ISO8601)
447
snprintf(buffer, buffer_length,
448
"%04d-%02d-%02d%c%02d:%02d:%02d", year, month,
451
DATE_FORMAT_STRICT_ISO8601) ? 'T' : ' ', hour,
454
snprintf(buffer, buffer_length,
455
"%02d-%02d-%04d %02d:%02d:%02d", month, day,
456
year, hour, minute, second);
460
else if(type == SHORT_DATE) {
461
if(date_format == DATE_FORMAT_EURO)
462
snprintf(buffer, buffer_length, "%02d-%02d-%04d", day,
464
else if(date_format == DATE_FORMAT_ISO8601
465
|| date_format == DATE_FORMAT_STRICT_ISO8601)
466
snprintf(buffer, buffer_length, "%04d-%02d-%02d", year,
469
snprintf(buffer, buffer_length, "%02d-%02d-%04d", month,
473
/* expiration date/time for HTTP headers */
474
else if(type == HTTP_DATE_TIME)
475
snprintf(buffer, buffer_length,
476
"%s, %02d %s %d %02d:%02d:%02d GMT",
477
weekdays[tm_ptr->tm_wday], day, months[tm_ptr->tm_mon],
478
year, hour, minute, second);
482
snprintf(buffer, buffer_length, "%02d:%02d:%02d", hour, minute,
485
buffer[buffer_length - 1] = '\x0';
488
/* get days, hours, minutes, and seconds from a raw time_t format or total seconds */
489
void get_time_breakdown(unsigned long raw_time, int *days, int *hours,
490
int *minutes, int *seconds) {
491
unsigned long temp_time;
497
temp_time = raw_time;
499
temp_days = temp_time / 86400;
500
temp_time -= (temp_days * 86400);
501
temp_hours = temp_time / 3600;
502
temp_time -= (temp_hours * 3600);
503
temp_minutes = temp_time / 60;
504
temp_time -= (temp_minutes * 60);
505
temp_seconds = (int)temp_time;
509
*minutes = temp_minutes;
510
*seconds = temp_seconds;