static struct cookie *cookie_from_netscape_line(char *cookie_line) { struct cookie *new_cookie = NULL; if (cookie_line && cookie_line[0]) { /* Only parse the line if it is not a comment and it has the requisite number * of tabs. Comment lines begin with a leading # symbol. * Syntax checking is rudimentary, because these lines are * machine-generated. */ if (cookie_line[0] != '#' && count_tabs(cookie_line) == FIELDS_PER_COOKIE_LINE - 1) { char *start, *end; new_cookie = allocZeroMem(sizeof(struct cookie)); start = cookie_line; end = strchr(cookie_line, '\t'); new_cookie->domain = pullString1(start, end); start = end + 1; end = strchr(start, '\t'); if ((*start == 't') || (*start == 'T')) new_cookie->tail = true; else new_cookie->tail = false; start = end + 1; end = strchr(start, '\t'); new_cookie->path = pullString1(start, end); start = end + 1; if (*start == 'T' || *start == 't') new_cookie->secure = true; else new_cookie->secure = false; start = strchr(start, '\t') + 1; new_cookie->expires = strtol(start, &end, 10); /* Now end points to the tab following the expiration time. */ start = end + 1; end = strchr(start, '\t'); new_cookie->name = pullString1(start, end); start = end + 1; /* strcspn gives count of non-newline characters in string, which is the * length of the final field. Either CR or LF is considered a newline. */ new_cookie->value = pullString(start, strcspn(start, "\r\n")); /* Whenever new_cookie->tail is true, there's going to be a dot at the front of the * domain name. Libcurl even puts one there when it parses set-cookie * headers. But let's be sure. */ if (new_cookie->tail && (new_cookie->domain[0] != '.')) new_cookie->domain = prependString(new_cookie->domain, "."); } } return new_cookie; } /* cookie_from_netscape_line */
static item_string* pullString (const char** ptr, int length) { item_string* result; char c = *(*ptr)++; if (c != '"') { int cl = 0; unsigned mask = 0; unsigned codepoint = (uint8_t)c; if (c == '\\') { c = *(*ptr)++; switch (c) { case '\\': codepoint = '\\'; break; case '/': codepoint = '/'; break; case '"': codepoint = '"'; break; case 'b': codepoint = '\b'; break; case 't': codepoint = '\t'; break; case 'n': codepoint = '\n'; break; case 'f': codepoint = '\f'; break; case 'r': codepoint = '\r'; break; case 'u': sscanf(*ptr,"%4x",&codepoint); *ptr += 4; if (codepoint & 0xff80) { if (codepoint & 0xf800) { cl = 2; mask = 0xe0; } else { cl = 1; mask = 0xc0; } } default: break; } } result = pullString (ptr, length + cl + 1); for (;cl > 0;cl--) { result->string[length+cl] = (codepoint & 0x3F) | 0x80; codepoint >>= 6; } result->string[length] = (char)(codepoint | mask); }