~ubuntu-branches/ubuntu/natty/lighttpd/natty

« back to all changes in this revision

Viewing changes to src/mod_accesslog.c

  • Committer: Bazaar Package Importer
  • Author(s): Krzysztof Krzyżaniak (eloy)
  • Date: 2009-10-30 17:37:29 UTC
  • mto: (6.1.4 squeeze)
  • mto: This revision was merged to the branch mainline in revision 50.
  • Revision ID: james.westby@ubuntu.com-20091030173729-ehmsdiba9nkcd0j7
Tags: upstream-1.4.24
Import upstream version 1.4.24

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
#define _GNU_SOURCE
 
1
#include "base.h"
 
2
#include "log.h"
 
3
#include "buffer.h"
 
4
 
 
5
#include "plugin.h"
 
6
 
 
7
#include "inet_ntop_cache.h"
 
8
 
 
9
#include "sys-socket.h"
2
10
 
3
11
#include <sys/types.h>
4
12
#include <sys/stat.h>
13
21
 
14
22
#include <stdio.h>
15
23
 
16
 
#include "base.h"
17
 
#include "log.h"
18
 
#include "buffer.h"
19
 
 
20
 
#include "plugin.h"
21
 
 
22
 
#include "inet_ntop_cache.h"
23
 
 
24
 
#include "sys-socket.h"
25
 
 
26
24
#ifdef HAVE_SYSLOG_H
27
25
# include <syslog.h>
28
26
#endif
137
135
 
138
136
        buffer *access_logbuffer;
139
137
        buffer *ts_accesslog_str;
 
138
        buffer *ts_accesslog_fmt_str;
 
139
        unsigned short append_tz_offset;
140
140
 
141
141
        format_fields *parsed_format;
142
142
} plugin_config;
156
156
        return p;
157
157
}
158
158
 
 
159
static void accesslog_append_escaped(buffer *dest, buffer *str) {
 
160
        /* replaces non-printable chars with \xHH where HH is the hex representation of the byte */
 
161
        /* exceptions: " => \", \ => \\, whitespace chars => \n \t etc. */
 
162
        if (str->used == 0) return;
 
163
        buffer_prepare_append(dest, str->used - 1);
 
164
 
 
165
        for (unsigned int i = 0; i < str->used - 1; i++) {
 
166
                if (str->ptr[i] >= ' ' && str->ptr[i] <= '~') {
 
167
                        /* printable chars */
 
168
                        buffer_append_string_len(dest, &str->ptr[i], 1);
 
169
                } else switch (str->ptr[i]) {
 
170
                case '"':
 
171
                        BUFFER_APPEND_STRING_CONST(dest, "\\\"");
 
172
                        break;
 
173
                case '\\':
 
174
                        BUFFER_APPEND_STRING_CONST(dest, "\\\\");
 
175
                        break;
 
176
                case '\b':
 
177
                        BUFFER_APPEND_STRING_CONST(dest, "\\b");
 
178
                        break;
 
179
                case '\n':
 
180
                        BUFFER_APPEND_STRING_CONST(dest, "\\n");
 
181
                        break;
 
182
                case '\r':
 
183
                        BUFFER_APPEND_STRING_CONST(dest, "\\r");
 
184
                        break;
 
185
                case '\t':
 
186
                        BUFFER_APPEND_STRING_CONST(dest, "\\t");
 
187
                        break;
 
188
                case '\v':
 
189
                        BUFFER_APPEND_STRING_CONST(dest, "\\v");
 
190
                        break;
 
191
                default: {
 
192
                                /* non printable char => \xHH */
 
193
                                char hh[5] = {'\\','x',0,0,0};
 
194
                                char h = str->ptr[i] / 16;
 
195
                                hh[2] = (h > 9) ? (h - 10 + 'A') : (h + '0');
 
196
                                h = str->ptr[i] % 16;
 
197
                                hh[3] = (h > 9) ? (h - 10 + 'A') : (h + '0');
 
198
                                buffer_append_string_len(dest, &hh[0], 4);
 
199
                        }
 
200
                        break;
 
201
                }
 
202
        }
 
203
}
 
204
 
