CProxy/request.c

350 lines
14 KiB
C
Raw Normal View History

2020-01-21 19:48:05 +08:00
#include "request.h"
// 字符串替换
char *replace(char *replace_memory, int *replace_memory_len, const char *src, const int src_len, const char *dest, const int dest_len)
{
if (!replace_memory || !src || !dest)
return replace_memory;
char *p;
int diff;
if (src_len == dest_len) {
for (p = memmem(replace_memory, *replace_memory_len, src, src_len); p; p = memmem(p, *replace_memory_len - (p - replace_memory), src, src_len)) {
memcpy(p, dest, dest_len);
p += dest_len;
}
} else if (src_len < dest_len) {
int before_len;
char *before_end, *new_replace_memory;
diff = dest_len - src_len;
for (p = memmem(replace_memory, *replace_memory_len, src, src_len); p; p = memmem(p, *replace_memory_len - (p - replace_memory), src, src_len)) {
*replace_memory_len += diff;
before_len = p - replace_memory;
new_replace_memory = (char *)realloc(replace_memory, *replace_memory_len + 1);
if (new_replace_memory == NULL) {
free(replace_memory);
return NULL;
}
replace_memory = new_replace_memory;
before_end = replace_memory + before_len;
p = before_end + dest_len;
memmove(p, p - diff, *replace_memory_len - (p - replace_memory));
memcpy(before_end, dest, dest_len);
}
} else if (src_len > dest_len) {
diff = src_len - dest_len;
for (p = memmem(replace_memory, *replace_memory_len, src, src_len); p; p = memmem(p, *replace_memory_len - (p - replace_memory), src, src_len)) {
*replace_memory_len -= diff;
memcpy(p, dest, dest_len);
p += dest_len;
memmove(p, p + diff, *replace_memory_len - (p - replace_memory));
}
}
replace_memory[*replace_memory_len] = '\0';
return replace_memory;
}
/* 正则表达式字符串替换str为可用free释放的指针 */
static char *regrep(char *str, int *str_len, const char *src, char *dest,
int dest_len)
{
if (!str || !src || !dest)
return NULL;
regmatch_t pm[10];
regex_t reg;
char child_num[2] = { '\\', '0' }, *p, *real_dest;
int match_len, real_dest_len, i;
p = str;
regcomp(&reg, src, REG_NEWLINE | REG_ICASE | REG_EXTENDED);
while (regexec(&reg, p, 10, pm, 0) == 0) {
real_dest = (char *)malloc(dest_len);
if (real_dest == NULL) {
regfree(&reg);
free(str);
return NULL;
}
memcpy(real_dest, dest, dest_len);
real_dest_len = dest_len;
//不进行不必要的字符串操作
if (pm[1].rm_so >= 0) {
/* 替换目标字符串中的子表达式 */
for (i = 1; i < 10 && pm[i].rm_so > -1; i++) {
child_num[1] = i + 48;
real_dest =
replace(real_dest, &real_dest_len, child_num, 2,
p + pm[i].rm_so, pm[i].rm_eo - pm[i].rm_so);
if (real_dest == NULL) {
regfree(&reg);
free(str);
return NULL;
}
}
}
match_len = pm[0].rm_eo - pm[0].rm_so;
p += pm[0].rm_so;
//目标字符串不大于匹配字符串则不用分配新内存
if (match_len >= real_dest_len) {
memcpy(p, real_dest, real_dest_len);
if (match_len > real_dest_len)
//strcpy(p + real_dest_len, p + match_len);
memmove(p + real_dest_len, p + match_len,
*str_len - (p + match_len - str));
p += real_dest_len;
*str_len -= match_len - real_dest_len;
} else {
int diff;
char *before_end, *new_str;
diff = real_dest_len - match_len;
*str_len += diff;
new_str = (char *)realloc(str, *str_len + 1);
if (new_str == NULL) {
free(str);
free(real_dest);
regfree(&reg);
return NULL;
}
str = new_str;
before_end = str + pm[0].rm_so;
p = before_end + real_dest_len;
memmove(p, p - diff, *str_len - (p - str) + 1);
memcpy(before_end, real_dest, real_dest_len);
}
free(real_dest);
}
regfree(&reg);
return str;
}
// 删除字符串head中第一位到character处并拼接string, character为空返回原字符串.(string字符替换第一个字符到character处)
char *splice_head(char *head, const char *character, char *string)
{
int len_first = strlen(string);
char *p1 = strstr(head, character);
if (p1 == NULL) {
return head;
}
p1 = p1 + 1;
char new_string[len_first + strlen(p1) + 1];
strcpy(new_string, string);
return strcat(new_string, p1);
}
// 删除字符串head中character到string处, character为空返回原字符串.
char *delete_head(char *head, const char *character, int string)
{
int head_len = strlen(head);
char *p1 = strstr(head, character);
if (p1 == NULL) {
return head;
}
char *p2 = strchr(p1, string);
if (p2 == NULL) {
return head;
}
char tmp[head_len];
strncpy_(tmp, head, head_len-strlen(p1)-1);
strcat(tmp, p2);
return strcpy(head, tmp);
}
int extract_host(char *header, char *host, char *port, char *H)
{
bzero(host, 0);
bzero(port, 0);
bzero(H, 0);
char *_p = strstr(header, "CONNECT"); // 在 CONNECT 方法中解析 隧道主机名称及端口号
if (_p) {
char *_p1 = strchr(_p, ' ');
char *_p2 = strchr(_p1 + 1, ':');
char *_p3 = strchr(_p1 + 1, ' ');
if (_p2) {
char s_port[10];
bzero(s_port, 10);
strncpy(host, _p1 + 1, (int)(_p2 - _p1) - 1);
strncpy(s_port, _p2 + 1, (int)(_p3 - _p2) - 1);
strcpy(port, s_port);
} else {
strncpy(host, _p1 + 1, (int)(_p3 - _p1) - 1);
strcpy(port, "80");
}
strcpy(H, host);
strcat(H, ":");
strcat(H, port);
return 0;
}
char *p = strstr(header, "Host:");
if (!p) {
return -1;
}
char *p1 = strchr(p, '\n');
if (!p1) {
return -1;
}
char *p2 = strchr(p + 5, ':'); // 5是指'Host:'的长度
if (p2 && p2 < p1) {
int p_len = (int)(p1 - p2 - 1);
char s_port[p_len];
strncpy(s_port, p2 + 1, p_len);
s_port[p_len] = '\0';
strcpy(port, s_port);
int h_len = (int)(p2 - p - 5 - 1);
strncpy(host, p + 5 + 1, h_len); // Host:
host[h_len] = '\0';
} else {
int h_len = (int)(p1 - p - 5 - 1 - 1);
strncpy(host, p + 5 + 1, h_len);
host[h_len] = '\0';
strcpy(port, "80");
}
strcpy(H, host);
strcat(H, ":");
strcat(H, port);
return 0;
}
char *request_head(conn *in, conf *configure)
{
const char *method, *path;
size_t method_len, path_len, num_headers;
int minor_version;
struct phr_header headers[32];
num_headers = sizeof(headers) / sizeof(headers[0]);
phr_parse_request(in->header_buffer, strlen(in->header_buffer) - 1, &method, &method_len, &path, &path_len, &minor_version, headers, &num_headers, 0);
char M[method_len+2];
strncpy_(M, method, method_len);
int M_len = strlen(M);
//printf("%s\n", M);
char U[path_len+1];
strncpy_(U, path, path_len);
int U_len = strlen(U);
//printf("%s\n", U);
char V[9];
sprintf(V, "HTTP/1.%.d", minor_version);
int V_len = strlen(V);
//printf("%s\n", V);
char host[path_len];
char port[path_len];
char H[path_len*2];
extract_host(in->header_buffer, host, port, H);
if (strncmp(M, "CONNECT", 7) == 0) {
char https_del_copy[configure->https_del_len];
char *result = NULL;
char *incomplete_head;
int incomplete_head_len;
if (configure->https_port > 0)
remote_port = configure->https_port;
if (configure->https_ip != NULL)
strcpy(remote_host, configure->https_ip);
incomplete_head = (char *)malloc(1024 + 10240);
strcpy(incomplete_head, in->header_buffer);
strcpy(https_del_copy, configure->https_del);
result = strtok(https_del_copy, ",");
while (result != NULL) {
delete_head(incomplete_head, result, '\n');
result = strtok(NULL, ",");
}
strcpy(incomplete_head, splice_head(incomplete_head, "\n", configure->https_first));
incomplete_head_len = strlen(incomplete_head);
incomplete_head = replace(incomplete_head, &incomplete_head_len, "\\r", 2, "\r", 1);
incomplete_head = replace(incomplete_head, &incomplete_head_len, "\\n", 2, "\n", 1);
incomplete_head = replace(incomplete_head, &incomplete_head_len, "\\b", 2, "\b", 1);
incomplete_head = replace(incomplete_head, &incomplete_head_len, "\\v", 2, "\v", 1);
incomplete_head = replace(incomplete_head, &incomplete_head_len, "\\f", 2, "\f", 1);
incomplete_head = replace(incomplete_head, &incomplete_head_len, "\\a", 2, "\a", 1);
incomplete_head = replace(incomplete_head, &incomplete_head_len, "\\t", 2, "\t", 1);
incomplete_head = replace(incomplete_head, &incomplete_head_len, "\\r", 2, "\r", 1);
incomplete_head = replace(incomplete_head, &incomplete_head_len, "\\n", 2, "\n", 1);
incomplete_head = replace(incomplete_head, &incomplete_head_len, "[M]", 3, M, M_len);
incomplete_head = replace(incomplete_head, &incomplete_head_len, "[U]", 3, U, U_len);
incomplete_head = replace(incomplete_head, &incomplete_head_len, "[V]", 3, V, V_len);
incomplete_head = replace(incomplete_head, &incomplete_head_len, "[host]", 6, host, (int)strlen(host));
incomplete_head = replace(incomplete_head, &incomplete_head_len, "[port]", 6, port, (int)strlen(port));
incomplete_head = replace(incomplete_head, &incomplete_head_len, "[H]", 3, H, (int)strlen(H));
if (configure->https_strrep) {
incomplete_head = replace(incomplete_head, &incomplete_head_len, configure->https_strrep_aim, configure->https_strrep_aim_len, configure->https_strrep_obj, configure->https_strrep_obj_len);
}
if (configure->https_regrep) {
incomplete_head = regrep(incomplete_head, &incomplete_head_len, configure->https_regrep_aim, configure->https_regrep_obj, configure->https_regrep_obj_len);
}
//printf("%s", incomplete_head);
memset(in->header_buffer, 0, strlen(in->header_buffer));
strcpy(in->header_buffer, incomplete_head);
in->header_buffer_len = strlen(in->header_buffer);
free(incomplete_head);
} else {
char *incomplete_head;
char https_del_copy[configure->http_del_len];
char *result = NULL;
int incomplete_head_len;
if (configure->http_port > 0)
remote_port = configure->http_port;
if (configure->https_ip != NULL)
strcpy(remote_host, configure->http_ip);
incomplete_head = (char *)malloc(1024 + 10240);
strcpy(incomplete_head, in->header_buffer);
strcpy(https_del_copy, configure->http_del);
result = strtok(https_del_copy, ",");
while (result != NULL) {
delete_head(incomplete_head, result, '\n');
result = strtok(NULL, ",");
}
strcpy(incomplete_head, splice_head(incomplete_head, "\n", configure->http_first));
incomplete_head_len = strlen(incomplete_head);
incomplete_head = replace(incomplete_head, &incomplete_head_len, "\\r", 2, "\r", 1);
incomplete_head = replace(incomplete_head, &incomplete_head_len, "\\n", 2, "\n", 1);
incomplete_head = replace(incomplete_head, &incomplete_head_len, "\\b", 2, "\b", 1);
incomplete_head = replace(incomplete_head, &incomplete_head_len, "\\v", 2, "\v", 1);
incomplete_head = replace(incomplete_head, &incomplete_head_len, "\\f", 2, "\f", 1);
incomplete_head = replace(incomplete_head, &incomplete_head_len, "\\a", 2, "\a", 1);
incomplete_head = replace(incomplete_head, &incomplete_head_len, "\\t", 2, "\t", 1);
incomplete_head = replace(incomplete_head, &incomplete_head_len, "\\r", 2, "\r", 1);
incomplete_head = replace(incomplete_head, &incomplete_head_len, "\\n", 2, "\n", 1);
incomplete_head = replace(incomplete_head, &incomplete_head_len, "[M]", 3, M, M_len);
incomplete_head = replace(incomplete_head, &incomplete_head_len, "[U]", 3, U, U_len);
incomplete_head = replace(incomplete_head, &incomplete_head_len, "[V]", 3, V, V_len);
incomplete_head = replace(incomplete_head, &incomplete_head_len, "[host]", 6, host, (int)strlen(host));
incomplete_head = replace(incomplete_head, &incomplete_head_len, "[port]", 6, port, (int)strlen(port));
incomplete_head = replace(incomplete_head, &incomplete_head_len, "[H]", 3, H, (int)strlen(H));
if (configure->http_strrep) {
incomplete_head = replace(incomplete_head, &incomplete_head_len, configure->http_strrep_aim, configure->http_strrep_aim_len, configure->http_strrep_obj, configure->http_strrep_obj_len);
}
if (configure->http_regrep) {
incomplete_head = regrep(incomplete_head, &incomplete_head_len, configure->http_regrep_aim, configure->http_regrep_obj, configure->http_regrep_obj_len);
}
//printf("%s", incomplete_head);
memset(in->header_buffer, 0, strlen(in->header_buffer));
strcpy(in->header_buffer, incomplete_head);
in->header_buffer_len = strlen(in->header_buffer);
free(incomplete_head);
}
return in->header_buffer;
}