/*****************************************************************************
*
* Curl_cookie_init()
*
* Inits a cookie struct to read data from a local file. This is always
* called before any cookies are set. File may be NULL.
*
* If 'newsession' is TRUE, discard all "session cookies" on read from file.
*
****************************************************************************/
struct CookieInfo *Curl_cookie_init(struct SessionHandle *data,
char *file,
struct CookieInfo *inc,
bool newsession)
{
char line[MAX_COOKIE_LINE];
struct CookieInfo *c;
FILE *fp;
bool fromfile=TRUE;
if(NULL == inc) {
/* we didn't get a struct, create one */
c = (struct CookieInfo *)malloc(sizeof(struct CookieInfo));
if(!c)
return NULL; /* failed to get memory */
memset(c, 0, sizeof(struct CookieInfo));
c->filename = strdup(file?file:"none"); /* copy the name just in case */
}
else {
/* we got an already existing one, use that */
c = inc;
}
c->running = FALSE; /* this is not running, this is init */
if(file && strequal(file, "-")) {
fp = stdin;
fromfile=FALSE;
}
else
fp = file?fopen(file, "r"):NULL;
c->newsession = newsession; /* new session? */
if(fp) {
char *lineptr;
bool headerline;
while(fgets(line, MAX_COOKIE_LINE, fp)) {
if(checkprefix("Set-Cookie:", line)) {
/* This is a cookie line, get it! */
lineptr=&line[11];
headerline=TRUE;
}
else {
lineptr=line;
headerline=FALSE;
}
while(*lineptr && isspace((int)*lineptr))
lineptr++;
Curl_cookie_add(data, c, headerline, lineptr, NULL, NULL);
}
if(fromfile)
fclose(fp);
}
c->running = TRUE; /* now, we're running */
return c;
}
struct Cookie *Curl_cookie_getlist(struct CookieInfo *c,
char *host, char *path, bool secure)
{
struct Cookie *newco;
struct Cookie *co;
time_t now = time(NULL);
struct Cookie *mainco=NULL;
if(!c || !c->cookies)
return NULL; /* no cookie struct or no cookies in the struct */
co = c->cookies;
while(co) {
/* only process this cookie if it is not expired or had no expire
date AND that if the cookie requires we're secure we must only
continue if we are! */
if( (co->expires<=0 || (co->expires> now)) &&
(co->secure?secure:TRUE) ) {
/* now check if the domain is correct */
if(!co->domain ||
(co->tailmatch && tailmatch(co->domain, host)) ||
(!co->tailmatch && strequal(host, co->domain)) ) {
/* the right part of the host matches the domain stuff in the
cookie data */
/* now check the left part of the path with the cookies path
requirement */
if(!co->path ||
checkprefix(co->path, path) ) {
/* and now, we know this is a match and we should create an
entry for the return-linked-list */
newco = (struct Cookie *)malloc(sizeof(struct Cookie));
if(newco) {
/* first, copy the whole source cookie: */
memcpy(newco, co, sizeof(struct Cookie));
/* then modify our next */
newco->next = mainco;
/* point the main to us */
mainco = newco;
}
}
}
}
co = co->next;
}
return mainco; /* return the new list */
}
开发者ID:newobj,项目名称:taz,代码行数:54,代码来源:cookie.c
示例8: Curl_input_ntlm
CURLcode Curl_input_ntlm(struct connectdata *conn,
bool proxy, /* if proxy or not */
const char *header) /* rest of the www-authenticate:
header */
{
/* point to the correct struct with this */
struct ntlmdata *ntlm;
CURLcode result = CURLE_OK;
#ifdef USE_NSS
result = Curl_nss_force_init(conn->data);
if(result)
return result;
#endif
ntlm = proxy ? &conn->proxyntlm : &conn->ntlm;
/* skip initial whitespaces */
while(*header && ISSPACE(*header))
header++;
if(checkprefix("NTLM", header)) {
header += strlen("NTLM");
while(*header && ISSPACE(*header))
header++;
if(*header) {
result = Curl_ntlm_decode_type2_message(conn->data, header, ntlm);
if(CURLE_OK != result)
return result;
ntlm->state = NTLMSTATE_TYPE2; /* We got a type-2 message */
}
else {
if(ntlm->state == NTLMSTATE_TYPE3) {
infof(conn->data, "NTLM handshake rejected\n");
Curl_http_ntlm_cleanup(conn);
ntlm->state = NTLMSTATE_NONE;
return CURLE_REMOTE_ACCESS_DENIED;
}
else if(ntlm->state >= NTLMSTATE_TYPE1) {
infof(conn->data, "NTLM handshake failure (internal error)\n");
return CURLE_REMOTE_ACCESS_DENIED;
}
ntlm->state = NTLMSTATE_TYPE1; /* We should send away a type-1 */
}
}
return result;
}
int formparse(struct Configurable *config,
const char *input,
struct curl_httppost **httppost,
struct curl_httppost **last_post,
bool literal_value)
{
/* nextarg MUST be a string in the format 'name=contents' and we'll
build a linked list with the info */
char name[256];
char *contents = NULL;
char major[128];
char minor[128];
char *contp;
const char *type = NULL;
char *sep;
char *sep2;
if((1 == sscanf(input, "%255[^=]=", name)) &&
((contp = strchr(input, '=')) != NULL)) {
/* the input was using the correct format */
/* Allocate the contents */
contents = strdup(contp+1);
if(!contents) {
fprintf(config->errors, "out of memory\n");
return 1;
}
contp = contents;
if('@' == contp[0] && !literal_value) {
/* we use the @-letter to indicate file name(s) */
struct multi_files *multi_start = NULL;
struct multi_files *multi_current = NULL;
contp++;
do {
/* since this was a file, it may have a content-type specifier
at the end too, or a filename. Or both. */
char *ptr;
char *filename = NULL;
sep = strchr(contp, FORM_TYPE_SEPARATOR);
sep2 = strchr(contp, FORM_FILE_SEPARATOR);
/* pick the closest */
if(sep2 && (sep2 < sep)) {
sep = sep2;
/* no type was specified! */
}
type = NULL;
if(sep) {
/* if we got here on a comma, don't do much */
if(FORM_FILE_SEPARATOR == *sep)
ptr = NULL;
else
ptr = sep+1;
*sep = '\0'; /* terminate file name at separator */
while(ptr && (FORM_FILE_SEPARATOR!= *ptr)) {
/* pass all white spaces */
while(ISSPACE(*ptr))
ptr++;
if(checkprefix("type=", ptr)) {
/* set type pointer */
type = &ptr[5];
/* verify that this is a fine type specifier */
if(2 != sscanf(type, "%127[^/]/%127[^;,\n]",
major, minor)) {
warnf(config, "Illegally formatted content-type field!\n");
Curl_safefree(contents);
FreeMultiInfo(&multi_start, &multi_current);
return 2; /* illegal content-type syntax! */
}
/* now point beyond the content-type specifier */
sep = (char *)type + strlen(major)+strlen(minor)+1;
/* there's a semicolon following - we check if it is a filename
specified and if not we simply assume that it is text that
the user wants included in the type and include that too up
to the next zero or semicolon. */
if((*sep==';') && !checkprefix(";filename=", sep)) {
sep2 = strchr(sep+1, ';');
if(sep2)
sep = sep2;
else
sep = sep + strlen(sep); /* point to end of string */
}
//.........这里部分代码省略.........
int formparse(struct OperationConfig *config,
const char *input,
struct curl_httppost **httppost,
struct curl_httppost **last_post,
bool literal_value)
{
/* nextarg MUST be a string in the format 'name=contents' and we'll
build a linked list with the info */
char name[256];
char *contents = NULL;
char type_major[128] = "";
char type_minor[128] = "";
char *contp;
const char *type = NULL;
char *sep;
if((1 == sscanf(input, "%255[^=]=", name)) &&
((contp = strchr(input, '=')) != NULL)) {
/* the input was using the correct format */
/* Allocate the contents */
contents = strdup(contp+1);
if(!contents) {
fprintf(config->global->errors, "out of memory\n");
return 1;
}
contp = contents;
if('@' == contp[0] && !literal_value) {
/* we use the @-letter to indicate file name(s) */
struct multi_files *multi_start = NULL;
struct multi_files *multi_current = NULL;
char *ptr = contp;
char *end = ptr + strlen(ptr);
do {
/* since this was a file, it may have a content-type specifier
at the end too, or a filename. Or both. */
char *filename = NULL;
char *word_end;
bool semicolon;
type = NULL;
++ptr;
contp = get_param_word(&ptr, &word_end);
semicolon = (';' == *ptr) ? TRUE : FALSE;
*word_end = '\0'; /* terminate the contp */
/* have other content, continue parse */
while(semicolon) {
/* have type or filename field */
++ptr;
while(*ptr && (ISSPACE(*ptr)))
++ptr;
if(checkprefix("type=", ptr)) {
/* set type pointer */
type = &ptr[5];
/* verify that this is a fine type specifier */
if(2 != sscanf(type, "%127[^/]/%127[^;,\n]",
type_major, type_minor)) {
warnf(config, "Illegally formatted content-type field!\n");
Curl_safefree(contents);
FreeMultiInfo(&multi_start, &multi_current);
return 2; /* illegal content-type syntax! */
}
/* now point beyond the content-type specifier */
sep = (char *)type + strlen(type_major)+strlen(type_minor)+1;
/* there's a semicolon following - we check if it is a filename
specified and if not we simply assume that it is text that
the user wants included in the type and include that too up
to the next sep. */
ptr = sep;
if(*sep==';') {
if(!checkprefix(";filename=", sep)) {
ptr = sep + 1;
(void)get_param_word(&ptr, &sep);
semicolon = (';' == *ptr) ? TRUE : FALSE;
}
}
else
semicolon = FALSE;
if(*sep)
*sep = '\0'; /* zero terminate type string */
}
else if(checkprefix("filename=", ptr)) {
ptr += 9;
filename = get_param_word(&ptr, &word_end);
semicolon = (';' == *ptr) ? TRUE : FALSE;
*word_end = '\0';
}
else {
//.........这里部分代码省略.........
/*****************************************************************************
*
* Curl_cookie_init()
*
* Inits a cookie struct to read data from a local file. This is always
* called before any cookies are set. File may be NULL.
*
* If 'newsession' is TRUE, discard all "session cookies" on read from file.
*
* Returns NULL on out of memory. Invalid cookies are ignored.
****************************************************************************/
struct CookieInfo *Curl_cookie_init(struct Curl_easy *data,
const char *file,
struct CookieInfo *inc,
bool newsession)
{
struct CookieInfo *c;
FILE *fp = NULL;
bool fromfile = TRUE;
char *line = NULL;
if(NULL == inc) {
/* we didn't get a struct, create one */
c = calloc(1, sizeof(struct CookieInfo));
if(!c)
return NULL; /* failed to get memory */
c->filename = strdup(file?file:"none"); /* copy the name just in case */
if(!c->filename)
goto fail; /* failed to get memory */
}
else {
/* we got an already existing one, use that */
c = inc;
}
c->running = FALSE; /* this is not running, this is init */
if(file && !strcmp(file, "-")) {
fp = stdin;
fromfile = FALSE;
}
else if(file && !*file) {
/* points to a "" string */
fp = NULL;
}
else
fp = file?fopen(file, FOPEN_READTEXT):NULL;
c->newsession = newsession; /* new session? */
if(fp) {
char *lineptr;
bool headerline;
line = malloc(MAX_COOKIE_LINE);
if(!line)
goto fail;
while(get_line(line, MAX_COOKIE_LINE, fp)) {
if(checkprefix("Set-Cookie:", line)) {
/* This is a cookie line, get it! */
lineptr = &line[11];
headerline = TRUE;
}
else {
lineptr = line;
headerline = FALSE;
}
while(*lineptr && ISBLANK(*lineptr))
lineptr++;
Curl_cookie_add(data, c, headerline, TRUE, lineptr, NULL, NULL);
}
free(line); /* free the line buffer */
remove_expired(c); /* run this once, not on every cookie */
if(fromfile)
fclose(fp);
}
c->running = TRUE; /* now, we're running */
return c;
fail:
free(line);
if(!inc)
/* Only clean up if we allocated it here, as the original could still be in
* use by a share handle */
Curl_cookie_cleanup(c);
if(fromfile && fp)
fclose(fp);
return NULL; /* out of memory */
}
size_t tool_header_cb(void *ptr, size_t size, size_t nmemb, void *userdata)
{
struct OutStruct *outs = userdata;
const char *str = ptr;
const size_t cb = size * nmemb;
const char *end = (char*)ptr + cb;
/*
* Once that libcurl has called back tool_header_cb() the returned value
* is checked against the amount that was intended to be written, if
* it does not match then it fails with CURLE_WRITE_ERROR. So at this
* point returning a value different from sz*nmemb indicates failure.
*/
size_t failure = (size * nmemb) ? 0 : 1;
if(!outs->config)
return failure;
#ifdef DEBUGBUILD
if(size * nmemb > (size_t)CURL_MAX_HTTP_HEADER) {
warnf(outs->config, "Header data exceeds single call write limit!\n");
return failure;
}
#endif
if((cb > 20) && checkprefix("Content-disposition:", str)) {
const char *p = str + 20;
/* look for the 'filename=' parameter
(encoded filenames (*=) are not supported) */
for(;;) {
char *filename;
size_t len;
while(*p && (p < end) && !ISALPHA(*p))
p++;
if(p > end - 9)
break;
if(memcmp(p, "filename=", 9)) {
/* no match, find next parameter */
while((p < end) && (*p != ';'))
p++;
continue;
}
p += 9;
/* this expression below typecasts 'cb' only to avoid
warning: signed and unsigned type in conditional expression
*/
len = (ssize_t)cb - (p - str);
filename = parse_filename(p, len);
if(filename) {
outs->filename = filename;
outs->alloc_filename = TRUE;
outs->s_isreg = TRUE;
outs->fopened = FALSE;
outs->stream = NULL;
break;
}
else
return failure;
}
}
return cb;
}
//.........这里部分代码省略.........
if(s->line_start[1] == '\n') {
/* this can only be a LF if the letter at index 0
was a CR */
s->line_start++;
}
/* now parse the chunked piece of data so that we can
properly tell when the stream ends */
r = Curl_httpchunk_read(conn, s->line_start + 1, 1, &gotbytes);
if(r == CHUNKE_STOP) {
/* we're done reading chunks! */
infof(data, "chunk reading DONE\n");
s->keepon = FALSE;
/* we did the full CONNECT treatment, go to COMPLETE */
s->tunnel_state = TUNNEL_COMPLETE;
}
}
else {
/* without content-length or chunked encoding, we
can't keep the connection alive since the close is
the end signal so we bail out at once instead */
s->keepon = FALSE;
}
}
else
s->keepon = FALSE;
if(!s->cl)
/* we did the full CONNECT treatment, go to COMPLETE */
s->tunnel_state = TUNNEL_COMPLETE;
continue;
}
s->line_start[s->perline] = 0; /* zero terminate the buffer */
if((checkprefix("WWW-Authenticate:", s->line_start) &&
(401 == k->httpcode)) ||
(checkprefix("Proxy-authenticate:", s->line_start) &&
(407 == k->httpcode))) {
bool proxy = (k->httpcode == 407) ? TRUE : FALSE;
char *auth = Curl_copy_header_value(s->line_start);
if(!auth)
return CURLE_OUT_OF_MEMORY;
result = Curl_http_input_auth(conn, proxy, auth);
free(auth);
if(result)
return result;
}
else if(checkprefix("Content-Length:", s->line_start)) {
if(k->httpcode/100 == 2) {
/* A client MUST ignore any Content-Length or Transfer-Encoding
header fields received in a successful response to CONNECT.
"Successful" described as: 2xx (Successful). RFC 7231 4.3.6 */
infof(data, "Ignoring Content-Length in CONNECT %03d response\n",
k->httpcode);
}
else {
(void)curlx_strtoofft(s->line_start +
strlen("Content-Length:"), NULL, 10, &s->cl);
}
}
else if(Curl_compareheader(s->line_start, "Connection:", "close"))
s->close_connection = TRUE;
else if(checkprefix("Transfer-Encoding:", s->line_start)) {
size_t tool_header_cb(void *ptr, size_t size, size_t nmemb, void *userdata)
{
struct HdrCbData *hdrcbdata = userdata;
struct OutStruct *outs = hdrcbdata->outs;
struct OutStruct *heads = hdrcbdata->heads;
const char *str = ptr;
const size_t cb = size * nmemb;
const char *end = (char*)ptr + cb;
/*
* Once that libcurl has called back tool_header_cb() the returned value
* is checked against the amount that was intended to be written, if
* it does not match then it fails with CURLE_WRITE_ERROR. So at this
* point returning a value different from sz*nmemb indicates failure.
*/
size_t failure = (size * nmemb) ? 0 : 1;
if(!heads->config)
return failure;
#ifdef DEBUGBUILD
if(size * nmemb > (size_t)CURL_MAX_HTTP_HEADER) {
warnf(heads->config->global, "Header data exceeds single call write "
"limit!\n");
return failure;
}
#endif
/*
* Write header data when curl option --dump-header (-D) is given.
*/
if(heads->config->headerfile && heads->stream) {
size_t rc = fwrite(ptr, size, nmemb, heads->stream);
if(rc != cb)
return rc;
/* flush the stream to send off what we got earlier */
(void)fflush(heads->stream);
}
/*
* This callback sets the filename where output shall be written when
* curl options --remote-name (-O) and --remote-header-name (-J) have
* been simultaneously given and additionally server returns an HTTP
* Content-Disposition header specifying a filename property.
*/
if(hdrcbdata->honor_cd_filename &&
(cb > 20) && checkprefix("Content-disposition:", str)) {
const char *p = str + 20;
/* look for the 'filename=' parameter
(encoded filenames (*=) are not supported) */
for(;;) {
char *filename;
size_t len;
while(*p && (p < end) && !ISALPHA(*p))
p++;
if(p > end - 9)
break;
if(memcmp(p, "filename=", 9)) {
/* no match, find next parameter */
while((p < end) && (*p != ';'))
p++;
continue;
}
p += 9;
/* this expression below typecasts 'cb' only to avoid
warning: signed and unsigned type in conditional expression
*/
len = (ssize_t)cb - (p - str);
filename = parse_filename(p, len);
if(filename) {
outs->filename = filename;
outs->alloc_filename = TRUE;
outs->is_cd_filename = TRUE;
outs->s_isreg = TRUE;
outs->fopened = FALSE;
outs->stream = NULL;
hdrcbdata->honor_cd_filename = FALSE;
break;
}
else
return failure;
}
}
return cb;
}
开发者ID:AndyUI,项目名称:curl,代码行数:92,代码来源:tool_cb_hdr.c
示例17: Curl_getFormData
//.........这里部分代码省略.........
}
if(file->contenttype) {
/* we have a specified type */
result = AddFormDataf(&form, &size,
"\r\nContent-Type: %s",
file->contenttype);
if (result)
break;
}
curList = file->contentheader;
while( curList ) {
/* Process the additional headers specified for this form */
result = AddFormDataf( &form, &size, "\r\n%s", curList->data );
if (result)
break;
curList = curList->next;
}
if (result) {
Curl_formclean(firstform);
free(boundary);
return result;
}
#if 0
/* The header Content-Transfer-Encoding: seems to confuse some receivers
* (like the built-in PHP engine). While I can't see any reason why it
* should, I can just as well skip this to the benefit of the users who
* are using such confused receivers.
*/
if(file->contenttype &&
!checkprefix("text/", file->contenttype)) {
/* this is not a text content, mention our binary encoding */
size += AddFormData(&form, "\r\nContent-Transfer-Encoding: binary", 0);
}
#endif
result = AddFormDataf(&form, &size, "\r\n\r\n");
if (result)
break;
if((post->flags & HTTPPOST_FILENAME) ||
(post->flags & HTTPPOST_READFILE)) {
/* we should include the contents from the specified file */
FILE *fileread;
fileread = strequal("-", file->contents)?
stdin:fopen(file->contents, "rb"); /* binary read for win32 */
/*
* VMS: This only allows for stream files on VMS. Stream files are
* OK, as are FIXED & VAR files WITHOUT implied CC For implied CC,
* every record needs to have a \n appended & 1 added to SIZE
*/
if(fileread) {
if(fileread != stdin) {
/* close the file again */
fclose(fileread);
/* add the file name only - for later reading from this */
result = AddFormData(&form, FORM_FILE, file->contents, 0, &size);
}
else {
/* When uploading from stdin, we can't know the size of the file,
请发表评论