159
205
static int accesslog_parse_format(server *srv, format_fields *fields, buffer *format) {
160
206
        size_t i, j, k = 0, start = 0;
161
207
 
367
413
                        if (s->log_access_fd != -1) close(s->log_access_fd);
368
414
 
369
415
                        buffer_free(s->ts_accesslog_str);
 
416
                        buffer_free(s->ts_accesslog_fmt_str);
370
417
                        buffer_free(s->access_logbuffer);
371
418
                        buffer_free(s->format);
372
419
                        buffer_free(s->access_logfile);
415
462
                s->format = buffer_init();
416
463
                s->access_logbuffer = buffer_init();
417
464
                s->ts_accesslog_str = buffer_init();
 
465
                s->ts_accesslog_fmt_str = buffer_init();
418
466
                s->log_access_fd = -1;
419
467
                s->last_generated_accesslog_ts = 0;
420
468
                s->last_generated_accesslog_ts_ptr = &(s->last_generated_accesslog_ts);
439
487
                /* parse */
440
488
 
441
489
                if (s->format->used) {
 
490
                        size_t j, count;
 
491
 
442
492
                        s->parsed_format = calloc(1, sizeof(*(s->parsed_format)));
443
493
 
444
494
                        if (-1 == accesslog_parse_format(srv, s->parsed_format, s->format)) {
448
498
 
449
499
                                return HANDLER_ERROR;
450
500
                        }
 
501
 
 
502
                        /* make sure they didn't try to send the timestamp in twice...
 
503
                         * also, save the format string in a different variable (this
 
504
                         * will save a few conditionals later)
 
505
                         */
 
506
                        count = 0;
 
507
                        for (j = 0; j < s->parsed_format->used; j++) {
 
508
                                if (FIELD_FORMAT == s->parsed_format->ptr[j]->type) {
 
509
                                        if (FORMAT_TIMESTAMP == s->parsed_format->ptr[j]->field) {
 
510
                                                if (!buffer_is_empty(s->parsed_format->ptr[j]->string)) {
 
511
                                                        buffer_copy_string(s->ts_accesslog_fmt_str, s->parsed_format->ptr[j]->string->ptr);
 
512
                                                }
 
513
 
 
514
                                                if (++count > 1) {
 
515
                                                        log_error_write(srv, __FILE__, __LINE__, "sb",
 
516
                                                                "you may not use the timestamp twice in the same access log:", s->format);
 
517
 
 
518
                                                        return HANDLER_ERROR;
 
519
                                                }
 
520
                                        }
 
521
                                }
 
522
                        }
 
523
 
451
524
#if 0
452
525
                        /* debugging */
453
526
                        for (j = 0; j < s->parsed_format->used; j++) {
468
541
#endif
469
542
                }
470
543
 
 
544
                s->append_tz_offset = 0;
 
545
                if (buffer_is_empty(s->ts_accesslog_fmt_str)) {
 
546
#if defined(HAVE_STRUCT_TM_GMTOFF)
 
547
                        BUFFER_COPY_STRING_CONST(s->ts_accesslog_fmt_str, "[%d/%b/%Y:%H:%M:%S ");
 
548
                        s->append_tz_offset = 1;
 
549
#else
 
550
                        BUFFER_COPY_STRING_CONST(s->ts_accesslog_fmt_str, "[%d/%b/%Y:%H:%M:%S +0000]");
 
551
#endif
 
552
                }
 
553
 
471
554
                if (s->use_syslog) {
472
555
                        /* ignore the next checks */
473
556
                        continue;
541
624
        PATCH(last_generated_accesslog_ts_ptr);
542
625
        PATCH(access_logbuffer);
543
626
        PATCH(ts_accesslog_str);
 
627
        PATCH(ts_accesslog_fmt_str);
 
628
        PATCH(append_tz_offset);
544
629
        PATCH(parsed_format);
545
630
        PATCH(use_syslog);
546
631
 
559
644
                        if (buffer_is_equal_string(du->key, CONST_STR_LEN("accesslog.filename"))) {
560
645
                                PATCH(access_logfile);
561
646
                                PATCH(log_access_fd);
562
 
                                PATCH(last_generated_accesslog_ts_ptr);
563
647
                                PATCH(access_logbuffer);
564
 
                                PATCH(ts_accesslog_str);
565
648
                        } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("accesslog.format"))) {
566
649
                                PATCH(format);
567
650
                                PATCH(parsed_format);
 
651
                                PATCH(last_generated_accesslog_ts_ptr);
 
652
                                PATCH(ts_accesslog_str);
 
653
                                PATCH(ts_accesslog_fmt_str);
 
654
                                PATCH(append_tz_offset);
568
655
                        } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("accesslog.use-syslog"))) {
569
656
                                PATCH(use_syslog);
570
 
                                PATCH(last_generated_accesslog_ts_ptr);
571
657
                                PATCH(access_logbuffer);
572
 
                                PATCH(ts_accesslog_str);
573
658
                        }
574
659
                }
575
660
        }
616
701
#if defined(HAVE_STRUCT_TM_GMTOFF)
617
702
# ifdef HAVE_LOCALTIME_R
618
703
                                        localtime_r(&(srv->cur_ts), &tm);
619
 
                                        strftime(p->conf.ts_accesslog_str->ptr, p->conf.ts_accesslog_str->size - 1, "[%d/%b/%Y:%H:%M:%S ", &tm);
620
 
# else
621
 
                                        strftime(p->conf.ts_accesslog_str->ptr, p->conf.ts_accesslog_str->size - 1, "[%d/%b/%Y:%H:%M:%S ", localtime(&(srv->cur_ts)));
622
 
# endif
 
704
                                        strftime(p->conf.ts_accesslog_str->ptr, p->conf.ts_accesslog_str->size - 1, p->conf.ts_accesslog_fmt_str->ptr, &tm);
 
705
# else /* HAVE_LOCALTIME_R */
 
706
                                        strftime(p->conf.ts_accesslog_str->ptr, p->conf.ts_accesslog_str->size - 1, p->conf.ts_accesslog_fmt_str->ptr, localtime_r(&(srv->cur_ts)));
 
707
# endif /* HAVE_LOCALTIME_R */
623
708
                                        p->conf.ts_accesslog_str->used = strlen(p->conf.ts_accesslog_str->ptr) + 1;
624
709
 
625
 
                                        buffer_append_string_len(p->conf.ts_accesslog_str, tm.tm_gmtoff >= 0 ? "+" : "-", 1);
626
 
 
627
 
                                        scd = abs(tm.tm_gmtoff);
628
 
                                        hrs = scd / 3600;
629
 
                                        min = (scd % 3600) / 60;
630
 
 
631
 
                                        /* hours */
632
 
                                        if (hrs < 10) buffer_append_string_len(p->conf.ts_accesslog_str, CONST_STR_LEN("0"));
633
 
                                        buffer_append_long(p->conf.ts_accesslog_str, hrs);
634
 
 
635
 
                                        if (min < 10) buffer_append_string_len(p->conf.ts_accesslog_str, CONST_STR_LEN("0"));
636
 
                                        buffer_append_long(p->conf.ts_accesslog_str, min);
637
 
                                        buffer_append_string_len(p->conf.ts_accesslog_str, CONST_STR_LEN("]"));
638
 
#else
639
 
#ifdef HAVE_GMTIME_R
 
710
                                        if (p->conf.append_tz_offset) {
 
711
                                                buffer_append_string_len(p->conf.ts_accesslog_str, tm.tm_gmtoff >= 0 ? "+" : "-", 1);
 
712
 
 
713
                                                scd = abs(tm.tm_gmtoff);
 
714
                                                hrs = scd / 3600;
 
715
                                                min = (scd % 3600) / 60;
 
716
 
 
717
                                                /* hours */
 
718
                                                if (hrs < 10) buffer_append_string_len(p->conf.ts_accesslog_str, CONST_STR_LEN("0"));
 
719
                                                buffer_append_long(p->conf.ts_accesslog_str, hrs);
 
720
 
 
721
                                                if (min < 10) buffer_append_string_len(p->conf.ts_accesslog_str, CONST_STR_LEN("0"));
 
722
                                                buffer_append_long(p->conf.ts_accesslog_str, min);
 
723
                                                buffer_append_string_len(p->conf.ts_accesslog_str, CONST_STR_LEN("]"));
 
724
                                        }
 
