Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
T
TLMSP curl
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Package registry
Container Registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
CYBER - Cyber Security
TS 103 523 MSP
TLMSP
TLMSP curl
Commits
1e9a946e
Commit
1e9a946e
authored
15 years ago
by
Daniel Stenberg
Browse files
Options
Downloads
Patches
Plain Diff
move HTTP-specific functions to http.c where they belong
parent
7cd5ffc1
No related branches found
Branches containing commit
No related tags found
Tags containing commit
No related merge requests found
Changes
3
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
lib/http.c
+756
-0
756 additions, 0 deletions
lib/http.c
lib/http.h
+12
-0
12 additions, 0 deletions
lib/http.h
lib/transfer.c
+1
-769
1 addition, 769 deletions
lib/transfer.c
with
769 additions
and
769 deletions
lib/http.c
+
756
−
0
View file @
1e9a946e
...
...
@@ -2985,4 +2985,760 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
return
result
;
}
/*
* checkhttpprefix()
*
* Returns TRUE if member of the list matches prefix of string
*/
static
bool
checkhttpprefix
(
struct
SessionHandle
*
data
,
const
char
*
s
)
{
struct
curl_slist
*
head
=
data
->
set
.
http200aliases
;
bool
rc
=
FALSE
;
#ifdef CURL_DOES_CONVERSIONS
/* convert from the network encoding using a scratch area */
char
*
scratch
=
calloc
(
1
,
strlen
(
s
)
+
1
);
if
(
NULL
==
scratch
)
{
failf
(
data
,
"Failed to calloc memory for conversion!"
);
return
FALSE
;
/* can't return CURLE_OUT_OF_MEMORY so return FALSE */
}
strcpy
(
scratch
,
s
);
if
(
CURLE_OK
!=
Curl_convert_from_network
(
data
,
scratch
,
strlen
(
s
)
+
1
))
{
/* Curl_convert_from_network calls failf if unsuccessful */
free
(
scratch
);
return
FALSE
;
/* can't return CURLE_foobar so return FALSE */
}
s
=
scratch
;
#endif
/* CURL_DOES_CONVERSIONS */
while
(
head
)
{
if
(
checkprefix
(
head
->
data
,
s
))
{
rc
=
TRUE
;
break
;
}
head
=
head
->
next
;
}
if
((
rc
!=
TRUE
)
&&
(
checkprefix
(
"HTTP/"
,
s
)))
{
rc
=
TRUE
;
}
#ifdef CURL_DOES_CONVERSIONS
free
(
scratch
);
#endif
/* CURL_DOES_CONVERSIONS */
return
rc
;
}
/*
* header_append() copies a chunk of data to the end of the already received
* header. We make sure that the full string fit in the allocated header
* buffer, or else we enlarge it.
*/
static
CURLcode
header_append
(
struct
SessionHandle
*
data
,
struct
SingleRequest
*
k
,
size_t
length
)
{
if
(
k
->
hbuflen
+
length
>=
data
->
state
.
headersize
)
{
/* We enlarge the header buffer as it is too small */
char
*
newbuff
;
size_t
hbufp_index
;
size_t
newsize
;
if
(
k
->
hbuflen
+
length
>
CURL_MAX_HTTP_HEADER
)
{
/* The reason to have a max limit for this is to avoid the risk of a bad
server feeding libcurl with a never-ending header that will cause
reallocs infinitely */
failf
(
data
,
"Avoided giant realloc for header (max is %d)!"
,
CURL_MAX_HTTP_HEADER
);
return
CURLE_OUT_OF_MEMORY
;
}
newsize
=
CURLMAX
((
k
->
hbuflen
+
length
)
*
3
/
2
,
data
->
state
.
headersize
*
2
);
hbufp_index
=
k
->
hbufp
-
data
->
state
.
headerbuff
;
newbuff
=
realloc
(
data
->
state
.
headerbuff
,
newsize
);
if
(
!
newbuff
)
{
failf
(
data
,
"Failed to alloc memory for big header!"
);
return
CURLE_OUT_OF_MEMORY
;
}
data
->
state
.
headersize
=
newsize
;
data
->
state
.
headerbuff
=
newbuff
;
k
->
hbufp
=
data
->
state
.
headerbuff
+
hbufp_index
;
}
memcpy
(
k
->
hbufp
,
k
->
str_start
,
length
);
k
->
hbufp
+=
length
;
k
->
hbuflen
+=
length
;
*
k
->
hbufp
=
0
;
return
CURLE_OK
;
}
/*
* Read any HTTP header lines from the server and pass them to the client app.
*/
CURLcode
Curl_http_readwrite_headers
(
struct
SessionHandle
*
data
,
struct
connectdata
*
conn
,
struct
SingleRequest
*
k
,
ssize_t
*
nread
,
bool
*
stop_reading
)
{
CURLcode
result
;
/* header line within buffer loop */
do
{
size_t
rest_length
;
size_t
full_length
;
int
writetype
;
/* str_start is start of line within buf */
k
->
str_start
=
k
->
str
;
/* data is in network encoding so use 0x0a instead of '\n' */
k
->
end_ptr
=
memchr
(
k
->
str_start
,
0x0a
,
*
nread
);
if
(
!
k
->
end_ptr
)
{
/* Not a complete header line within buffer, append the data to
the end of the headerbuff. */
result
=
header_append
(
data
,
k
,
*
nread
);
if
(
result
)
return
result
;
if
(
!
k
->
headerline
&&
(
k
->
hbuflen
>
5
))
{
/* make a first check that this looks like a HTTP header */
if
(
!
checkhttpprefix
(
data
,
data
->
state
.
headerbuff
))
{
/* this is not the beginning of a HTTP first header line */
k
->
header
=
FALSE
;
k
->
badheader
=
HEADER_ALLBAD
;
break
;
}
}
break
;
/* read more and try again */
}
/* decrease the size of the remaining (supposed) header line */
rest_length
=
(
k
->
end_ptr
-
k
->
str
)
+
1
;
*
nread
-=
(
ssize_t
)
rest_length
;
k
->
str
=
k
->
end_ptr
+
1
;
/* move past new line */
full_length
=
k
->
str
-
k
->
str_start
;
result
=
header_append
(
data
,
k
,
full_length
);
if
(
result
)
return
result
;
k
->
end_ptr
=
k
->
hbufp
;
k
->
p
=
data
->
state
.
headerbuff
;
/****
* We now have a FULL header line that p points to
*****/
if
(
!
k
->
headerline
)
{
/* the first read header */
if
((
k
->
hbuflen
>
5
)
&&
!
checkhttpprefix
(
data
,
data
->
state
.
headerbuff
))
{
/* this is not the beginning of a HTTP first header line */
k
->
header
=
FALSE
;
if
(
*
nread
)
/* since there's more, this is a partial bad header */
k
->
badheader
=
HEADER_PARTHEADER
;
else
{
/* this was all we read so it's all a bad header */
k
->
badheader
=
HEADER_ALLBAD
;
*
nread
=
(
ssize_t
)
rest_length
;
}
break
;
}
}
/* headers are in network encoding so
use 0x0a and 0x0d instead of '\n' and '\r' */
if
((
0x0a
==
*
k
->
p
)
||
(
0x0d
==
*
k
->
p
))
{
size_t
headerlen
;
/* Zero-length header line means end of headers! */
#ifdef CURL_DOES_CONVERSIONS
if
(
0x0d
==
*
k
->
p
)
{
*
k
->
p
=
'\r'
;
/* replace with CR in host encoding */
k
->
p
++
;
/* pass the CR byte */
}
if
(
0x0a
==
*
k
->
p
)
{
*
k
->
p
=
'\n'
;
/* replace with LF in host encoding */
k
->
p
++
;
/* pass the LF byte */
}
#else
if
(
'\r'
==
*
k
->
p
)
k
->
p
++
;
/* pass the \r byte */
if
(
'\n'
==
*
k
->
p
)
k
->
p
++
;
/* pass the \n byte */
#endif
/* CURL_DOES_CONVERSIONS */
if
(
100
<=
k
->
httpcode
&&
199
>=
k
->
httpcode
)
{
/*
* We have made a HTTP PUT or POST and this is 1.1-lingo
* that tells us that the server is OK with this and ready
* to receive the data.
* However, we'll get more headers now so we must get
* back into the header-parsing state!
*/
k
->
header
=
TRUE
;
k
->
headerline
=
0
;
/* restart the header line counter */
/* if we did wait for this do enable write now! */
if
(
k
->
exp100
)
{
k
->
exp100
=
EXP100_SEND_DATA
;
k
->
keepon
|=
KEEP_SEND
;
}
}
else
{
k
->
header
=
FALSE
;
/* no more header to parse! */
if
((
k
->
size
==
-
1
)
&&
!
k
->
chunk
&&
!
conn
->
bits
.
close
&&
(
conn
->
httpversion
>=
11
)
)
{
/* On HTTP 1.1, when connection is not to get closed, but no
Content-Length nor Content-Encoding chunked have been
received, according to RFC2616 section 4.4 point 5, we
assume that the server will close the connection to
signal the end of the document. */
infof
(
data
,
"no chunk, no close, no size. Assume close to "
"signal end
\n
"
);
conn
->
bits
.
close
=
TRUE
;
}
}
if
(
417
==
k
->
httpcode
)
{
/*
* we got: "417 Expectation Failed" this means:
* we have made a HTTP call and our Expect Header
* seems to cause a problem => abort the write operations
* (or prevent them from starting).
*/
k
->
exp100
=
EXP100_FAILED
;
k
->
keepon
&=
~
KEEP_SEND
;
}
/*
* When all the headers have been parsed, see if we should give
* up and return an error.
*/
if
(
Curl_http_should_fail
(
conn
))
{
failf
(
data
,
"The requested URL returned error: %d"
,
k
->
httpcode
);
return
CURLE_HTTP_RETURNED_ERROR
;
}
/* now, only output this if the header AND body are requested:
*/
writetype
=
CLIENTWRITE_HEADER
;
if
(
data
->
set
.
include_header
)
writetype
|=
CLIENTWRITE_BODY
;
headerlen
=
k
->
p
-
data
->
state
.
headerbuff
;
result
=
Curl_client_write
(
conn
,
writetype
,
data
->
state
.
headerbuff
,
headerlen
);
if
(
result
)
return
result
;
data
->
info
.
header_size
+=
(
long
)
headerlen
;
data
->
req
.
headerbytecount
+=
(
long
)
headerlen
;
data
->
req
.
deductheadercount
=
(
100
<=
k
->
httpcode
&&
199
>=
k
->
httpcode
)
?
data
->
req
.
headerbytecount
:
0
;
if
(
data
->
state
.
resume_from
&&
(
data
->
set
.
httpreq
==
HTTPREQ_GET
)
&&
(
k
->
httpcode
==
416
))
{
/* "Requested Range Not Satisfiable" */
*
stop_reading
=
TRUE
;
}
if
(
!*
stop_reading
)
{
/* Curl_http_auth_act() checks what authentication methods
* that are available and decides which one (if any) to
* use. It will set 'newurl' if an auth method was picked. */
result
=
Curl_http_auth_act
(
conn
);
if
(
result
)
return
result
;
if
(
conn
->
bits
.
rewindaftersend
)
{
/* We rewind after a complete send, so thus we continue
sending now */
infof
(
data
,
"Keep sending data to get tossed away!
\n
"
);
k
->
keepon
|=
KEEP_SEND
;
}
}
if
(
!
k
->
header
)
{
/*
* really end-of-headers.
*
* If we requested a "no body", this is a good time to get
* out and return home.
*/
if
(
data
->
set
.
opt_no_body
)
*
stop_reading
=
TRUE
;
else
{
/* If we know the expected size of this document, we set the
maximum download size to the size of the expected
document or else, we won't know when to stop reading!
Note that we set the download maximum even if we read a
"Connection: close" header, to make sure that
"Content-Length: 0" still prevents us from attempting to
read the (missing) response-body.
*/
/* According to RFC2616 section 4.4, we MUST ignore
Content-Length: headers if we are now receiving data
using chunked Transfer-Encoding.
*/
if
(
k
->
chunk
)
k
->
size
=-
1
;
}
if
(
-
1
!=
k
->
size
)
{
/* We do this operation even if no_body is true, since this
data might be retrieved later with curl_easy_getinfo()
and its CURLINFO_CONTENT_LENGTH_DOWNLOAD option. */
Curl_pgrsSetDownloadSize
(
data
,
k
->
size
);
k
->
maxdownload
=
k
->
size
;
}
/* If max download size is *zero* (nothing) we already
have nothing and can safely return ok now! */
if
(
0
==
k
->
maxdownload
)
*
stop_reading
=
TRUE
;
if
(
*
stop_reading
)
{
/* we make sure that this socket isn't read more now */
k
->
keepon
&=
~
KEEP_RECV
;
}
if
(
data
->
set
.
verbose
)
Curl_debug
(
data
,
CURLINFO_HEADER_IN
,
k
->
str_start
,
headerlen
,
conn
);
break
;
/* exit header line loop */
}
/* We continue reading headers, so reset the line-based
header parsing variables hbufp && hbuflen */
k
->
hbufp
=
data
->
state
.
headerbuff
;
k
->
hbuflen
=
0
;
continue
;
}
/*
* Checks for special headers coming up.
*/
if
(
!
k
->
headerline
++
)
{
/* This is the first header, it MUST be the error code line
or else we consider this to be the body right away! */
int
httpversion_major
;
int
nc
;
#ifdef CURL_DOES_CONVERSIONS
#define HEADER1 scratch
#define SCRATCHSIZE 21
CURLcode
res
;
char
scratch
[
SCRATCHSIZE
+
1
];
/* "HTTP/major.minor 123" */
/* We can't really convert this yet because we
don't know if it's the 1st header line or the body.
So we do a partial conversion into a scratch area,
leaving the data at k->p as-is.
*/
strncpy
(
&
scratch
[
0
],
k
->
p
,
SCRATCHSIZE
);
scratch
[
SCRATCHSIZE
]
=
0
;
/* null terminate */
res
=
Curl_convert_from_network
(
data
,
&
scratch
[
0
],
SCRATCHSIZE
);
if
(
CURLE_OK
!=
res
)
{
/* Curl_convert_from_network calls failf if unsuccessful */
return
res
;
}
#else
#define HEADER1 k->p
/* no conversion needed, just use k->p */
#endif
/* CURL_DOES_CONVERSIONS */
nc
=
sscanf
(
HEADER1
,
" HTTP/%d.%d %3d"
,
&
httpversion_major
,
&
conn
->
httpversion
,
&
k
->
httpcode
);
if
(
nc
==
3
)
{
conn
->
httpversion
+=
10
*
httpversion_major
;
}
else
{
/* this is the real world, not a Nirvana
NCSA 1.5.x returns this crap when asked for HTTP/1.1
*/
nc
=
sscanf
(
HEADER1
,
" HTTP %3d"
,
&
k
->
httpcode
);
conn
->
httpversion
=
10
;
/* If user has set option HTTP200ALIASES,
compare header line against list of aliases
*/
if
(
!
nc
)
{
if
(
checkhttpprefix
(
data
,
k
->
p
))
{
nc
=
1
;
k
->
httpcode
=
200
;
conn
->
httpversion
=
10
;
}
}
}
if
(
nc
)
{
data
->
info
.
httpcode
=
k
->
httpcode
;
data
->
info
.
httpversion
=
conn
->
httpversion
;
if
(
!
data
->
state
.
httpversion
||
data
->
state
.
httpversion
>
conn
->
httpversion
)
/* store the lowest server version we encounter */
data
->
state
.
httpversion
=
conn
->
httpversion
;
/*
* This code executes as part of processing the header. As a
* result, it's not totally clear how to interpret the
* response code yet as that depends on what other headers may
* be present. 401 and 407 may be errors, but may be OK
* depending on how authentication is working. Other codes
* are definitely errors, so give up here.
*/
if
(
data
->
set
.
http_fail_on_error
&&
(
k
->
httpcode
>=
400
)
&&
((
k
->
httpcode
!=
401
)
||
!
conn
->
bits
.
user_passwd
)
&&
((
k
->
httpcode
!=
407
)
||
!
conn
->
bits
.
proxy_user_passwd
)
)
{
if
(
data
->
state
.
resume_from
&&
(
data
->
set
.
httpreq
==
HTTPREQ_GET
)
&&
(
k
->
httpcode
==
416
))
{
/* "Requested Range Not Satisfiable", just proceed and
pretend this is no error */
}
else
{
/* serious error, go home! */
failf
(
data
,
"The requested URL returned error: %d"
,
k
->
httpcode
);
return
CURLE_HTTP_RETURNED_ERROR
;
}
}
if
(
conn
->
httpversion
==
10
)
{
/* Default action for HTTP/1.0 must be to close, unless
we get one of those fancy headers that tell us the
server keeps it open for us! */
infof
(
data
,
"HTTP 1.0, assume close after body
\n
"
);
conn
->
bits
.
close
=
TRUE
;
}
else
if
(
conn
->
httpversion
>=
11
&&
!
conn
->
bits
.
close
)
{
/* If HTTP version is >= 1.1 and connection is persistent
server supports pipelining. */
DEBUGF
(
infof
(
data
,
"HTTP 1.1 or later with persistent connection, "
"pipelining supported
\n
"
));
conn
->
server_supports_pipelining
=
TRUE
;
}
switch
(
k
->
httpcode
)
{
case
204
:
/* (quote from RFC2616, section 10.2.5): The server has
* fulfilled the request but does not need to return an
* entity-body ... The 204 response MUST NOT include a
* message-body, and thus is always terminated by the first
* empty line after the header fields. */
/* FALLTHROUGH */
case
416
:
/* Requested Range Not Satisfiable, it has the
Content-Length: set as the "real" document but no
actual response is sent. */
case
304
:
/* (quote from RFC2616, section 10.3.5): The 304 response
* MUST NOT contain a message-body, and thus is always
* terminated by the first empty line after the header
* fields. */
if
(
data
->
set
.
timecondition
)
data
->
info
.
timecond
=
TRUE
;
k
->
size
=
0
;
k
->
maxdownload
=
0
;
k
->
ignorecl
=
TRUE
;
/* ignore Content-Length headers */
break
;
default:
/* nothing */
break
;
}
}
else
{
k
->
header
=
FALSE
;
/* this is not a header line */
break
;
}
}
#ifdef CURL_DOES_CONVERSIONS
/* convert from the network encoding */
result
=
Curl_convert_from_network
(
data
,
k
->
p
,
strlen
(
k
->
p
));
if
(
CURLE_OK
!=
result
)
{
return
(
result
);
}
/* Curl_convert_from_network calls failf if unsuccessful */
#endif
/* CURL_DOES_CONVERSIONS */
/* Check for Content-Length: header lines to get size. Ignore
the header completely if we get a 416 response as then we're
resuming a document that we don't get, and this header contains
info about the true size of the document we didn't get now. */
if
(
!
k
->
ignorecl
&&
!
data
->
set
.
ignorecl
&&
checkprefix
(
"Content-Length:"
,
k
->
p
))
{
curl_off_t
contentlength
=
curlx_strtoofft
(
k
->
p
+
15
,
NULL
,
10
);
if
(
data
->
set
.
max_filesize
&&
contentlength
>
data
->
set
.
max_filesize
)
{
failf
(
data
,
"Maximum file size exceeded"
);
return
CURLE_FILESIZE_EXCEEDED
;
}
if
(
contentlength
>=
0
)
{
k
->
size
=
contentlength
;
k
->
maxdownload
=
k
->
size
;
/* we set the progress download size already at this point
just to make it easier for apps/callbacks to extract this
info as soon as possible */
Curl_pgrsSetDownloadSize
(
data
,
k
->
size
);
}
else
{
/* Negative Content-Length is really odd, and we know it
happens for example when older Apache servers send large
files */
conn
->
bits
.
close
=
TRUE
;
infof
(
data
,
"Negative content-length: %"
FORMAT_OFF_T
", closing after transfer
\n
"
,
contentlength
);
}
}
/* check for Content-Type: header lines to get the MIME-type */
else
if
(
checkprefix
(
"Content-Type:"
,
k
->
p
))
{
char
*
contenttype
=
Curl_copy_header_value
(
k
->
p
);
if
(
!
contenttype
)
return
CURLE_OUT_OF_MEMORY
;
if
(
!*
contenttype
)
/* ignore empty data */
free
(
contenttype
);
else
{
Curl_safefree
(
data
->
info
.
contenttype
);
data
->
info
.
contenttype
=
contenttype
;
}
}
else
if
((
conn
->
httpversion
==
10
)
&&
conn
->
bits
.
httpproxy
&&
Curl_compareheader
(
k
->
p
,
"Proxy-Connection:"
,
"keep-alive"
))
{
/*
* When a HTTP/1.0 reply comes when using a proxy, the
* 'Proxy-Connection: keep-alive' line tells us the
* connection will be kept alive for our pleasure.
* Default action for 1.0 is to close.
*/
conn
->
bits
.
close
=
FALSE
;
/* don't close when done */
infof
(
data
,
"HTTP/1.0 proxy connection set to keep alive!
\n
"
);
}
else
if
((
conn
->
httpversion
==
11
)
&&
conn
->
bits
.
httpproxy
&&
Curl_compareheader
(
k
->
p
,
"Proxy-Connection:"
,
"close"
))
{
/*
* We get a HTTP/1.1 response from a proxy and it says it'll
* close down after this transfer.
*/
conn
->
bits
.
close
=
TRUE
;
/* close when done */
infof
(
data
,
"HTTP/1.1 proxy connection set close!
\n
"
);
}
else
if
((
conn
->
httpversion
==
10
)
&&
Curl_compareheader
(
k
->
p
,
"Connection:"
,
"keep-alive"
))
{
/*
* A HTTP/1.0 reply with the 'Connection: keep-alive' line
* tells us the connection will be kept alive for our
* pleasure. Default action for 1.0 is to close.
*
* [RFC2068, section 19.7.1] */
conn
->
bits
.
close
=
FALSE
;
/* don't close when done */
infof
(
data
,
"HTTP/1.0 connection set to keep alive!
\n
"
);
}
else
if
(
Curl_compareheader
(
k
->
p
,
"Connection:"
,
"close"
))
{
/*
* [RFC 2616, section 8.1.2.1]
* "Connection: close" is HTTP/1.1 language and means that
* the connection will close when this request has been
* served.
*/
conn
->
bits
.
close
=
TRUE
;
/* close when done */
}
else
if
(
Curl_compareheader
(
k
->
p
,
"Transfer-Encoding:"
,
"chunked"
))
{
/*
* [RFC 2616, section 3.6.1] A 'chunked' transfer encoding
* means that the server will send a series of "chunks". Each
* chunk starts with line with info (including size of the
* coming block) (terminated with CRLF), then a block of data
* with the previously mentioned size. There can be any amount
* of chunks, and a chunk-data set to zero signals the
* end-of-chunks. */
k
->
chunk
=
TRUE
;
/* chunks coming our way */
/* init our chunky engine */
Curl_httpchunk_init
(
conn
);
}
else
if
(
checkprefix
(
"Trailer:"
,
k
->
p
)
||
checkprefix
(
"Trailers:"
,
k
->
p
))
{
/*
* This test helps Curl_httpchunk_read() to determine to look
* for well formed trailers after the zero chunksize record. In
* this case a CRLF is required after the zero chunksize record
* when no trailers are sent, or after the last trailer record.
*
* It seems both Trailer: and Trailers: occur in the wild.
*/
k
->
trailerhdrpresent
=
TRUE
;
}
else
if
(
checkprefix
(
"Content-Encoding:"
,
k
->
p
)
&&
data
->
set
.
str
[
STRING_ENCODING
])
{
/*
* Process Content-Encoding. Look for the values: identity,
* gzip, deflate, compress, x-gzip and x-compress. x-gzip and
* x-compress are the same as gzip and compress. (Sec 3.5 RFC
* 2616). zlib cannot handle compress. However, errors are
* handled further down when the response body is processed
*/
char
*
start
;
/* Find the first non-space letter */
start
=
k
->
p
+
17
;
while
(
*
start
&&
ISSPACE
(
*
start
))
start
++
;
/* Record the content-encoding for later use */
if
(
checkprefix
(
"identity"
,
start
))
k
->
content_encoding
=
IDENTITY
;
else
if
(
checkprefix
(
"deflate"
,
start
))
k
->
content_encoding
=
DEFLATE
;
else
if
(
checkprefix
(
"gzip"
,
start
)
||
checkprefix
(
"x-gzip"
,
start
))
k
->
content_encoding
=
GZIP
;
else
if
(
checkprefix
(
"compress"
,
start
)
||
checkprefix
(
"x-compress"
,
start
))
k
->
content_encoding
=
COMPRESS
;
}
else
if
(
checkprefix
(
"Content-Range:"
,
k
->
p
))
{
/* Content-Range: bytes [num]-
Content-Range: bytes: [num]-
Content-Range: [num]-
The second format was added since Sun's webserver
JavaWebServer/1.1.1 obviously sends the header this way!
The third added since some servers use that!
*/
char
*
ptr
=
k
->
p
+
14
;
/* Move forward until first digit */
while
(
*
ptr
&&
!
ISDIGIT
(
*
ptr
))
ptr
++
;
k
->
offset
=
curlx_strtoofft
(
ptr
,
NULL
,
10
);
if
(
data
->
state
.
resume_from
==
k
->
offset
)
/* we asked for a resume and we got it */
k
->
content_range
=
TRUE
;
}
#if !defined(CURL_DISABLE_COOKIES)
else
if
(
data
->
cookies
&&
checkprefix
(
"Set-Cookie:"
,
k
->
p
))
{
Curl_share_lock
(
data
,
CURL_LOCK_DATA_COOKIE
,
CURL_LOCK_ACCESS_SINGLE
);
Curl_cookie_add
(
data
,
data
->
cookies
,
TRUE
,
k
->
p
+
11
,
/* If there is a custom-set Host: name, use it
here, or else use real peer host name. */
conn
->
allocptr
.
cookiehost
?
conn
->
allocptr
.
cookiehost
:
conn
->
host
.
name
,
data
->
state
.
path
);
Curl_share_unlock
(
data
,
CURL_LOCK_DATA_COOKIE
);
}
#endif
else
if
(
checkprefix
(
"Last-Modified:"
,
k
->
p
)
&&
(
data
->
set
.
timecondition
||
data
->
set
.
get_filetime
)
)
{
time_t
secs
=
time
(
NULL
);
k
->
timeofdoc
=
curl_getdate
(
k
->
p
+
strlen
(
"Last-Modified:"
),
&
secs
);
if
(
data
->
set
.
get_filetime
)
data
->
info
.
filetime
=
(
long
)
k
->
timeofdoc
;
}
else
if
((
checkprefix
(
"WWW-Authenticate:"
,
k
->
p
)
&&
(
401
==
k
->
httpcode
))
||
(
checkprefix
(
"Proxy-authenticate:"
,
k
->
p
)
&&
(
407
==
k
->
httpcode
)))
{
result
=
Curl_http_input_auth
(
conn
,
k
->
httpcode
,
k
->
p
);
if
(
result
)
return
result
;
}
else
if
((
k
->
httpcode
>=
300
&&
k
->
httpcode
<
400
)
&&
checkprefix
(
"Location:"
,
k
->
p
))
{
/* this is the URL that the server advises us to use instead */
char
*
location
=
Curl_copy_header_value
(
k
->
p
);
if
(
!
location
)
return
CURLE_OUT_OF_MEMORY
;
if
(
!*
location
)
/* ignore empty data */
free
(
location
);
else
{
DEBUGASSERT
(
!
data
->
req
.
location
);
data
->
req
.
location
=
location
;
if
(
data
->
set
.
http_follow_location
)
{
DEBUGASSERT
(
!
data
->
req
.
newurl
);
data
->
req
.
newurl
=
strdup
(
data
->
req
.
location
);
/* clone */
if
(
!
data
->
req
.
newurl
)
return
CURLE_OUT_OF_MEMORY
;
/* some cases of POST and PUT etc needs to rewind the data
stream at this point */
result
=
Curl_http_perhapsrewind
(
conn
);
if
(
result
)
return
result
;
}
}
}
/*
* End of header-checks. Write them to the client.
*/
writetype
=
CLIENTWRITE_HEADER
;
if
(
data
->
set
.
include_header
)
writetype
|=
CLIENTWRITE_BODY
;
if
(
data
->
set
.
verbose
)
Curl_debug
(
data
,
CURLINFO_HEADER_IN
,
k
->
p
,
(
size_t
)
k
->
hbuflen
,
conn
);
result
=
Curl_client_write
(
conn
,
writetype
,
k
->
p
,
k
->
hbuflen
);
if
(
result
)
return
result
;
data
->
info
.
header_size
+=
(
long
)
k
->
hbuflen
;
data
->
req
.
headerbytecount
+=
(
long
)
k
->
hbuflen
;
/* reset hbufp pointer && hbuflen */
k
->
hbufp
=
data
->
state
.
headerbuff
;
k
->
hbuflen
=
0
;
}
while
(
!*
stop_reading
&&
*
k
->
str
);
/* header line within buffer */
/* We might have reached the end of the header part here, but
there might be a non-header part left in the end of the read
buffer. */
return
CURLE_OK
;
}
#endif
This diff is collapsed.
Click to expand it.
lib/http.h
+
12
−
0
View file @
1e9a946e
...
...
@@ -25,6 +25,8 @@
***************************************************************************/
#ifndef CURL_DISABLE_HTTP
struct
SingleRequest
;
extern
const
struct
Curl_handler
Curl_handler_http
;
#ifdef USE_SSL
...
...
@@ -123,4 +125,14 @@ struct HTTP {
points to an allocated send_buffer struct */
};
CURLcode
Curl_http_header_append
(
struct
SessionHandle
*
data
,
struct
SingleRequest
*
k
,
size_t
length
);
CURLcode
Curl_http_readwrite_headers
(
struct
SessionHandle
*
data
,
struct
connectdata
*
conn
,
struct
SingleRequest
*
k
,
ssize_t
*
nread
,
bool
*
stop_reading
);
#endif
This diff is collapsed.
Click to expand it.
lib/transfer.c
+
1
−
769
View file @
1e9a946e
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment