--- modules/generators/mod_autoindex.c.old Sun Nov 11 23:32:47 2007 +++ modules/generators/mod_autoindex.c Sun Nov 11 23:33:51 2007 @@ -72,7 +72,8 @@ #define SHOW_FORBIDDEN (1 << 18) #define OPTION_UNSET (1 << 19) #define OPTION_UNSET (1 << 19) +#define ALWAYS_EMIT_H1 (1 << 31) #define K_NOADJUST 0 #define K_ADJUST 1 @@ -101,6 +102,13 @@ #define DEFAULT_NAME_WIDTH 23 #define DEFAULT_DESC_WIDTH 23 +/* + * Thumbnail types + */ +#define THUMB_NONE 'n' +#define THUMB_STATIC 's' +#define THUMB_DYNAMIC 'd' + struct item { char *type; char *apply_to; @@ -136,6 +144,8 @@ apr_array_header_t *desc_list; apr_array_header_t *ign_list; apr_array_header_t *hdr_list; + apr_array_header_t *mnu_list; + apr_array_header_t *thb_list; apr_array_header_t *rdme_list; char *ctype; @@ -148,6 +158,8 @@ #define BY_TYPE &c_by_type #define BY_PATH &c_by_path +static char overall_thumb_type = THUMB_NONE; + /* * This routine puts the standard HTML header at the top of the index page. * We include the DOCTYPE because we may be using features therefrom (i.e., @@ -167,6 +179,16 @@ ap_rvputs(r, " style_sheet, "\" type=\"text/css\"", xhtml ? " />\n" : ">\n", NULL); } + if (overall_thumb_type != THUMB_NONE) { + ap_rvputs(r, " \n" : ">\n", NULL); + } + if (overall_thumb_type == THUMB_DYNAMIC) { + ap_rvputs(r, "", NULL); + } ap_rvputs(r, " \n \n", NULL); } @@ -307,6 +329,19 @@ return NULL; } +static const char *add_menu(cmd_parms *cmd, void *d, const char *name) +{ + push_item(((autoindex_config_rec *) d)->mnu_list, 0, NULL, cmd->path, + name); + return NULL; +} + +static const char *add_thumb(cmd_parms *cmd, void *d, const char *type, const char* to) +{ + push_item(((autoindex_config_rec *) d)->thb_list, cmd->info, to, cmd->path, type); + return NULL; +} + static const char *add_readme(cmd_parms *cmd, void *d, const char *name) { push_item(((autoindex_config_rec *) d)->rdme_list, 0, NULL, cmd->path, @@ -389,6 +424,9 @@ else if (!strcasecmp(w, "XHTML")) { option = EMIT_XHTML; } + else if (!strcasecmp(w, "AlwaysEmitH1")) { + option = ALWAYS_EMIT_H1; + } else if (!strcasecmp(w, "ShowForbidden")) { option = SHOW_FORBIDDEN; } @@ -574,6 +612,10 @@ "Descriptive text followed by one or more filenames"), AP_INIT_TAKE1("HeaderName", add_header, NULL, DIR_CMD_PERMS, "a filename"), + AP_INIT_TAKE1("MenuName", add_menu, NULL, DIR_CMD_PERMS, + "a filename"), + AP_INIT_ITERATE2("AddThumbByType", add_thumb, BY_TYPE, DIR_CMD_PERMS, + "set default thumb type for one or more MIME types"), AP_INIT_TAKE1("ReadmeName", add_readme, NULL, DIR_CMD_PERMS, "a filename"), AP_INIT_RAW_ARGS("FancyIndexing", ap_set_deprecated, NULL, OR_ALL, @@ -604,6 +646,8 @@ new->desc_list = apr_array_make(p, 4, sizeof(ai_desc_t)); new->ign_list = apr_array_make(p, 4, sizeof(struct item)); new->hdr_list = apr_array_make(p, 4, sizeof(struct item)); + new->mnu_list = apr_array_make(p, 4, sizeof(struct item)); + new->thb_list = apr_array_make(p, 4, sizeof(struct item)); new->rdme_list = apr_array_make(p, 4, sizeof(struct item)); new->opts = 0; new->incremented_opts = 0; @@ -634,6 +678,8 @@ new->alt_list = apr_array_append(p, add->alt_list, base->alt_list); new->ign_list = apr_array_append(p, add->ign_list, base->ign_list); new->hdr_list = apr_array_append(p, add->hdr_list, base->hdr_list); + new->mnu_list = apr_array_append(p, add->mnu_list, base->mnu_list); + new->thb_list = apr_array_append(p, add->thb_list, base->thb_list); new->desc_list = apr_array_append(p, add->desc_list, base->desc_list); new->icon_list = apr_array_append(p, add->icon_list, base->icon_list); new->rdme_list = apr_array_append(p, add->rdme_list, base->rdme_list); @@ -722,6 +768,8 @@ struct ent { char *name; char *icon; + char *thumb; + int thumb_type; char *alt; char *desc; apr_off_t size; @@ -781,6 +829,8 @@ #define find_icon(d,p,t) find_item(p,d->icon_list,t) #define find_alt(d,p,t) find_item(p,d->alt_list,t) #define find_header(d,p) find_item(p,d->hdr_list,0) +#define find_menu(d,p) find_item(p,d->mnu_list,0) +#define find_thumb(d,p) find_item(p,d->thb_list,0) #define find_readme(d,p) find_item(p,d->rdme_list,0) static char *find_default_item(char *bogus_name, apr_array_header_t *list) @@ -912,7 +962,7 @@ * Header file * Emitted if found (and able). * H1 tag line - * Emitted if a header file is NOT emitted. + * Emitted if a header file is NOT emitted OR ALWAYS_EMIT_H1 is set. * Directory stuff * Always emitted. * HR @@ -984,11 +1034,13 @@ * oh well. */ static void emit_head(request_rec *r, char *header_fname, int suppress_amble, - int emit_xhtml, char *title) + int emit_xhtml, char *title, int always_emit_H1, + char *menu_fname) { apr_table_t *hdrs = r->headers_in; apr_file_t *f = NULL; request_rec *rr = NULL; + request_rec *rr_menu = NULL; int emit_amble = 1; int emit_H1 = 1; const char *r_accept; @@ -1008,6 +1060,10 @@ header_fname = apr_pstrcat(r->pool, header_fname, "?", r->args, NULL); } + if ((menu_fname != NULL) && r->args) { + menu_fname = apr_pstrcat(r->pool, menu_fname, "?", r->args, NULL); + } + if ((header_fname != NULL) && (rr = ap_sub_req_lookup_uri(header_fname, r, r->output_filters)) && (rr->status == HTTP_OK) @@ -1075,6 +1131,34 @@ } } + if ((menu_fname != NULL) + && (rr_menu = ap_sub_req_lookup_uri(menu_fname, r, r->output_filters)) + && (rr_menu->status == HTTP_OK) + && (rr_menu->filename != NULL) + && (rr_menu->finfo.filetype == APR_REG)) { + + if (rr_menu->content_type != NULL) { + if (!strcasecmp(ap_field_noparam(r->pool, rr_menu->content_type), + "text/html")) { + ap_filter_t *f; + + if (emit_amble) { + emit_preamble(r, emit_xhtml, title); + } + + /* copy of hack from rr / header_fname request */ + for (f=rr_menu->output_filters; + f->frec != ap_subreq_core_filter_handle; f = f->next); + f->next = r->output_filters; + + if (ap_run_sub_req(rr_menu) == OK) { + /* success */ + emit_amble = 0; + } + } + } + } + if (r_accept) { apr_table_setn(hdrs, "Accept", r_accept); } @@ -1089,12 +1173,15 @@ if (emit_amble) { emit_preamble(r, emit_xhtml, title); } - if (emit_H1) { - ap_rvputs(r, "