725
#else /* HAVE_STRUCT_TM_GMTOFF */
 
726
# ifdef HAVE_GMTIME_R
640
727
                                        gmtime_r(&(srv->cur_ts), &tm);
641
 
                                        strftime(p->conf.ts_accesslog_str->ptr, p->conf.ts_accesslog_str->size - 1, "[%d/%b/%Y:%H:%M:%S +0000]", &tm);
642
 
#else
643
 
                                        strftime(p->conf.ts_accesslog_str->ptr, p->conf.ts_accesslog_str->size - 1, "[%d/%b/%Y:%H:%M:%S +0000]", gmtime(&(srv->cur_ts)));
644
 
#endif
 
728
                                        strftime(p->conf.ts_accesslog_str->ptr, p->conf.ts_accesslog_str->size - 1, p->conf.ts_accesslog_fmt_str->ptr, &tm);
 
729
# else /* HAVE_GMTIME_R */
 
730
                                        strftime(p->conf.ts_accesslog_str->ptr, p->conf.ts_accesslog_str->size - 1, p->conf.ts_accesslog_fmt_str->ptr, gmtime(&(srv->cur_ts)));
 
731
# endif /* HAVE_GMTIME_R */
645
732
                                        p->conf.ts_accesslog_str->used = strlen(p->conf.ts_accesslog_str->ptr) + 1;
646
 
#endif
 
733
#endif /* HAVE_STRUCT_TM_GMTOFF */
647
734
 
648
735
                                        *(p->conf.last_generated_accesslog_ts_ptr) = srv->cur_ts;
649
736
                                        newts = 1;
672
759
                                break;
673
760
                        case FORMAT_REQUEST_LINE:
674
761
                                if (con->request.request_line->used) {
675
 
                                        buffer_append_string_buffer(b, con->request.request_line);
 
762
                                        accesslog_append_escaped(b, con->request.request_line);
676
763
                                }
677
764
                                break;
678
765
                        case FORMAT_STATUS:
689
776
                                break;
690
777
                        case FORMAT_HEADER:
691
778
                                if (NULL != (ds = (data_string *)array_get_element(con->request.headers, p->conf.parsed_format->ptr[j]->string->ptr))) {
692
 
                                        buffer_append_string_buffer(b, ds->value);
 
779
                                        accesslog_append_escaped(b, ds->value);
693
780
                                } else {
694
781
                                        buffer_append_string_len(b, CONST_STR_LEN("-"));
695
782
                                }
696
783
                                break;
697
784
                        case FORMAT_RESPONSE_HEADER:
698
785
                                if (NULL != (ds = (data_string *)array_get_element(con->response.headers, p->conf.parsed_format->ptr[j]->string->ptr))) {
699
 
                                        buffer_append_string_buffer(b, ds->value);
 
786
                                        accesslog_append_escaped(b, ds->value);
700
787
                                } else {
701
788
                                        buffer_append_string_len(b, CONST_STR_LEN("-"));
702
789
                                }
734
821
                                break;
735
822
                        case FORMAT_HTTP_HOST:
736
823
                                if (con->uri.authority->used > 1) {
737
 
                                        buffer_append_string_buffer(b, con->uri.authority);
 
824
                                        accesslog_append_escaped(b, con->uri.authority);
738
825
                                } else {
739
826
                                        buffer_append_string_len(b, CONST_STR_LEN("-"));
740
827
                                }
760
847
                                }
761
848
                                break;
762
849
                        case FORMAT_QUERY_STRING:
763
 
                                buffer_append_string_buffer(b, con->uri.query);
 
850
                                accesslog_append_escaped(b, con->uri.query);
764
851
                                break;
765
852
                        case FORMAT_URL:
766
 
                                buffer_append_string_buffer(b, con->uri.path_raw);
 
853
                                accesslog_append_escaped(b, con->uri.path_raw);
767
854
                                break;
768
855
                        case FORMAT_CONNECTION_STATUS:
769
856
                                switch(con->keep_alive) {