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
+
+
+