Example #1
0
static int
read_reply(int s, cachemgr_request * req)
{
    char buf[4 * 1024];
    FILE *fp = fdopen(s, "r");
    /* interpretation states */
    enum {
	isStatusLine, isHeaders, isBodyStart, isBody, isForward, isEof, isForwardEof, isSuccess, isError
    } istate = isStatusLine;
    int parse_menu = 0;
    const char *action = req->action;
    const char *statusStr = NULL;
    int status = -1;
    if (0 == strlen(req->action))
	parse_menu = 1;
    else if (0 == strcasecmp(req->action, "menu"))
	parse_menu = 1;
    if (fp == NULL) {
	perror("fdopen");
	return 1;
    }
    if (parse_menu)
	action = "menu";
    /* read reply interpreting one line at a time depending on state */
    while (istate < isEof) {
	if (!fgets(buf, sizeof(buf), fp))
	    istate = istate == isForward ? isForwardEof : isEof;
	switch (istate) {
	case isStatusLine:
	    /* get HTTP status */
	    /* uncomment the following if you want to debug headers */
	    /* fputs("\r\n\r\n", stdout); */
	    status = parse_status_line(buf, &statusStr);
	    istate = status == 200 ? isHeaders : isForward;
	    /* if cache asks for authentication, we have to reset our info */
	    if (status == 401 || status == 407) {
		reset_auth(req);
		status = 403;	/* Forbiden, see comments in case isForward: */
	    }
	    /* this is a way to pass HTTP status to the Web server */
	    if (statusStr)
		printf("Status: %d %s", status, statusStr);	/* statusStr has '\n' */
	    break;
	case isHeaders:
	    /* forward header field */
	    if (!strcmp(buf, "\r\n")) {		/* end of headers */
		fputs("Content-Type: text/html\r\n", stdout);	/* add our type */
		istate = isBodyStart;
	    }
	    if (strncasecmp(buf, "Content-Type:", 13))	/* filter out their type */
		fputs(buf, stdout);
	    break;
	case isBodyStart:
	    printf("<HTML><HEAD><TITLE>CacheMgr@%s: %s</TITLE></HEAD><BODY>\n",
		req->hostname, action);
	    if (parse_menu) {
		printf("<H2><a href=\"%s\">Cache Manager</a> menu for %s:</H2>",
		    menu_url(req, "authenticate"), req->hostname);
		printf("<UL>\n");
	    } else {
		printf("<P><A HREF=\"%s\">%s</A>\n<HR>\n",
		    menu_url(req, "menu"), "Cache Manager menu");
		printf("<PRE>\n");
	    }
	    istate = isBody;
	    /* yes, fall through, we do not want to loose the first line */
	case isBody:
	    /* interpret [and reformat] cache response */
	    if (parse_menu)
		fputs(munge_menu_line(buf, req), stdout);
	    else
		fputs(munge_other_line(buf, req), stdout);
	    break;
	case isForward:
	    /* forward: no modifications allowed */
	    /*
	     * Note: we currently do not know any way to get browser.reply to
	     * 401 to .cgi because web server filters out all auth info. Thus we
	     * disable authentication headers for now.
	     */
	    if (!strncasecmp(buf, "WWW-Authenticate:", 17) || !strncasecmp(buf, "Proxy-Authenticate:", 19));	/* skip */
	    else
		fputs(buf, stdout);
	    break;
	case isEof:
	    /* print trailers */
	    if (parse_menu)
		printf("</UL>\n");
	    else
		printf("</table></PRE>\n");
	    print_trailer();
	    istate = isSuccess;
	    break;
	case isForwardEof:
	    /* indicate that we finished processing an "error" sequence */
	    istate = isError;
	    break;
	default:
	    printf("%s: internal bug: invalid state reached: %d", script_name, istate);
	    istate = isError;
	}
    }
    close(s);
    return 0;
}
Example #2
0
static int
read_reply(int s, cachemgr_request * req)
{
    char buf[4 * 1024];
#ifdef _SQUID_MSWIN_
    int reply;
    char *tmpfile = tempnam(NULL, "tmp0000");
    FILE *fp = fopen(tmpfile, "w+");
#else
    FILE *fp = fdopen(s, "r");
#endif
    /* interpretation states */
    enum {
	isStatusLine, isHeaders, isActions, isBodyStart, isBody, isForward, isEof, isForwardEof, isSuccess, isError
    } istate = isStatusLine;
    int parse_menu = 0;
    const char *action = req->action;
    const char *statusStr = NULL;
    int status = -1;
    if (0 == strlen(req->action))
	parse_menu = 1;
    else if (0 == strcasecmp(req->action, "menu"))
	parse_menu = 1;
    if (fp == NULL) {
#ifdef _SQUID_MSWIN_
	perror(tmpfile);
	xfree(tmpfile);
	closesocket(s);
#else
	perror("fdopen");
	close(s);
#endif
	return 1;
    }
#ifdef _SQUID_MSWIN_
    while ((reply = recv(s, buf, sizeof(buf), 0)) > 0)
	fwrite(buf, 1, reply, fp);
    rewind(fp);
#endif
    if (parse_menu)
	action = "menu";
    /* read reply interpreting one line at a time depending on state */
    while (istate < isEof) {
	if (!fgets(buf, sizeof(buf), fp))
	    istate = istate == isForward ? isForwardEof : isEof;
	switch (istate) {
	case isStatusLine:
	    /* get HTTP status */
	    /* uncomment the following if you want to debug headers */
	    /* fputs("\r\n\r\n", stdout); */
	    status = parse_status_line(buf, &statusStr);
	    istate = status == 200 ? isHeaders : isForward;
	    /* if cache asks for authentication, we have to reset our info */
	    if (status == 401 || status == 407) {
		reset_auth(req);
		status = 403;	/* Forbiden, see comments in case isForward: */
	    }
	    /* this is a way to pass HTTP status to the Web server */
	    if (statusStr)
		printf("Status: %d %s", status, statusStr);	/* statusStr has '\n' */
	    break;
	case isHeaders:
	    /* forward header field */
	    if (!strcmp(buf, "\r\n")) {		/* end of headers */
		fputs("Content-Type: text/html\r\n", stdout);	/* add our type */
		istate = isBodyStart;
	    }
	    if (strncasecmp(buf, "Content-Type:", 13))	/* filter out their type */
		fputs(buf, stdout);
	    break;
	case isBodyStart:
	    printf("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">\n");
	    printf("<HTML><HEAD><TITLE>CacheMgr@%s: %s</TITLE>\n",
		req->hostname, action);
	    printf("<STYLE type=\"text/css\"><!--BODY{background-color:#ffffff;font-family:verdana,sans-serif}TABLE{background-color:#333333;border:0pt;padding:0pt}TH,TD{background-color:#ffffff;white-space:nowrap}--></STYLE>\n");
	    printf("</HEAD><BODY>\n");
	    if (parse_menu) {
		printf("<H2><a href=\"%s\">Cache Manager</a> menu for %s:</H2>",
		    menu_url(req, "authenticate"), req->hostname);
	    } else {
		printf("<P><A HREF=\"%s\">%s</A>\n",
		    menu_url(req, "menu"), "Cache Manager menu");
	    }
	    istate = isActions;
	    /* yes, fall through, we do not want to loose the first line */
	case isActions:
	    if (strncmp(buf, "action:", 7) == 0) {
		fputs(" ", stdout);
		fputs(munge_action_line(buf + 7, req), stdout);
		break;
	    }
	    if (parse_menu) {
		printf("<UL>\n");
	    } else {
		printf("<HR noshade size=\"1px\">\n");
		printf("<PRE>\n");
	    }
	    istate = isBody;
	    /* yes, fall through, we do not want to loose the first line */
	case isBody:
	    /* interpret [and reformat] cache response */
	    if (parse_menu)
		fputs(munge_menu_line(buf, req), stdout);
	    else
		fputs(munge_other_line(buf, req), stdout);
	    break;
	case isForward:
	    /* forward: no modifications allowed */
	    /*
	     * Note: we currently do not know any way to get browser.reply to
	     * 401 to .cgi because web server filters out all auth info. Thus we
	     * disable authentication headers for now.
	     */
	    if (!strncasecmp(buf, "WWW-Authenticate:", 17) || !strncasecmp(buf, "Proxy-Authenticate:", 19));	/* skip */
	    else
		fputs(buf, stdout);
	    break;
	case isEof:
	    /* print trailers */
	    if (parse_menu)
		printf("</UL>\n");
	    else
		printf("</table></PRE>\n");
	    print_trailer();
	    istate = isSuccess;
	    break;
	case isForwardEof:
	    /* indicate that we finished processing an "error" sequence */
	    istate = isError;
	    break;
	default:
	    printf("%s: internal bug: invalid state reached: %d", script_name, istate);
	    istate = isError;
	}
    }
#ifdef _SQUID_MSWIN_
    fclose(fp);
    remove(tmpfile);
    xfree(tmpfile);
    closesocket(s);
#else
    close(s);
#endif
    return 0;
}