ngx_int_t ngx_http_set_local_today(ngx_http_request_t *r, ngx_str_t *res, ngx_http_variable_value_t *v) { time_t now; ngx_tm_t tm; u_char *p; /*t = ngx_timeofday();*/ now = ngx_time(); ngx_gmtime(now + ngx_cached_time->gmtoff * 60, &tm); dd("tm.ngx_tm_hour:%d", tm.ngx_tm_hour); p = ngx_palloc(r->pool, sizeof("yyyy-mm-dd") - 1); if (p == NULL) { return NGX_ERROR; } ngx_sprintf(p, "%04d-%02d-%02d", tm.ngx_tm_year, tm.ngx_tm_mon, tm.ngx_tm_mday); res->data = p; res->len = sizeof("yyyy-mm-dd") - 1; return NGX_OK; }
u_char * ngx_http_cookie_time(u_char *buf, time_t t) { ngx_tm_t tm; ngx_gmtime(t, &tm); /* * Netscape 3.x does not understand 4-digit years at all and * 2-digit years more than "37" */ return ngx_sprintf(buf, (tm.ngx_tm_year > 2037) ? "%s, %02d-%s-%d %02d:%02d:%02d GMT": "%s, %02d-%s-%02d %02d:%02d:%02d GMT", week[tm.ngx_tm_wday], tm.ngx_tm_mday, months[tm.ngx_tm_mon - 1], (tm.ngx_tm_year > 2037) ? tm.ngx_tm_year: tm.ngx_tm_year % 100, tm.ngx_tm_hour, tm.ngx_tm_min, tm.ngx_tm_sec); }
int ngx_http_lua_ngx_utctime(lua_State *L) { ngx_http_request_t *r; ngx_tm_t tm; u_char buf[sizeof("2010-11-19 20:56:31") - 1]; lua_getglobal(L, GLOBALS_SYMBOL_REQUEST); r = lua_touserdata(L, -1); lua_pop(L, 1); if (r == NULL) { return luaL_error(L, "no request object found"); } if (lua_gettop(L) > 0) { return luaL_error(L, "shouldn't have argument"); } ngx_gmtime(ngx_time(), &tm); ngx_sprintf(buf, "%04d-%02d-%02d %02d:%02d:%02d", tm.ngx_tm_year, tm.ngx_tm_mon, tm.ngx_tm_mday, tm.ngx_tm_hour, tm.ngx_tm_min, tm.ngx_tm_sec); lua_pushlstring(L, (char *) buf, sizeof(buf)); return 1; }
int ngx_http_lua_ngx_today(lua_State *L) { ngx_http_request_t *r; time_t now; ngx_tm_t tm; u_char buf[sizeof("2010-11-19") - 1]; lua_getglobal(L, GLOBALS_SYMBOL_REQUEST); r = lua_touserdata(L, -1); lua_pop(L, 1); if (r == NULL) { return luaL_error(L, "no request object found"); } if (lua_gettop(L) > 0) { return luaL_error(L, "shouldn't have argument"); } now = ngx_time(); ngx_gmtime(now + ngx_cached_time->gmtoff * 60, &tm); ngx_sprintf(buf, "%04d-%02d-%02d", tm.ngx_tm_year, tm.ngx_tm_mon, tm.ngx_tm_mday); lua_pushlstring(L, (char *) buf, sizeof(buf)); return 1; }
void ngx_time_sigsafe_update(void) { u_char *p, *p2; ngx_tm_t tm; time_t sec; ngx_time_t *tp; struct timeval tv; if (!ngx_trylock(&ngx_time_lock)) { return; } ngx_gettimeofday(&tv); sec = tv.tv_sec; tp = &cached_time[slot]; if (tp->sec == sec) { ngx_unlock(&ngx_time_lock); return; } if (slot == NGX_TIME_SLOTS - 1) { slot = 0; } else { slot++; } tp = &cached_time[slot]; tp->sec = 0; ngx_gmtime(sec + cached_gmtoff * 60, &tm); p = &cached_err_log_time[slot][0]; (void) ngx_sprintf(p, "%4d/%02d/%02d %02d:%02d:%02d", tm.ngx_tm_year, tm.ngx_tm_mon, tm.ngx_tm_mday, tm.ngx_tm_hour, tm.ngx_tm_min, tm.ngx_tm_sec); p2 = &cached_syslog_time[slot][0]; (void) ngx_sprintf(p2, "%s %2d %02d:%02d:%02d", months[tm.ngx_tm_mon - 1], tm.ngx_tm_mday, tm.ngx_tm_hour, tm.ngx_tm_min, tm.ngx_tm_sec); ngx_memory_barrier(); ngx_cached_err_log_time.data = p; ngx_cached_syslog_time.data = p2; ngx_unlock(&ngx_time_lock); }
// Convert UNIX timestamp to DOS timestamp static ngx_uint_t ngx_dos_time(time_t t) { ngx_tm_t tm; ngx_gmtime(t, &tm); // ngx_gmtime does the mon++ and year += 1900 for us return (tm.ngx_tm_sec >> 1) + (tm.ngx_tm_min << 5) + (tm.ngx_tm_hour << 11) + (tm.ngx_tm_mday << 16) + (tm.ngx_tm_mon << 21) + ((tm.ngx_tm_year-1980) << 25); }
static mrb_value ngx_http_mruby_local_time(mrb_state *mrb, mrb_value self) { ngx_tm_t tm; u_char buf[sizeof("2013-08-04 01:00:00") - 1]; ngx_gmtime(ngx_time() + ngx_cached_time->gmtoff * 60, &tm); ngx_sprintf(buf, "%04d-%02d-%02d %02d:%02d:%02d", tm.ngx_tm_year, tm.ngx_tm_mon, tm.ngx_tm_mday, tm.ngx_tm_hour, tm.ngx_tm_min, tm.ngx_tm_sec); return mrb_str_new(mrb, (char *)buf, sizeof(buf)); }
u_char * ngx_http_time(u_char *buf, time_t t) { ngx_tm_t tm; ngx_gmtime(t, &tm); return ngx_sprintf(buf, "%s, %02d %s %4d %02d:%02d:%02d GMT", week[tm.ngx_tm_wday], tm.ngx_tm_mday, months[tm.ngx_tm_mon - 1], tm.ngx_tm_year, tm.ngx_tm_hour, tm.ngx_tm_min, tm.ngx_tm_sec); }
static int ngx_tcp_lua_ngx_utctime(lua_State *L) { ngx_tm_t tm; u_char buf[sizeof("2010-11-19 20:56:31") - 1]; ngx_gmtime(ngx_time(), &tm); ngx_sprintf(buf, "%04d-%02d-%02d %02d:%02d:%02d", tm.ngx_tm_year, tm.ngx_tm_mon, tm.ngx_tm_mday, tm.ngx_tm_hour, tm.ngx_tm_min, tm.ngx_tm_sec); lua_pushlstring(L, (char *) buf, sizeof(buf)); return 1; }
static int ngx_tcp_lua_ngx_today(lua_State *L) { time_t now; ngx_tm_t tm; u_char buf[sizeof("2010-11-19") - 1]; now = ngx_time(); ngx_gmtime(now + ngx_cached_time->gmtoff * 60, &tm); ngx_sprintf(buf, "%04d-%02d-%02d", tm.ngx_tm_year, tm.ngx_tm_mon, tm.ngx_tm_mday); lua_pushlstring(L, (char *) buf, sizeof(buf)); return 1; }
void ngx_time_update(void) { u_char *p0, *p1, *p2, *p3; ngx_tm_t tm, gmt; time_t sec; ngx_uint_t msec; ngx_time_t *tp; struct timeval tv; if (!ngx_trylock(&ngx_time_lock)) { return; } ngx_gettimeofday(&tv); sec = tv.tv_sec; msec = tv.tv_usec / 1000; ngx_current_msec = (ngx_msec_t) sec * 1000 + msec; tp = &cached_time[slot]; if (tp->sec == sec) { tp->msec = msec; ngx_unlock(&ngx_time_lock); return; } if (slot == NGX_TIME_SLOTS - 1) { slot = 0; } else { slot++; } tp = &cached_time[slot]; tp->sec = sec; tp->msec = msec; ngx_gmtime(sec, &gmt); p0 = &cached_http_time[slot][0]; (void) ngx_sprintf(p0, "%s, %02d %s %4d %02d:%02d:%02d GMT", week[gmt.ngx_tm_wday], gmt.ngx_tm_mday, months[gmt.ngx_tm_mon - 1], gmt.ngx_tm_year, gmt.ngx_tm_hour, gmt.ngx_tm_min, gmt.ngx_tm_sec); #if (NGX_HAVE_GETTIMEZONE) tp->gmtoff = ngx_gettimezone(); ngx_gmtime(sec + tp->gmtoff * 60, &tm); #elif (NGX_HAVE_GMTOFF) ngx_localtime(sec, &tm); cached_gmtoff = (ngx_int_t) (tm.ngx_tm_gmtoff / 60); tp->gmtoff = cached_gmtoff; #else ngx_localtime(sec, &tm); cached_gmtoff = ngx_timezone(tm.ngx_tm_isdst); tp->gmtoff = cached_gmtoff; #endif p1 = &cached_err_log_time[slot][0]; (void) ngx_sprintf(p1, "%4d/%02d/%02d %02d:%02d:%02d", tm.ngx_tm_year, tm.ngx_tm_mon, tm.ngx_tm_mday, tm.ngx_tm_hour, tm.ngx_tm_min, tm.ngx_tm_sec); p2 = &cached_http_log_time[slot][0]; (void) ngx_sprintf(p2, "%02d/%s/%d:%02d:%02d:%02d %c%02d%02d", tm.ngx_tm_mday, months[tm.ngx_tm_mon - 1], tm.ngx_tm_year, tm.ngx_tm_hour, tm.ngx_tm_min, tm.ngx_tm_sec, tp->gmtoff < 0 ? '-' : '+', ngx_abs(tp->gmtoff / 60), ngx_abs(tp->gmtoff % 60)); p3 = &cached_http_log_iso8601[slot][0]; (void) ngx_sprintf(p3, "%4d-%02d-%02dT%02d:%02d:%02d%c%02d:%02d", tm.ngx_tm_year, tm.ngx_tm_mon, tm.ngx_tm_mday, tm.ngx_tm_hour, tm.ngx_tm_min, tm.ngx_tm_sec, tp->gmtoff < 0 ? '-' : '+', ngx_abs(tp->gmtoff / 60), ngx_abs(tp->gmtoff % 60)); ngx_memory_barrier(); ngx_cached_time = tp; ngx_cached_http_time.data = p0; ngx_cached_err_log_time.data = p1; ngx_cached_http_log_time.data = p2; ngx_cached_http_log_iso8601.data = p3; ngx_unlock(&ngx_time_lock); }
static ngx_buf_t * ngx_http_autoindex_xml(ngx_http_request_t *r, ngx_array_t *entries) { size_t len; ngx_tm_t tm; ngx_buf_t *b; ngx_str_t type; ngx_uint_t i; ngx_http_autoindex_entry_t *entry; static u_char head[] = "<?xml version=\"1.0\"?>" CRLF "<list>" CRLF; static u_char tail[] = "</list>" CRLF; len = sizeof(head) - 1 + sizeof(tail) - 1; entry = entries->elts; for (i = 0; i < entries->nelts; i++) { entry[i].escape = ngx_escape_html(NULL, entry[i].name.data, entry[i].name.len); len += sizeof("<directory></directory>" CRLF) - 1 + entry[i].name.len + entry[i].escape + sizeof(" mtime=\"1986-12-31T10:00:00Z\"") - 1; if (entry[i].file) { len += sizeof(" size=\"\"") - 1 + NGX_OFF_T_LEN; } } b = ngx_create_temp_buf(r->pool, len); if (b == NULL) { return NULL; } b->last = ngx_cpymem(b->last, head, sizeof(head) - 1); for (i = 0; i < entries->nelts; i++) { *b->last++ = '<'; if (entry[i].dir) { ngx_str_set(&type, "directory"); } else if (entry[i].file) { ngx_str_set(&type, "file"); } else { ngx_str_set(&type, "other"); } b->last = ngx_cpymem(b->last, type.data, type.len); b->last = ngx_cpymem(b->last, " mtime=\"", sizeof(" mtime=\"") - 1); ngx_gmtime(entry[i].mtime, &tm); b->last = ngx_sprintf(b->last, "%4d-%02d-%02dT%02d:%02d:%02dZ", tm.ngx_tm_year, tm.ngx_tm_mon, tm.ngx_tm_mday, tm.ngx_tm_hour, tm.ngx_tm_min, tm.ngx_tm_sec); if (entry[i].file) { b->last = ngx_cpymem(b->last, "\" size=\"", sizeof("\" size=\"") - 1); b->last = ngx_sprintf(b->last, "%O", entry[i].size); } *b->last++ = '"'; *b->last++ = '>'; if (entry[i].escape) { b->last = (u_char *) ngx_escape_html(b->last, entry[i].name.data, entry[i].name.len); } else { b->last = ngx_cpymem(b->last, entry[i].name.data, entry[i].name.len); } *b->last++ = '<'; *b->last++ = '/'; b->last = ngx_cpymem(b->last, type.data, type.len); *b->last++ = '>'; *b->last++ = CR; *b->last++ = LF; } b->last = ngx_cpymem(b->last, tail, sizeof(tail) - 1); return b; }
static ngx_buf_t * ngx_http_autoindex_html(ngx_http_request_t *r, ngx_array_t *entries) { u_char *last, scale; off_t length; size_t len, char_len, escape_html; ngx_tm_t tm; ngx_buf_t *b; ngx_int_t size; ngx_uint_t i, utf8; ngx_time_t *tp; ngx_http_autoindex_entry_t *entry; ngx_http_autoindex_loc_conf_t *alcf; static u_char title[] = "<html>" CRLF "<head><title>Index of " ; static u_char header[] = "</title></head>" CRLF "<body bgcolor=\"white\">" CRLF "<h1>Index of " ; static u_char tail[] = "</body>" CRLF "</html>" CRLF ; static char *months[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; if (r->headers_out.charset.len == 5 && ngx_strncasecmp(r->headers_out.charset.data, (u_char *) "utf-8", 5) == 0) { utf8 = 1; } else { utf8 = 0; } escape_html = ngx_escape_html(NULL, r->uri.data, r->uri.len); len = sizeof(title) - 1 + r->uri.len + escape_html + sizeof(header) - 1 + r->uri.len + escape_html + sizeof("</h1>") - 1 + sizeof("<hr><pre><a href=\"../\">../</a>" CRLF) - 1 + sizeof("</pre><hr>") - 1 + sizeof(tail) - 1; entry = entries->elts; for (i = 0; i < entries->nelts; i++) { entry[i].escape = 2 * ngx_escape_uri(NULL, entry[i].name.data, entry[i].name.len, NGX_ESCAPE_URI_COMPONENT); entry[i].escape_html = ngx_escape_html(NULL, entry[i].name.data, entry[i].name.len); if (utf8) { entry[i].utf_len = ngx_utf8_length(entry[i].name.data, entry[i].name.len); } else { entry[i].utf_len = entry[i].name.len; } len += sizeof("<a href=\"") - 1 + entry[i].name.len + entry[i].escape + 1 /* 1 is for "/" */ + sizeof("\">") - 1 + entry[i].name.len - entry[i].utf_len + entry[i].escape_html + NGX_HTTP_AUTOINDEX_NAME_LEN + sizeof(">") - 2 + sizeof("</a>") - 1 + sizeof(" 28-Sep-1970 12:00 ") - 1 + 20 /* the file size */ + 2; } b = ngx_create_temp_buf(r->pool, len); if (b == NULL) { return NULL; } b->last = ngx_cpymem(b->last, title, sizeof(title) - 1); if (escape_html) { b->last = (u_char *) ngx_escape_html(b->last, r->uri.data, r->uri.len); b->last = ngx_cpymem(b->last, header, sizeof(header) - 1); b->last = (u_char *) ngx_escape_html(b->last, r->uri.data, r->uri.len); } else { b->last = ngx_cpymem(b->last, r->uri.data, r->uri.len); b->last = ngx_cpymem(b->last, header, sizeof(header) - 1); b->last = ngx_cpymem(b->last, r->uri.data, r->uri.len); } b->last = ngx_cpymem(b->last, "</h1>", sizeof("</h1>") - 1); b->last = ngx_cpymem(b->last, "<hr><pre><a href=\"../\">../</a>" CRLF, sizeof("<hr><pre><a href=\"../\">../</a>" CRLF) - 1); alcf = ngx_http_get_module_loc_conf(r, ngx_http_autoindex_module); tp = ngx_timeofday(); for (i = 0; i < entries->nelts; i++) { b->last = ngx_cpymem(b->last, "<a href=\"", sizeof("<a href=\"") - 1); if (entry[i].escape) { ngx_escape_uri(b->last, entry[i].name.data, entry[i].name.len, NGX_ESCAPE_URI_COMPONENT); b->last += entry[i].name.len + entry[i].escape; } else { b->last = ngx_cpymem(b->last, entry[i].name.data, entry[i].name.len); } if (entry[i].dir) { *b->last++ = '/'; } *b->last++ = '"'; *b->last++ = '>'; len = entry[i].utf_len; if (entry[i].name.len != len) { if (len > NGX_HTTP_AUTOINDEX_NAME_LEN) { char_len = NGX_HTTP_AUTOINDEX_NAME_LEN - 3 + 1; } else { char_len = NGX_HTTP_AUTOINDEX_NAME_LEN + 1; } last = b->last; b->last = ngx_utf8_cpystrn(b->last, entry[i].name.data, char_len, entry[i].name.len + 1); if (entry[i].escape_html) { b->last = (u_char *) ngx_escape_html(last, entry[i].name.data, b->last - last); } last = b->last; } else { if (entry[i].escape_html) { if (len > NGX_HTTP_AUTOINDEX_NAME_LEN) { char_len = NGX_HTTP_AUTOINDEX_NAME_LEN - 3; } else { char_len = len; } b->last = (u_char *) ngx_escape_html(b->last, entry[i].name.data, char_len); last = b->last; } else { b->last = ngx_cpystrn(b->last, entry[i].name.data, NGX_HTTP_AUTOINDEX_NAME_LEN + 1); last = b->last - 3; } } if (len > NGX_HTTP_AUTOINDEX_NAME_LEN) { b->last = ngx_cpymem(last, "..></a>", sizeof("..></a>") - 1); } else { if (entry[i].dir && NGX_HTTP_AUTOINDEX_NAME_LEN - len > 0) { *b->last++ = '/'; len++; } b->last = ngx_cpymem(b->last, "</a>", sizeof("</a>") - 1); if (NGX_HTTP_AUTOINDEX_NAME_LEN - len > 0) { ngx_memset(b->last, ' ', NGX_HTTP_AUTOINDEX_NAME_LEN - len); b->last += NGX_HTTP_AUTOINDEX_NAME_LEN - len; } } *b->last++ = ' '; ngx_gmtime(entry[i].mtime + tp->gmtoff * 60 * alcf->localtime, &tm); b->last = ngx_sprintf(b->last, "%02d-%s-%d %02d:%02d ", tm.ngx_tm_mday, months[tm.ngx_tm_mon - 1], tm.ngx_tm_year, tm.ngx_tm_hour, tm.ngx_tm_min); if (alcf->exact_size) { if (entry[i].dir) { b->last = ngx_cpymem(b->last, " -", sizeof(" -") - 1); } else { b->last = ngx_sprintf(b->last, "%19O", entry[i].size); } } else { if (entry[i].dir) { b->last = ngx_cpymem(b->last, " -", sizeof(" -") - 1); } else { length = entry[i].size; if (length > 1024 * 1024 * 1024 - 1) { size = (ngx_int_t) (length / (1024 * 1024 * 1024)); if ((length % (1024 * 1024 * 1024)) > (1024 * 1024 * 1024 / 2 - 1)) { size++; } scale = 'G'; } else if (length > 1024 * 1024 - 1) { size = (ngx_int_t) (length / (1024 * 1024)); if ((length % (1024 * 1024)) > (1024 * 1024 / 2 - 1)) { size++; } scale = 'M'; } else if (length > 9999) { size = (ngx_int_t) (length / 1024); if (length % 1024 > 511) { size++; } scale = 'K'; } else { size = (ngx_int_t) length; scale = '\0'; } if (scale) { b->last = ngx_sprintf(b->last, "%6i%c", size, scale); } else { b->last = ngx_sprintf(b->last, " %6i", size); } } } *b->last++ = CR; *b->last++ = LF; } b->last = ngx_cpymem(b->last, "</pre><hr>", sizeof("</pre><hr>") - 1); b->last = ngx_cpymem(b->last, tail, sizeof(tail) - 1); return b; }
static ngx_int_t ngx_http_autoindex_handler(ngx_http_request_t *r) { u_char *last, *filename, scale; off_t length; size_t len, utf_len, allocated, root; ngx_tm_t tm; ngx_err_t err; ngx_buf_t *b; ngx_int_t rc, size; ngx_str_t path; ngx_dir_t dir; ngx_uint_t i, level, utf8; ngx_pool_t *pool; ngx_time_t *tp; ngx_chain_t out; ngx_array_t entries; ngx_http_autoindex_entry_t *entry; ngx_http_autoindex_loc_conf_t *alcf; static char *months[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; if (r->uri.data[r->uri.len - 1] != '/') { return NGX_DECLINED; } if (!(r->method & (NGX_HTTP_GET|NGX_HTTP_HEAD))) { return NGX_DECLINED; } alcf = ngx_http_get_module_loc_conf(r, ngx_http_autoindex_module); if (!alcf->enable) { return NGX_DECLINED; } /* NGX_DIR_MASK_LEN is lesser than NGX_HTTP_AUTOINDEX_PREALLOCATE */ last = ngx_http_map_uri_to_path(r, &path, &root, NGX_HTTP_AUTOINDEX_PREALLOCATE); if (last == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } allocated = path.len; path.len = last - path.data; if (path.len > 1) { path.len--; } path.data[path.len] = '\0'; ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "http autoindex: \"%s\"", path.data); if (ngx_open_dir(&path, &dir) == NGX_ERROR) { err = ngx_errno; if (err == NGX_ENOENT || err == NGX_ENOTDIR || err == NGX_ENAMETOOLONG) { level = NGX_LOG_ERR; rc = NGX_HTTP_NOT_FOUND; } else if (err == NGX_EACCES) { level = NGX_LOG_ERR; rc = NGX_HTTP_FORBIDDEN; } else { level = NGX_LOG_CRIT; rc = NGX_HTTP_INTERNAL_SERVER_ERROR; } ngx_log_error(level, r->connection->log, err, ngx_open_dir_n " \"%s\" failed", path.data); return rc; } #if (NGX_SUPPRESS_WARN) /* MSVC thinks 'entries' may be used without having been initialized */ ngx_memzero(&entries, sizeof(ngx_array_t)); #endif /* TODO: pool should be temporary pool */ pool = r->pool; if (ngx_array_init(&entries, pool, 40, sizeof(ngx_http_autoindex_entry_t)) != NGX_OK) { return ngx_http_autoindex_error(r, &dir, &path); } r->headers_out.status = NGX_HTTP_OK; r->headers_out.content_type_len = sizeof("text/html") - 1; ngx_str_set(&r->headers_out.content_type, "text/html"); rc = ngx_http_send_header(r); if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) { if (ngx_close_dir(&dir) == NGX_ERROR) { ngx_log_error(NGX_LOG_ALERT, r->connection->log, ngx_errno, ngx_close_dir_n " \"%V\" failed", &path); } return rc; } filename = path.data; filename[path.len] = '/'; if (r->headers_out.charset.len == 5 && ngx_strncasecmp(r->headers_out.charset.data, (u_char *) "utf-8", 5) == 0) { utf8 = 1; } else { utf8 = 0; } for ( ;; ) { ngx_set_errno(0); if (ngx_read_dir(&dir) == NGX_ERROR) { err = ngx_errno; if (err != NGX_ENOMOREFILES) { ngx_log_error(NGX_LOG_CRIT, r->connection->log, err, ngx_read_dir_n " \"%V\" failed", &path); return ngx_http_autoindex_error(r, &dir, &path); } break; } ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "http autoindex file: \"%s\"", ngx_de_name(&dir)); len = ngx_de_namelen(&dir); if (ngx_de_name(&dir)[0] == '.') { continue; } if (!dir.valid_info) { /* 1 byte for '/' and 1 byte for terminating '\0' */ if (path.len + 1 + len + 1 > allocated) { allocated = path.len + 1 + len + 1 + NGX_HTTP_AUTOINDEX_PREALLOCATE; filename = ngx_pnalloc(pool, allocated); if (filename == NULL) { return ngx_http_autoindex_error(r, &dir, &path); } last = ngx_cpystrn(filename, path.data, path.len + 1); *last++ = '/'; } ngx_cpystrn(last, ngx_de_name(&dir), len + 1); if (ngx_de_info(filename, &dir) == NGX_FILE_ERROR) { err = ngx_errno; if (err != NGX_ENOENT) { ngx_log_error(NGX_LOG_CRIT, r->connection->log, err, ngx_de_info_n " \"%s\" failed", filename); if (err == NGX_EACCES) { continue; } return ngx_http_autoindex_error(r, &dir, &path); } if (ngx_de_link_info(filename, &dir) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_CRIT, r->connection->log, ngx_errno, ngx_de_link_info_n " \"%s\" failed", filename); return ngx_http_autoindex_error(r, &dir, &path); } } } entry = ngx_array_push(&entries); if (entry == NULL) { return ngx_http_autoindex_error(r, &dir, &path); } entry->name.len = len; entry->name.data = ngx_pnalloc(pool, len + 1); if (entry->name.data == NULL) { return ngx_http_autoindex_error(r, &dir, &path); } ngx_cpystrn(entry->name.data, ngx_de_name(&dir), len + 1); entry->escape = 2 * ngx_escape_uri(NULL, ngx_de_name(&dir), len, NGX_ESCAPE_HTML); if (utf8) { entry->utf_len = ngx_utf8_length(entry->name.data, entry->name.len); } else { entry->utf_len = len; } entry->colon = (ngx_strchr(entry->name.data, ':') != NULL); entry->dir = ngx_de_is_dir(&dir); entry->mtime = ngx_de_mtime(&dir); entry->size = ngx_de_size(&dir); } if (ngx_close_dir(&dir) == NGX_ERROR) { ngx_log_error(NGX_LOG_ALERT, r->connection->log, ngx_errno, ngx_close_dir_n " \"%s\" failed", &path); } len = sizeof(title) - 1 + r->uri.len + sizeof(header) - 1 + r->uri.len + sizeof("</h1>") - 1 + sizeof("<hr><pre><a href=\"../\">../</a>" CRLF) - 1 + sizeof("</pre><hr>") - 1 + sizeof(tail) - 1; entry = entries.elts; for (i = 0; i < entries.nelts; i++) { len += sizeof("<a href=\"") - 1 + entry[i].name.len + entry[i].escape + 1 /* 1 is for "/" */ + sizeof("\">") - 1 + entry[i].name.len - entry[i].utf_len + entry[i].colon * 2 + NGX_HTTP_AUTOINDEX_NAME_LEN + sizeof(">") - 2 + sizeof("</a>") - 1 + sizeof(" 28-Sep-1970 12:00 ") - 1 + 20 /* the file size */ + 2; } b = ngx_create_temp_buf(r->pool, len); if (b == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } if (entries.nelts > 1) { ngx_qsort(entry, (size_t) entries.nelts, sizeof(ngx_http_autoindex_entry_t), ngx_http_autoindex_cmp_entries); } b->last = ngx_cpymem(b->last, title, sizeof(title) - 1); b->last = ngx_cpymem(b->last, r->uri.data, r->uri.len); b->last = ngx_cpymem(b->last, header, sizeof(header) - 1); b->last = ngx_cpymem(b->last, r->uri.data, r->uri.len); b->last = ngx_cpymem(b->last, "</h1>", sizeof("</h1>") - 1); b->last = ngx_cpymem(b->last, "<hr><pre><a href=\"../\">../</a>" CRLF, sizeof("<hr><pre><a href=\"../\">../</a>" CRLF) - 1); tp = ngx_timeofday(); for (i = 0; i < entries.nelts; i++) { b->last = ngx_cpymem(b->last, "<a href=\"", sizeof("<a href=\"") - 1); if (entry[i].colon) { *b->last++ = '.'; *b->last++ = '/'; } if (entry[i].escape) { ngx_escape_uri(b->last, entry[i].name.data, entry[i].name.len, NGX_ESCAPE_HTML); b->last += entry[i].name.len + entry[i].escape; } else { b->last = ngx_cpymem(b->last, entry[i].name.data, entry[i].name.len); } if (entry[i].dir) { *b->last++ = '/'; } *b->last++ = '"'; *b->last++ = '>'; len = entry[i].utf_len; if (entry[i].name.len != len) { if (len > NGX_HTTP_AUTOINDEX_NAME_LEN) { utf_len = NGX_HTTP_AUTOINDEX_NAME_LEN - 3 + 1; } else { utf_len = NGX_HTTP_AUTOINDEX_NAME_LEN + 1; } b->last = ngx_utf8_cpystrn(b->last, entry[i].name.data, utf_len, entry[i].name.len + 1); last = b->last; } else { b->last = ngx_cpystrn(b->last, entry[i].name.data, NGX_HTTP_AUTOINDEX_NAME_LEN + 1); last = b->last - 3; } if (len > NGX_HTTP_AUTOINDEX_NAME_LEN) { b->last = ngx_cpymem(last, "..></a>", sizeof("..></a>") - 1); } else { if (entry[i].dir && NGX_HTTP_AUTOINDEX_NAME_LEN - len > 0) { *b->last++ = '/'; len++; } b->last = ngx_cpymem(b->last, "</a>", sizeof("</a>") - 1); ngx_memset(b->last, ' ', NGX_HTTP_AUTOINDEX_NAME_LEN - len); b->last += NGX_HTTP_AUTOINDEX_NAME_LEN - len; } *b->last++ = ' '; ngx_gmtime(entry[i].mtime + tp->gmtoff * 60 * alcf->localtime, &tm); b->last = ngx_sprintf(b->last, "%02d-%s-%d %02d:%02d ", tm.ngx_tm_mday, months[tm.ngx_tm_mon - 1], tm.ngx_tm_year, tm.ngx_tm_hour, tm.ngx_tm_min); if (alcf->exact_size) { if (entry[i].dir) { b->last = ngx_cpymem(b->last, " -", sizeof(" -") - 1); } else { b->last = ngx_sprintf(b->last, "%19O", entry[i].size); } } else { if (entry[i].dir) { b->last = ngx_cpymem(b->last, " -", sizeof(" -") - 1); } else { length = entry[i].size; if (length > 1024 * 1024 * 1024 - 1) { size = (ngx_int_t) (length / (1024 * 1024 * 1024)); if ((length % (1024 * 1024 * 1024)) > (1024 * 1024 * 1024 / 2 - 1)) { size++; } scale = 'G'; } else if (length > 1024 * 1024 - 1) { size = (ngx_int_t) (length / (1024 * 1024)); if ((length % (1024 * 1024)) > (1024 * 1024 / 2 - 1)) { size++; } scale = 'M'; } else if (length > 9999) { size = (ngx_int_t) (length / 1024); if (length % 1024 > 511) { size++; } scale = 'K'; } else { size = (ngx_int_t) length; scale = '\0'; } if (scale) { b->last = ngx_sprintf(b->last, "%6i%c", size, scale); } else { b->last = ngx_sprintf(b->last, " %6i", size); } } } *b->last++ = CR; *b->last++ = LF; } /* TODO: free temporary pool */ b->last = ngx_cpymem(b->last, "</pre><hr>", sizeof("</pre><hr>") - 1); b->last = ngx_cpymem(b->last, tail, sizeof(tail) - 1); if (r == r->main) { b->last_buf = 1; } b->last_in_chain = 1; out.buf = b; out.next = NULL; return ngx_http_output_filter(r, &out); }
static ngx_inline ngx_int_t make_content_buf( ngx_http_request_t *r, ngx_buf_t **pb, ngx_http_fancyindex_loc_conf_t *alcf) { ngx_http_fancyindex_entry_t *entry; off_t length; size_t len, root, copy, allocated; u_char *filename, *last, scale; ngx_tm_t tm; ngx_array_t entries; ngx_time_t *tp; ngx_uint_t i; ngx_int_t size; ngx_str_t path; ngx_dir_t dir; ngx_buf_t *b; static char *months[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", }; /* * NGX_DIR_MASK_LEN is lesser than NGX_HTTP_FANCYINDEX_PREALLOCATE */ if ((last = ngx_http_map_uri_to_path(r, &path, &root, NGX_HTTP_FANCYINDEX_PREALLOCATE)) == NULL) return NGX_HTTP_INTERNAL_SERVER_ERROR; allocated = path.len; path.len = last - path.data - 1; path.data[path.len] = '\0'; ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "http fancyindex: \"%s\"", path.data); if (ngx_open_dir(&path, &dir) == NGX_ERROR) { ngx_int_t rc, err = ngx_errno; ngx_uint_t level; if (err == NGX_ENOENT || err == NGX_ENOTDIR || err == NGX_ENAMETOOLONG) { level = NGX_LOG_ERR; rc = NGX_HTTP_NOT_FOUND; } else if (err == NGX_EACCES) { level = NGX_LOG_ERR; rc = NGX_HTTP_FORBIDDEN; } else { level = NGX_LOG_CRIT; rc = NGX_HTTP_INTERNAL_SERVER_ERROR; } ngx_log_error(level, r->connection->log, err, ngx_open_dir_n " \"%s\" failed", path.data); return rc; } #if (NGX_SUPPRESS_WARN) /* MSVC thinks 'entries' may be used without having been initialized */ ngx_memzero(&entries, sizeof(ngx_array_t)); #endif /* NGX_SUPPRESS_WARN */ if (ngx_array_init(&entries, r->pool, 40, sizeof(ngx_http_fancyindex_entry_t)) != NGX_OK) return ngx_http_fancyindex_error(r, &dir, &path); filename = path.data; filename[path.len] = '/'; /* Read directory entries and their associated information. */ for (;;) { ngx_set_errno(0); if (ngx_read_dir(&dir) == NGX_ERROR) { ngx_int_t err = ngx_errno; if (err != NGX_ENOMOREFILES) { ngx_log_error(NGX_LOG_CRIT, r->connection->log, err, ngx_read_dir_n " \"%V\" failed", &path); return ngx_http_fancyindex_error(r, &dir, &path); } break; } ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "http fancyindex file: \"%s\"", ngx_de_name(&dir)); len = ngx_de_namelen(&dir); if (ngx_de_name(&dir)[0] == '.') continue; #if NGX_PCRE { ngx_str_t str = { len, ngx_de_name(&dir) }; if (alcf->ignore && ngx_regex_exec_array(alcf->ignore, &str, r->connection->log) != NGX_DECLINED) { continue; } } #else /* !NGX_PCRE */ if (alcf->ignore) { u_int match_found = 0; ngx_str_t *s = alcf->ignore->elts; for (i = 0; i < alcf->ignore->nelts; i++, s++) { if (ngx_strcmp(ngx_de_name(&dir), s->data) == 0) { match_found = 1; break; } } if (match_found) { continue; } } #endif /* NGX_PCRE */ if (!dir.valid_info) { /* 1 byte for '/' and 1 byte for terminating '\0' */ if (path.len + 1 + len + 1 > allocated) { allocated = path.len + 1 + len + 1 + NGX_HTTP_FANCYINDEX_PREALLOCATE; if ((filename = ngx_palloc(r->pool, allocated)) == NULL) return ngx_http_fancyindex_error(r, &dir, &path); last = ngx_cpystrn(filename, path.data, path.len + 1); *last++ = '/'; } ngx_cpystrn(last, ngx_de_name(&dir), len + 1); if (ngx_de_info(filename, &dir) == NGX_FILE_ERROR) { ngx_int_t err = ngx_errno; if (err != NGX_ENOENT) { ngx_log_error(NGX_LOG_ERR, r->connection->log, err, ngx_de_info_n " \"%s\" failed", filename); continue; } if (ngx_de_link_info(filename, &dir) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_CRIT, r->connection->log, ngx_errno, ngx_de_link_info_n " \"%s\" failed", filename); return ngx_http_fancyindex_error(r, &dir, &path); } } } if ((entry = ngx_array_push(&entries)) == NULL) return ngx_http_fancyindex_error(r, &dir, &path); entry->name.len = len; entry->name.data = ngx_palloc(r->pool, len + 1); if (entry->name.data == NULL) return ngx_http_fancyindex_error(r, &dir, &path); ngx_cpystrn(entry->name.data, ngx_de_name(&dir), len + 1); entry->escape = 2 * ngx_fancyindex_escape_uri(NULL, ngx_de_name(&dir), len); entry->dir = ngx_de_is_dir(&dir); entry->mtime = ngx_de_mtime(&dir); entry->size = ngx_de_size(&dir); entry->utf_len = (r->headers_out.charset.len == 5 && ngx_strncasecmp(r->headers_out.charset.data, (u_char*) "utf-8", 5) == 0) ? ngx_utf8_length(entry->name.data, entry->name.len) : len; } if (ngx_close_dir(&dir) == NGX_ERROR) { ngx_log_error(NGX_LOG_ALERT, r->connection->log, ngx_errno, ngx_close_dir_n " \"%s\" failed", &path); } /* * Calculate needed buffer length. */ len = r->uri.len + ngx_sizeof_ssz(t05_body2) + ngx_sizeof_ssz(t06_list1) + ngx_sizeof_ssz(t07_list2) ; entry = entries.elts; for (i = 0; i < entries.nelts; i++) { /* * Genearated table rows are as follows, unneeded whitespace * is stripped out: * * <tr class="X"> * <td><a href="U">fname</a></td> * <td>size</td><td>date</td> * </tr> */ len += ngx_sizeof_ssz("<tr class=\"X\"><td><a href=\"") + entry[i].name.len + entry[i].escape /* Escaped URL */ + ngx_sizeof_ssz("\">") + entry[i].name.len + entry[i].utf_len + NGX_HTTP_FANCYINDEX_NAME_LEN + ngx_sizeof_ssz(">") + ngx_sizeof_ssz("</a></td><td>") + 20 /* File size */ + ngx_sizeof_ssz("</td><td>") + ngx_sizeof_ssz(" 28-Sep-1970 12:00 ") + ngx_sizeof_ssz("</td></tr>\n") + 2 /* CR LF */ ; } if ((b = ngx_create_temp_buf(r->pool, len)) == NULL) return NGX_HTTP_INTERNAL_SERVER_ERROR; /* Sort entries, if needed */ if (entries.nelts > 1) { ngx_qsort(entry, (size_t) entries.nelts, sizeof(ngx_http_fancyindex_entry_t), ngx_http_fancyindex_cmp_entries); } b->last = ngx_cpymem_str(b->last, r->uri); b->last = ngx_cpymem_ssz(b->last, t05_body2); b->last = ngx_cpymem_ssz(b->last, t06_list1); tp = ngx_timeofday(); for (i = 0; i < entries.nelts; i++) { static const char _evenodd[] = { 'e', 'o' }; b->last = ngx_cpymem_ssz(b->last, "<tr class=\""); *b->last++ = _evenodd[i & 0x01]; /* * Alternative implementation: * *b->last++ = (i & 0x01) ? 'e' : 'o'; */ b->last = ngx_cpymem_ssz(b->last, "\"><td><a href=\""); if (entry[i].escape) { ngx_fancyindex_escape_uri(b->last, entry[i].name.data, entry[i].name.len); b->last += entry[i].name.len + entry[i].escape; } else { b->last = ngx_cpymem_str(b->last, entry[i].name); } if (entry[i].dir) { *b->last++ = '/'; } *b->last++ = '"'; *b->last++ = '>'; len = entry[i].utf_len; if (entry[i].name.len - len) { if (len > NGX_HTTP_FANCYINDEX_NAME_LEN) { copy = NGX_HTTP_FANCYINDEX_NAME_LEN - 3 + 1; } else { copy = NGX_HTTP_FANCYINDEX_NAME_LEN + 1; } b->last = ngx_utf8_cpystrn(b->last, entry[i].name.data, copy, entry[i].name.len); last = b->last; } else { b->last = ngx_cpystrn(b->last, entry[i].name.data, NGX_HTTP_FANCYINDEX_NAME_LEN + 1); last = b->last - 3; } if (len > NGX_HTTP_FANCYINDEX_NAME_LEN) { b->last = ngx_cpymem_ssz(last, "..></a></td><td>"); } else { if (entry[i].dir && NGX_HTTP_FANCYINDEX_NAME_LEN - len > 0) { *b->last++ = '/'; len++; } b->last = ngx_cpymem_ssz(b->last, "</a></td><td>"); } if (alcf->exact_size) { if (entry[i].dir) { *b->last++ = '-'; } else { b->last = ngx_sprintf(b->last, "%19O", entry[i].size); } } else { if (entry[i].dir) { *b->last++ = '-'; } else { length = entry[i].size; if (length > 1024 * 1024 * 1024 - 1) { size = (ngx_int_t) (length / (1024 * 1024 * 1024)); if ((length % (1024 * 1024 * 1024)) > (1024 * 1024 * 1024 / 2 - 1)) { size++; } scale = 'G'; } else if (length > 1024 * 1024 - 1) { size = (ngx_int_t) (length / (1024 * 1024)); if ((length % (1024 * 1024)) > (1024 * 1024 / 2 - 1)) { size++; } scale = 'M'; } else if (length > 9999) { size = (ngx_int_t) (length / 1024); if (length % 1024 > 511) { size++; } scale = 'K'; } else { size = (ngx_int_t) length; scale = '\0'; } if (scale) { b->last = ngx_sprintf(b->last, "%6i%c", size, scale); } else { b->last = ngx_sprintf(b->last, " %6i", size); } } } ngx_gmtime(entry[i].mtime + tp->gmtoff * 60 * alcf->localtime, &tm); b->last = ngx_sprintf(b->last, "</td><td>%02d-%s-%d %02d:%02d</td></tr>", tm.ngx_tm_mday, months[tm.ngx_tm_mon - 1], tm.ngx_tm_year, tm.ngx_tm_hour, tm.ngx_tm_min); *b->last++ = CR; *b->last++ = LF; } /* Output table bottom */ b->last = ngx_cpymem_ssz(b->last, t07_list2); *pb = b; return NGX_OK; }