home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Spezial / SPEZIAL2_97.zip / SPEZIAL2_97.iso / ANWEND / ONLINE / IJB20OS2 / SOURCE / PARSERS.C < prev    next >
C/C++ Source or Header  |  1997-09-16  |  12KB  |  638 lines

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