parsers.c
上传用户:qunlip
上传日期:2007-01-04
资源大小:203k
文件大小:12k
源码类别:

代理服务器

开发平台:

Visual C++

  1. char *parsers_rcs = "$Id: parsers.c,v 1.26 1998/10/23 01:54:12 ACJC Exp $";
  2. /* Written and copyright 1997 Anonymous Coders and Junkbusters Corporation.
  3.  * Distributed under the GNU General Public License; see the README file.
  4.  * This code comes with NO WARRANTY. http://www.junkbusters.com/ht/en/gpl.html
  5.  */
  6. #include <stdio.h>
  7. #include <sys/types.h>
  8. #include <stdlib.h>
  9. #include <ctype.h>
  10. #include <string.h>
  11. #ifndef _WIN32
  12. #include <unistd.h>
  13. #endif
  14. #ifdef REGEX
  15. #include <gnu_regex.h>
  16. #endif
  17. #include "jcc.h"
  18. struct parsers client_patterns[] = {
  19. { "referer:", /* sic */  8, client_referrer },
  20. { "user-agent:", 11, client_uagent },
  21. { "ua-",  3, client_ua },
  22. { "from:",  5, client_from },
  23. { "cookie:",  7, client_send_cookie },
  24. { "x-forwarded-for:", 16, client_x_forwarded },
  25. { "proxy-connection:", 17, crumble },
  26. /* { "if-modified-since:", 18, crumble }, */
  27. { NULL,  0, NULL }
  28. };
  29. struct interceptors intercept_patterns[] = {
  30. { "show-proxy-args", 14, show_proxy_args },
  31. { "ij-blocked-url", 14, ij_blocked_url },
  32. { "ij-untrusted-url", 14, ij_untrusted_url },
  33. { NULL,  0, NULL }
  34. };
  35. struct parsers server_patterns[] = {
  36. { "set-cookie:", 11, server_set_cookie },
  37. { "connection:", 11, crumble },
  38. { NULL,  0, NULL }
  39. };
  40. void (*add_client_headers[])() = {
  41. client_cookie_adder,
  42. client_x_forwarded_adder,
  43. client_xtra_adder,
  44. NULL
  45. };
  46. void (*add_server_headers[])() = {
  47. NULL
  48. };
  49. struct parsers *
  50. match(char *buf, struct parsers *pats)
  51. {
  52. struct parsers *v;
  53. if(buf == NULL) {
  54. /* hit me */
  55. fprintf(logfp, "bingo!n");
  56. return(NULL);
  57. }
  58. for(v = pats; v->str ; v++) {
  59. if(strncmpic(buf, v->str, v->len) == 0) {
  60. return(v);
  61. }
  62. }
  63. return(NULL);
  64. }
  65. int
  66. flush_socket(int fd, struct client_state *csp)
  67. {
  68. struct iob *iob = csp->iob;
  69. int n = iob->eod - iob->cur;
  70. if(n <= 0) return(0);
  71. n = write_socket(fd, iob->cur, n);
  72. iob->eod = iob->cur = iob->buf;
  73. return(n);
  74. }
  75. int
  76. add_to_iob(struct client_state *csp, char *buf, int n)
  77. {
  78. struct iob *iob = csp->iob;
  79. int have, need;
  80. char *p;
  81. have = iob->eod - iob->cur;
  82. if(n <= 0) return(have);
  83. need = have + n;
  84. if((p = malloc(need + 1)) == NULL) {
  85. fprintf(logfp, "%s: malloc() iob failedn", prog);
  86. fperror(logfp, "");
  87. return(-1);
  88. }
  89. if(have) {
  90. /* there is something in the buffer - save it */
  91. memcpy(p, iob->cur, have);
  92. /* replace the buffer with the new space */
  93. freez(iob->buf);
  94. iob->buf = p;
  95. /* point to the end of the data */
  96. p += have;
  97. } else {
  98. /* the buffer is empty, free it and reinitialize */
  99. freez(iob->buf);
  100. iob->buf = p;
  101. }
  102. /* copy the new data into the iob buffer */
  103. memcpy(p, buf, n);
  104. /* point to the end of the data */
  105.  p +=   n ;
  106. /* null terminate == cheap insurance */
  107. *p  = '';
  108. /* set the pointers to the new values */
  109. iob->cur = iob->buf;
  110. iob->eod = p;
  111. return(need);
  112. }
  113. /* this (odd) routine will parse the csp->iob and return one of the following:
  114.  *
  115.  * 1) a pointer to a dynamically allocated string that contains a header line
  116.  * 2) NULL  indicating that the end of the header was reached
  117.  * 3) ""    indicating that the end of the iob was reached before finding
  118.  *          a complete header line.
  119.  */
  120. char *
  121. get_header(struct client_state *csp)
  122. {
  123. struct iob *iob = csp->iob;
  124. char *p, *q, *ret;
  125. if((iob->cur == NULL)
  126. || ((p = strchr(iob->cur, 'n')) == NULL)) {
  127. return(""); /* couldn't find a complete header */
  128. }
  129. *p = '';
  130. ret = strdup(iob->cur);
  131. iob->cur = p+1;
  132. if((q = strchr(ret, 'r'))) *q = '';
  133. /* is this a blank linke (i.e. the end of the header) ? */
  134. if(*ret == '') {
  135. freez(ret);
  136. return(NULL);
  137. }
  138. return(ret);
  139. }
  140. /* h = pointer to list 'dummy' header
  141.  * s = string to add to the list
  142.  */
  143. void
  144. enlist(struct list *h, char *s)
  145. {
  146. struct list *n = (struct list *)malloc(sizeof(*n));
  147. struct list *l;
  148. if(n) {
  149. n->str  = strdup(s);
  150. n->next = NULL;
  151. if((l = h->last)) {
  152. l->next = n;
  153. } else {
  154. h->next = n;
  155. }
  156. h->last = n;
  157. }
  158. }
  159. void
  160. destroy_list(struct list *h)
  161. {
  162. struct list *p, *n;
  163. for(p = h->next; p ; p = n) {
  164. n = p->next;
  165. freez(p->str);
  166. freez(p);
  167. }
  168. memset(h, '', sizeof(*h));
  169. }
  170. char *
  171. list_to_text(struct list *h)
  172. {
  173. struct list *p;
  174. char *ret = NULL;
  175. char *s;
  176. int size;
  177. size = 0;
  178. for(p = h->next; p ; p = p->next) {
  179. if(p->str) {
  180. size += strlen(p->str) + 2;
  181. }
  182. }
  183. if((ret = malloc(size + 1)) == NULL) {
  184. return(NULL);
  185. }
  186. ret[size] = '';
  187. s = ret;
  188. for(p = h->next; p ; p = p->next) {
  189. if(p->str) {
  190. strcpy(s, p->str);
  191. s += strlen(s);
  192. *s++ = 'r'; *s++ = 'n';
  193. }
  194. }
  195. return(ret);
  196. }
  197. /* sed(): add, delete or modify lines in the HTTP header streams.
  198.  * on entry, it receives a linked list of headers space that was
  199.  * allocated dynamically (both the list nodes and the header contents).
  200.  *
  201.  * it returns a single pointer to a fully formed header.
  202.  *
  203.  * as a side effect it frees the space used by the original header lines.
  204.  *
  205.  */
  206. char *
  207. sed(pats, more_headers, csp)
  208. struct parsers pats[];
  209. int (*more_headers[])();
  210. struct client_state *csp;
  211. {
  212. struct list *p;
  213. struct parsers *v;
  214. char *hdr;
  215. int (**f)();
  216. for(p = csp->headers->next; p ; p = p->next) {
  217. if(DEBUG(HDR)) fprintf(logfp, "scan: %s", p->str);
  218. if((v = match(p->str, pats))) {
  219. hdr = v->parser(v, p->str, csp);
  220. freez(p->str);
  221. p->str = hdr;
  222. }
  223. if(DEBUG(HDR)) fprintf(logfp, "n");
  224. }
  225. /* place any additional headers on the csp->headers list */
  226. for(f = more_headers; *f ; f++) {
  227. (*f)(csp);
  228. }
  229. /* add the blank line at the end of the header */
  230. enlist(csp->headers, "");
  231. hdr = list_to_text(csp->headers);
  232. return(hdr);
  233. }
  234. void
  235. free_http_request(struct http_request *http)
  236. {
  237. freez(http->cmd);
  238. freez(http->gpc);
  239. freez(http->host);
  240. freez(http->hostport);
  241. freez(http->path);
  242. freez(http->ver);
  243. }
  244. /* parse out the host and port from the URL */
  245. void
  246. parse_http_request(char *req, struct http_request *http, struct client_state *csp)
  247. {
  248. char *buf, *v[10], *url, *p;
  249. int n;
  250. memset(http, '', sizeof(*http));
  251. http->cmd = strdup(req);
  252. buf = strdup(req);
  253. n = ssplit(buf, " rn", v, SZ(v), 1, 1);
  254. if(n == 3) {
  255. /* this could be a CONNECT request */
  256. if(strcmpic(v[0], "connect") == 0) {
  257. http->ssl      = 1;
  258. http->gpc      = strdup(v[0]);
  259. http->hostport = strdup(v[1]);
  260. http->ver      = strdup(v[2]);
  261. }
  262. /* or it could be a GET or a POST */
  263. if((strcmpic(v[0], "get")  == 0)
  264. || (strcmpic(v[0], "head") == 0)
  265. || (strcmpic(v[0], "post") == 0)) {
  266. http->ssl      = 0;
  267. http->gpc      = strdup(v[0]);
  268. url            =        v[1] ;
  269. http->ver      = strdup(v[2]);
  270. if(strncmpic(url, "http://",  7) == 0) {
  271. url += 7;
  272. } else if(strncmpic(url, "https://", 8) == 0) {
  273. url += 8;
  274. } else {
  275. url = NULL;
  276. }
  277. if(url && (p = strchr(url, '/'))) {
  278. http->path = strdup(p);
  279. *p = '';
  280. http->hostport = strdup(url);
  281. }
  282. }
  283. }
  284. freez(buf);
  285. if(http->hostport == NULL) {
  286. free_http_request(http);
  287. return;
  288. }
  289. buf = strdup(http->hostport);
  290. n = ssplit(buf, ":", v, SZ(v), 1, 1);
  291. if(n == 1) {
  292. http->host = strdup(v[0]);
  293. http->port = 80;
  294. }
  295. if(n == 2) {
  296. http->host = strdup(v[0]);
  297. http->port = atoi(v[1]);
  298. }
  299. freez(buf);
  300. if(http->host == NULL) {
  301. free_http_request(http);
  302. }
  303. if(http->path == NULL) {
  304. http->path = strdup("");
  305. }
  306. }
  307. /* here begins the family of parser functions that reformat header lines */
  308. char *crumble(struct parsers *v, char *s, struct client_state *csp)
  309. {
  310. if(DEBUG(HDR)) fprintf(logfp, " crunch!");
  311. return(NULL);
  312. }
  313. char *client_referrer(struct parsers *v, char *s, struct client_state *csp)
  314. {
  315. csp->referrer = strdup(s);
  316. if(referrer == NULL) {
  317. if(DEBUG(HDR)) fprintf(logfp, " crunch!");
  318. return(NULL);
  319. }
  320. if(*referrer == '.') {
  321. return(strdup(s));
  322. }
  323. if(*referrer == '@') {
  324. if(csp->send_user_cookie) {
  325. return(strdup(s));
  326. } else {
  327. if(DEBUG(HDR)) fprintf(logfp, " crunch!");
  328. return(NULL);
  329. }
  330. }
  331. if(DEBUG(HDR)) fprintf(logfp, " modified");
  332. s = strsav(NULL, "Referer: ");
  333. s = strsav(s,     referrer  );
  334. return(s);
  335. }
  336. char *client_uagent(struct parsers *v, char *s, struct client_state *csp)
  337. {
  338. if(uagent == NULL) {
  339. if(DEBUG(HDR)) fprintf(logfp, " default");
  340. return(strdup(DEFAULT_USER_AGENT));
  341. }
  342. if(*uagent == '.') {
  343. return(strdup(s));
  344. }
  345. if(*uagent == '@') {
  346. if(csp->send_user_cookie) {
  347. return(strdup(s));
  348. } else {
  349. if(DEBUG(HDR)) fprintf(logfp, " default");
  350. return(strdup(DEFAULT_USER_AGENT));
  351. }
  352. }
  353. if(DEBUG(HDR)) fprintf(logfp, " modified");
  354. s = strsav(NULL, "User-Agent: ");
  355. s = strsav(s,     uagent   );
  356. return(s);
  357. }
  358. char *client_ua(struct parsers *v, char *s, struct client_state *csp)
  359. {
  360. if(uagent == NULL) {
  361. if(DEBUG(HDR)) fprintf(logfp, " crunch!");
  362. return(NULL);
  363. }
  364. if(*uagent == '.') {
  365. return(strdup(s));
  366. }
  367. if(*uagent == '@') {
  368. if(csp->send_user_cookie) {
  369. return(strdup(s));
  370. } else {
  371. if(DEBUG(HDR)) fprintf(logfp, " crunch!");
  372. return(NULL);
  373. }
  374. }
  375. if(DEBUG(HDR)) fprintf(logfp, " crunch!");
  376. return(NULL);
  377. }
  378. char *client_from(struct parsers *v, char *s, struct client_state *csp)
  379. {
  380. /* if not set, zap it */
  381. if(from == NULL) {
  382. if(DEBUG(HDR)) fprintf(logfp, " crunch!");
  383. return(NULL);
  384. }
  385. if(*from == '.') {
  386. return(strdup(s));
  387. }
  388. if(DEBUG(HDR)) fprintf(logfp, " modified");
  389. s = strsav(NULL, "From: ");
  390. s = strsav(s,     from   );
  391. return(s);
  392. }
  393. char *client_send_cookie(struct parsers *v, char *s, struct client_state *csp)
  394. {
  395. if(csp->send_user_cookie) {
  396. enlist(csp->cookie_list, s + v->len + 1);
  397. } else {
  398. if(DEBUG(HDR)) fprintf(logfp, " crunch!");
  399. }
  400. /* always return NULL here.  the cookie header will be sent
  401.  * at the end of the header.
  402.  */
  403. return(NULL);
  404. }
  405. char *client_x_forwarded(struct parsers *v, char *s, struct client_state *csp)
  406. {
  407. if(add_forwarded) {
  408. csp->x_forwarded = strdup(s);
  409. }
  410. /* always return NULL, since this information
  411.  * will be sent at the end of the header.
  412.  */
  413. return(NULL);
  414. }
  415. /* the following functions add headers directly to the header list */
  416. void client_cookie_adder(struct client_state *csp)
  417. {
  418. struct list *l;
  419. char *tmp = NULL;
  420. char *e;
  421. for(l = csp->cookie_list->next; l ; l = l->next) {
  422. if(tmp) {
  423. tmp = strsav(tmp, "; ");
  424. }
  425. tmp = strsav(tmp, l->str);
  426. }
  427. for(l = wafer_list->next;  l ; l = l->next) {
  428. if(tmp) {
  429. tmp = strsav(tmp, "; ");
  430. }
  431. if((e = url_encode(cookie_code_map, l->str))) {
  432. tmp = strsav(tmp, e);
  433. freez(e);
  434. }
  435. }
  436. if(tmp) {
  437. char *ret;
  438. ret = strdup("Cookie: ");
  439. ret = strsav(ret, tmp);
  440. if(DEBUG(HDR)) fprintf(logfp, "addh: %srn", ret);
  441. enlist(csp->headers, ret);
  442. freez(tmp);
  443. freez(ret);
  444. }
  445. }
  446. void client_xtra_adder(struct client_state *csp)
  447. {
  448. struct list *l;
  449. for(l = xtra_list->next; l ; l = l->next) {
  450. if(DEBUG(HDR)) fprintf(logfp, "addh: %srn", l->str);
  451. enlist(csp->headers, l->str);
  452. }
  453. }
  454. void client_x_forwarded_adder(struct client_state *csp)
  455. {
  456. char *p = NULL;
  457. if(add_forwarded == 0) return;
  458. if(csp->x_forwarded) {
  459. p = strsav(p, csp->x_forwarded);
  460. p = strsav(p, ", ");
  461. p = strsav(p, csp->ip_addr_str);
  462. } else {
  463. p = strsav(p, "X-Forwarded-For: ");
  464. p = strsav(p, csp->ip_addr_str);
  465. }
  466. if(DEBUG(HDR)) fprintf(logfp, "addh: %srn", p);
  467. enlist(csp->headers, p);
  468. }
  469. char *server_set_cookie(struct parsers *v, char *s, struct client_state *csp)
  470. {
  471. if(jar) fprintf(jar, "%st%sn", csp->http->host, (s + v->len + 1));
  472. if(csp->accept_server_cookie == 0) return(crumble(v, s, csp));
  473. return(strdup(s));
  474. }
  475. /* case insensitive string comparison */
  476. int strcmpic(char *s1, char *s2)
  477. {
  478. while(*s1 && *s2) {
  479. if((        *s1  !=         *s2)
  480. && (tolower(*s1) != tolower(*s2))) {
  481. break;
  482. }
  483. s1++, s2++;
  484. }
  485. return(tolower(*s1) - tolower(*s2));
  486. }
  487. int strncmpic(char *s1, char *s2, size_t n)
  488. {
  489. if(n <= 0) return(0);
  490. while(*s1 && *s2) {
  491. if((        *s1  !=         *s2)
  492. && (tolower(*s1) != tolower(*s2))) {
  493. break;
  494. }
  495. if(--n <= 0) break;
  496. s1++, s2++;
  497. }
  498. return(tolower(*s1) - tolower(*s2));
  499. }