├── .gitattributes ├── .gitignore ├── .travis.yml ├── README.markdown ├── config ├── src ├── ddebug.h ├── ngx_http_set_base32.c ├── ngx_http_set_base32.h ├── ngx_http_set_base64.c ├── ngx_http_set_base64.h ├── ngx_http_set_base64url.c ├── ngx_http_set_base64url.h ├── ngx_http_set_default_value.c ├── ngx_http_set_default_value.h ├── ngx_http_set_escape_uri.c ├── ngx_http_set_escape_uri.h ├── ngx_http_set_hash.c ├── ngx_http_set_hash.h ├── ngx_http_set_hashed_upstream.c ├── ngx_http_set_hashed_upstream.h ├── ngx_http_set_hex.c ├── ngx_http_set_hex.h ├── ngx_http_set_hmac.c ├── ngx_http_set_hmac.h ├── ngx_http_set_local_today.c ├── ngx_http_set_local_today.h ├── ngx_http_set_misc_module.c ├── ngx_http_set_misc_module.h ├── ngx_http_set_quote_json.c ├── ngx_http_set_quote_json.h ├── ngx_http_set_quote_sql.c ├── ngx_http_set_quote_sql.h ├── ngx_http_set_random.c ├── ngx_http_set_random.h ├── ngx_http_set_rotate.c ├── ngx_http_set_rotate.h ├── ngx_http_set_secure_random.c ├── ngx_http_set_secure_random.h ├── ngx_http_set_unescape_uri.c └── ngx_http_set_unescape_uri.h ├── t ├── base32.t ├── base32_no_padding.t ├── base64.t ├── base64url.t ├── default-value.t ├── escape-uri.t ├── formatted-time.t ├── hash.t ├── hashed-upstream.t ├── hex.t ├── hmac.t ├── local-today.t ├── quote-json.t ├── quote-sql.t ├── rand.t ├── rotate.t ├── secure-random.t └── unescape-uri.t ├── util └── build.sh └── valgrind.suppress /.gitattributes: -------------------------------------------------------------------------------- 1 | *.t linguist-language=Text 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | reindex 2 | .libs 3 | *.swp 4 | *.slo 5 | *.la 6 | *.swo 7 | *.lo 8 | *~ 9 | *.o 10 | print.txt 11 | .rsync 12 | *.tar.gz 13 | dist 14 | build[789] 15 | build 16 | tags 17 | update-readme 18 | *.tmp 19 | test/Makefile 20 | test/blib 21 | test.sh 22 | all 23 | t/t.sh 24 | test/t/servroot/ 25 | releng 26 | reset 27 | *.t_ 28 | genmobi.sh 29 | *.mobi 30 | misc/chunked 31 | ctags 32 | src/base32.h 33 | src/uri.c 34 | src/module.c 35 | src/upstream.c 36 | src/upstream.h 37 | src/uri.c 38 | src/sql.c 39 | src/uri.h 40 | src/sql.h 41 | src/uri.h 42 | src/value.c 43 | src/base32.c 44 | src/value.h 45 | src/hash.h 46 | src/hash.c 47 | src/today.h 48 | src/today.c 49 | src/json.[ch] 50 | all.sh 51 | go 52 | t/servroot/ 53 | src/base64.c 54 | src/base64.h 55 | src/hex.c 56 | src/hex.h 57 | src/hmac.c 58 | src/hmac.h 59 | src/rotate.[ch] 60 | analyze 61 | buildroot/ 62 | src/module.h 63 | work/ 64 | src/random.[ch] 65 | build1[0-9] 66 | nginx 67 | analyze 68 | src/rotate.[ch] 69 | *.plist 70 | Makefile 71 | src/base64url.[ch] 72 | src/expired.[ch] 73 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: required 2 | dist: focal 3 | 4 | branches: 5 | only: 6 | - "master" 7 | 8 | os: linux 9 | 10 | language: c 11 | compiler: gcc 12 | 13 | env: 14 | global: 15 | - LUAJIT_PREFIX=/opt/luajit21 16 | - LUAJIT_LIB=$LUAJIT_PREFIX/lib 17 | - LD_LIBRARY_PATH=$LUAJIT_LIB:$LD_LIBRARY_PATH 18 | - LUAJIT_INC=$LUAJIT_PREFIX/include/luajit-2.1 19 | - LUA_INCLUDE_DIR=$LUAJIT_INC 20 | - LUA_CMODULE_DIR=/lib 21 | - JOBS=3 22 | - NGX_BUILD_JOBS=$JOBS 23 | - TEST_NGINX_SLEEP=0.006 24 | matrix: 25 | - NGINX_VERSION=1.27.1 26 | 27 | before_install: 28 | - sudo apt-get install -qq -y axel cpanminus libtest-base-perl libtext-diff-perl liburi-perl libwww-perl libtest-longstring-perl liblist-moreutils-perl > build.log 2>&1 || (cat build.log && exit 1) 29 | 30 | install: 31 | - git clone https://github.com/openresty/openresty-devel-utils.git 32 | - git clone https://github.com/openresty/openresty.git ../openresty 33 | - git clone https://github.com/openresty/no-pool-nginx.git ../no-pool-nginx 34 | - git clone https://github.com/simpl/ngx_devel_kit.git ../ndk-nginx-module 35 | - git clone https://github.com/openresty/test-nginx.git 36 | - git clone -b v2.1-agentzh https://github.com/openresty/luajit2.git 37 | - git clone https://github.com/openresty/lua-nginx-module.git ../lua-nginx-module 38 | - git clone https://github.com/openresty/lua-resty-core.git ../lua-resty-core 39 | - git clone https://github.com/openresty/lua-resty-lrucache.git ../lua-resty-lrucache 40 | - git clone https://github.com/openresty/echo-nginx-module.git ../echo-nginx-module 41 | - git clone https://github.com/calio/iconv-nginx-module.git ../iconv-nginx-module 42 | 43 | script: 44 | - export PATH=$PWD/work/nginx/sbin:$PWD/openresty-devel-utils:$PATH 45 | - ngx-releng > check.txt || true 46 | - lines=`wc -l check.txt | awk '{print $1}'`; if [ $lines -gt 3 ]; then cat check.txt; exit 1; fi 47 | - cd luajit2 48 | - make -j$JOBS CCDEBUG=-g Q= PREFIX=$LUAJIT_PREFIX CC=$CC XCFLAGS='-DLUA_USE_APICHECK -DLUA_USE_ASSERT' > build.log 2>&1 || (cat build.log && exit 1) 49 | - sudo make install PREFIX=$LUAJIT_PREFIX > build.log 2>&1 || (cat build.log && exit 1) 50 | - cd ../test-nginx && sudo cpanm . && cd .. 51 | - export NGX_BUILD_CC=$CC 52 | - sh util/build.sh $NGINX_VERSION > build.log 2>&1 || (cat build.log && exit 1) 53 | - nginx -V 54 | - prove -I. -r t 55 | -------------------------------------------------------------------------------- /README.markdown: -------------------------------------------------------------------------------- 1 | 5 | 6 | Name 7 | ==== 8 | 9 | **ngx_set_misc** - Various set_xxx directives added to nginx's rewrite module (md5/sha1, sql/json quoting, and many more) 10 | 11 | *This module is not distributed with the Nginx source.* See [the installation instructions](#installation). 12 | 13 | Table of Contents 14 | ================= 15 | 16 | * [Name](#name) 17 | * [Version](#version) 18 | * [Synopsis](#synopsis) 19 | * [Description](#description) 20 | * [Directives](#directives) 21 | * [set_if_empty](#set_if_empty) 22 | * [set_quote_sql_str](#set_quote_sql_str) 23 | * [set_quote_pgsql_str](#set_quote_pgsql_str) 24 | * [set_quote_json_str](#set_quote_json_str) 25 | * [set_unescape_uri](#set_unescape_uri) 26 | * [set_escape_uri](#set_escape_uri) 27 | * [set_hashed_upstream](#set_hashed_upstream) 28 | * [set_encode_base32](#set_encode_base32) 29 | * [set_base32_padding](#set_base32_padding) 30 | * [set_misc_base32_padding](#set_misc_base32_padding) 31 | * [set_base32_alphabet](#set_base32_alphabet) 32 | * [set_decode_base32](#set_decode_base32) 33 | * [set_encode_base64](#set_encode_base64) 34 | * [set_decode_base64](#set_decode_base64) 35 | * [set_encode_base64url](#set_encode_base64url) 36 | * [set_decode_base64url](#set_decode_base64url) 37 | * [set_encode_hex](#set_encode_hex) 38 | * [set_decode_hex](#set_decode_hex) 39 | * [set_sha1](#set_sha1) 40 | * [set_md5](#set_md5) 41 | * [set_hmac_sha1](#set_hmac_sha1) 42 | * [set_hmac_sha256](#set_hmac_sha256) 43 | * [set_random](#set_random) 44 | * [set_secure_random_alphanum](#set_secure_random_alphanum) 45 | * [set_secure_random_lcalpha](#set_secure_random_lcalpha) 46 | * [set_rotate](#set_rotate) 47 | * [set_local_today](#set_local_today) 48 | * [set_formatted_gmt_time](#set_formatted_gmt_time) 49 | * [set_formatted_local_time](#set_formatted_local_time) 50 | * [Caveats](#caveats) 51 | * [Installation](#installation) 52 | * [Building as a dynamic module](#building-as-a-dynamic-module) 53 | * [Compatibility](#compatibility) 54 | * [Report Bugs](#report-bugs) 55 | * [Source Repository](#source-repository) 56 | * [Changes](#changes) 57 | * [Test Suite](#test-suite) 58 | * [Getting involved](#getting-involved) 59 | * [Author](#author) 60 | * [Copyright & License](#copyright--license) 61 | * [See Also](#see-also) 62 | 63 | Version 64 | ======= 65 | 66 | This document describes ngx_set_misc [v0.32](https://github.com/openresty/set-misc-nginx-module/tags) released on 19 April 2018. 67 | 68 | Synopsis 69 | ======== 70 | 71 | ```nginx 72 | 73 | location /foo { 74 | set $a $arg_a; 75 | set_if_empty $a 56; 76 | 77 | # GET /foo?a=32 will yield $a == 32 78 | # while GET /foo and GET /foo?a= will 79 | # yeild $a == 56 here. 80 | } 81 | 82 | location /bar { 83 | set $foo "hello\n\n'\"\\"; 84 | set_quote_sql_str $foo $foo; # for mysql 85 | 86 | # OR in-place editing: 87 | # set_quote_sql_str $foo; 88 | 89 | # now $foo is: 'hello\n\n\'\"\\' 90 | } 91 | 92 | location /bar { 93 | set $foo "hello\n\n'\"\\"; 94 | set_quote_pgsql_str $foo; # for PostgreSQL 95 | 96 | # now $foo is: E'hello\n\n\'\"\\' 97 | } 98 | 99 | location /json { 100 | set $foo "hello\n\n'\"\\"; 101 | set_quote_json_str $foo $foo; 102 | 103 | # OR in-place editing: 104 | # set_quote_json_str $foo; 105 | 106 | # now $foo is: "hello\n\n'\"\\" 107 | } 108 | 109 | location /baz { 110 | set $foo "hello%20world"; 111 | set_unescape_uri $foo $foo; 112 | 113 | # OR in-place editing: 114 | # set_unescape_uri $foo; 115 | 116 | # now $foo is: hello world 117 | } 118 | 119 | upstream_list universe moon sun earth; 120 | upstream moon { ... } 121 | upstream sun { ... } 122 | upstream earth { ... } 123 | location /foo { 124 | set_hashed_upstream $backend universe $arg_id; 125 | drizzle_pass $backend; # used with ngx_drizzle 126 | } 127 | 128 | location /base32 { 129 | set $a 'abcde'; 130 | set_encode_base32 $a; 131 | set_decode_base32 $b $a; 132 | 133 | # now $a == 'c5h66p35' and 134 | # $b == 'abcde' 135 | } 136 | 137 | location /base64 { 138 | set $a 'abcde'; 139 | set_encode_base64 $a; 140 | set_decode_base64 $b $a; 141 | 142 | # now $a == 'YWJjZGU=' and 143 | # $b == 'abcde' 144 | } 145 | 146 | location /hex { 147 | set $a 'abcde'; 148 | set_encode_hex $a; 149 | set_decode_hex $b $a; 150 | 151 | # now $a == '6162636465' and 152 | # $b == 'abcde' 153 | } 154 | 155 | # GET /sha1 yields the output 156 | # aaf4c61ddcc5e8a2dabede0f3b482cd9aea9434d 157 | location /sha1 { 158 | set_sha1 $a hello; 159 | echo $a; 160 | } 161 | 162 | # ditto 163 | location /sha1 { 164 | set $a hello; 165 | set_sha1 $a; 166 | echo $a; 167 | } 168 | 169 | # GET /today yields the date of today in local time using format 'yyyy-mm-dd' 170 | location /today { 171 | set_local_today $today; 172 | echo $today; 173 | } 174 | 175 | # GET /signature yields the hmac-sha-1 signature 176 | # given a secret and a string to sign 177 | # this example yields the base64 encoded singature which is 178 | # "HkADYytcoQQzqbjQX33k/ZBB/DQ=" 179 | location /signature { 180 | set $secret_key 'secret-key'; 181 | set $string_to_sign "some-string-to-sign"; 182 | set_hmac_sha1 $signature $secret_key $string_to_sign; 183 | set_encode_base64 $signature $signature; 184 | echo $signature; 185 | } 186 | 187 | location = /rand { 188 | set $from 3; 189 | set $to 15; 190 | set_random $rand $from $to; 191 | 192 | # or write directly 193 | # set_random $rand 3 15; 194 | 195 | echo $rand; # will print a random integer in the range [3, 15] 196 | } 197 | ``` 198 | 199 | Description 200 | =========== 201 | 202 | This module extends the standard HttpRewriteModule's directive set to provide more functionalities like URI escaping and unescaping, JSON quoting, Hexadecimal/MD5/SHA1/Base32/Base64 digest encoding and decoding, random number generator, and more! 203 | 204 | Every directive provided by this module can be mixed freely with other [ngx_http_rewrite_module](http://nginx.org/en/docs/http/ngx_http_rewrite_module.html)'s directives, like [if](http://nginx.org/en/docs/http/ngx_http_rewrite_module.html#if) and [set](http://nginx.org/en/docs/http/ngx_http_rewrite_module.html#set). (Thanks to the [Nginx Devel Kit](https://github.com/simpl/ngx_devel_kit)!) 205 | 206 | [Back to TOC](#table-of-contents) 207 | 208 | Directives 209 | ========== 210 | 211 | [Back to TOC](#table-of-contents) 212 | 213 | set_if_empty 214 | ------------ 215 | **syntax:** *set_if_empty $dst <src>* 216 | 217 | **default:** *no* 218 | 219 | **context:** *location, location if* 220 | 221 | **phase:** *rewrite* 222 | 223 | Assign the value of the argument `` if and only if variable `$dst` is empty (i.e., not found or has an empty string value). 224 | 225 | In the following example, 226 | 227 | ```nginx 228 | 229 | set $a 32; 230 | set_if_empty $a 56; 231 | ``` 232 | 233 | the variable `$dst` will take the value 32 at last. But in the sample 234 | 235 | ```nginx 236 | 237 | set $a ''; 238 | set $value "hello, world" 239 | set_if_empty $a $value; 240 | ``` 241 | 242 | `$a` will take the value `"hello, world"` at last. 243 | 244 | [Back to TOC](#table-of-contents) 245 | 246 | set_quote_sql_str 247 | ----------------- 248 | **syntax:** *set_quote_sql_str $dst <src>* 249 | 250 | **syntax:** *set_quote_sql_str $dst* 251 | 252 | **default:** *no* 253 | 254 | **context:** *location, location if* 255 | 256 | **phase:** *rewrite* 257 | 258 | **category:** *ndk_set_var_value* 259 | 260 | When taking two arguments, this directive will quote the value of the second argument `` by MySQL's string value quoting rule and assign the result into the first argument, variable `$dst`. For example, 261 | 262 | ```nginx 263 | 264 | location /test { 265 | set $value "hello\n\r'\"\\"; 266 | set_quote_sql_str $quoted $value; 267 | 268 | echo $quoted; 269 | } 270 | ``` 271 | 272 | Then request `GET /test` will yield the following output 273 | 274 | ```sql 275 | 276 | 'hello\n\r\'\"\\' 277 | ``` 278 | 279 | Please note that we're using [echo-nginx-module](http://github.com/openresty/echo-nginx-module)'s [echo directive](http://github.com/openresty/echo-nginx-module#echo) here to output values of nginx variables directly. 280 | 281 | When taking a single argument, this directive will do in-place modification of the argument variable. For example, 282 | 283 | ```nginx 284 | 285 | location /test { 286 | set $value "hello\n\r'\"\\"; 287 | set_quote_sql_str $value; 288 | 289 | echo $value; 290 | } 291 | ``` 292 | 293 | then request `GET /test` will give exactly the same output as the previous example. 294 | 295 | This directive is usually used to prevent SQL injection. 296 | 297 | This directive can be invoked by [lua-nginx-module](http://github.com/openresty/lua-nginx-module)'s [ndk.set_var.DIRECTIVE](http://github.com/openresty/lua-nginx-module#ndkset_vardirective) interface and [array-var-nginx-module](http://github.com/openresty/array-var-nginx-module)'s [array_map_op](http://github.com/openresty/array-var-nginx-module#array_map_op) directive. 298 | 299 | [Back to TOC](#table-of-contents) 300 | 301 | set_quote_pgsql_str 302 | ------------------- 303 | **syntax:** *set_quote_pgsql_str $dst <src>* 304 | 305 | **syntax:** *set_quote_pgsql_str $dst* 306 | 307 | **default:** *no* 308 | 309 | **context:** *location, location if* 310 | 311 | **phase:** *rewrite* 312 | 313 | **category:** *ndk_set_var_value* 314 | 315 | Very much like [set_quote_sql_str](#set_quote_sql_str), but with PostgreSQL quoting rules for SQL string literals. 316 | 317 | [Back to TOC](#table-of-contents) 318 | 319 | set_quote_json_str 320 | ------------------ 321 | **syntax:** *set_quote_json_str $dst <src>* 322 | 323 | **syntax:** *set_quote_json_str $dst* 324 | 325 | **default:** *no* 326 | 327 | **context:** *location, location if* 328 | 329 | **phase:** *rewrite* 330 | 331 | **category:** *ndk_set_var_value* 332 | 333 | When taking two arguments, this directive will quote the value of the second argument `` by JSON string value quoting rule and assign the result into the first argument, variable `$dst`. For example, 334 | 335 | ```nginx 336 | 337 | location /test { 338 | set $value "hello\n\r'\"\\"; 339 | set_quote_json_str $quoted $value; 340 | 341 | echo $quoted; 342 | } 343 | ``` 344 | 345 | Then request `GET /test` will yield the following output 346 | 347 | ```javascript 348 | 349 | "hello\n\r'\"\\" 350 | ``` 351 | 352 | Please note that we're using [echo-nginx-module](http://github.com/openresty/echo-nginx-module)'s [echo directive](http://github.com/openresty/echo-nginx-module#echo) here to output values of nginx variables directly. 353 | 354 | When taking a single argument, this directive will do in-place modification of the argument variable. For example, 355 | 356 | ```nginx 357 | 358 | location /test { 359 | set $value "hello\n\r'\"\\"; 360 | set_quote_json_str $value; 361 | 362 | echo $value; 363 | } 364 | ``` 365 | 366 | then request `GET /test` will give exactly the same output as the previous example. 367 | 368 | This directive can be invoked by [lua-nginx-module](http://github.com/openresty/lua-nginx-module)'s [ndk.set_var.DIRECTIVE](http://github.com/openresty/lua-nginx-module#ndkset_vardirective) interface and [array-var-nginx-module](http://github.com/openresty/array-var-nginx-module)'s [array_map_op](http://github.com/openresty/array-var-nginx-module#array_map_op) directive. 369 | 370 | [Back to TOC](#table-of-contents) 371 | 372 | set_unescape_uri 373 | ---------------- 374 | **syntax:** *set_unescape_uri $dst <src>* 375 | 376 | **syntax:** *set_unescape_uri $dst* 377 | 378 | **default:** *no* 379 | 380 | **context:** *location, location if* 381 | 382 | **phase:** *rewrite* 383 | 384 | **category:** *ndk_set_var_value* 385 | 386 | When taking two arguments, this directive will unescape the value of the second argument `` as a URI component and assign the result into the first argument, variable `$dst`. For example, 387 | 388 | ```nginx 389 | 390 | location /test { 391 | set_unescape_uri $key $arg_key; 392 | echo $key; 393 | } 394 | ``` 395 | 396 | Then request `GET /test?key=hello+world%21` will yield the following output 397 | 398 | ``` 399 | hello world! 400 | ``` 401 | 402 | The nginx standard [$arg_PARAMETER](http://nginx.org/en/docs/http/ngx_http_core_module.html#var_arg_) variable holds the raw (escaped) value of the URI parameter. So we need the `set_unescape_uri` directive to unescape it first. 403 | 404 | Please note that we're using [echo-nginx-module](http://github.com/openresty/echo-nginx-module)'s [echo directive](http://github.com/openresty/echo-nginx-module#echo) here to output values of nginx variables directly. 405 | 406 | When taking a single argument, this directive will do in-place modification of the argument variable. For example, 407 | 408 | ```nginx 409 | 410 | location /test { 411 | set $key $arg_key; 412 | set_unescape_uri $key; 413 | 414 | echo $key; 415 | } 416 | ``` 417 | 418 | then request `GET /test?key=hello+world%21` will give exactly the same output as the previous example. 419 | 420 | This directive can be invoked by [lua-nginx-module](http://github.com/openresty/lua-nginx-module)'s [ndk.set_var.DIRECTIVE](http://github.com/openresty/lua-nginx-module#ndkset_vardirective) interface and [array-var-nginx-module](http://github.com/openresty/array-var-nginx-module)'s [array_map_op](http://github.com/openresty/array-var-nginx-module#array_map_op) directive. 421 | 422 | [Back to TOC](#table-of-contents) 423 | 424 | set_escape_uri 425 | -------------- 426 | **syntax:** *set_escape_uri $dst <src>* 427 | 428 | **syntax:** *set_escape_uri $dst* 429 | 430 | **default:** *no* 431 | 432 | **context:** *location, location if* 433 | 434 | **phase:** *rewrite* 435 | 436 | **category:** *ndk_set_var_value* 437 | 438 | Very much like the [set_unescape_uri](#set_unescape_uri) directive, but does the conversion the other way around, i.e., URL component escaping. 439 | 440 | [Back to TOC](#table-of-contents) 441 | 442 | set_hashed_upstream 443 | ------------------- 444 | **syntax:** *set_hashed_upstream $dst <upstream_list_name> <src>* 445 | 446 | **default:** *no* 447 | 448 | **context:** *location, location if* 449 | 450 | **phase:** *rewrite* 451 | 452 | Hashes the string argument `` into one of the upstream name included in the upstream list named ``. The hash function being used is simple modulo. 453 | 454 | Here's an example, 455 | 456 | ```nginx 457 | 458 | upstream moon { ... } 459 | upstream sun { ... } 460 | upstream earth { ... } 461 | 462 | upstream_list universe moon sun earth; 463 | 464 | location /test { 465 | set_unescape_uri $key $arg_key; 466 | set $list_name universe; 467 | set_hashed_upstream $backend $list_name $key; 468 | 469 | echo $backend; 470 | } 471 | ``` 472 | 473 | Then `GET /test?key=blah` will output either "moon", "sun", or "earth", depending on the actual value of the `key` query argument. 474 | 475 | This directive is usually used to compute an nginx variable to be passed to [memc-nginx-module](http://github.com/openresty/memc-nginx-module)'s [memc_pass](http://github.com/openresty/memc-nginx-module#memc_pass) directive, [redis2-nginx-module](http://github.com/openresty/redis2-nginx-module)'s [[HttpRedis2Module#redis2_pass]] directive, and [ngx_http_proxy_module](http://nginx.org/en/docs/http/ngx_http_proxy_module.html)'s [proxy_pass](http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_pass) directive, among others. 476 | 477 | [Back to TOC](#table-of-contents) 478 | 479 | set_encode_base32 480 | ----------------- 481 | **syntax:** *set_encode_base32 $dst <src>* 482 | 483 | **syntax:** *set_encode_base32 $dst* 484 | 485 | **default:** *no* 486 | 487 | **context:** *location, location if* 488 | 489 | **phase:** *rewrite* 490 | 491 | **category:** *ndk_set_var_value* 492 | 493 | When taking two arguments, this directive will encode the value of the second argument `` to its base32(hex) digest and assign the result into the first argument, variable `$dst`. For example, 494 | 495 | ```nginx 496 | 497 | location /test { 498 | set $raw "abcde"; 499 | set_encode_base32 $digest $raw; 500 | 501 | echo $digest; 502 | } 503 | ``` 504 | 505 | Then request `GET /test` will yield the following output 506 | 507 | ``` 508 | c5h66p35 509 | ``` 510 | 511 | Please note that we're using [echo-nginx-module](http://github.com/openresty/echo-nginx-module)'s [echo directive](http://github.com/openresty/echo-nginx-module#echo) here to output values of nginx variables directly. 512 | 513 | RFC forces the `[A-Z2-7]` RFC-3548 compliant encoding, but we are using the "base32hex" encoding (`[0-9a-v]`) by default. The [set_base32_alphabet](#set_base32_alphabet) directive (first introduced in `v0.28`) allows you to change the alphabet used for encoding/decoding so RFC-3548 compliant encoding is still possible by custom configurations. 514 | 515 | By default, the `=` character is used to pad the left-over bytes due to alignment. But the padding behavior can be completely disabled by setting [set_base32_padding](#set_base32_padding) `off`. 516 | 517 | When taking a single argument, this directive will do in-place modification of the argument variable. For example, 518 | 519 | ```nginx 520 | 521 | location /test { 522 | set $value "abcde"; 523 | set_encode_base32 $value; 524 | 525 | echo $value; 526 | } 527 | ``` 528 | 529 | then request `GET /test` will give exactly the same output as the previous example. 530 | 531 | This directive can be invoked by [lua-nginx-module](http://github.com/openresty/lua-nginx-module)'s [ndk.set_var.DIRECTIVE](http://github.com/openresty/lua-nginx-module#ndkset_vardirective) interface and [array-var-nginx-module](http://github.com/openresty/array-var-nginx-module)'s [array_map_op](http://github.com/openresty/array-var-nginx-module#array_map_op) directive. 532 | 533 | [Back to TOC](#table-of-contents) 534 | 535 | set_base32_padding 536 | ------------------ 537 | **syntax:** *set_base32_padding on|off* 538 | 539 | **default:** *on* 540 | 541 | **context:** *http, server, server if, location, location if* 542 | 543 | **phase:** *no* 544 | 545 | This directive can control whether to pad left-over bytes with the "=" character when encoding a base32 digest by the 546 | [set_encode_base32](#set_encode_base32) directive. 547 | 548 | This directive was first introduced in `v0.28`. If you use earlier versions of this module, then you should use [set_misc_base32_padding](#set_misc_base32_padding) instead. 549 | 550 | [Back to TOC](#table-of-contents) 551 | 552 | set_misc_base32_padding 553 | ----------------------- 554 | **syntax:** *set_misc_base32_padding on|off* 555 | 556 | **default:** *on* 557 | 558 | **context:** *http, server, server if, location, location if* 559 | 560 | **phase:** *no* 561 | 562 | This directive has been deprecated since `v0.28`. Use [set_base32_padding](#set_base32_padding) instead if you are using `v0.28+`. 563 | 564 | [Back to TOC](#table-of-contents) 565 | 566 | set_base32_alphabet 567 | ------------------- 568 | **syntax:** *set_base32_alphabet <alphabet>* 569 | 570 | **default:** *"0123456789abcdefghijklmnopqrstuv"* 571 | 572 | **context:** *http, server, server if, location, location if* 573 | 574 | **phase:** *no* 575 | 576 | This directive controls the alphabet used for encoding/decoding a base32 digest. It accepts a string containing the desired alphabet like "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567" for standard alphabet. 577 | 578 | Extended (base32hex) alphabet is used by default. 579 | 580 | This directive was first introduced in `v0.28`. 581 | 582 | [Back to TOC](#table-of-contents) 583 | 584 | set_decode_base32 585 | ----------------- 586 | **syntax:** *set_decode_base32 $dst <src>* 587 | 588 | **syntax:** *set_decode_base32 $dst* 589 | 590 | **default:** *no* 591 | 592 | **context:** *location, location if* 593 | 594 | **phase:** *rewrite* 595 | 596 | **category:** *ndk_set_var_value* 597 | 598 | Similar to the [set_encode_base32](#set_encode_base32) directive, but does exactly the opposite operation, .i.e, decoding a base32(hex) digest into its original form. 599 | 600 | [Back to TOC](#table-of-contents) 601 | 602 | set_encode_base64 603 | ----------------- 604 | **syntax:** *set_encode_base64 $dst <src>* 605 | 606 | **syntax:** *set_encode_base64 $dst* 607 | 608 | **default:** *no* 609 | 610 | **context:** *location, location if* 611 | 612 | **phase:** *rewrite* 613 | 614 | **category:** *ndk_set_var_value* 615 | 616 | When taking two arguments, this directive will encode the value of the second argument `` to its base64 digest and assign the result into the first argument, variable `$dst`. For example, 617 | 618 | ```nginx 619 | 620 | location /test { 621 | set $raw "abcde"; 622 | set_encode_base64 $digest $raw; 623 | 624 | echo $digest; 625 | } 626 | ``` 627 | 628 | Then request `GET /test` will yield the following output 629 | 630 | ``` 631 | YWJjZGU= 632 | ``` 633 | 634 | Please note that we're using [echo-nginx-module](http://github.com/openresty/echo-nginx-module)'s [echo directive](http://github.com/openresty/echo-nginx-module#echo) here to output values of nginx variables directly. 635 | 636 | When taking a single argument, this directive will do in-place modification of the argument variable. For example, 637 | 638 | ```nginx 639 | 640 | location /test { 641 | set $value "abcde"; 642 | set_encode_base64 $value; 643 | 644 | echo $value; 645 | } 646 | ``` 647 | 648 | then request `GET /test` will give exactly the same output as the previous example. 649 | 650 | This directive can be invoked by [lua-nginx-module](http://github.com/openresty/lua-nginx-module)'s [ndk.set_var.DIRECTIVE](http://github.com/openresty/lua-nginx-module#ndkset_vardirective) interface and [array-var-nginx-module](http://github.com/openresty/array-var-nginx-module)'s [array_map_op](http://github.com/openresty/array-var-nginx-module#array_map_op) directive. 651 | 652 | [Back to TOC](#table-of-contents) 653 | 654 | set_encode_base64url 655 | ----------------- 656 | **syntax:** *set_encode_base64url $dst <src>* 657 | 658 | **syntax:** *set_encode_base64url $dst* 659 | 660 | **default:** *no* 661 | 662 | **context:** *location, location if* 663 | 664 | **phase:** *rewrite* 665 | 666 | **category:** *ndk_set_var_value* 667 | 668 | When taking two arguments, this directive will encode the value of the second argument `` to its base64 url safe digest and assign the result into the first argument, variable `$dst`. For example, 669 | 670 | ```nginx 671 | 672 | location /test { 673 | set $raw "abcde"; 674 | set_encode_base64url $digest $raw; 675 | 676 | echo $digest; 677 | } 678 | ``` 679 | 680 | Then request `GET /test` will yield the following output 681 | 682 | ``` 683 | YWJjZGU= 684 | ``` 685 | 686 | Please note that we're using [echo-nginx-module](http://github.com/openresty/echo-nginx-module)'s [echo directive](http://github.com/openresty/echo-nginx-module#echo) here to output values of nginx variables directly. 687 | 688 | When taking a single argument, this directive will do in-place modification of the argument variable. For example, 689 | 690 | ```nginx 691 | 692 | location /test { 693 | set $value "abcde"; 694 | set_encode_base64url $value; 695 | 696 | echo $value; 697 | } 698 | ``` 699 | 700 | then request `GET /test` will give exactly the same output as the previous example. 701 | 702 | This directive can be invoked by [lua-nginx-module](http://github.com/openresty/lua-nginx-module)'s [ndk.set_var.DIRECTIVE](http://github.com/openresty/lua-nginx-module#ndkset_vardirective) interface and [array-var-nginx-module](http://github.com/openresty/array-var-nginx-module)'s [array_map_op](http://github.com/openresty/array-var-nginx-module#array_map_op) directive. 703 | 704 | [Back to TOC](#table-of-contents) 705 | 706 | set_decode_base64 707 | ----------------- 708 | **syntax:** *set_decode_base64 $dst <src>* 709 | 710 | **syntax:** *set_decode_base64 $dst* 711 | 712 | **default:** *no* 713 | 714 | **context:** *location, location if* 715 | 716 | **phase:** *rewrite* 717 | 718 | **category:** *ndk_set_var_value* 719 | 720 | Similar to the [set_encode_base64](#set_encode_base64) directive, but does exactly the opposite operation, .i.e, decoding a base64 digest into its original form. 721 | 722 | [Back to TOC](#table-of-contents) 723 | 724 | set_decode_base64url 725 | ----------------- 726 | **syntax:** *set_decode_base64url $dst <src>* 727 | 728 | **syntax:** *set_decode_base64url $dst* 729 | 730 | **default:** *no* 731 | 732 | **context:** *location, location if* 733 | 734 | **phase:** *rewrite* 735 | 736 | **category:** *ndk_set_var_value* 737 | 738 | Similar to the [set_encode_base64url](#set_encode_base64url) directive, but does exactly the the opposite operation, .i.e, decoding a base64 url safe digest into its original form. 739 | 740 | [Back to TOC](#table-of-contents) 741 | 742 | set_encode_hex 743 | -------------- 744 | **syntax:** *set_encode_hex $dst <src>* 745 | 746 | **syntax:** *set_encode_hex $dst* 747 | 748 | **default:** *no* 749 | 750 | **context:** *location, location if* 751 | 752 | **phase:** *rewrite* 753 | 754 | **category:** *ndk_set_var_value* 755 | 756 | When taking two arguments, this directive will encode the value of the second argument `` to its hexadecimal digest and assign the result into the first argument, variable `$dst`. For example, 757 | 758 | ```nginx 759 | 760 | location /test { 761 | set $raw "章亦春"; 762 | set_encode_hex $digest $raw; 763 | 764 | echo $digest; 765 | } 766 | ``` 767 | 768 | Then request `GET /test` will yield the following output 769 | 770 | ``` 771 | e7aba0e4baa6e698a5 772 | ``` 773 | 774 | Please note that we're using [echo-nginx-module](http://github.com/openresty/echo-nginx-module)'s [echo directive](http://github.com/openresty/echo-nginx-module#echo) here to output values of nginx variables directly. 775 | 776 | When taking a single argument, this directive will do in-place modification of the argument variable. For example, 777 | 778 | ```nginx 779 | 780 | location /test { 781 | set $value "章亦春"; 782 | set_encode_hex $value; 783 | 784 | echo $value; 785 | } 786 | ``` 787 | 788 | then request `GET /test` will give exactly the same output as the previous example. 789 | 790 | This directive can be invoked by [lua-nginx-module](http://github.com/openresty/lua-nginx-module)'s [ndk.set_var.DIRECTIVE](http://github.com/openresty/lua-nginx-module#ndkset_vardirective) interface and [array-var-nginx-module](http://github.com/openresty/array-var-nginx-module)'s [array_map_op](http://github.com/openresty/array-var-nginx-module#array_map_op) directive. 791 | 792 | [Back to TOC](#table-of-contents) 793 | 794 | set_decode_hex 795 | -------------- 796 | **syntax:** *set_decode_hex $dst <src>* 797 | 798 | **syntax:** *set_decode_hex $dst* 799 | 800 | **default:** *no* 801 | 802 | **context:** *location, location if* 803 | 804 | **phase:** *rewrite* 805 | 806 | **category:** *ndk_set_var_value* 807 | 808 | Similar to the [set_encode_hex](#set_encode_hex) directive, but does exactly the opposite operation, .i.e, decoding a hexadecimal digest into its original form. 809 | 810 | [Back to TOC](#table-of-contents) 811 | 812 | set_sha1 813 | -------- 814 | **syntax:** *set_sha1 $dst <src>* 815 | 816 | **syntax:** *set_sha1 $dst* 817 | 818 | **default:** *no* 819 | 820 | **context:** *location, location if* 821 | 822 | **phase:** *rewrite* 823 | 824 | **category:** *ndk_set_var_value* 825 | 826 | When taking two arguments, this directive will encode the value of the second argument `` to its [SHA-1](http://en.wikipedia.org/wiki/SHA-1) digest and assign the result into the first argument, variable `$dst`. The hexadecimal form of the `SHA-1` digest will be generated automatically, use [set_decode_hex](#set_decode_hex) to decode the result if you want the binary form of the `SHA-1` digest. 827 | 828 | For example, 829 | 830 | ```nginx 831 | 832 | location /test { 833 | set $raw "hello"; 834 | set_sha1 $digest $raw; 835 | 836 | echo $digest; 837 | } 838 | ``` 839 | 840 | Then request `GET /test` will yield the following output 841 | 842 | ``` 843 | aaf4c61ddcc5e8a2dabede0f3b482cd9aea9434d 844 | ``` 845 | 846 | Please note that we're using [echo-nginx-module](http://github.com/openresty/echo-nginx-module)'s [echo directive](http://github.com/openresty/echo-nginx-module#echo) here to output values of nginx variables directly. 847 | 848 | When taking a single argument, this directive will do in-place modification of the argument variable. For example, 849 | 850 | ```nginx 851 | 852 | location /test { 853 | set $value "hello"; 854 | set_sha1 $value; 855 | 856 | echo $value; 857 | } 858 | ``` 859 | 860 | then request `GET /test` will give exactly the same output as the previous example. 861 | 862 | This directive can be invoked by [lua-nginx-module](http://github.com/openresty/lua-nginx-module)'s [ndk.set_var.DIRECTIVE](http://github.com/openresty/lua-nginx-module#ndkset_vardirective) interface and [array-var-nginx-module](http://github.com/openresty/array-var-nginx-module)'s [array_map_op](http://github.com/openresty/array-var-nginx-module#array_map_op) directive. 863 | 864 | [Back to TOC](#table-of-contents) 865 | 866 | set_md5 867 | ------- 868 | **syntax:** *set_md5 $dst <src>* 869 | 870 | **syntax:** *set_md5 $dst* 871 | 872 | **default:** *no* 873 | 874 | **context:** *location, location if* 875 | 876 | **phase:** *rewrite* 877 | 878 | **category:** *ndk_set_var_value* 879 | 880 | When taking two arguments, this directive will encode the value of the second argument `` to its [MD5](http://en.wikipedia.org/wiki/MD5) digest and assign the result into the first argument, variable `$dst`. The hexadecimal form of the `MD5` digest will be generated automatically, use [set_decode_hex](#set_decode_hex) to decode the result if you want the binary form of the `MD5` digest. 881 | 882 | For example, 883 | 884 | ```nginx 885 | 886 | location /test { 887 | set $raw "hello"; 888 | set_md5 $digest $raw; 889 | 890 | echo $digest; 891 | } 892 | ``` 893 | 894 | Then request `GET /test` will yield the following output 895 | 896 | 897 | 5d41402abc4b2a76b9719d911017c592 898 | 899 | 900 | Please note that we're using [echo-nginx-module](http://github.com/openresty/echo-nginx-module)'s [echo directive](http://github.com/openresty/echo-nginx-module#echo) here to output values of nginx variables directly. 901 | 902 | When taking a single argument, this directive will do in-place modification of the argument variable. For example, 903 | 904 | ```nginx 905 | 906 | location /test { 907 | set $value "hello"; 908 | set_md5 $value; 909 | 910 | echo $value; 911 | } 912 | ``` 913 | 914 | then request `GET /test` will give exactly the same output as the previous example. 915 | 916 | This directive can be invoked by [lua-nginx-module](http://github.com/openresty/lua-nginx-module)'s [ndk.set_var.DIRECTIVE](http://github.com/openresty/lua-nginx-module#ndkset_vardirective) interface and [array-var-nginx-module](http://github.com/openresty/array-var-nginx-module)'s [array_map_op](http://github.com/openresty/array-var-nginx-module#array_map_op) directive. 917 | 918 | [Back to TOC](#table-of-contents) 919 | 920 | set_hmac_sha1 921 | ------------- 922 | **syntax:** *set_hmac_sha1 $dst <secret_key> <src>* 923 | 924 | **syntax:** *set_hmac_sha1 $dst* 925 | 926 | **default:** *no* 927 | 928 | **context:** *location, location if* 929 | 930 | **phase:** *rewrite* 931 | 932 | Computes the [HMAC-SHA1](http://en.wikipedia.org/wiki/HMAC) digest of the argument `` and assigns the result into the argument variable `$dst` with the secret key ``. 933 | 934 | The raw binary form of the `HMAC-SHA1` digest will be generated, use [set_encode_base64](#set_encode_base64), for example, to encode the result to a textual representation if desired. 935 | 936 | For example, 937 | 938 | ```nginx 939 | 940 | location /test { 941 | set $secret 'thisisverysecretstuff'; 942 | set $string_to_sign 'some string we want to sign'; 943 | set_hmac_sha1 $signature $secret $string_to_sign; 944 | set_encode_base64 $signature $signature; 945 | echo $signature; 946 | } 947 | ``` 948 | 949 | Then request `GET /test` will yield the following output 950 | 951 | ``` 952 | R/pvxzHC4NLtj7S+kXFg/NePTmk= 953 | ``` 954 | 955 | Please note that we're using [echo-nginx-module](http://github.com/openresty/echo-nginx-module)'s [echo directive](http://github.com/openresty/echo-nginx-module#echo) here to output values of nginx variables directly. 956 | 957 | This directive requires the OpenSSL library enabled in your Nginx build (usually by passing the `--with-http_ssl_module` option to the `./configure` script). 958 | 959 | [Back to TOC](#table-of-contents) 960 | 961 | set_hmac_sha256 962 | --------------- 963 | **syntax:** *set_hmac_sha256 $dst <secret_key> <src>* 964 | 965 | **syntax:** *set_hmac_sha256 $dst* 966 | 967 | **default:** *no* 968 | 969 | **context:** *location, location if* 970 | 971 | **phase:** *rewrite* 972 | 973 | Computes the [HMAC-SHA256](http://en.wikipedia.org/wiki/HMAC) digest of the argument `` and assigns the result into the argument variable `$dst` with the secret key ``. 974 | 975 | The raw binary form of the `HMAC-SHA256` digest will be generated, use [set_encode_base64](#set_encode_base64), for example, to encode the result to a textual representation if desired. 976 | 977 | For example, 978 | 979 | ```nginx 980 | 981 | location /test { 982 | set $secret 'thisisverysecretstuff'; 983 | set $string_to_sign 'some string we want to sign'; 984 | set_hmac_sha256 $signature $secret $string_to_sign; 985 | set_encode_base64 $signature $signature; 986 | echo $signature; 987 | } 988 | ``` 989 | 990 | Then request `GET /test` will yield the following output 991 | 992 | ``` 993 | 4pU3GRQrKKIoeLb9CqYsavHE2l6Hx+KMmRmesU+Cfrs= 994 | ``` 995 | 996 | Please note that we're using [echo-nginx-module](http://github.com/openresty/echo-nginx-module)'s [echo directive](http://github.com/openresty/echo-nginx-module#echo) here to output values of nginx variables directly. 997 | 998 | This directive requires the OpenSSL library enabled in your Nginx build (usually by passing the `--with-http_ssl_module` option to the `./configure` script). 999 | 1000 | [Back to TOC](#table-of-contents) 1001 | 1002 | set_random 1003 | ---------- 1004 | **syntax:** *set_random $res <from> <to>* 1005 | 1006 | **default:** *no* 1007 | 1008 | **context:** *location, location if* 1009 | 1010 | **phase:** *rewrite* 1011 | 1012 | Generates a (pseudo) random number (in textual form) within the range `[<$from>, <$to>]` (inclusive). 1013 | 1014 | Only non-negative numbers are allowed for the `` and `` arguments. 1015 | 1016 | When `` is greater than ``, their values will be exchanged accordingly. 1017 | 1018 | For instance, 1019 | 1020 | ```nginx 1021 | 1022 | location /test { 1023 | set $from 5; 1024 | set $to 7; 1025 | set_random $res $from $to; 1026 | 1027 | echo $res; 1028 | } 1029 | ``` 1030 | 1031 | then request `GET /test` will output a number between 5 and 7 (i.e., among 5, 6, 7). 1032 | 1033 | For now, there's no way to configure a custom random generator seed. 1034 | 1035 | Behind the scene, it makes use of the standard C function `rand()`. 1036 | 1037 | This directive was first introduced in the `v0.22rc1` release. 1038 | 1039 | See also [set_secure_random_alphanum](#set_secure_random_alphanum) and [set_secure_random_lcalpha](#set_secure_random_lcalpha). 1040 | 1041 | [Back to TOC](#table-of-contents) 1042 | 1043 | set_secure_random_alphanum 1044 | -------------------------- 1045 | **syntax:** *set_secure_random_alphanum $res <length>* 1046 | 1047 | **default:** *no* 1048 | 1049 | **context:** *location, location if* 1050 | 1051 | **phase:** *rewrite* 1052 | 1053 | Generates a cryptographically-strong random string `` characters long with the alphabet `[a-zA-Z0-9]`. 1054 | 1055 | `` may be between 1 and 64, inclusive. 1056 | 1057 | For instance, 1058 | 1059 | ```nginx 1060 | 1061 | location /test { 1062 | set_secure_random_alphanum $res 32; 1063 | 1064 | echo $res; 1065 | } 1066 | ``` 1067 | 1068 | then request `GET /test` will output a string like `ivVVRP2DGaAqDmdf3Rv4ZDJ7k0gOfASz`. 1069 | 1070 | This functionality depends on the presence of the `/dev/urandom` device, available on most UNIX-like systems. 1071 | 1072 | See also [set_secure_random_lcalpha](#set_secure_random_lcalpha) and [set_random](#set_random). 1073 | 1074 | This directive was first introduced in the `v0.22rc8` release. 1075 | 1076 | [Back to TOC](#table-of-contents) 1077 | 1078 | set_secure_random_lcalpha 1079 | ------------------------- 1080 | **syntax:** *set_secure_random_lcalpha $res <length>* 1081 | 1082 | **default:** *no* 1083 | 1084 | **context:** *location, location if* 1085 | 1086 | **phase:** *rewrite* 1087 | 1088 | Generates a cryptographically-strong random string `` characters long with the alphabet `[a-z]`. 1089 | 1090 | `` may be between 1 and 64, inclusive. 1091 | 1092 | For instance, 1093 | 1094 | ```nginx 1095 | 1096 | location /test { 1097 | set_secure_random_lcalpha $res 32; 1098 | 1099 | echo $res; 1100 | } 1101 | ``` 1102 | 1103 | then request `GET /test` will output a string like `kcuxcddktffsippuekhshdaclaquiusj`. 1104 | 1105 | This functionality depends on the presence of the `/dev/urandom` device, available on most UNIX-like systems. 1106 | 1107 | This directive was first introduced in the `v0.22rc8` release. 1108 | 1109 | See also [set_secure_random_alphanum](#set_secure_random_alphanum) and [set_random](#set_random). 1110 | 1111 | [Back to TOC](#table-of-contents) 1112 | 1113 | set_rotate 1114 | ---------- 1115 | **syntax:** *set_rotate $value <from> <to>* 1116 | 1117 | **default:** *no* 1118 | 1119 | **context:** *location, location if* 1120 | 1121 | **phase:** *rewrite* 1122 | 1123 | Increments `$value` but keeps it in range from `` to ``. 1124 | If `$value` is greater than `` or less than `` it will be 1125 | set to `` value. 1126 | 1127 | The current value after running this directive will always be saved on a per-location basis. And then this saved value will be used for incrementation when the `$value` is not initialized or has a bad value. 1128 | 1129 | Only non-negative numbers are allowed for the `` and `` arguments. 1130 | 1131 | When `` is greater than ``, their values will be exchanged accordingly. 1132 | 1133 | For instance, 1134 | 1135 | ```nginx 1136 | 1137 | location /rotate { 1138 | default_type text/plain; 1139 | set $counter $cookie_counter; 1140 | set_rotate $counter 1 5; 1141 | echo $counter; 1142 | add_header Set-Cookie counter=$counter; 1143 | } 1144 | ``` 1145 | 1146 | then request `GET /rotate` will output next number between 1 and 5 (i.e., 1, 2, 3, 4, 5) on each 1147 | refresh of the page. This directive may be userful for banner rotation purposes. 1148 | 1149 | Another example is to use server-side value persistence to do simple round-robin: 1150 | 1151 | ```nginx 1152 | 1153 | location /rotate { 1154 | default_type text/plain; 1155 | set_rotate $counter 0 3; 1156 | echo $counter; 1157 | } 1158 | ``` 1159 | 1160 | And accessing `/rotate` will also output integer sequence 0, 1, 2, 3, 0, 1, 2, 3, and so on. 1161 | 1162 | This directive was first introduced in the `v0.22rc7` release. 1163 | 1164 | [Back to TOC](#table-of-contents) 1165 | 1166 | set_local_today 1167 | --------------- 1168 | **syntax:** *set_local_today $dst* 1169 | 1170 | **default:** *no* 1171 | 1172 | **context:** *location, location if* 1173 | 1174 | **phase:** *rewrite* 1175 | 1176 | Set today's date ("yyyy-mm-dd") in localtime to the argument variable `$dst`. 1177 | 1178 | Here's an example, 1179 | 1180 | ```nginx 1181 | 1182 | location /today { 1183 | set_local_today $today; 1184 | echo $today; 1185 | } 1186 | ``` 1187 | 1188 | then request `GET /today` will output something like 1189 | 1190 | ``` 1191 | 2011-08-16 1192 | ``` 1193 | 1194 | and yeah, the actual date you get here will vary every day ;) 1195 | 1196 | Behind the scene, this directive utilizes the `ngx_time` API in the Nginx core, so usually no syscall is involved due to the time caching mechanism in the Nginx core. 1197 | 1198 | [Back to TOC](#table-of-contents) 1199 | 1200 | set_formatted_gmt_time 1201 | ---------------------- 1202 | **syntax:** *set_formatted_gmt_time $res <time-format>* 1203 | 1204 | **default:** *no* 1205 | 1206 | **context:** *location, location if* 1207 | 1208 | **phase:** *rewrite* 1209 | 1210 | Set a formatted GMT time to variable `$res` (as the first argument) using the format string in the second argument. 1211 | 1212 | All the conversion specification notations in the standard C function `strftime` are supported, like `%Y` (for 4-digit years) and `%M` (for minutes in decimal). See for a complete list of conversion specification symbols. 1213 | 1214 | Below is an example: 1215 | 1216 | ```nginx 1217 | 1218 | location = /t { 1219 | set_formatted_gmt_time $timestr "%a %b %e %H:%M:%S %Y GMT"; 1220 | echo $timestr; 1221 | } 1222 | ``` 1223 | 1224 | Accessing `/t` yields the output 1225 | 1226 | ``` 1227 | Fri Dec 13 15:34:37 2013 GMT 1228 | ``` 1229 | 1230 | This directive was first added in the `0.23` release. 1231 | 1232 | See also [set_formatted_local_time](#set_formatted_local_time). 1233 | 1234 | [Back to TOC](#table-of-contents) 1235 | 1236 | set_formatted_local_time 1237 | ------------------------ 1238 | **syntax:** *set_formatted_local_time $res <time-format>* 1239 | 1240 | **default:** *no* 1241 | 1242 | **context:** *location, location if* 1243 | 1244 | **phase:** *rewrite* 1245 | 1246 | Set a formatted local time to variable `$res` (as the first argument) using the format string in the second argument. 1247 | 1248 | All the conversion specification notations in the standard C function `strftime` are supported, like `%Y` (for 4-digit years) and `%M` (for minutes in decimal). See for a complete list of conversion specification symbols. 1249 | 1250 | Below is an example: 1251 | 1252 | ```nginx 1253 | 1254 | location = /t { 1255 | set_formatted_local_time $timestr "%a %b %e %H:%M:%S %Y %Z"; 1256 | echo $timestr; 1257 | } 1258 | ``` 1259 | 1260 | Accessing `/t` yields the output 1261 | 1262 | ``` 1263 | Fri Dec 13 15:42:15 2013 PST 1264 | ``` 1265 | 1266 | This directive was first added in the `0.23` release. 1267 | 1268 | See also [set_formatted_gmt_time](#set_formatted_gmt_time). 1269 | 1270 | [Back to TOC](#table-of-contents) 1271 | 1272 | Caveats 1273 | ======= 1274 | 1275 | Do not use [$arg_PARAMETER](http://nginx.org/en/docs/http/ngx_http_core_module.html#var_arg_), [$cookie_COOKIE](http://nginx.org/en/docs/http/ngx_http_core_module.html#var_cookie_), [$http_HEADER](http://nginx.org/en/docs/http/ngx_http_core_module.html#var_http_) or other special variables defined in the Nginx core module as the target variable in this module's directives. For instance, 1276 | 1277 | ```nginx 1278 | 1279 | set_if_empty $arg_user 'foo'; # DO NOT USE THIS! 1280 | ``` 1281 | 1282 | may lead to segmentation faults. 1283 | 1284 | [Back to TOC](#table-of-contents) 1285 | 1286 | Installation 1287 | ============ 1288 | 1289 | This module is included and enabled by default in the [OpenResty bundle](http://openresty.org). If you want to install this module manually with your own Nginx source tarball, then follow the steps below: 1290 | 1291 | Grab the nginx source code from [nginx.org](http://nginx.org/), for example, 1292 | the version 1.13.6 (see [nginx compatibility](#compatibility)), and then build the source with this module: 1293 | 1294 | ```bash 1295 | 1296 | wget 'http://nginx.org/download/nginx-1.13.6.tar.gz' 1297 | tar -xzvf nginx-1.13.6.tar.gz 1298 | cd nginx-1.13.6/ 1299 | 1300 | # Here we assume you would install you nginx under /opt/nginx/. 1301 | ./configure --prefix=/opt/nginx \ 1302 | --with-http_ssl_module \ 1303 | --add-module=/path/to/ngx_devel_kit \ 1304 | --add-module=/path/to/set-misc-nginx-module 1305 | 1306 | make -j2 1307 | make install 1308 | ``` 1309 | 1310 | Download the latest version of the release tarball of this module from [set-misc-nginx-module file list](http://github.com/openresty/set-misc-nginx-module/tags), and the latest tarball for [ngx_devel_kit](https://github.com/simplresty/ngx_devel_kit) from its [file list](https://github.com/simplresty/ngx_devel_kit/tags). 1311 | 1312 | [Back to TOC](#table-of-contents) 1313 | 1314 | Building as a dynamic module 1315 | ---------------------------- 1316 | 1317 | Starting from NGINX 1.9.11, you can also compile this module as a dynamic module, by using the `--add-dynamic-module=PATH` option instead of `--add-module=PATH` on the 1318 | `./configure` command line above. And then you can explicitly load the module in your `nginx.conf` via the [load_module](http://nginx.org/en/docs/ngx_core_module.html#load_module) 1319 | directive, for example, 1320 | 1321 | ```nginx 1322 | load_module /path/to/modules/ndk_http_module.so; # assuming NDK is built as a dynamic module too 1323 | load_module /path/to/modules/ngx_http_set_misc_module.so; 1324 | ``` 1325 | 1326 | Also, this module is included and enabled by default in the [OpenResty bundle](http://openresty.org/). 1327 | 1328 | [Back to TOC](#table-of-contents) 1329 | 1330 | Compatibility 1331 | ============= 1332 | 1333 | The following versions of Nginx should work with this module: 1334 | 1335 | * **1.13.x** (last tested: 1.13.6) 1336 | * **1.12.x** 1337 | * **1.11.x** (last tested: 1.11.2) 1338 | * **1.10.x** 1339 | * **1.9.x** (last tested: 1.9.15) 1340 | * **1.8.x** 1341 | * **1.7.x** (last tested: 1.7.10) 1342 | * **1.6.x** 1343 | * **1.5.x** (last tested: 1.5.8) 1344 | * **1.4.x** (last tested: 1.4.4) 1345 | * **1.2.x** (last tested: 1.2.9) 1346 | * **1.1.x** (last tested: 1.1.5) 1347 | * **1.0.x** (last tested: 1.0.15) 1348 | * **0.9.x** (last tested: 0.9.4) 1349 | * **0.8.x** (last tested: 0.8.54) 1350 | * **0.7.x >= 0.7.46** (last tested: 0.7.68) 1351 | 1352 | If you find that any particular version of Nginx above 0.7.46 does not work with this module, please consider [reporting a bug](#report-bugs). 1353 | 1354 | [Back to TOC](#table-of-contents) 1355 | 1356 | Report Bugs 1357 | =========== 1358 | 1359 | Although a lot of effort has been put into testing and code tuning, there must be some serious bugs lurking somewhere in this module. So whenever you are bitten by any quirks, please don't hesitate to 1360 | 1361 | 1. send a bug report or even patches to the [openresty-en mailing list](https://groups.google.com/group/openresty-en), 1362 | 1. or create a ticket on the [issue tracking interface](http://github.com/openresty/set-misc-nginx-module/issues) provided by GitHub. 1363 | 1364 | [Back to TOC](#table-of-contents) 1365 | 1366 | Source Repository 1367 | ================= 1368 | 1369 | Available on github at [openresty/set-misc-nginx-module](http://github.com/openresty/set-misc-nginx-module). 1370 | 1371 | [Back to TOC](#table-of-contents) 1372 | 1373 | Changes 1374 | ======= 1375 | 1376 | The change logs for every release of this module can be obtained from the OpenResty bundle's change logs: 1377 | 1378 | 1379 | 1380 | [Back to TOC](#table-of-contents) 1381 | 1382 | Test Suite 1383 | ========== 1384 | 1385 | This module comes with a Perl-driven test suite. The [test cases](http://github.com/openresty/set-misc-nginx-module/tree/master/t/) are 1386 | [declarative](http://github.com/openresty/set-misc-nginx-module/blob/master/t/escape-uri.t) too. Thanks to the [Test::Nginx](http://search.cpan.org/perldoc?Test::Nginx) module in the Perl world. 1387 | 1388 | To run it on your side: 1389 | 1390 | ```bash 1391 | 1392 | $ PATH=/path/to/your/nginx-with-set-misc-module:$PATH prove -r t 1393 | ``` 1394 | 1395 | You need to terminate any Nginx processes before running the test suite if you have changed the Nginx server binary. 1396 | 1397 | Because a single nginx server (by default, `localhost:1984`) is used across all the test scripts (`.t` files), it's meaningless to run the test suite in parallel by specifying `-jN` when invoking the `prove` utility. 1398 | 1399 | [Back to TOC](#table-of-contents) 1400 | 1401 | Getting involved 1402 | ================ 1403 | 1404 | You'll be very welcomed to submit patches to the [author](#author) or just ask for a commit bit to the [source repository](#source-repository) on GitHub. 1405 | 1406 | [Back to TOC](#table-of-contents) 1407 | 1408 | Author 1409 | ====== 1410 | 1411 | Yichun Zhang (agentzh) *<agentzh@gmail.com>*, OpenResty Inc. 1412 | 1413 | This wiki page is also maintained by the author himself, and everybody is encouraged to improve this page as well. 1414 | 1415 | [Back to TOC](#table-of-contents) 1416 | 1417 | Copyright & License 1418 | =================== 1419 | 1420 | Copyright (C) 2009-2018, Yichun Zhang (章亦春) , OpenResty Inc. 1421 | 1422 | This module is licensed under the terms of the BSD license. 1423 | 1424 | Redistribution and use in source and binary forms, with or without 1425 | modification, are permitted provided that the following conditions 1426 | are met: 1427 | 1428 | * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 1429 | * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 1430 | 1431 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1432 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 1433 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 1434 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 1435 | HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 1436 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 1437 | TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 1438 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 1439 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 1440 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 1441 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 1442 | 1443 | [Back to TOC](#table-of-contents) 1444 | 1445 | See Also 1446 | ======== 1447 | * [Nginx Devel Kit](https://github.com/simpl/ngx_devel_kit) 1448 | * [The OpenResty bundle](http://openresty.org) 1449 | 1450 | [Back to TOC](#table-of-contents) 1451 | 1452 | -------------------------------------------------------------------------------- /config: -------------------------------------------------------------------------------- 1 | ngx_addon_name=ngx_http_set_misc_module 2 | 3 | if test -n "$ngx_module_link"; then 4 | if test -n "$NDK_SRCS"; then 5 | echo "found ngx_devel_kit for ngx_set_misc; looks good." 6 | else 7 | echo "error: ngx_devel_kit is required to build ngx_set_misc; please put it before ngx_set_misc." 1>&2 8 | exit 1 9 | fi 10 | else 11 | if echo $HTTP_MODULES | grep " ndk_http_module" > /dev/null; then 12 | echo "found ngx_devel_kit for ngx_set_misc; looks good." 13 | else 14 | echo "error: ngx_devel_kit is required to build ngx_set_misc; please put it before ngx_set_misc." 1>&2 15 | exit 1 16 | fi 17 | fi 18 | 19 | SET_MISC_SRCS=" \ 20 | $ngx_addon_dir/src/ngx_http_set_base32.c \ 21 | $ngx_addon_dir/src/ngx_http_set_default_value.c \ 22 | $ngx_addon_dir/src/ngx_http_set_hashed_upstream.c \ 23 | $ngx_addon_dir/src/ngx_http_set_quote_sql.c \ 24 | $ngx_addon_dir/src/ngx_http_set_quote_json.c \ 25 | $ngx_addon_dir/src/ngx_http_set_unescape_uri.c \ 26 | $ngx_addon_dir/src/ngx_http_set_misc_module.c \ 27 | $ngx_addon_dir/src/ngx_http_set_escape_uri.c \ 28 | $ngx_addon_dir/src/ngx_http_set_hash.c \ 29 | $ngx_addon_dir/src/ngx_http_set_local_today.c \ 30 | $ngx_addon_dir/src/ngx_http_set_hex.c \ 31 | $ngx_addon_dir/src/ngx_http_set_base64.c \ 32 | $ngx_addon_dir/src/ngx_http_set_base64url.c \ 33 | $ngx_addon_dir/src/ngx_http_set_random.c \ 34 | $ngx_addon_dir/src/ngx_http_set_secure_random.c \ 35 | $ngx_addon_dir/src/ngx_http_set_rotate.c 36 | " 37 | 38 | SET_MISC_DEPS=" \ 39 | $ngx_addon_dir/src/ddebug.h \ 40 | $ngx_addon_dir/src/ngx_http_set_default_value.h \ 41 | $ngx_addon_dir/src/ngx_http_set_hashed_upstream.h \ 42 | $ngx_addon_dir/src/ngx_http_set_quote_sql.h \ 43 | $ngx_addon_dir/src/ngx_http_set_quote_json.h \ 44 | $ngx_addon_dir/src/ngx_http_set_unescape_uri.h \ 45 | $ngx_addon_dir/src/ngx_http_set_escape_uri.h \ 46 | $ngx_addon_dir/src/ngx_http_set_hash.h \ 47 | $ngx_addon_dir/src/ngx_http_set_local_today.h \ 48 | $ngx_addon_dir/src/ngx_http_set_hex.h \ 49 | $ngx_addon_dir/src/ngx_http_set_base64url.h \ 50 | $ngx_addon_dir/src/ngx_http_set_base64.h \ 51 | $ngx_addon_dir/src/ngx_http_set_random.h \ 52 | $ngx_addon_dir/src/ngx_http_set_rotate.h \ 53 | $ngx_addon_dir/src/ngx_http_set_secure_random.h \ 54 | $ngx_addon_dir/src/ngx_http_set_misc_module.h \ 55 | " 56 | 57 | if [ $USE_OPENSSL = YES -o $MAIL_SSL = YES ]; then 58 | SET_MISC_DEPS="$SET_MISC_DEPS $ngx_addon_dir/src/ngx_http_set_hmac.h" 59 | SET_MISC_SRCS="$SET_MISC_SRCS $ngx_addon_dir/src/ngx_http_set_hmac.c" 60 | fi 61 | 62 | CFLAGS="$CFLAGS -DNDK_SET_VAR -DNDK_UPSTREAM_LIST" 63 | USE_SHA1=YES 64 | USE_MD5=YES 65 | 66 | if test -n "$ngx_module_link"; then 67 | ngx_module_type=HTTP 68 | ngx_module_name=$ngx_addon_name 69 | ngx_module_incs= 70 | ngx_module_deps="$SET_MISC_DEPS" 71 | ngx_module_srcs="$SET_MISC_SRCS" 72 | ngx_module_libs= 73 | 74 | . auto/module 75 | else 76 | HTTP_MODULES="$HTTP_MODULES $ngx_addon_name" 77 | NGX_ADDON_SRCS="$NGX_ADDON_SRCS $SET_MISC_SRCS" 78 | NGX_ADDON_DEPS="$NGX_ADDON_DEPS $SET_MISC_DEPS" 79 | fi 80 | -------------------------------------------------------------------------------- /src/ddebug.h: -------------------------------------------------------------------------------- 1 | #ifndef DDEBUG_H 2 | #define DDEBUG_H 3 | 4 | #include 5 | #include 6 | 7 | #if defined(DDEBUG) && (DDEBUG) 8 | 9 | # if (NGX_HAVE_VARIADIC_MACROS) 10 | 11 | # define dd(...) fprintf(stderr, "set_misc *** "); \ 12 | fprintf(stderr, __VA_ARGS__); \ 13 | fprintf(stderr, " at %s line %d.\n", __FILE__, __LINE__) 14 | 15 | # else 16 | 17 | #include 18 | #include 19 | 20 | #include 21 | 22 | static ngx_inline void 23 | dd(const char *fmt, ...) { 24 | } 25 | 26 | # endif 27 | 28 | #else 29 | 30 | # if (NGX_HAVE_VARIADIC_MACROS) 31 | 32 | # define dd(...) 33 | 34 | # else 35 | 36 | #include 37 | 38 | static ngx_inline void 39 | dd(const char *fmt, ...) { 40 | } 41 | 42 | # endif 43 | 44 | #endif 45 | 46 | #if defined(DDEBUG) && (DDEBUG) 47 | 48 | #define dd_check_read_event_handler(r) \ 49 | dd("r->read_event_handler = %s", \ 50 | r->read_event_handler == ngx_http_block_reading ? \ 51 | "ngx_http_block_reading" : \ 52 | r->read_event_handler == ngx_http_test_reading ? \ 53 | "ngx_http_test_reading" : \ 54 | r->read_event_handler == ngx_http_request_empty_handler ? \ 55 | "ngx_http_request_empty_handler" : "UNKNOWN") 56 | 57 | #define dd_check_write_event_handler(r) \ 58 | dd("r->write_event_handler = %s", \ 59 | r->write_event_handler == ngx_http_handler ? \ 60 | "ngx_http_handler" : \ 61 | r->write_event_handler == ngx_http_core_run_phases ? \ 62 | "ngx_http_core_run_phases" : \ 63 | r->write_event_handler == ngx_http_request_empty_handler ? \ 64 | "ngx_http_request_empty_handler" : "UNKNOWN") 65 | 66 | #else 67 | 68 | #define dd_check_read_event_handler(r) 69 | #define dd_check_write_event_handler(r) 70 | 71 | #endif 72 | 73 | #endif /* DDEBUG_H */ 74 | 75 | -------------------------------------------------------------------------------- /src/ngx_http_set_base32.c: -------------------------------------------------------------------------------- 1 | #ifndef DDEBUG 2 | #define DDEBUG 0 3 | #endif 4 | #include "ddebug.h" 5 | 6 | 7 | #include 8 | 9 | #include "ngx_http_set_base32.h" 10 | #include "ngx_http_set_misc_module.h" 11 | 12 | 13 | #define base32_encoded_length(len) ((((len)+4)/5)*8) 14 | #define base32_decoded_length(len) ((((len)+7)/8)*5) 15 | 16 | 17 | static void encode_base32(size_t slen, u_char *src, size_t *dlen, u_char *dst, 18 | ngx_flag_t padding, ngx_str_t *alphabet); 19 | static int decode_base32(size_t slen, u_char *src, size_t *dlen, u_char *dst, 20 | u_char *basis32); 21 | 22 | 23 | ngx_int_t 24 | ngx_http_set_misc_encode_base32(ngx_http_request_t *r, ngx_str_t *res, 25 | ngx_http_variable_value_t *v) 26 | { 27 | size_t len; 28 | u_char *p; 29 | u_char *src, *dst; 30 | 31 | ngx_http_set_misc_loc_conf_t *conf; 32 | 33 | conf = ngx_http_get_module_loc_conf(r, ngx_http_set_misc_module); 34 | 35 | len = base32_encoded_length(v->len); 36 | 37 | dd("estimated dst len: %d", (int) len); 38 | 39 | p = ngx_palloc(r->pool, len); 40 | if (p == NULL) { 41 | return NGX_ERROR; 42 | } 43 | 44 | src = v->data; dst = p; 45 | 46 | encode_base32(v->len, src, &len, dst, conf->base32_padding, 47 | &conf->base32_alphabet); 48 | 49 | res->data = p; 50 | res->len = len; 51 | 52 | dd("res (len %d): %.*s", (int) res->len, (int) res->len, res->data); 53 | 54 | return NGX_OK; 55 | } 56 | 57 | 58 | ngx_int_t 59 | ngx_http_set_misc_decode_base32(ngx_http_request_t *r, ngx_str_t *res, 60 | ngx_http_variable_value_t *v) 61 | { 62 | size_t len; 63 | u_char *p; 64 | u_char *src, *dst; 65 | int ret; 66 | 67 | ngx_http_set_misc_loc_conf_t *conf; 68 | 69 | conf = ngx_http_get_module_loc_conf(r, ngx_http_set_misc_module); 70 | 71 | len = base32_decoded_length(v->len); 72 | 73 | dd("estimated dst len: %d", (int) len); 74 | 75 | p = ngx_palloc(r->pool, len); 76 | if (p == NULL) { 77 | return NGX_ERROR; 78 | } 79 | 80 | src = v->data; dst = p; 81 | 82 | ret = decode_base32(v->len, src, &len, dst, conf->basis32); 83 | 84 | if (ret == 0 /* OK */) { 85 | res->data = p; 86 | res->len = len; 87 | 88 | return NGX_OK; 89 | } 90 | 91 | /* failed to decode */ 92 | 93 | res->data = NULL; 94 | res->len = 0; 95 | 96 | return NGX_OK; 97 | } 98 | 99 | 100 | /* See the implementation in src/core/ngx_string.c's 101 | * ngx_(encode|decode)_base64() for details. */ 102 | 103 | static void 104 | encode_base32(size_t slen, u_char *src, size_t *dlen, u_char *dst, 105 | ngx_flag_t padding, ngx_str_t *alphabet) 106 | { 107 | unsigned char *basis32 = alphabet->data; 108 | 109 | size_t len; 110 | u_char *s; 111 | u_char *d; 112 | 113 | len = slen; 114 | s = src; 115 | d = dst; 116 | 117 | while (len > 4) { 118 | *d++ = basis32[s[0] >> 3]; 119 | *d++ = basis32[((s[0] & 0x07) << 2) | (s[1] >> 6)]; 120 | *d++ = basis32[(s[1] >> 1) & 0x1f]; 121 | *d++ = basis32[((s[1] & 1) << 4) | (s[2] >> 4)]; 122 | *d++ = basis32[((s[2] & 0x0f) << 1) | (s[3] >> 7)]; 123 | *d++ = basis32[(s[3] >> 2) & 0x1f]; 124 | *d++ = basis32[((s[3] & 0x03) << 3) | (s[4] >> 5)]; 125 | *d++ = basis32[s[4] & 0x1f]; 126 | 127 | s += 5; 128 | len -= 5; 129 | } 130 | 131 | if (len) { 132 | *d++ = basis32[s[0] >> 3]; 133 | 134 | if (len == 1) { 135 | /* 1 byte left */ 136 | *d++ = basis32[(s[0] & 0x07) << 2]; 137 | 138 | /* pad six '='s to the end */ 139 | if (padding) { 140 | *d++ = '='; 141 | *d++ = '='; 142 | *d++ = '='; 143 | *d++ = '='; 144 | *d++ = '='; 145 | } 146 | 147 | } else { 148 | *d++ = basis32[((s[0] & 0x07) << 2) | (s[1] >> 6)]; 149 | *d++ = basis32[(s[1] >> 1) & 0x1f]; 150 | 151 | if (len == 2) { 152 | /* 2 bytes left */ 153 | *d++ = basis32[(s[1] & 1) << 4]; 154 | 155 | /* pad four '='s to the end */ 156 | if (padding) { 157 | *d++ = '='; 158 | *d++ = '='; 159 | *d++ = '='; 160 | } 161 | 162 | } else { 163 | *d++ = basis32[((s[1] & 1) << 4) | (s[2] >> 4)]; 164 | 165 | if (len == 3) { 166 | /* 3 bytes left */ 167 | *d++ = basis32[(s[2] & 0x0f) << 1]; 168 | 169 | if (padding) { 170 | /* pad three '='s to the end */ 171 | *d++ = '='; 172 | *d++ = '='; 173 | } 174 | 175 | } else { 176 | /* 4 bytes left */ 177 | *d++ = basis32[((s[2] & 0x0f) << 1) | (s[3] >> 7)]; 178 | *d++ = basis32[(s[3] >> 2) & 0x1f]; 179 | *d++ = basis32[(s[3] & 0x03) << 3]; 180 | 181 | /* pad one '=' to the end */ 182 | } 183 | } 184 | } 185 | 186 | if (padding) { 187 | *d++ = '='; 188 | } 189 | } 190 | 191 | *dlen = (size_t) (d - dst); 192 | } 193 | 194 | 195 | static int 196 | decode_base32(size_t slen, u_char *src, size_t *dlen, u_char *dst, 197 | u_char *basis32) 198 | { 199 | size_t len, mod; 200 | u_char *s = src; 201 | u_char *d = dst; 202 | 203 | for (len = 0; len < slen; len++) { 204 | if (s[len] == '=') { 205 | break; 206 | } 207 | 208 | if (basis32[s[len]] == 77) { 209 | return -1; 210 | } 211 | } 212 | 213 | mod = len % 8; 214 | 215 | if (mod == 1 || mod == 3 || mod == 6) { 216 | /* bad Base32 digest length */ 217 | return -1; 218 | } 219 | 220 | while (len > 7) { 221 | *d++ = (basis32[s[0]] << 3) | ((basis32[s[1]] >> 2) & 0x07); 222 | 223 | *d++ = ((basis32[s[1]] & 0x03) << 6) | (basis32[s[2]] << 1) | 224 | ((basis32[s[3]] >> 4) & 1); 225 | 226 | *d++ = ((basis32[s[3]] & 0x0f) << 4) | ((basis32[s[4]] >> 1) & 0x0f); 227 | 228 | *d++ = ((basis32[s[4]] & 1) << 7) | ((basis32[s[5]] & 0x1f) << 2) | 229 | ((basis32[s[6]] >> 3) & 0x03); 230 | *d++ = ((basis32[s[6]] & 0x07) << 5) | (basis32[s[7]] & 0x1f); 231 | 232 | s += 8; 233 | len -= 8; 234 | } 235 | 236 | if (len) { 237 | /* 2 bytes left */ 238 | *d++ = (basis32[s[0]] << 3) | ((basis32[s[1]] >> 2) & 0x07); 239 | 240 | if (len > 2) { 241 | /* 4 bytes left */ 242 | *d++ = ((basis32[s[1]] & 0x03) << 6) | ((basis32[s[2]] & 0x1f) << 1) 243 | | ((basis32[s[3]] >> 4) & 1); 244 | 245 | if (len > 4) { 246 | /* 5 bytes left */ 247 | *d++ = ((basis32[s[3]] & 0x0f) << 4) | 248 | ((basis32[s[4]] >> 1) & 0x0f); 249 | 250 | if (len > 5) { 251 | /* 7 bytes left */ 252 | *d++ = ((basis32[s[4]] & 1) << 7) | 253 | ((basis32[s[5]] & 0x1f) << 2) | 254 | ((basis32[s[6]] >> 3) & 0x03); 255 | } 256 | } 257 | } 258 | } 259 | 260 | *dlen = (size_t) (d - dst); 261 | 262 | return 0; 263 | } 264 | -------------------------------------------------------------------------------- /src/ngx_http_set_base32.h: -------------------------------------------------------------------------------- 1 | #ifndef NGX_HTTP_SET_BASE32 2 | #define NGX_HTTP_SET_BASE32 3 | 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | 10 | ngx_int_t ngx_http_set_misc_encode_base32(ngx_http_request_t *r, 11 | ngx_str_t *res, ngx_http_variable_value_t *v); 12 | 13 | ngx_int_t ngx_http_set_misc_decode_base32(ngx_http_request_t *r, 14 | ngx_str_t *res, ngx_http_variable_value_t *v); 15 | 16 | 17 | #endif /* NGX_HTTP_SET_BASE32 */ 18 | 19 | -------------------------------------------------------------------------------- /src/ngx_http_set_base64.c: -------------------------------------------------------------------------------- 1 | #ifndef DDEBUG 2 | #define DDEBUG 0 3 | #endif 4 | #include "ddebug.h" 5 | 6 | #include 7 | #include "ngx_http_set_base64.h" 8 | 9 | 10 | ngx_int_t 11 | ngx_http_set_misc_set_decode_base64(ngx_http_request_t *r, ngx_str_t *res, 12 | ngx_http_variable_value_t *v) 13 | { 14 | ngx_str_t src; 15 | 16 | src.len = v->len; 17 | src.data = v->data; 18 | 19 | res->len = ngx_base64_decoded_length(v->len); 20 | ndk_palloc_re(res->data, r->pool, res->len); 21 | 22 | if (ngx_decode_base64(res, &src) != NGX_OK) { 23 | ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, 24 | "set_decode_base64: invalid value"); 25 | return NGX_ERROR; 26 | } 27 | 28 | return NGX_OK; 29 | } 30 | 31 | 32 | ngx_int_t 33 | ngx_http_set_misc_set_encode_base64(ngx_http_request_t *r, ngx_str_t *res, 34 | ngx_http_variable_value_t *v) 35 | { 36 | ngx_str_t src; 37 | 38 | src.len = v->len; 39 | src.data = v->data; 40 | 41 | res->len = ngx_base64_encoded_length(v->len); 42 | ndk_palloc_re(res->data, r->pool, res->len); 43 | 44 | ngx_encode_base64(res, &src); 45 | 46 | return NGX_OK; 47 | } 48 | 49 | -------------------------------------------------------------------------------- /src/ngx_http_set_base64.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | ngx_int_t ngx_http_set_misc_set_encode_base64(ngx_http_request_t *r, 6 | ngx_str_t *res, ngx_http_variable_value_t *v); 7 | 8 | ngx_int_t ngx_http_set_misc_set_decode_base64(ngx_http_request_t *r, 9 | ngx_str_t *res, ngx_http_variable_value_t *v); 10 | 11 | -------------------------------------------------------------------------------- /src/ngx_http_set_base64url.c: -------------------------------------------------------------------------------- 1 | #ifndef DDEBUG 2 | #define DDEBUG 0 3 | #endif 4 | #include "ddebug.h" 5 | 6 | #include 7 | #include "ngx_http_set_base64url.h" 8 | 9 | 10 | ngx_int_t 11 | ngx_http_set_misc_set_decode_base64url(ngx_http_request_t *r, ngx_str_t *res, 12 | ngx_http_variable_value_t *v) 13 | { 14 | 15 | ngx_str_t src; 16 | 17 | src.len = v->len; 18 | src.data = v->data; 19 | 20 | res->len = ngx_base64_decoded_length(v->len); 21 | ndk_palloc_re(res->data, r->pool, res->len); 22 | 23 | if (ngx_decode_base64url(res, &src) != NGX_OK) { 24 | ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, 25 | "set_decode_base64url: invalid value"); 26 | return NGX_ERROR; 27 | } 28 | 29 | return NGX_OK; 30 | } 31 | 32 | 33 | ngx_int_t 34 | ngx_http_set_misc_set_encode_base64url(ngx_http_request_t *r, ngx_str_t *res, 35 | ngx_http_variable_value_t *v) 36 | { 37 | 38 | ngx_str_t src; 39 | 40 | src.len = v->len; 41 | src.data = v->data; 42 | 43 | res->len = ngx_base64_encoded_length(v->len); 44 | ndk_palloc_re(res->data, r->pool, res->len); 45 | 46 | ngx_encode_base64url(res, &src); 47 | 48 | return NGX_OK; 49 | } 50 | 51 | -------------------------------------------------------------------------------- /src/ngx_http_set_base64url.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | ngx_int_t ngx_http_set_misc_set_encode_base64url(ngx_http_request_t *r, 6 | ngx_str_t *res, ngx_http_variable_value_t *v); 7 | 8 | ngx_int_t ngx_http_set_misc_set_decode_base64url(ngx_http_request_t *r, 9 | ngx_str_t *res, ngx_http_variable_value_t *v); 10 | 11 | -------------------------------------------------------------------------------- /src/ngx_http_set_default_value.c: -------------------------------------------------------------------------------- 1 | #ifndef DDEBUG 2 | #define DDEBUG 0 3 | #endif 4 | #include "ddebug.h" 5 | 6 | #include 7 | #include "ngx_http_set_default_value.h" 8 | 9 | 10 | ngx_int_t 11 | ngx_http_set_misc_set_if_empty(ngx_http_request_t *r, ngx_str_t *res, 12 | ngx_http_variable_value_t *v) 13 | { 14 | ngx_http_variable_value_t *cur_v, *default_v; 15 | 16 | cur_v = &v[0]; 17 | default_v = &v[1]; 18 | 19 | if (cur_v->not_found || cur_v->len == 0) { 20 | res->data = default_v->data; 21 | res->len = default_v->len; 22 | 23 | return NGX_OK; 24 | } 25 | 26 | res->data = cur_v->data; 27 | res->len = cur_v->len; 28 | 29 | return NGX_OK; 30 | } 31 | 32 | 33 | char * 34 | ngx_http_set_if_empty(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) 35 | { 36 | ngx_str_t *value; 37 | ndk_set_var_t filter; 38 | 39 | value = cf->args->elts; 40 | 41 | filter.type = NDK_SET_VAR_MULTI_VALUE; 42 | filter.func = (void *) ngx_http_set_misc_set_if_empty; 43 | filter.size = 2; 44 | filter.data = NULL; 45 | 46 | return ndk_set_var_multi_value_core(cf, &value[1], &value[1], &filter); 47 | } 48 | 49 | -------------------------------------------------------------------------------- /src/ngx_http_set_default_value.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #ifndef NGX_HTTP_SET_DEFAULT_VALUE 6 | #define NGX_HTTP_SET_DEFAULT_VALUE 7 | 8 | 9 | char *ngx_http_set_if_empty(ngx_conf_t *cf, ngx_command_t *cmd, 10 | void *conf); 11 | ngx_int_t ngx_http_set_misc_set_if_empty(ngx_http_request_t *r, 12 | ngx_str_t *res, ngx_http_variable_value_t *v); 13 | 14 | 15 | #endif /* NGX_HTTP_SET_DEFAULT_VALUE */ 16 | -------------------------------------------------------------------------------- /src/ngx_http_set_escape_uri.c: -------------------------------------------------------------------------------- 1 | #ifndef DDEBUG 2 | #define DDEBUG 0 3 | #endif 4 | #include "ddebug.h" 5 | 6 | #include 7 | #include "ngx_http_set_escape_uri.h" 8 | #include "ngx_string.h" 9 | 10 | 11 | static uintptr_t ngx_escape_uri_patched(u_char *dst, u_char *src, size_t size, 12 | ngx_uint_t type); 13 | 14 | 15 | ngx_int_t 16 | ngx_http_set_misc_escape_uri(ngx_http_request_t *r, ngx_str_t *res, 17 | ngx_http_variable_value_t *v) 18 | { 19 | size_t len; 20 | uintptr_t escape; 21 | u_char *src, *dst; 22 | 23 | if (v->len == 0) { 24 | res->len = 0; 25 | res->data = NULL; 26 | return NGX_OK; 27 | } 28 | 29 | src = v->data; 30 | 31 | dd("before escape:%.*s", v->len, v->data); 32 | escape = 2 * ngx_escape_uri_patched(NULL, src, v->len, NGX_ESCAPE_URI); 33 | /* len = v->len + 2 * ngx_escape_uri(NULL, src, v->len, NGX_ESCAPE_URI); */ 34 | len = escape + v->len; 35 | dd("escaped string len:%zu", len); 36 | 37 | dst = ngx_palloc(r->pool, len); 38 | 39 | if (dst == NULL) { 40 | return NGX_ERROR; 41 | } 42 | 43 | if (escape == 0) { 44 | ngx_memcpy(dst, src, len); 45 | dd("escape == 0"); 46 | 47 | } else { 48 | ngx_escape_uri_patched(dst, src, v->len, NGX_ESCAPE_URI); 49 | } 50 | 51 | res->data = dst; 52 | res->len = len; 53 | 54 | dd("after eacape:%.*s", (int) res->len, res->data); 55 | 56 | return NGX_OK; 57 | } 58 | 59 | 60 | static uintptr_t 61 | ngx_escape_uri_patched(u_char *dst, u_char *src, size_t size, ngx_uint_t type) 62 | { 63 | ngx_uint_t n; 64 | uint32_t *escape; 65 | static u_char hex[] = "0123456789ABCDEF"; 66 | 67 | /* " ", "#", "%", "?", %00-%1F, %7F-%FF */ 68 | 69 | static uint32_t uri[] = { 70 | 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ 71 | 72 | /* ?>=< ;:98 7654 3210 /.-, +*)( '&%$ #"! */ 73 | 0xfc00886d, /* 1111 1100 0000 0000 1000 1000 0110 1101 */ 74 | 75 | /* _^]\ [ZYX WVUT SRQP ONML KJIH GFED CBA@ */ 76 | 0x78000000, /* 0111 1000 0000 0000 0000 0000 0000 0000 */ 77 | 78 | /* ~}| {zyx wvut srqp onml kjih gfed cba` */ 79 | 0xa8000000, /* 1010 1000 0000 0000 0000 0000 0000 0000 */ 80 | 81 | 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ 82 | 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ 83 | 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ 84 | 0xffffffff /* 1111 1111 1111 1111 1111 1111 1111 1111 */ 85 | }; 86 | 87 | /* " ", "#", "%", "+", "?", %00-%1F, %7F-%FF */ 88 | 89 | static uint32_t args[] = { 90 | 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ 91 | 92 | /* ?>=< ;:98 7654 3210 /.-, +*)( '&%$ #"! */ 93 | 0x80000829, /* 1000 0000 0000 0000 0000 1000 0010 1001 */ 94 | 95 | /* _^]\ [ZYX WVUT SRQP ONML KJIH GFED CBA@ */ 96 | 0x00000000, /* 0000 0000 0000 0000 0000 0000 0000 0000 */ 97 | 98 | /* ~}| {zyx wvut srqp onml kjih gfed cba` */ 99 | 0x80000000, /* 1000 0000 0000 0000 0000 0000 0000 0000 */ 100 | 101 | 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ 102 | 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ 103 | 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ 104 | 0xffffffff /* 1111 1111 1111 1111 1111 1111 1111 1111 */ 105 | }; 106 | 107 | /* " ", "#", """, "%", "'", %00-%1F, %7F-%FF */ 108 | 109 | static uint32_t html[] = { 110 | 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ 111 | 112 | /* ?>=< ;:98 7654 3210 /.-, +*)( '&%$ #"! */ 113 | 0x000000ad, /* 0000 0000 0000 0000 0000 0000 1010 1101 */ 114 | 115 | /* _^]\ [ZYX WVUT SRQP ONML KJIH GFED CBA@ */ 116 | 0x00000000, /* 0000 0000 0000 0000 0000 0000 0000 0000 */ 117 | 118 | /* ~}| {zyx wvut srqp onml kjih gfed cba` */ 119 | 0x80000000, /* 1000 0000 0000 0000 0000 0000 0000 0000 */ 120 | 121 | 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ 122 | 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ 123 | 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ 124 | 0xffffffff /* 1111 1111 1111 1111 1111 1111 1111 1111 */ 125 | }; 126 | 127 | /* " ", """, "%", "'", %00-%1F, %7F-%FF */ 128 | 129 | static uint32_t refresh[] = { 130 | 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ 131 | 132 | /* ?>=< ;:98 7654 3210 /.-, +*)( '&%$ #"! */ 133 | 0x00000085, /* 0000 0000 0000 0000 0000 0000 1000 0101 */ 134 | 135 | /* _^]\ [ZYX WVUT SRQP ONML KJIH GFED CBA@ */ 136 | 0x00000000, /* 0000 0000 0000 0000 0000 0000 0000 0000 */ 137 | 138 | /* ~}| {zyx wvut srqp onml kjih gfed cba` */ 139 | 0x80000000, /* 1000 0000 0000 0000 0000 0000 0000 0000 */ 140 | 141 | 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ 142 | 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ 143 | 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ 144 | 0xffffffff /* 1111 1111 1111 1111 1111 1111 1111 1111 */ 145 | }; 146 | 147 | /* " ", "%", %00-%1F */ 148 | 149 | static uint32_t memcached[] = { 150 | 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ 151 | 152 | /* ?>=< ;:98 7654 3210 /.-, +*)( '&%$ #"! */ 153 | 0x00000021, /* 0000 0000 0000 0000 0000 0000 0010 0001 */ 154 | 155 | /* _^]\ [ZYX WVUT SRQP ONML KJIH GFED CBA@ */ 156 | 0x00000000, /* 0000 0000 0000 0000 0000 0000 0000 0000 */ 157 | 158 | /* ~}| {zyx wvut srqp onml kjih gfed cba` */ 159 | 0x00000000, /* 0000 0000 0000 0000 0000 0000 0000 0000 */ 160 | 161 | 0x00000000, /* 0000 0000 0000 0000 0000 0000 0000 0000 */ 162 | 0x00000000, /* 0000 0000 0000 0000 0000 0000 0000 0000 */ 163 | 0x00000000, /* 0000 0000 0000 0000 0000 0000 0000 0000 */ 164 | 0x00000000, /* 0000 0000 0000 0000 0000 0000 0000 0000 */ 165 | }; 166 | 167 | /* mail_auth is the same as memcached */ 168 | 169 | static uint32_t *map[] = 170 | { uri, args, html, refresh, memcached, memcached }; 171 | 172 | 173 | escape = map[type]; 174 | 175 | if (dst == NULL) { 176 | 177 | /* find the number of the characters to be escaped */ 178 | 179 | n = 0; 180 | 181 | while (size) { 182 | if (escape[*src >> 5] & (1 << (*src & 0x1f))) { 183 | n++; 184 | } 185 | 186 | src++; 187 | size--; 188 | } 189 | 190 | return (uintptr_t) n; 191 | } 192 | 193 | while (size) { 194 | if (escape[*src >> 5] & (1 << (*src & 0x1f))) { 195 | *dst++ = '%'; 196 | *dst++ = hex[*src >> 4]; 197 | *dst++ = hex[*src & 0xf]; 198 | src++; 199 | 200 | } else { 201 | *dst++ = *src++; 202 | } 203 | 204 | size--; 205 | } 206 | 207 | return (uintptr_t) dst; 208 | } 209 | 210 | 211 | -------------------------------------------------------------------------------- /src/ngx_http_set_escape_uri.h: -------------------------------------------------------------------------------- 1 | #ifndef NGX_HTTP_SET_ESCAPE_URI 2 | #define NGX_HTTP_SET_ESCAPE_URI 3 | 4 | 5 | ngx_int_t 6 | ngx_http_set_misc_escape_uri(ngx_http_request_t *r, ngx_str_t *res, 7 | ngx_http_variable_value_t *v); 8 | 9 | 10 | #endif /* NGX_HTTP_SET_ESCAPE_URI */ 11 | -------------------------------------------------------------------------------- /src/ngx_http_set_hash.c: -------------------------------------------------------------------------------- 1 | #ifndef DDEBUG 2 | #define DDEBUG 0 3 | #endif 4 | #include "ddebug.h" 5 | 6 | #include "ngx_http_set_hash.h" 7 | 8 | #if NGX_HAVE_SHA1 9 | #include "ngx_sha1.h" 10 | 11 | #ifndef SHA_DIGEST_LENGTH 12 | #define SHA_DIGEST_LENGTH 20 13 | #endif 14 | 15 | #endif 16 | 17 | #include "ngx_md5.h" 18 | 19 | 20 | #ifndef MD5_DIGEST_LENGTH 21 | #define MD5_DIGEST_LENGTH 16 22 | #endif 23 | 24 | enum { 25 | #if NGX_HAVE_SHA1 26 | SHA_HEX_LENGTH = SHA_DIGEST_LENGTH * 2, 27 | #endif 28 | MD5_HEX_LENGTH = MD5_DIGEST_LENGTH * 2 29 | }; 30 | 31 | 32 | #if NGX_HAVE_SHA1 33 | ngx_int_t 34 | ngx_http_set_misc_set_sha1(ngx_http_request_t *r, ngx_str_t *res, 35 | ngx_http_variable_value_t *v) 36 | { 37 | u_char *p; 38 | ngx_sha1_t sha; 39 | u_char sha_buf[SHA_DIGEST_LENGTH]; 40 | 41 | p = ngx_palloc(r->pool, SHA_HEX_LENGTH); 42 | if (p == NULL) { 43 | return NGX_ERROR; 44 | } 45 | 46 | ngx_sha1_init(&sha); 47 | ngx_sha1_update(&sha, v->data, v->len); 48 | ngx_sha1_final(sha_buf, &sha); 49 | 50 | ngx_hex_dump(p, sha_buf, sizeof(sha_buf)); 51 | 52 | res->data = p; 53 | res->len = SHA_HEX_LENGTH; 54 | 55 | return NGX_OK; 56 | } 57 | #endif 58 | 59 | 60 | ngx_int_t 61 | ngx_http_set_misc_set_md5(ngx_http_request_t *r, ngx_str_t *res, 62 | ngx_http_variable_value_t *v) 63 | { 64 | u_char *p; 65 | ngx_md5_t md5; 66 | u_char md5_buf[MD5_DIGEST_LENGTH]; 67 | 68 | p = ngx_palloc(r->pool, MD5_HEX_LENGTH); 69 | if (p == NULL) { 70 | return NGX_ERROR; 71 | } 72 | 73 | ngx_md5_init(&md5); 74 | ngx_md5_update(&md5, v->data, v->len); 75 | ngx_md5_final(md5_buf, &md5); 76 | 77 | ngx_hex_dump(p, md5_buf, sizeof(md5_buf)); 78 | 79 | res->data = p; 80 | res->len = MD5_HEX_LENGTH; 81 | 82 | return NGX_OK; 83 | } 84 | -------------------------------------------------------------------------------- /src/ngx_http_set_hash.h: -------------------------------------------------------------------------------- 1 | #ifndef NGX_HTTP_SET_HASH_H 2 | #define NGX_HTTP_SET_HASH_H 3 | 4 | 5 | #include "ngx_http_set_misc_module.h" 6 | 7 | 8 | ngx_int_t ngx_http_set_misc_set_sha1(ngx_http_request_t *r, 9 | ngx_str_t *res, ngx_http_variable_value_t *v); 10 | 11 | 12 | ngx_int_t ngx_http_set_misc_set_md5(ngx_http_request_t *r, 13 | ngx_str_t *res, ngx_http_variable_value_t *v); 14 | 15 | #endif /* NGX_HTTP_SET_HASH_H */ 16 | -------------------------------------------------------------------------------- /src/ngx_http_set_hashed_upstream.c: -------------------------------------------------------------------------------- 1 | #ifndef DDEBUG 2 | #define DDEBUG 0 3 | #endif 4 | #include "ddebug.h" 5 | 6 | #include "ngx_http_set_hashed_upstream.h" 7 | 8 | 9 | ngx_uint_t 10 | ngx_http_set_misc_apply_distribution(ngx_log_t *log, ngx_uint_t hash, 11 | ndk_upstream_list_t *ul, ngx_http_set_misc_distribution_t type) 12 | { 13 | switch (type) { 14 | case ngx_http_set_misc_distribution_modula: 15 | return (uint32_t) hash % (uint32_t) ul->nelts; 16 | 17 | default: 18 | ngx_log_error(NGX_LOG_ERR, log, 0, "apply_distribution: " 19 | "unknown distribution: %d", type); 20 | 21 | return 0; 22 | } 23 | 24 | /* impossible to reach here */ 25 | } 26 | 27 | 28 | ngx_int_t 29 | ngx_http_set_misc_set_hashed_upstream(ngx_http_request_t *r, ngx_str_t *res, 30 | ngx_http_variable_value_t *v, void *data) 31 | { 32 | ngx_str_t **u; 33 | ndk_upstream_list_t *ul = data; 34 | ngx_str_t ulname; 35 | ngx_uint_t hash, index; 36 | ngx_http_variable_value_t *key; 37 | 38 | if (ul == NULL) { 39 | ulname.data = v->data; 40 | ulname.len = v->len; 41 | 42 | dd("ulname: %.*s", (int) ulname.len, ulname.data); 43 | 44 | ul = ndk_get_upstream_list(ndk_http_get_main_conf(r), 45 | ulname.data, ulname.len); 46 | 47 | if (ul == NULL) { 48 | ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, 49 | "set_hashed_upstream: upstream list \"%V\" " 50 | "not defined yet", &ulname); 51 | return NGX_ERROR; 52 | } 53 | 54 | key = v + 1; 55 | 56 | } else { 57 | key = v; 58 | } 59 | 60 | if (ul->nelts == 0) { 61 | res->data = NULL; 62 | res->len = 0; 63 | 64 | return NGX_OK; 65 | } 66 | 67 | u = ul->elts; 68 | 69 | dd("upstream list: %d upstreams found", (int) ul->nelts); 70 | 71 | if (ul->nelts == 1) { 72 | dd("only one upstream found in the list"); 73 | 74 | res->data = u[0]->data; 75 | res->len = u[0]->len; 76 | 77 | return NGX_OK; 78 | } 79 | 80 | dd("key: \"%.*s\"", key->len, key->data); 81 | 82 | hash = ngx_hash_key_lc(key->data, key->len); 83 | 84 | index = ngx_http_set_misc_apply_distribution(r->connection->log, hash, ul, 85 | ngx_http_set_misc_distribution_modula); 86 | 87 | res->data = u[index]->data; 88 | res->len = u[index]->len; 89 | 90 | return NGX_OK; 91 | } 92 | 93 | 94 | char * 95 | ngx_http_set_hashed_upstream(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) 96 | { 97 | ngx_str_t *value; 98 | ndk_set_var_t filter; 99 | ngx_uint_t n; 100 | ngx_str_t *var; 101 | ngx_str_t *ulname; 102 | ndk_upstream_list_t *ul; 103 | ngx_str_t *v; 104 | 105 | value = cf->args->elts; 106 | 107 | var = &value[1]; 108 | ulname = &value[2]; 109 | 110 | n = ngx_http_script_variables_count(ulname); 111 | 112 | filter.func = (void *) ngx_http_set_misc_set_hashed_upstream; 113 | 114 | if (n) { 115 | /* upstream list name contains variables */ 116 | v = &value[2]; 117 | filter.size = 2; 118 | filter.data = NULL; 119 | filter.type = NDK_SET_VAR_MULTI_VALUE_DATA; 120 | 121 | return ndk_set_var_multi_value_core(cf, var, v, &filter); 122 | } 123 | 124 | ul = ndk_get_upstream_list(ndk_http_conf_get_main_conf(cf), 125 | ulname->data, ulname->len); 126 | if (ul == NULL) { 127 | ngx_log_error(NGX_LOG_ERR, cf->log, 0, 128 | "set_hashed_upstream: upstream list \"%V\" " 129 | "not defined yet", ulname); 130 | return NGX_CONF_ERROR; 131 | } 132 | 133 | v = &value[3]; 134 | 135 | filter.size = 1; 136 | filter.data = ul; 137 | filter.type = NDK_SET_VAR_VALUE_DATA; 138 | 139 | return ndk_set_var_value_core(cf, var, v, &filter); 140 | } 141 | 142 | -------------------------------------------------------------------------------- /src/ngx_http_set_hashed_upstream.h: -------------------------------------------------------------------------------- 1 | #ifndef NGX_HTTP_SET_HASHED_UPSTREAM 2 | #define NGX_HTTP_SET_HASHED_UPSTREAM 3 | 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | 11 | typedef enum { 12 | ngx_http_set_misc_distribution_modula, 13 | ngx_http_set_misc_distribution_random /* XXX not used */ 14 | } ngx_http_set_misc_distribution_t; 15 | 16 | 17 | ngx_uint_t ngx_http_set_misc_apply_distribution(ngx_log_t *log, ngx_uint_t hash, 18 | ndk_upstream_list_t *ul, ngx_http_set_misc_distribution_t type); 19 | 20 | char *ngx_http_set_hashed_upstream(ngx_conf_t *cf, 21 | ngx_command_t *cmd, void *conf); 22 | 23 | ngx_int_t ngx_http_set_misc_set_hashed_upstream(ngx_http_request_t *r, 24 | ngx_str_t *res, ngx_http_variable_value_t *v, void *data); 25 | 26 | 27 | #endif /* NGX_HTTP_SET_HASHED_UPSTREAM */ 28 | -------------------------------------------------------------------------------- /src/ngx_http_set_hex.c: -------------------------------------------------------------------------------- 1 | #ifndef DDEBUG 2 | #define DDEBUG 0 3 | #endif 4 | #include "ddebug.h" 5 | 6 | #include 7 | #include "ngx_http_set_hex.h" 8 | 9 | 10 | ngx_int_t 11 | ngx_http_set_misc_set_decode_hex(ngx_http_request_t *r, ngx_str_t *res, 12 | ngx_http_variable_value_t *v) 13 | { 14 | u_char *p; 15 | ngx_int_t n; 16 | ngx_uint_t i; 17 | size_t len; 18 | 19 | if (v->len % 2 != 0) { 20 | ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, 21 | "set_decode_hex: invalid value"); 22 | return NGX_ERROR; 23 | } 24 | 25 | p = v->data; 26 | len = v->len >> 1; 27 | 28 | res->data = ngx_palloc(r->pool, len); 29 | if (res->data == NULL) { 30 | return NGX_ERROR; 31 | } 32 | 33 | for (i = 0; i < len; i++) { 34 | n = ngx_hextoi(p, 2); 35 | if (n == NGX_ERROR || n > 255) { 36 | ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, 37 | "set_decode_hex: invalid value"); 38 | return NGX_ERROR; 39 | } 40 | 41 | p += 2; 42 | res->data[i] = (u_char) n; 43 | } 44 | 45 | res->len = len; 46 | return NGX_OK; 47 | } 48 | 49 | 50 | ngx_int_t 51 | ngx_http_set_misc_set_encode_hex(ngx_http_request_t *r, ngx_str_t *res, 52 | ngx_http_variable_value_t *v) 53 | { 54 | res->len = v->len << 1; 55 | res->data = ngx_palloc(r->pool, res->len); 56 | if (res->data == NULL) { 57 | return NGX_ERROR; 58 | } 59 | 60 | ngx_hex_dump(res->data, v->data, v->len); 61 | return NGX_OK; 62 | } 63 | -------------------------------------------------------------------------------- /src/ngx_http_set_hex.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | ngx_int_t ngx_http_set_misc_set_decode_hex(ngx_http_request_t *r, 6 | ngx_str_t *res, ngx_http_variable_value_t *v); 7 | 8 | ngx_int_t ngx_http_set_misc_set_encode_hex(ngx_http_request_t *r, 9 | ngx_str_t *res, ngx_http_variable_value_t *v); 10 | -------------------------------------------------------------------------------- /src/ngx_http_set_hmac.c: -------------------------------------------------------------------------------- 1 | #ifndef DDEBUG 2 | #define DDEBUG 0 3 | #endif 4 | #include "ddebug.h" 5 | 6 | #include 7 | 8 | #include "ngx_http_set_hmac.h" 9 | #include 10 | #include 11 | 12 | 13 | /* this function's implementation is partly borrowed from 14 | * https://github.com/anomalizer/ngx_aws_auth */ 15 | static ngx_int_t 16 | ngx_http_set_misc_set_hmac(ngx_http_request_t *r, ngx_str_t *res, 17 | ngx_http_variable_value_t *v, const EVP_MD *evp_md) 18 | { 19 | ngx_http_variable_value_t *secret, *string_to_sign; 20 | unsigned int md_len = 0; 21 | unsigned char md[EVP_MAX_MD_SIZE]; 22 | 23 | secret = v; 24 | string_to_sign = v + 1; 25 | 26 | dd("secret=%.*s, string_to_sign=%.*s", (int) secret->len, secret->data, 27 | (int) string_to_sign->len, string_to_sign->data); 28 | 29 | HMAC(evp_md, secret->data, secret->len, string_to_sign->data, 30 | string_to_sign->len, md, &md_len); 31 | 32 | /* defensive test if there is something wrong with openssl */ 33 | if (md_len == 0 || md_len > EVP_MAX_MD_SIZE) { 34 | res->len = 0; 35 | return NGX_ERROR; 36 | } 37 | 38 | res->len = md_len; 39 | ndk_palloc_re(res->data, r->pool, md_len); 40 | 41 | ngx_memcpy(res->data, 42 | &md, 43 | md_len); 44 | 45 | return NGX_OK; 46 | } 47 | 48 | 49 | ngx_int_t 50 | ngx_http_set_misc_set_hmac_sha1(ngx_http_request_t *r, ngx_str_t *res, 51 | ngx_http_variable_value_t *v) 52 | { 53 | return ngx_http_set_misc_set_hmac(r, res, v, EVP_sha1()); 54 | } 55 | 56 | 57 | ngx_int_t 58 | ngx_http_set_misc_set_hmac_sha256(ngx_http_request_t *r, ngx_str_t *res, 59 | ngx_http_variable_value_t *v) 60 | { 61 | return ngx_http_set_misc_set_hmac(r, res, v, EVP_sha256()); 62 | } 63 | -------------------------------------------------------------------------------- /src/ngx_http_set_hmac.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | ngx_int_t ngx_http_set_misc_set_hmac_sha1(ngx_http_request_t *r, 6 | ngx_str_t *res, ngx_http_variable_value_t *v); 7 | 8 | ngx_int_t ngx_http_set_misc_set_hmac_sha256(ngx_http_request_t *r, 9 | ngx_str_t *res, ngx_http_variable_value_t *v); 10 | -------------------------------------------------------------------------------- /src/ngx_http_set_local_today.c: -------------------------------------------------------------------------------- 1 | #ifndef DDEBUG 2 | #define DDEBUG 0 3 | #endif 4 | #include "ddebug.h" 5 | 6 | #include 7 | 8 | 9 | #ifndef NGX_HTTP_SET_MISC_FMT_DATE_LEN 10 | #define NGX_HTTP_SET_MISC_FMT_DATE_LEN 256 11 | #endif 12 | 13 | 14 | ngx_int_t 15 | ngx_http_set_local_today(ngx_http_request_t *r, ngx_str_t *res, 16 | ngx_http_variable_value_t *v) 17 | { 18 | time_t now; 19 | ngx_tm_t tm; 20 | u_char *p; 21 | 22 | /*t = ngx_timeofday();*/ 23 | 24 | now = ngx_time(); 25 | 26 | ngx_gmtime(now + ngx_cached_time->gmtoff * 60, &tm); 27 | 28 | dd("tm.ngx_tm_hour:%d", tm.ngx_tm_hour); 29 | 30 | p = ngx_palloc(r->pool, sizeof("yyyy-mm-dd") - 1); 31 | if (p == NULL) { 32 | return NGX_ERROR; 33 | } 34 | 35 | ngx_sprintf(p, "%04d-%02d-%02d", tm.ngx_tm_year, tm.ngx_tm_mon, 36 | tm.ngx_tm_mday); 37 | 38 | res->data = p; 39 | res->len = sizeof("yyyy-mm-dd") - 1; 40 | 41 | return NGX_OK; 42 | } 43 | 44 | 45 | ngx_int_t 46 | ngx_http_set_formatted_gmt_time(ngx_http_request_t *r, ngx_str_t *res, 47 | ngx_http_variable_value_t *v) 48 | { 49 | time_t now; 50 | u_char *p; 51 | struct tm tm; 52 | 53 | if (v->not_found || v->len == 0) { 54 | res->data = NULL; 55 | res->len = 0; 56 | return NGX_OK; 57 | } 58 | 59 | now = ngx_time(); 60 | ngx_libc_gmtime(now, &tm); 61 | 62 | p = ngx_palloc(r->pool, NGX_HTTP_SET_MISC_FMT_DATE_LEN); 63 | if (p == NULL) { 64 | return NGX_ERROR; 65 | } 66 | 67 | res->len = strftime((char *) p, NGX_HTTP_SET_MISC_FMT_DATE_LEN, 68 | (char *) v->data, &tm); 69 | if (res->len == 0) { 70 | return NGX_ERROR; 71 | } 72 | 73 | res->data = p; 74 | 75 | return NGX_OK; 76 | } 77 | 78 | 79 | ngx_int_t 80 | ngx_http_set_formatted_local_time(ngx_http_request_t *r, ngx_str_t *res, 81 | ngx_http_variable_value_t *v) 82 | { 83 | time_t now; 84 | u_char *p; 85 | struct tm tm; 86 | 87 | if (v->not_found || v->len == 0) { 88 | res->data = NULL; 89 | res->len = 0; 90 | return NGX_OK; 91 | } 92 | 93 | now = ngx_time(); 94 | ngx_libc_localtime(now, &tm); 95 | 96 | p = ngx_palloc(r->pool, NGX_HTTP_SET_MISC_FMT_DATE_LEN); 97 | if (p == NULL) { 98 | return NGX_ERROR; 99 | } 100 | 101 | res->len = strftime((char *) p, NGX_HTTP_SET_MISC_FMT_DATE_LEN, 102 | (char *) v->data, &tm); 103 | if (res->len == 0) { 104 | return NGX_ERROR; 105 | } 106 | 107 | res->data = p; 108 | 109 | return NGX_OK; 110 | } 111 | -------------------------------------------------------------------------------- /src/ngx_http_set_local_today.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | 6 | ngx_int_t ngx_http_set_local_today(ngx_http_request_t *r, ngx_str_t *res, 7 | ngx_http_variable_value_t *v); 8 | 9 | ngx_int_t ngx_http_set_formatted_gmt_time(ngx_http_request_t *r, ngx_str_t *res, 10 | ngx_http_variable_value_t *v); 11 | 12 | ngx_int_t ngx_http_set_formatted_local_time(ngx_http_request_t *r, 13 | ngx_str_t *res, ngx_http_variable_value_t *v); 14 | -------------------------------------------------------------------------------- /src/ngx_http_set_misc_module.c: -------------------------------------------------------------------------------- 1 | #ifndef DDEBUG 2 | #define DDEBUG 0 3 | #endif 4 | #include "ddebug.h" 5 | 6 | 7 | #include "ngx_http_set_misc_module.h" 8 | #include 9 | #include "ngx_http_set_base32.h" 10 | #include "ngx_http_set_default_value.h" 11 | #include "ngx_http_set_hashed_upstream.h" 12 | #include "ngx_http_set_unescape_uri.h" 13 | #include "ngx_http_set_quote_sql.h" 14 | #include "ngx_http_set_quote_json.h" 15 | #include "ngx_http_set_escape_uri.h" 16 | #include "ngx_http_set_local_today.h" 17 | #include "ngx_http_set_hash.h" 18 | #include "ngx_http_set_hex.h" 19 | #include "ngx_http_set_base64.h" 20 | #include "ngx_http_set_base64url.h" 21 | #if NGX_OPENSSL 22 | #include "ngx_http_set_hmac.h" 23 | #endif 24 | #include "ngx_http_set_random.h" 25 | #include "ngx_http_set_secure_random.h" 26 | #include "ngx_http_set_rotate.h" 27 | 28 | 29 | #define NGX_UNESCAPE_URI_COMPONENT 0 30 | #define BASE32_ALPHABET_LEN 32 31 | 32 | 33 | static void *ngx_http_set_misc_create_loc_conf(ngx_conf_t *cf); 34 | static char *ngx_http_set_misc_merge_loc_conf(ngx_conf_t *cf, void *parent, 35 | void *child); 36 | static char *ngx_http_set_misc_base32_alphabet(ngx_conf_t *cf, 37 | ngx_command_t *cmd, void *conf); 38 | 39 | 40 | static ngx_conf_deprecated_t ngx_conf_deprecated_set_misc_base32_padding = { 41 | ngx_conf_deprecated, "set_misc_base32_padding", "set_base32_padding" 42 | }; 43 | 44 | 45 | static ndk_set_var_t ngx_http_set_misc_set_encode_base64_filter = { 46 | NDK_SET_VAR_VALUE, 47 | (void *) ngx_http_set_misc_set_encode_base64, 48 | 1, 49 | NULL 50 | }; 51 | 52 | 53 | static ndk_set_var_t ngx_http_set_misc_set_decode_base64_filter = { 54 | NDK_SET_VAR_VALUE, 55 | (void *) ngx_http_set_misc_set_decode_base64, 56 | 1, 57 | NULL 58 | }; 59 | 60 | 61 | static ndk_set_var_t ngx_http_set_misc_set_encode_base64url_filter = { 62 | NDK_SET_VAR_VALUE, 63 | (void *) ngx_http_set_misc_set_encode_base64url, 64 | 1, 65 | NULL 66 | }; 67 | 68 | 69 | static ndk_set_var_t ngx_http_set_misc_set_decode_base64url_filter = { 70 | NDK_SET_VAR_VALUE, 71 | (void *) ngx_http_set_misc_set_decode_base64url, 72 | 1, 73 | NULL 74 | }; 75 | 76 | 77 | static ndk_set_var_t ngx_http_set_misc_set_decode_hex_filter = { 78 | NDK_SET_VAR_VALUE, 79 | (void *) ngx_http_set_misc_set_decode_hex, 80 | 1, 81 | NULL 82 | }; 83 | 84 | 85 | static ndk_set_var_t ngx_http_set_misc_set_encode_hex_filter = { 86 | NDK_SET_VAR_VALUE, 87 | (void *) ngx_http_set_misc_set_encode_hex, 88 | 1, 89 | NULL 90 | }; 91 | 92 | 93 | #if NGX_OPENSSL 94 | static ndk_set_var_t ngx_http_set_misc_set_hmac_sha1_filter = { 95 | NDK_SET_VAR_MULTI_VALUE, 96 | (void *) ngx_http_set_misc_set_hmac_sha1, 97 | 2, 98 | NULL 99 | }; 100 | 101 | 102 | static ndk_set_var_t ngx_http_set_misc_set_hmac_sha256_filter = { 103 | NDK_SET_VAR_MULTI_VALUE, 104 | (void *) ngx_http_set_misc_set_hmac_sha256, 105 | 2, 106 | NULL 107 | }; 108 | #endif 109 | 110 | 111 | #ifndef NGX_HTTP_SET_HASH 112 | static ndk_set_var_t ngx_http_set_misc_set_md5_filter = { 113 | NDK_SET_VAR_VALUE, 114 | (void *) ngx_http_set_misc_set_md5, 115 | 1, 116 | NULL 117 | }; 118 | 119 | 120 | #if NGX_HAVE_SHA1 121 | static ndk_set_var_t ngx_http_set_misc_set_sha1_filter = { 122 | NDK_SET_VAR_VALUE, 123 | (void *) ngx_http_set_misc_set_sha1, 124 | 1, 125 | NULL 126 | }; 127 | #endif 128 | #endif 129 | 130 | 131 | static ndk_set_var_t ngx_http_set_misc_unescape_uri_filter = { 132 | NDK_SET_VAR_VALUE, 133 | (void *) ngx_http_set_misc_unescape_uri, 134 | 1, 135 | NULL 136 | }; 137 | 138 | 139 | static ndk_set_var_t ngx_http_set_misc_escape_uri_filter = { 140 | NDK_SET_VAR_VALUE, 141 | (void *) ngx_http_set_misc_escape_uri, 142 | 1, 143 | NULL 144 | }; 145 | 146 | 147 | static ndk_set_var_t ngx_http_set_misc_decode_base32_filter = { 148 | NDK_SET_VAR_VALUE, 149 | (void *) ngx_http_set_misc_decode_base32, 150 | 1, 151 | NULL 152 | }; 153 | 154 | 155 | static ndk_set_var_t ngx_http_set_misc_quote_sql_str_filter = { 156 | NDK_SET_VAR_VALUE, 157 | (void *) ngx_http_set_misc_quote_sql_str, 158 | 1, 159 | NULL 160 | }; 161 | 162 | 163 | static ndk_set_var_t ngx_http_set_misc_quote_pgsql_str_filter = { 164 | NDK_SET_VAR_VALUE, 165 | (void *) ngx_http_set_misc_quote_pgsql_str, 166 | 1, 167 | NULL 168 | }; 169 | 170 | 171 | static ndk_set_var_t ngx_http_set_misc_quote_json_str_filter = { 172 | NDK_SET_VAR_VALUE, 173 | (void *) ngx_http_set_misc_quote_json_str, 174 | 1, 175 | NULL 176 | }; 177 | 178 | 179 | static ndk_set_var_t ngx_http_set_misc_encode_base32_filter = { 180 | NDK_SET_VAR_VALUE, 181 | (void *) ngx_http_set_misc_encode_base32, 182 | 1, 183 | NULL 184 | }; 185 | 186 | 187 | static ndk_set_var_t ngx_http_set_misc_local_today_filter = { 188 | NDK_SET_VAR_VALUE, 189 | (void *) ngx_http_set_local_today, 190 | 0, 191 | NULL 192 | }; 193 | 194 | 195 | static ndk_set_var_t ngx_http_set_misc_formatted_gmt_time_filter = { 196 | NDK_SET_VAR_VALUE, 197 | (void *) ngx_http_set_formatted_gmt_time, 198 | 2, 199 | NULL 200 | }; 201 | 202 | 203 | static ndk_set_var_t ngx_http_set_misc_formatted_local_time_filter = { 204 | NDK_SET_VAR_VALUE, 205 | (void *) ngx_http_set_formatted_local_time, 206 | 2, 207 | NULL 208 | }; 209 | 210 | 211 | static ndk_set_var_t ngx_http_set_misc_set_random_filter = { 212 | NDK_SET_VAR_MULTI_VALUE, 213 | (void *) ngx_http_set_misc_set_random, 214 | 2, 215 | NULL 216 | }; 217 | 218 | 219 | static ndk_set_var_t ngx_http_set_misc_set_secure_random_alphanum_filter = { 220 | NDK_SET_VAR_VALUE, 221 | (void *) ngx_http_set_misc_set_secure_random_alphanum, 222 | 1, 223 | NULL 224 | }; 225 | 226 | 227 | static ndk_set_var_t ngx_http_set_misc_set_secure_random_lcalpha_filter = { 228 | NDK_SET_VAR_VALUE, 229 | (void *) ngx_http_set_misc_set_secure_random_lcalpha, 230 | 1, 231 | NULL 232 | }; 233 | 234 | 235 | static ngx_command_t ngx_http_set_misc_commands[] = { 236 | { ngx_string ("set_encode_base64"), 237 | NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_SIF_CONF 238 | |NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_CONF_TAKE12, 239 | ndk_set_var_value, 240 | 0, 241 | 0, 242 | &ngx_http_set_misc_set_encode_base64_filter 243 | }, 244 | { ngx_string ("set_decode_base64"), 245 | NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_SIF_CONF 246 | |NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_CONF_TAKE12, 247 | ndk_set_var_value, 248 | 0, 249 | 0, 250 | &ngx_http_set_misc_set_decode_base64_filter 251 | }, 252 | { ngx_string ("set_encode_base64url"), 253 | NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_SIF_CONF 254 | |NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_CONF_TAKE12, 255 | ndk_set_var_value, 256 | 0, 257 | 0, 258 | &ngx_http_set_misc_set_encode_base64url_filter 259 | }, 260 | { ngx_string ("set_decode_base64url"), 261 | NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_SIF_CONF 262 | |NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_CONF_TAKE12, 263 | ndk_set_var_value, 264 | 0, 265 | 0, 266 | &ngx_http_set_misc_set_decode_base64url_filter 267 | }, 268 | { ngx_string ("set_decode_hex"), 269 | NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_SIF_CONF 270 | |NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_CONF_TAKE12, 271 | ndk_set_var_value, 272 | 0, 273 | 0, 274 | &ngx_http_set_misc_set_decode_hex_filter 275 | }, 276 | { ngx_string ("set_encode_hex"), 277 | NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_SIF_CONF 278 | |NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_CONF_TAKE12, 279 | ndk_set_var_value, 280 | 0, 281 | 0, 282 | &ngx_http_set_misc_set_encode_hex_filter 283 | }, 284 | #if NGX_OPENSSL 285 | { ngx_string ("set_hmac_sha1"), 286 | NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_SIF_CONF 287 | |NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_CONF_TAKE3, 288 | ndk_set_var_multi_value, 289 | 0, 290 | 0, 291 | &ngx_http_set_misc_set_hmac_sha1_filter 292 | }, 293 | { ngx_string ("set_hmac_sha256"), 294 | NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_SIF_CONF 295 | |NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_CONF_TAKE3, 296 | ndk_set_var_multi_value, 297 | 0, 298 | 0, 299 | &ngx_http_set_misc_set_hmac_sha256_filter 300 | }, 301 | #endif 302 | #ifndef NGX_HTTP_SET_HASH 303 | { ngx_string ("set_md5"), 304 | NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_SIF_CONF 305 | |NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_CONF_TAKE12, 306 | ndk_set_var_value, 307 | 0, 308 | 0, 309 | &ngx_http_set_misc_set_md5_filter 310 | }, 311 | #if NGX_HAVE_SHA1 312 | { 313 | ngx_string ("set_sha1"), 314 | NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_SIF_CONF 315 | |NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_CONF_TAKE12, 316 | ndk_set_var_value, 317 | 0, 318 | 0, 319 | &ngx_http_set_misc_set_sha1_filter 320 | }, 321 | #endif 322 | #endif 323 | { 324 | ngx_string ("set_unescape_uri"), 325 | NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_SIF_CONF 326 | |NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_CONF_TAKE12, 327 | ndk_set_var_value, 328 | 0, 329 | 0, 330 | &ngx_http_set_misc_unescape_uri_filter 331 | }, 332 | { 333 | ngx_string ("set_escape_uri"), 334 | NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_SIF_CONF 335 | |NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_CONF_TAKE12, 336 | ndk_set_var_value, 337 | 0, 338 | 0, 339 | &ngx_http_set_misc_escape_uri_filter 340 | }, 341 | { 342 | ngx_string ("set_quote_sql_str"), 343 | NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_SIF_CONF 344 | |NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_CONF_TAKE12, 345 | ndk_set_var_value, 346 | 0, 347 | 0, 348 | &ngx_http_set_misc_quote_sql_str_filter 349 | }, 350 | { 351 | ngx_string ("set_quote_pgsql_str"), 352 | NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_SIF_CONF 353 | |NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_CONF_TAKE12, 354 | ndk_set_var_value, 355 | 0, 356 | 0, 357 | &ngx_http_set_misc_quote_pgsql_str_filter 358 | }, 359 | { 360 | ngx_string ("set_quote_json_str"), 361 | NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_SIF_CONF 362 | |NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_CONF_TAKE12, 363 | ndk_set_var_value, 364 | 0, 365 | 0, 366 | &ngx_http_set_misc_quote_json_str_filter 367 | }, 368 | { 369 | ngx_string ("set_if_empty"), 370 | NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_SIF_CONF 371 | |NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_CONF_TAKE2, 372 | ngx_http_set_if_empty, 373 | 0, 374 | 0, 375 | NULL 376 | }, 377 | { 378 | ngx_string("set_hashed_upstream"), 379 | NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_SIF_CONF 380 | |NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_CONF_TAKE3, 381 | ngx_http_set_hashed_upstream, 382 | 0, 383 | 0, 384 | NULL 385 | }, 386 | { 387 | /* this is now deprecated; use set_base32_padding instead */ 388 | ngx_string("set_misc_base32_padding"), 389 | NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_SIF_CONF 390 | |NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_CONF_FLAG, 391 | ngx_conf_set_flag_slot, 392 | NGX_HTTP_LOC_CONF_OFFSET, 393 | offsetof(ngx_http_set_misc_loc_conf_t, base32_padding), 394 | &ngx_conf_deprecated_set_misc_base32_padding, 395 | }, 396 | { 397 | ngx_string("set_base32_padding"), 398 | NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_SIF_CONF 399 | |NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_CONF_FLAG, 400 | ngx_conf_set_flag_slot, 401 | NGX_HTTP_LOC_CONF_OFFSET, 402 | offsetof(ngx_http_set_misc_loc_conf_t, base32_padding), 403 | NULL 404 | }, 405 | { 406 | ngx_string("set_base32_alphabet"), 407 | NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_SIF_CONF 408 | |NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_CONF_TAKE1, 409 | ngx_http_set_misc_base32_alphabet, 410 | NGX_HTTP_LOC_CONF_OFFSET, 411 | offsetof(ngx_http_set_misc_loc_conf_t, base32_alphabet), 412 | NULL 413 | }, 414 | { 415 | ngx_string("set_encode_base32"), 416 | NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_SIF_CONF 417 | |NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_CONF_TAKE12, 418 | ndk_set_var_value, 419 | 0, 420 | 0, 421 | &ngx_http_set_misc_encode_base32_filter 422 | }, 423 | { 424 | ngx_string("set_decode_base32"), 425 | NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_SIF_CONF 426 | |NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_CONF_TAKE12, 427 | ndk_set_var_value, 428 | 0, 429 | 0, 430 | &ngx_http_set_misc_decode_base32_filter 431 | }, 432 | { 433 | ngx_string("set_local_today"), 434 | NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_SIF_CONF 435 | |NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_CONF_TAKE1, 436 | ndk_set_var_value, 437 | 0, 438 | 0, 439 | &ngx_http_set_misc_local_today_filter 440 | }, 441 | { 442 | ngx_string("set_formatted_gmt_time"), 443 | NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_SIF_CONF 444 | |NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_CONF_TAKE2, 445 | ndk_set_var_value, 446 | 0, 447 | 0, 448 | &ngx_http_set_misc_formatted_gmt_time_filter 449 | }, 450 | { 451 | ngx_string("set_formatted_local_time"), 452 | NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_SIF_CONF 453 | |NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_CONF_TAKE2, 454 | ndk_set_var_value, 455 | 0, 456 | 0, 457 | &ngx_http_set_misc_formatted_local_time_filter 458 | }, 459 | { ngx_string ("set_random"), 460 | NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_SIF_CONF 461 | |NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_CONF_TAKE3, 462 | ndk_set_var_multi_value, 463 | 0, 464 | 0, 465 | &ngx_http_set_misc_set_random_filter 466 | }, 467 | { ngx_string ("set_secure_random_alphanum"), 468 | NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_SIF_CONF 469 | |NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_CONF_TAKE12, 470 | ndk_set_var_value, 471 | 0, 472 | 0, 473 | &ngx_http_set_misc_set_secure_random_alphanum_filter 474 | }, 475 | { ngx_string ("set_secure_random_lcalpha"), 476 | NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_SIF_CONF 477 | |NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_CONF_TAKE12, 478 | ndk_set_var_value, 479 | 0, 480 | 0, 481 | &ngx_http_set_misc_set_secure_random_lcalpha_filter 482 | }, 483 | { ngx_string ("set_rotate"), 484 | NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_SIF_CONF 485 | |NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_CONF_TAKE3, 486 | ngx_http_set_rotate, 487 | 0, 488 | 0, 489 | NULL 490 | }, 491 | 492 | ngx_null_command 493 | }; 494 | 495 | 496 | static ngx_http_module_t ngx_http_set_misc_module_ctx = { 497 | NULL, /* preconfiguration */ 498 | NULL, /* postconfiguration */ 499 | 500 | NULL, /* create main configuration */ 501 | NULL, /* init main configuration */ 502 | 503 | NULL, /* create server configuration */ 504 | NULL, /* merge server configuration */ 505 | 506 | ngx_http_set_misc_create_loc_conf, /* create location configuration */ 507 | ngx_http_set_misc_merge_loc_conf /* merge location configuration */ 508 | }; 509 | 510 | 511 | ngx_module_t ngx_http_set_misc_module = { 512 | NGX_MODULE_V1, 513 | &ngx_http_set_misc_module_ctx, /* module context */ 514 | ngx_http_set_misc_commands, /* module directives */ 515 | NGX_HTTP_MODULE, /* module type */ 516 | NULL, /* init master */ 517 | NULL, /* init module */ 518 | NULL, /* init process */ 519 | NULL, /* init thread */ 520 | NULL, /* exit thread */ 521 | NULL, /* exit process */ 522 | NULL, /* exit master */ 523 | NGX_MODULE_V1_PADDING 524 | }; 525 | 526 | 527 | void * 528 | ngx_http_set_misc_create_loc_conf(ngx_conf_t *cf) 529 | { 530 | ngx_http_set_misc_loc_conf_t *conf; 531 | 532 | conf = ngx_palloc(cf->pool, sizeof(ngx_http_set_misc_loc_conf_t)); 533 | if (conf == NULL) { 534 | return NULL; 535 | } 536 | 537 | conf->base32_padding = NGX_CONF_UNSET; 538 | conf->base32_alphabet.data = NULL; 539 | conf->base32_alphabet.len = 0; 540 | conf->current = NGX_CONF_UNSET; 541 | 542 | return conf; 543 | } 544 | 545 | 546 | char * 547 | ngx_http_set_misc_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child) 548 | { 549 | ngx_uint_t i; 550 | 551 | ngx_http_set_misc_loc_conf_t *prev = parent; 552 | ngx_http_set_misc_loc_conf_t *conf = child; 553 | 554 | ngx_conf_merge_value(conf->base32_padding, prev->base32_padding, 1); 555 | 556 | ngx_conf_merge_str_value(conf->base32_alphabet, prev->base32_alphabet, 557 | "0123456789abcdefghijklmnopqrstuv"); 558 | 559 | ngx_conf_merge_value(conf->current, prev->current, NGX_CONF_UNSET); 560 | 561 | for (i = 0; i < BASE32_ALPHABET_LEN; i++) { 562 | conf->basis32[conf->base32_alphabet.data[i]] = (u_char) i; 563 | } 564 | 565 | return NGX_CONF_OK; 566 | } 567 | 568 | 569 | static char * 570 | ngx_http_set_misc_base32_alphabet(ngx_conf_t *cf, ngx_command_t *cmd, 571 | void *conf) 572 | { 573 | ngx_str_t *value; 574 | 575 | value = cf->args->elts; 576 | 577 | if (value[1].len != BASE32_ALPHABET_LEN) { 578 | ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, 579 | "\"set_base32_alphabet\" directive takes an " 580 | "alphabet of %uz bytes but %d expected", 581 | value[1].len, BASE32_ALPHABET_LEN); 582 | return NGX_CONF_ERROR; 583 | } 584 | 585 | return ngx_conf_set_str_slot(cf, cmd, conf); 586 | } 587 | -------------------------------------------------------------------------------- /src/ngx_http_set_misc_module.h: -------------------------------------------------------------------------------- 1 | #ifndef NGX_HTTP_SET_MISC_MODULE_H 2 | #define NGX_HTTP_SET_MISC_MODULE_H 3 | 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | 11 | #ifndef NGX_HAVE_SHA1 12 | # if (nginx_version >= 1011002) 13 | # define NGX_HAVE_SHA1 1 14 | # endif 15 | #endif 16 | 17 | 18 | typedef struct { 19 | ngx_flag_t base32_padding; 20 | ngx_str_t base32_alphabet; 21 | u_char basis32[256]; 22 | ngx_int_t current; /* for set_rotate */ 23 | } ngx_http_set_misc_loc_conf_t; 24 | 25 | 26 | extern ngx_module_t ngx_http_set_misc_module; 27 | 28 | 29 | #endif /* NGX_HTTP_SET_MISC_MODULE_H */ 30 | 31 | -------------------------------------------------------------------------------- /src/ngx_http_set_quote_json.c: -------------------------------------------------------------------------------- 1 | #ifndef DDEBUG 2 | #define DDEBUG 0 3 | #endif 4 | #include "ddebug.h" 5 | 6 | #include 7 | #include "ngx_http_set_quote_json.h" 8 | 9 | ngx_int_t 10 | ngx_http_set_misc_quote_json_str(ngx_http_request_t *r, ngx_str_t *res, 11 | ngx_http_variable_value_t *v) 12 | { 13 | size_t len; 14 | u_char *p; 15 | size_t escape; 16 | 17 | if (v->not_found || v->len == 0) { 18 | res->data = (u_char *) "null"; 19 | res->len = sizeof("null") - 1; 20 | return NGX_OK; 21 | } 22 | 23 | escape = ngx_http_set_misc_escape_json_str(NULL, v->data, v->len); 24 | 25 | len = sizeof("''") - 1 26 | + v->len 27 | + escape; 28 | 29 | p = ngx_palloc(r->pool, len); 30 | if (p == NULL) { 31 | return NGX_ERROR; 32 | } 33 | 34 | res->data = p; 35 | res->len = len; 36 | 37 | *p++ = '\"'; 38 | 39 | if (escape == 0) { 40 | p = ngx_copy(p, v->data, v->len); 41 | 42 | } else { 43 | p = (u_char *) ngx_http_set_misc_escape_json_str(p, v->data, v->len); 44 | } 45 | 46 | *p++ = '\"'; 47 | 48 | if (p != res->data + res->len) { 49 | ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, 50 | "set_quote_sql_str: buffer error"); 51 | return NGX_ERROR; 52 | } 53 | 54 | return NGX_OK; 55 | } 56 | 57 | 58 | uintptr_t 59 | ngx_http_set_misc_escape_json_str(u_char *dst, u_char *src, size_t size) 60 | { 61 | ngx_uint_t n; 62 | 63 | static u_char hex[] = "0123456789abcdef"; 64 | 65 | if (dst == NULL) { 66 | /* find the number of characters to be escaped */ 67 | 68 | n = 0; 69 | 70 | while (size) { 71 | /* UTF-8 char has high bit of 1 */ 72 | if ((*src & 0x80) == 0) { 73 | switch (*src) { 74 | case '\r': 75 | case '\n': 76 | case '\\': 77 | case '"': 78 | case '\f': 79 | case '\b': 80 | case '\t': 81 | n++; 82 | break; 83 | default: 84 | if (*src < 32) { 85 | n += sizeof("\\u00xx") - 2; 86 | } 87 | 88 | break; 89 | } 90 | } 91 | 92 | src++; 93 | size--; 94 | } 95 | 96 | return (uintptr_t) n; 97 | } 98 | 99 | while (size) { 100 | if ((*src & 0x80) == 0) { 101 | switch (*src) { 102 | case '\r': 103 | *dst++ = '\\'; 104 | *dst++ = 'r'; 105 | break; 106 | 107 | case '\n': 108 | *dst++ = '\\'; 109 | *dst++ = 'n'; 110 | break; 111 | 112 | case '\\': 113 | *dst++ = '\\'; 114 | *dst++ = '\\'; 115 | break; 116 | 117 | case '"': 118 | *dst++ = '\\'; 119 | *dst++ = '"'; 120 | break; 121 | 122 | case '\f': 123 | *dst++ = '\\'; 124 | *dst++ = 'f'; 125 | break; 126 | 127 | case '\b': 128 | *dst++ = '\\'; 129 | *dst++ = 'b'; 130 | break; 131 | 132 | case '\t': 133 | *dst++ = '\\'; 134 | *dst++ = 't'; 135 | break; 136 | 137 | default: 138 | if (*src < 32) { /* control chars */ 139 | *dst++ = '\\'; 140 | *dst++ = 'u'; 141 | *dst++ = '0'; 142 | *dst++ = '0'; 143 | *dst++ = hex[*src >> 4]; 144 | *dst++ = hex[*src & 0x0f]; 145 | 146 | } else { 147 | *dst++ = *src; 148 | } 149 | 150 | break; 151 | } /* switch */ 152 | 153 | src++; 154 | 155 | } else { 156 | *dst++ = *src++; 157 | } 158 | 159 | size--; 160 | } 161 | 162 | return (uintptr_t) dst; 163 | } 164 | 165 | 166 | -------------------------------------------------------------------------------- /src/ngx_http_set_quote_json.h: -------------------------------------------------------------------------------- 1 | #ifndef NGX_HTTP_SET_QUOTE_JSON_H 2 | #define NGX_HTTP_SET_QUOTE_JSON_H 3 | 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | 10 | ngx_int_t ngx_http_set_misc_quote_json_str(ngx_http_request_t *r, 11 | ngx_str_t *res, ngx_http_variable_value_t *v); 12 | uintptr_t ngx_http_set_misc_escape_json_str(u_char *dst, u_char *src, 13 | size_t size); 14 | 15 | 16 | #endif /* NGX_HTTP_SET_QUOTE_JSON_H */ 17 | -------------------------------------------------------------------------------- /src/ngx_http_set_quote_sql.c: -------------------------------------------------------------------------------- 1 | #ifndef DDEBUG 2 | #define DDEBUG 0 3 | #endif 4 | #include "ddebug.h" 5 | 6 | #include 7 | #include "ngx_http_set_quote_sql.h" 8 | 9 | 10 | static ngx_int_t ngx_http_pg_utf_escape(ngx_http_request_t *r, ngx_str_t *res); 11 | static ngx_int_t ngx_http_pg_utf_islegal(const unsigned char *s, ngx_int_t len); 12 | static ngx_int_t ngx_http_pg_utf_mblen(const unsigned char *s); 13 | 14 | 15 | ngx_int_t 16 | ngx_http_set_misc_quote_pgsql_str(ngx_http_request_t *r, ngx_str_t *res, 17 | ngx_http_variable_value_t *v) 18 | { 19 | u_char *pstr; 20 | ngx_int_t length; 21 | 22 | if (v->not_found || v->len ==0) { 23 | res->data = (u_char *) "''"; 24 | res->len = sizeof("''") - 1; 25 | return NGX_OK; 26 | } 27 | 28 | ngx_http_set_misc_quote_sql_str(r, res, v); 29 | length = res->len; 30 | 31 | pstr = ngx_palloc(r->pool, length + 1); 32 | if (pstr == NULL) { 33 | return NGX_ERROR; 34 | } 35 | 36 | *pstr = 'E'; 37 | memcpy(pstr + 1, res->data, length); 38 | res->data = pstr; 39 | res->len = length + 1; 40 | 41 | if (ngx_http_pg_utf_islegal(res->data, res->len)) { 42 | return NGX_OK; 43 | } 44 | 45 | if (ngx_http_pg_utf_escape(r, res) != NGX_OK) { 46 | return NGX_ERROR; 47 | } 48 | 49 | return NGX_OK; 50 | } 51 | 52 | 53 | static ngx_int_t 54 | ngx_http_pg_utf_mblen(const unsigned char *s) 55 | { 56 | int len; 57 | 58 | if ((*s & 0x80) == 0) 59 | len = 1; 60 | else if ((*s & 0xe0) == 0xc0) 61 | len = 2; 62 | else if ((*s & 0xf0) == 0xe0) 63 | len = 3; 64 | else if ((*s & 0xf8) == 0xf0) 65 | len = 4; 66 | #ifdef NOT_USED 67 | else if ((*s & 0xfc) == 0xf8) 68 | len = 5; 69 | else if ((*s & 0xfe) == 0xfc) 70 | len = 6; 71 | #endif 72 | else 73 | len = 1; 74 | return len; 75 | } 76 | 77 | 78 | static ngx_int_t 79 | ngx_http_pg_utf_islegal(const unsigned char *s, ngx_int_t len) 80 | { 81 | ngx_int_t mblen; 82 | ngx_int_t slen; 83 | u_char a; 84 | 85 | slen = len; 86 | 87 | while (slen > 0) { 88 | mblen = ngx_http_pg_utf_mblen(s); 89 | if (slen < mblen) { 90 | return 0; 91 | } 92 | 93 | switch (mblen) { 94 | 95 | case 4: 96 | a = *(s + 3); 97 | if (a < 0x80 || a > 0xBF) { 98 | return 0; 99 | } 100 | 101 | break; 102 | 103 | case 3: 104 | a = *(s + 2); 105 | if (a < 0x80 || a > 0xBF) { 106 | return 0; 107 | } 108 | 109 | break; 110 | 111 | case 2: 112 | a = *(s + 1); 113 | 114 | switch (*s) { 115 | 116 | case 0xE0: 117 | if (a < 0xA0 || a > 0xBF) { 118 | return 0; 119 | } 120 | 121 | break; 122 | 123 | case 0xED: 124 | if (a < 0x80 || a > 0x9F) { 125 | return 0; 126 | } 127 | 128 | break; 129 | 130 | case 0xF0: 131 | if (a < 0x90 || a > 0xBF) { 132 | return 0; 133 | } 134 | 135 | break; 136 | 137 | case 0xF4: 138 | if (a < 0x80 || a > 0x8F) { 139 | return 0; 140 | } 141 | 142 | break; 143 | 144 | default: 145 | if (a < 0x80 || a > 0xBF) { 146 | return 0; 147 | } 148 | 149 | break; 150 | } 151 | 152 | break; 153 | 154 | case 1: 155 | a = *s; 156 | if (a >= 0x80 && a < 0xC2) { 157 | return 0; 158 | } 159 | 160 | if (a > 0xF4) { 161 | return 0; 162 | } 163 | 164 | break; 165 | 166 | default: 167 | return 0; 168 | } 169 | 170 | s += mblen; 171 | slen -= mblen; 172 | } 173 | 174 | return 1; 175 | } 176 | 177 | 178 | static ngx_int_t 179 | ngx_http_pg_utf_escape(ngx_http_request_t *r, ngx_str_t *res) 180 | { 181 | ngx_str_t *result; 182 | ngx_int_t l, count; 183 | u_char *d, *p, *p1; 184 | 185 | l = res->len; 186 | d = res->data; 187 | result = res; 188 | count = 0; 189 | 190 | while (l-- > 0) { 191 | if (*d & 0x80) { 192 | count += 4; 193 | } 194 | 195 | d++; 196 | count++; 197 | } 198 | 199 | d = res->data; 200 | l = res->len; 201 | 202 | p = ngx_palloc(r->pool, count); 203 | if (p == NULL) { 204 | return NGX_ERROR; 205 | } 206 | 207 | p1 = p; 208 | while (l-- > 0) { 209 | if ((*d & 0x80)) { 210 | *p++ = '\\'; 211 | *p++ = '\\'; 212 | *p++ = (*d >> 6) + '0'; 213 | *p++ = ((*d >> 3) & 07) + '0'; 214 | *p++ = (*d & 07) + '0'; 215 | 216 | } else { 217 | *p++ = *d; 218 | } 219 | 220 | d++; 221 | } 222 | 223 | result->len = count; 224 | result->data = p1; 225 | 226 | return NGX_OK; 227 | } 228 | 229 | 230 | ngx_int_t 231 | ngx_http_set_misc_quote_sql_str(ngx_http_request_t *r, ngx_str_t *res, 232 | ngx_http_variable_value_t *v) 233 | { 234 | size_t len; 235 | u_char *p; 236 | size_t escape; 237 | 238 | if (v->not_found || v->len == 0) { 239 | res->data = (u_char *) "''"; 240 | res->len = sizeof("''") - 1; 241 | return NGX_OK; 242 | } 243 | 244 | escape = ngx_http_set_misc_escape_sql_str(NULL, v->data, v->len); 245 | 246 | len = sizeof("''") - 1 + v->len + escape; 247 | 248 | p = ngx_palloc(r->pool, len); 249 | if (p == NULL) { 250 | return NGX_ERROR; 251 | } 252 | 253 | res->data = p; 254 | res->len = len; 255 | 256 | *p++ = '\''; 257 | 258 | if (escape == 0) { 259 | p = ngx_copy(p, v->data, v->len); 260 | 261 | } else { 262 | p = (u_char *) ngx_http_set_misc_escape_sql_str(p, v->data, v->len); 263 | } 264 | 265 | *p++ = '\''; 266 | 267 | if (p != res->data + res->len) { 268 | ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, 269 | "set_quote_sql_str: buffer error"); 270 | return NGX_ERROR; 271 | } 272 | 273 | return NGX_OK; 274 | } 275 | 276 | 277 | uintptr_t 278 | ngx_http_set_misc_escape_sql_str(u_char *dst, u_char *src, size_t size) 279 | { 280 | ngx_uint_t n; 281 | 282 | if (dst == NULL) { 283 | /* find the number of chars to be escaped */ 284 | n = 0; 285 | while (size) { 286 | /* the highest bit of all the UTF-8 chars 287 | * is always 1 */ 288 | if ((*src & 0x80) == 0) { 289 | switch (*src) { 290 | case '\0': 291 | case '\b': 292 | case '\n': 293 | case '\r': 294 | case '\t': 295 | case '\\': 296 | case '\'': 297 | case '"': 298 | case '$': 299 | case 26: /* \Z */ 300 | n++; 301 | break; 302 | default: 303 | break; 304 | } 305 | } 306 | 307 | src++; 308 | size--; 309 | } 310 | 311 | return (uintptr_t) n; 312 | } 313 | 314 | while (size) { 315 | if ((*src & 0x80) == 0) { 316 | switch (*src) { 317 | case '\0': 318 | *dst++ = '\\'; 319 | *dst++ = '0'; 320 | break; 321 | 322 | case '\b': 323 | *dst++ = '\\'; 324 | *dst++ = 'b'; 325 | break; 326 | 327 | case '\n': 328 | *dst++ = '\\'; 329 | *dst++ = 'n'; 330 | break; 331 | 332 | case '\r': 333 | *dst++ = '\\'; 334 | *dst++ = 'r'; 335 | break; 336 | 337 | case '\t': 338 | *dst++ = '\\'; 339 | *dst++ = 't'; 340 | break; 341 | 342 | case '\\': 343 | *dst++ = '\\'; 344 | *dst++ = '\\'; 345 | break; 346 | 347 | case '\'': 348 | *dst++ = '\\'; 349 | *dst++ = '\''; 350 | break; 351 | 352 | case '"': 353 | *dst++ = '\\'; 354 | *dst++ = '"'; 355 | break; 356 | 357 | case '$': 358 | *dst++ = '\\'; 359 | *dst++ = '$'; 360 | break; 361 | 362 | case 26: 363 | *dst++ = '\\'; 364 | *dst++ = 'Z'; 365 | break; 366 | 367 | default: 368 | *dst++ = *src; 369 | break; 370 | } 371 | 372 | } else { 373 | *dst++ = *src; 374 | } 375 | 376 | src++; 377 | size--; 378 | } /* while (size) */ 379 | 380 | return (uintptr_t) dst; 381 | } 382 | 383 | -------------------------------------------------------------------------------- /src/ngx_http_set_quote_sql.h: -------------------------------------------------------------------------------- 1 | #ifndef NGX_SET_QUOTE_SQL_H 2 | #define NGX_SET_QUOTE_SQL_H 3 | 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | 10 | uintptr_t ngx_http_set_misc_escape_sql_str(u_char *dst, u_char *src, 11 | size_t size); 12 | 13 | ngx_int_t ngx_http_set_misc_quote_sql_str(ngx_http_request_t *r, 14 | ngx_str_t *res, ngx_http_variable_value_t *v); 15 | 16 | ngx_int_t ngx_http_set_misc_quote_pgsql_str(ngx_http_request_t *r, 17 | ngx_str_t *res, ngx_http_variable_value_t *v); 18 | 19 | 20 | #endif /* NGX_SET_QUOTE_SQL_H */ 21 | 22 | -------------------------------------------------------------------------------- /src/ngx_http_set_random.c: -------------------------------------------------------------------------------- 1 | #ifndef DDEBUG 2 | #define DDEBUG 0 3 | #endif 4 | #include "ddebug.h" 5 | 6 | 7 | #include 8 | #include "ngx_http_set_random.h" 9 | #include 10 | 11 | 12 | ngx_int_t 13 | ngx_http_set_misc_set_random(ngx_http_request_t *r, ngx_str_t *res, 14 | ngx_http_variable_value_t *v) 15 | { 16 | ngx_http_variable_value_t *rand_from, *rand_to; 17 | ngx_int_t int_from, int_to, tmp, random; 18 | 19 | rand_from = v; 20 | rand_to = v + 1; 21 | 22 | int_from = ngx_atoi(rand_from->data, rand_from->len); 23 | if (int_from == NGX_ERROR) { 24 | ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, 25 | "set_random: bad \"from\" argument: %v", rand_from); 26 | return NGX_ERROR; 27 | } 28 | 29 | int_to = ngx_atoi(rand_to->data, rand_to->len); 30 | if (int_to == NGX_ERROR) { 31 | ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, 32 | "set_random: bad \"to\" argument: %v", rand_to); 33 | return NGX_ERROR; 34 | } 35 | 36 | if (int_from > int_to) { 37 | tmp = int_from; 38 | int_from = int_to; 39 | int_to = tmp; 40 | } 41 | 42 | random = rand() % (int_to - int_from + 1) + int_from; 43 | 44 | res->data = ngx_palloc(r->pool, NGX_INT_T_LEN); 45 | if (res->data == NULL) { 46 | return NGX_ERROR; 47 | } 48 | 49 | res->len = ngx_sprintf(res->data, "%i", random) - res->data; 50 | 51 | /* Set all required params */ 52 | v->valid = 1; 53 | v->no_cacheable = 0; 54 | v->not_found = 0; 55 | 56 | return NGX_OK; 57 | } 58 | -------------------------------------------------------------------------------- /src/ngx_http_set_random.h: -------------------------------------------------------------------------------- 1 | #ifndef NGX_SET_RANDOM_H 2 | #define NGX_SET_RANDOM_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | ngx_int_t ngx_http_set_misc_set_random(ngx_http_request_t *r, 9 | ngx_str_t *res, ngx_http_variable_value_t *v); 10 | 11 | #endif /* NGX_SET_RANDOM_H */ 12 | 13 | -------------------------------------------------------------------------------- /src/ngx_http_set_rotate.c: -------------------------------------------------------------------------------- 1 | #ifndef DDEBUG 2 | #define DDEBUG 0 3 | #endif 4 | #include "ddebug.h" 5 | 6 | #include 7 | #include "ngx_http_set_rotate.h" 8 | #include "ngx_http_set_misc_module.h" 9 | #include 10 | 11 | 12 | ngx_int_t 13 | ngx_http_set_misc_set_rotate(ngx_http_request_t *r, ngx_str_t *res, 14 | ngx_http_variable_value_t *v) 15 | { 16 | ngx_http_variable_value_t *rotate_from, *rotate_to, *rotate_num; 17 | ngx_int_t int_from, int_to, tmp, int_current; 18 | 19 | ngx_http_set_misc_loc_conf_t *conf; 20 | 21 | rotate_num = &v[0]; 22 | rotate_from = &v[1]; 23 | rotate_to = &v[2]; 24 | 25 | int_from = ngx_atoi(rotate_from->data, rotate_from->len); 26 | if (int_from == NGX_ERROR) { 27 | ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, 28 | "set_rotate: bad \"from\" argument value: \"%v\"", 29 | rotate_from); 30 | return NGX_ERROR; 31 | } 32 | 33 | int_to = ngx_atoi(rotate_to->data, rotate_to->len); 34 | if (int_to == NGX_ERROR) { 35 | ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, 36 | "set_rotate: bad \"to\" argument value: \"%v\"", 37 | rotate_to); 38 | return NGX_ERROR; 39 | } 40 | 41 | if (int_from > int_to) { 42 | tmp = int_from; 43 | int_from = int_to; 44 | int_to = tmp; 45 | } 46 | 47 | conf = ngx_http_get_module_loc_conf(r, ngx_http_set_misc_module); 48 | 49 | dd("current value not found: %d", (int) rotate_num->not_found); 50 | 51 | if (rotate_num->len == 0) { 52 | if (conf->current != NGX_CONF_UNSET) { 53 | int_current = conf->current; 54 | 55 | } else { 56 | int_current = int_from - 1; 57 | } 58 | 59 | } else { 60 | 61 | int_current = ngx_atoi(rotate_num->data, rotate_num->len); 62 | if (int_current == NGX_ERROR) { 63 | ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, 64 | "set_rotate: bad current value: \"%v\"", rotate_num); 65 | 66 | if (conf->current != NGX_CONF_UNSET) { 67 | int_current = conf->current; 68 | 69 | } else { 70 | int_current = int_from - 1; 71 | } 72 | } 73 | } 74 | 75 | int_current++; 76 | 77 | if (int_current > int_to || int_current < int_from) { 78 | int_current = int_from; 79 | } 80 | 81 | conf->current = int_current; 82 | 83 | res->data = ngx_palloc(r->pool, NGX_INT_T_LEN); 84 | if (res->data == NULL) { 85 | return NGX_ERROR; 86 | } 87 | 88 | res->len = ngx_sprintf(res->data, "%i", int_current) - res->data; 89 | 90 | v->valid = 1; 91 | v->no_cacheable = 0; 92 | v->not_found = 0; 93 | 94 | return NGX_OK; 95 | } 96 | 97 | 98 | char * 99 | ngx_http_set_rotate(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) 100 | { 101 | ngx_str_t *value; 102 | ndk_set_var_t filter; 103 | 104 | value = cf->args->elts; 105 | 106 | filter.type = NDK_SET_VAR_MULTI_VALUE; 107 | filter.func = (void *) ngx_http_set_misc_set_rotate; 108 | filter.size = 3; 109 | filter.data = NULL; 110 | 111 | return ndk_set_var_multi_value_core(cf, &value[1], &value[1], &filter); 112 | } 113 | 114 | -------------------------------------------------------------------------------- /src/ngx_http_set_rotate.h: -------------------------------------------------------------------------------- 1 | #ifndef NGX_HTTP_SET_MISC_ROTATE_H 2 | #define NGX_HTTP_SET_MISC_ROTATE_H 3 | 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | 10 | char *ngx_http_set_rotate(ngx_conf_t *cf, ngx_command_t *cmd, 11 | void *conf); 12 | 13 | ngx_int_t ngx_http_set_misc_set_rotate(ngx_http_request_t *r, 14 | ngx_str_t *res, ngx_http_variable_value_t *v); 15 | 16 | 17 | #endif /* NGX_HTTP_SET_MISC_ROTATE_H */ 18 | 19 | -------------------------------------------------------------------------------- /src/ngx_http_set_secure_random.c: -------------------------------------------------------------------------------- 1 | #ifndef DDEBUG 2 | #define DDEBUG 0 3 | #endif 4 | #include "ddebug.h" 5 | 6 | 7 | #include 8 | #include "ngx_http_set_secure_random.h" 9 | #include 10 | 11 | 12 | enum { 13 | MAX_RANDOM_STRING = 64, 14 | ALPHANUM = 1, 15 | LCALPHA = 2 16 | }; 17 | 18 | 19 | static ngx_int_t 20 | ngx_http_set_misc_set_secure_random_common(int alphabet_type, 21 | ngx_http_request_t *r, ngx_str_t *res, ngx_http_variable_value_t *v); 22 | 23 | 24 | ngx_int_t 25 | ngx_http_set_misc_set_secure_random_alphanum(ngx_http_request_t *r, 26 | ngx_str_t *res, ngx_http_variable_value_t *v) 27 | { 28 | return ngx_http_set_misc_set_secure_random_common(ALPHANUM, r, res, v); 29 | } 30 | 31 | 32 | ngx_int_t 33 | ngx_http_set_misc_set_secure_random_lcalpha(ngx_http_request_t *r, 34 | ngx_str_t *res, ngx_http_variable_value_t *v) 35 | { 36 | return ngx_http_set_misc_set_secure_random_common(LCALPHA, r, res, v); 37 | } 38 | 39 | 40 | static ngx_int_t 41 | ngx_http_set_misc_set_secure_random_common(int alphabet_type, 42 | ngx_http_request_t *r, ngx_str_t *res, ngx_http_variable_value_t *v) 43 | { 44 | static u_char alphabet[] = "abcdefghijklmnopqrstuvwxyz" 45 | "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; 46 | 47 | u_char entropy[MAX_RANDOM_STRING]; 48 | u_char output[MAX_RANDOM_STRING]; 49 | ngx_int_t length, i; 50 | ngx_fd_t fd; 51 | ssize_t n; 52 | 53 | length = ngx_atoi(v->data, v->len); 54 | 55 | if (length == NGX_ERROR || length < 1 || length > MAX_RANDOM_STRING) { 56 | ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, 57 | "set_random: bad \"length\" argument: %v", v); 58 | return NGX_ERROR; 59 | } 60 | 61 | fd = ngx_open_file((u_char *) "/dev/urandom", NGX_FILE_RDONLY, 62 | NGX_FILE_OPEN, 0); 63 | if (fd == NGX_INVALID_FILE) { 64 | ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, 65 | "set_secure_random: could not open /dev/urandom"); 66 | return NGX_ERROR; 67 | } 68 | 69 | n = ngx_read_fd(fd, entropy, length); 70 | if (n != length) { 71 | ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, 72 | "set_secure_random: could not read all %i byte(s) from " 73 | "/dev/urandom", length); 74 | ngx_close_file(fd); 75 | return NGX_ERROR; 76 | } 77 | 78 | ngx_close_file(fd); 79 | 80 | for (i = 0; i < length; i++) { 81 | if (alphabet_type == LCALPHA) { 82 | output[i] = entropy[i] % 26 + 'a'; 83 | 84 | } else { 85 | output[i] = alphabet[ entropy[i] % (sizeof alphabet - 1) ]; 86 | } 87 | } 88 | 89 | res->data = ngx_palloc(r->pool, length); 90 | if (res->data == NULL) { 91 | return NGX_ERROR; 92 | } 93 | 94 | ngx_memcpy(res->data, output, length); 95 | 96 | res->len = length; 97 | 98 | /* set all required params */ 99 | v->valid = 1; 100 | v->no_cacheable = 0; 101 | v->not_found = 0; 102 | 103 | return NGX_OK; 104 | } 105 | -------------------------------------------------------------------------------- /src/ngx_http_set_secure_random.h: -------------------------------------------------------------------------------- 1 | #ifndef NGX_SET_SECURE_RANDOM_H 2 | #define NGX_SET_SECURE_RANDOM_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | ngx_int_t ngx_http_set_misc_set_secure_random_alphanum(ngx_http_request_t *r, 9 | ngx_str_t *res, ngx_http_variable_value_t *v); 10 | 11 | ngx_int_t ngx_http_set_misc_set_secure_random_lcalpha(ngx_http_request_t *r, 12 | ngx_str_t *res, ngx_http_variable_value_t *v); 13 | 14 | #endif /* NGX_SET_SECURE_RANDOM_H */ 15 | 16 | -------------------------------------------------------------------------------- /src/ngx_http_set_unescape_uri.c: -------------------------------------------------------------------------------- 1 | #ifndef DDEBUG 2 | #define DDEBUG 0 3 | #endif 4 | #include "ddebug.h" 5 | 6 | #include 7 | #include "ngx_http_set_unescape_uri.h" 8 | 9 | #define NGX_UNESCAPE_URI_COMPONENT 0 10 | 11 | 12 | static void ngx_unescape_uri_patched(u_char **dst, u_char **src, size_t size, 13 | ngx_uint_t type); 14 | 15 | 16 | ngx_int_t 17 | ngx_http_set_misc_unescape_uri(ngx_http_request_t *r, ngx_str_t *res, 18 | ngx_http_variable_value_t *v) 19 | { 20 | size_t len; 21 | u_char *p; 22 | u_char *src, *dst; 23 | 24 | /* the unescaped string can only be smaller */ 25 | len = v->len; 26 | 27 | p = ngx_palloc(r->pool, len); 28 | if (p == NULL) { 29 | return NGX_ERROR; 30 | } 31 | 32 | src = v->data; dst = p; 33 | 34 | ngx_unescape_uri_patched(&dst, &src, v->len, NGX_UNESCAPE_URI_COMPONENT); 35 | 36 | if (src != v->data + v->len) { 37 | ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, 38 | "set_unescape_uri: input data not consumed completely"); 39 | return NGX_ERROR; 40 | } 41 | 42 | res->data = p; 43 | res->len = dst - p; 44 | 45 | return NGX_OK; 46 | } 47 | 48 | 49 | /* XXX we also decode '+' to ' ' */ 50 | static void 51 | ngx_unescape_uri_patched(u_char **dst, u_char **src, size_t size, 52 | ngx_uint_t type) 53 | { 54 | u_char *d, *s, ch, c, decoded; 55 | enum { 56 | sw_usual = 0, 57 | sw_quoted, 58 | sw_quoted_second 59 | } state; 60 | 61 | d = *dst; 62 | s = *src; 63 | 64 | state = 0; 65 | decoded = 0; 66 | 67 | while (size--) { 68 | 69 | ch = *s++; 70 | 71 | switch (state) { 72 | case sw_usual: 73 | if (ch == '?' 74 | && (type & (NGX_UNESCAPE_URI|NGX_UNESCAPE_REDIRECT))) 75 | { 76 | *d++ = ch; 77 | goto done; 78 | } 79 | 80 | if (ch == '%') { 81 | state = sw_quoted; 82 | break; 83 | } 84 | 85 | if (ch == '+') { 86 | *d++ = ' '; 87 | break; 88 | } 89 | 90 | *d++ = ch; 91 | break; 92 | 93 | case sw_quoted: 94 | 95 | if (ch >= '0' && ch <= '9') { 96 | decoded = (u_char) (ch - '0'); 97 | state = sw_quoted_second; 98 | break; 99 | } 100 | 101 | c = (u_char) (ch | 0x20); 102 | if (c >= 'a' && c <= 'f') { 103 | decoded = (u_char) (c - 'a' + 10); 104 | state = sw_quoted_second; 105 | break; 106 | } 107 | 108 | /* the invalid quoted character */ 109 | 110 | state = sw_usual; 111 | 112 | *d++ = ch; 113 | 114 | break; 115 | 116 | case sw_quoted_second: 117 | 118 | state = sw_usual; 119 | 120 | if (ch >= '0' && ch <= '9') { 121 | ch = (u_char) ((decoded << 4) + ch - '0'); 122 | 123 | if (type & NGX_UNESCAPE_REDIRECT) { 124 | if (ch > '%' && ch < 0x7f) { 125 | *d++ = ch; 126 | break; 127 | } 128 | 129 | *d++ = '%'; *d++ = *(s - 2); *d++ = *(s - 1); 130 | 131 | break; 132 | } 133 | 134 | *d++ = ch; 135 | 136 | break; 137 | } 138 | 139 | c = (u_char) (ch | 0x20); 140 | if (c >= 'a' && c <= 'f') { 141 | ch = (u_char) ((decoded << 4) + c - 'a' + 10); 142 | 143 | if (type & NGX_UNESCAPE_URI) { 144 | if (ch == '?') { 145 | *d++ = ch; 146 | goto done; 147 | } 148 | 149 | *d++ = ch; 150 | break; 151 | } 152 | 153 | if (type & NGX_UNESCAPE_REDIRECT) { 154 | if (ch == '?') { 155 | *d++ = ch; 156 | goto done; 157 | } 158 | 159 | if (ch > '%' && ch < 0x7f) { 160 | *d++ = ch; 161 | break; 162 | } 163 | 164 | *d++ = '%'; *d++ = *(s - 2); *d++ = *(s - 1); 165 | break; 166 | } 167 | 168 | *d++ = ch; 169 | 170 | break; 171 | } 172 | 173 | /* the invalid quoted character */ 174 | 175 | break; 176 | } 177 | } 178 | 179 | done: 180 | 181 | *dst = d; 182 | *src = s; 183 | } 184 | 185 | -------------------------------------------------------------------------------- /src/ngx_http_set_unescape_uri.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef NGX_HTTP_SET_UNESCAPE_URI 3 | #define NGX_HTTP_SET_UNESCAPE_URI 4 | 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | 11 | ngx_int_t ngx_http_set_misc_unescape_uri(ngx_http_request_t *r, 12 | ngx_str_t *res, ngx_http_variable_value_t *v); 13 | 14 | 15 | #endif /* NGX_HTTP_SET_UNESCAPE_URI */ 16 | 17 | -------------------------------------------------------------------------------- /t/base32.t: -------------------------------------------------------------------------------- 1 | # vi:filetype= 2 | 3 | use Test::Nginx::Socket; 4 | 5 | repeat_each(3); 6 | 7 | plan tests => repeat_each() * 2 * blocks(); 8 | 9 | no_long_string(); 10 | 11 | run_tests(); 12 | 13 | #no_diff(); 14 | 15 | __DATA__ 16 | 17 | === TEST 1: base32 (5 bytes) 18 | --- config 19 | location /bar { 20 | set $a 'abcde'; 21 | set_encode_base32 $a; 22 | set $b $a; 23 | set_decode_base32 $b; 24 | 25 | echo $a; 26 | echo $b; 27 | } 28 | --- request 29 | GET /bar 30 | --- response_body 31 | c5h66p35 32 | abcde 33 | 34 | 35 | 36 | === TEST 2: base32 (1 byte) 37 | --- config 38 | location /bar { 39 | set $a '!'; 40 | set_encode_base32 $a; 41 | set $b $a; 42 | set_decode_base32 $b; 43 | 44 | echo $a; 45 | echo $b; 46 | } 47 | --- request 48 | GET /bar 49 | --- response_body 50 | 44====== 51 | ! 52 | 53 | 54 | 55 | === TEST 3: base32 (1 byte) - not in-place editing 56 | --- config 57 | location /bar { 58 | set $a '!'; 59 | set_encode_base32 $a $a; 60 | set_decode_base32 $b $a; 61 | 62 | echo $a; 63 | echo $b; 64 | } 65 | --- request 66 | GET /bar 67 | --- response_body 68 | 44====== 69 | ! 70 | 71 | 72 | 73 | === TEST 4: base32 (hello world) 74 | --- config 75 | location /bar { 76 | set $a '"hello, world!\nhiya"'; 77 | set_encode_base32 $a; 78 | set $b $a; 79 | set_decode_base32 $b; 80 | 81 | echo $a; 82 | echo $b; 83 | } 84 | --- request 85 | GET /bar 86 | --- response_body 87 | 49k6ar3cdsm20trfe9m6888ad1knio92 88 | "hello, world! 89 | hiya" 90 | 91 | 92 | 93 | === TEST 5: base32 (0 bytes left) 94 | --- config 95 | set_base32_padding on; 96 | location /bar { 97 | set $a '"hello, world!"'; 98 | set_encode_base32 $a; 99 | 100 | echo $a; 101 | } 102 | --- request 103 | GET /bar 104 | --- response_body 105 | 49k6ar3cdsm20trfe9m68892 106 | 107 | 108 | 109 | === TEST 6: base32 (6 bytes padded) 110 | --- config 111 | set_base32_padding on; 112 | location /bar { 113 | set $a '"hello, world!"a'; 114 | set_encode_base32 $a; 115 | 116 | echo $a; 117 | } 118 | --- request 119 | GET /bar 120 | --- response_body 121 | 49k6ar3cdsm20trfe9m68892c4====== 122 | 123 | 124 | 125 | === TEST 7: base32 (4 bytes left) 126 | --- config 127 | set_base32_padding on; 128 | location /bar { 129 | set $a '"hello, world!"ab'; 130 | set_encode_base32 $a; 131 | 132 | echo $a; 133 | } 134 | --- request 135 | GET /bar 136 | --- response_body 137 | 49k6ar3cdsm20trfe9m68892c5h0==== 138 | 139 | 140 | 141 | === TEST 8: base32 (3 bytes left) 142 | --- config 143 | set_base32_padding on; 144 | location /bar { 145 | set $a '"hello, world!"abc'; 146 | set_encode_base32 $a; 147 | 148 | echo $a; 149 | } 150 | --- request 151 | GET /bar 152 | --- response_body 153 | 49k6ar3cdsm20trfe9m68892c5h66=== 154 | 155 | 156 | 157 | === TEST 9: base32 (1 bytes left) 158 | --- config 159 | set_base32_padding on; 160 | location /bar { 161 | set $a '"hello, world!"abcd'; 162 | set_encode_base32 $a; 163 | 164 | echo $a; 165 | } 166 | --- request 167 | GET /bar 168 | --- response_body 169 | 49k6ar3cdsm20trfe9m68892c5h66p0= 170 | 171 | 172 | 173 | === TEST 10: base32 standard alphabet (5 bytes) 174 | --- config 175 | set_base32_alphabet "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"; 176 | location /bar { 177 | set $a 'abcde'; 178 | set_encode_base32 $a; 179 | set $b $a; 180 | set_decode_base32 $b; 181 | 182 | echo $a; 183 | echo $b; 184 | } 185 | --- request 186 | GET /bar 187 | --- response_body 188 | MFRGGZDF 189 | abcde 190 | 191 | 192 | 193 | === TEST 11: base32 standard alphabet (1 byte) 194 | --- config 195 | set_base32_alphabet "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"; 196 | location /bar { 197 | set $a '!'; 198 | set_encode_base32 $a; 199 | set $b $a; 200 | set_decode_base32 $b; 201 | 202 | echo $a; 203 | echo $b; 204 | } 205 | --- request 206 | GET /bar 207 | --- response_body 208 | EE====== 209 | ! 210 | 211 | 212 | 213 | === TEST 12: base32 standard alphabet (1 byte) - not in-place editing 214 | --- config 215 | set_base32_alphabet "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"; 216 | location /bar { 217 | set $a '!'; 218 | set_encode_base32 $a $a; 219 | set_decode_base32 $b $a; 220 | 221 | echo $a; 222 | echo $b; 223 | } 224 | --- request 225 | GET /bar 226 | --- response_body 227 | EE====== 228 | ! 229 | 230 | 231 | 232 | === TEST 13: base32 standard alphabet (hello world) 233 | --- config 234 | set_base32_alphabet "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"; 235 | location /bar { 236 | set $a '"hello, world!\nhiya"'; 237 | set_encode_base32 $a; 238 | set $b $a; 239 | set_decode_base32 $b; 240 | 241 | echo $a; 242 | echo $b; 243 | } 244 | --- request 245 | GET /bar 246 | --- response_body 247 | EJUGK3DMN4WCA53POJWGIIIKNBUXSYJC 248 | "hello, world! 249 | hiya" 250 | 251 | 252 | 253 | === TEST 14: base32 standard alphabet (0 bytes left) 254 | --- config 255 | set_base32_padding on; 256 | set_base32_alphabet "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"; 257 | location /bar { 258 | set $a '"hello, world!"'; 259 | set_encode_base32 $a; 260 | 261 | echo $a; 262 | } 263 | --- request 264 | GET /bar 265 | --- response_body 266 | EJUGK3DMN4WCA53POJWGIIJC 267 | 268 | 269 | 270 | === TEST 15: base32 standard alphabet (6 bytes padded) 271 | --- config 272 | set_base32_padding on; 273 | set_base32_alphabet "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"; 274 | location /bar { 275 | set $a '"hello, world!"a'; 276 | set_encode_base32 $a; 277 | 278 | echo $a; 279 | } 280 | --- request 281 | GET /bar 282 | --- response_body 283 | EJUGK3DMN4WCA53POJWGIIJCME====== 284 | 285 | 286 | 287 | === TEST 16: base32 standard alphabet (4 bytes left) 288 | --- config 289 | set_base32_padding on; 290 | set_base32_alphabet "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"; 291 | location /bar { 292 | set $a '"hello, world!"ab'; 293 | set_encode_base32 $a; 294 | 295 | echo $a; 296 | } 297 | --- request 298 | GET /bar 299 | --- response_body 300 | EJUGK3DMN4WCA53POJWGIIJCMFRA==== 301 | 302 | 303 | 304 | === TEST 17: base32 standard alphabet (3 bytes left) 305 | --- config 306 | set_base32_padding on; 307 | set_base32_alphabet "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"; 308 | location /bar { 309 | set $a '"hello, world!"abc'; 310 | set_encode_base32 $a; 311 | 312 | echo $a; 313 | } 314 | --- request 315 | GET /bar 316 | --- response_body 317 | EJUGK3DMN4WCA53POJWGIIJCMFRGG=== 318 | 319 | 320 | 321 | === TEST 18: base32 standard alphabet (1 bytes left) 322 | --- config 323 | set_base32_padding on; 324 | set_base32_alphabet "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"; 325 | location /bar { 326 | set $a '"hello, world!"abcd'; 327 | set_encode_base32 $a; 328 | 329 | echo $a; 330 | } 331 | --- request 332 | GET /bar 333 | --- response_body 334 | EJUGK3DMN4WCA53POJWGIIJCMFRGGZA= 335 | 336 | 337 | 338 | === TEST 19: base32 custom alphabet (5 bytes) 339 | --- config 340 | set_base32_alphabet "efghijklmnopqrstuvwxyz0123456789"; 341 | location /bar { 342 | set $a 'abcde'; 343 | set_encode_base32 $a; 344 | set $b $a; 345 | set_decode_base32 $b; 346 | 347 | echo $a; 348 | echo $b; 349 | } 350 | --- request 351 | GET /bar 352 | --- response_body 353 | qjvkk3hj 354 | abcde 355 | 356 | 357 | 358 | === TEST 20: base32 custom alphabet (1 byte) 359 | --- config 360 | set_base32_alphabet "efghijklmnopqrstuvwxyz0123456789"; 361 | location /bar { 362 | set $a '!'; 363 | set_encode_base32 $a; 364 | set $b $a; 365 | set_decode_base32 $b; 366 | 367 | echo $a; 368 | echo $b; 369 | } 370 | --- request 371 | GET /bar 372 | --- response_body 373 | ii====== 374 | ! 375 | 376 | 377 | 378 | === TEST 21: base32 custom alphabet (1 byte) - not in-place editing 379 | --- config 380 | set_base32_alphabet "efghijklmnopqrstuvwxyz0123456789"; 381 | location /bar { 382 | set $a '!'; 383 | set_encode_base32 $a $a; 384 | set_decode_base32 $b $a; 385 | 386 | echo $a; 387 | echo $b; 388 | } 389 | --- request 390 | GET /bar 391 | --- response_body 392 | ii====== 393 | ! 394 | 395 | 396 | 397 | === TEST 22: base32 custom alphabet (hello world) 398 | --- config 399 | set_base32_alphabet "efghijklmnopqrstuvwxyz0123456789"; 400 | location /bar { 401 | set $a '"hello, world!\nhiya"'; 402 | set_encode_base32 $a; 403 | set $b $a; 404 | set_decode_base32 $b; 405 | 406 | echo $a; 407 | echo $b; 408 | } 409 | --- request 410 | GET /bar 411 | --- response_body 412 | inyko5hqr60ge75tsn0kmmmorfy1w2ng 413 | "hello, world! 414 | hiya" 415 | 416 | 417 | 418 | === TEST 23: base32 custom alphabet (0 bytes left) 419 | --- config 420 | set_base32_padding on; 421 | set_base32_alphabet "efghijklmnopqrstuvwxyz0123456789"; 422 | location /bar { 423 | set $a '"hello, world!"'; 424 | set_encode_base32 $a; 425 | 426 | echo $a; 427 | } 428 | --- request 429 | GET /bar 430 | --- response_body 431 | inyko5hqr60ge75tsn0kmmng 432 | 433 | 434 | 435 | === TEST 24: base32 custom alphabet (6 bytes padded) 436 | --- config 437 | set_base32_padding on; 438 | set_base32_alphabet "efghijklmnopqrstuvwxyz0123456789"; 439 | location /bar { 440 | set $a '"hello, world!"a'; 441 | set_encode_base32 $a; 442 | 443 | echo $a; 444 | } 445 | --- request 446 | GET /bar 447 | --- response_body 448 | inyko5hqr60ge75tsn0kmmngqi====== 449 | 450 | 451 | 452 | === TEST 25: base32 custom alphabet (4 bytes left) 453 | --- config 454 | set_base32_padding on; 455 | set_base32_alphabet "efghijklmnopqrstuvwxyz0123456789"; 456 | location /bar { 457 | set $a '"hello, world!"ab'; 458 | set_encode_base32 $a; 459 | 460 | echo $a; 461 | } 462 | --- request 463 | GET /bar 464 | --- response_body 465 | inyko5hqr60ge75tsn0kmmngqjve==== 466 | 467 | 468 | 469 | === TEST 26: base32 custom alphabet (3 bytes left) 470 | --- config 471 | set_base32_padding on; 472 | set_base32_alphabet "efghijklmnopqrstuvwxyz0123456789"; 473 | location /bar { 474 | set $a '"hello, world!"abc'; 475 | set_encode_base32 $a; 476 | 477 | echo $a; 478 | } 479 | --- request 480 | GET /bar 481 | --- response_body 482 | inyko5hqr60ge75tsn0kmmngqjvkk=== 483 | 484 | 485 | 486 | === TEST 27: base32 custom alphabet (1 bytes left) 487 | --- config 488 | set_base32_padding on; 489 | set_base32_alphabet "efghijklmnopqrstuvwxyz0123456789"; 490 | location /bar { 491 | set $a '"hello, world!"abcd'; 492 | set_encode_base32 $a; 493 | 494 | echo $a; 495 | } 496 | --- request 497 | GET /bar 498 | --- response_body 499 | inyko5hqr60ge75tsn0kmmngqjvkk3e= 500 | 501 | 502 | 503 | === TEST 28: use set_base32_alphabet in location 504 | --- config 505 | set_base32_padding on; 506 | location /bar { 507 | set_base32_alphabet "efghijklmnopqrstuvwxyz0123456789"; 508 | set $a '"hello, world!"abcd'; 509 | set_encode_base32 $a; 510 | 511 | echo $a; 512 | } 513 | --- request 514 | GET /bar 515 | --- response_body 516 | inyko5hqr60ge75tsn0kmmngqjvkk3e= 517 | 518 | 519 | 520 | === TEST 29: one byte less in set_base32_alphabet 521 | --- config 522 | set_base32_padding on; 523 | location /bar { 524 | set_base32_alphabet "efghijklmnopqrstuvwxyz012345678"; 525 | set $a '"hello, world!"abcd?\/.;'; 526 | set_encode_base32 $a; 527 | 528 | echo $a; 529 | } 530 | --- request 531 | GET /bar 532 | --- response_body 533 | inyko5hqr60ge75tsn0kmmngqjvkk3e= 534 | --- must_die 535 | --- error_log eval 536 | qr/\[emerg\] .*? "set_base32_alphabet" directive takes an alphabet of 31 bytes but 32 expected/ 537 | 538 | 539 | 540 | === TEST 30: one byte more in set_base32_alphabet 541 | --- config 542 | set_base32_padding on; 543 | location /bar { 544 | set_base32_alphabet "efghijklmnopqrstuvwxyz0123456789A"; 545 | set $a '"hello, world!"abcd?\/.;'; 546 | set_encode_base32 $a; 547 | 548 | echo $a; 549 | } 550 | --- request 551 | GET /bar 552 | --- response_body 553 | inyko5hqr60ge75tsn0kmmngqjvkk3e= 554 | --- must_die 555 | --- error_log eval 556 | qr/\[emerg\] .*? "set_base32_alphabet" directive takes an alphabet of 33 bytes but 32 expected/ 557 | -------------------------------------------------------------------------------- /t/base32_no_padding.t: -------------------------------------------------------------------------------- 1 | # vi:filetype= 2 | 3 | use Test::Nginx::Socket; 4 | 5 | repeat_each(3); 6 | 7 | plan tests => repeat_each() * 2 * blocks(); 8 | 9 | no_long_string(); 10 | 11 | run_tests(); 12 | 13 | #no_diff(); 14 | 15 | __DATA__ 16 | 17 | === TEST 1: base32 (5 bytes) 18 | --- config 19 | set_base32_padding off; 20 | location /bar { 21 | set $a 'abcde'; 22 | set_encode_base32 $a; 23 | set $b $a; 24 | set_decode_base32 $b; 25 | 26 | echo $a; 27 | echo $b; 28 | } 29 | --- request 30 | GET /bar 31 | --- response_body 32 | c5h66p35 33 | abcde 34 | 35 | 36 | 37 | === TEST 2: base32 (1 byte) 38 | --- config 39 | set_base32_padding off; 40 | location /bar { 41 | set $a '!'; 42 | set_encode_base32 $a; 43 | set $b $a; 44 | set_decode_base32 $b; 45 | 46 | echo $a; 47 | echo $b; 48 | } 49 | --- request 50 | GET /bar 51 | --- response_body 52 | 44 53 | ! 54 | 55 | 56 | 57 | === TEST 3: base32 (1 byte) - not in-place editing 58 | --- config 59 | location /bar { 60 | set_base32_padding off; 61 | set $a '!'; 62 | set_encode_base32 $a $a; 63 | set_decode_base32 $b $a; 64 | 65 | echo $a; 66 | echo $b; 67 | } 68 | --- request 69 | GET /bar 70 | --- response_body 71 | 44 72 | ! 73 | 74 | 75 | 76 | === TEST 4: base32 (hello world) 77 | --- config 78 | set_base32_padding off; 79 | location /bar { 80 | set $a '"hello, world!\nhiya"'; 81 | set_encode_base32 $a; 82 | set $b $a; 83 | set_decode_base32 $b; 84 | 85 | echo $a; 86 | echo $b; 87 | } 88 | --- request 89 | GET /bar 90 | --- response_body 91 | 49k6ar3cdsm20trfe9m6888ad1knio92 92 | "hello, world! 93 | hiya" 94 | 95 | 96 | 97 | === TEST 5: base32 (0 bytes left) 98 | --- config 99 | set_base32_padding off; 100 | location /bar { 101 | set $a '"hello, world!"'; 102 | set_encode_base32 $a; 103 | 104 | echo $a; 105 | } 106 | --- request 107 | GET /bar 108 | --- response_body 109 | 49k6ar3cdsm20trfe9m68892 110 | 111 | 112 | 113 | === TEST 6: base32 (6 bytes padded) 114 | --- config 115 | set_base32_padding off; 116 | location /bar { 117 | set $a '"hello, world!"a'; 118 | set_encode_base32 $a; 119 | 120 | echo $a; 121 | } 122 | --- request 123 | GET /bar 124 | --- response_body 125 | 49k6ar3cdsm20trfe9m68892c4 126 | 127 | 128 | 129 | === TEST 7: base32 (4 bytes left) 130 | --- config 131 | set_base32_padding off; 132 | location /bar { 133 | set $a '"hello, world!"ab'; 134 | set_encode_base32 $a; 135 | 136 | echo $a; 137 | } 138 | --- request 139 | GET /bar 140 | --- response_body 141 | 49k6ar3cdsm20trfe9m68892c5h0 142 | 143 | 144 | 145 | === TEST 8: base32 (3 bytes left) 146 | --- config 147 | set_base32_padding off; 148 | location /bar { 149 | set $a '"hello, world!"abc'; 150 | set_encode_base32 $a; 151 | 152 | echo $a; 153 | } 154 | --- request 155 | GET /bar 156 | --- response_body 157 | 49k6ar3cdsm20trfe9m68892c5h66 158 | 159 | 160 | 161 | === TEST 9: base32 (1 bytes left) 162 | --- config 163 | set_base32_padding off; 164 | location /bar { 165 | set $a '"hello, world!"abcd'; 166 | set_encode_base32 $a; 167 | 168 | echo $a; 169 | } 170 | --- request 171 | GET /bar 172 | --- response_body 173 | 49k6ar3cdsm20trfe9m68892c5h66p0 174 | 175 | 176 | 177 | === TEST 10: base32 standard alphabet (5 bytes) 178 | --- config 179 | set_base32_padding off; 180 | set_base32_alphabet "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"; 181 | location /bar { 182 | set $a 'abcde'; 183 | set_encode_base32 $a; 184 | set $b $a; 185 | set_decode_base32 $b; 186 | 187 | echo $a; 188 | echo $b; 189 | } 190 | --- request 191 | GET /bar 192 | --- response_body 193 | MFRGGZDF 194 | abcde 195 | 196 | 197 | 198 | === TEST 11: base32 standard alphabet (1 byte) 199 | --- config 200 | set_base32_padding off; 201 | set_base32_alphabet "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"; 202 | location /bar { 203 | set $a '!'; 204 | set_encode_base32 $a; 205 | set $b $a; 206 | set_decode_base32 $b; 207 | 208 | echo $a; 209 | echo $b; 210 | } 211 | --- request 212 | GET /bar 213 | --- response_body 214 | EE 215 | ! 216 | 217 | 218 | 219 | === TEST 12: base32 standard alphabet (1 byte) - not in-place editing 220 | --- config 221 | location /bar { 222 | set_base32_padding off; 223 | set_base32_alphabet "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"; 224 | set $a '!'; 225 | set_encode_base32 $a $a; 226 | set_decode_base32 $b $a; 227 | 228 | echo $a; 229 | echo $b; 230 | } 231 | --- request 232 | GET /bar 233 | --- response_body 234 | EE 235 | ! 236 | 237 | 238 | 239 | === TEST 13: base32 standard alphabet (hello world) 240 | --- config 241 | set_base32_padding off; 242 | set_base32_alphabet "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"; 243 | location /bar { 244 | set $a '"hello, world!\nhiya"'; 245 | set_encode_base32 $a; 246 | set $b $a; 247 | set_decode_base32 $b; 248 | 249 | echo $a; 250 | echo $b; 251 | } 252 | --- request 253 | GET /bar 254 | --- response_body 255 | EJUGK3DMN4WCA53POJWGIIIKNBUXSYJC 256 | "hello, world! 257 | hiya" 258 | 259 | 260 | 261 | === TEST 14: base32 standard alphabet (0 bytes left) 262 | --- config 263 | set_base32_padding off; 264 | set_base32_alphabet "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"; 265 | location /bar { 266 | set $a '"hello, world!"'; 267 | set_encode_base32 $a; 268 | 269 | echo $a; 270 | } 271 | --- request 272 | GET /bar 273 | --- response_body 274 | EJUGK3DMN4WCA53POJWGIIJC 275 | 276 | 277 | 278 | === TEST 15: base32 standard alphabet (6 bytes padded) 279 | --- config 280 | set_base32_padding off; 281 | set_base32_alphabet "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"; 282 | location /bar { 283 | set $a '"hello, world!"a'; 284 | set_encode_base32 $a; 285 | 286 | echo $a; 287 | } 288 | --- request 289 | GET /bar 290 | --- response_body 291 | EJUGK3DMN4WCA53POJWGIIJCME 292 | 293 | 294 | 295 | === TEST 16: base32 standard alphabet (4 bytes left) 296 | --- config 297 | set_base32_padding off; 298 | set_base32_alphabet "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"; 299 | location /bar { 300 | set $a '"hello, world!"ab'; 301 | set_encode_base32 $a; 302 | 303 | echo $a; 304 | } 305 | --- request 306 | GET /bar 307 | --- response_body 308 | EJUGK3DMN4WCA53POJWGIIJCMFRA 309 | 310 | 311 | 312 | === TEST 17: base32 standard alphabet (3 bytes left) 313 | --- config 314 | set_base32_padding off; 315 | set_base32_alphabet "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"; 316 | location /bar { 317 | set $a '"hello, world!"abc'; 318 | set_encode_base32 $a; 319 | 320 | echo $a; 321 | } 322 | --- request 323 | GET /bar 324 | --- response_body 325 | EJUGK3DMN4WCA53POJWGIIJCMFRGG 326 | 327 | 328 | 329 | === TEST 18: base32 standard alphabet (1 bytes left) 330 | --- config 331 | set_base32_padding off; 332 | set_base32_alphabet "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"; 333 | location /bar { 334 | set $a '"hello, world!"abcd'; 335 | set_encode_base32 $a; 336 | 337 | echo $a; 338 | } 339 | --- request 340 | GET /bar 341 | --- response_body 342 | EJUGK3DMN4WCA53POJWGIIJCMFRGGZA 343 | 344 | 345 | 346 | === TEST 19: base32 custom alphabet (5 bytes) 347 | --- config 348 | set_base32_padding off; 349 | set_base32_alphabet "cdefghijklmnopqrstuvwxyz12345678"; 350 | location /bar { 351 | set $a 'abcde'; 352 | set_encode_base32 $a; 353 | set $b $a; 354 | set_decode_base32 $b; 355 | 356 | echo $a; 357 | echo $b; 358 | } 359 | --- request 360 | GET /bar 361 | --- response_body 362 | ohtii2fh 363 | abcde 364 | 365 | 366 | 367 | === TEST 20: base32 custom alphabet (1 byte) 368 | --- config 369 | set_base32_padding off; 370 | set_base32_alphabet "cdefghijklmnopqrstuvwxyz12345678"; 371 | location /bar { 372 | set $a '!'; 373 | set_encode_base32 $a; 374 | set $b $a; 375 | set_decode_base32 $b; 376 | 377 | echo $a; 378 | echo $b; 379 | } 380 | --- request 381 | GET /bar 382 | --- response_body 383 | gg 384 | ! 385 | 386 | 387 | 388 | === TEST 21: base32 custom alphabet (1 byte) - not in-place editing 389 | --- config 390 | location /bar { 391 | set_base32_padding off; 392 | set_base32_alphabet "cdefghijklmnopqrstuvwxyz12345678"; 393 | set $a '!'; 394 | set_encode_base32 $a $a; 395 | set_decode_base32 $b $a; 396 | 397 | echo $a; 398 | echo $b; 399 | } 400 | --- request 401 | GET /bar 402 | --- response_body 403 | gg 404 | ! 405 | 406 | 407 | 408 | === TEST 22: base32 custom alphabet (hello world) 409 | --- config 410 | set_base32_padding off; 411 | set_base32_alphabet "cdefghijklmnopqrstuvwxyz12345678"; 412 | location /bar { 413 | set $a '"hello, world!\nhiya"'; 414 | set_encode_base32 $a; 415 | set $b $a; 416 | set_decode_base32 $b; 417 | 418 | echo $a; 419 | echo $b; 420 | } 421 | --- request 422 | GET /bar 423 | --- response_body 424 | glwim4fop5yec64rqlyikkkmpdwzu1le 425 | "hello, world! 426 | hiya" 427 | 428 | 429 | 430 | === TEST 23: base32 custom alphabet (0 bytes left) 431 | --- config 432 | set_base32_padding off; 433 | set_base32_alphabet "cdefghijklmnopqrstuvwxyz12345678"; 434 | location /bar { 435 | set $a '"hello, world!"'; 436 | set_encode_base32 $a; 437 | 438 | echo $a; 439 | } 440 | --- request 441 | GET /bar 442 | --- response_body 443 | glwim4fop5yec64rqlyikkle 444 | 445 | 446 | 447 | === TEST 24: base32 custom alphabet (6 bytes padded) 448 | --- config 449 | set_base32_padding off; 450 | set_base32_alphabet "cdefghijklmnopqrstuvwxyz12345678"; 451 | location /bar { 452 | set $a '"hello, world!"a'; 453 | set_encode_base32 $a; 454 | 455 | echo $a; 456 | } 457 | --- request 458 | GET /bar 459 | --- response_body 460 | glwim4fop5yec64rqlyikkleog 461 | 462 | 463 | 464 | === TEST 25: base32 custom alphabet (4 bytes left) 465 | --- config 466 | set_base32_padding off; 467 | set_base32_alphabet "cdefghijklmnopqrstuvwxyz12345678"; 468 | location /bar { 469 | set $a '"hello, world!"ab'; 470 | set_encode_base32 $a; 471 | 472 | echo $a; 473 | } 474 | --- request 475 | GET /bar 476 | --- response_body 477 | glwim4fop5yec64rqlyikkleohtc 478 | 479 | 480 | 481 | === TEST 26: base32 custom alphabet (3 bytes left) 482 | --- config 483 | set_base32_padding off; 484 | set_base32_alphabet "cdefghijklmnopqrstuvwxyz12345678"; 485 | location /bar { 486 | set $a '"hello, world!"abc'; 487 | set_encode_base32 $a; 488 | 489 | echo $a; 490 | } 491 | --- request 492 | GET /bar 493 | --- response_body 494 | glwim4fop5yec64rqlyikkleohtii 495 | 496 | 497 | 498 | === TEST 27: base32 custom alphabet (1 bytes left) 499 | --- config 500 | set_base32_padding off; 501 | set_base32_alphabet "cdefghijklmnopqrstuvwxyz12345678"; 502 | location /bar { 503 | set $a '"hello, world!"abcd'; 504 | set_encode_base32 $a; 505 | 506 | echo $a; 507 | } 508 | --- request 509 | GET /bar 510 | --- response_body 511 | glwim4fop5yec64rqlyikkleohtii2c 512 | 513 | 514 | 515 | === TEST 28: deprecated set_misc_base32_padding 516 | --- config 517 | set_misc_base32_padding off; 518 | location /bar { 519 | set $a 'abcde'; 520 | set_encode_base32 $a; 521 | set $b $a; 522 | set_decode_base32 $b; 523 | 524 | echo $a; 525 | echo $b; 526 | } 527 | --- request 528 | GET /bar 529 | --- response_body 530 | c5h66p35 531 | abcde 532 | -------------------------------------------------------------------------------- /t/base64.t: -------------------------------------------------------------------------------- 1 | # vi:filetype= 2 | 3 | use lib 'lib'; 4 | use Test::Nginx::Socket; 5 | 6 | #repeat_each(3); 7 | 8 | plan tests => repeat_each() * 2 * blocks(); 9 | 10 | no_long_string(); 11 | 12 | run_tests(); 13 | 14 | #no_diff(); 15 | 16 | __DATA__ 17 | 18 | === TEST 1: base64 encode 19 | --- config 20 | location /bar { 21 | set_encode_base64 $out "abcde"; 22 | echo $out; 23 | } 24 | --- request 25 | GET /bar 26 | --- response_body 27 | YWJjZGU= 28 | 29 | 30 | 31 | === TEST 2: base64 decode 32 | --- config 33 | location /bar { 34 | set_decode_base64 $out "YWJjZGU="; 35 | echo $out; 36 | } 37 | --- request 38 | GET /bar 39 | --- response_body 40 | abcde 41 | -------------------------------------------------------------------------------- /t/base64url.t: -------------------------------------------------------------------------------- 1 | # vi:filetype= 2 | 3 | use lib 'lib'; 4 | use Test::Nginx::Socket; 5 | 6 | #repeat_each(3); 7 | 8 | plan tests => repeat_each() * 2 * blocks(); 9 | 10 | no_long_string(); 11 | 12 | run_tests(); 13 | 14 | #no_diff(); 15 | 16 | __DATA__ 17 | 18 | === TEST 1: base64url encode 19 | --- config 20 | location /bar { 21 | set_encode_base64url $out "?b> repeat_each() * 2 * blocks(); 9 | 10 | no_long_string(); 11 | 12 | run_tests(); 13 | 14 | #no_diff(); 15 | 16 | __DATA__ 17 | 18 | === TEST 1: set if empty 19 | --- config 20 | location /foo { 21 | set $a 32; 22 | set_if_empty $a 56; 23 | echo $a; 24 | 25 | set_if_empty $b 72; 26 | echo $b; 27 | } 28 | --- request 29 | GET /foo 30 | --- response_body 31 | 32 32 | 72 33 | 34 | 35 | 36 | === TEST 2: set if empty 37 | --- config 38 | location /foo { 39 | set $bar $arg_bar; 40 | set_if_empty $bar 15; 41 | echo $bar; 42 | 43 | set $bah $arg_bah; 44 | set_if_empty $bah 25; 45 | echo $bah; 46 | } 47 | --- request 48 | GET /foo?bar=71 49 | --- response_body 50 | 71 51 | 25 52 | 53 | 54 | 55 | === TEST 3: set if empty 56 | --- config 57 | location /foo { 58 | set $bar $arg_bar; 59 | set_if_empty $bar 15; 60 | echo $bar; 61 | 62 | set $bah $arg_bah; 63 | set_if_empty $bah 25; 64 | echo $bah; 65 | } 66 | --- request 67 | GET /foo?bar= 68 | --- response_body 69 | 15 70 | 25 71 | 72 | 73 | 74 | === TEST 4: set if empty (using arg_xxx directly) 75 | buggy? 76 | --- config 77 | location /foo { 78 | set_if_empty $arg_bar 15; 79 | echo $arg_bar; 80 | 81 | set_if_empty $arg_bah 25; 82 | echo $arg_bah; 83 | } 84 | --- request 85 | GET /foo?bar=71 86 | --- response_body 87 | 71 88 | 25 89 | -------------------------------------------------------------------------------- /t/escape-uri.t: -------------------------------------------------------------------------------- 1 | # vi:filetype= 2 | 3 | use lib 'lib'; 4 | use Test::Nginx::Socket; 5 | 6 | repeat_each(3); 7 | 8 | plan tests => repeat_each() * 2 * blocks(); 9 | 10 | no_long_string(); 11 | #no_diff(); 12 | 13 | run_tests(); 14 | 15 | __DATA__ 16 | 17 | === TEST 1: set escape uri 18 | --- config 19 | location /foo { 20 | set $foo "hello world"; 21 | set_escape_uri $foo $foo; 22 | echo $foo; 23 | } 24 | --- request 25 | GET /foo 26 | --- response_body 27 | hello%20world 28 | 29 | 30 | 31 | === TEST 2: set escape uri(in-place) 32 | --- config 33 | location /foo { 34 | set $foo "hello world"; 35 | set_escape_uri $foo; 36 | echo $foo; 37 | } 38 | --- request 39 | GET /foo 40 | --- response_body 41 | hello%20world 42 | 43 | 44 | 45 | === TEST 3: blank string 46 | --- config 47 | location /foo { 48 | set $foo ""; 49 | set_escape_uri $foo; 50 | echo $foo; 51 | } 52 | --- request 53 | GET /foo 54 | --- response_body eval 55 | "\n" 56 | 57 | 58 | 59 | === TEST 4: blank string(in place) 60 | --- config 61 | location /foo { 62 | set $foo ""; 63 | set_escape_uri $foo; 64 | echo $foo; 65 | } 66 | --- request 67 | GET /foo 68 | --- response_body eval 69 | "\n" 70 | 71 | 72 | 73 | === TEST 5: eacape chinese character 74 | --- config 75 | location /foo { 76 | set $foo "你好"; 77 | set_escape_uri $foo; 78 | echo $foo; 79 | } 80 | --- request 81 | GET /foo 82 | --- response_body 83 | %E4%BD%A0%E5%A5%BD 84 | 85 | 86 | 87 | === TEST 6: escape long string 88 | --- config 89 | location /foo { 90 | set $foo "法规及饿哦物权法家哦低价非结果哦我二期界 附件饿哦武器 积分饿哦为契机佛i 该软件哦气氛 份额叫我起 国无二君哦气氛为界非ieowq结果哦而完全附件 份额叫我iqfjeowiqgjeriowqfjpdjfosadijfoiasdjf 附件饿哦武器界 份额叫我起界份额叫我起哦ifjefejwioq附件饿哦武器界非风格及去哦根据份额叫我起哦界份额为契机哦乳房阿基完全哦igqtewqo个人就去哦ieorjwrewqoi日哦额外起今天诶哦我亲热为特务前日哦我而哥特完全哦iijrtewmkdf 服务鄂潜江哦irewq"; 91 | set_escape_uri $foo; 92 | echo $foo; 93 | } 94 | --- request 95 | GET /foo 96 | --- response_body 97 | %E6%B3%95%E8%A7%84%E5%8F%8A%E9%A5%BF%E5%93%A6%E7%89%A9%E6%9D%83%E6%B3%95%E5%AE%B6%E5%93%A6%E4%BD%8E%E4%BB%B7%E9%9D%9E%E7%BB%93%E6%9E%9C%E5%93%A6%E6%88%91%E4%BA%8C%E6%9C%9F%E7%95%8C%20%20%E9%99%84%E4%BB%B6%E9%A5%BF%E5%93%A6%E6%AD%A6%E5%99%A8%20%20%E7%A7%AF%E5%88%86%E9%A5%BF%E5%93%A6%E4%B8%BA%E5%A5%91%E6%9C%BA%E4%BD%9Bi%20%E8%AF%A5%E8%BD%AF%E4%BB%B6%E5%93%A6%E6%B0%94%E6%B0%9B%20%20%E4%BB%BD%E9%A2%9D%E5%8F%AB%E6%88%91%E8%B5%B7%20%E5%9B%BD%E6%97%A0%E4%BA%8C%E5%90%9B%E5%93%A6%E6%B0%94%E6%B0%9B%E4%B8%BA%E7%95%8C%E9%9D%9Eieowq%E7%BB%93%E6%9E%9C%E5%93%A6%E8%80%8C%E5%AE%8C%E5%85%A8%E9%99%84%E4%BB%B6%20%20%E4%BB%BD%E9%A2%9D%E5%8F%AB%E6%88%91iqfjeowiqgjeriowqfjpdjfosadijfoiasdjf%20%E9%99%84%E4%BB%B6%E9%A5%BF%E5%93%A6%E6%AD%A6%E5%99%A8%E7%95%8C%20%E4%BB%BD%E9%A2%9D%E5%8F%AB%E6%88%91%E8%B5%B7%E7%95%8C%E4%BB%BD%E9%A2%9D%E5%8F%AB%E6%88%91%E8%B5%B7%E5%93%A6ifjefejwioq%E9%99%84%E4%BB%B6%E9%A5%BF%E5%93%A6%E6%AD%A6%E5%99%A8%E7%95%8C%E9%9D%9E%E9%A3%8E%E6%A0%BC%E5%8F%8A%E5%8E%BB%E5%93%A6%E6%A0%B9%E6%8D%AE%E4%BB%BD%E9%A2%9D%E5%8F%AB%E6%88%91%E8%B5%B7%E5%93%A6%E7%95%8C%E4%BB%BD%E9%A2%9D%E4%B8%BA%E5%A5%91%E6%9C%BA%E5%93%A6%E4%B9%B3%E6%88%BF%E9%98%BF%E5%9F%BA%E5%AE%8C%E5%85%A8%E5%93%A6igqtewqo%E4%B8%AA%E4%BA%BA%E5%B0%B1%E5%8E%BB%E5%93%A6ieorjwrewqoi%E6%97%A5%E5%93%A6%E9%A2%9D%E5%A4%96%E8%B5%B7%E4%BB%8A%E5%A4%A9%E8%AF%B6%E5%93%A6%E6%88%91%E4%BA%B2%E7%83%AD%E4%B8%BA%E7%89%B9%E5%8A%A1%E5%89%8D%E6%97%A5%E5%93%A6%E6%88%91%E8%80%8C%E5%93%A5%E7%89%B9%E5%AE%8C%E5%85%A8%E5%93%A6iijrtewmkdf%20%E6%9C%8D%E5%8A%A1%E9%84%82%E6%BD%9C%E6%B1%9F%E5%93%A6irewq 98 | 99 | 100 | 101 | === TEST 7: no need to escape 102 | --- config 103 | location /foo { 104 | set $foo 'welcometotheworldofnginx'; 105 | set_escape_uri $foo; 106 | echo $foo; 107 | } 108 | --- request 109 | GET /foo 110 | --- response_body 111 | welcometotheworldofnginx 112 | 113 | 114 | 115 | === TEST 8: fixed ngx_escape_uri issues: + and / should also be escaped 116 | --- config 117 | location /foo { 118 | set $foo '+/='; 119 | set_escape_uri $foo; 120 | echo $foo; 121 | } 122 | --- request 123 | GET /foo 124 | --- response_body 125 | %2B%2F%3D 126 | 127 | 128 | 129 | === TEST 9: fixed ngx_escape_uri issues: / {} : & [] and more 130 | --- config 131 | location /foo { 132 | set $foo '"a/b={}:<>;&[]\\^'; 133 | set_escape_uri $foo; 134 | echo $foo; 135 | } 136 | --- request 137 | GET /foo 138 | --- response_body 139 | %22a%2Fb%3D%7B%7D%3A%3C%3E%3B%26%5B%5D%5C%5E 140 | -------------------------------------------------------------------------------- /t/formatted-time.t: -------------------------------------------------------------------------------- 1 | # vi:filetype= 2 | 3 | use lib 'lib'; 4 | use Test::Nginx::Socket; 5 | use POSIX qw(strftime); 6 | 7 | my $fmt="%a %b %e %H:%M:%S %Y"; 8 | 9 | our $str_local = (strftime $fmt, localtime time()).'|'.(strftime $fmt, localtime time()+1).'|'.(strftime $fmt, localtime time()+2); 10 | 11 | our $str_gmt = (strftime $fmt, gmtime time()).'|'.(strftime $fmt, gmtime time()+1).'|'.(strftime $fmt, gmtime time()+2); 12 | 13 | repeat_each(2); 14 | 15 | plan tests => repeat_each() * 2 * blocks(); 16 | 17 | log_level('warn'); 18 | 19 | run_tests(); 20 | 21 | #no_diff(); 22 | 23 | __DATA__ 24 | 25 | === TEST 1: local time format 26 | --- config 27 | location /foo { 28 | set_formatted_local_time $today "%a %b %e %H:%M:%S %Y"; 29 | echo $today; 30 | } 31 | --- request 32 | GET /foo 33 | --- response_body_like eval: $main::str_local 34 | 35 | 36 | 37 | === TEST 2: GMT time format 38 | --- config 39 | location /bar { 40 | set_formatted_gmt_time $today "%a %b %e %H:%M:%S %Y"; 41 | echo $today; 42 | } 43 | --- request 44 | GET /bar 45 | --- response_body_like eval: $main::str_gmt 46 | 47 | 48 | 49 | === TEST 3: set_formatted_gmt_time (empty formatter) 50 | --- config 51 | location /bar { 52 | set_formatted_gmt_time $today ""; 53 | echo "[$today]"; 54 | } 55 | --- request 56 | GET /bar 57 | --- response_body 58 | [] 59 | 60 | 61 | 62 | === TEST 4: set_formatted_local_time (empty formatter) 63 | --- config 64 | location /bar { 65 | set_formatted_local_time $today ""; 66 | echo "[$today]"; 67 | } 68 | --- request 69 | GET /bar 70 | --- response_body 71 | [] 72 | 73 | 74 | 75 | === TEST 5: set_formatted_local_time (constant formatter) 76 | --- config 77 | location /bar { 78 | set_formatted_local_time $today "hello world"; 79 | echo "[$today]"; 80 | } 81 | --- request 82 | GET /bar 83 | --- response_body 84 | [hello world] 85 | -------------------------------------------------------------------------------- /t/hash.t: -------------------------------------------------------------------------------- 1 | # vi:filetype=perl 2 | 3 | use lib 'lib'; 4 | use Test::Nginx::Socket; 5 | 6 | #repeat_each(3); 7 | 8 | plan tests => repeat_each() * 2 * blocks(); 9 | 10 | no_long_string(); 11 | 12 | run_tests(); 13 | 14 | #no_diff(); 15 | 16 | __DATA__ 17 | 18 | === TEST 1: sha1 hello (copy) 19 | --- config 20 | location /sha1 { 21 | set_sha1 $a hello; 22 | echo $a; 23 | } 24 | --- request 25 | GET /sha1 26 | --- response_body 27 | aaf4c61ddcc5e8a2dabede0f3b482cd9aea9434d 28 | 29 | 30 | 31 | === TEST 2: sha1 hello (in-place) 32 | --- config 33 | location /sha1 { 34 | set $a hello; 35 | set_sha1 $a; 36 | echo $a; 37 | } 38 | --- request 39 | GET /sha1 40 | --- response_body 41 | aaf4c61ddcc5e8a2dabede0f3b482cd9aea9434d 42 | 43 | 44 | 45 | === TEST 3: sha1 (empty) 46 | --- config 47 | location /sha1 { 48 | set_sha1 $a ""; 49 | echo $a; 50 | } 51 | --- request 52 | GET /sha1 53 | --- response_body 54 | da39a3ee5e6b4b0d3255bfef95601890afd80709 55 | 56 | 57 | 58 | === TEST 4: md5 hello (copy) 59 | --- config 60 | location /md5 { 61 | set_md5 $a hello; 62 | echo $a; 63 | } 64 | --- request 65 | GET /md5 66 | --- response_body 67 | 5d41402abc4b2a76b9719d911017c592 68 | 69 | 70 | 71 | === TEST 5: md5 hello (in-place) 72 | --- config 73 | location /md5 { 74 | set $a hello; 75 | set_md5 $a; 76 | echo $a; 77 | } 78 | --- request 79 | GET /md5 80 | --- response_body 81 | 5d41402abc4b2a76b9719d911017c592 82 | 83 | 84 | 85 | === TEST 6: md5 (empty) 86 | --- config 87 | location /md5 { 88 | set_md5 $a ""; 89 | echo $a; 90 | } 91 | --- request 92 | GET /md5 93 | --- response_body 94 | d41d8cd98f00b204e9800998ecf8427e 95 | -------------------------------------------------------------------------------- /t/hashed-upstream.t: -------------------------------------------------------------------------------- 1 | # vi:filetype= 2 | 3 | use lib 'lib'; 4 | use Test::Nginx::Socket; 5 | 6 | #repeat_each(3); 7 | 8 | plan tests => repeat_each() * 2 * blocks(); 9 | 10 | no_long_string(); 11 | 12 | #master_on(); 13 | #log_level("warn"); 14 | 15 | run_tests(); 16 | 17 | #no_diff(); 18 | 19 | __DATA__ 20 | 21 | === TEST 1: set hashed upstream 22 | buggy? 23 | --- config 24 | upstream_list universe moon sun earth; 25 | location /foo { 26 | set_hashed_upstream $backend universe $arg_id; 27 | echo $backend; 28 | } 29 | location /main { 30 | echo_location_async /foo; 31 | echo_location_async /foo?id=hello; 32 | echo_location_async /foo?id=world; 33 | echo_location_async /foo?id=larry; 34 | echo_location_async /foo?id=audreyt; 35 | } 36 | --- request 37 | GET /main 38 | --- response_body 39 | moon 40 | sun 41 | moon 42 | earth 43 | earth 44 | 45 | 46 | 47 | === TEST 2: set hashed upstream (use var for upstream_list name) 48 | buggy? 49 | --- config 50 | upstream_list universe moon sun earth; 51 | location /foo { 52 | set $list_name universe; 53 | set_hashed_upstream $backend $list_name $arg_id; 54 | echo $backend; 55 | } 56 | location /main { 57 | echo_location_async /foo; 58 | echo_location_async /foo?id=hello; 59 | echo_location_async /foo?id=world; 60 | echo_location_async /foo?id=larry; 61 | echo_location_async /foo?id=audreyt; 62 | } 63 | --- request 64 | GET /main 65 | --- response_body 66 | moon 67 | sun 68 | moon 69 | earth 70 | earth 71 | -------------------------------------------------------------------------------- /t/hex.t: -------------------------------------------------------------------------------- 1 | # vi:filetype=perl 2 | 3 | use lib 'lib'; 4 | use Test::Nginx::Socket; 5 | 6 | #repeat_each(3); 7 | 8 | plan tests => repeat_each() * 2 * blocks(); 9 | 10 | no_long_string(); 11 | 12 | run_tests(); 13 | 14 | #no_diff(); 15 | 16 | __DATA__ 17 | 18 | === TEST 1: hex encode 19 | --- config 20 | location /bar { 21 | set_encode_hex $out "abcde"; 22 | echo $out; 23 | } 24 | --- request 25 | GET /bar 26 | --- response_body 27 | 6162636465 28 | 29 | 30 | 31 | === TEST 2: hex decode 32 | --- config 33 | location /bar { 34 | set_decode_hex $out "6162636465"; 35 | echo $out; 36 | } 37 | --- request 38 | GET /bar 39 | --- response_body 40 | abcde 41 | 42 | 43 | 44 | === TEST 3: hex encode (chinese) 45 | --- config 46 | location /bar { 47 | set $raw "章亦春"; 48 | set_encode_hex $digest $raw; 49 | set_decode_hex $hex $digest; 50 | echo $digest; 51 | echo $hex; 52 | } 53 | --- request 54 | GET /bar 55 | --- response_body 56 | e7aba0e4baa6e698a5 57 | 章亦春 58 | -------------------------------------------------------------------------------- /t/hmac.t: -------------------------------------------------------------------------------- 1 | # vi:filetype= 2 | 3 | use lib 'lib'; 4 | use Test::Nginx::Socket; 5 | 6 | #repeat_each(3); 7 | 8 | plan tests => repeat_each() * 2 * blocks(); 9 | 10 | no_long_string(); 11 | 12 | run_tests(); 13 | 14 | #no_diff(); 15 | 16 | __DATA__ 17 | 18 | === TEST 1: hmac_sha1 19 | --- config 20 | location /bar { 21 | set $secret 'thisisverysecretstuff'; 22 | set $string_to_sign 'some string we want to sign'; 23 | set_hmac_sha1 $signature $secret $string_to_sign; 24 | set_encode_base64 $signature $signature; 25 | echo $signature; 26 | } 27 | --- request 28 | GET /bar 29 | --- response_body 30 | R/pvxzHC4NLtj7S+kXFg/NePTmk= 31 | 32 | 33 | 34 | === TEST 2: hmac_sha1 empty vars 35 | --- config 36 | location /bar { 37 | set $secret ''; 38 | set $string_to_sign ''; 39 | set_hmac_sha1 $signature $secret $string_to_sign; 40 | set_encode_base64 $signature $signature; 41 | echo $signature; 42 | } 43 | --- request 44 | GET /bar 45 | --- response_body 46 | +9sdGxiqbAgyS31ktx+3Y3BpDh0= 47 | 48 | 49 | 50 | === TEST 3: hmac_sha256 51 | --- config 52 | location /bar { 53 | set $secret 'thisisverysecretstuff'; 54 | set $string_to_sign 'some string we want to sign'; 55 | set_hmac_sha256 $signature $secret $string_to_sign; 56 | set_encode_base64 $signature $signature; 57 | echo $signature; 58 | } 59 | --- request 60 | GET /bar 61 | --- response_body 62 | 4pU3GRQrKKIoeLb9CqYsavHE2l6Hx+KMmRmesU+Cfrs= 63 | 64 | 65 | 66 | === TEST 4: hmac_sha256 empty vars 67 | --- config 68 | location /bar { 69 | set $secret ''; 70 | set $string_to_sign ''; 71 | set_hmac_sha256 $signature $secret $string_to_sign; 72 | set_encode_base64 $signature $signature; 73 | echo $signature; 74 | } 75 | --- request 76 | GET /bar 77 | --- response_body 78 | thNnmggU2ex3L5XXeMNfxf8Wl8STcVZTxscSFEKSxa0= 79 | -------------------------------------------------------------------------------- /t/local-today.t: -------------------------------------------------------------------------------- 1 | # vi:filetype=perl 2 | 3 | use lib 'lib'; 4 | use Test::Nginx::Socket; 5 | 6 | my ($sec, $min, $hour, $mday, $mon, $year) = localtime; 7 | 8 | our $str = sprintf("%04d-%02d-%02d\n", $year + 1900, $mon + 1, $mday); 9 | #repeat_each(3); 10 | 11 | plan tests => repeat_each() * 2 * blocks(); 12 | 13 | #no_long_string(); 14 | 15 | run_tests(); 16 | 17 | #no_diff(); 18 | 19 | __DATA__ 20 | 21 | === TEST 1: sanity 22 | --- config 23 | location /foo { 24 | set_local_today $today; 25 | echo $today; 26 | } 27 | --- request 28 | GET /foo 29 | --- response_body eval: $main::str 30 | -------------------------------------------------------------------------------- /t/quote-json.t: -------------------------------------------------------------------------------- 1 | # vi:filetype=perl 2 | 3 | use lib 'lib'; 4 | use Test::Nginx::Socket; 5 | 6 | #repeat_each(3); 7 | 8 | plan tests => repeat_each() * 2 * blocks(); 9 | 10 | no_long_string(); 11 | 12 | run_tests(); 13 | 14 | #no_diff(); 15 | 16 | __DATA__ 17 | 18 | === TEST 1: set quote json value 19 | --- config 20 | location /foo { 21 | set $foo "hello\n\r'\"\\"; 22 | set_quote_json_str $foo $foo; 23 | echo $foo; 24 | } 25 | --- request 26 | GET /foo 27 | --- response_body 28 | "hello\n\r'\"\\" 29 | 30 | 31 | 32 | === TEST 2: set quote json value (in place) 33 | --- config 34 | location /foo { 35 | set $foo "hello\n\r'\"\\"; 36 | set_quote_json_str $foo; 37 | echo $foo; 38 | } 39 | --- request 40 | GET /foo 41 | --- response_body 42 | "hello\n\r'\"\\" 43 | 44 | 45 | 46 | === TEST 3: set quote empty json value 47 | --- config 48 | location /foo { 49 | set $foo ""; 50 | set_quote_json_str $foo; 51 | echo $foo; 52 | } 53 | --- request 54 | GET /foo 55 | --- response_body 56 | null 57 | 58 | 59 | 60 | === TEST 4: set quote null json value 61 | --- config 62 | location /foo { 63 | set_quote_json_str $foo; 64 | echo $foo; 65 | } 66 | --- request 67 | GET /foo 68 | --- response_body 69 | null 70 | -------------------------------------------------------------------------------- /t/quote-sql.t: -------------------------------------------------------------------------------- 1 | # vi:filetype= 2 | 3 | use lib 'lib'; 4 | use Test::Nginx::Socket; 5 | 6 | #repeat_each(3); 7 | 8 | plan tests => repeat_each() * 2 * blocks(); 9 | 10 | no_long_string(); 11 | 12 | run_tests(); 13 | 14 | #no_diff(); 15 | 16 | __DATA__ 17 | 18 | === TEST 1: set quote sql value 19 | --- config 20 | location /foo { 21 | set $foo "hello\n\r'\"\\"; 22 | set_quote_sql_str $foo $foo; 23 | echo $foo; 24 | } 25 | --- request 26 | GET /foo 27 | --- response_body 28 | 'hello\n\r\'\"\\' 29 | 30 | 31 | 32 | === TEST 2: set quote sql value (in place) 33 | --- config 34 | location /foo { 35 | set $foo "hello\n\r'\"\\"; 36 | set_quote_sql_str $foo; 37 | echo $foo; 38 | } 39 | --- request 40 | GET /foo 41 | --- response_body 42 | 'hello\n\r\'\"\\' 43 | 44 | 45 | 46 | === TEST 3: set quote empty sql value 47 | --- config 48 | location /foo { 49 | set $foo ""; 50 | set_quote_sql_str $foo; 51 | echo $foo; 52 | } 53 | --- request 54 | GET /foo 55 | --- response_body 56 | '' 57 | 58 | 59 | 60 | === TEST 4: set quote null sql value 61 | --- config 62 | location /foo { 63 | set_quote_sql_str $foo; 64 | echo $foo; 65 | } 66 | --- request 67 | GET /foo 68 | --- response_body 69 | '' 70 | 71 | 72 | 73 | === TEST 5: set quote null pgsql value 74 | --- config 75 | location /foo { 76 | set_quote_pgsql_str $foo; 77 | echo $foo; 78 | } 79 | --- request 80 | GET /foo 81 | --- response_body 82 | '' 83 | 84 | 85 | 86 | === TEST 6: set quote pgsql value 87 | --- config 88 | location /foo { 89 | set $foo "hello\n\r'\"\\"; 90 | set_quote_pgsql_str $foo; 91 | echo $foo; 92 | } 93 | --- request 94 | GET /foo 95 | --- response_body 96 | E'hello\n\r\'\"\\' 97 | 98 | 99 | 100 | === TEST 7: set quote pgsql valid utf8 value 101 | --- config 102 | location /foo { 103 | set $foo "你好"; 104 | set_quote_pgsql_str $foo; 105 | echo $foo; 106 | } 107 | --- request 108 | GET /foo 109 | --- response_body 110 | E'你好' 111 | 112 | 113 | 114 | === TEST 8: set quote pgsql invalid utf8 value 115 | --- config 116 | location /foo { 117 | set $foo "你好"; 118 | set_iconv $foo $foo from=utf-8 to=gbk; 119 | set_quote_pgsql_str $foo; 120 | echo $foo; 121 | } 122 | --- request 123 | GET /foo 124 | --- response_body 125 | E'\\304\\343\\272\\303' 126 | 127 | 128 | 129 | === TEST 9: \0 for mysql 130 | --- config 131 | location /foo { 132 | set_unescape_uri $foo $arg_a; 133 | set_quote_sql_str $foo $foo; 134 | echo $foo; 135 | } 136 | --- request 137 | GET /foo?a=a%00b%00 138 | --- response_body 139 | 'a\0b\0' 140 | 141 | 142 | 143 | === TEST 10: \b for mysql 144 | --- config 145 | location /foo { 146 | set_unescape_uri $foo $arg_a; 147 | set_quote_sql_str $foo $foo; 148 | echo $foo; 149 | } 150 | --- request 151 | GET /foo?a=a%08b%08 152 | --- response_body 153 | 'a\bb\b' 154 | 155 | 156 | 157 | === TEST 11: \t for mysql 158 | --- config 159 | location /foo { 160 | set_unescape_uri $foo $arg_a; 161 | set_quote_sql_str $foo $foo; 162 | echo $foo; 163 | } 164 | --- request 165 | GET /foo?a=a%09b%09 166 | --- response_body 167 | 'a\tb\t' 168 | 169 | 170 | 171 | === TEST 12: \Z for mysql 172 | --- config 173 | location /foo { 174 | set_unescape_uri $foo $arg_a; 175 | set_quote_sql_str $foo $foo; 176 | echo $foo; 177 | } 178 | --- request 179 | GET /foo?a=a%1ab%1a 180 | --- response_body 181 | 'a\Zb\Z' 182 | 183 | 184 | 185 | === TEST 13: set quote sql value 186 | --- config 187 | location /foo { 188 | set_unescape_uri $foo $arg_a; 189 | set_quote_sql_str $foo $foo; 190 | echo $foo; 191 | } 192 | --- request 193 | GET /foo?a=$$ 194 | --- response_body 195 | '\$\$' 196 | -------------------------------------------------------------------------------- /t/rand.t: -------------------------------------------------------------------------------- 1 | # vi:filetype=perl 2 | 3 | use Test::Nginx::Socket; 4 | 5 | repeat_each(100); 6 | 7 | plan tests => repeat_each() * 2 * blocks(); 8 | 9 | no_long_string(); 10 | 11 | run_tests(); 12 | 13 | #no_diff(); 14 | 15 | __DATA__ 16 | 17 | === TEST 1: sanity 18 | --- config 19 | location /rand { 20 | set $from 5; 21 | set $to 7; 22 | set_random $res $from $to; 23 | 24 | echo $res; 25 | } 26 | --- request 27 | GET /rand 28 | --- response_body_like: [5-7] 29 | 30 | 31 | 32 | === TEST 2: sanity (two digits) 33 | --- config 34 | location /rand { 35 | set $from 35; 36 | set $to 37; 37 | set_random $res $from $to; 38 | 39 | echo $res; 40 | } 41 | --- request 42 | GET /rand 43 | --- response_body_like: 3[5-7] 44 | 45 | 46 | 47 | === TEST 3: sanity (two digits, from > to) 48 | --- config 49 | location /rand { 50 | set $from 37; 51 | set $to 35; 52 | set_random $res $from $to; 53 | 54 | echo $res; 55 | } 56 | --- request 57 | GET /rand 58 | --- response_body_like: 3[5-7] 59 | 60 | 61 | 62 | === TEST 4: sanity (two digits, from == to) 63 | --- config 64 | location /rand { 65 | set $from 117; 66 | set $to 117; 67 | set_random $res $from $to; 68 | 69 | echo $res; 70 | } 71 | --- request 72 | GET /rand 73 | --- response_body 74 | 117 75 | 76 | 77 | 78 | === TEST 5: negative number not allowed in from arg 79 | --- config 80 | location /rand { 81 | set $from -2; 82 | set $to 4; 83 | set_random $res $from $to; 84 | 85 | echo $res; 86 | } 87 | --- request 88 | GET /rand 89 | --- response_body_like: 500 Internal Server Error 90 | --- error_code: 500 91 | 92 | 93 | 94 | === TEST 6: negative number not allowed in to arg 95 | --- config 96 | location /rand { 97 | set $from 2; 98 | set $to -4; 99 | set_random $res $from $to; 100 | 101 | echo $res; 102 | } 103 | --- request 104 | GET /rand 105 | --- response_body_like: 500 Internal Server Error 106 | --- error_code: 500 107 | 108 | 109 | 110 | === TEST 7: empty string not allowed in from arg 111 | --- config 112 | location /rand { 113 | set $from ''; 114 | set $to 4; 115 | set_random $res $from $to; 116 | 117 | echo $res; 118 | } 119 | --- request 120 | GET /rand 121 | --- response_body_like: 500 Internal Server Error 122 | --- error_code: 500 123 | 124 | 125 | 126 | === TEST 8: empty string not allowed in to arg 127 | --- config 128 | location /rand { 129 | set $from 2; 130 | set $to ''; 131 | set_random $res $from $to; 132 | 133 | echo $res; 134 | } 135 | --- request 136 | GET /rand 137 | --- response_body_like: 500 Internal Server Error 138 | --- error_code: 500 139 | 140 | 141 | 142 | === TEST 9: wrong number of arguments 143 | --- config 144 | location /rand { 145 | set $from 2; 146 | set_random $res $from; 147 | 148 | echo $res; 149 | } 150 | --- request 151 | GET /rand 152 | --- response_body_like: 500 Internal Server Error 153 | --- error_code: 500 154 | --- SKIP 155 | 156 | 157 | 158 | === TEST 10: zero is fine 159 | --- config 160 | location /rand { 161 | set_random $res 0 0; 162 | 163 | echo $res; 164 | } 165 | --- request 166 | GET /rand 167 | --- response_body 168 | 0 169 | -------------------------------------------------------------------------------- /t/rotate.t: -------------------------------------------------------------------------------- 1 | # vi:filetype= 2 | 3 | use Test::Nginx::Socket; 4 | 5 | repeat_each(2); 6 | 7 | plan tests => repeat_each() * (3 * blocks()); 8 | 9 | no_long_string(); 10 | 11 | run_tests(); 12 | 13 | #no_diff(); 14 | 15 | __DATA__ 16 | 17 | === TEST 1: sanity 18 | --- config 19 | location /bar { 20 | set $a 1; 21 | set_rotate $a 1 3; 22 | 23 | set $b 2; 24 | set_rotate $b 1 3; 25 | 26 | set $c 3; 27 | set_rotate $c 1 3; 28 | 29 | set $d 0; 30 | set_rotate $d 1 3; 31 | 32 | set $e 1; 33 | set_rotate $e 3 5; 34 | 35 | echo "a = $a"; 36 | echo "b = $b"; 37 | echo "c = $c"; 38 | echo "d = $d"; 39 | echo "e = $e"; 40 | } 41 | --- request 42 | GET /bar 43 | --- response_body 44 | a = 2 45 | b = 3 46 | c = 1 47 | d = 1 48 | e = 3 49 | --- no_error_log 50 | [error] 51 | 52 | 53 | 54 | === TEST 2: bad current value 55 | --- config 56 | location /bar { 57 | set $a abc; 58 | set_rotate $a 1 3; 59 | 60 | echo "a = $a"; 61 | } 62 | --- request 63 | GET /bar 64 | --- response_body_like: ^a = [12]$ 65 | --- error_log 66 | set_rotate: bad current value: "abc" 67 | 68 | 69 | 70 | === TEST 3: bad "from" value 71 | --- config 72 | location /bar { 73 | set $a 2; 74 | set_rotate $a abc 3; 75 | 76 | echo "a = $a"; 77 | } 78 | --- request 79 | GET /bar 80 | --- response_body_like: 500 Internal Server Error 81 | --- error_code: 500 82 | --- error_log 83 | set_rotate: bad "from" argument value: "abc" 84 | 85 | 86 | 87 | === TEST 4: bad "to" argument value 88 | --- config 89 | location /bar { 90 | set $a 2; 91 | set_rotate $a 1 abc; 92 | 93 | echo "a = $a"; 94 | } 95 | --- request 96 | GET /bar 97 | --- response_body_like: 500 Internal Server Error 98 | --- error_code: 500 99 | --- error_log 100 | set_rotate: bad "to" argument value: "abc" 101 | 102 | 103 | 104 | === TEST 5: when no current value is given 105 | --- config 106 | location /incr { 107 | set_rotate $a 1 3; 108 | 109 | echo "a = $a"; 110 | } 111 | 112 | location /t { 113 | echo_location /incr; 114 | echo_location /incr; 115 | echo_location /incr; 116 | echo_location /incr; 117 | echo_location /incr; 118 | echo_location /incr; 119 | } 120 | --- request 121 | GET /t 122 | --- response_body 123 | a = 1 124 | a = 2 125 | a = 3 126 | a = 1 127 | a = 2 128 | a = 3 129 | --- no_error_log 130 | [error] 131 | 132 | 133 | 134 | === TEST 6: when no current value is given (starting from 0) 135 | --- config 136 | location /incr { 137 | set_rotate $a 0 2; 138 | 139 | echo "a = $a"; 140 | } 141 | 142 | location /t { 143 | echo_location /incr; 144 | echo_location /incr; 145 | echo_location /incr; 146 | echo_location /incr; 147 | echo_location /incr; 148 | echo_location /incr; 149 | } 150 | --- request 151 | GET /t 152 | --- response_body 153 | a = 0 154 | a = 1 155 | a = 2 156 | a = 0 157 | a = 1 158 | a = 2 159 | --- no_error_log 160 | [error] 161 | 162 | 163 | 164 | === TEST 7: when a non-integer string value is given 165 | --- config 166 | location /incr { 167 | set $a "hello"; 168 | set_rotate $a 0 2; 169 | 170 | echo "a = $a"; 171 | } 172 | 173 | location /t { 174 | echo_location /incr; 175 | echo_location /incr; 176 | echo_location /incr; 177 | echo_location /incr; 178 | echo_location /incr; 179 | echo_location /incr; 180 | } 181 | --- request 182 | GET /t 183 | --- response_body 184 | a = 0 185 | a = 1 186 | a = 2 187 | a = 0 188 | a = 1 189 | a = 2 190 | --- error_log 191 | set_rotate: bad current value: "hello" 192 | 193 | 194 | 195 | === TEST 8: when an empty string value is given 196 | --- config 197 | location /incr { 198 | set $a ""; 199 | set_rotate $a 0 2; 200 | 201 | echo "a = $a"; 202 | } 203 | 204 | location /t { 205 | echo_location /incr; 206 | echo_location /incr; 207 | echo_location /incr; 208 | echo_location /incr; 209 | echo_location /incr; 210 | echo_location /incr; 211 | } 212 | --- request 213 | GET /t 214 | --- response_body 215 | a = 0 216 | a = 1 217 | a = 2 218 | a = 0 219 | a = 1 220 | a = 2 221 | --- no_error_log 222 | [error] 223 | 224 | 225 | 226 | === TEST 9: value persistence is per-location 227 | --- config 228 | location /incr { 229 | set_rotate $a 0 2; 230 | 231 | echo "a = $a"; 232 | } 233 | 234 | location /incr2 { 235 | set_rotate $a 0 2; 236 | 237 | echo "a = $a"; 238 | } 239 | 240 | location /t { 241 | echo_location /incr; 242 | echo_location /incr2; 243 | echo_location /incr; 244 | echo_location /incr2; 245 | echo_location /incr; 246 | echo_location /incr2; 247 | echo_location /incr; 248 | echo_location /incr2; 249 | echo_location /incr; 250 | echo_location /incr2; 251 | echo_location /incr; 252 | echo_location /incr2; 253 | } 254 | --- request 255 | GET /t 256 | --- response_body 257 | a = 0 258 | a = 0 259 | a = 1 260 | a = 1 261 | a = 2 262 | a = 2 263 | a = 0 264 | a = 0 265 | a = 1 266 | a = 1 267 | a = 2 268 | a = 2 269 | --- no_error_log 270 | [error] 271 | -------------------------------------------------------------------------------- /t/secure-random.t: -------------------------------------------------------------------------------- 1 | # vi:filetype= 2 | 3 | use Test::Nginx::Socket; 4 | 5 | repeat_each(2); 6 | 7 | plan tests => repeat_each() * 2 * blocks(); 8 | 9 | no_long_string(); 10 | 11 | run_tests(); 12 | 13 | #no_diff(); 14 | 15 | __DATA__ 16 | 17 | === TEST 1: a 32-character alphanum 18 | --- config 19 | location /alphanum { 20 | set_secure_random_alphanum $res 32; 21 | 22 | echo $res; 23 | } 24 | --- request 25 | GET /alphanum 26 | --- response_body_like: ^[a-zA-Z0-9]{32}$ 27 | 28 | 29 | 30 | === TEST 2: a 16-character alphanum 31 | --- config 32 | location /alphanum { 33 | set_secure_random_alphanum $res 16; 34 | 35 | echo $res; 36 | } 37 | --- request 38 | GET /alphanum 39 | --- response_body_like: ^[a-zA-Z0-9]{16}$ 40 | 41 | 42 | 43 | === TEST 3: a 1-character alphanum 44 | --- config 45 | location /alphanum { 46 | set_secure_random_alphanum $res 1; 47 | 48 | echo $res; 49 | } 50 | --- request 51 | GET /alphanum 52 | --- response_body_like: ^[a-zA-Z0-9]{1}$ 53 | 54 | 55 | 56 | === TEST 4: length less than <= 0 should fail 57 | --- config 58 | location /alphanum { 59 | set_secure_random_alphanum $res 0; 60 | 61 | echo $res; 62 | } 63 | --- request 64 | GET /alphanum 65 | --- response_body_like: 500 Internal Server Error 66 | --- error_code: 500 67 | 68 | 69 | 70 | === TEST 5: length less than <= 0 should fail 71 | --- config 72 | location /alphanum { 73 | set_secure_random_alphanum $res -4; 74 | 75 | echo $res; 76 | } 77 | --- request 78 | GET /alphanum 79 | --- response_body_like: 500 Internal Server Error 80 | --- error_code: 500 81 | 82 | 83 | 84 | === TEST 6: non-numeric length should fail 85 | --- config 86 | location /alphanum { 87 | set_secure_random_alphanum $res bob; 88 | 89 | echo $res; 90 | } 91 | --- request 92 | GET /alphanum 93 | --- response_body_like: 500 Internal Server Error 94 | --- error_code: 500 95 | 96 | 97 | 98 | === TEST 7: a 16-character lcalpha 99 | --- config 100 | location /lcalpha { 101 | set_secure_random_lcalpha $res 16; 102 | 103 | echo $res; 104 | } 105 | --- request 106 | GET /lcalpha 107 | --- response_body_like: ^[a-z]{16}$ 108 | -------------------------------------------------------------------------------- /t/unescape-uri.t: -------------------------------------------------------------------------------- 1 | # vi:filetype=perl 2 | 3 | use lib 'lib'; 4 | use Test::Nginx::Socket; 5 | 6 | #repeat_each(3); 7 | 8 | plan tests => repeat_each() * 2 * blocks(); 9 | 10 | no_long_string(); 11 | 12 | run_tests(); 13 | 14 | #no_diff(); 15 | 16 | __DATA__ 17 | 18 | === TEST 1: set unescape uri 19 | buggy? 20 | --- config 21 | location /foo { 22 | set $foo "hello%20world"; 23 | set_unescape_uri $foo $foo; 24 | echo $foo; 25 | } 26 | --- request 27 | GET /foo 28 | --- response_body 29 | hello world 30 | 31 | 32 | 33 | === TEST 2: set unescape uri (in-place) 34 | buggy? 35 | --- config 36 | location /foo { 37 | set $foo "hello%20world"; 38 | set_unescape_uri $foo; 39 | echo $foo; 40 | } 41 | --- request 42 | GET /foo 43 | --- response_body 44 | hello world 45 | 46 | 47 | 48 | === TEST 3: unescape '+' to ' ' 49 | --- config 50 | location /bar { 51 | set $a 'a+b'; 52 | set_unescape_uri $a; 53 | echo $a; 54 | } 55 | --- request 56 | GET /bar 57 | --- response_body 58 | a b 59 | -------------------------------------------------------------------------------- /util/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # this file is mostly meant to be used by the author himself. 4 | 5 | root=`pwd` 6 | home=~ 7 | version=$1 8 | force=$2 9 | 10 | #--with-cc="gcc46" \ 11 | #--with-ld-opt="-rdynamic" \ 12 | #--with-mail \ 13 | #--with-mail_ssl_module \ 14 | 15 | ngx-build $force $version \ 16 | --with-cc-opt="-I$PCRE_INC -I$OPENSSL_INC" \ 17 | --with-ld-opt="-L$PCRE_LIB -L$OPENSSL_LIB -Wl,-rpath,$PCRE_LIB:$OPENSSL_LIB" \ 18 | --with-http_ssl_module \ 19 | --without-mail_pop3_module \ 20 | --without-mail_imap_module \ 21 | --without-mail_smtp_module \ 22 | --without-http_upstream_ip_hash_module \ 23 | --without-http_empty_gif_module \ 24 | --without-http_memcached_module \ 25 | --without-http_referer_module \ 26 | --without-http_autoindex_module \ 27 | --without-http_auth_basic_module \ 28 | --without-http_userid_module \ 29 | --add-module=$root/../echo-nginx-module \ 30 | --add-module=$root/../ndk-nginx-module \ 31 | --add-module=$root/../iconv-nginx-module \ 32 | --add-module=$root $opts \ 33 | --with-debug \ 34 | || exit 1 35 | 36 | -------------------------------------------------------------------------------- /valgrind.suppress: -------------------------------------------------------------------------------- 1 | { 2 | 3 | Memcheck:Leak 4 | fun:malloc 5 | fun:ngx_alloc 6 | fun:ngx_create_pool 7 | fun:ngx_http_init_request 8 | } 9 | { 10 | 11 | Memcheck:Leak 12 | fun:malloc 13 | fun:ngx_alloc 14 | fun:ngx_create_pool 15 | fun:ngx_event_accept 16 | } 17 | { 18 | 19 | Memcheck:Addr4 20 | fun:ngx_init_cycle 21 | fun:ngx_master_process_cycle 22 | fun:main 23 | } 24 | { 25 | 26 | Memcheck:Leak 27 | fun:malloc 28 | fun:ngx_alloc 29 | fun:ngx_calloc 30 | fun:ngx_event_process_init 31 | } 32 | { 33 | 34 | exp-sgcheck:SorG 35 | fun:ngx_http_variables_init_vars 36 | fun:ngx_http_block 37 | } 38 | { 39 | 40 | exp-sgcheck:SorG 41 | fun:ngx_conf_parse 42 | } 43 | { 44 | 45 | exp-sgcheck:SorG 46 | fun:ngx_vslprintf 47 | fun:ngx_log_error_core 48 | } 49 | { 50 | 51 | exp-sgcheck:SorG 52 | fun:ngx_conf_parse 53 | fun:ngx_http_core_location 54 | } 55 | { 56 | nginx-core-process-init 57 | Memcheck:Leak 58 | fun:malloc 59 | fun:ngx_alloc 60 | fun:ngx_event_process_init 61 | } 62 | { 63 | nginx-core-crc32-init 64 | Memcheck:Leak 65 | fun:malloc 66 | fun:ngx_alloc 67 | fun:ngx_crc32_table_init 68 | fun:main 69 | } 70 | { 71 | libc-2.12.so 72 | Memcheck:Param 73 | epoll_ctl(event) 74 | fun:epoll_ctl 75 | } 76 | { 77 | 78 | Memcheck:Cond 79 | fun:index 80 | fun:expand_dynamic_string_token 81 | fun:_dl_map_object 82 | fun:map_doit 83 | fun:_dl_catch_error 84 | fun:do_preload 85 | fun:dl_main 86 | } 87 | { 88 | 89 | Memcheck:Leak 90 | match-leak-kinds: definite 91 | fun:malloc 92 | fun:ngx_alloc 93 | fun:ngx_set_environment 94 | fun:ngx_single_process_cycle 95 | } 96 | { 97 | 98 | Memcheck:Leak 99 | match-leak-kinds: definite 100 | fun:malloc 101 | fun:ngx_alloc 102 | fun:ngx_set_environment 103 | fun:ngx_worker_process_init 104 | fun:ngx_worker_process_cycle 105 | } 106 | --------------------------------------------------------------------------------