Example #1
0
/* XFF version: takes IP from X-Forwarded-For header */
void vcl_geoip_country_set_header_xff(const struct sess *sp) {
    vcl_string hval[HEADER_MAXLEN];
    vcl_string *ip = VRT_GetHdr(sp, HDR_REQ, "\020X-Forwarded-For:");
    if (ip) {
        geoip_lookup_country(ip, hval);
        VRT_SetHdr(sp, HDR_REQ, "\011X-Geo-IP:", hval, vrt_magic_string_end);
    } else {
        VCL_Log("geoip: no ip from X-Forwarded-For");
        VRT_SetHdr(sp, HDR_REQ, "\011X-Geo-IP:", "", vrt_magic_string_end);
    }
}
static int vmod_Hook_vcl_error(struct sess *sp){
	int status=VRT_r_obj_status(sp);
	if (
		status == 301 ||
		status == 302 ||
		status == 303
	){
		char * location = VRT_GetHdr(sp, HDR_REQ, "\030X-VMODREDIRECT-Location:");
		if(location != 0){
			VRT_SetHdr(sp, HDR_OBJ, "\011Location:" , location , vrt_magic_string_end);
			VRT_done(sp, VCL_RET_DELIVER);
		}
	}

	return(vmod_redirect_Hook_vcl_error(sp));

}
int 
vmod_parse(struct sess *sp,const char* tgHeadName,unsigned setParam,const char* paramPrefix,unsigned parseMulti,unsigned parseFile){
#ifdef DEBUG_SYSLOG
		syslog(6,"parse:start");
#endif

/*
	struct sess *sp,			OK
	const char* tgHeadName,		OK
	const char* paramPrefix,	url,
	unsigned setParam,			url,
	unsigned parseMulti,		OK
	unsigned parseFile			OK
*/	
	//デバッグでReInitとかrestartの時に不具合でないかチェック(ロールバックも)
//Content = pipeline.e-bの時はRxbuf確保をしない(必要ないので)
//mix形式をurlencodeに切り替える(組み換えで安全に)<-完了
/*
	  string(41) "submitter\"=a&submitter2=b&submitter3=vcc"
    string(42) "submitter%5C=a&submitter2=b&submitter3=vcc"
    
  string(39) "submitter=a&submitter2=b&submitter3=vcc"
  string(39) "submitter=a&submitter2=b&submitter3=vcc"
  string(83) "submitter=%e3%81%82%e3%81%84%e3%81%86%e3%81%88%e3%81%8a&submitter2=b&submitter3=vcc"
  string(83) "submitter=%E3%81%82%E3%81%84%E3%81%86%E3%81%88%E3%81%8A&submitter2=b&submitter3=vcc"

	1	=成功
	-1	=エラー		ワークスペースサイズが足りない
	-2	=エラー		target/ContentLengthがない/不正
	-3	=エラー		指定ContentLengthに満たないデータ
	-4	=エラー		未対応形式
	if (!(
		!VRT_strcmp(VRT_r_req_request(sp), "POST") ||
		!VRT_strcmp(VRT_r_req_request(sp), "PUT")
	)){return "";}
*/
	unsigned long	content_length,orig_content_length;
	char 			*h_clen_ptr, *h_ctype_ptr, *body;
	int				buf_size, rsize;
	char			buf[1024],tgHead[256];
	unsigned		multipart = 0;

	
	
	//////////////////////////////
	//build tgHead
	int hsize = strlen(tgHeadName) +1;
	if(hsize > 1){
		if(hsize > 255){
#ifdef DEBUG_SYSLOG
		syslog(6,"parse:err -2");
#endif
			return -2;
		}
		tgHead[0] = hsize;
		tgHead[1] = 0;
		snprintf(tgHead +1,255,"%s:",tgHeadName);
	}else{
		tgHead[0] = 0;
	}

	//////////////////////////////
	//check Content-Type
#ifdef DEBUG_SYSLOG
		syslog(6,"GetHdr Content-Type:");
#endif

	h_ctype_ptr = VRT_GetHdr(sp, HDR_REQ, "\015Content-Type:");
	
	if(h_ctype_ptr != NULL){
		if      (h_ctype_ptr == strstr(h_ctype_ptr, "application/x-www-form-urlencoded")) {
			//application/x-www-form-urlencoded
		}else if(h_ctype_ptr == strstr(h_ctype_ptr, "multipart/form-data") && parseMulti){
			//multipart/form-data
			multipart = 1;
		}else{
#ifdef DEBUG_SYSLOG
		syslog(6,"parse:err -4");
#endif
			return -4;
		}
	}else{
		//none support type
#ifdef DEBUG_SYSLOG
		syslog(6,"parse:err -4");
#endif
		return -4;
	}

	//////////////////////////////
	//check Content-Length
#ifdef DEBUG_SYSLOG
		syslog(6,"GetHdr Content-Length:");
#endif

	h_clen_ptr = VRT_GetHdr(sp, HDR_REQ, "\017Content-Length:");
	if (!h_clen_ptr) {
		//can't get
#ifdef DEBUG_SYSLOG
		syslog(6,"parse:err -2");
#endif
		return -2;
	}
	orig_content_length = content_length = strtoul(h_clen_ptr, NULL, 10);

	if (content_length <= 0) {
		//illegal length
#ifdef DEBUG_SYSLOG
		syslog(6,"parse:err -2");
#endif
		return -2;
	}

	//////////////////////////////
	//Check POST data is loaded
#ifdef DEBUG_HTCREAD
	if(0 == 1){
#else
	if(sp->htc->pipeline.b != NULL && Tlen(sp->htc->pipeline) == content_length){
#endif

#ifdef DEBUG_SYSLOG
		syslog(6,"noread");
#endif
		//complete read
		body = sp->htc->pipeline.b;
	}else{
#ifdef DEBUG_SYSLOG
		syslog(6,"read");
#endif
		//incomplete read
		int rxbuf_size = Tlen(sp->htc->rxbuf);
		///////////////////////////////////////////////
		//use ws
		int u = WS_Reserve(sp->wrk->ws, 0);
		if(u < content_length + rxbuf_size + 1){
#ifdef DEBUG_SYSLOG
		syslog(6,"parse:err -1");
#endif
			return -1;
		}
		body = (char*)sp->wrk->ws->f;
		memcpy(body, sp->htc->rxbuf.b, rxbuf_size);
		sp->htc->rxbuf.b = body;
		body += rxbuf_size;
		body[0]= 0;
		sp->htc->rxbuf.e = body;
		WS_Release(sp->wrk->ws,content_length + rxbuf_size + 1);
		///////////////////////////////////////////////
		
		//////////////////////////////
		//read post data
		while (content_length) {
			if (content_length > sizeof(buf)) {
				buf_size = sizeof(buf) - 1;
			}
			else {
				buf_size = content_length;
			}

			// read body data into 'buf'
			//rsize = HTC_Read(sp->htc, buf, buf_size);
			rsize = vmod_HTC_Read(sp->wrk, sp->htc, buf, buf_size);
			if (rsize <= 0) {
#ifdef DEBUG_SYSLOG
		syslog(6,"parse:err -3");
#endif
				return -3;
			}

			hsize += rsize;
			content_length -= rsize;

			strncat(body, buf, buf_size);
		}
		sp->htc->pipeline.b = body;
		sp->htc->pipeline.e = body + orig_content_length;
	}


	//////////////////////////////
	//decode form
#ifdef DEBUG_SYSLOG
		syslog(6,"content-size (orig)%d (read)%d",orig_content_length,strlen(body));
#endif

	int ret = 1;
	if(multipart){
		ret = decodeForm_multipart(sp, body,tgHead,parseFile,paramPrefix,setParam);
	}else{
		if(tgHead[0] != 0)
			VRT_SetHdr(sp, HDR_REQ, tgHead, body, vrt_magic_string_end);
		if(setParam)
			ret = decodeForm_urlencoded(sp, body,paramPrefix);
	}
#ifdef DEBUG_SYSLOG
		syslog(6,"parse:end %d",ret);
#endif
	return ret;
}
int decodeForm_multipart(struct sess *sp,char *body,char *tgHead,unsigned parseFile,const char *paramPrefix, unsigned setParam){
	
	char *prefix;
	char defPrefix[] = "X-VMODPOST-";
	if(!setParam){
		prefix = defPrefix;
	}else{
		prefix = (char*)paramPrefix;
	}
	int prefix_len = strlen(prefix);
	char tmp;
	char head[256];
	char sk_boundary[258];
	char *raw_boundary, *h_ctype_ptr;
	char *p_start, *p_end, *p_body_end, *name_line_end, *name_line_end_tmp, *start_body, *sc_name, *sc_filename;
	int  hsize, boundary_size ,idx;
	
	char *tmpbody    = body;
	int  encoded_size= 0;
	char *basehead   = 0;
	char *curhead;
	int  ll_u, ll_head_len, ll_size;
	int  ll_entry_count = 0;

	int u;
	char *orig_cv_body, *cv_body, *h_val;
	
	//////////////////////////////
	//get boundary
#ifdef DEBUG_SYSLOG
		syslog(6,"GetHdr Content-Type:");
#endif

	h_ctype_ptr = VRT_GetHdr(sp, HDR_REQ, "\015Content-Type:");
	raw_boundary = strstr(h_ctype_ptr,"; boundary=");
	if(!raw_boundary || strlen(raw_boundary) > 255){
#ifdef DEBUG_SYSLOG
		syslog(6,"parse:decodeForm_multipart boudary size>255");
#endif
		return -5;
	}
	
	raw_boundary   +=11;
	sk_boundary[0] = '-';
	sk_boundary[1] = '-';
	sk_boundary[2] = 0;
	strncat(sk_boundary,raw_boundary,strlen(raw_boundary));
	boundary_size = strlen(sk_boundary);


	p_start = strstr(tmpbody,sk_boundary);
	while(1){
		///////////////////////////////////////////////
		//search data
		if(!p_start) break;

		//boundary
		p_end = strstr(p_start + 1,sk_boundary);
		if(!p_end) break;
		//name
		sc_name = strstr(p_start +boundary_size,"name=\"");
		if(!sc_name) break;
		sc_name+=6;
		//line end
		name_line_end  = strstr(sc_name,"\"\r\n");
		name_line_end_tmp = strstr(sc_name,"\"; ");
		if(!name_line_end) break;
		
		if(name_line_end_tmp && name_line_end_tmp < name_line_end)
			name_line_end = name_line_end_tmp;
		
		//body
		start_body = strstr(sc_name,"\r\n\r\n");
		if(!start_body) break;
		//filename
		sc_filename  = strstr(sc_name,"; filename");

		///////////////////////////////////////////////
		//build head
		if((name_line_end -1)[0]=='\\'){
			idx = 1;
		}else{
			idx=0;
		}
		tmp                   = name_line_end[idx];
		name_line_end[idx]    = 0;
		hsize                 = strlen(sc_name) + prefix_len +1;
		if(hsize > 255) return -5;
		head[0]               = hsize;
		head[1]               = 0;
		snprintf(head +1,255,"%s%s:",prefix,sc_name);
		name_line_end[idx]    = tmp;
		

		///////////////////////////////////////////////
		//filecheck
		if(!parseFile){
			if(sc_filename && sc_filename < start_body){
				//content is file(skip)
				p_start = p_end;
				continue;
			}
		}
		
		///////////////////////////////////////////////
		//create linked list
		//use ws
		ll_u = WS_Reserve(sp->wrk->ws, 0);
		ll_head_len = strlen(head +1) +1;
		ll_size = ll_head_len + sizeof(char*)+2;
		if(ll_u < ll_size){
#ifdef DEBUG_SYSLOG
		syslog(6,"parse:decodeForm_multipart more ws size");
#endif
			return -1;
		}

		if(!basehead){
			curhead = (char*)sp->wrk->ws->f;
			basehead = curhead;
		}else{
			((char**)curhead)[0] = (char*)sp->wrk->ws->f;
			curhead = (char*)sp->wrk->ws->f;
		}
		++ll_entry_count;
		
		memcpy(curhead,head,ll_head_len);
		curhead +=ll_head_len;
		memset(curhead,0,sizeof(char*)+1);
		++curhead;
		WS_Release(sp->wrk->ws,ll_size);
		///////////////////////////////////////////////
		
		///////////////////////////////////////////////
		//url encode & set header
		p_body_end    = p_end -2;
		start_body    +=4;
		tmp           = p_body_end[0];
		p_body_end[0] = 0;
		//bodyをURLエンコードする
		if(!url_encode_setHdr(sp,start_body,head,&encoded_size)){
			//メモリない
			p_body_end[0] = tmp;
			return -1;
		}
		encoded_size -= prefix_len;
		p_body_end[0] = tmp;

		///////////////////////////////////////////////
		//check last boundary
		if(!p_end) break;
		
		p_start = p_end;
	}
	if(tgHead[0] == 0 && !setParam){
#ifdef DEBUG_SYSLOG
		syslog(6,"parse:decodeForm_multipart head 0 & no set param [OK]");
#endif
		return 1;
	}

	//////////////
	//genarate x-www-form-urlencoded format data
	
	//////////////
	//use ws
	if(tgHead[0] == 0){
		orig_cv_body = cv_body = NULL;
	}else{
		u = WS_Reserve(sp->wrk->ws, 0);
		if(u < encoded_size + 1){
#ifdef DEBUG_SYSLOG
		syslog(6,"parse:decodeForm_multipart more ws size(2)");
#endif

			return -1;
		}
		orig_cv_body = cv_body = (char*)sp->wrk->ws->f;
		WS_Release(sp->wrk->ws,encoded_size+1);
	}
	//////////////
	for(int i=0;i<ll_entry_count;++i){
		if(cv_body){
			hsize = basehead[0] -prefix_len;
			memcpy(cv_body,basehead+1+prefix_len,hsize);
			cv_body    += hsize - 1;
			cv_body[0] ='=';
			++cv_body;

#ifdef DEBUG_SYSLOG
		syslog(6,"GetHdr %s",basehead +1);
#endif
			h_val      = VRT_GetHdr(sp,HDR_REQ,basehead);
		}
		if(!setParam){
			//remove header
			VRT_SetHdr(sp, HDR_REQ, basehead, 0);
		}
		if(cv_body){
			memcpy(cv_body,h_val,strlen(h_val));
			cv_body    +=strlen(h_val);
			cv_body[0] ='&';
			++cv_body;
		}
		basehead   = *(char**)(basehead+strlen(basehead+1)+2);
	}
	if(cv_body){
		orig_cv_body[encoded_size - 1] =0;
	}

	if(tgHead[0] == 0){
#ifdef DEBUG_SYSLOG
		syslog(6,"parse:decodeForm_multipart head 0 [OK]");
#endif
		return 1;
	}
	VRT_SetHdr(sp, HDR_REQ, tgHead, orig_cv_body, vrt_magic_string_end);
	return 1;
}