Annotation of embedaddon/nginx/src/http/ngx_http_variables.c, revision 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: #include <nginx.h>
        !            12: 
        !            13: 
        !            14: static ngx_int_t ngx_http_variable_request(ngx_http_request_t *r,
        !            15:     ngx_http_variable_value_t *v, uintptr_t data);
        !            16: static void ngx_http_variable_request_set(ngx_http_request_t *r,
        !            17:     ngx_http_variable_value_t *v, uintptr_t data);
        !            18: static ngx_int_t ngx_http_variable_request_get_size(ngx_http_request_t *r,
        !            19:     ngx_http_variable_value_t *v, uintptr_t data);
        !            20: static void ngx_http_variable_request_set_size(ngx_http_request_t *r,
        !            21:     ngx_http_variable_value_t *v, uintptr_t data);
        !            22: static ngx_int_t ngx_http_variable_header(ngx_http_request_t *r,
        !            23:     ngx_http_variable_value_t *v, uintptr_t data);
        !            24: 
        !            25: static ngx_int_t ngx_http_variable_cookies(ngx_http_request_t *r,
        !            26:     ngx_http_variable_value_t *v, uintptr_t data);
        !            27: static ngx_int_t ngx_http_variable_headers(ngx_http_request_t *r,
        !            28:     ngx_http_variable_value_t *v, uintptr_t data);
        !            29: static ngx_int_t ngx_http_variable_headers_internal(ngx_http_request_t *r,
        !            30:     ngx_http_variable_value_t *v, uintptr_t data, u_char sep);
        !            31: 
        !            32: static ngx_int_t ngx_http_variable_unknown_header_in(ngx_http_request_t *r,
        !            33:     ngx_http_variable_value_t *v, uintptr_t data);
        !            34: static ngx_int_t ngx_http_variable_unknown_header_out(ngx_http_request_t *r,
        !            35:     ngx_http_variable_value_t *v, uintptr_t data);
        !            36: static ngx_int_t ngx_http_variable_request_line(ngx_http_request_t *r,
        !            37:     ngx_http_variable_value_t *v, uintptr_t data);
        !            38: static ngx_int_t ngx_http_variable_cookie(ngx_http_request_t *r,
        !            39:     ngx_http_variable_value_t *v, uintptr_t data);
        !            40: static ngx_int_t ngx_http_variable_argument(ngx_http_request_t *r,
        !            41:     ngx_http_variable_value_t *v, uintptr_t data);
        !            42: #if (NGX_HAVE_TCP_INFO)
        !            43: static ngx_int_t ngx_http_variable_tcpinfo(ngx_http_request_t *r,
        !            44:     ngx_http_variable_value_t *v, uintptr_t data);
        !            45: #endif
        !            46: 
        !            47: static ngx_int_t ngx_http_variable_content_length(ngx_http_request_t *r,
        !            48:     ngx_http_variable_value_t *v, uintptr_t data);
        !            49: static ngx_int_t ngx_http_variable_host(ngx_http_request_t *r,
        !            50:     ngx_http_variable_value_t *v, uintptr_t data);
        !            51: static ngx_int_t ngx_http_variable_binary_remote_addr(ngx_http_request_t *r,
        !            52:     ngx_http_variable_value_t *v, uintptr_t data);
        !            53: static ngx_int_t ngx_http_variable_remote_addr(ngx_http_request_t *r,
        !            54:     ngx_http_variable_value_t *v, uintptr_t data);
        !            55: static ngx_int_t ngx_http_variable_remote_port(ngx_http_request_t *r,
        !            56:     ngx_http_variable_value_t *v, uintptr_t data);
        !            57: static ngx_int_t ngx_http_variable_server_addr(ngx_http_request_t *r,
        !            58:     ngx_http_variable_value_t *v, uintptr_t data);
        !            59: static ngx_int_t ngx_http_variable_server_port(ngx_http_request_t *r,
        !            60:     ngx_http_variable_value_t *v, uintptr_t data);
        !            61: static ngx_int_t ngx_http_variable_scheme(ngx_http_request_t *r,
        !            62:     ngx_http_variable_value_t *v, uintptr_t data);
        !            63: static ngx_int_t ngx_http_variable_https(ngx_http_request_t *r,
        !            64:     ngx_http_variable_value_t *v, uintptr_t data);
        !            65: static ngx_int_t ngx_http_variable_is_args(ngx_http_request_t *r,
        !            66:     ngx_http_variable_value_t *v, uintptr_t data);
        !            67: static ngx_int_t ngx_http_variable_document_root(ngx_http_request_t *r,
        !            68:     ngx_http_variable_value_t *v, uintptr_t data);
        !            69: static ngx_int_t ngx_http_variable_realpath_root(ngx_http_request_t *r,
        !            70:     ngx_http_variable_value_t *v, uintptr_t data);
        !            71: static ngx_int_t ngx_http_variable_request_filename(ngx_http_request_t *r,
        !            72:     ngx_http_variable_value_t *v, uintptr_t data);
        !            73: static ngx_int_t ngx_http_variable_server_name(ngx_http_request_t *r,
        !            74:     ngx_http_variable_value_t *v, uintptr_t data);
        !            75: static ngx_int_t ngx_http_variable_request_method(ngx_http_request_t *r,
        !            76:     ngx_http_variable_value_t *v, uintptr_t data);
        !            77: static ngx_int_t ngx_http_variable_remote_user(ngx_http_request_t *r,
        !            78:     ngx_http_variable_value_t *v, uintptr_t data);
        !            79: static ngx_int_t ngx_http_variable_bytes_sent(ngx_http_request_t *r,
        !            80:     ngx_http_variable_value_t *v, uintptr_t data);
        !            81: static ngx_int_t ngx_http_variable_body_bytes_sent(ngx_http_request_t *r,
        !            82:     ngx_http_variable_value_t *v, uintptr_t data);
        !            83: static ngx_int_t ngx_http_variable_pipe(ngx_http_request_t *r,
        !            84:     ngx_http_variable_value_t *v, uintptr_t data);
        !            85: static ngx_int_t ngx_http_variable_request_completion(ngx_http_request_t *r,
        !            86:     ngx_http_variable_value_t *v, uintptr_t data);
        !            87: static ngx_int_t ngx_http_variable_request_body(ngx_http_request_t *r,
        !            88:     ngx_http_variable_value_t *v, uintptr_t data);
        !            89: static ngx_int_t ngx_http_variable_request_body_file(ngx_http_request_t *r,
        !            90:     ngx_http_variable_value_t *v, uintptr_t data);
        !            91: static ngx_int_t ngx_http_variable_request_length(ngx_http_request_t *r,
        !            92:     ngx_http_variable_value_t *v, uintptr_t data);
        !            93: static ngx_int_t ngx_http_variable_request_time(ngx_http_request_t *r,
        !            94:     ngx_http_variable_value_t *v, uintptr_t data);
        !            95: static ngx_int_t ngx_http_variable_status(ngx_http_request_t *r,
        !            96:     ngx_http_variable_value_t *v, uintptr_t data);
        !            97: 
        !            98: static ngx_int_t ngx_http_variable_sent_content_type(ngx_http_request_t *r,
        !            99:     ngx_http_variable_value_t *v, uintptr_t data);
        !           100: static ngx_int_t ngx_http_variable_sent_content_length(ngx_http_request_t *r,
        !           101:     ngx_http_variable_value_t *v, uintptr_t data);
        !           102: static ngx_int_t ngx_http_variable_sent_location(ngx_http_request_t *r,
        !           103:     ngx_http_variable_value_t *v, uintptr_t data);
        !           104: static ngx_int_t ngx_http_variable_sent_last_modified(ngx_http_request_t *r,
        !           105:     ngx_http_variable_value_t *v, uintptr_t data);
        !           106: static ngx_int_t ngx_http_variable_sent_connection(ngx_http_request_t *r,
        !           107:     ngx_http_variable_value_t *v, uintptr_t data);
        !           108: static ngx_int_t ngx_http_variable_sent_keep_alive(ngx_http_request_t *r,
        !           109:     ngx_http_variable_value_t *v, uintptr_t data);
        !           110: static ngx_int_t ngx_http_variable_sent_transfer_encoding(ngx_http_request_t *r,
        !           111:     ngx_http_variable_value_t *v, uintptr_t data);
        !           112: 
        !           113: static ngx_int_t ngx_http_variable_connection(ngx_http_request_t *r,
        !           114:     ngx_http_variable_value_t *v, uintptr_t data);
        !           115: static ngx_int_t ngx_http_variable_connection_requests(ngx_http_request_t *r,
        !           116:     ngx_http_variable_value_t *v, uintptr_t data);
        !           117: 
        !           118: static ngx_int_t ngx_http_variable_nginx_version(ngx_http_request_t *r,
        !           119:     ngx_http_variable_value_t *v, uintptr_t data);
        !           120: static ngx_int_t ngx_http_variable_hostname(ngx_http_request_t *r,
        !           121:     ngx_http_variable_value_t *v, uintptr_t data);
        !           122: static ngx_int_t ngx_http_variable_pid(ngx_http_request_t *r,
        !           123:     ngx_http_variable_value_t *v, uintptr_t data);
        !           124: static ngx_int_t ngx_http_variable_msec(ngx_http_request_t *r,
        !           125:     ngx_http_variable_value_t *v, uintptr_t data);
        !           126: static ngx_int_t ngx_http_variable_time_iso8601(ngx_http_request_t *r,
        !           127:     ngx_http_variable_value_t *v, uintptr_t data);
        !           128: static ngx_int_t ngx_http_variable_time_local(ngx_http_request_t *r,
        !           129:     ngx_http_variable_value_t *v, uintptr_t data);
        !           130: 
        !           131: /*
        !           132:  * TODO:
        !           133:  *     Apache CGI: AUTH_TYPE, PATH_INFO (null), PATH_TRANSLATED
        !           134:  *                 REMOTE_HOST (null), REMOTE_IDENT (null),
        !           135:  *                 SERVER_SOFTWARE
        !           136:  *
        !           137:  *     Apache SSI: DOCUMENT_NAME, LAST_MODIFIED, USER_NAME (file owner)
        !           138:  */
        !           139: 
        !           140: /*
        !           141:  * the $http_host, $http_user_agent, $http_referer, and $http_via
        !           142:  * variables may be handled by generic
        !           143:  * ngx_http_variable_unknown_header_in(), but for performance reasons
        !           144:  * they are handled using dedicated entries
        !           145:  */
        !           146: 
        !           147: static ngx_http_variable_t  ngx_http_core_variables[] = {
        !           148: 
        !           149:     { ngx_string("http_host"), NULL, ngx_http_variable_header,
        !           150:       offsetof(ngx_http_request_t, headers_in.host), 0, 0 },
        !           151: 
        !           152:     { ngx_string("http_user_agent"), NULL, ngx_http_variable_header,
        !           153:       offsetof(ngx_http_request_t, headers_in.user_agent), 0, 0 },
        !           154: 
        !           155:     { ngx_string("http_referer"), NULL, ngx_http_variable_header,
        !           156:       offsetof(ngx_http_request_t, headers_in.referer), 0, 0 },
        !           157: 
        !           158: #if (NGX_HTTP_GZIP)
        !           159:     { ngx_string("http_via"), NULL, ngx_http_variable_header,
        !           160:       offsetof(ngx_http_request_t, headers_in.via), 0, 0 },
        !           161: #endif
        !           162: 
        !           163: #if (NGX_HTTP_X_FORWARDED_FOR)
        !           164:     { ngx_string("http_x_forwarded_for"), NULL, ngx_http_variable_headers,
        !           165:       offsetof(ngx_http_request_t, headers_in.x_forwarded_for), 0, 0 },
        !           166: #endif
        !           167: 
        !           168:     { ngx_string("http_cookie"), NULL, ngx_http_variable_cookies,
        !           169:       offsetof(ngx_http_request_t, headers_in.cookies), 0, 0 },
        !           170: 
        !           171:     { ngx_string("content_length"), NULL, ngx_http_variable_content_length,
        !           172:       0, 0, 0 },
        !           173: 
        !           174:     { ngx_string("content_type"), NULL, ngx_http_variable_header,
        !           175:       offsetof(ngx_http_request_t, headers_in.content_type), 0, 0 },
        !           176: 
        !           177:     { ngx_string("host"), NULL, ngx_http_variable_host, 0, 0, 0 },
        !           178: 
        !           179:     { ngx_string("binary_remote_addr"), NULL,
        !           180:       ngx_http_variable_binary_remote_addr, 0, 0, 0 },
        !           181: 
        !           182:     { ngx_string("remote_addr"), NULL, ngx_http_variable_remote_addr, 0, 0, 0 },
        !           183: 
        !           184:     { ngx_string("remote_port"), NULL, ngx_http_variable_remote_port, 0, 0, 0 },
        !           185: 
        !           186:     { ngx_string("server_addr"), NULL, ngx_http_variable_server_addr, 0, 0, 0 },
        !           187: 
        !           188:     { ngx_string("server_port"), NULL, ngx_http_variable_server_port, 0, 0, 0 },
        !           189: 
        !           190:     { ngx_string("server_protocol"), NULL, ngx_http_variable_request,
        !           191:       offsetof(ngx_http_request_t, http_protocol), 0, 0 },
        !           192: 
        !           193:     { ngx_string("scheme"), NULL, ngx_http_variable_scheme, 0, 0, 0 },
        !           194: 
        !           195:     { ngx_string("https"), NULL, ngx_http_variable_https, 0, 0, 0 },
        !           196: 
        !           197:     { ngx_string("request_uri"), NULL, ngx_http_variable_request,
        !           198:       offsetof(ngx_http_request_t, unparsed_uri), 0, 0 },
        !           199: 
        !           200:     { ngx_string("uri"), NULL, ngx_http_variable_request,
        !           201:       offsetof(ngx_http_request_t, uri),
        !           202:       NGX_HTTP_VAR_NOCACHEABLE, 0 },
        !           203: 
        !           204:     { ngx_string("document_uri"), NULL, ngx_http_variable_request,
        !           205:       offsetof(ngx_http_request_t, uri),
        !           206:       NGX_HTTP_VAR_NOCACHEABLE, 0 },
        !           207: 
        !           208:     { ngx_string("request"), NULL, ngx_http_variable_request_line, 0, 0, 0 },
        !           209: 
        !           210:     { ngx_string("document_root"), NULL,
        !           211:       ngx_http_variable_document_root, 0, NGX_HTTP_VAR_NOCACHEABLE, 0 },
        !           212: 
        !           213:     { ngx_string("realpath_root"), NULL,
        !           214:       ngx_http_variable_realpath_root, 0, NGX_HTTP_VAR_NOCACHEABLE, 0 },
        !           215: 
        !           216:     { ngx_string("query_string"), NULL, ngx_http_variable_request,
        !           217:       offsetof(ngx_http_request_t, args),
        !           218:       NGX_HTTP_VAR_NOCACHEABLE, 0 },
        !           219: 
        !           220:     { ngx_string("args"),
        !           221:       ngx_http_variable_request_set,
        !           222:       ngx_http_variable_request,
        !           223:       offsetof(ngx_http_request_t, args),
        !           224:       NGX_HTTP_VAR_CHANGEABLE|NGX_HTTP_VAR_NOCACHEABLE, 0 },
        !           225: 
        !           226:     { ngx_string("is_args"), NULL, ngx_http_variable_is_args,
        !           227:       0, NGX_HTTP_VAR_NOCACHEABLE, 0 },
        !           228: 
        !           229:     { ngx_string("request_filename"), NULL,
        !           230:       ngx_http_variable_request_filename, 0,
        !           231:       NGX_HTTP_VAR_NOCACHEABLE, 0 },
        !           232: 
        !           233:     { ngx_string("server_name"), NULL, ngx_http_variable_server_name, 0, 0, 0 },
        !           234: 
        !           235:     { ngx_string("request_method"), NULL,
        !           236:       ngx_http_variable_request_method, 0,
        !           237:       NGX_HTTP_VAR_NOCACHEABLE, 0 },
        !           238: 
        !           239:     { ngx_string("remote_user"), NULL, ngx_http_variable_remote_user, 0, 0, 0 },
        !           240: 
        !           241:     { ngx_string("bytes_sent"), NULL, ngx_http_variable_bytes_sent,
        !           242:       0, 0, 0 },
        !           243: 
        !           244:     { ngx_string("body_bytes_sent"), NULL, ngx_http_variable_body_bytes_sent,
        !           245:       0, 0, 0 },
        !           246: 
        !           247:     { ngx_string("pipe"), NULL, ngx_http_variable_pipe,
        !           248:       0, 0, 0 },
        !           249: 
        !           250:     { ngx_string("request_completion"), NULL,
        !           251:       ngx_http_variable_request_completion,
        !           252:       0, 0, 0 },
        !           253: 
        !           254:     { ngx_string("request_body"), NULL,
        !           255:       ngx_http_variable_request_body,
        !           256:       0, 0, 0 },
        !           257: 
        !           258:     { ngx_string("request_body_file"), NULL,
        !           259:       ngx_http_variable_request_body_file,
        !           260:       0, 0, 0 },
        !           261: 
        !           262:     { ngx_string("request_length"), NULL, ngx_http_variable_request_length,
        !           263:       0, NGX_HTTP_VAR_NOCACHEABLE, 0 },
        !           264: 
        !           265:     { ngx_string("request_time"), NULL, ngx_http_variable_request_time,
        !           266:       0, NGX_HTTP_VAR_NOCACHEABLE, 0 },
        !           267: 
        !           268:     { ngx_string("status"), NULL,
        !           269:       ngx_http_variable_status, 0,
        !           270:       NGX_HTTP_VAR_NOCACHEABLE, 0 },
        !           271: 
        !           272:     { ngx_string("sent_http_content_type"), NULL,
        !           273:       ngx_http_variable_sent_content_type, 0, 0, 0 },
        !           274: 
        !           275:     { ngx_string("sent_http_content_length"), NULL,
        !           276:       ngx_http_variable_sent_content_length, 0, 0, 0 },
        !           277: 
        !           278:     { ngx_string("sent_http_location"), NULL,
        !           279:       ngx_http_variable_sent_location, 0, 0, 0 },
        !           280: 
        !           281:     { ngx_string("sent_http_last_modified"), NULL,
        !           282:       ngx_http_variable_sent_last_modified, 0, 0, 0 },
        !           283: 
        !           284:     { ngx_string("sent_http_connection"), NULL,
        !           285:       ngx_http_variable_sent_connection, 0, 0, 0 },
        !           286: 
        !           287:     { ngx_string("sent_http_keep_alive"), NULL,
        !           288:       ngx_http_variable_sent_keep_alive, 0, 0, 0 },
        !           289: 
        !           290:     { ngx_string("sent_http_transfer_encoding"), NULL,
        !           291:       ngx_http_variable_sent_transfer_encoding, 0, 0, 0 },
        !           292: 
        !           293:     { ngx_string("sent_http_cache_control"), NULL, ngx_http_variable_headers,
        !           294:       offsetof(ngx_http_request_t, headers_out.cache_control), 0, 0 },
        !           295: 
        !           296:     { ngx_string("limit_rate"), ngx_http_variable_request_set_size,
        !           297:       ngx_http_variable_request_get_size,
        !           298:       offsetof(ngx_http_request_t, limit_rate),
        !           299:       NGX_HTTP_VAR_CHANGEABLE|NGX_HTTP_VAR_NOCACHEABLE, 0 },
        !           300: 
        !           301:     { ngx_string("connection"), NULL,
        !           302:       ngx_http_variable_connection, 0, 0, 0 },
        !           303: 
        !           304:     { ngx_string("connection_requests"), NULL,
        !           305:       ngx_http_variable_connection_requests, 0, 0, 0 },
        !           306: 
        !           307:     { ngx_string("nginx_version"), NULL, ngx_http_variable_nginx_version,
        !           308:       0, 0, 0 },
        !           309: 
        !           310:     { ngx_string("hostname"), NULL, ngx_http_variable_hostname,
        !           311:       0, 0, 0 },
        !           312: 
        !           313:     { ngx_string("pid"), NULL, ngx_http_variable_pid,
        !           314:       0, 0, 0 },
        !           315: 
        !           316:     { ngx_string("msec"), NULL, ngx_http_variable_msec,
        !           317:       0, NGX_HTTP_VAR_NOCACHEABLE, 0 },
        !           318: 
        !           319:     { ngx_string("time_iso8601"), NULL, ngx_http_variable_time_iso8601,
        !           320:       0, NGX_HTTP_VAR_NOCACHEABLE, 0 },
        !           321: 
        !           322:     { ngx_string("time_local"), NULL, ngx_http_variable_time_local,
        !           323:       0, NGX_HTTP_VAR_NOCACHEABLE, 0 },
        !           324: 
        !           325: #if (NGX_HAVE_TCP_INFO)
        !           326:     { ngx_string("tcpinfo_rtt"), NULL, ngx_http_variable_tcpinfo,
        !           327:       0, NGX_HTTP_VAR_NOCACHEABLE, 0 },
        !           328: 
        !           329:     { ngx_string("tcpinfo_rttvar"), NULL, ngx_http_variable_tcpinfo,
        !           330:       1, NGX_HTTP_VAR_NOCACHEABLE, 0 },
        !           331: 
        !           332:     { ngx_string("tcpinfo_snd_cwnd"), NULL, ngx_http_variable_tcpinfo,
        !           333:       2, NGX_HTTP_VAR_NOCACHEABLE, 0 },
        !           334: 
        !           335:     { ngx_string("tcpinfo_rcv_space"), NULL, ngx_http_variable_tcpinfo,
        !           336:       3, NGX_HTTP_VAR_NOCACHEABLE, 0 },
        !           337: #endif
        !           338: 
        !           339:     { ngx_null_string, NULL, NULL, 0, 0, 0 }
        !           340: };
        !           341: 
        !           342: 
        !           343: ngx_http_variable_value_t  ngx_http_variable_null_value =
        !           344:     ngx_http_variable("");
        !           345: ngx_http_variable_value_t  ngx_http_variable_true_value =
        !           346:     ngx_http_variable("1");
        !           347: 
        !           348: 
        !           349: ngx_http_variable_t *
        !           350: ngx_http_add_variable(ngx_conf_t *cf, ngx_str_t *name, ngx_uint_t flags)
        !           351: {
        !           352:     ngx_int_t                   rc;
        !           353:     ngx_uint_t                  i;
        !           354:     ngx_hash_key_t             *key;
        !           355:     ngx_http_variable_t        *v;
        !           356:     ngx_http_core_main_conf_t  *cmcf;
        !           357: 
        !           358:     if (name->len == 0) {
        !           359:         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
        !           360:                            "invalid variable name \"$\"");
        !           361:         return NULL;
        !           362:     }
        !           363: 
        !           364:     cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);
        !           365: 
        !           366:     key = cmcf->variables_keys->keys.elts;
        !           367:     for (i = 0; i < cmcf->variables_keys->keys.nelts; i++) {
        !           368:         if (name->len != key[i].key.len
        !           369:             || ngx_strncasecmp(name->data, key[i].key.data, name->len) != 0)
        !           370:         {
        !           371:             continue;
        !           372:         }
        !           373: 
        !           374:         v = key[i].value;
        !           375: 
        !           376:         if (!(v->flags & NGX_HTTP_VAR_CHANGEABLE)) {
        !           377:             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
        !           378:                                "the duplicate \"%V\" variable", name);
        !           379:             return NULL;
        !           380:         }
        !           381: 
        !           382:         return v;
        !           383:     }
        !           384: 
        !           385:     v = ngx_palloc(cf->pool, sizeof(ngx_http_variable_t));
        !           386:     if (v == NULL) {
        !           387:         return NULL;
        !           388:     }
        !           389: 
        !           390:     v->name.len = name->len;
        !           391:     v->name.data = ngx_pnalloc(cf->pool, name->len);
        !           392:     if (v->name.data == NULL) {
        !           393:         return NULL;
        !           394:     }
        !           395: 
        !           396:     ngx_strlow(v->name.data, name->data, name->len);
        !           397: 
        !           398:     v->set_handler = NULL;
        !           399:     v->get_handler = NULL;
        !           400:     v->data = 0;
        !           401:     v->flags = flags;
        !           402:     v->index = 0;
        !           403: 
        !           404:     rc = ngx_hash_add_key(cmcf->variables_keys, &v->name, v, 0);
        !           405: 
        !           406:     if (rc == NGX_ERROR) {
        !           407:         return NULL;
        !           408:     }
        !           409: 
        !           410:     if (rc == NGX_BUSY) {
        !           411:         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
        !           412:                            "conflicting variable name \"%V\"", name);
        !           413:         return NULL;
        !           414:     }
        !           415: 
        !           416:     return v;
        !           417: }
        !           418: 
        !           419: 
        !           420: ngx_int_t
        !           421: ngx_http_get_variable_index(ngx_conf_t *cf, ngx_str_t *name)
        !           422: {
        !           423:     ngx_uint_t                  i;
        !           424:     ngx_http_variable_t        *v;
        !           425:     ngx_http_core_main_conf_t  *cmcf;
        !           426: 
        !           427:     if (name->len == 0) {
        !           428:         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
        !           429:                            "invalid variable name \"$\"");
        !           430:         return NGX_ERROR;
        !           431:     }
        !           432: 
        !           433:     cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);
        !           434: 
        !           435:     v = cmcf->variables.elts;
        !           436: 
        !           437:     if (v == NULL) {
        !           438:         if (ngx_array_init(&cmcf->variables, cf->pool, 4,
        !           439:                            sizeof(ngx_http_variable_t))
        !           440:             != NGX_OK)
        !           441:         {
        !           442:             return NGX_ERROR;
        !           443:         }
        !           444: 
        !           445:     } else {
        !           446:         for (i = 0; i < cmcf->variables.nelts; i++) {
        !           447:             if (name->len != v[i].name.len
        !           448:                 || ngx_strncasecmp(name->data, v[i].name.data, name->len) != 0)
        !           449:             {
        !           450:                 continue;
        !           451:             }
        !           452: 
        !           453:             return i;
        !           454:         }
        !           455:     }
        !           456: 
        !           457:     v = ngx_array_push(&cmcf->variables);
        !           458:     if (v == NULL) {
        !           459:         return NGX_ERROR;
        !           460:     }
        !           461: 
        !           462:     v->name.len = name->len;
        !           463:     v->name.data = ngx_pnalloc(cf->pool, name->len);
        !           464:     if (v->name.data == NULL) {
        !           465:         return NGX_ERROR;
        !           466:     }
        !           467: 
        !           468:     ngx_strlow(v->name.data, name->data, name->len);
        !           469: 
        !           470:     v->set_handler = NULL;
        !           471:     v->get_handler = NULL;
        !           472:     v->data = 0;
        !           473:     v->flags = 0;
        !           474:     v->index = cmcf->variables.nelts - 1;
        !           475: 
        !           476:     return v->index;
        !           477: }
        !           478: 
        !           479: 
        !           480: ngx_http_variable_value_t *
        !           481: ngx_http_get_indexed_variable(ngx_http_request_t *r, ngx_uint_t index)
        !           482: {
        !           483:     ngx_http_variable_t        *v;
        !           484:     ngx_http_core_main_conf_t  *cmcf;
        !           485: 
        !           486:     cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
        !           487: 
        !           488:     if (cmcf->variables.nelts <= index) {
        !           489:         ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
        !           490:                       "unknown variable index: %d", index);
        !           491:         return NULL;
        !           492:     }
        !           493: 
        !           494:     if (r->variables[index].not_found || r->variables[index].valid) {
        !           495:         return &r->variables[index];
        !           496:     }
        !           497: 
        !           498:     v = cmcf->variables.elts;
        !           499: 
        !           500:     if (v[index].get_handler(r, &r->variables[index], v[index].data)
        !           501:         == NGX_OK)
        !           502:     {
        !           503:         if (v[index].flags & NGX_HTTP_VAR_NOCACHEABLE) {
        !           504:             r->variables[index].no_cacheable = 1;
        !           505:         }
        !           506: 
        !           507:         return &r->variables[index];
        !           508:     }
        !           509: 
        !           510:     r->variables[index].valid = 0;
        !           511:     r->variables[index].not_found = 1;
        !           512: 
        !           513:     return NULL;
        !           514: }
        !           515: 
        !           516: 
        !           517: ngx_http_variable_value_t *
        !           518: ngx_http_get_flushed_variable(ngx_http_request_t *r, ngx_uint_t index)
        !           519: {
        !           520:     ngx_http_variable_value_t  *v;
        !           521: 
        !           522:     v = &r->variables[index];
        !           523: 
        !           524:     if (v->valid || v->not_found) {
        !           525:         if (!v->no_cacheable) {
        !           526:             return v;
        !           527:         }
        !           528: 
        !           529:         v->valid = 0;
        !           530:         v->not_found = 0;
        !           531:     }
        !           532: 
        !           533:     return ngx_http_get_indexed_variable(r, index);
        !           534: }
        !           535: 
        !           536: 
        !           537: ngx_http_variable_value_t *
        !           538: ngx_http_get_variable(ngx_http_request_t *r, ngx_str_t *name, ngx_uint_t key)
        !           539: {
        !           540:     ngx_http_variable_t        *v;
        !           541:     ngx_http_variable_value_t  *vv;
        !           542:     ngx_http_core_main_conf_t  *cmcf;
        !           543: 
        !           544:     cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
        !           545: 
        !           546:     v = ngx_hash_find(&cmcf->variables_hash, key, name->data, name->len);
        !           547: 
        !           548:     if (v) {
        !           549:         if (v->flags & NGX_HTTP_VAR_INDEXED) {
        !           550:             return ngx_http_get_flushed_variable(r, v->index);
        !           551: 
        !           552:         } else {
        !           553: 
        !           554:             vv = ngx_palloc(r->pool, sizeof(ngx_http_variable_value_t));
        !           555: 
        !           556:             if (vv && v->get_handler(r, vv, v->data) == NGX_OK) {
        !           557:                 return vv;
        !           558:             }
        !           559: 
        !           560:             return NULL;
        !           561:         }
        !           562:     }
        !           563: 
        !           564:     vv = ngx_palloc(r->pool, sizeof(ngx_http_variable_value_t));
        !           565:     if (vv == NULL) {
        !           566:         return NULL;
        !           567:     }
        !           568: 
        !           569:     if (ngx_strncmp(name->data, "http_", 5) == 0) {
        !           570: 
        !           571:         if (ngx_http_variable_unknown_header_in(r, vv, (uintptr_t) name)
        !           572:             == NGX_OK)
        !           573:         {
        !           574:             return vv;
        !           575:         }
        !           576: 
        !           577:         return NULL;
        !           578:     }
        !           579: 
        !           580:     if (ngx_strncmp(name->data, "sent_http_", 10) == 0) {
        !           581: 
        !           582:         if (ngx_http_variable_unknown_header_out(r, vv, (uintptr_t) name)
        !           583:             == NGX_OK)
        !           584:         {
        !           585:             return vv;
        !           586:         }
        !           587: 
        !           588:         return NULL;
        !           589:     }
        !           590: 
        !           591:     if (ngx_strncmp(name->data, "upstream_http_", 14) == 0) {
        !           592: 
        !           593:         if (ngx_http_upstream_header_variable(r, vv, (uintptr_t) name)
        !           594:             == NGX_OK)
        !           595:         {
        !           596:             return vv;
        !           597:         }
        !           598: 
        !           599:         return NULL;
        !           600:     }
        !           601: 
        !           602:     if (ngx_strncmp(name->data, "cookie_", 7) == 0) {
        !           603: 
        !           604:         if (ngx_http_variable_cookie(r, vv, (uintptr_t) name) == NGX_OK) {
        !           605:             return vv;
        !           606:         }
        !           607: 
        !           608:         return NULL;
        !           609:     }
        !           610: 
        !           611:     if (ngx_strncmp(name->data, "arg_", 4) == 0) {
        !           612: 
        !           613:         if (ngx_http_variable_argument(r, vv, (uintptr_t) name) == NGX_OK) {
        !           614:             return vv;
        !           615:         }
        !           616: 
        !           617:         return NULL;
        !           618:     }
        !           619: 
        !           620:     vv->not_found = 1;
        !           621: 
        !           622:     return vv;
        !           623: }
        !           624: 
        !           625: 
        !           626: static ngx_int_t
        !           627: ngx_http_variable_request(ngx_http_request_t *r, ngx_http_variable_value_t *v,
        !           628:     uintptr_t data)
        !           629: {
        !           630:     ngx_str_t  *s;
        !           631: 
        !           632:     s = (ngx_str_t *) ((char *) r + data);
        !           633: 
        !           634:     if (s->data) {
        !           635:         v->len = s->len;
        !           636:         v->valid = 1;
        !           637:         v->no_cacheable = 0;
        !           638:         v->not_found = 0;
        !           639:         v->data = s->data;
        !           640: 
        !           641:     } else {
        !           642:         v->not_found = 1;
        !           643:     }
        !           644: 
        !           645:     return NGX_OK;
        !           646: }
        !           647: 
        !           648: 
        !           649: static void
        !           650: ngx_http_variable_request_set(ngx_http_request_t *r,
        !           651:     ngx_http_variable_value_t *v, uintptr_t data)
        !           652: {
        !           653:     ngx_str_t  *s;
        !           654: 
        !           655:     s = (ngx_str_t *) ((char *) r + data);
        !           656: 
        !           657:     s->len = v->len;
        !           658:     s->data = v->data;
        !           659: }
        !           660: 
        !           661: 
        !           662: static ngx_int_t
        !           663: ngx_http_variable_request_get_size(ngx_http_request_t *r,
        !           664:     ngx_http_variable_value_t *v, uintptr_t data)
        !           665: {
        !           666:     size_t  *sp;
        !           667: 
        !           668:     sp = (size_t *) ((char *) r + data);
        !           669: 
        !           670:     v->data = ngx_pnalloc(r->pool, NGX_SIZE_T_LEN);
        !           671:     if (v->data == NULL) {
        !           672:         return NGX_ERROR;
        !           673:     }
        !           674: 
        !           675:     v->len = ngx_sprintf(v->data, "%uz", *sp) - v->data;
        !           676:     v->valid = 1;
        !           677:     v->no_cacheable = 0;
        !           678:     v->not_found = 0;
        !           679: 
        !           680:     return NGX_OK;
        !           681: }
        !           682: 
        !           683: 
        !           684: static void
        !           685: ngx_http_variable_request_set_size(ngx_http_request_t *r,
        !           686:     ngx_http_variable_value_t *v, uintptr_t data)
        !           687: {
        !           688:     ssize_t    s, *sp;
        !           689:     ngx_str_t  val;
        !           690: 
        !           691:     val.len = v->len;
        !           692:     val.data = v->data;
        !           693: 
        !           694:     s = ngx_parse_size(&val);
        !           695: 
        !           696:     if (s == NGX_ERROR) {
        !           697:         ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
        !           698:                       "invalid size \"%V\"", &val);
        !           699:         return;
        !           700:     }
        !           701: 
        !           702:     sp = (ssize_t *) ((char *) r + data);
        !           703: 
        !           704:     *sp = s;
        !           705: 
        !           706:     return;
        !           707: }
        !           708: 
        !           709: 
        !           710: static ngx_int_t
        !           711: ngx_http_variable_header(ngx_http_request_t *r, ngx_http_variable_value_t *v,
        !           712:     uintptr_t data)
        !           713: {
        !           714:     ngx_table_elt_t  *h;
        !           715: 
        !           716:     h = *(ngx_table_elt_t **) ((char *) r + data);
        !           717: 
        !           718:     if (h) {
        !           719:         v->len = h->value.len;
        !           720:         v->valid = 1;
        !           721:         v->no_cacheable = 0;
        !           722:         v->not_found = 0;
        !           723:         v->data = h->value.data;
        !           724: 
        !           725:     } else {
        !           726:         v->not_found = 1;
        !           727:     }
        !           728: 
        !           729:     return NGX_OK;
        !           730: }
        !           731: 
        !           732: 
        !           733: static ngx_int_t
        !           734: ngx_http_variable_cookies(ngx_http_request_t *r,
        !           735:     ngx_http_variable_value_t *v, uintptr_t data)
        !           736: {
        !           737:     return ngx_http_variable_headers_internal(r, v, data, ';');
        !           738: }
        !           739: 
        !           740: 
        !           741: static ngx_int_t
        !           742: ngx_http_variable_headers(ngx_http_request_t *r,
        !           743:     ngx_http_variable_value_t *v, uintptr_t data)
        !           744: {
        !           745:     return ngx_http_variable_headers_internal(r, v, data, ',');
        !           746: }
        !           747: 
        !           748: 
        !           749: static ngx_int_t
        !           750: ngx_http_variable_headers_internal(ngx_http_request_t *r,
        !           751:     ngx_http_variable_value_t *v, uintptr_t data, u_char sep)
        !           752: {
        !           753:     size_t             len;
        !           754:     u_char            *p, *end;
        !           755:     ngx_uint_t         i, n;
        !           756:     ngx_array_t       *a;
        !           757:     ngx_table_elt_t  **h;
        !           758: 
        !           759:     a = (ngx_array_t *) ((char *) r + data);
        !           760: 
        !           761:     n = a->nelts;
        !           762:     h = a->elts;
        !           763: 
        !           764:     len = 0;
        !           765: 
        !           766:     for (i = 0; i < n; i++) {
        !           767: 
        !           768:         if (h[i]->hash == 0) {
        !           769:             continue;
        !           770:         }
        !           771: 
        !           772:         len += h[i]->value.len + 2;
        !           773:     }
        !           774: 
        !           775:     if (len == 0) {
        !           776:         v->not_found = 1;
        !           777:         return NGX_OK;
        !           778:     }
        !           779: 
        !           780:     len -= 2;
        !           781: 
        !           782:     v->valid = 1;
        !           783:     v->no_cacheable = 0;
        !           784:     v->not_found = 0;
        !           785: 
        !           786:     if (n == 1) {
        !           787:         v->len = (*h)->value.len;
        !           788:         v->data = (*h)->value.data;
        !           789: 
        !           790:         return NGX_OK;
        !           791:     }
        !           792: 
        !           793:     p = ngx_pnalloc(r->pool, len);
        !           794:     if (p == NULL) {
        !           795:         return NGX_ERROR;
        !           796:     }
        !           797: 
        !           798:     v->len = len;
        !           799:     v->data = p;
        !           800: 
        !           801:     end = p + len;
        !           802: 
        !           803:     for (i = 0; /* void */ ; i++) {
        !           804: 
        !           805:         if (h[i]->hash == 0) {
        !           806:             continue;
        !           807:         }
        !           808: 
        !           809:         p = ngx_copy(p, h[i]->value.data, h[i]->value.len);
        !           810: 
        !           811:         if (p == end) {
        !           812:             break;
        !           813:         }
        !           814: 
        !           815:         *p++ = sep; *p++ = ' ';
        !           816:     }
        !           817: 
        !           818:     return NGX_OK;
        !           819: }
        !           820: 
        !           821: 
        !           822: static ngx_int_t
        !           823: ngx_http_variable_unknown_header_in(ngx_http_request_t *r,
        !           824:     ngx_http_variable_value_t *v, uintptr_t data)
        !           825: {
        !           826:     return ngx_http_variable_unknown_header(v, (ngx_str_t *) data,
        !           827:                                             &r->headers_in.headers.part,
        !           828:                                             sizeof("http_") - 1);
        !           829: }
        !           830: 
        !           831: 
        !           832: static ngx_int_t
        !           833: ngx_http_variable_unknown_header_out(ngx_http_request_t *r,
        !           834:     ngx_http_variable_value_t *v, uintptr_t data)
        !           835: {
        !           836:     return ngx_http_variable_unknown_header(v, (ngx_str_t *) data,
        !           837:                                             &r->headers_out.headers.part,
        !           838:                                             sizeof("sent_http_") - 1);
        !           839: }
        !           840: 
        !           841: 
        !           842: ngx_int_t
        !           843: ngx_http_variable_unknown_header(ngx_http_variable_value_t *v, ngx_str_t *var,
        !           844:     ngx_list_part_t *part, size_t prefix)
        !           845: {
        !           846:     u_char            ch;
        !           847:     ngx_uint_t        i, n;
        !           848:     ngx_table_elt_t  *header;
        !           849: 
        !           850:     header = part->elts;
        !           851: 
        !           852:     for (i = 0; /* void */ ; i++) {
        !           853: 
        !           854:         if (i >= part->nelts) {
        !           855:             if (part->next == NULL) {
        !           856:                 break;
        !           857:             }
        !           858: 
        !           859:             part = part->next;
        !           860:             header = part->elts;
        !           861:             i = 0;
        !           862:         }
        !           863: 
        !           864:         if (header[i].hash == 0) {
        !           865:             continue;
        !           866:         }
        !           867: 
        !           868:         for (n = 0; n + prefix < var->len && n < header[i].key.len; n++) {
        !           869:             ch = header[i].key.data[n];
        !           870: 
        !           871:             if (ch >= 'A' && ch <= 'Z') {
        !           872:                 ch |= 0x20;
        !           873: 
        !           874:             } else if (ch == '-') {
        !           875:                 ch = '_';
        !           876:             }
        !           877: 
        !           878:             if (var->data[n + prefix] != ch) {
        !           879:                 break;
        !           880:             }
        !           881:         }
        !           882: 
        !           883:         if (n + prefix == var->len && n == header[i].key.len) {
        !           884:             v->len = header[i].value.len;
        !           885:             v->valid = 1;
        !           886:             v->no_cacheable = 0;
        !           887:             v->not_found = 0;
        !           888:             v->data = header[i].value.data;
        !           889: 
        !           890:             return NGX_OK;
        !           891:         }
        !           892:     }
        !           893: 
        !           894:     v->not_found = 1;
        !           895: 
        !           896:     return NGX_OK;
        !           897: }
        !           898: 
        !           899: 
        !           900: static ngx_int_t
        !           901: ngx_http_variable_request_line(ngx_http_request_t *r,
        !           902:     ngx_http_variable_value_t *v, uintptr_t data)
        !           903: {
        !           904:     u_char  *p, *s;
        !           905: 
        !           906:     s = r->request_line.data;
        !           907: 
        !           908:     if (s == NULL) {
        !           909:         s = r->request_start;
        !           910: 
        !           911:         if (s == NULL) {
        !           912:             v->not_found = 1;
        !           913:             return NGX_OK;
        !           914:         }
        !           915: 
        !           916:         for (p = s; p < r->header_in->last; p++) {
        !           917:             if (*p == CR || *p == LF) {
        !           918:                 break;
        !           919:             }
        !           920:         }
        !           921: 
        !           922:         r->request_line.len = p - s;
        !           923:         r->request_line.data = s;
        !           924:     }
        !           925: 
        !           926:     v->len = r->request_line.len;
        !           927:     v->valid = 1;
        !           928:     v->no_cacheable = 0;
        !           929:     v->not_found = 0;
        !           930:     v->data = s;
        !           931: 
        !           932:     return NGX_OK;
        !           933: }
        !           934: 
        !           935: 
        !           936: static ngx_int_t
        !           937: ngx_http_variable_cookie(ngx_http_request_t *r, ngx_http_variable_value_t *v,
        !           938:     uintptr_t data)
        !           939: {
        !           940:     ngx_str_t *name = (ngx_str_t *) data;
        !           941: 
        !           942:     ngx_str_t  cookie, s;
        !           943: 
        !           944:     s.len = name->len - (sizeof("cookie_") - 1);
        !           945:     s.data = name->data + sizeof("cookie_") - 1;
        !           946: 
        !           947:     if (ngx_http_parse_multi_header_lines(&r->headers_in.cookies, &s, &cookie)
        !           948:         == NGX_DECLINED)
        !           949:     {
        !           950:         v->not_found = 1;
        !           951:         return NGX_OK;
        !           952:     }
        !           953: 
        !           954:     v->len = cookie.len;
        !           955:     v->valid = 1;
        !           956:     v->no_cacheable = 0;
        !           957:     v->not_found = 0;
        !           958:     v->data = cookie.data;
        !           959: 
        !           960:     return NGX_OK;
        !           961: }
        !           962: 
        !           963: 
        !           964: static ngx_int_t
        !           965: ngx_http_variable_argument(ngx_http_request_t *r, ngx_http_variable_value_t *v,
        !           966:     uintptr_t data)
        !           967: {
        !           968:     ngx_str_t *name = (ngx_str_t *) data;
        !           969: 
        !           970:     u_char     *arg;
        !           971:     size_t      len;
        !           972:     ngx_str_t   value;
        !           973: 
        !           974:     len = name->len - (sizeof("arg_") - 1);
        !           975:     arg = name->data + sizeof("arg_") - 1;
        !           976: 
        !           977:     if (ngx_http_arg(r, arg, len, &value) != NGX_OK) {
        !           978:         v->not_found = 1;
        !           979:         return NGX_OK;
        !           980:     }
        !           981: 
        !           982:     v->data = value.data;
        !           983:     v->len = value.len;
        !           984:     v->valid = 1;
        !           985:     v->no_cacheable = 0;
        !           986:     v->not_found = 0;
        !           987: 
        !           988:     return NGX_OK;
        !           989: }
        !           990: 
        !           991: 
        !           992: #if (NGX_HAVE_TCP_INFO)
        !           993: 
        !           994: static ngx_int_t
        !           995: ngx_http_variable_tcpinfo(ngx_http_request_t *r, ngx_http_variable_value_t *v,
        !           996:     uintptr_t data)
        !           997: {
        !           998:     struct tcp_info  ti;
        !           999:     socklen_t        len;
        !          1000:     uint32_t         value;
        !          1001: 
        !          1002:     len = sizeof(struct tcp_info);
        !          1003:     if (getsockopt(r->connection->fd, IPPROTO_TCP, TCP_INFO, &ti, &len) == -1) {
        !          1004:         v->not_found = 1;
        !          1005:         return NGX_OK;
        !          1006:     }
        !          1007: 
        !          1008:     v->data = ngx_pnalloc(r->pool, NGX_INT32_LEN);
        !          1009:     if (v->data == NULL) {
        !          1010:         return NGX_ERROR;
        !          1011:     }
        !          1012: 
        !          1013:     switch (data) {
        !          1014:     case 0:
        !          1015:         value = ti.tcpi_rtt;
        !          1016:         break;
        !          1017: 
        !          1018:     case 1:
        !          1019:         value = ti.tcpi_rttvar;
        !          1020:         break;
        !          1021: 
        !          1022:     case 2:
        !          1023:         value = ti.tcpi_snd_cwnd;
        !          1024:         break;
        !          1025: 
        !          1026:     case 3:
        !          1027:         value = ti.tcpi_rcv_space;
        !          1028:         break;
        !          1029: 
        !          1030:     /* suppress warning */
        !          1031:     default:
        !          1032:         value = 0;
        !          1033:         break;
        !          1034:     }
        !          1035: 
        !          1036:     v->len = ngx_sprintf(v->data, "%uD", value) - v->data;
        !          1037:     v->valid = 1;
        !          1038:     v->no_cacheable = 0;
        !          1039:     v->not_found = 0;
        !          1040: 
        !          1041:     return NGX_OK;
        !          1042: }
        !          1043: 
        !          1044: #endif
        !          1045: 
        !          1046: 
        !          1047: static ngx_int_t
        !          1048: ngx_http_variable_content_length(ngx_http_request_t *r,
        !          1049:     ngx_http_variable_value_t *v, uintptr_t data)
        !          1050: {
        !          1051:     u_char  *p;
        !          1052: 
        !          1053:     if (r->headers_in.content_length) {
        !          1054:         v->len = r->headers_in.content_length->value.len;
        !          1055:         v->data = r->headers_in.content_length->value.data;
        !          1056:         v->valid = 1;
        !          1057:         v->no_cacheable = 0;
        !          1058:         v->not_found = 0;
        !          1059: 
        !          1060:     } else if (r->headers_in.content_length_n >= 0) {
        !          1061:         p = ngx_pnalloc(r->pool, NGX_OFF_T_LEN);
        !          1062:         if (p == NULL) {
        !          1063:             return NGX_ERROR;
        !          1064:         }
        !          1065: 
        !          1066:         v->len = ngx_sprintf(p, "%O", r->headers_in.content_length_n) - p;
        !          1067:         v->data = p;
        !          1068:         v->valid = 1;
        !          1069:         v->no_cacheable = 0;
        !          1070:         v->not_found = 0;
        !          1071: 
        !          1072:     } else {
        !          1073:         v->not_found = 1;
        !          1074:     }
        !          1075: 
        !          1076:     return NGX_OK;
        !          1077: }
        !          1078: 
        !          1079: 
        !          1080: static ngx_int_t
        !          1081: ngx_http_variable_host(ngx_http_request_t *r, ngx_http_variable_value_t *v,
        !          1082:     uintptr_t data)
        !          1083: {
        !          1084:     ngx_http_core_srv_conf_t  *cscf;
        !          1085: 
        !          1086:     if (r->headers_in.server.len) {
        !          1087:         v->len = r->headers_in.server.len;
        !          1088:         v->data = r->headers_in.server.data;
        !          1089: 
        !          1090:     } else {
        !          1091:         cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
        !          1092: 
        !          1093:         v->len = cscf->server_name.len;
        !          1094:         v->data = cscf->server_name.data;
        !          1095:     }
        !          1096: 
        !          1097:     v->valid = 1;
        !          1098:     v->no_cacheable = 0;
        !          1099:     v->not_found = 0;
        !          1100: 
        !          1101:     return NGX_OK;
        !          1102: }
        !          1103: 
        !          1104: 
        !          1105: static ngx_int_t
        !          1106: ngx_http_variable_binary_remote_addr(ngx_http_request_t *r,
        !          1107:     ngx_http_variable_value_t *v, uintptr_t data)
        !          1108: {
        !          1109:     struct sockaddr_in   *sin;
        !          1110: #if (NGX_HAVE_INET6)
        !          1111:     struct sockaddr_in6  *sin6;
        !          1112: #endif
        !          1113: 
        !          1114:     switch (r->connection->sockaddr->sa_family) {
        !          1115: 
        !          1116: #if (NGX_HAVE_INET6)
        !          1117:     case AF_INET6:
        !          1118:         sin6 = (struct sockaddr_in6 *) r->connection->sockaddr;
        !          1119: 
        !          1120:         v->len = sizeof(struct in6_addr);
        !          1121:         v->valid = 1;
        !          1122:         v->no_cacheable = 0;
        !          1123:         v->not_found = 0;
        !          1124:         v->data = sin6->sin6_addr.s6_addr;
        !          1125: 
        !          1126:         break;
        !          1127: #endif
        !          1128: 
        !          1129:     default: /* AF_INET */
        !          1130:         sin = (struct sockaddr_in *) r->connection->sockaddr;
        !          1131: 
        !          1132:         v->len = sizeof(in_addr_t);
        !          1133:         v->valid = 1;
        !          1134:         v->no_cacheable = 0;
        !          1135:         v->not_found = 0;
        !          1136:         v->data = (u_char *) &sin->sin_addr;
        !          1137: 
        !          1138:         break;
        !          1139:     }
        !          1140: 
        !          1141:     return NGX_OK;
        !          1142: }
        !          1143: 
        !          1144: 
        !          1145: static ngx_int_t
        !          1146: ngx_http_variable_remote_addr(ngx_http_request_t *r,
        !          1147:     ngx_http_variable_value_t *v, uintptr_t data)
        !          1148: {
        !          1149:     v->len = r->connection->addr_text.len;
        !          1150:     v->valid = 1;
        !          1151:     v->no_cacheable = 0;
        !          1152:     v->not_found = 0;
        !          1153:     v->data = r->connection->addr_text.data;
        !          1154: 
        !          1155:     return NGX_OK;
        !          1156: }
        !          1157: 
        !          1158: 
        !          1159: static ngx_int_t
        !          1160: ngx_http_variable_remote_port(ngx_http_request_t *r,
        !          1161:     ngx_http_variable_value_t *v, uintptr_t data)
        !          1162: {
        !          1163:     ngx_uint_t            port;
        !          1164:     struct sockaddr_in   *sin;
        !          1165: #if (NGX_HAVE_INET6)
        !          1166:     struct sockaddr_in6  *sin6;
        !          1167: #endif
        !          1168: 
        !          1169:     v->len = 0;
        !          1170:     v->valid = 1;
        !          1171:     v->no_cacheable = 0;
        !          1172:     v->not_found = 0;
        !          1173: 
        !          1174:     v->data = ngx_pnalloc(r->pool, sizeof("65535") - 1);
        !          1175:     if (v->data == NULL) {
        !          1176:         return NGX_ERROR;
        !          1177:     }
        !          1178: 
        !          1179:     switch (r->connection->sockaddr->sa_family) {
        !          1180: 
        !          1181: #if (NGX_HAVE_INET6)
        !          1182:     case AF_INET6:
        !          1183:         sin6 = (struct sockaddr_in6 *) r->connection->sockaddr;
        !          1184:         port = ntohs(sin6->sin6_port);
        !          1185:         break;
        !          1186: #endif
        !          1187: 
        !          1188:     default: /* AF_INET */
        !          1189:         sin = (struct sockaddr_in *) r->connection->sockaddr;
        !          1190:         port = ntohs(sin->sin_port);
        !          1191:         break;
        !          1192:     }
        !          1193: 
        !          1194:     if (port > 0 && port < 65536) {
        !          1195:         v->len = ngx_sprintf(v->data, "%ui", port) - v->data;
        !          1196:     }
        !          1197: 
        !          1198:     return NGX_OK;
        !          1199: }
        !          1200: 
        !          1201: 
        !          1202: static ngx_int_t
        !          1203: ngx_http_variable_server_addr(ngx_http_request_t *r,
        !          1204:     ngx_http_variable_value_t *v, uintptr_t data)
        !          1205: {
        !          1206:     ngx_str_t  s;
        !          1207:     u_char     addr[NGX_SOCKADDR_STRLEN];
        !          1208: 
        !          1209:     s.len = NGX_SOCKADDR_STRLEN;
        !          1210:     s.data = addr;
        !          1211: 
        !          1212:     if (ngx_connection_local_sockaddr(r->connection, &s, 0) != NGX_OK) {
        !          1213:         return NGX_ERROR;
        !          1214:     }
        !          1215: 
        !          1216:     s.data = ngx_pnalloc(r->pool, s.len);
        !          1217:     if (s.data == NULL) {
        !          1218:         return NGX_ERROR;
        !          1219:     }
        !          1220: 
        !          1221:     ngx_memcpy(s.data, addr, s.len);
        !          1222: 
        !          1223:     v->len = s.len;
        !          1224:     v->valid = 1;
        !          1225:     v->no_cacheable = 0;
        !          1226:     v->not_found = 0;
        !          1227:     v->data = s.data;
        !          1228: 
        !          1229:     return NGX_OK;
        !          1230: }
        !          1231: 
        !          1232: 
        !          1233: static ngx_int_t
        !          1234: ngx_http_variable_server_port(ngx_http_request_t *r,
        !          1235:     ngx_http_variable_value_t *v, uintptr_t data)
        !          1236: {
        !          1237:     ngx_uint_t            port;
        !          1238:     struct sockaddr_in   *sin;
        !          1239: #if (NGX_HAVE_INET6)
        !          1240:     struct sockaddr_in6  *sin6;
        !          1241: #endif
        !          1242: 
        !          1243:     v->len = 0;
        !          1244:     v->valid = 1;
        !          1245:     v->no_cacheable = 0;
        !          1246:     v->not_found = 0;
        !          1247: 
        !          1248:     if (ngx_connection_local_sockaddr(r->connection, NULL, 0) != NGX_OK) {
        !          1249:         return NGX_ERROR;
        !          1250:     }
        !          1251: 
        !          1252:     v->data = ngx_pnalloc(r->pool, sizeof("65535") - 1);
        !          1253:     if (v->data == NULL) {
        !          1254:         return NGX_ERROR;
        !          1255:     }
        !          1256: 
        !          1257:     switch (r->connection->local_sockaddr->sa_family) {
        !          1258: 
        !          1259: #if (NGX_HAVE_INET6)
        !          1260:     case AF_INET6:
        !          1261:         sin6 = (struct sockaddr_in6 *) r->connection->local_sockaddr;
        !          1262:         port = ntohs(sin6->sin6_port);
        !          1263:         break;
        !          1264: #endif
        !          1265: 
        !          1266:     default: /* AF_INET */
        !          1267:         sin = (struct sockaddr_in *) r->connection->local_sockaddr;
        !          1268:         port = ntohs(sin->sin_port);
        !          1269:         break;
        !          1270:     }
        !          1271: 
        !          1272:     if (port > 0 && port < 65536) {
        !          1273:         v->len = ngx_sprintf(v->data, "%ui", port) - v->data;
        !          1274:     }
        !          1275: 
        !          1276:     return NGX_OK;
        !          1277: }
        !          1278: 
        !          1279: 
        !          1280: static ngx_int_t
        !          1281: ngx_http_variable_scheme(ngx_http_request_t *r,
        !          1282:     ngx_http_variable_value_t *v, uintptr_t data)
        !          1283: {
        !          1284: #if (NGX_HTTP_SSL)
        !          1285: 
        !          1286:     if (r->connection->ssl) {
        !          1287:         v->len = sizeof("https") - 1;
        !          1288:         v->valid = 1;
        !          1289:         v->no_cacheable = 0;
        !          1290:         v->not_found = 0;
        !          1291:         v->data = (u_char *) "https";
        !          1292: 
        !          1293:         return NGX_OK;
        !          1294:     }
        !          1295: 
        !          1296: #endif
        !          1297: 
        !          1298:     v->len = sizeof("http") - 1;
        !          1299:     v->valid = 1;
        !          1300:     v->no_cacheable = 0;
        !          1301:     v->not_found = 0;
        !          1302:     v->data = (u_char *) "http";
        !          1303: 
        !          1304:     return NGX_OK;
        !          1305: }
        !          1306: 
        !          1307: 
        !          1308: static ngx_int_t
        !          1309: ngx_http_variable_https(ngx_http_request_t *r,
        !          1310:     ngx_http_variable_value_t *v, uintptr_t data)
        !          1311: {
        !          1312: #if (NGX_HTTP_SSL)
        !          1313: 
        !          1314:     if (r->connection->ssl) {
        !          1315:         v->len = sizeof("on") - 1;
        !          1316:         v->valid = 1;
        !          1317:         v->no_cacheable = 0;
        !          1318:         v->not_found = 0;
        !          1319:         v->data = (u_char *) "on";
        !          1320: 
        !          1321:         return NGX_OK;
        !          1322:     }
        !          1323: 
        !          1324: #endif
        !          1325: 
        !          1326:     *v = ngx_http_variable_null_value;
        !          1327: 
        !          1328:     return NGX_OK;
        !          1329: }
        !          1330: 
        !          1331: 
        !          1332: static ngx_int_t
        !          1333: ngx_http_variable_is_args(ngx_http_request_t *r,
        !          1334:     ngx_http_variable_value_t *v, uintptr_t data)
        !          1335: {
        !          1336:     v->valid = 1;
        !          1337:     v->no_cacheable = 0;
        !          1338:     v->not_found = 0;
        !          1339: 
        !          1340:     if (r->args.len == 0) {
        !          1341:         v->len = 0;
        !          1342:         v->data = NULL;
        !          1343:         return NGX_OK;
        !          1344:     }
        !          1345: 
        !          1346:     v->len = 1;
        !          1347:     v->data = (u_char *) "?";
        !          1348: 
        !          1349:     return NGX_OK;
        !          1350: }
        !          1351: 
        !          1352: 
        !          1353: static ngx_int_t
        !          1354: ngx_http_variable_document_root(ngx_http_request_t *r,
        !          1355:     ngx_http_variable_value_t *v, uintptr_t data)
        !          1356: {
        !          1357:     ngx_str_t                  path;
        !          1358:     ngx_http_core_loc_conf_t  *clcf;
        !          1359: 
        !          1360:     clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
        !          1361: 
        !          1362:     if (clcf->root_lengths == NULL) {
        !          1363:         v->len = clcf->root.len;
        !          1364:         v->valid = 1;
        !          1365:         v->no_cacheable = 0;
        !          1366:         v->not_found = 0;
        !          1367:         v->data = clcf->root.data;
        !          1368: 
        !          1369:     } else {
        !          1370:         if (ngx_http_script_run(r, &path, clcf->root_lengths->elts, 0,
        !          1371:                                 clcf->root_values->elts)
        !          1372:             == NULL)
        !          1373:         {
        !          1374:             return NGX_ERROR;
        !          1375:         }
        !          1376: 
        !          1377:         if (ngx_conf_full_name((ngx_cycle_t *) ngx_cycle, &path, 0) != NGX_OK) {
        !          1378:             return NGX_ERROR;
        !          1379:         }
        !          1380: 
        !          1381:         v->len = path.len;
        !          1382:         v->valid = 1;
        !          1383:         v->no_cacheable = 0;
        !          1384:         v->not_found = 0;
        !          1385:         v->data = path.data;
        !          1386:     }
        !          1387: 
        !          1388:     return NGX_OK;
        !          1389: }
        !          1390: 
        !          1391: 
        !          1392: static ngx_int_t
        !          1393: ngx_http_variable_realpath_root(ngx_http_request_t *r,
        !          1394:     ngx_http_variable_value_t *v, uintptr_t data)
        !          1395: {
        !          1396:     u_char                    *real;
        !          1397:     size_t                     len;
        !          1398:     ngx_str_t                  path;
        !          1399:     ngx_http_core_loc_conf_t  *clcf;
        !          1400: #if (NGX_HAVE_MAX_PATH)
        !          1401:     u_char                     buffer[NGX_MAX_PATH];
        !          1402: #endif
        !          1403: 
        !          1404:     clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
        !          1405: 
        !          1406:     if (clcf->root_lengths == NULL) {
        !          1407:         path = clcf->root;
        !          1408: 
        !          1409:     } else {
        !          1410:         if (ngx_http_script_run(r, &path, clcf->root_lengths->elts, 1,
        !          1411:                                 clcf->root_values->elts)
        !          1412:             == NULL)
        !          1413:         {
        !          1414:             return NGX_ERROR;
        !          1415:         }
        !          1416: 
        !          1417:         path.data[path.len - 1] = '\0';
        !          1418: 
        !          1419:         if (ngx_conf_full_name((ngx_cycle_t *) ngx_cycle, &path, 0) != NGX_OK) {
        !          1420:             return NGX_ERROR;
        !          1421:         }
        !          1422:     }
        !          1423: 
        !          1424: #if (NGX_HAVE_MAX_PATH)
        !          1425:     real = buffer;
        !          1426: #else
        !          1427:     real = NULL;
        !          1428: #endif
        !          1429: 
        !          1430:     real = ngx_realpath(path.data, real);
        !          1431: 
        !          1432:     if (real == NULL) {
        !          1433:         ngx_log_error(NGX_LOG_CRIT, r->connection->log, ngx_errno,
        !          1434:                       ngx_realpath_n " \"%s\" failed", path.data);
        !          1435:         return NGX_ERROR;
        !          1436:     }
        !          1437: 
        !          1438:     len = ngx_strlen(real);
        !          1439: 
        !          1440:     v->data = ngx_pnalloc(r->pool, len);
        !          1441:     if (v->data == NULL) {
        !          1442: #if !(NGX_HAVE_MAX_PATH)
        !          1443:         ngx_free(real);
        !          1444: #endif
        !          1445:         return NGX_ERROR;
        !          1446:     }
        !          1447: 
        !          1448:     v->len = len;
        !          1449:     v->valid = 1;
        !          1450:     v->no_cacheable = 0;
        !          1451:     v->not_found = 0;
        !          1452: 
        !          1453:     ngx_memcpy(v->data, real, len);
        !          1454: 
        !          1455: #if !(NGX_HAVE_MAX_PATH)
        !          1456:     ngx_free(real);
        !          1457: #endif
        !          1458: 
        !          1459:     return NGX_OK;
        !          1460: }
        !          1461: 
        !          1462: 
        !          1463: static ngx_int_t
        !          1464: ngx_http_variable_request_filename(ngx_http_request_t *r,
        !          1465:     ngx_http_variable_value_t *v, uintptr_t data)
        !          1466: {
        !          1467:     size_t     root;
        !          1468:     ngx_str_t  path;
        !          1469: 
        !          1470:     if (ngx_http_map_uri_to_path(r, &path, &root, 0) == NULL) {
        !          1471:         return NGX_ERROR;
        !          1472:     }
        !          1473: 
        !          1474:     /* ngx_http_map_uri_to_path() allocates memory for terminating '\0' */
        !          1475: 
        !          1476:     v->len = path.len - 1;
        !          1477:     v->valid = 1;
        !          1478:     v->no_cacheable = 0;
        !          1479:     v->not_found = 0;
        !          1480:     v->data = path.data;
        !          1481: 
        !          1482:     return NGX_OK;
        !          1483: }
        !          1484: 
        !          1485: 
        !          1486: static ngx_int_t
        !          1487: ngx_http_variable_server_name(ngx_http_request_t *r,
        !          1488:     ngx_http_variable_value_t *v, uintptr_t data)
        !          1489: {
        !          1490:     ngx_http_core_srv_conf_t  *cscf;
        !          1491: 
        !          1492:     cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
        !          1493: 
        !          1494:     v->len = cscf->server_name.len;
        !          1495:     v->valid = 1;
        !          1496:     v->no_cacheable = 0;
        !          1497:     v->not_found = 0;
        !          1498:     v->data = cscf->server_name.data;
        !          1499: 
        !          1500:     return NGX_OK;
        !          1501: }
        !          1502: 
        !          1503: 
        !          1504: static ngx_int_t
        !          1505: ngx_http_variable_request_method(ngx_http_request_t *r,
        !          1506:     ngx_http_variable_value_t *v, uintptr_t data)
        !          1507: {
        !          1508:     if (r->main->method_name.data) {
        !          1509:         v->len = r->main->method_name.len;
        !          1510:         v->valid = 1;
        !          1511:         v->no_cacheable = 0;
        !          1512:         v->not_found = 0;
        !          1513:         v->data = r->main->method_name.data;
        !          1514: 
        !          1515:     } else {
        !          1516:         v->not_found = 1;
        !          1517:     }
        !          1518: 
        !          1519:     return NGX_OK;
        !          1520: }
        !          1521: 
        !          1522: 
        !          1523: static ngx_int_t
        !          1524: ngx_http_variable_remote_user(ngx_http_request_t *r,
        !          1525:     ngx_http_variable_value_t *v, uintptr_t data)
        !          1526: {
        !          1527:     ngx_int_t  rc;
        !          1528: 
        !          1529:     rc = ngx_http_auth_basic_user(r);
        !          1530: 
        !          1531:     if (rc == NGX_DECLINED) {
        !          1532:         v->not_found = 1;
        !          1533:         return NGX_OK;
        !          1534:     }
        !          1535: 
        !          1536:     if (rc == NGX_ERROR) {
        !          1537:         return NGX_ERROR;
        !          1538:     }
        !          1539: 
        !          1540:     v->len = r->headers_in.user.len;
        !          1541:     v->valid = 1;
        !          1542:     v->no_cacheable = 0;
        !          1543:     v->not_found = 0;
        !          1544:     v->data = r->headers_in.user.data;
        !          1545: 
        !          1546:     return NGX_OK;
        !          1547: }
        !          1548: 
        !          1549: 
        !          1550: static ngx_int_t
        !          1551: ngx_http_variable_bytes_sent(ngx_http_request_t *r,
        !          1552:     ngx_http_variable_value_t *v, uintptr_t data)
        !          1553: {
        !          1554:     u_char  *p;
        !          1555: 
        !          1556:     p = ngx_pnalloc(r->pool, NGX_OFF_T_LEN);
        !          1557:     if (p == NULL) {
        !          1558:         return NGX_ERROR;
        !          1559:     }
        !          1560: 
        !          1561:     v->len = ngx_sprintf(p, "%O", r->connection->sent) - p;
        !          1562:     v->valid = 1;
        !          1563:     v->no_cacheable = 0;
        !          1564:     v->not_found = 0;
        !          1565:     v->data = p;
        !          1566: 
        !          1567:     return NGX_OK;
        !          1568: }
        !          1569: 
        !          1570: 
        !          1571: static ngx_int_t
        !          1572: ngx_http_variable_body_bytes_sent(ngx_http_request_t *r,
        !          1573:     ngx_http_variable_value_t *v, uintptr_t data)
        !          1574: {
        !          1575:     off_t    sent;
        !          1576:     u_char  *p;
        !          1577: 
        !          1578:     sent = r->connection->sent - r->header_size;
        !          1579: 
        !          1580:     if (sent < 0) {
        !          1581:         sent = 0;
        !          1582:     }
        !          1583: 
        !          1584:     p = ngx_pnalloc(r->pool, NGX_OFF_T_LEN);
        !          1585:     if (p == NULL) {
        !          1586:         return NGX_ERROR;
        !          1587:     }
        !          1588: 
        !          1589:     v->len = ngx_sprintf(p, "%O", sent) - p;
        !          1590:     v->valid = 1;
        !          1591:     v->no_cacheable = 0;
        !          1592:     v->not_found = 0;
        !          1593:     v->data = p;
        !          1594: 
        !          1595:     return NGX_OK;
        !          1596: }
        !          1597: 
        !          1598: 
        !          1599: static ngx_int_t
        !          1600: ngx_http_variable_pipe(ngx_http_request_t *r,
        !          1601:     ngx_http_variable_value_t *v, uintptr_t data)
        !          1602: {
        !          1603:     v->data = (u_char *) (r->pipeline ? "p" : ".");
        !          1604:     v->len = 1;
        !          1605:     v->valid = 1;
        !          1606:     v->no_cacheable = 0;
        !          1607:     v->not_found = 0;
        !          1608: 
        !          1609:     return NGX_OK;
        !          1610: }
        !          1611: 
        !          1612: 
        !          1613: static ngx_int_t
        !          1614: ngx_http_variable_status(ngx_http_request_t *r,
        !          1615:     ngx_http_variable_value_t *v, uintptr_t data)
        !          1616: {
        !          1617:     ngx_uint_t  status;
        !          1618: 
        !          1619:     v->data = ngx_pnalloc(r->pool, NGX_INT_T_LEN);
        !          1620:     if (v->data == NULL) {
        !          1621:         return NGX_ERROR;
        !          1622:     }
        !          1623: 
        !          1624:     if (r->err_status) {
        !          1625:         status = r->err_status;
        !          1626: 
        !          1627:     } else if (r->headers_out.status) {
        !          1628:         status = r->headers_out.status;
        !          1629: 
        !          1630:     } else if (r->http_version == NGX_HTTP_VERSION_9) {
        !          1631:         status = 9;
        !          1632: 
        !          1633:     } else {
        !          1634:         status = 0;
        !          1635:     }
        !          1636: 
        !          1637:     v->len = ngx_sprintf(v->data, "%03ui", status) - v->data;
        !          1638:     v->valid = 1;
        !          1639:     v->no_cacheable = 0;
        !          1640:     v->not_found = 0;
        !          1641: 
        !          1642:     return NGX_OK;
        !          1643: }
        !          1644: 
        !          1645: 
        !          1646: static ngx_int_t
        !          1647: ngx_http_variable_sent_content_type(ngx_http_request_t *r,
        !          1648:     ngx_http_variable_value_t *v, uintptr_t data)
        !          1649: {
        !          1650:     if (r->headers_out.content_type.len) {
        !          1651:         v->len = r->headers_out.content_type.len;
        !          1652:         v->valid = 1;
        !          1653:         v->no_cacheable = 0;
        !          1654:         v->not_found = 0;
        !          1655:         v->data = r->headers_out.content_type.data;
        !          1656: 
        !          1657:     } else {
        !          1658:         v->not_found = 1;
        !          1659:     }
        !          1660: 
        !          1661:     return NGX_OK;
        !          1662: }
        !          1663: 
        !          1664: 
        !          1665: static ngx_int_t
        !          1666: ngx_http_variable_sent_content_length(ngx_http_request_t *r,
        !          1667:     ngx_http_variable_value_t *v, uintptr_t data)
        !          1668: {
        !          1669:     u_char  *p;
        !          1670: 
        !          1671:     if (r->headers_out.content_length) {
        !          1672:         v->len = r->headers_out.content_length->value.len;
        !          1673:         v->valid = 1;
        !          1674:         v->no_cacheable = 0;
        !          1675:         v->not_found = 0;
        !          1676:         v->data = r->headers_out.content_length->value.data;
        !          1677: 
        !          1678:         return NGX_OK;
        !          1679:     }
        !          1680: 
        !          1681:     if (r->headers_out.content_length_n >= 0) {
        !          1682:         p = ngx_pnalloc(r->pool, NGX_OFF_T_LEN);
        !          1683:         if (p == NULL) {
        !          1684:             return NGX_ERROR;
        !          1685:         }
        !          1686: 
        !          1687:         v->len = ngx_sprintf(p, "%O", r->headers_out.content_length_n) - p;
        !          1688:         v->valid = 1;
        !          1689:         v->no_cacheable = 0;
        !          1690:         v->not_found = 0;
        !          1691:         v->data = p;
        !          1692: 
        !          1693:         return NGX_OK;
        !          1694:     }
        !          1695: 
        !          1696:     v->not_found = 1;
        !          1697: 
        !          1698:     return NGX_OK;
        !          1699: }
        !          1700: 
        !          1701: 
        !          1702: static ngx_int_t
        !          1703: ngx_http_variable_sent_location(ngx_http_request_t *r,
        !          1704:     ngx_http_variable_value_t *v, uintptr_t data)
        !          1705: {
        !          1706:     ngx_str_t  name;
        !          1707: 
        !          1708:     if (r->headers_out.location) {
        !          1709:         v->len = r->headers_out.location->value.len;
        !          1710:         v->valid = 1;
        !          1711:         v->no_cacheable = 0;
        !          1712:         v->not_found = 0;
        !          1713:         v->data = r->headers_out.location->value.data;
        !          1714: 
        !          1715:         return NGX_OK;
        !          1716:     }
        !          1717: 
        !          1718:     ngx_str_set(&name, "sent_http_location");
        !          1719: 
        !          1720:     return ngx_http_variable_unknown_header(v, &name,
        !          1721:                                             &r->headers_out.headers.part,
        !          1722:                                             sizeof("sent_http_") - 1);
        !          1723: }
        !          1724: 
        !          1725: 
        !          1726: static ngx_int_t
        !          1727: ngx_http_variable_sent_last_modified(ngx_http_request_t *r,
        !          1728:     ngx_http_variable_value_t *v, uintptr_t data)
        !          1729: {
        !          1730:     u_char  *p;
        !          1731: 
        !          1732:     if (r->headers_out.last_modified) {
        !          1733:         v->len = r->headers_out.last_modified->value.len;
        !          1734:         v->valid = 1;
        !          1735:         v->no_cacheable = 0;
        !          1736:         v->not_found = 0;
        !          1737:         v->data = r->headers_out.last_modified->value.data;
        !          1738: 
        !          1739:         return NGX_OK;
        !          1740:     }
        !          1741: 
        !          1742:     if (r->headers_out.last_modified_time >= 0) {
        !          1743:         p = ngx_pnalloc(r->pool,
        !          1744:                    sizeof("Last-Modified: Mon, 28 Sep 1970 06:00:00 GMT") - 1);
        !          1745:         if (p == NULL) {
        !          1746:             return NGX_ERROR;
        !          1747:         }
        !          1748: 
        !          1749:         v->len = ngx_http_time(p, r->headers_out.last_modified_time) - p;
        !          1750:         v->valid = 1;
        !          1751:         v->no_cacheable = 0;
        !          1752:         v->not_found = 0;
        !          1753:         v->data = p;
        !          1754: 
        !          1755:         return NGX_OK;
        !          1756:     }
        !          1757: 
        !          1758:     v->not_found = 1;
        !          1759: 
        !          1760:     return NGX_OK;
        !          1761: }
        !          1762: 
        !          1763: 
        !          1764: static ngx_int_t
        !          1765: ngx_http_variable_sent_connection(ngx_http_request_t *r,
        !          1766:     ngx_http_variable_value_t *v, uintptr_t data)
        !          1767: {
        !          1768:     size_t   len;
        !          1769:     char    *p;
        !          1770: 
        !          1771:     if (r->headers_out.status == NGX_HTTP_SWITCHING_PROTOCOLS) {
        !          1772:         len = sizeof("upgrade") - 1;
        !          1773:         p = "upgrade";
        !          1774: 
        !          1775:     } else if (r->keepalive) {
        !          1776:         len = sizeof("keep-alive") - 1;
        !          1777:         p = "keep-alive";
        !          1778: 
        !          1779:     } else {
        !          1780:         len = sizeof("close") - 1;
        !          1781:         p = "close";
        !          1782:     }
        !          1783: 
        !          1784:     v->len = len;
        !          1785:     v->valid = 1;
        !          1786:     v->no_cacheable = 0;
        !          1787:     v->not_found = 0;
        !          1788:     v->data = (u_char *) p;
        !          1789: 
        !          1790:     return NGX_OK;
        !          1791: }
        !          1792: 
        !          1793: 
        !          1794: static ngx_int_t
        !          1795: ngx_http_variable_sent_keep_alive(ngx_http_request_t *r,
        !          1796:     ngx_http_variable_value_t *v, uintptr_t data)
        !          1797: {
        !          1798:     u_char                    *p;
        !          1799:     ngx_http_core_loc_conf_t  *clcf;
        !          1800: 
        !          1801:     if (r->keepalive) {
        !          1802:         clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
        !          1803: 
        !          1804:         if (clcf->keepalive_header) {
        !          1805: 
        !          1806:             p = ngx_pnalloc(r->pool, sizeof("timeout=") - 1 + NGX_TIME_T_LEN);
        !          1807:             if (p == NULL) {
        !          1808:                 return NGX_ERROR;
        !          1809:             }
        !          1810: 
        !          1811:             v->len = ngx_sprintf(p, "timeout=%T", clcf->keepalive_header) - p;
        !          1812:             v->valid = 1;
        !          1813:             v->no_cacheable = 0;
        !          1814:             v->not_found = 0;
        !          1815:             v->data = p;
        !          1816: 
        !          1817:             return NGX_OK;
        !          1818:         }
        !          1819:     }
        !          1820: 
        !          1821:     v->not_found = 1;
        !          1822: 
        !          1823:     return NGX_OK;
        !          1824: }
        !          1825: 
        !          1826: 
        !          1827: static ngx_int_t
        !          1828: ngx_http_variable_sent_transfer_encoding(ngx_http_request_t *r,
        !          1829:     ngx_http_variable_value_t *v, uintptr_t data)
        !          1830: {
        !          1831:     if (r->chunked) {
        !          1832:         v->len = sizeof("chunked") - 1;
        !          1833:         v->valid = 1;
        !          1834:         v->no_cacheable = 0;
        !          1835:         v->not_found = 0;
        !          1836:         v->data = (u_char *) "chunked";
        !          1837: 
        !          1838:     } else {
        !          1839:         v->not_found = 1;
        !          1840:     }
        !          1841: 
        !          1842:     return NGX_OK;
        !          1843: }
        !          1844: 
        !          1845: 
        !          1846: static ngx_int_t
        !          1847: ngx_http_variable_request_completion(ngx_http_request_t *r,
        !          1848:     ngx_http_variable_value_t *v, uintptr_t data)
        !          1849: {
        !          1850:     if (r->request_complete) {
        !          1851:         v->len = 2;
        !          1852:         v->valid = 1;
        !          1853:         v->no_cacheable = 0;
        !          1854:         v->not_found = 0;
        !          1855:         v->data = (u_char *) "OK";
        !          1856: 
        !          1857:         return NGX_OK;
        !          1858:     }
        !          1859: 
        !          1860:     v->len = 0;
        !          1861:     v->valid = 1;
        !          1862:     v->no_cacheable = 0;
        !          1863:     v->not_found = 0;
        !          1864:     v->data = (u_char *) "";
        !          1865: 
        !          1866:     return NGX_OK;
        !          1867: }
        !          1868: 
        !          1869: 
        !          1870: static ngx_int_t
        !          1871: ngx_http_variable_request_body(ngx_http_request_t *r,
        !          1872:     ngx_http_variable_value_t *v, uintptr_t data)
        !          1873: {
        !          1874:     u_char       *p;
        !          1875:     size_t        len;
        !          1876:     ngx_buf_t    *buf;
        !          1877:     ngx_chain_t  *cl;
        !          1878: 
        !          1879:     if (r->request_body == NULL
        !          1880:         || r->request_body->bufs == NULL
        !          1881:         || r->request_body->temp_file)
        !          1882:     {
        !          1883:         v->not_found = 1;
        !          1884: 
        !          1885:         return NGX_OK;
        !          1886:     }
        !          1887: 
        !          1888:     cl = r->request_body->bufs;
        !          1889:     buf = cl->buf;
        !          1890: 
        !          1891:     if (cl->next == NULL) {
        !          1892:         v->len = buf->last - buf->pos;
        !          1893:         v->valid = 1;
        !          1894:         v->no_cacheable = 0;
        !          1895:         v->not_found = 0;
        !          1896:         v->data = buf->pos;
        !          1897: 
        !          1898:         return NGX_OK;
        !          1899:     }
        !          1900: 
        !          1901:     len = buf->last - buf->pos;
        !          1902:     cl = cl->next;
        !          1903: 
        !          1904:     for ( /* void */ ; cl; cl = cl->next) {
        !          1905:         buf = cl->buf;
        !          1906:         len += buf->last - buf->pos;
        !          1907:     }
        !          1908: 
        !          1909:     p = ngx_pnalloc(r->pool, len);
        !          1910:     if (p == NULL) {
        !          1911:         return NGX_ERROR;
        !          1912:     }
        !          1913: 
        !          1914:     v->data = p;
        !          1915:     cl = r->request_body->bufs;
        !          1916: 
        !          1917:     for ( /* void */ ; cl; cl = cl->next) {
        !          1918:         buf = cl->buf;
        !          1919:         p = ngx_cpymem(p, buf->pos, buf->last - buf->pos);
        !          1920:     }
        !          1921: 
        !          1922:     v->len = len;
        !          1923:     v->valid = 1;
        !          1924:     v->no_cacheable = 0;
        !          1925:     v->not_found = 0;
        !          1926: 
        !          1927:     return NGX_OK;
        !          1928: }
        !          1929: 
        !          1930: 
        !          1931: static ngx_int_t
        !          1932: ngx_http_variable_request_body_file(ngx_http_request_t *r,
        !          1933:     ngx_http_variable_value_t *v, uintptr_t data)
        !          1934: {
        !          1935:     if (r->request_body == NULL || r->request_body->temp_file == NULL) {
        !          1936:         v->not_found = 1;
        !          1937: 
        !          1938:         return NGX_OK;
        !          1939:     }
        !          1940: 
        !          1941:     v->len = r->request_body->temp_file->file.name.len;
        !          1942:     v->valid = 1;
        !          1943:     v->no_cacheable = 0;
        !          1944:     v->not_found = 0;
        !          1945:     v->data = r->request_body->temp_file->file.name.data;
        !          1946: 
        !          1947:     return NGX_OK;
        !          1948: }
        !          1949: 
        !          1950: 
        !          1951: static ngx_int_t
        !          1952: ngx_http_variable_request_length(ngx_http_request_t *r,
        !          1953:     ngx_http_variable_value_t *v, uintptr_t data)
        !          1954: {
        !          1955:     u_char  *p;
        !          1956: 
        !          1957:     p = ngx_pnalloc(r->pool, NGX_OFF_T_LEN);
        !          1958:     if (p == NULL) {
        !          1959:         return NGX_ERROR;
        !          1960:     }
        !          1961: 
        !          1962:     v->len = ngx_sprintf(p, "%O", r->request_length) - p;
        !          1963:     v->valid = 1;
        !          1964:     v->no_cacheable = 0;
        !          1965:     v->not_found = 0;
        !          1966:     v->data = p;
        !          1967: 
        !          1968:     return NGX_OK;
        !          1969: }
        !          1970: 
        !          1971: 
        !          1972: static ngx_int_t
        !          1973: ngx_http_variable_request_time(ngx_http_request_t *r,
        !          1974:     ngx_http_variable_value_t *v, uintptr_t data)
        !          1975: {
        !          1976:     u_char          *p;
        !          1977:     ngx_time_t      *tp;
        !          1978:     ngx_msec_int_t   ms;
        !          1979: 
        !          1980:     p = ngx_pnalloc(r->pool, NGX_TIME_T_LEN + 4);
        !          1981:     if (p == NULL) {
        !          1982:         return NGX_ERROR;
        !          1983:     }
        !          1984: 
        !          1985:     tp = ngx_timeofday();
        !          1986: 
        !          1987:     ms = (ngx_msec_int_t)
        !          1988:              ((tp->sec - r->start_sec) * 1000 + (tp->msec - r->start_msec));
        !          1989:     ms = ngx_max(ms, 0);
        !          1990: 
        !          1991:     v->len = ngx_sprintf(p, "%T.%03M", (time_t) ms / 1000, ms % 1000) - p;
        !          1992:     v->valid = 1;
        !          1993:     v->no_cacheable = 0;
        !          1994:     v->not_found = 0;
        !          1995:     v->data = p;
        !          1996: 
        !          1997:     return NGX_OK;
        !          1998: }
        !          1999: 
        !          2000: 
        !          2001: static ngx_int_t
        !          2002: ngx_http_variable_connection(ngx_http_request_t *r,
        !          2003:     ngx_http_variable_value_t *v, uintptr_t data)
        !          2004: {
        !          2005:     u_char  *p;
        !          2006: 
        !          2007:     p = ngx_pnalloc(r->pool, NGX_ATOMIC_T_LEN);
        !          2008:     if (p == NULL) {
        !          2009:         return NGX_ERROR;
        !          2010:     }
        !          2011: 
        !          2012:     v->len = ngx_sprintf(p, "%uA", r->connection->number) - p;
        !          2013:     v->valid = 1;
        !          2014:     v->no_cacheable = 0;
        !          2015:     v->not_found = 0;
        !          2016:     v->data = p;
        !          2017: 
        !          2018:     return NGX_OK;
        !          2019: }
        !          2020: 
        !          2021: 
        !          2022: static ngx_int_t
        !          2023: ngx_http_variable_connection_requests(ngx_http_request_t *r,
        !          2024:     ngx_http_variable_value_t *v, uintptr_t data)
        !          2025: {
        !          2026:     u_char  *p;
        !          2027: 
        !          2028:     p = ngx_pnalloc(r->pool, NGX_INT_T_LEN);
        !          2029:     if (p == NULL) {
        !          2030:         return NGX_ERROR;
        !          2031:     }
        !          2032: 
        !          2033:     v->len = ngx_sprintf(p, "%ui", r->connection->requests) - p;
        !          2034:     v->valid = 1;
        !          2035:     v->no_cacheable = 0;
        !          2036:     v->not_found = 0;
        !          2037:     v->data = p;
        !          2038: 
        !          2039:     return NGX_OK;
        !          2040: }
        !          2041: 
        !          2042: 
        !          2043: static ngx_int_t
        !          2044: ngx_http_variable_nginx_version(ngx_http_request_t *r,
        !          2045:     ngx_http_variable_value_t *v, uintptr_t data)
        !          2046: {
        !          2047:     v->len = sizeof(NGINX_VERSION) - 1;
        !          2048:     v->valid = 1;
        !          2049:     v->no_cacheable = 0;
        !          2050:     v->not_found = 0;
        !          2051:     v->data = (u_char *) NGINX_VERSION;
        !          2052: 
        !          2053:     return NGX_OK;
        !          2054: }
        !          2055: 
        !          2056: 
        !          2057: static ngx_int_t
        !          2058: ngx_http_variable_hostname(ngx_http_request_t *r,
        !          2059:     ngx_http_variable_value_t *v, uintptr_t data)
        !          2060: {
        !          2061:     v->len = ngx_cycle->hostname.len;
        !          2062:     v->valid = 1;
        !          2063:     v->no_cacheable = 0;
        !          2064:     v->not_found = 0;
        !          2065:     v->data = ngx_cycle->hostname.data;
        !          2066: 
        !          2067:     return NGX_OK;
        !          2068: }
        !          2069: 
        !          2070: 
        !          2071: static ngx_int_t
        !          2072: ngx_http_variable_pid(ngx_http_request_t *r,
        !          2073:     ngx_http_variable_value_t *v, uintptr_t data)
        !          2074: {
        !          2075:     u_char  *p;
        !          2076: 
        !          2077:     p = ngx_pnalloc(r->pool, NGX_INT64_LEN);
        !          2078:     if (p == NULL) {
        !          2079:         return NGX_ERROR;
        !          2080:     }
        !          2081: 
        !          2082:     v->len = ngx_sprintf(p, "%P", ngx_pid) - p;
        !          2083:     v->valid = 1;
        !          2084:     v->no_cacheable = 0;
        !          2085:     v->not_found = 0;
        !          2086:     v->data = p;
        !          2087: 
        !          2088:     return NGX_OK;
        !          2089: }
        !          2090: 
        !          2091: 
        !          2092: static ngx_int_t
        !          2093: ngx_http_variable_msec(ngx_http_request_t *r,
        !          2094:     ngx_http_variable_value_t *v, uintptr_t data)
        !          2095: {
        !          2096:     u_char      *p;
        !          2097:     ngx_time_t  *tp;
        !          2098: 
        !          2099:     p = ngx_pnalloc(r->pool, NGX_TIME_T_LEN + 4);
        !          2100:     if (p == NULL) {
        !          2101:         return NGX_ERROR;
        !          2102:     }
        !          2103: 
        !          2104:     tp = ngx_timeofday();
        !          2105: 
        !          2106:     v->len = ngx_sprintf(p, "%T.%03M", tp->sec, tp->msec) - p;
        !          2107:     v->valid = 1;
        !          2108:     v->no_cacheable = 0;
        !          2109:     v->not_found = 0;
        !          2110:     v->data = p;
        !          2111: 
        !          2112:     return NGX_OK;
        !          2113: }
        !          2114: 
        !          2115: 
        !          2116: static ngx_int_t
        !          2117: ngx_http_variable_time_iso8601(ngx_http_request_t *r,
        !          2118:     ngx_http_variable_value_t *v, uintptr_t data)
        !          2119: {
        !          2120:     u_char  *p;
        !          2121: 
        !          2122:     p = ngx_pnalloc(r->pool, ngx_cached_http_log_iso8601.len);
        !          2123:     if (p == NULL) {
        !          2124:         return NGX_ERROR;
        !          2125:     }
        !          2126: 
        !          2127:     ngx_memcpy(p, ngx_cached_http_log_iso8601.data,
        !          2128:                ngx_cached_http_log_iso8601.len);
        !          2129: 
        !          2130:     v->len = ngx_cached_http_log_iso8601.len;
        !          2131:     v->valid = 1;
        !          2132:     v->no_cacheable = 0;
        !          2133:     v->not_found = 0;
        !          2134:     v->data = p;
        !          2135: 
        !          2136:     return NGX_OK;
        !          2137: }
        !          2138: 
        !          2139: 
        !          2140: static ngx_int_t
        !          2141: ngx_http_variable_time_local(ngx_http_request_t *r,
        !          2142:     ngx_http_variable_value_t *v, uintptr_t data)
        !          2143: {
        !          2144:     u_char  *p;
        !          2145: 
        !          2146:     p = ngx_pnalloc(r->pool, ngx_cached_http_log_time.len);
        !          2147:     if (p == NULL) {
        !          2148:         return NGX_ERROR;
        !          2149:     }
        !          2150: 
        !          2151:     ngx_memcpy(p, ngx_cached_http_log_time.data, ngx_cached_http_log_time.len);
        !          2152: 
        !          2153:     v->len = ngx_cached_http_log_time.len;
        !          2154:     v->valid = 1;
        !          2155:     v->no_cacheable = 0;
        !          2156:     v->not_found = 0;
        !          2157:     v->data = p;
        !          2158: 
        !          2159:     return NGX_OK;
        !          2160: }
        !          2161: 
        !          2162: 
        !          2163: void *
        !          2164: ngx_http_map_find(ngx_http_request_t *r, ngx_http_map_t *map, ngx_str_t *match)
        !          2165: {
        !          2166:     void        *value;
        !          2167:     u_char      *low;
        !          2168:     size_t       len;
        !          2169:     ngx_uint_t   key;
        !          2170: 
        !          2171:     len = match->len;
        !          2172: 
        !          2173:     if (len) {
        !          2174:         low = ngx_pnalloc(r->pool, len);
        !          2175:         if (low == NULL) {
        !          2176:             return NULL;
        !          2177:         }
        !          2178: 
        !          2179:     } else {
        !          2180:         low = NULL;
        !          2181:     }
        !          2182: 
        !          2183:     key = ngx_hash_strlow(low, match->data, len);
        !          2184: 
        !          2185:     value = ngx_hash_find_combined(&map->hash, key, low, len);
        !          2186:     if (value) {
        !          2187:         return value;
        !          2188:     }
        !          2189: 
        !          2190: #if (NGX_PCRE)
        !          2191: 
        !          2192:     if (len && map->nregex) {
        !          2193:         ngx_int_t              n;
        !          2194:         ngx_uint_t             i;
        !          2195:         ngx_http_map_regex_t  *reg;
        !          2196: 
        !          2197:         reg = map->regex;
        !          2198: 
        !          2199:         for (i = 0; i < map->nregex; i++) {
        !          2200: 
        !          2201:             n = ngx_http_regex_exec(r, reg[i].regex, match);
        !          2202: 
        !          2203:             if (n == NGX_OK) {
        !          2204:                 return reg[i].value;
        !          2205:             }
        !          2206: 
        !          2207:             if (n == NGX_DECLINED) {
        !          2208:                 continue;
        !          2209:             }
        !          2210: 
        !          2211:             /* NGX_ERROR */
        !          2212: 
        !          2213:             return NULL;
        !          2214:         }
        !          2215:     }
        !          2216: 
        !          2217: #endif
        !          2218: 
        !          2219:     return NULL;
        !          2220: }
        !          2221: 
        !          2222: 
        !          2223: #if (NGX_PCRE)
        !          2224: 
        !          2225: static ngx_int_t
        !          2226: ngx_http_variable_not_found(ngx_http_request_t *r, ngx_http_variable_value_t *v,
        !          2227:     uintptr_t data)
        !          2228: {
        !          2229:     v->not_found = 1;
        !          2230:     return NGX_OK;
        !          2231: }
        !          2232: 
        !          2233: 
        !          2234: ngx_http_regex_t *
        !          2235: ngx_http_regex_compile(ngx_conf_t *cf, ngx_regex_compile_t *rc)
        !          2236: {
        !          2237:     u_char                     *p;
        !          2238:     size_t                      size;
        !          2239:     ngx_str_t                   name;
        !          2240:     ngx_uint_t                  i, n;
        !          2241:     ngx_http_variable_t        *v;
        !          2242:     ngx_http_regex_t           *re;
        !          2243:     ngx_http_regex_variable_t  *rv;
        !          2244:     ngx_http_core_main_conf_t  *cmcf;
        !          2245: 
        !          2246:     rc->pool = cf->pool;
        !          2247: 
        !          2248:     if (ngx_regex_compile(rc) != NGX_OK) {
        !          2249:         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "%V", &rc->err);
        !          2250:         return NULL;
        !          2251:     }
        !          2252: 
        !          2253:     re = ngx_pcalloc(cf->pool, sizeof(ngx_http_regex_t));
        !          2254:     if (re == NULL) {
        !          2255:         return NULL;
        !          2256:     }
        !          2257: 
        !          2258:     re->regex = rc->regex;
        !          2259:     re->ncaptures = rc->captures;
        !          2260: 
        !          2261:     cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);
        !          2262:     cmcf->ncaptures = ngx_max(cmcf->ncaptures, re->ncaptures);
        !          2263: 
        !          2264:     n = (ngx_uint_t) rc->named_captures;
        !          2265: 
        !          2266:     if (n == 0) {
        !          2267:         return re;
        !          2268:     }
        !          2269: 
        !          2270:     rv = ngx_palloc(rc->pool, n * sizeof(ngx_http_regex_variable_t));
        !          2271:     if (rv == NULL) {
        !          2272:         return NULL;
        !          2273:     }
        !          2274: 
        !          2275:     re->variables = rv;
        !          2276:     re->nvariables = n;
        !          2277:     re->name = rc->pattern;
        !          2278: 
        !          2279:     size = rc->name_size;
        !          2280:     p = rc->names;
        !          2281: 
        !          2282:     for (i = 0; i < n; i++) {
        !          2283:         rv[i].capture = 2 * ((p[0] << 8) + p[1]);
        !          2284: 
        !          2285:         name.data = &p[2];
        !          2286:         name.len = ngx_strlen(name.data);
        !          2287: 
        !          2288:         v = ngx_http_add_variable(cf, &name, NGX_HTTP_VAR_CHANGEABLE);
        !          2289:         if (v == NULL) {
        !          2290:             return NULL;
        !          2291:         }
        !          2292: 
        !          2293:         rv[i].index = ngx_http_get_variable_index(cf, &name);
        !          2294:         if (rv[i].index == NGX_ERROR) {
        !          2295:             return NULL;
        !          2296:         }
        !          2297: 
        !          2298:         v->get_handler = ngx_http_variable_not_found;
        !          2299: 
        !          2300:         p += size;
        !          2301:     }
        !          2302: 
        !          2303:     return re;
        !          2304: }
        !          2305: 
        !          2306: 
        !          2307: ngx_int_t
        !          2308: ngx_http_regex_exec(ngx_http_request_t *r, ngx_http_regex_t *re, ngx_str_t *s)
        !          2309: {
        !          2310:     ngx_int_t                   rc, index;
        !          2311:     ngx_uint_t                  i, n, len;
        !          2312:     ngx_http_variable_value_t  *vv;
        !          2313:     ngx_http_core_main_conf_t  *cmcf;
        !          2314: 
        !          2315:     cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
        !          2316: 
        !          2317:     if (re->ncaptures) {
        !          2318:         len = cmcf->ncaptures;
        !          2319: 
        !          2320:         if (r->captures == NULL) {
        !          2321:             r->captures = ngx_palloc(r->pool, len * sizeof(int));
        !          2322:             if (r->captures == NULL) {
        !          2323:                 return NGX_ERROR;
        !          2324:             }
        !          2325:         }
        !          2326: 
        !          2327:     } else {
        !          2328:         len = 0;
        !          2329:     }
        !          2330: 
        !          2331:     rc = ngx_regex_exec(re->regex, s, r->captures, len);
        !          2332: 
        !          2333:     if (rc == NGX_REGEX_NO_MATCHED) {
        !          2334:         return NGX_DECLINED;
        !          2335:     }
        !          2336: 
        !          2337:     if (rc < 0) {
        !          2338:         ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
        !          2339:                       ngx_regex_exec_n " failed: %i on \"%V\" using \"%V\"",
        !          2340:                       rc, s, &re->name);
        !          2341:         return NGX_ERROR;
        !          2342:     }
        !          2343: 
        !          2344:     for (i = 0; i < re->nvariables; i++) {
        !          2345: 
        !          2346:         n = re->variables[i].capture;
        !          2347:         index = re->variables[i].index;
        !          2348:         vv = &r->variables[index];
        !          2349: 
        !          2350:         vv->len = r->captures[n + 1] - r->captures[n];
        !          2351:         vv->valid = 1;
        !          2352:         vv->no_cacheable = 0;
        !          2353:         vv->not_found = 0;
        !          2354:         vv->data = &s->data[r->captures[n]];
        !          2355: 
        !          2356: #if (NGX_DEBUG)
        !          2357:         {
        !          2358:         ngx_http_variable_t  *v;
        !          2359: 
        !          2360:         v = cmcf->variables.elts;
        !          2361: 
        !          2362:         ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
        !          2363:                        "http regex set $%V to \"%*s\"",
        !          2364:                        &v[index].name, vv->len, vv->data);
        !          2365:         }
        !          2366: #endif
        !          2367:     }
        !          2368: 
        !          2369:     r->ncaptures = rc * 2;
        !          2370:     r->captures_data = s->data;
        !          2371: 
        !          2372:     return NGX_OK;
        !          2373: }
        !          2374: 
        !          2375: #endif
        !          2376: 
        !          2377: 
        !          2378: ngx_int_t
        !          2379: ngx_http_variables_add_core_vars(ngx_conf_t *cf)
        !          2380: {
        !          2381:     ngx_int_t                   rc;
        !          2382:     ngx_http_variable_t        *cv, *v;
        !          2383:     ngx_http_core_main_conf_t  *cmcf;
        !          2384: 
        !          2385:     cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);
        !          2386: 
        !          2387:     cmcf->variables_keys = ngx_pcalloc(cf->temp_pool,
        !          2388:                                        sizeof(ngx_hash_keys_arrays_t));
        !          2389:     if (cmcf->variables_keys == NULL) {
        !          2390:         return NGX_ERROR;
        !          2391:     }
        !          2392: 
        !          2393:     cmcf->variables_keys->pool = cf->pool;
        !          2394:     cmcf->variables_keys->temp_pool = cf->pool;
        !          2395: 
        !          2396:     if (ngx_hash_keys_array_init(cmcf->variables_keys, NGX_HASH_SMALL)
        !          2397:         != NGX_OK)
        !          2398:     {
        !          2399:         return NGX_ERROR;
        !          2400:     }
        !          2401: 
        !          2402:     for (cv = ngx_http_core_variables; cv->name.len; cv++) {
        !          2403:         v = ngx_palloc(cf->pool, sizeof(ngx_http_variable_t));
        !          2404:         if (v == NULL) {
        !          2405:             return NGX_ERROR;
        !          2406:         }
        !          2407: 
        !          2408:         *v = *cv;
        !          2409: 
        !          2410:         rc = ngx_hash_add_key(cmcf->variables_keys, &v->name, v,
        !          2411:                               NGX_HASH_READONLY_KEY);
        !          2412: 
        !          2413:         if (rc == NGX_OK) {
        !          2414:             continue;
        !          2415:         }
        !          2416: 
        !          2417:         if (rc == NGX_BUSY) {
        !          2418:             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
        !          2419:                                "conflicting variable name \"%V\"", &v->name);
        !          2420:         }
        !          2421: 
        !          2422:         return NGX_ERROR;
        !          2423:     }
        !          2424: 
        !          2425:     return NGX_OK;
        !          2426: }
        !          2427: 
        !          2428: 
        !          2429: ngx_int_t
        !          2430: ngx_http_variables_init_vars(ngx_conf_t *cf)
        !          2431: {
        !          2432:     ngx_uint_t                  i, n;
        !          2433:     ngx_hash_key_t             *key;
        !          2434:     ngx_hash_init_t             hash;
        !          2435:     ngx_http_variable_t        *v, *av;
        !          2436:     ngx_http_core_main_conf_t  *cmcf;
        !          2437: 
        !          2438:     /* set the handlers for the indexed http variables */
        !          2439: 
        !          2440:     cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);
        !          2441: 
        !          2442:     v = cmcf->variables.elts;
        !          2443:     key = cmcf->variables_keys->keys.elts;
        !          2444: 
        !          2445:     for (i = 0; i < cmcf->variables.nelts; i++) {
        !          2446: 
        !          2447:         for (n = 0; n < cmcf->variables_keys->keys.nelts; n++) {
        !          2448: 
        !          2449:             av = key[n].value;
        !          2450: 
        !          2451:             if (av->get_handler
        !          2452:                 && v[i].name.len == key[n].key.len
        !          2453:                 && ngx_strncmp(v[i].name.data, key[n].key.data, v[i].name.len)
        !          2454:                    == 0)
        !          2455:             {
        !          2456:                 v[i].get_handler = av->get_handler;
        !          2457:                 v[i].data = av->data;
        !          2458: 
        !          2459:                 av->flags |= NGX_HTTP_VAR_INDEXED;
        !          2460:                 v[i].flags = av->flags;
        !          2461: 
        !          2462:                 av->index = i;
        !          2463: 
        !          2464:                 goto next;
        !          2465:             }
        !          2466:         }
        !          2467: 
        !          2468:         if (ngx_strncmp(v[i].name.data, "http_", 5) == 0) {
        !          2469:             v[i].get_handler = ngx_http_variable_unknown_header_in;
        !          2470:             v[i].data = (uintptr_t) &v[i].name;
        !          2471: 
        !          2472:             continue;
        !          2473:         }
        !          2474: 
        !          2475:         if (ngx_strncmp(v[i].name.data, "sent_http_", 10) == 0) {
        !          2476:             v[i].get_handler = ngx_http_variable_unknown_header_out;
        !          2477:             v[i].data = (uintptr_t) &v[i].name;
        !          2478: 
        !          2479:             continue;
        !          2480:         }
        !          2481: 
        !          2482:         if (ngx_strncmp(v[i].name.data, "upstream_http_", 14) == 0) {
        !          2483:             v[i].get_handler = ngx_http_upstream_header_variable;
        !          2484:             v[i].data = (uintptr_t) &v[i].name;
        !          2485:             v[i].flags = NGX_HTTP_VAR_NOCACHEABLE;
        !          2486: 
        !          2487:             continue;
        !          2488:         }
        !          2489: 
        !          2490:         if (ngx_strncmp(v[i].name.data, "cookie_", 7) == 0) {
        !          2491:             v[i].get_handler = ngx_http_variable_cookie;
        !          2492:             v[i].data = (uintptr_t) &v[i].name;
        !          2493: 
        !          2494:             continue;
        !          2495:         }
        !          2496: 
        !          2497:         if (ngx_strncmp(v[i].name.data, "arg_", 4) == 0) {
        !          2498:             v[i].get_handler = ngx_http_variable_argument;
        !          2499:             v[i].data = (uintptr_t) &v[i].name;
        !          2500:             v[i].flags = NGX_HTTP_VAR_NOCACHEABLE;
        !          2501: 
        !          2502:             continue;
        !          2503:         }
        !          2504: 
        !          2505:         ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
        !          2506:                       "unknown \"%V\" variable", &v[i].name);
        !          2507: 
        !          2508:         return NGX_ERROR;
        !          2509: 
        !          2510:     next:
        !          2511:         continue;
        !          2512:     }
        !          2513: 
        !          2514: 
        !          2515:     for (n = 0; n < cmcf->variables_keys->keys.nelts; n++) {
        !          2516:         av = key[n].value;
        !          2517: 
        !          2518:         if (av->flags & NGX_HTTP_VAR_NOHASH) {
        !          2519:             key[n].key.data = NULL;
        !          2520:         }
        !          2521:     }
        !          2522: 
        !          2523: 
        !          2524:     hash.hash = &cmcf->variables_hash;
        !          2525:     hash.key = ngx_hash_key;
        !          2526:     hash.max_size = cmcf->variables_hash_max_size;
        !          2527:     hash.bucket_size = cmcf->variables_hash_bucket_size;
        !          2528:     hash.name = "variables_hash";
        !          2529:     hash.pool = cf->pool;
        !          2530:     hash.temp_pool = NULL;
        !          2531: 
        !          2532:     if (ngx_hash_init(&hash, cmcf->variables_keys->keys.elts,
        !          2533:                       cmcf->variables_keys->keys.nelts)
        !          2534:         != NGX_OK)
        !          2535:     {
        !          2536:         return NGX_ERROR;
        !          2537:     }
        !          2538: 
        !          2539:     cmcf->variables_keys = NULL;
        !          2540: 
        !          2541:     return NGX_OK;
        !          2542: }

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