static const char * munge_menu_line(const char *buf, cachemgr_request * req) { char *x; const char *a; const char *d; const char *p; char *a_url; char *buf_copy; static char html[2 * 1024]; if (strlen(buf) < 1) return buf; if (*buf != ' ') return buf; buf_copy = x = xstrdup(buf); a = xstrtok(&x, '\t'); d = xstrtok(&x, '\t'); p = xstrtok(&x, '\t'); a_url = xstrdup(menu_url(req, a)); /* no reason to give a url for a disabled action */ if (!strcmp(p, "disabled")) snprintf(html, sizeof(html), "<LI type=\"circle\">%s (disabled)<A HREF=\"%s\">.</A>\n", d, a_url); else /* disable a hidden action (requires a password, but password is not in squid.conf) */ if (!strcmp(p, "hidden")) snprintf(html, sizeof(html), "<LI type=\"circle\">%s (hidden)<A HREF=\"%s\">.</A>\n", d, a_url); else /* disable link if authentication is required and we have no password */ if (!strcmp(p, "protected") && !req->passwd) snprintf(html, sizeof(html), "<LI type=\"circle\">%s (requires <a href=\"%s\">authentication</a>)<A HREF=\"%s\">.</A>\n", d, menu_url(req, "authenticate"), a_url); else /* highlight protected but probably available entries */ if (!strcmp(p, "protected")) snprintf(html, sizeof(html), "<LI type=\"square\"><A HREF=\"%s\"><font color=\"#FF0000\">%s</font></A>\n", a_url, d); /* public entry or unknown type of protection */ else snprintf(html, sizeof(html), "<LI type=\"disk\"><A HREF=\"%s\">%s</A>\n", a_url, d); xfree(a_url); xfree(buf_copy); return html; }
static const char * munge_action_line(const char *_buf, cachemgr_request * req) { static char html[2 * 1024]; char *buf = xstrdup(_buf); char *x = buf; const char *action, *description; char *p; if ((p = strchr(x, '\n'))) *p = '\0'; action = xstrtok(&x, '\t'); description = xstrtok(&x, '\t'); if (!description) description = action; if (!action) return ""; snprintf(html, sizeof(html), " <a href=\"%s\">%s</a>", menu_url(req, action), description); return html; }
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; }
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; }