curl-users
Wrong for "Content-Range: " in HTTP Resume Uploading with Digest Authentication
Date: Wed, 8 Aug 2007 10:44:41 +0800
Hi Daniel,
I've found "Content-Range: " field would get wrong value if user want to use
resume uploading to a HTTP server with Digest Authentication method. Here is
the scenario.
Best Regards,
Song Ma
I am using the latest snapshot: curl-7.17.0-20070807
I input command line: "curl -v
http://my-server:8181/digest/new.file.upload-u digest:digest -T
file.upload -C 2 --digest" after successful building.
"file.upload" content is "test\n".
Here is the log I got:
* About to connect() to my-server port 8181 (#0)
* Trying my-server... connected
* Connected to my-server (my-server) port 8181 (#0)
* Server auth using Digest with user 'digest'
> PUT /digest/new.file.upload HTTP/1.1
> Content-Range: bytes 2-4/5
> User-Agent: curl/7.17.0-20070807 (i686-pc-linux-gnu)
libcurl/7.17.0-20070807 OpenSSL/0.9.7d zlib/1.2.3 libidn/0.6.0
> Host: my-server:8181
> Accept: */*
> Content-Length: 0
> Expect: 100-continue
>
< HTTP/1.1 401 Authorization Required
< Date: Wed, 08 Aug 2007 01:53:17 GMT
< Server: Apache/2.2.2 (Fedora)
< WWW-Authenticate: Digest realm="digest",
nonce="k4jXZyY3BAA=a682589cab13eb8f594e42cb0902a8ba2f5a5a98", algorithm=MD5,
qop="auth"
< Content-Length: 479
< Content-Type: text/html; charset=iso-8859-1
<
* Ignoring the response-body
* Connection #0 to host my-server left intact
* Issue another request to this URL: '
http://my-server:8181/digest/new.file.upload'
* Re-using existing connection! (#0) with host my-server
* Connected to my-server (my-server) port 8181 (#0)
* Server auth using Digest with user 'digest'
> PUT /digest/new.file.upload HTTP/1.1
> Authorization: Digest username="digest", realm="digest",
nonce="k4jXZyY3BAA=a682589cab13eb8f594e42cb0902a8ba2f5a5a98",
uri="/digest/new.file.upload", cnonce="MTE4NjUz", nc=00000001, qop="auth",
response="5a25bf51196b8a7639cc66a34f8cadca", algorithm="MD5"
> Content-Range: bytes 2-2/3
> User-Agent: curl/7.17.0-20070807 (i686-pc-linux-gnu)
libcurl/7.17.0-20070807 OpenSSL/0.9.7d zlib/1.2.3 libidn/0.6.0
> Host: my-server:8181
> Accept: */*
> Content-Length: 1
> Expect: 100-continue
>
< HTTP/1.1 100 Continue
< HTTP/1.1 201 Created
< Date: Wed, 08 Aug 2007 01:53:17 GMT
< Server: Apache/2.2.2 (Fedora)
< X-Powered-By: PHP/5.1.4
< Content-Length: 48
< Content-Type: text/html; charset=UTF-8
<
* Connection #0 to host my-server left intact
* Closing connection #0
As you can see the "Content-Range: " has been changed and the first one is
what I want but the second one is wrong.
The root cause for this error is in the "curl_http()" function in "http.c"
at line 1996. It will calculate the content range value for resume uploading
as soon as "curl_http()" is called and resume is set. But in HTTP Digest
Auth., "curl_http()" is called twice because of authentication reason, then
the "content-range: " was calculated twice but this is wrong.
I made one patch for it. The idea is when user is doing resume uploading we
need to check not only if the resume position is set but also if the
file-to-be-uploaded is the same file with the previous "curl_http()"
calling. For the same file, we do not make the re-calculation for resume.
Here is the diff file for "http.c" in "curl/7.17.0-20070807".
--- http.c.orig 2007-08-08 10:33:04.000000000 +0800
+++ http.c 2007-08-08 10:39:40.000000000 +0800
@@ -1728,6 +1728,8 @@
return CURLE_OK;
}
+char fupload_swap[512];
+
/*
* Curl_http() gets called from the generic Curl_do() function when a HTTP
* request is to be performed. This creates and sends a properly
constructed
@@ -1993,7 +1995,7 @@
data->reqdata.resume_from = 0;
}
- if(data->reqdata.resume_from) {
+ if(data->reqdata.resume_from && strcmp(fupload_swap, data->reqdata.path))
{
/* do we still game? */
curl_off_t passed=0;
@@ -2030,6 +2032,12 @@
}
}
/* we've passed, proceed as normal */
+ /* Keep the file-to-be-uploaed name for "this" connection.
+ * We need the file name because if the "next" resume uploading
requested,
+ * we don't make the caculation for "Content-Range: " twice on
+ * the same file.
+ */
+ strcpy(fupload_swap, data->reqdata.path);
}
}
if(data->reqdata.use_range) {
Here is the log after the patch was applied:
* About to connect() to my-server port 8181 (#0)
* Trying my-server... connected
* Connected to my-server (my-server) port 8181 (#0)
* Server auth using Digest with user 'digest'
> PUT /digest/new.file.upload HTTP/1.1
> Content-Range: bytes 2-4/5
> User-Agent: curl/7.17.0-20070807 (i686-pc-linux-gnu)
libcurl/7.17.0-20070807 OpenSSL/0.9.7d zlib/1.2.3 libidn/0.6.0
> Host: my-server:8181
> Accept: */*
> Content-Length: 0
> Expect: 100-continue
>
< HTTP/1.1 401 Authorization Required
< Date: Wed, 08 Aug 2007 02:33:09 GMT
< Server: Apache/2.2.2 (Fedora)
< WWW-Authenticate: Digest realm="digest",
nonce="KWlu9iY3BAA=3fcab5d2faefc7a92d9f5a7df677db4f094cbfc4", algorithm=MD5,
qop="auth"
< Content-Length: 479
< Content-Type: text/html; charset=iso-8859-1
<
* Ignoring the response-body
* Connection #0 to host my-server left intact
* Issue another request to this URL: '
http://my-server:8181/digest/new.file.upload'
* Re-using existing connection! (#0) with host my-server
* Connected to my-server (my-server) port 8181 (#0)
* Server auth using Digest with user 'digest'
> PUT /digest/new.file.upload HTTP/1.1
> Authorization: Digest username="digest", realm="digest",
nonce="KWlu9iY3BAA=3fcab5d2faefc7a92d9f5a7df677db4f094cbfc4",
uri="/digest/new.file.upload", cnonce="MTE4NjU0", nc=00000001, qop="auth",
response="42a0cd7b19154d8fa48bca1ef793b613", algorithm="MD5"
> Content-Range: bytes 2-4/5
> User-Agent: curl/7.17.0-20070807 (i686-pc-linux-gnu)
libcurl/7.17.0-20070807 OpenSSL/0.9.7d zlib/1.2.3 libidn/0.6.0
> Host: my-server:8181
> Accept: */*
> Content-Length: 3
> Expect: 100-continue
>
< HTTP/1.1 100 Continue
< HTTP/1.1 201 Created
< Date: Wed, 08 Aug 2007 02:33:09 GMT
< Server: Apache/2.2.2 (Fedora)
< X-Powered-By: PHP/5.1.4
< Content-Length: 48
< Content-Type: text/html; charset=UTF-8
<
* Connection #0 to host my-server left intact
* Closing connection #0
Received on 2007-08-08