Annotation of embedaddon/nginx/src/http/modules/ngx_http_autoindex_module.c, revision 1.1.1.1

1.1       misho       1: 
                      2: /*
                      3:  * Copyright (C) Igor Sysoev
                      4:  * Copyright (C) Nginx, Inc.
                      5:  */
                      6: 
                      7: 
                      8: #include <ngx_config.h>
                      9: #include <ngx_core.h>
                     10: #include <ngx_http.h>
                     11: 
                     12: 
                     13: #if 0
                     14: 
                     15: typedef struct {
                     16:     ngx_buf_t     *buf;
                     17:     size_t         size;
                     18:     ngx_pool_t    *pool;
                     19:     size_t         alloc_size;
                     20:     ngx_chain_t  **last_out;
                     21: } ngx_http_autoindex_ctx_t;
                     22: 
                     23: #endif
                     24: 
                     25: 
                     26: typedef struct {
                     27:     ngx_str_t      name;
                     28:     size_t         utf_len;
                     29:     size_t         escape;
                     30:     size_t         escape_html;
                     31: 
                     32:     unsigned       dir:1;
                     33: 
                     34:     time_t         mtime;
                     35:     off_t          size;
                     36: } ngx_http_autoindex_entry_t;
                     37: 
                     38: 
                     39: typedef struct {
                     40:     ngx_flag_t     enable;
                     41:     ngx_flag_t     localtime;
                     42:     ngx_flag_t     exact_size;
                     43: } ngx_http_autoindex_loc_conf_t;
                     44: 
                     45: 
                     46: #define NGX_HTTP_AUTOINDEX_PREALLOCATE  50
                     47: 
                     48: #define NGX_HTTP_AUTOINDEX_NAME_LEN     50
                     49: 
                     50: 
                     51: static int ngx_libc_cdecl ngx_http_autoindex_cmp_entries(const void *one,
                     52:     const void *two);
                     53: static ngx_int_t ngx_http_autoindex_error(ngx_http_request_t *r,
                     54:     ngx_dir_t *dir, ngx_str_t *name);
                     55: static ngx_int_t ngx_http_autoindex_init(ngx_conf_t *cf);
                     56: static void *ngx_http_autoindex_create_loc_conf(ngx_conf_t *cf);
                     57: static char *ngx_http_autoindex_merge_loc_conf(ngx_conf_t *cf,
                     58:     void *parent, void *child);
                     59: 
                     60: 
                     61: static ngx_command_t  ngx_http_autoindex_commands[] = {
                     62: 
                     63:     { ngx_string("autoindex"),
                     64:       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
                     65:       ngx_conf_set_flag_slot,
                     66:       NGX_HTTP_LOC_CONF_OFFSET,
                     67:       offsetof(ngx_http_autoindex_loc_conf_t, enable),
                     68:       NULL },
                     69: 
                     70:     { ngx_string("autoindex_localtime"),
                     71:       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
                     72:       ngx_conf_set_flag_slot,
                     73:       NGX_HTTP_LOC_CONF_OFFSET,
                     74:       offsetof(ngx_http_autoindex_loc_conf_t, localtime),
                     75:       NULL },
                     76: 
                     77:     { ngx_string("autoindex_exact_size"),
                     78:       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
                     79:       ngx_conf_set_flag_slot,
                     80:       NGX_HTTP_LOC_CONF_OFFSET,
                     81:       offsetof(ngx_http_autoindex_loc_conf_t, exact_size),
                     82:       NULL },
                     83: 
                     84:       ngx_null_command
                     85: };
                     86: 
                     87: 
                     88: static ngx_http_module_t  ngx_http_autoindex_module_ctx = {
                     89:     NULL,                                  /* preconfiguration */
                     90:     ngx_http_autoindex_init,               /* postconfiguration */
                     91: 
                     92:     NULL,                                  /* create main configuration */
                     93:     NULL,                                  /* init main configuration */
                     94: 
                     95:     NULL,                                  /* create server configuration */
                     96:     NULL,                                  /* merge server configuration */
                     97: 
                     98:     ngx_http_autoindex_create_loc_conf,    /* create location configuration */
                     99:     ngx_http_autoindex_merge_loc_conf      /* merge location configuration */
                    100: };
                    101: 
                    102: 
                    103: ngx_module_t  ngx_http_autoindex_module = {
                    104:     NGX_MODULE_V1,
                    105:     &ngx_http_autoindex_module_ctx,        /* module context */
                    106:     ngx_http_autoindex_commands,           /* module directives */
                    107:     NGX_HTTP_MODULE,                       /* module type */
                    108:     NULL,                                  /* init master */
                    109:     NULL,                                  /* init module */
                    110:     NULL,                                  /* init process */
                    111:     NULL,                                  /* init thread */
                    112:     NULL,                                  /* exit thread */
                    113:     NULL,                                  /* exit process */
                    114:     NULL,                                  /* exit master */
                    115:     NGX_MODULE_V1_PADDING
                    116: };
                    117: 
                    118: 
                    119: static u_char title[] =
                    120: "<html>" CRLF
                    121: "<head><title>Index of "
                    122: ;
                    123: 
                    124: 
                    125: static u_char header[] =
                    126: "</title></head>" CRLF
                    127: "<body bgcolor=\"white\">" CRLF
                    128: "<h1>Index of "
                    129: ;
                    130: 
                    131: static u_char tail[] =
                    132: "</body>" CRLF
                    133: "</html>" CRLF
                    134: ;
                    135: 
                    136: 
                    137: static ngx_int_t
                    138: ngx_http_autoindex_handler(ngx_http_request_t *r)
                    139: {
                    140:     u_char                         *last, *filename, scale;
                    141:     off_t                           length;
                    142:     size_t                          len, char_len, escape_html, allocated, root;
                    143:     ngx_tm_t                        tm;
                    144:     ngx_err_t                       err;
                    145:     ngx_buf_t                      *b;
                    146:     ngx_int_t                       rc, size;
                    147:     ngx_str_t                       path;
                    148:     ngx_dir_t                       dir;
                    149:     ngx_uint_t                      i, level, utf8;
                    150:     ngx_pool_t                     *pool;
                    151:     ngx_time_t                     *tp;
                    152:     ngx_chain_t                     out;
                    153:     ngx_array_t                     entries;
                    154:     ngx_http_autoindex_entry_t     *entry;
                    155:     ngx_http_autoindex_loc_conf_t  *alcf;
                    156: 
                    157:     static char  *months[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
                    158:                                "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
                    159: 
                    160:     if (r->uri.data[r->uri.len - 1] != '/') {
                    161:         return NGX_DECLINED;
                    162:     }
                    163: 
                    164:     if (!(r->method & (NGX_HTTP_GET|NGX_HTTP_HEAD))) {
                    165:         return NGX_DECLINED;
                    166:     }
                    167: 
                    168:     alcf = ngx_http_get_module_loc_conf(r, ngx_http_autoindex_module);
                    169: 
                    170:     if (!alcf->enable) {
                    171:         return NGX_DECLINED;
                    172:     }
                    173: 
                    174:     /* NGX_DIR_MASK_LEN is lesser than NGX_HTTP_AUTOINDEX_PREALLOCATE */
                    175: 
                    176:     last = ngx_http_map_uri_to_path(r, &path, &root,
                    177:                                     NGX_HTTP_AUTOINDEX_PREALLOCATE);
                    178:     if (last == NULL) {
                    179:         return NGX_HTTP_INTERNAL_SERVER_ERROR;
                    180:     }
                    181: 
                    182:     allocated = path.len;
                    183:     path.len = last - path.data;
                    184:     if (path.len > 1) {
                    185:         path.len--;
                    186:     }
                    187:     path.data[path.len] = '\0';
                    188: 
                    189:     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                    190:                    "http autoindex: \"%s\"", path.data);
                    191: 
                    192:     if (ngx_open_dir(&path, &dir) == NGX_ERROR) {
                    193:         err = ngx_errno;
                    194: 
                    195:         if (err == NGX_ENOENT
                    196:             || err == NGX_ENOTDIR
                    197:             || err == NGX_ENAMETOOLONG)
                    198:         {
                    199:             level = NGX_LOG_ERR;
                    200:             rc = NGX_HTTP_NOT_FOUND;
                    201: 
                    202:         } else if (err == NGX_EACCES) {
                    203:             level = NGX_LOG_ERR;
                    204:             rc = NGX_HTTP_FORBIDDEN;
                    205: 
                    206:         } else {
                    207:             level = NGX_LOG_CRIT;
                    208:             rc = NGX_HTTP_INTERNAL_SERVER_ERROR;
                    209:         }
                    210: 
                    211:         ngx_log_error(level, r->connection->log, err,
                    212:                       ngx_open_dir_n " \"%s\" failed", path.data);
                    213: 
                    214:         return rc;
                    215:     }
                    216: 
                    217: #if (NGX_SUPPRESS_WARN)
                    218: 
                    219:     /* MSVC thinks 'entries' may be used without having been initialized */
                    220:     ngx_memzero(&entries, sizeof(ngx_array_t));
                    221: 
                    222: #endif
                    223: 
                    224:     /* TODO: pool should be temporary pool */
                    225:     pool = r->pool;
                    226: 
                    227:     if (ngx_array_init(&entries, pool, 40, sizeof(ngx_http_autoindex_entry_t))
                    228:         != NGX_OK)
                    229:     {
                    230:         return ngx_http_autoindex_error(r, &dir, &path);
                    231:     }
                    232: 
                    233:     r->headers_out.status = NGX_HTTP_OK;
                    234:     r->headers_out.content_type_len = sizeof("text/html") - 1;
                    235:     ngx_str_set(&r->headers_out.content_type, "text/html");
                    236: 
                    237:     rc = ngx_http_send_header(r);
                    238: 
                    239:     if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) {
                    240:         if (ngx_close_dir(&dir) == NGX_ERROR) {
                    241:             ngx_log_error(NGX_LOG_ALERT, r->connection->log, ngx_errno,
                    242:                           ngx_close_dir_n " \"%V\" failed", &path);
                    243:         }
                    244: 
                    245:         return rc;
                    246:     }
                    247: 
                    248:     filename = path.data;
                    249:     filename[path.len] = '/';
                    250: 
                    251:     if (r->headers_out.charset.len == 5
                    252:         && ngx_strncasecmp(r->headers_out.charset.data, (u_char *) "utf-8", 5)
                    253:            == 0)
                    254:     {
                    255:         utf8 = 1;
                    256: 
                    257:     } else {
                    258:         utf8 = 0;
                    259:     }
                    260: 
                    261:     for ( ;; ) {
                    262:         ngx_set_errno(0);
                    263: 
                    264:         if (ngx_read_dir(&dir) == NGX_ERROR) {
                    265:             err = ngx_errno;
                    266: 
                    267:             if (err != NGX_ENOMOREFILES) {
                    268:                 ngx_log_error(NGX_LOG_CRIT, r->connection->log, err,
                    269:                               ngx_read_dir_n " \"%V\" failed", &path);
                    270:                 return ngx_http_autoindex_error(r, &dir, &path);
                    271:             }
                    272: 
                    273:             break;
                    274:         }
                    275: 
                    276:         ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                    277:                        "http autoindex file: \"%s\"", ngx_de_name(&dir));
                    278: 
                    279:         len = ngx_de_namelen(&dir);
                    280: 
                    281:         if (ngx_de_name(&dir)[0] == '.') {
                    282:             continue;
                    283:         }
                    284: 
                    285:         if (!dir.valid_info) {
                    286: 
                    287:             /* 1 byte for '/' and 1 byte for terminating '\0' */
                    288: 
                    289:             if (path.len + 1 + len + 1 > allocated) {
                    290:                 allocated = path.len + 1 + len + 1
                    291:                                      + NGX_HTTP_AUTOINDEX_PREALLOCATE;
                    292: 
                    293:                 filename = ngx_pnalloc(pool, allocated);
                    294:                 if (filename == NULL) {
                    295:                     return ngx_http_autoindex_error(r, &dir, &path);
                    296:                 }
                    297: 
                    298:                 last = ngx_cpystrn(filename, path.data, path.len + 1);
                    299:                 *last++ = '/';
                    300:             }
                    301: 
                    302:             ngx_cpystrn(last, ngx_de_name(&dir), len + 1);
                    303: 
                    304:             if (ngx_de_info(filename, &dir) == NGX_FILE_ERROR) {
                    305:                 err = ngx_errno;
                    306: 
                    307:                 if (err != NGX_ENOENT && err != NGX_ELOOP) {
                    308:                     ngx_log_error(NGX_LOG_CRIT, r->connection->log, err,
                    309:                                   ngx_de_info_n " \"%s\" failed", filename);
                    310: 
                    311:                     if (err == NGX_EACCES) {
                    312:                         continue;
                    313:                     }
                    314: 
                    315:                     return ngx_http_autoindex_error(r, &dir, &path);
                    316:                 }
                    317: 
                    318:                 if (ngx_de_link_info(filename, &dir) == NGX_FILE_ERROR) {
                    319:                     ngx_log_error(NGX_LOG_CRIT, r->connection->log, ngx_errno,
                    320:                                   ngx_de_link_info_n " \"%s\" failed",
                    321:                                   filename);
                    322:                     return ngx_http_autoindex_error(r, &dir, &path);
                    323:                 }
                    324:             }
                    325:         }
                    326: 
                    327:         entry = ngx_array_push(&entries);
                    328:         if (entry == NULL) {
                    329:             return ngx_http_autoindex_error(r, &dir, &path);
                    330:         }
                    331: 
                    332:         entry->name.len = len;
                    333: 
                    334:         entry->name.data = ngx_pnalloc(pool, len + 1);
                    335:         if (entry->name.data == NULL) {
                    336:             return ngx_http_autoindex_error(r, &dir, &path);
                    337:         }
                    338: 
                    339:         ngx_cpystrn(entry->name.data, ngx_de_name(&dir), len + 1);
                    340: 
                    341:         entry->escape = 2 * ngx_escape_uri(NULL, ngx_de_name(&dir), len,
                    342:                                            NGX_ESCAPE_URI_COMPONENT);
                    343: 
                    344:         entry->escape_html = ngx_escape_html(NULL, entry->name.data,
                    345:                                              entry->name.len);
                    346: 
                    347:         if (utf8) {
                    348:             entry->utf_len = ngx_utf8_length(entry->name.data, entry->name.len);
                    349:         } else {
                    350:             entry->utf_len = len;
                    351:         }
                    352: 
                    353:         entry->dir = ngx_de_is_dir(&dir);
                    354:         entry->mtime = ngx_de_mtime(&dir);
                    355:         entry->size = ngx_de_size(&dir);
                    356:     }
                    357: 
                    358:     if (ngx_close_dir(&dir) == NGX_ERROR) {
                    359:         ngx_log_error(NGX_LOG_ALERT, r->connection->log, ngx_errno,
                    360:                       ngx_close_dir_n " \"%s\" failed", &path);
                    361:     }
                    362: 
                    363:     escape_html = ngx_escape_html(NULL, r->uri.data, r->uri.len);
                    364: 
                    365:     len = sizeof(title) - 1
                    366:           + r->uri.len + escape_html
                    367:           + sizeof(header) - 1
                    368:           + r->uri.len + escape_html
                    369:           + sizeof("</h1>") - 1
                    370:           + sizeof("<hr><pre><a href=\"../\">../</a>" CRLF) - 1
                    371:           + sizeof("</pre><hr>") - 1
                    372:           + sizeof(tail) - 1;
                    373: 
                    374:     entry = entries.elts;
                    375:     for (i = 0; i < entries.nelts; i++) {
                    376:         len += sizeof("<a href=\"") - 1
                    377:             + entry[i].name.len + entry[i].escape
                    378:             + 1                                          /* 1 is for "/" */
                    379:             + sizeof("\">") - 1
                    380:             + entry[i].name.len - entry[i].utf_len
                    381:             + entry[i].escape_html
                    382:             + NGX_HTTP_AUTOINDEX_NAME_LEN + sizeof("&gt;") - 2
                    383:             + sizeof("</a>") - 1
                    384:             + sizeof(" 28-Sep-1970 12:00 ") - 1
                    385:             + 20                                         /* the file size */
                    386:             + 2;
                    387:     }
                    388: 
                    389:     b = ngx_create_temp_buf(r->pool, len);
                    390:     if (b == NULL) {
                    391:         return NGX_ERROR;
                    392:     }
                    393: 
                    394:     if (entries.nelts > 1) {
                    395:         ngx_qsort(entry, (size_t) entries.nelts,
                    396:                   sizeof(ngx_http_autoindex_entry_t),
                    397:                   ngx_http_autoindex_cmp_entries);
                    398:     }
                    399: 
                    400:     b->last = ngx_cpymem(b->last, title, sizeof(title) - 1);
                    401: 
                    402:     if (escape_html) {
                    403:         b->last = (u_char *) ngx_escape_html(b->last, r->uri.data, r->uri.len);
                    404:         b->last = ngx_cpymem(b->last, header, sizeof(header) - 1);
                    405:         b->last = (u_char *) ngx_escape_html(b->last, r->uri.data, r->uri.len);
                    406: 
                    407:     } else {
                    408:         b->last = ngx_cpymem(b->last, r->uri.data, r->uri.len);
                    409:         b->last = ngx_cpymem(b->last, header, sizeof(header) - 1);
                    410:         b->last = ngx_cpymem(b->last, r->uri.data, r->uri.len);
                    411:     }
                    412: 
                    413:     b->last = ngx_cpymem(b->last, "</h1>", sizeof("</h1>") - 1);
                    414: 
                    415:     b->last = ngx_cpymem(b->last, "<hr><pre><a href=\"../\">../</a>" CRLF,
                    416:                          sizeof("<hr><pre><a href=\"../\">../</a>" CRLF) - 1);
                    417: 
                    418:     tp = ngx_timeofday();
                    419: 
                    420:     for (i = 0; i < entries.nelts; i++) {
                    421:         b->last = ngx_cpymem(b->last, "<a href=\"", sizeof("<a href=\"") - 1);
                    422: 
                    423:         if (entry[i].escape) {
                    424:             ngx_escape_uri(b->last, entry[i].name.data, entry[i].name.len,
                    425:                            NGX_ESCAPE_URI_COMPONENT);
                    426: 
                    427:             b->last += entry[i].name.len + entry[i].escape;
                    428: 
                    429:         } else {
                    430:             b->last = ngx_cpymem(b->last, entry[i].name.data,
                    431:                                  entry[i].name.len);
                    432:         }
                    433: 
                    434:         if (entry[i].dir) {
                    435:             *b->last++ = '/';
                    436:         }
                    437: 
                    438:         *b->last++ = '"';
                    439:         *b->last++ = '>';
                    440: 
                    441:         len = entry[i].utf_len;
                    442: 
                    443:         if (entry[i].name.len != len) {
                    444:             if (len > NGX_HTTP_AUTOINDEX_NAME_LEN) {
                    445:                 char_len = NGX_HTTP_AUTOINDEX_NAME_LEN - 3 + 1;
                    446: 
                    447:             } else {
                    448:                 char_len = NGX_HTTP_AUTOINDEX_NAME_LEN + 1;
                    449:             }
                    450: 
                    451:             last = b->last;
                    452:             b->last = ngx_utf8_cpystrn(b->last, entry[i].name.data,
                    453:                                        char_len, entry[i].name.len + 1);
                    454: 
                    455:             if (entry[i].escape_html) {
                    456:                 b->last = (u_char *) ngx_escape_html(last, entry[i].name.data,
                    457:                                                      b->last - last);
                    458:             }
                    459: 
                    460:             last = b->last;
                    461: 
                    462:         } else {
                    463:             if (entry[i].escape_html) {
                    464:                 if (len > NGX_HTTP_AUTOINDEX_NAME_LEN) {
                    465:                     char_len = NGX_HTTP_AUTOINDEX_NAME_LEN - 3;
                    466: 
                    467:                 } else {
                    468:                     char_len = len;
                    469:                 }
                    470: 
                    471:                 b->last = (u_char *) ngx_escape_html(b->last,
                    472:                                                   entry[i].name.data, char_len);
                    473:                 last = b->last;
                    474: 
                    475:             } else {
                    476:                 b->last = ngx_cpystrn(b->last, entry[i].name.data,
                    477:                                       NGX_HTTP_AUTOINDEX_NAME_LEN + 1);
                    478:                 last = b->last - 3;
                    479:             }
                    480:         }
                    481: 
                    482:         if (len > NGX_HTTP_AUTOINDEX_NAME_LEN) {
                    483:             b->last = ngx_cpymem(last, "..&gt;</a>", sizeof("..&gt;</a>") - 1);
                    484: 
                    485:         } else {
                    486:             if (entry[i].dir && NGX_HTTP_AUTOINDEX_NAME_LEN - len > 0) {
                    487:                 *b->last++ = '/';
                    488:                 len++;
                    489:             }
                    490: 
                    491:             b->last = ngx_cpymem(b->last, "</a>", sizeof("</a>") - 1);
                    492: 
                    493:             if (NGX_HTTP_AUTOINDEX_NAME_LEN - len > 0) {
                    494:                 ngx_memset(b->last, ' ', NGX_HTTP_AUTOINDEX_NAME_LEN - len);
                    495:                 b->last += NGX_HTTP_AUTOINDEX_NAME_LEN - len;
                    496:             }
                    497:         }
                    498: 
                    499:         *b->last++ = ' ';
                    500: 
                    501:         ngx_gmtime(entry[i].mtime + tp->gmtoff * 60 * alcf->localtime, &tm);
                    502: 
                    503:         b->last = ngx_sprintf(b->last, "%02d-%s-%d %02d:%02d ",
                    504:                               tm.ngx_tm_mday,
                    505:                               months[tm.ngx_tm_mon - 1],
                    506:                               tm.ngx_tm_year,
                    507:                               tm.ngx_tm_hour,
                    508:                               tm.ngx_tm_min);
                    509: 
                    510:         if (alcf->exact_size) {
                    511:             if (entry[i].dir) {
                    512:                 b->last = ngx_cpymem(b->last,  "                  -",
                    513:                                      sizeof("                  -") - 1);
                    514:             } else {
                    515:                 b->last = ngx_sprintf(b->last, "%19O", entry[i].size);
                    516:             }
                    517: 
                    518:         } else {
                    519:             if (entry[i].dir) {
                    520:                 b->last = ngx_cpymem(b->last,  "      -",
                    521:                                      sizeof("      -") - 1);
                    522: 
                    523:             } else {
                    524:                 length = entry[i].size;
                    525: 
                    526:                 if (length > 1024 * 1024 * 1024 - 1) {
                    527:                     size = (ngx_int_t) (length / (1024 * 1024 * 1024));
                    528:                     if ((length % (1024 * 1024 * 1024))
                    529:                                                 > (1024 * 1024 * 1024 / 2 - 1))
                    530:                     {
                    531:                         size++;
                    532:                     }
                    533:                     scale = 'G';
                    534: 
                    535:                 } else if (length > 1024 * 1024 - 1) {
                    536:                     size = (ngx_int_t) (length / (1024 * 1024));
                    537:                     if ((length % (1024 * 1024)) > (1024 * 1024 / 2 - 1)) {
                    538:                         size++;
                    539:                     }
                    540:                     scale = 'M';
                    541: 
                    542:                 } else if (length > 9999) {
                    543:                     size = (ngx_int_t) (length / 1024);
                    544:                     if (length % 1024 > 511) {
                    545:                         size++;
                    546:                     }
                    547:                     scale = 'K';
                    548: 
                    549:                 } else {
                    550:                     size = (ngx_int_t) length;
                    551:                     scale = '\0';
                    552:                 }
                    553: 
                    554:                 if (scale) {
                    555:                     b->last = ngx_sprintf(b->last, "%6i%c", size, scale);
                    556: 
                    557:                 } else {
                    558:                     b->last = ngx_sprintf(b->last, " %6i", size);
                    559:                 }
                    560:             }
                    561:         }
                    562: 
                    563:         *b->last++ = CR;
                    564:         *b->last++ = LF;
                    565:     }
                    566: 
                    567:     /* TODO: free temporary pool */
                    568: 
                    569:     b->last = ngx_cpymem(b->last, "</pre><hr>", sizeof("</pre><hr>") - 1);
                    570: 
                    571:     b->last = ngx_cpymem(b->last, tail, sizeof(tail) - 1);
                    572: 
                    573:     if (r == r->main) {
                    574:         b->last_buf = 1;
                    575:     }
                    576: 
                    577:     b->last_in_chain = 1;
                    578: 
                    579:     out.buf = b;
                    580:     out.next = NULL;
                    581: 
                    582:     return ngx_http_output_filter(r, &out);
                    583: }
                    584: 
                    585: 
                    586: static int ngx_libc_cdecl
                    587: ngx_http_autoindex_cmp_entries(const void *one, const void *two)
                    588: {
                    589:     ngx_http_autoindex_entry_t *first = (ngx_http_autoindex_entry_t *) one;
                    590:     ngx_http_autoindex_entry_t *second = (ngx_http_autoindex_entry_t *) two;
                    591: 
                    592:     if (first->dir && !second->dir) {
                    593:         /* move the directories to the start */
                    594:         return -1;
                    595:     }
                    596: 
                    597:     if (!first->dir && second->dir) {
                    598:         /* move the directories to the start */
                    599:         return 1;
                    600:     }
                    601: 
                    602:     return (int) ngx_strcmp(first->name.data, second->name.data);
                    603: }
                    604: 
                    605: 
                    606: #if 0
                    607: 
                    608: static ngx_buf_t *
                    609: ngx_http_autoindex_alloc(ngx_http_autoindex_ctx_t *ctx, size_t size)
                    610: {
                    611:     ngx_chain_t  *cl;
                    612: 
                    613:     if (ctx->buf) {
                    614: 
                    615:         if ((size_t) (ctx->buf->end - ctx->buf->last) >= size) {
                    616:             return ctx->buf;
                    617:         }
                    618: 
                    619:         ctx->size += ctx->buf->last - ctx->buf->pos;
                    620:     }
                    621: 
                    622:     ctx->buf = ngx_create_temp_buf(ctx->pool, ctx->alloc_size);
                    623:     if (ctx->buf == NULL) {
                    624:         return NULL;
                    625:     }
                    626: 
                    627:     cl = ngx_alloc_chain_link(ctx->pool);
                    628:     if (cl == NULL) {
                    629:         return NULL;
                    630:     }
                    631: 
                    632:     cl->buf = ctx->buf;
                    633:     cl->next = NULL;
                    634: 
                    635:     *ctx->last_out = cl;
                    636:     ctx->last_out = &cl->next;
                    637: 
                    638:     return ctx->buf;
                    639: }
                    640: 
                    641: #endif
                    642: 
                    643: 
                    644: static ngx_int_t
                    645: ngx_http_autoindex_error(ngx_http_request_t *r, ngx_dir_t *dir, ngx_str_t *name)
                    646: {
                    647:     if (ngx_close_dir(dir) == NGX_ERROR) {
                    648:         ngx_log_error(NGX_LOG_ALERT, r->connection->log, ngx_errno,
                    649:                       ngx_close_dir_n " \"%V\" failed", name);
                    650:     }
                    651: 
                    652:     return r->header_sent ? NGX_ERROR : NGX_HTTP_INTERNAL_SERVER_ERROR;
                    653: }
                    654: 
                    655: 
                    656: static void *
                    657: ngx_http_autoindex_create_loc_conf(ngx_conf_t *cf)
                    658: {
                    659:     ngx_http_autoindex_loc_conf_t  *conf;
                    660: 
                    661:     conf = ngx_palloc(cf->pool, sizeof(ngx_http_autoindex_loc_conf_t));
                    662:     if (conf == NULL) {
                    663:         return NULL;
                    664:     }
                    665: 
                    666:     conf->enable = NGX_CONF_UNSET;
                    667:     conf->localtime = NGX_CONF_UNSET;
                    668:     conf->exact_size = NGX_CONF_UNSET;
                    669: 
                    670:     return conf;
                    671: }
                    672: 
                    673: 
                    674: static char *
                    675: ngx_http_autoindex_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
                    676: {
                    677:     ngx_http_autoindex_loc_conf_t *prev = parent;
                    678:     ngx_http_autoindex_loc_conf_t *conf = child;
                    679: 
                    680:     ngx_conf_merge_value(conf->enable, prev->enable, 0);
                    681:     ngx_conf_merge_value(conf->localtime, prev->localtime, 0);
                    682:     ngx_conf_merge_value(conf->exact_size, prev->exact_size, 1);
                    683: 
                    684:     return NGX_CONF_OK;
                    685: }
                    686: 
                    687: 
                    688: static ngx_int_t
                    689: ngx_http_autoindex_init(ngx_conf_t *cf)
                    690: {
                    691:     ngx_http_handler_pt        *h;
                    692:     ngx_http_core_main_conf_t  *cmcf;
                    693: 
                    694:     cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);
                    695: 
                    696:     h = ngx_array_push(&cmcf->phases[NGX_HTTP_CONTENT_PHASE].handlers);
                    697:     if (h == NULL) {
                    698:         return NGX_ERROR;
                    699:     }
                    700: 
                    701:     *h = ngx_http_autoindex_handler;
                    702: 
                    703:     return NGX_OK;
                    704: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>