ci_off_t ci_http_content_length(ci_request_t * req) { ci_headers_list_t *heads; const char *val; ci_off_t res = 0; char *e; if (!(heads = ci_http_response_headers(req))) { /*Then maybe is a reqmod reauest, try to get request headers */ if (!(heads = ci_http_request_headers(req))) return 0; } if (!(val = ci_headers_value(heads, "Content-Length"))) return -1; errno = 0; res = ci_strto_off_t(val, &e, 10); if (errno == ERANGE && (res == CI_STRTO_OFF_T_MAX || res == CI_STRTO_OFF_T_MIN)) { ci_debug_printf(4, "Content-Length: overflow\n"); return -2; } if (val == e) { ci_debug_printf(4, "Content-Length: not valid value: '%s' \n", val); return -2; } return res; }
int access_check_logging(ci_request_t * req) { char *user; int i, res; if (!used_access_controllers) return CI_ACCESS_DENY; user = ci_headers_value(req->request_header, "X-Authenticated-User"); if (user) { ci_base64_decode(user, req->user, MAX_USERNAME_LEN); } i = 0; while (used_access_controllers[i] != NULL) { if (used_access_controllers[i]->log_access) { res = used_access_controllers[i]->log_access(req->user, req->service, req->type, &(req->connection-> claddr), &(req->connection-> srvaddr)); if (res != CI_ACCESS_UNKNOWN) return res; } i++; } return CI_ACCESS_DENY; /*By default log this request ....... */ }
const char *get_header(ci_headers_list_t *headers, char *head) { const char *val; char *buf; int i; if(!headers || !head) return NULL; if (!(val = ci_headers_value(headers, head))) return NULL; if (!headers->packed) /*The headers are not packed, so it is NULL terminated*/ return val; /*assume that an 8k buffer is enough for a header value*/ if (!(buf = ci_buffer_alloc(8192))) return NULL; for(i=0;i<8191 && *val!= '\0' && *val != '\r' && *val!='\n'; i++,val++) buf[i] = *val; buf[8191]='\0'; return buf; }
const char *ci_http_request_get_header(ci_request_t * req, const char *head_name) { ci_headers_list_t *heads; const char *val; if (!(heads = ci_http_request_headers(req))) return NULL; if (!(val = ci_headers_value(heads, head_name))) return NULL; return val; }
char *ci_respmod_get_header(request_t * req, char *head_name) { ci_headers_list_t *heads; char *val; if (!(heads = ci_respmod_headers(req))) return NULL; if (!(val = ci_headers_value(heads, head_name))) return NULL; return val; }
/* static int search_record_data_init(struct search_record_req_data *data) { if((data->full_url = malloc(URL_LEN*sizeof(char))) == NULL) return 0; if((data->ip = malloc(IP_LEN*sizeof(char))) == NULL) return 0; // if((data->body = ci_membuf_new()) == NULL) // return 0; return 1; } static void search_record_data_clean(struct search_record_req_data *data) { free(data->full_url); free(data->ip); } */ static const char* get_client_ip(ci_request_t* req,char* result) { const char* ip; if((ip = ci_http_request_get_header(req,"X-Forwarded-For")) == NULL) { ip = ci_headers_value(req->request_header,"X-Client-IP"); if(ip == NULL) return NULL; } strcpy(result,ip); return result; }
ci_off_t ci_content_lenght(request_t * req) { ci_headers_list_t *heads; char *val; if (!(heads = ci_respmod_headers(req))) { /*Then maybe is a reqmod reauest, try to get request headers */ if (!(heads = ci_reqmod_headers(req))) return 0; } if (!(val = ci_headers_value(heads, "Content-Length"))) return 0; return ci_strto_off_t(val, NULL, 10); }
int fmt_httpserverip(ci_request_t *req, char *buf,int len, char *param) { char *s; int i; if (!len) return 0; if ((s = ci_headers_value(req->request_header, "X-Server-IP")) != NULL) { for(i=0;i<len && *s!= '\0' && *s != '\r' && *s!='\n'; i++,s++) buf[i] = *s; return i; } else { *buf = '-'; return 1; } }
int get_http_info(request_t *req,ci_headers_list_t *req_header , struct http_info *httpinf){ char *str; int i; /*Now get the site name*/ str=ci_headers_value(req_header,"Host"); strncpy(httpinf->site,str,CI_MAXHOSTNAMELEN); httpinf->site[CI_MAXHOSTNAMELEN]='\0'; str=req_header->headers[0]; if(str[0]=='g' || str[0]=='G') /*Get request....*/ httpinf->method=HTTP_GET; else if(str[0]=='p' || str[0]=='P') /*post request....*/ httpinf->method=HTTP_POST; else{ httpinf->method=HTTP_UNKNOWN; return 0; } if((str=strchr(str,' '))==NULL){ /*The request must have the form:GETPOST page HTTP/X.X */ return 0; } while(*str==' ') str++; i=0; while(*str!=' ' && *str!='\0' && i<1022) /*copy page to the struct.*/ httpinf->page[i++]=*str++; httpinf->page[i]='\0'; if(*str!=' '){ /*Where is the protocol info?????*/ return 0; } while(*str==' ') str++; if(*str!='H' || *(str+4)!='/'){ /*Not in HTTP/X.X form*/ return 0; } str+=5; httpinf->http_major=strtol(str,&str,10); if(*str!='.'){ return 0; } str++; httpinf->http_minor=strtol(str,&str,10); return 1; }
int ci_http_request_url(ci_request_t * req, char *buf, int buf_size) { ci_headers_list_t *heads; const char *str, *host; int i, bytes; /*The request must have the form: GET url HTTP/X.X */ if (!(heads = ci_http_request_headers(req))) return 0; if (!heads->used) return 0; str = heads->headers[0]; if ((str = strchr(str, ' ')) == NULL) { /*Ignore method i*/ return 0; } while (*str == ' ') /*ignore spaces*/ str++; bytes = 0; if (*str == '/' && (host = ci_headers_value(heads,"Host"))) { /*Looks like a transparent proxy, we do not know the protocol lets try to preserve the major part of the url.... */ for (i=0; (i < buf_size-1) && !header_end(host[i]) && !isspace(host[i]); i++) { buf[i] = host[i]; } buf += i; buf_size -= i; bytes = i; } /*copy the url...*/ for (i=0; (i < buf_size-1) && !header_end(str[i]) && !isspace(str[i]) && str[i] != '?'; i++) { buf[i] = str[i]; } buf[i] = '\0'; bytes += i; return bytes; }
int fmt_icap_res_head(ci_request_t *req, char *buf,int len, char *param) { char *s = NULL; int i; if (!len) return 0; if (!param || param[0] == '\0') { if (req->response_header && req->response_header->used) s = req->response_header->headers[0]; } else { s = ci_headers_value(req->response_header, param); } if (s) { for(i=0;i<len && *s!= '\0' && *s != '\r' && *s!='\n'; i++,s++) buf[i] = *s; return i; } else { *buf = '-'; return 1; } }
const ci_ip_t * ci_http_client_ip(ci_request_t * req) { const char *ip; if (!req) return NULL; if (req->xclient_ip.family == -1) /*Already check and failed to read it*/ return NULL; if (req->xclient_ip.family != 0) /*Already check, return cached*/ return &req->xclient_ip; if (!(ip = ci_headers_value(req->request_header, "X-Client-IP"))) return NULL; #ifdef HAVE_IPV6 if(strchr(ip, ':')) { if (ci_inet_aton(AF_INET6, ip, &(req->xclient_ip.address))) { req->xclient_ip.family = AF_INET6; ci_ipv6_inaddr_hostnetmask(req->xclient_ip.netmask); } else req->xclient_ip.family = -1; } else #endif { if (ci_inet_aton(AF_INET, ip, &(req->xclient_ip.address))) { req->xclient_ip.family = AF_INET; ci_ipv4_inaddr_hostnetmask(req->xclient_ip.netmask); } else req->xclient_ip.family = -1; } if (req->xclient_ip.family == -1) /*Failed to read correctly*/ return NULL; return &req->xclient_ip; }
int get_request_options(ci_request_t * req, ci_headers_list_t * h) { char *pstr; if ((pstr = ci_headers_value(h, "Preview")) != NULL) { req->preview = strtol(pstr, NULL, 10); } else req->preview = -1; req->allow204 = 0; if ((pstr = ci_headers_value(h, "Allow")) != NULL) { if (strtol(pstr, NULL, 10) == 204) req->allow204 = 1; } if ((pstr = ci_headers_value(h, "Connection")) != NULL && strncmp(pstr, "close", 5) == 0) { req->keepalive = 0; } /*Moreover we are interested for the followings */ if ((pstr = ci_headers_value(h, "Transfer-Preview")) != NULL) { /*Not implemented yet */ } if ((pstr = ci_headers_value(h, "Transfer-Ignore")) != NULL) { /*Not implemented yet */ } if ((pstr = ci_headers_value(h, "Transfer-Complete")) != NULL) { /*Not implemented yet */ } /* The headers Max-Connections and Options-TTL are not needed in this client but if this functions moves to a general client api must be implemented */ return CI_OK; }
int get_http_info(ci_request_t * req, ci_headers_list_t * req_header, struct http_info *httpinf) { char *str, *tmp; int i, proxy_mode=0; /*Initialize htto_info struct*/ httpinf->url[0]='\0'; httpinf->args = NULL; httpinf->site[0] = '\0'; httpinf->host[0] = '\0'; httpinf->server_ip[0] = '\0'; httpinf->method = HTTP_UNKNOWN; httpinf->port = 0; httpinf->proto = UNKNOWN; httpinf->http_major = -1; httpinf->http_minor = -1; /*Now get the site name */ str = ci_headers_value(req_header, "Host"); if (str) { strncpy(httpinf->host, str, CI_MAXHOSTNAMELEN); httpinf->site[CI_MAXHOSTNAMELEN] = '\0'; } /* When x-server-ip implemented in c-icap (and squid3) strcpy(http->inf,req->xserverip); else do a getipbyname */ str = req_header->headers[0]; if (str[0] == 'g' || str[0] == 'G') /*Get request.... */ httpinf->method = HTTP_GET; else if (str[0] == 'p' || str[0] == 'P') /*post request.... */ httpinf->method = HTTP_POST; /*else unknown*/ if ((str = strchr(str, ' ')) == NULL) { /*The request must have the form:GETPOST page HTTP/X.X */ return 0; } while (*str == ' ') str++; /*here we are at the beggining of the URL. If we are in a reqmod request the URL propably has the form http://site[:port]/page or just /page (where, in squid transparent mode?) */ /*check if we are in the form proto://url */ if ((tmp=strstr(str,"://"))) { proxy_mode=1; httpinf->proto = get_protocol(str,str-tmp); str = tmp+3; i=0; while(*str!=':' && *str!= '/' && i < CI_MAXHOSTNAMELEN){ httpinf->site[i] = *str; httpinf->url[i] = *str; i++; str++; } httpinf->site[i] = '\0'; httpinf->url[i] = '\0'; if(*str==':'){ httpinf->port = strtol(str+1,&tmp,10); if(*tmp!='/') return 0; /*Do we want the port contained into URL? if no:*/ /*str = tmp;*/ } } else { strcpy(httpinf->url, httpinf->host); strcpy(httpinf->site, httpinf->host); httpinf->port = 80; } i = strlen(httpinf->url); while (*str != ' ' && *str != '?' && *str != '\0' && i < MAX_PAGE_SIZE) /*copy page to the struct. */ httpinf->url[i++] = *str++; if (*str == '?') { httpinf->args = &(httpinf->url[i]); while (*str != ' ' && *str != '\0' && i < MAX_PAGE_SIZE) httpinf->url[i++] = *str++; /*copy page arguments*/ } httpinf->url[i] = '\0'; if (*str != ' ') { /*Where is the protocol info????? */ return 0; } while (*str == ' ') str++; if (*str != 'H' || *(str + 4) != '/') { /*Not in HTTP/X.X form */ return 0; } str += 5; httpinf->http_major = strtol(str, &str, 10); if (*str != '.') { return 0; } str++; httpinf->http_minor = strtol(str, &str, 10); return 1; }