Index of ", title, "

\n", NULL); + if (emit_H1 || always_emit_H1) { + ap_rvputs(r, "

Index of ", title, "

\n", NULL); } if (rr != NULL) { ap_destroy_sub_req(rr); } + if (rr_menu != NULL) { + ap_destroy_sub_req(rr_menu); + } } @@ -1281,10 +1368,12 @@ autoindex_config_rec *d, request_rec *r, char keyid, char direction, - const char *pattern) + const char *pattern, + const char *thumb_cookie) { request_rec *rr; struct ent *p; + const char *thumb; int show_forbidden = 0; /* Dot is ignored, Parent is handled by make_parent_entry() */ @@ -1346,6 +1435,7 @@ p->ascending = (apr_toupper(direction) == D_ASCENDING); p->version_sort = !!(autoindex_opts & VERSION_SORT); p->ignore_case = !!(autoindex_opts & IGNORE_CASE); + p->thumb = NULL; if (autoindex_opts & (FANCY_INDEXING | TABLE_INDEXING)) { p->lm = rr->finfo.mtime; @@ -1368,7 +1458,38 @@ } } else { + // find icon and default thumb for this entry p->icon = find_icon(d, rr, 0); + thumb = find_thumb(d, rr); + + if (thumb) { + // override thumb with cookie (if any) + if (thumb_cookie) { + thumb = thumb_cookie; + } + + // are thumbs enabled for this type? (in this request) + if (thumb && (thumb[0] != THUMB_NONE)) { + // create thumb url + // TODO: + // use config + p->thumb = apr_psprintf (r->pool, "%s?thumb", p->name); + p->thumb_type = thumb[0]; + // type of thumb + switch (p->thumb_type) { + case THUMB_STATIC: + p->icon = p->thumb; + if (overall_thumb_type != THUMB_DYNAMIC) { + overall_thumb_type = THUMB_STATIC; + } + break; + case THUMB_DYNAMIC: + overall_thumb_type = THUMB_DYNAMIC; + break; + } + } + } + p->alt = find_alt(d, rr, 0); p->size = rr->finfo.size; } @@ -1661,7 +1782,7 @@ if (autoindex_opts & TABLE_INDEXING) { ap_rputs("", r); if (!(autoindex_opts & SUPPRESS_ICON)) { - ap_rputs("", r); + ap_rputs("", r); if (autoindex_opts & ICONS_ARE_LINKS) { ap_rvputs(r, "", NULL); } @@ -1672,6 +1793,9 @@ : d->default_icon), "\" alt=\"[", (ar[x]->alt ? ar[x]->alt : " "), "]\"", NULL); + if (ar[x]->thumb_type == THUMB_STATIC) { + ap_rvputs(r, "class=\"st\"", NULL); + } if (d->icon_width) { ap_rprintf(r, " width=\"%d\"", d->icon_width); } @@ -1682,7 +1806,7 @@ if (autoindex_opts & EMIT_XHTML) { ap_rputs(" /", r); } - ap_rputs(">", r); + ap_rputs(">",r); } else { ap_rputs(" ", r); @@ -1694,11 +1818,8 @@ ap_rputs("", r); } } - if (d->name_adjust == K_ADJUST) { - ap_rvputs(r, "", - ap_escape_html(scratch, t2), "", NULL); - } - else { + + if (d->name_adjust != K_ADJUST) { nwidth = strlen(t2); if (nwidth > name_width) { memcpy(name_scratch, t2, name_width - 3); @@ -1709,10 +1830,29 @@ t2 = name_scratch; nwidth = name_width; } - ap_rvputs(r, "", - ap_escape_html(scratch, t2), - "", pad_scratch + nwidth, NULL); } + + ap_rvputs(r, "thumb_type==THUMB_DYNAMIC) { + ap_rprintf(r, "class='p' " \ + "onmouseover='javascript:s(%d,\"%s\");' " \ + "onmouseout='javascript:h(%d);' ", + x, anchor, x); + } + ap_rvputs(r,">", ap_escape_html(scratch, t2), NULL); + if (ar[x]->thumb_type==THUMB_DYNAMIC) { + ap_rprintf(r, "thumb",r); + } + + if (d->name_adjust != K_ADJUST) { + ap_rvputs(r, pad_scratch + nwidth, NULL); + } + ap_rvputs(r, "", NULL); + if (!(autoindex_opts & SUPPRESS_LAST_MOD)) { if (ar[x]->lm != -1) { char time_str[MAX_STRING_LEN]; @@ -1983,7 +2123,20 @@ char *fullpath; apr_size_t dirpathlen; char *ctype = "text/html"; + const char *cookie_header; + const char *thumb_cookie = NULL; + ap_regex_t *regexp; + ap_regmatch_t regm[2]; char *charset; + + if ((cookie_header = apr_table_get(r->headers_in, "Cookie"))) { + regexp = ap_pregcomp(r->pool, "THUMB=([^;,]*)", AP_REG_EXTENDED); + if (regexp && !ap_regexec(regexp, cookie_header, 2, regm, 0)) { + if (regm[1].rm_so != -1) { + thumb_cookie = ap_pregsub(r->pool, "$1", cookie_header, 2, regm); + } + } + } if ((status = apr_dir_open(&thedir, name, r->pool)) != APR_SUCCESS) { ap_log_rerror(APLOG_MARK, APLOG_ERR, status, r, @@ -2144,18 +2297,6 @@ } colargs = apr_pstrcat(r->pool, fval, vval, ppre, epattern, NULL); } - - /* Spew HTML preamble */ - title_endp = title_name + strlen(title_name) - 1; - - while (title_endp > title_name && *title_endp == '/') { - *title_endp-- = '\0'; - } - - emit_head(r, find_header(autoindex_conf, r), - autoindex_opts & SUPPRESS_PREAMBLE, - autoindex_opts & EMIT_XHTML, title_name); - /* * Since we don't know how many dir. entries there are, put them into a * linked list and then arrayificate them so qsort can use them. @@ -2199,13 +2340,26 @@ dirent.valid |= APR_FINFO_NAME; } p = make_autoindex_entry(&dirent, autoindex_opts, autoindex_conf, r, - keyid, direction, pstring); + keyid, direction, pstring, thumb_cookie); if (p != NULL) { p->next = head; head = p; num_ent++; } } while (1); + + /* Spew HTML preamble */ + title_endp = title_name + strlen(title_name) - 1; + + while (title_endp > title_name && *title_endp == '/') { + *title_endp-- = '\0'; + } + + emit_head(r, find_header(autoindex_conf, r), + autoindex_opts & SUPPRESS_PREAMBLE, + autoindex_opts & EMIT_XHTML, title_name, + autoindex_opts & ALWAYS_EMIT_H1, + find_menu(autoindex_conf, r)); if (num_ent > 0) { ar = (struct ent **) apr_palloc(r->pool,