/* add extension header (these fields are not parsed/analyzed/joined, etc.) */ void httpHeaderPutExt(HttpHeader * hdr, const char *name, const char *value) { assert(name && value); debug(55, 8) ("%p adds ext entry '%s: %s'\n", hdr, name, value); httpHeaderAddEntry(hdr, httpHeaderEntryCreate(HDR_OTHER, name, value)); }
// send check header "X-CC-DOWN-CHECK" to lower FC static int SendCheckHeader(clientHttpRequest *http) { // do not send X-CC-UP-CHECK to client as possible httpHeaderDelByName(&http->reply->header, "X-CC-UP-CHECK"); struct mod_conf_param *cfg = cc_get_mod_param(http->conn->fd, mod); if (NULL == cfg || !cfg->send) { debug(107,3)("mod_check_response: no need to send X-CC-UP-CHECK header\n"); return -1; } const char *down_buf = httpHeaderGetValue(&http->request->header, "X-CC-DOWN-CHECK"); if (NULL == down_buf) { if (cfg->send) debug(107,2)("mod_check_response: do not send X-CC-UP-CHECK header, for not received X-CC-DOWN-CHECK header\n"); return -1; } char key[512]; memset(key, 0, 512); unsigned char md5[SQUID_MD5_DIGEST_LENGTH]; memset(md5, 0, SQUID_MD5_DIGEST_LENGTH); strncpy(key, down_buf, 511); char *host = key + strlen(key); url2host(host, http->uri); GetMD5Digest(key, md5); assert(cfg->send); httpHeaderAddEntry(&http->reply->header, httpHeaderEntryCreate(HDR_OTHER, "X-CC-UP-CHECK", (char*)md5)); debug(107, 3)("mod_check_response: send X-CC-UP-CHECK=[%s] header to client\n", md5); return 0; }
static int func_http_repl_send_start(clientHttpRequest *http) { assert(http); if (0 == http->request->flags.redirected) return -1; HttpHeader *hdr = &http->reply->header; HttpHeaderEntry e; stringInit(&e.name,"Content-Disposition"); stringInit(&e.value,"attachment; filename=\""); char *filename = strrchr(http->uri, '/'); if (NULL == filename) return -1; filename++; stringAppend(&e.value, filename, strlen(filename)); stringAppend(&e.value, "\"", 1); e.id = HDR_CONTENT_DISPOSITION; httpHeaderDelById(hdr, e.id); httpHeaderAddEntry(hdr, httpHeaderEntryClone(&e)); stringClean(&e.name); stringClean(&e.value); return 0; }
void httpHeaderPutTime(HttpHeader * hdr, http_hdr_type id, time_t htime) { assert_eid(id); assert(Headers[id].type == ftDate_1123); /* must be of an appropriate type */ assert(htime >= 0); httpHeaderAddEntry(hdr, httpHeaderEntryCreate(id, NULL, mkrfc1123(htime))); }
void httpHeaderPutInt(HttpHeader * hdr, http_hdr_type id, int number) { assert_eid(id); assert(Headers[id].type == ftInt); /* must be of an appropriate type */ assert(number >= 0); httpHeaderAddEntry(hdr, httpHeaderEntryCreate(id, NULL, xitoa(number))); }
void httpHeaderPutStr(HttpHeader * hdr, http_hdr_type id, const char *str) { assert_eid(id); assert(Headers[id].type == ftStr); /* must be of an appropriate type */ assert(str); httpHeaderAddEntry(hdr, httpHeaderEntryCreate(id, NULL, str)); }
void httpHeaderPutSize(HttpHeader * hdr, http_hdr_type id, squid_off_t number) { char size[64]; assert_eid(id); assert(Headers[id].type == ftSize); /* must be of an appropriate type */ assert(number >= 0); snprintf(size, sizeof(size), "%" PRINTF_OFF_T, number); httpHeaderAddEntry(hdr, httpHeaderEntryCreate(id, NULL, size)); }
/* append entries (also see httpHeaderUpdate) */ void httpHeaderAppend(HttpHeader * dest, const HttpHeader * src) { const HttpHeaderEntry *e; HttpHeaderPos pos = HttpHeaderInitPos; assert(src && dest); assert(src != dest); debug(55, 7) ("appending hdr: %p += %p\n", dest, src); while ((e = httpHeaderGetEntry(src, &pos))) { httpHeaderAddEntry(dest, httpHeaderEntryClone(e)); } }
/* *This line is to modify the header */ static int mod_modify_s2o_header(HttpStateData* data, HttpHeader* hdr) { assert(data); int fd = data->fd; int i, len; struct mod_conf_param *param = (struct mod_conf_param *)cc_get_mod_param(fd, mod); assert(param); debug(107, 3)("param->orig_name=%s, param->new_name=%s\n", strBuf(param->orig_name), strBuf(param->new_name)); HttpHeaderPos pos = HttpHeaderInitPos; HttpHeaderEntry *myheader; HttpHeaderEntry e; while ((myheader = httpHeaderGetEntry(hdr, &pos))) { debug(107, 3)("myheader=%s, param->new_name=%s\n", strBuf(myheader->name), strBuf(param->new_name)); if (strCaseCmp(myheader->name, strBuf(param->orig_name)) == 0) { debug(107, 3)("%s is myheader->value,%s is param->orig_name\n",strBuf(myheader->value), strBuf(param->orig_name)); if(strLen(myheader->value) >= 4095) { debug(107, 3)("A too long header value!!\n"); return -1; } stringInit(&e.name, strBuf(param->new_name)); stringInit(&e.value, myheader->value.buf); len=strlen(strBuf(e.name)); i=httpHeaderIdByNameDef(strBuf(e.name), len); if(-1 == i) e.id = HDR_OTHER; else e.id = i; httpHeaderDelByName(hdr, strBuf(param->orig_name)); httpHeaderAddEntry(hdr, httpHeaderEntryClone(&e)); //httpHeaderDelAt(&request->header, pos); //httpHeaderRefreshMask(&request->header); //httpHeaderInsertEntry(&request->header, httpHeaderEntryClone(&e), pos); stringClean(&e.name); stringClean(&e.value); break; } } return 0; }
/* use fresh entries to replace old ones */ void httpHeaderUpdate(HttpHeader * old, const HttpHeader * fresh, const HttpHeaderMask * denied_mask) { const HttpHeaderEntry *e; HttpHeaderPos pos = HttpHeaderInitPos; assert(old && fresh); assert(old != fresh); debug(55, 7) ("updating hdr: %p <- %p\n", old, fresh); while ((e = httpHeaderGetEntry(fresh, &pos))) { /* deny bad guys (ok to check for HDR_OTHER) here */ if (denied_mask && CBIT_TEST(*denied_mask, e->id)) continue; httpHeaderDelByName(old, strBuf(e->name)); httpHeaderAddEntry(old, httpHeaderEntryClone(e)); } }
void httpHeaderPutRange(HttpHeader * hdr, const HttpHdrRange * range) { MemBuf mb; Packer p; assert(hdr && range); /* remove old directives if any */ httpHeaderDelById(hdr, HDR_RANGE); /* pack into mb */ memBufDefInit(&mb); packerToMemInit(&p, &mb); httpHdrRangePackInto(range, &p); /* put */ httpHeaderAddEntry(hdr, httpHeaderEntryCreate(HDR_RANGE, NULL, mb.buf)); /* cleanup */ packerClean(&p); memBufClean(&mb); }
void httpHeaderPutCc(HttpHeader * hdr, const HttpHdrCc * cc) { MemBuf mb; Packer p; assert(hdr && cc); /* remove old directives if any */ httpHeaderDelById(hdr, HDR_CACHE_CONTROL); /* pack into mb */ memBufDefInit(&mb); packerToMemInit(&p, &mb); httpHdrCcPackInto(cc, &p); /* put */ httpHeaderAddEntry(hdr, httpHeaderEntryCreate(HDR_CACHE_CONTROL, NULL, mb.buf)); /* cleanup */ packerClean(&p); memBufClean(&mb); }
int httpHeaderParse(HttpHeader * hdr, const char *header_start, const char *header_end) { const char *field_start = header_start; HttpHeaderEntry *e; assert(hdr); assert(header_start && header_end); debug(55, 7) ("parsing hdr: (%p)\n%s\n", hdr, getStringPrefix(header_start, header_end)); HttpHeaderStats[hdr->owner].parsedCount++; /* commonn format headers are "<name>:[ws]<value>" lines delimited by <CRLF> */ while (field_start < header_end) { const char *field_end; const char *field_ptr = field_start; do { field_end = field_ptr = field_ptr + strcspn(field_ptr, "\r\n"); /* skip CRLF */ if (*field_ptr == '\r') field_ptr++; if (*field_ptr == '\n') field_ptr++; } while (*field_ptr == ' ' || *field_ptr == '\t'); if (!*field_end || field_end > header_end) return httpHeaderReset(hdr); /* missing <CRLF> */ e = httpHeaderEntryParseCreate(field_start, field_end); if (e != NULL) httpHeaderAddEntry(hdr, e); else debug(55, 2) ("warning: ignoring unparseable http header field near '%s'\n", getStringPrefix(field_start, field_end)); field_start = field_end; /* skip CRLF */ if (*field_start == '\r') field_start++; if (*field_start == '\n') field_start++; } return 1; /* even if no fields where found, it is a valid header */ }
// send a special header to upper FC static int SendRandomNumber(HttpStateData *httpState, HttpHeader* hdr) { struct mod_conf_param *cfg = cc_get_mod_param(httpState->fd, mod); if (NULL == cfg) return -1; struct timeval tp; if (gettimeofday(&tp, NULL)) { debug(107, 2)("mod_check_response: gettimeofday error\n"); return -1; } struct send_random *data = cc_get_mod_private_data(FWDSTATE_PRIVATE_DATA, httpState->fwd, mod); if (!data) { data = xcalloc(1, sizeof(struct send_random)); snprintf(data->number, 10, "%ld", tp.tv_usec); cc_register_mod_private_data(FWDSTATE_PRIVATE_DATA, httpState->fwd, data, free_random, mod); httpHeaderAddEntry(hdr, httpHeaderEntryCreate(HDR_OTHER, "X-CC-DOWN-CHECK", data->number)); debug(107,3)("mod_check_response: send X-CC-DOWN-CHECK=[%s] to orgin\n", data->number); } return 0; }
void httpHeaderAddClone(HttpHeader * hdr, const HttpHeaderEntry * e) { httpHeaderAddEntry(hdr, httpHeaderEntryClone(e)); }
/*if the origindomain doesn't need cookie,this part is not neccessary * static int update_cookie_direction_0(clientHttpRequest *http) { assert(http); assert(http->request); const char head_name_request[20] = "Cookie"; int len = strlen(head_name_request); int flag = 0; HttpHeaderPos pos = HttpHeaderInitPos; request_t* request = http->request; char *uri = http->uri; char cookie_value[100]="0"; char cookie_primary_key_name[20]; char cookie_sub_key_name[20]; int i = 0; debug(139,3)("in update_cookie_direction_0 receive uri %s\n",uri); HttpHeaderEntry e; HttpHeaderEntry *myheader; stringInit(&e.name, head_name_request); i = httpHeaderIdByNameDef(head_name_request, len); e.id = i; if (-1 == i) e.id = HDR_OTHER; while ((myheader = httpHeaderGetEntry(&request->header, &pos))) { if (strCaseCmp(myheader->name, head_name_request) == 0) { debug(139, 3)("%s is myheader->value,%s is name\n",myheader->value.buf,myheader->name.buf); flag = 1; } } debug(139,3)("flag=%d\n",flag); if(!flag) { if(0 == get_param_from_uri(uri,cookie_primary_key_name,cookie_sub_key_name)) { return 1; } to_upper(cookie_primary_key_name); snprintf(cookie_value,100,"%s:(FM%s=0)",cookie_primary_key_name,cookie_sub_key_name); debug(139,3)("cookie value is %s\n",cookie_value); debug(139,3)("cookie_primary_key_name is %s\n",cookie_primary_key_name); debug(139,3)("cookie_sub_key_name is %s\n",cookie_sub_key_name); stringInit(&e.value, cookie_value); httpHeaderAddEntry(&request->header, httpHeaderEntryClone(&e)); } return 1; } */ static int update_cookie_direction_3(clientHttpRequest *http) { assert(http); assert(http->request); // const char head_name_request[20] = "Cookie"; const char head_name_reply[20] = "Set-Cookie"; // int len = strlen(head_name_reply); // int flag = 0; // HttpHeaderPos pos = HttpHeaderInitPos; // request_t* request = http->request; HttpReply* reply = http->reply; char *uri = http->uri; // char cookie_value[MAX_NAME_SIZE] = "0"; // char cookie_value_from_url[MAX_NAME_SIZE] = "0 "; char cookie_primary_key_name[MAX_NAME_SIZE] = "0"; char cookie_sub_key_name[MAX_NAME_SIZE] = "0"; char cookie_file_name[MAX_NAME_SIZE] = "0"; debug(139,3)("in update_cookie_direction_3 receive uri %s\n",uri); HttpHeaderEntry e; // HttpHeaderEntry *myheader; stringInit(&e.name, head_name_reply); // i = httpHeaderIdByNameDef(head_name_reply, len); // e.id = i; e.id = HDR_SET_COOKIE; // if (-1 == i) // e.id = HDR_OTHER; /* while ((myheader = httpHeaderGetEntry(&request->header, &pos))) { if (strCaseCmp(myheader->name, head_name_request) == 0) { debug(139, 3)("%s is myheader->value,%s is name\n",myheader->value.buf,myheader->name.buf); flag = 1; strcpy(cookie_value,myheader->value.buf); debug(139,5)("cookie_value =%s\n",cookie_value); if(0 == deal_with_cookie(cookie_value)) { debug(139,3)("Cookie format is wrong\n"); return 0; } if(0 == get_param_from_uri(uri,cookie_primary_key_name,cookie_sub_key_name)) { debug(139,3)("get_param_from_uri error\n"); return 0; } to_upper(cookie_primary_key_name); snprintf(cookie_value_from_url,100,"%s:(FM%s=",cookie_primary_key_name,cookie_sub_key_name); debug(139,5)("cookie_value_from_url is %s\n",cookie_value_from_url); if(strncmp(cookie_value,cookie_value_from_url,strlen(cookie_value_from_url))) { debug(139,3)("get_param_from_uri cookie_value_from_url doesn't match cookie_value\n"); return 0; } } } */ if(reply->sline.status >= HTTP_OK && reply->sline.status < HTTP_BAD_REQUEST ) { if(0 == get_param_from_uri(uri,cookie_primary_key_name,cookie_sub_key_name,cookie_file_name)) { debug(139,3)("get_param_from_uri error\n"); stringClean(&e.name); return 0; } struct tm *ptr; ptr = gmtime(&reply->expires); debug(139,3)("expires = %s\n", asctime(ptr)); char tmpbuf[128]; char cookie_value[MAX_HEADER_SIZE]; strftime( tmpbuf, 128, "%a, %d %b %G %T GMT \n", ptr); debug(139,3)("expires = %s\n", tmpbuf); snprintf(cookie_value,MAX_HEADER_SIZE,"DTAG=CAM=%s&LOC=%s&CRT=%s; expires=%s; path=/",cookie_primary_key_name,cookie_sub_key_name,cookie_file_name,tmpbuf); debug(139,5)("cookie value is %s\n",cookie_value); stringInit(&e.value, cookie_value); httpHeaderAddEntry(&reply->header, httpHeaderEntryClone(&e)); stringClean(&e.value); } else { ;//do nothing } stringClean(&e.name); return 1; }
/* *?????Ǵ????ġ?????һ??header?Ĵ??�?? */ static int modifyHeader3(struct action_part* acp, HttpReply* reply) { assert(acp); assert(reply); int flag = 0; int act = acp->action; struct header_info* hdr = acp->hdr; HttpHeaderEntry e; //HttpHeaderEntry *mye; int i; HttpHeaderEntry *myheader; HttpHeaderPos pos = HttpHeaderInitPos + HDR_ENUM_END; e.name = stringDup(&hdr->header); e.value = stringDup(&hdr->value); i = httpHeaderIdByNameDef(strBuf(hdr->header), strLen(hdr->header)); e.id = i; if(i == -1) { e.id = HDR_OTHER; if(0 == act) { httpHeaderAddEntry(&reply->header, httpHeaderEntryClone(&e)); } else if(2 == act) { while ((myheader = httpHeaderGetEntryPlus(&reply->header, &pos))) { if (myheader->id == HDR_OTHER && strCaseCmp(myheader->name, strBuf(hdr->header)) == 0) { debug(98, 3)("%s is myheader->value,%s is hdr->value\n",strBuf(myheader->value), strBuf(hdr->value)); stringReset(&myheader->value, strBuf(hdr->value)); } } } else if(1 == act) { httpHeaderDelByName(&reply->header,strBuf(hdr->header)); } else if(3 == act) { while ((myheader = httpHeaderGetEntryPlus(&reply->header, &pos))) { if (myheader->id == HDR_OTHER && strCaseCmp(myheader->name, strBuf(hdr->header)) == 0) { debug(98, 3)("%s is myheader->value,%s is hdr->value\n",strBuf(myheader->value), strBuf(hdr->value)); flag = 1; stringReset(&myheader->value, strBuf(hdr->value)); } } if(!flag) httpHeaderAddEntry(&reply->header, httpHeaderEntryClone(&e)); } } else { //mye = httpHeaderFindEntry2(&reply->header, i); //debug(98, 3) ("%d is i\n", i); if(0 == act) { httpHeaderAddEntry(&reply->header, httpHeaderEntryClone(&e)); } else if(2 == act) { if(httpHeaderDelByName(&reply->header,strBuf(hdr->header))) { httpHeaderAddEntry(&reply->header, httpHeaderEntryClone(&e)); } //mye = httpHeaderFindEntry2(&reply->header, i); //debug(98, 3)("%s is newvalue\n",strBuf(mye->value)); } else if(1 == act) { httpHeaderDelByName(&reply->header,strBuf(hdr->header)); } else if(3 == act) { httpHeaderDelByName(&reply->header,strBuf(hdr->header)); httpHeaderAddEntry(&reply->header, httpHeaderEntryClone(&e)); } } stringClean(&e.name); stringClean(&e.value); return 0; }
int httpHeaderParse(HttpHeader * hdr, const char *header_start, const char *header_end) { const char *field_ptr = header_start; HttpHeaderEntry *e; assert(hdr); assert(header_start && header_end); debug(55, 7) ("parsing hdr: (%p)\n%s\n", hdr, getStringPrefix(header_start, header_end)); HttpHeaderStats[hdr->owner].parsedCount++; if (memchr(header_start, '\0', header_end - header_start)) { debug(55, 1) ("WARNING: HTTP header contains NULL characters {%s}\n", getStringPrefix(header_start, header_end)); return httpHeaderReset(hdr); } /* common format headers are "<name>:[ws]<value>" lines delimited by <CRLF>. * continuation lines start with a (single) space or tab */ while (field_ptr < header_end) { const char *field_start = field_ptr; const char *field_end; do { const char *this_line = field_ptr; field_ptr = memchr(field_ptr, '\n', header_end - field_ptr); if (!field_ptr) return httpHeaderReset(hdr); /* missing <LF> */ field_end = field_ptr; field_ptr++; /* Move to next line */ if (field_end > this_line && field_end[-1] == '\r') { field_end--; /* Ignore CR LF */ /* Ignore CR CR LF in relaxed mode */ if (Config.onoff.relaxed_header_parser && field_end > this_line + 1 && field_end[-1] == '\r') { debug(55, Config.onoff.relaxed_header_parser <= 0 ? 1 : 2) ("WARNING: Double CR characters in HTTP header {%s}\n", getStringPrefix(field_start, field_end)); field_end--; } } /* Barf on stray CR characters */ if (memchr(this_line, '\r', field_end - this_line)) { debug(55, 1) ("WARNING: suspicious CR characters in HTTP header {%s}\n", getStringPrefix(field_start, field_end)); if (Config.onoff.relaxed_header_parser) { char *p = (char *) this_line; /* XXX Warning! This destroys original header content and violates specifications somewhat */ while ((p = memchr(p, '\r', field_end - p)) != NULL) *p++ = ' '; } else return httpHeaderReset(hdr); } if (this_line + 1 == field_end && this_line > field_start) { debug(55, 1) ("WARNING: Blank continuation line in HTTP header {%s}\n", getStringPrefix(header_start, header_end)); return httpHeaderReset(hdr); } } while (field_ptr < header_end && (*field_ptr == ' ' || *field_ptr == '\t')); if (field_start == field_end) { if (field_ptr < header_end) { debug(55, 1) ("WARNING: unparseable HTTP header field near {%s}\n", getStringPrefix(field_start, header_end)); return httpHeaderReset(hdr); } break; /* terminating blank line */ } e = httpHeaderEntryParseCreate(field_start, field_end); if (NULL == e) { debug(55, 1) ("WARNING: unparseable HTTP header field {%s}\n", getStringPrefix(field_start, field_end)); debug(55, Config.onoff.relaxed_header_parser <= 0 ? 1 : 2) (" in {%s}\n", getStringPrefix(header_start, header_end)); if (Config.onoff.relaxed_header_parser) continue; else return httpHeaderReset(hdr); } if (e->id == HDR_CONTENT_LENGTH) { squid_off_t l1; HttpHeaderEntry *e2; if (!httpHeaderParseSize(strBuf(e->value), &l1)) { debug(55, 1) ("WARNING: Unparseable content-length '%s'\n", strBuf(e->value)); httpHeaderEntryDestroy(e); return httpHeaderReset(hdr); } e2 = httpHeaderFindEntry(hdr, e->id); if (e2 && strCmp(e->value, strBuf(e2->value)) != 0) { squid_off_t l2; debug(55, Config.onoff.relaxed_header_parser <= 0 ? 1 : 2) ("WARNING: found two conflicting content-length headers in {%s}\n", getStringPrefix(header_start, header_end)); if (!Config.onoff.relaxed_header_parser) { httpHeaderEntryDestroy(e); return httpHeaderReset(hdr); } if (!httpHeaderParseSize(strBuf(e2->value), &l2)) { debug(55, 1) ("WARNING: Unparseable content-length '%s'\n", strBuf(e->value)); httpHeaderEntryDestroy(e); return httpHeaderReset(hdr); } if (l1 > l2) { httpHeaderDelById(hdr, e2->id); } else { httpHeaderEntryDestroy(e); continue; } } else if (e2) { debug(55, Config.onoff.relaxed_header_parser <= 0 ? 1 : 2) ("NOTICE: found double content-length header\n"); if (Config.onoff.relaxed_header_parser) { httpHeaderEntryDestroy(e); continue; } else { httpHeaderEntryDestroy(e); return httpHeaderReset(hdr); } } } if (e->id == HDR_OTHER && stringHasWhitespace(strBuf(e->name))) { debug(55, Config.onoff.relaxed_header_parser <= 0 ? 1 : 2) ("WARNING: found whitespace in HTTP header name {%s}\n", getStringPrefix(field_start, field_end)); if (!Config.onoff.relaxed_header_parser) { httpHeaderEntryDestroy(e); return httpHeaderReset(hdr); } } httpHeaderAddEntry(hdr, e); } return 1; /* even if no fields where found, it is a valid header */ }