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

« back to all changes in this revision

Viewing changes to src/mod_dirlisting.c

  • Committer: Bazaar Package Importer
  • Author(s): Soren Hansen
  • Date: 2006-12-08 14:40:42 UTC
  • mto: (6.1.1 lenny)
  • mto: This revision was merged to the branch mainline in revision 14.
  • Revision ID: james.westby@ubuntu.com-20061208144042-ehr7h8c6xmijqipw
Tags: upstream-1.4.13
ImportĀ upstreamĀ versionĀ 1.4.13

Show diffs side-by-side

added added

removed removed

Lines of Context:
54
54
        unsigned short hide_readme_file;
55
55
        unsigned short show_header;
56
56
        unsigned short hide_header_file;
57
 
        
 
57
 
58
58
        excludes_buffer *excludes;
59
59
 
60
60
        buffer *external_css;
63
63
 
64
64
typedef struct {
65
65
        PLUGIN_DATA;
66
 
        
 
66
 
67
67
        buffer *tmp_buf;
68
68
        buffer *content_charset;
69
 
        
 
69
 
70
70
        plugin_config **config_storage;
71
 
        
72
 
        plugin_config conf; 
 
71
 
 
72
        plugin_config conf;
73
73
} plugin_data;
74
74
 
75
75
excludes_buffer *excludes_buffer_init(void) {
146
146
/* init the plugin data */
147
147
INIT_FUNC(mod_dirlisting_init) {
148
148
        plugin_data *p;
149
 
        
 
149
 
150
150
        p = calloc(1, sizeof(*p));
151
151
 
152
152
        p->tmp_buf = buffer_init();
153
153
        p->content_charset = buffer_init();
154
 
        
 
154
 
155
155
        return p;
156
156
}
157
157
 
158
158
/* detroy the plugin data */
159
159
FREE_FUNC(mod_dirlisting_free) {
160
160
        plugin_data *p = p_d;
161
 
        
 
161
 
162
162
        UNUSED(srv);
163
163
 
164
164
        if (!p) return HANDLER_GO_ON;
165
 
        
 
165
 
166
166
        if (p->config_storage) {
167
167
                size_t i;
168
168
                for (i = 0; i < srv->config_context->used; i++) {
169
169
                        plugin_config *s = p->config_storage[i];
170
 
                        
 
170
 
171
171
                        if (!s) continue;
172
 
                        
 
172
 
173
173
                        excludes_buffer_free(s->excludes);
174
174
                        buffer_free(s->external_css);
175
175
                        buffer_free(s->encoding);
176
 
                        
 
176
 
177
177
                        free(s);
178
178
                }
179
179
                free(p->config_storage);
180
180
        }
181
 
        
 
181
 
182
182
        buffer_free(p->tmp_buf);
183
183
        buffer_free(p->content_charset);
184
 
        
 
184
 
185
185
        free(p);
186
 
        
 
186
 
187
187
        return HANDLER_GO_ON;
188
188
}
189
189
 
215
215
                        if (0 != excludes_buffer_append(s->excludes,
216
216
                                    ((data_string *)(da->value->data[j]))->value)) {
217
217
#ifdef HAVE_PCRE_H
218
 
                                log_error_write(srv, __FILE__, __LINE__, "sb", 
 
218
                                log_error_write(srv, __FILE__, __LINE__, "sb",
219
219
                                                "pcre-compile failed for", ((data_string *)(da->value->data[j]))->value);
220
220
#else
221
 
                                log_error_write(srv, __FILE__, __LINE__, "s", 
 
221
                                log_error_write(srv, __FILE__, __LINE__, "s",
222
222
                                                "pcre support is missing, please install libpcre and the headers");
223
223
#endif
224
224
                        }
233
233
SETDEFAULTS_FUNC(mod_dirlisting_set_defaults) {
234
234
        plugin_data *p = p_d;
235
235
        size_t i = 0;
236
 
        
237
 
        config_values_t cv[] = { 
 
236
 
 
237
        config_values_t cv[] = {
238
238
                { "dir-listing.exclude",          NULL, T_CONFIG_LOCAL, T_CONFIG_SCOPE_CONNECTION },   /* 0 */
239
239
                { "dir-listing.activate",         NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 1 */
240
240
                { "dir-listing.hide-dotfiles",    NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 2 */
245
245
                { "dir-listing.show-header",      NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 7 */
246
246
                { "dir-listing.hide-header-file", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 8 */
247
247
                { "server.dir-listing",           NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 9 */
248
 
                
 
248
 
249
249
                { NULL,                          NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
250
250
        };
251
 
        
 
251
 
252
252
        if (!p) return HANDLER_ERROR;
253
 
        
 
253
 
254
254
        p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
255
 
        
 
255
 
256
256
        for (i = 0; i < srv->config_context->used; i++) {
257
257
                plugin_config *s;
258
258
                array *ca;
259
 
                
 
259
 
260
260
                s = calloc(1, sizeof(plugin_config));
261
261
                s->excludes = excludes_buffer_init();
262
262
                s->dir_listing = 0;
267
267
                s->show_header = 0;
268
268
                s->hide_header_file = 0;
269
269
                s->encoding = buffer_init();
270
 
                
 
270
 
271
271
                cv[0].destination = s->excludes;
272
272
                cv[1].destination = &(s->dir_listing);
273
273
                cv[2].destination = &(s->hide_dot_files);
307
307
        PATCH(show_header);
308
308
        PATCH(hide_header_file);
309
309
        PATCH(excludes);
310
 
        
 
310
 
311
311
        /* skip the first, the global context */
312
312
        for (i = 1; i < srv->config_context->used; i++) {
313
313
                data_config *dc = (data_config *)srv->config_context->data[i];
314
314
                s = p->config_storage[i];
315
 
                
 
315
 
316
316
                /* condition didn't match */
317
317
                if (!config_check_cond(srv, con, dc)) continue;
318
 
                
 
318
 
319
319
                /* merge config */
320
320
                for (j = 0; j < dc->value->used; j++) {
321
321
                        data_unset *du = dc->value->data[j];
322
 
                        
 
322
 
323
323
                        if (buffer_is_equal_string(du->key, CONST_STR_LEN("dir-listing.activate")) ||
324
324
                            buffer_is_equal_string(du->key, CONST_STR_LEN("server.dir-listing"))) {
325
325
                                PATCH(dir_listing);
342
342
                        }
343
343
                }
344
344
        }
345
 
        
 
345
 
346
346
        return 0;
347
347
}
348
348
#undef PATCH
432
432
 
433
433
static void http_list_directory_header(server *srv, connection *con, plugin_data *p, buffer *out) {
434
434
        UNUSED(srv);
435
 
        
 
435
 
436
436
        BUFFER_APPEND_STRING_CONST(out,
437
437
                "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.1//EN\" \"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd\">\n"
438
438
                "<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\">\n"
492
492
        if (p->conf.show_header) {
493
493
                stream s;
494
494
                /* if we have a HEADER file, display it in <pre class="header"></pre> */
495
 
                
 
495
 
496
496
                buffer_copy_string_buffer(p->tmp_buf, con->physical.path);
497
497
                BUFFER_APPEND_SLASH(p->tmp_buf);
498
498
                BUFFER_APPEND_STRING_CONST(p->tmp_buf, "HEADER.txt");
499
 
                
 
499
 
500
500
                if (-1 != stream_open(&s, p->tmp_buf)) {
501
501
                        BUFFER_APPEND_STRING_CONST(out, "<pre class=\"header\">");
502
502
                        buffer_append_string_encoded(out, s.start, s.size, ENCODING_MINIMAL_XML);
531
531
 
532
532
static void http_list_directory_footer(server *srv, connection *con, plugin_data *p, buffer *out) {
533
533
        UNUSED(srv);
534
 
        
 
534
 
535
535
        BUFFER_APPEND_STRING_CONST(out,
536
536
                "</tbody>\n"
537
537
                "</table>\n"
538
538
                "</div>\n"
539
539
        );
540
 
        
 
540
 
541
541
        if (p->conf.show_readme) {
542
542
                stream s;
543
543
                /* if we have a README file, display it in <pre class="readme"></pre> */
544
 
                
 
544
 
545
545
                buffer_copy_string_buffer(p->tmp_buf,  con->physical.path);
546
546
                BUFFER_APPEND_SLASH(p->tmp_buf);
547
547
                BUFFER_APPEND_STRING_CONST(p->tmp_buf, "README.txt");
548
 
                
 
548
 
549
549
                if (-1 != stream_open(&s, p->tmp_buf)) {
550
550
                        BUFFER_APPEND_STRING_CONST(out, "<pre class=\"readme\">");
551
551
                        buffer_append_string_encoded(out, s.start, s.size, ENCODING_MINIMAL_XML);
553
553
                }
554
554
                stream_close(&s);
555
555
        }
556
 
        
 
556
 
557
557
        BUFFER_APPEND_STRING_CONST(out,
558
558
                "<div class=\"foot\">"
559
559
        );
595
595
#endif
596
596
 
597
597
        if (dir->used == 0) return -1;
598
 
        
 
598
 
599
599
        i = dir->used - 1;
600
600
 
601
601
#ifdef HAVE_PATHCONF
611
611
#else
612
612
        name_max = NAME_MAX;
613
613
#endif
614
 
        
 
614
 
615
615
        path = malloc(dir->used + name_max);
616
616
        assert(path);
617
617
        strcpy(path, dir->ptr);
618
618
        path_file = path + i;
619
619
 
620
620
        if (NULL == (dp = opendir(path))) {
621
 
                log_error_write(srv, __FILE__, __LINE__, "sbs", 
 
621
                log_error_write(srv, __FILE__, __LINE__, "sbs",
622
622
                        "opendir failed:", dir, strerror(errno));
623
623
 
624
624
                free(path);
633
633
        assert(files.ent);
634
634
        files.size = DIRLIST_BLOB_SIZE;
635
635
        files.used = 0;
636
 
        
 
636
 
637
637
        while ((dent = readdir(dp)) != NULL) {
638
638
                unsigned short exclude_match = 0;
639
639
 
686
686
#endif
687
687
 
688
688
                i = strlen(dent->d_name);
689
 
                
 
689
 
690
690
                /* NOTE: the manual says, d_name is never more than NAME_MAX
691
691
                 *       so this should actually not be a buffer-overflow-risk
692
692
                 */
693
693
                if (i > (size_t)name_max) continue;
694
 
                
 
694
 
695
695
                memcpy(path_file, dent->d_name, i + 1);
696
696
                if (stat(path, &st) != 0)
697
697
                        continue;
740
740
#else
741
741
                strftime(datebuf, sizeof(datebuf), "%Y-%b-%d %H:%M:%S", localtime(&(tmp->mtime)));
742
742
#endif
743
 
                
 
743
 
744
744
                BUFFER_APPEND_STRING_CONST(out, "<tr><td class=\"n\"><a href=\"");
745
745
                buffer_append_string_encoded(out, DIRLIST_ENT_NAME(tmp), tmp->namelen, ENCODING_REL_URI_PART);
746
746
                BUFFER_APPEND_STRING_CONST(out, "/\">");
758
758
 
759
759
                content_type = NULL;
760
760
#ifdef HAVE_XATTR
761
 
                
 
761
 
762
762
                if (con->conf.use_xattr) {
763
763
                        memcpy(path_file, DIRLIST_ENT_NAME(tmp), tmp->namelen + 1);
764
764
                        attrlen = sizeof(attrval) - 1;
768
768
                        }
769
769
                }
770
770
#endif
771
 
                
 
771
 
772
772
                if (content_type == NULL) {
773
773
                        content_type = "application/octet-stream";
774
774
                        for (k = 0; k < con->conf.mimetypes->used; k++) {
788
788
                                }
789
789
                        }
790
790
                }
791
 
                        
 
791
 
792
792
#ifdef HAVE_LOCALTIME_R
793
793
                localtime_r(&(tmp->mtime), &tm);
794
794
                strftime(datebuf, sizeof(datebuf), "%Y-%b-%d %H:%M:%S", &tm);
837
837
URIHANDLER_FUNC(mod_dirlisting_subrequest) {
838
838
        plugin_data *p = p_d;
839
839
        stat_cache_entry *sce = NULL;
840
 
        
 
840
 
841
841
        UNUSED(srv);
842
 
        
 
842
 
843
843
        if (con->physical.path->used == 0) return HANDLER_GO_ON;
844
844
        if (con->uri.path->used == 0) return HANDLER_GO_ON;
845
845
        if (con->uri.path->ptr[con->uri.path->used - 2] != '/') return HANDLER_GO_ON;
846
 
        
 
846
 
847
847
        mod_dirlisting_patch_connection(srv, con, p);
848
848
 
849
849
        if (!p->conf.dir_listing) return HANDLER_GO_ON;
850
 
        
 
850
 
851
851
        if (con->conf.log_request_handling) {
852
852
                log_error_write(srv, __FILE__, __LINE__,  "s",  "-- handling the request as Dir-Listing");
853
853
                log_error_write(srv, __FILE__, __LINE__,  "sb", "URI          :", con->uri.path);
854
854
        }
855
 
        
 
855
 
856
856
        if (HANDLER_ERROR == stat_cache_get_entry(srv, con, con->physical.path, &sce)) {
857
857
                fprintf(stderr, "%s.%d: %s\n", __FILE__, __LINE__, con->physical.path->ptr);
858
858
                SEGFAULT();
859
859
        }
860
 
        
 
860
 
861
861
        if (!S_ISDIR(sce->st.st_mode)) return HANDLER_GO_ON;
862
 
        
 
862
 
863
863
        if (http_list_directory(srv, con, p, con->physical.path)) {
864
864
                /* dirlisting failed */
865
865
                con->http_status = 403;
866
866
        }
867
 
        
 
867
 
868
868
        buffer_reset(con->physical.path);
869
 
        
 
869
 
870
870
        /* not found */
871
871
        return HANDLER_FINISHED;
872
872
}
876
876
int mod_dirlisting_plugin_init(plugin *p) {
877
877
        p->version     = LIGHTTPD_VERSION_ID;
878
878
        p->name        = buffer_init_string("dirlisting");
879
 
        
 
879
 
880
880
        p->init        = mod_dirlisting_init;
881
881
        p->handle_subrequest_start  = mod_dirlisting_subrequest;
882
882
        p->set_defaults  = mod_dirlisting_set_defaults;
883
883
        p->cleanup     = mod_dirlisting_free;
884
 
        
 
884
 
885
885
        p->data        = NULL;
886
 
        
 
886
 
887
887
        return 0;
888
888
}