diff --git a/docs/cmdline-opts/variable.md b/docs/cmdline-opts/variable.md index a84078ab8e..5b23e1fc42 100644 --- a/docs/cmdline-opts/variable.md +++ b/docs/cmdline-opts/variable.md @@ -36,14 +36,20 @@ the environment variable is not set, use --variable %name=content or --variable %name@content. Note that on some systems - but not all - environment variables are case insensitive. -Added in curl 8.12.0: when getting contents from a file, you can request to -get a byte range from it by appending ";[start-end]" to the filename, where -*start* and *end* are byte offsets to include from the file. For example, -asking for offset "2-10" means offset two to offset ten, including the byte -offset 10, meaning 9 bytes in total. "2-2" means a single byte at offset 2. -Not providing a second number implies to the end of the file. The start offset -cannot be larger than the end offset. Asking for a range that is outside of -the file size makes the variable contents empty. +Added in curl 8.12.0: you can get a byte range from the source by appending +`[start-end]` to the variable name, where *start* and *end* are byte offsets +to include from the contents. For example, asking for offset "2-10" means +offset two to offset ten, inclusive, resulting in 9 bytes in total. `2-2` +means a single byte at offset 2. Not providing a second number implies to the +end of data. The start offset cannot be larger than the end offset. Asking for +a range that is outside of the file size makes the variable contents empty. +For example, getting the first one hundred bytes from a given file: + + curl --variable "fraction[0-99]@filename" + +Given a byte range that has no data results in an empty string. Asking for a +range that is larger than the content makes curl use the piece of the data +that exists. To assign a variable using contents from another variable, use --expand-variable. Like for example assigning a new variable using contents diff --git a/src/var.c b/src/var.c index e42b5b2c40..f4b221e74a 100644 --- a/src/var.c +++ b/src/var.c @@ -389,6 +389,8 @@ ParameterError setvariable(struct GlobalConfig *global, bool import = FALSE; char *ge = NULL; char buf[MAX_VAR_LEN]; + curl_off_t startoffset = 0; + curl_off_t endoffset = CURL_OFF_T_MAX; if(*input == '%') { import = TRUE; @@ -423,43 +425,37 @@ ParameterError setvariable(struct GlobalConfig *global, clen = strlen(ge); } } + if(*line == '[') { + /* is there a byte range specified? [num-num] */ + if(ISDIGIT(line[1])) { + char *endp; + if(curlx_strtoofft(&line[1], &endp, 10, &startoffset) || (*endp != '-')) + return PARAM_VAR_SYNTAX; + else { + char *p = endp + 1; /* pass the '-' */ + if(*p != ']') { + if(curlx_strtoofft(p, &endp, 10, &endoffset) || (*endp != ']')) + return PARAM_VAR_SYNTAX; + line = &endp[1]; /* pass the ']' */ + } + else + line = &p[1]; /* pass the ']' */ + } + if(startoffset > endoffset) + return PARAM_VAR_SYNTAX; + } + } if(content) ; else if(*line == '@') { /* read from file or stdin */ FILE *file; bool use_stdin; - char *range; struct dynbuf fname; - curl_off_t startoffset = 0; - curl_off_t endoffset = CURL_OFF_T_MAX; line++; Curl_dyn_init(&fname, MAX_FILENAME); - /* is there a byte range specified? ;[num-num] */ - range = strstr(line, ";["); - if(range && ISDIGIT(range[2])) { - char *p = range; - char *endp; - if(curlx_strtoofft(&p[2], &endp, 10, &startoffset) || (*endp != '-')) - return PARAM_VAR_SYNTAX; - else { - p = endp + 1; /* pass the '-' */ - if(*p != ']') { - if(curlx_strtoofft(p, &endp, 10, &endoffset) || (*endp != ']')) - return PARAM_VAR_SYNTAX; - } - } - if(startoffset > endoffset) - return PARAM_VAR_SYNTAX; - /* create a dynbuf for the filename without the range */ - if(Curl_dyn_addn(&fname, line, (range - line))) - return PARAM_NO_MEM; - /* point to the new file name buffer */ - line = Curl_dyn_ptr(&fname); - } - use_stdin = !strcmp(line, "-"); if(use_stdin) file = stdin; @@ -485,9 +481,20 @@ ParameterError setvariable(struct GlobalConfig *global, } else if(*line == '=') { line++; + clen = strlen(line); /* this is the exact content */ content = (char *)line; - clen = strlen(line); + if(startoffset || (endoffset != CURL_OFF_T_MAX)) { + if(startoffset >= (curl_off_t)clen) + clen = 0; + else { + /* make the end offset no larger than the last byte */ + if(endoffset >= (curl_off_t)clen) + endoffset = clen - 1; + clen = (size_t)(endoffset - startoffset) + 1; + content += startoffset; + } + } } else { warnf(global, "Bad --variable syntax, skipping: %s", input); diff --git a/tests/data/Makefile.am b/tests/data/Makefile.am index 73ef90920a..b012848ca3 100644 --- a/tests/data/Makefile.am +++ b/tests/data/Makefile.am @@ -110,7 +110,7 @@ test727 test728 test729 test730 test731 test732 test733 test734 test735 \ test736 test737 test738 test739 test740 test741 test742 \ \ test780 test781 test782 test783 test784 test785 test786 test787 test788 \ -test789 \ +test789 test790 test791 \ \ test799 test800 test801 test802 test803 test804 test805 test806 test807 \ test808 test809 test810 test811 test812 test813 test814 test815 test816 \ diff --git a/tests/data/test784 b/tests/data/test784 index 0c6acc67a8..845a3acfc7 100644 --- a/tests/data/test784 +++ b/tests/data/test784 @@ -35,7 +35,7 @@ http --variable with a file byte range -http://%HOSTIP:%HTTPPORT/%TESTNUMBER --variable name"@%LOGDIR/in%TESTNUMBER;[5-15]" --expand-data '{{name}}' +http://%HOSTIP:%HTTPPORT/%TESTNUMBER --variable "name[5-15]@%LOGDIR/in%TESTNUMBER" --expand-data '{{name}}' On the first Monday of the month of April, 1625, the market town of Meung diff --git a/tests/data/test785 b/tests/data/test785 index c46104a67a..6c8ae5dabb 100644 --- a/tests/data/test785 +++ b/tests/data/test785 @@ -35,7 +35,7 @@ http --variable with a file byte range without end -http://%HOSTIP:%HTTPPORT/%TESTNUMBER --variable name"@%LOGDIR/in%TESTNUMBER;[5-]" --expand-data '{{name}}' +http://%HOSTIP:%HTTPPORT/%TESTNUMBER --variable "name[5-]@%LOGDIR/in%TESTNUMBER" --expand-data '{{name}}' On the first Monday of the month of April, 1625, the market town of Meung diff --git a/tests/data/test786 b/tests/data/test786 index 5da450aae0..bc5cca28d0 100644 --- a/tests/data/test786 +++ b/tests/data/test786 @@ -35,7 +35,7 @@ http --variable with a file byte range, reading from stdin -http://%HOSTIP:%HTTPPORT/%TESTNUMBER --variable name"@-;[5-15]" --expand-data '{{name}}' +http://%HOSTIP:%HTTPPORT/%TESTNUMBER --variable "name[5-15]@-" --expand-data '{{name}}' On the first Monday of the month of April, 1625, the market town of Meung diff --git a/tests/data/test787 b/tests/data/test787 index 23dbad8993..798d2d368f 100644 --- a/tests/data/test787 +++ b/tests/data/test787 @@ -21,7 +21,7 @@ http --variable with a file byte range, bad range -http://%HOSTIP:%HTTPPORT/%TESTNUMBER --variable name"@&LOGDIR/fooo;[15-14]" --expand-data '{{name}}' +http://%HOSTIP:%HTTPPORT/%TESTNUMBER --variable "name[15-14]@&LOGDIR/fooo" --expand-data '{{name}}' diff --git a/tests/data/test788 b/tests/data/test788 index 268eeb6cc9..544732f7ad 100644 --- a/tests/data/test788 +++ b/tests/data/test788 @@ -35,7 +35,7 @@ http --variable with a file and single-byte byte range -http://%HOSTIP:%HTTPPORT/%TESTNUMBER --variable name"@%LOGDIR/in%TESTNUMBER;[15-15]" --expand-data '{{name}}' +http://%HOSTIP:%HTTPPORT/%TESTNUMBER --variable "name[15-15]@%LOGDIR/in%TESTNUMBER" --expand-data '{{name}}' On the first Monday of the month of April, 1625, the market town of Meung diff --git a/tests/data/test789 b/tests/data/test789 index dd36303e24..ce15967a0a 100644 --- a/tests/data/test789 +++ b/tests/data/test789 @@ -35,7 +35,7 @@ http --variable with a file and byte range out of file -http://%HOSTIP:%HTTPPORT/%TESTNUMBER --variable name"@%LOGDIR/in%TESTNUMBER;[75-85]" --expand-data '{{name}}' +http://%HOSTIP:%HTTPPORT/%TESTNUMBER --variable "name[75-85]@%LOGDIR/in%TESTNUMBER" --expand-data '{{name}}' On the first Monday of the month of April, 1625, the market town of Meung diff --git a/tests/data/test790 b/tests/data/test790 new file mode 100644 index 0000000000..1c7827bcd7 --- /dev/null +++ b/tests/data/test790 @@ -0,0 +1,56 @@ + + + +HTTP +--variable + + + +# +# Server-side + + +HTTP/1.1 200 OK +Date: Tue, 09 Nov 2010 14:49:00 GMT +Server: test-server/fake +Last-Modified: Tue, 13 Jun 2000 12:10:00 GMT +ETag: "21025-dc7-39462498" +Accept-Ranges: bytes +Content-Length: 6 +Connection: close +Content-Type: text/html +Funny-head: yesyes + +-foo- + + + +# +# Client-side + + +http + + +--variable with a byte range using plain assign + + +http://%HOSTIP:%HTTPPORT/%TESTNUMBER --variable "name[5-9]=0123456789abcdef" --expand-data '{{name}}' + + + +# +# Verify data after the test has been "shot" + + +POST /%TESTNUMBER HTTP/1.1 +Host: %HOSTIP:%HTTPPORT +User-Agent: curl/%VERSION +Accept: */* +Content-Length: 5 +Content-Type: application/x-www-form-urlencoded + +56789 + + + diff --git a/tests/data/test791 b/tests/data/test791 new file mode 100644 index 0000000000..6dcdc172aa --- /dev/null +++ b/tests/data/test791 @@ -0,0 +1,56 @@ + + + +HTTP +--variable + + + +# +# Server-side + + +HTTP/1.1 200 OK +Date: Tue, 09 Nov 2010 14:49:00 GMT +Server: test-server/fake +Last-Modified: Tue, 13 Jun 2000 12:10:00 GMT +ETag: "21025-dc7-39462498" +Accept-Ranges: bytes +Content-Length: 6 +Connection: close +Content-Type: text/html +Funny-head: yesyes + +-foo- + + + +# +# Client-side + + +http + + +--variable with a byte range using plain assign, out of range + + +http://%HOSTIP:%HTTPPORT/%TESTNUMBER --variable "name[10-30]=0123456789abcdef" --expand-data '{{name}}' + + + +# +# Verify data after the test has been "shot" + + +POST /%TESTNUMBER HTTP/1.1 +Host: %HOSTIP:%HTTPPORT +User-Agent: curl/%VERSION +Accept: */* +Content-Length: 6 +Content-Type: application/x-www-form-urlencoded + +abcdef + + +