示例#1
0
/* figure out content type from file extension */
static void
gopher_mime_content(MemBuf * mb, const char *name, const char *def_ctype)
{
    char *ctype = mimeGetContentType(name);
    char *cenc = mimeGetContentEncoding(name);
    if (cenc)
	memBufPrintf(mb, "Content-Encoding: %s\r\n", cenc);
    memBufPrintf(mb, "Content-Type: %s\r\n",
	ctype ? ctype : def_ctype);
}
示例#2
0
static void
getICAPRespModString(MemBuf * mb, int o1, int o2, int o3,
    const char *client_addr, IcapStateData * icap, const icap_service * service)
{
    memBufPrintf(mb, "RESPMOD %s ICAP/1.0\r\nEncapsulated:", service->uri);
    if (o1 >= 0)
	memBufPrintf(mb, " req-hdr=%1d", o1);
    if (o2 >= 0)
	memBufPrintf(mb, ", res-hdr=%1d", o2);
    if (o3 >= 0)
	memBufPrintf(mb, ", res-body=%1d", o3);
    else
	memBufPrintf(mb, ", null-body=%1d", -o3);

    memBufPrintf(mb, crlf);
    if (Config.icapcfg.send_client_ip || service->flags.need_x_client_ip) {
	memBufPrintf(mb, "X-Client-IP: %s\r\n", client_addr);
    }
    if ((Config.icapcfg.send_auth_user
	    || service->flags.need_x_authenticated_user)
	&& (icap->request->auth_user_request != NULL)) {
	icapAddAuthUserHeader(mb, icap->request->auth_user_request);
    }
#if NOT_YET_FINISHED
    if (Config.icapcfg.trailers) {
	memBufPrintf(mb, "X-TE: trailers\r\n");
    }
#endif
    if (service->flags.allow_204)
	memBufPrintf(mb, "Allow: 204\r\n");
}
示例#3
0
文件: ident.c 项目: selecli/squid
static void
identConnectDone(int fd, int status, void *data)
{
	IdentStateData *state = data;
	IdentClient *c;
	MemBuf mb;
	if (status != COMM_OK)
	{
		/* Failed to connect */
		comm_close(fd);
		return;
	}
	/*
	 * see if our clients still care
	 */
	for (c = state->clients; c; c = c->next)
	{
		if (cbdataValid(c->callback_data))
			break;
	}
	if (c == NULL)
	{
		/* no clients care */
		comm_close(fd);
		return;
	}
	memBufDefInit(&mb);
	memBufPrintf(&mb, "%d, %d\r\n",
				 ntohs(state->my_peer.sin_port),
				 ntohs(state->me.sin_port));
	comm_write_mbuf(fd, mb, NULL, state);
	commSetSelect(fd, COMM_SELECT_READ, identReadReply, state, 0);
	commSetTimeout(fd, Config.Timeout.ident, identTimeout, state);
}
wordlist *
aclDumpExternal(void *data)
{
    external_acl_data *acl = data;
    wordlist *result = NULL;
    wordlist *arg;
    MemBuf mb;
    memBufDefInit(&mb);
    memBufPrintf(&mb, "%s", acl->def->name);
    for (arg = acl->arguments; arg; arg = arg->next) {
	memBufPrintf(&mb, " %s", arg->key);
    }
    wordlistAdd(&result, mb.buf);
    memBufClean(&mb);
    return result;
}
示例#5
0
static void
sslProxyConnected(int fd, void *data)
{
    SslStateData *sslState = data;
    MemBuf mb;
    HttpHeader hdr_out;
    Packer p;
    http_state_flags flags;
    debug(26, 3) ("sslProxyConnected: FD %d sslState=%p\n", fd, sslState);
    memset(&flags, '\0', sizeof(flags));
    memBufDefInit(&mb);
    memBufPrintf(&mb, "CONNECT %s HTTP/1.0\r\n", sslState->url);
    httpBuildRequestHeader(sslState->request,
	sslState->request,
	NULL,			/* StoreEntry */
	&hdr_out,
	sslState->client.fd,
	flags);			/* flags */
    packerToMemInit(&p, &mb);
    httpHeaderPackInto(&hdr_out, &p);
    httpHeaderClean(&hdr_out);
    packerClean(&p);
    memBufAppend(&mb, "\r\n", 2);
    xstrncpy(sslState->client.buf, mb.buf, SQUID_TCP_SO_RCVBUF);
    debug(26, 3) ("sslProxyConnected: Sending {%s}\n", sslState->client.buf);
    sslState->client.len = mb.size;
    memBufClean(&mb);
    commSetTimeout(sslState->server.fd,
	Config.Timeout.read,
	sslTimeout,
	sslState);
    sslSetSelect(sslState);
}
示例#6
0
void
storeLog(int tag, const StoreEntry * e)
{
    MemBuf mb;
    MemObject *mem = e->mem_obj;
    HttpReply *reply;
    if (storelog_fd < 0)
        return;
    if (mem == NULL)
        return;
    if (EBIT_TEST(e->flags, ENTRY_DONT_LOG))
        return;
    if (mem->log_url == NULL) {
        debug(20, 1) ("storeLog: NULL log_url for %s\n", mem->url);
        storeMemObjectDump(mem);
        mem->log_url = xstrdup(mem->url);
    }
    memBufDefInit(&mb);
    reply = mem->reply;
    memBufPrintf(&mb, "%9d.%03d %-7s %08X %4d %9d %9d %9d %s %d/%d %s %s\n",
                 (int) current_time.tv_sec,
                 (int) current_time.tv_usec / 1000,
                 storeLogTags[tag],
                 e->swap_file_number,
                 reply->sline.status,
                 (int) reply->date,
                 (int) reply->last_modified,
                 (int) reply->expires,
                 strLen(reply->content_type) ? strBuf(reply->content_type) : "unknown",
                 reply->content_length,
                 (int) (mem->inmem_hi - mem->reply->hdr_sz),
                 RequestMethodStr[mem->method],
                 mem->log_url);
    file_write_mbuf(storelog_fd, -1, mb, NULL, NULL);
}
示例#7
0
void
refreshCheckSubmit(StoreEntry * entry, REFRESHCHECK * callback, void *callback_data)
{
    MemBuf buf;
    const char *key;
    refresh_check_helper *def = Config.Program.refresh_check;
    refreshCheckState *state;
    dlink_node *node;
    refreshCheckState *oldstate = NULL;

    if (!def) {
	callback(callback_data, 0, NULL);
	return;
    }
    key = makeRefreshCheckRequest(entry, def->format);
    if (!key) {
	callback(callback_data, 0, NULL);
	return;
    }
    debug(84, 2) ("refreshCheckSubmit: for '%s'\n", key);

    /* Check for a pending lookup to hook into */
    for (node = def->queue.head; node; node = node->next) {
	refreshCheckState *oldstatetmp = node->data;
	if (entry == oldstatetmp->entry) {
	    oldstate = oldstatetmp;
	    break;
	}
    }

    state = cbdataAlloc(refreshCheckState);
    state->def = def;
    cbdataLock(state->def);
    state->entry = entry;
    storeLockObject(entry);
    state->callback = callback;
    state->callback_data = callback_data;
    cbdataLock(state->callback_data);
    if (oldstate) {
	/* Hook into pending lookup */
	state->queue = oldstate->queue;
	oldstate->queue = state;
    } else {
	/* No pending lookup found. Sumbit to helper */
	/* Check for queue overload */
	if (refreshCheckOverload(def)) {
	    debug(84, 1) ("refreshCheckSubmit: queue overload\n");
	    cbdataFree(state);
	    callback(callback_data, 0, "Overload");
	    return;
	}
	/* Send it off to the helper */
	memBufDefInit(&buf);
	memBufPrintf(&buf, "%s\n", key);
	helperSubmit(def->helper, buf.buf, refreshCheckHandleReply, state);
	dlinkAdd(state, &state->list, &def->queue);
	memBufClean(&buf);
    }
}
示例#8
0
const char *
storeKeyText(const unsigned char *key)
{
    static MemBuf mb = MemBufNULL;
    int i;
    memBufReset(&mb);
    for (i = 0; i < MD5_DIGEST_CHARS; i++)
	memBufPrintf(&mb, "%02X", *(key + i));
    return mb.buf;
}
示例#9
0
static MemBuf
errorBuildContent(ErrorState * err)
{
    MemBuf content;
    const char *m;
    const char *p;
    const char *t;
    assert(err != NULL);
    assert(err->page_id > ERR_NONE && err->page_id < error_page_count);
    memBufDefInit(&content);
    m = error_text[err->page_id];
    assert(m);
    while ((p = strchr(m, '%'))) {
	memBufAppend(&content, m, p - m);	/* copy */
	t = errorConvert(*++p, err);	/* convert */
	memBufPrintf(&content, "%s", t);	/* copy */
	m = p + 1;		/* advance */
    }
    if (*m)
	memBufPrintf(&content, "%s", m);	/* copy tail */
    assert(content.size == strlen(content.buf));
    return content;
}
示例#10
0
const char *
mimeGetIconURL(const char *fn)
{
    static MemBuf mb = MemBufNULL;
    char *icon = mimeGetIcon(fn);
    if (icon == NULL)
	return null_string;
    if (Config.icons.use_short_names) {
	memBufReset(&mb);
	memBufPrintf(&mb, "/squid-internal-static/icons/%s", icon);
	return mb.buf;
    } else {
	return internalLocalUri("/squid-internal-static/icons/", icon);
    }
}
示例#11
0
/* create MIME Header for Gopher Data */
static void
gopherMimeCreate(GopherStateData * gopherState)
{
    MemBuf mb;

    memBufDefInit(&mb);

    memBufPrintf(&mb,
	"HTTP/1.0 200 OK Gatewaying\r\n"
	"Server: Squid/%s\r\n"
	"Date: %s\r\n"
	"MIME-version: 1.0\r\n",
	version_string, mkrfc1123(squid_curtime));

    switch (gopherState->type_id) {

    case GOPHER_DIRECTORY:
    case GOPHER_INDEX:
    case GOPHER_HTML:
    case GOPHER_WWW:
    case GOPHER_CSO:
	memBufPrintf(&mb, "Content-Type: text/html\r\n");
	break;
    case GOPHER_GIF:
    case GOPHER_IMAGE:
    case GOPHER_PLUS_IMAGE:
	memBufPrintf(&mb, "Content-Type: image/gif\r\n");
	break;
    case GOPHER_SOUND:
    case GOPHER_PLUS_SOUND:
	memBufPrintf(&mb, "Content-Type: audio/basic\r\n");
	break;
    case GOPHER_PLUS_MOVIE:
	memBufPrintf(&mb, "Content-Type: video/mpeg\r\n");
	break;
    case GOPHER_MACBINHEX:
    case GOPHER_DOSBIN:
    case GOPHER_UUENCODED:
    case GOPHER_BIN:
	/* Rightnow We have no idea what it is. */
	gopher_mime_content(&mb, gopherState->request, def_gopher_bin);
	break;
    case GOPHER_FILE:
    default:
	gopher_mime_content(&mb, gopherState->request, def_gopher_text);
	break;
    }
    memBufPrintf(&mb, "\r\n");
    EBIT_CLR(gopherState->entry->flags, ENTRY_FWD_HDR_WAIT);
    storeAppend(gopherState->entry, mb.buf, mb.size);
    memBufClean(&mb);
}
示例#12
0
MemBuf
httpPacked304Reply(const HttpReply * rep)
{
    static const http_hdr_type ImsEntries[] =
    {HDR_DATE, HDR_CONTENT_TYPE, HDR_EXPIRES, HDR_LAST_MODIFIED, /* eof */ HDR_OTHER};
    int t;
    MemBuf mb;
    Packer p;
    HttpHeaderEntry *e;
    assert(rep);

    memBufDefInit(&mb);
    packerToMemInit(&p, &mb);
    memBufPrintf(&mb, "%s", "HTTP/1.0 304 Not Modified\r\n");
    for (t = 0; ImsEntries[t] != HDR_OTHER; ++t)
	if ((e = httpHeaderFindEntry(&rep->header, ImsEntries[t])))
	    httpHeaderEntryPackInto(e, &p);
    memBufAppend(&mb, "\r\n", 2);
    packerClean(&p);
    return mb;
}
static void  errorTryLoadText(MemBuf * text, char *path)
{
	int fd;
	struct stat sb;
//	char *text = NULL;

	//snprintf(path, sizeof(path), "%s/%s", dir, page_name);
#ifdef _SQUID_MSWIN_
	fd = open(path, O_RDONLY | O_BINARY);
#else
	fd = open(path, O_RDONLY | O_TEXT);
#endif
	if (fd < 0 || fstat(fd, &sb) < 0)
	{
		debug(115, 0) ("mod_customized_server_side_error_page errorTryLoadText: '%s': %s\n", path, xstrerror());
		if (fd >= 0)
			file_close(fd);
		//return NULL;
		memBufInit(text, 1*sizeof(char), 1*sizeof(char));
		memBufPrintf(text, "%s", "");
	}
	else
	{
		memBufInit(text, (size_t)sb.st_size+2+1, (size_t)sb.st_size+2+1);
		if (read(fd, text->buf, (int) sb.st_size) != sb.st_size)
		{
			debug(115,0) ("mod_customized_server_side_error_page errorTryLoadText: failed to fully read: '%s': %s\n",
					path, xstrerror());
			memBufClean(text);
		}
		text->size += sb.st_size;
		text->buf[text->size] = '\0';
		debug(115,4)("mod_customized_server_side_error_page errorTryLoadText: the path is: %s point before end and text is: %s.....\n", path,text->buf);
		close(fd);
	}
#ifndef CC_FRAMEWORK
	if (NULL != text->buf && strstr(text->buf, "%s") == NULL)
		memBufAppend(text,"%S", strlen("%S"));	/* add signature */
#endif 
}
示例#14
0
static const char *
errorConvert(char token, ErrorState * err)
{
    request_t *r = err->request;
    static MemBuf mb = MemBufNULL;
    const char *p = NULL;	/* takes priority over mb if set */
    int do_quote = 1;

    memBufReset(&mb);
    switch (token) {
    case 'a':
	if (r && r->auth_user_request)
	    p = authenticateUserRequestUsername(r->auth_user_request);
	if (!p)
	    p = "-";
	break;
    case 'B':
	p = r ? ftpUrlWith2f(r) : "[no URL]";
	break;
    case 'c':
	p = errorPageName(err->type);
	break;
    case 'e':
	memBufPrintf(&mb, "%d", err->xerrno);
	break;
    case 'E':
	if (err->xerrno)
	    memBufPrintf(&mb, "(%d) %s", err->xerrno, strerror(err->xerrno));
	else
	    memBufPrintf(&mb, "[No Error]");
	break;
    case 'f':
	/* FTP REQUEST LINE */
	if (err->ftp.request)
	    p = err->ftp.request;
	else
	    p = "nothing";
	break;
    case 'F':
	/* FTP REPLY LINE */
	if (err->ftp.request)
	    p = err->ftp.reply;
	else
	    p = "nothing";
	break;
    case 'g':
	/* FTP SERVER MESSAGE */
	wordlistCat(err->ftp.server_msg, &mb);
	break;
    case 'h':
	memBufPrintf(&mb, "%s", getMyHostname());
	break;
    case 'H':
	if (r) {
	    if (r->hier.host)
		p = r->hier.host;
	    else
		p = r->host;
	} else
	    p = "[unknown host]";
	break;
    case 'i':
	memBufPrintf(&mb, "%s", inet_ntoa(err->src_addr));
	break;
    case 'I':
	if (r && r->hier.host) {
	    memBufPrintf(&mb, "%s", r->hier.host);
	} else
	    p = "[unknown]";
	break;
    case 'L':
	if (Config.errHtmlText) {
	    memBufPrintf(&mb, "%s", Config.errHtmlText);
	    do_quote = 0;
	} else
	    p = "[not available]";
	break;
    case 'm':
	p = authenticateAuthUserRequestMessage(err->auth_user_request) ? authenticateAuthUserRequestMessage(err->auth_user_request) : "[not available]";
	break;
    case 'M':
	p = r ? RequestMethods[r->method].str : "[unknown method]";
	break;
    case 'o':
	p = external_acl_message;
	if (!p)
	    p = "[not available]";
	break;
    case 'p':
	if (r) {
	    memBufPrintf(&mb, "%d", (int) r->port);
	} else {
	    p = "[unknown port]";
	}
	break;
    case 'P':
	p = r ? ProtocolStr[r->protocol] : "[unkown protocol]";
	break;
    case 'R':
	if (NULL != r) {
	    Packer p;
	    memBufPrintf(&mb, "%s %s HTTP/%d.%d\n",
		RequestMethods[r->method].str,
		strLen(r->urlpath) ? strBuf(r->urlpath) : "/",
		r->http_ver.major, r->http_ver.minor);
	    packerToMemInit(&p, &mb);
	    httpHeaderPackInto(&r->header, &p);
	    packerClean(&p);
	} else if (err->request_hdrs) {
	    p = err->request_hdrs;
	} else {
	    p = "[no request]";
	}
	break;
    case 's':
	p = visible_appname_string;
	break;
    case 'S':
	/* signature may contain %-escapes, recursion */
	if (err->page_id != ERR_SQUID_SIGNATURE) {
	    const int saved_id = err->page_id;
	    MemBuf sign_mb;
	    err->page_id = ERR_SQUID_SIGNATURE;
	    sign_mb = errorBuildContent(err);
	    memBufPrintf(&mb, "%s", sign_mb.buf);
	    memBufClean(&sign_mb);
	    err->page_id = saved_id;
	    do_quote = 0;
	} else {
	    /* wow, somebody put %S into ERR_SIGNATURE, stop recursion */
	    p = "[%S]";
	}
	break;
    case 't':
	memBufPrintf(&mb, "%s", mkhttpdlogtime(&squid_curtime));
	break;
    case 'T':
	memBufPrintf(&mb, "%s", mkrfc1123(squid_curtime));
	break;
    case 'U':
	p = r ? urlCanonicalClean(r) : err->url ? err->url : "[no URL]";
	break;
    case 'u':
	p = r ? urlCanonical(r) : err->url ? err->url : "[no URL]";
	break;
    case 'w':
	if (Config.adminEmail)
	    memBufPrintf(&mb, "%s", Config.adminEmail);
	else
	    p = "[unknown]";
	break;
    case 'z':
	if (err->dnsserver_msg)
	    p = err->dnsserver_msg;
	else
	    p = "[unknown]";
	break;
    case '%':
	p = "%";
	break;
    default:
	memBufPrintf(&mb, "%%%c", token);
	do_quote = 0;
	break;
    }
    if (!p)
	p = mb.buf;		/* do not use mb after this assignment! */
    assert(p);
    debug(4, 3) ("errorConvert: %%%c --> '%s'\n", token, p);
    if (do_quote)
	p = html_quote(p);
    return p;
}
示例#15
0
/*
 * The helper program receives queries on stdin, one
 * per line, and must return the result on on stdout
 */
static void
refreshCheckHandleReply(void *data, char *reply)
{
    refreshCheckState *state = data;
    refreshCheckState *next;
    int freshness = -1;
    char *log = NULL;
    MemBuf hdrs = MemBufNULL;


    debug(84, 2) ("refreshCheckHandleReply: reply=\"%s\"\n", reply);

    if (reply) {
	char *t = NULL;
	char *token = strwordtok(reply, &t);
	if (token && strcmp(token, "FRESH") == 0)
	    freshness = 0;
	else if (token && strcmp(token, "OK") == 0)
	    freshness = 0;

	while ((token = strwordtok(NULL, &t))) {
	    char *value = strchr(token, '=');
	    if (value) {
		*value++ = '\0';	/* terminate the token, and move up to the value */
		rfc1738_unescape(value);
		if (strcmp(token, "freshness") == 0)
		    freshness = atoi(value);
		else if (strcmp(token, "log") == 0)
		    log = value;
		else if (strncmp(token, "res{", 4) == 0) {
		    char *header, *t;
		    header = token + 4;
		    t = strrchr(header, '}');
		    if (!t)
			continue;
		    *t = '\0';
		    if (!hdrs.buf)
			memBufDefInit(&hdrs);
		    memBufPrintf(&hdrs, "%s: %s\r\n", header, value);
		}
	    }
	}
    }
    if (freshness >= 0) {
	if (hdrs.size) {
	    HttpReply *rep = httpReplyCreate();
	    httpHeaderParse(&rep->header, hdrs.buf, hdrs.buf + hdrs.size);
	    httpReplyUpdateOnNotModified(state->entry->mem_obj->reply, rep);
	    storeTimestampsSet(state->entry);
	    if (!httpHeaderHas(&rep->header, HDR_DATE)) {
		state->entry->timestamp = squid_curtime;
		state->entry->expires = squid_curtime + freshness;
	    } else if (freshness) {
		state->entry->expires = squid_curtime + freshness;
	    }
	    httpReplyDestroy(rep);
	    storeUpdate(state->entry, NULL);
	} else {
	    state->entry->timestamp = squid_curtime;
	    state->entry->expires = squid_curtime + freshness;
	}
    }
    if (hdrs.buf)
	memBufClean(&hdrs);
    dlinkDelete(&state->list, &state->def->queue);
    do {
	cbdataUnlock(state->def);
	state->def = NULL;

	if (state->callback && cbdataValid(state->callback_data))
	    state->callback(state->callback_data, freshness >= 0, log);
	cbdataUnlock(state->callback_data);
	state->callback_data = NULL;

	next = state->queue;
	cbdataFree(state);
	state = next;
    } while (state);
}
示例#16
0
文件: MemBuf.c 项目: CoolerVoid/squid
/* puts report on MemBuf _module_ usage into mb */
void
memBufReport(MemBuf * mb)
{
    assert(mb);
    memBufPrintf(mb, "memBufReport is not yet implemented @?@\n");
}
示例#17
0
static void
urnHandleReply(void *data, char *buf, ssize_t size)
{
    UrnState *urnState = data;
    StoreEntry *e = urnState->entry;
    StoreEntry *urlres_e = urnState->urlres_e;
    char *s = NULL;
    size_t k;
    HttpReply *rep;
    url_entry *urls;
    url_entry *u;
    url_entry *min_u;
    MemBuf mb;
    ErrorState *err;
    int i;
    int urlcnt = 0;
    http_version_t version;

    debug(52, 3) ("urnHandleReply: Called with size=%d.\n", (int) size);
    if (EBIT_TEST(urlres_e->flags, ENTRY_ABORTED)) {
	memFree(buf, MEM_4K_BUF);
	return;
    }
    if (size == 0) {
	memFree(buf, MEM_4K_BUF);
	return;
    } else if (size < 0) {
	memFree(buf, MEM_4K_BUF);
	return;
    }
    if (urlres_e->store_status == STORE_PENDING && size < SM_PAGE_SIZE) {
	storeClientCopy(urnState->sc, urlres_e,
	    size,
	    0,
	    SM_PAGE_SIZE,
	    buf,
	    urnHandleReply,
	    urnState);
	return;
    }
    /* we know its STORE_OK */
    k = headersEnd(buf, size);
    if (0 == k) {
	debug(52, 1) ("urnHandleReply: didn't find end-of-headers for %s\n",
	    storeUrl(e));
	return;
    }
    s = buf + k;
    assert(urlres_e->mem_obj->reply);
    httpReplyParse(urlres_e->mem_obj->reply, buf, k);
    debug(52, 3) ("mem->reply exists, code=%d.\n",
	urlres_e->mem_obj->reply->sline.status);
    if (urlres_e->mem_obj->reply->sline.status != HTTP_OK) {
	debug(52, 3) ("urnHandleReply: failed.\n");
	err = errorCon(ERR_URN_RESOLVE, HTTP_NOT_FOUND);
	err->request = requestLink(urnState->request);
	err->url = xstrdup(storeUrl(e));
	errorAppendEntry(e, err);
	return;
    }
    while (xisspace(*s))
	s++;
    urls = urnParseReply(s, urnState->request->method);
    for (i = 0; NULL != urls[i].url; i++)
	urlcnt++;
    debug(53, 3) ("urnFindMinRtt: Counted %d URLs\n", i);
    if (urls == NULL) {		/* unkown URN error */
	debug(52, 3) ("urnTranslateDone: unknown URN %s\n", storeUrl(e));
	err = errorCon(ERR_URN_RESOLVE, HTTP_NOT_FOUND);
	err->request = requestLink(urnState->request);
	err->url = xstrdup(storeUrl(e));
	errorAppendEntry(e, err);
	return;
    }
    min_u = urnFindMinRtt(urls, urnState->request->method, NULL);
    qsort(urls, urlcnt, sizeof(*urls), url_entry_sort);
    storeBuffer(e);
    memBufDefInit(&mb);
    memBufPrintf(&mb,
	"<TITLE>Select URL for %s</TITLE>\n"
	"<STYLE type=\"text/css\"><!--BODY{background-color:#ffffff;font-family:verdana,sans-serif}--></STYLE>\n"
	"<H2>Select URL for %s</H2>\n"
	"<TABLE BORDER=\"0\" WIDTH=\"100%%\">\n", storeUrl(e), storeUrl(e));
    for (i = 0; i < urlcnt; i++) {
	u = &urls[i];
	debug(52, 3) ("URL {%s}\n", u->url);
	memBufPrintf(&mb,
	    "<TR><TD><A HREF=\"%s\">%s</A></TD>", u->url, u->url);
	if (urls[i].rtt > 0)
	    memBufPrintf(&mb,
		"<TD align=\"right\">%4d <it>ms</it></TD>", u->rtt);
	else
	    memBufPrintf(&mb, "<TD align=\"right\">Unknown</TD>");
	memBufPrintf(&mb,
	    "<TD>%s</TD></TR>\n", u->flags.cached ? "    [cached]" : " ");
    }
    memBufPrintf(&mb,
	"</TABLE>"
	"<HR noshade size=\"1px\">\n"
	"<ADDRESS>\n"
	"Generated by %s@%s\n"
	"</ADDRESS>\n",
	full_appname_string, getMyHostname());
    rep = e->mem_obj->reply;
    httpReplyReset(rep);
    httpBuildVersion(&version, 1, 0);
    httpReplySetHeaders(rep, version, HTTP_MOVED_TEMPORARILY, NULL,
	"text/html", mb.size, 0, squid_curtime);
    if (urnState->flags.force_menu) {
	debug(51, 3) ("urnHandleReply: forcing menu\n");
    } else if (min_u) {
	httpHeaderPutStr(&rep->header, HDR_LOCATION, min_u->url);
    }
    httpBodySet(&rep->body, &mb);
    httpReplySwapOut(rep, e);
    storeComplete(e);
    memFree(buf, MEM_4K_BUF);
    for (i = 0; i < urlcnt; i++) {
	safe_free(urls[i].url);
	safe_free(urls[i].host);
    }
    safe_free(urls);
    /* mb was absorbed in httpBodySet call, so we must not clean it */
    storeUnregister(urnState->sc, urlres_e, urnState);
    storeUnlockObject(urlres_e);
    storeUnlockObject(urnState->entry);
    requestUnlink(urnState->request);
    requestUnlink(urnState->urlres_r);
    cbdataFree(urnState);
}
void
externalAclLookup(aclCheck_t * ch, void *acl_data, EAH * callback, void *callback_data)
{
    MemBuf buf;
    external_acl_data *acl = acl_data;
    external_acl *def = acl->def;
    const char *key;
    external_acl_entry *entry;
    externalAclState *state;
    if (acl->def->require_auth) {
	int ti;
	/* Make sure the user is authenticated */
	if ((ti = aclAuthenticated(ch)) != 1) {
	    debug(82, 1) ("externalAclLookup: %s user authentication failure (%d)\n", acl->def->name, ti);
	    callback(callback_data, NULL);
	    return;
	}
    }
    key = makeExternalAclKey(ch, acl);
    if (!key) {
	debug(82, 1) ("externalAclLookup: lookup in '%s', prerequisit failure\n", def->name);
	callback(callback_data, NULL);
	return;
    }
    debug(82, 2) ("externalAclLookup: lookup in '%s' for '%s'\n", def->name, key);
    entry = hash_lookup(def->cache, key);
    state = cbdataAlloc(externalAclState);
    state->def = def;
    cbdataLock(state->def);
    state->callback = callback;
    state->callback_data = callback_data;
    state->key = xstrdup(key);
    cbdataLock(state->callback_data);
    if (entry && !external_acl_entry_expired(def, entry)) {
	if (entry->result == -1) {
	    /* There is a pending lookup. Hook into it */
	    dlink_node *node;
	    for (node = def->queue.head; node; node = node->next) {
		externalAclState *oldstate = node->data;
		if (strcmp(state->key, oldstate->key) == 0) {
		    state->queue = oldstate->queue;
		    oldstate->queue = state;
		    return;
		}
	    }
	} else {
	    /* There is a cached valid result.. use it */
	    /* This should not really happen, but what the heck.. */
	    callback(callback_data, entry);
	    cbdataFree(state);
	    return;
	}
    }
    /* Check for queue overload */
    if (def->helper->stats.queue_size >= def->helper->n_running) {
	int result = -1;
	external_acl_entry *entry = hash_lookup(def->cache, key);
	debug(82, 1) ("externalAclLookup: '%s' queue overload\n", def->name);
	if (entry)
	    result = entry->result;
	cbdataFree(state);
	callback(callback_data, entry);
	return;
    }
    /* Send it off to the helper */
    memBufDefInit(&buf);
    memBufPrintf(&buf, "%s\n", key);
    helperSubmit(def->helper, buf.buf, externalAclHandleReply, state);
    external_acl_cache_add(def, key, -1, NULL, NULL);
    dlinkAdd(state, &state->list, &def->queue);
    memBufClean(&buf);
}
示例#19
0
void
icapSendRespMod(IcapStateData * icap, char *buf, int len, int theEnd)
{
    MemBuf mb;
#if ICAP_PREVIEW
    int size;
    const int preview_size = icap->preview_size;
#endif
    debug(81, 5) ("icapSendRespMod: FD %d, len %d, theEnd %d\n",
	icap->icap_fd, len, theEnd);

    if (icap->flags.no_content) {
	/*
	 * ICAP server said there are no modifications to make, so
	 * just append this data to the StoreEntry
	 */
	if (icap->respmod.resp_copy.size) {
	    /*
	     * first copy the data that we already sent to the ICAP server
	     */
	    memBufAppend(&icap->chunk_buf,
		icap->respmod.resp_copy.buf, icap->respmod.resp_copy.size);
	    icap->respmod.resp_copy.size = 0;
	}
	debug(81, 5) ("icapSendRepMod: len=%d theEnd=%d write_pending=%d\n",
	    len, theEnd, icap->flags.write_pending);
	if (len) {
	    /*
	     * also copy any new data from the HTTP side
	     */
	    memBufAppend(&icap->chunk_buf, buf, len);
	}
	(void) icapReadReply2(icap);
	return;
    }
    if (theEnd) {
	if (icap->respmod.res_body_sz)
	    icap->flags.send_zero_chunk = 1;
	icap->flags.http_server_eof = 1;
    }
    /*
     * httpReadReply is going to call us with a chunk and then
     * right away again with an EOF if httpPconnTransferDone() is true.
     * Since the first write is already dispatched, we'll have to 
     * hack this in somehow.
     */
    if (icap->flags.write_pending) {
	debug(81, 3) ("icapSendRespMod: oops, write_pending=1\n");
	assert(theEnd);
	assert(len == 0);
	return;
    }
    if (!cbdataValid(icap)) {
	debug(81, 3) ("icapSendRespMod: failed to establish connection?\n");
	return;
    }
    memBufDefInit(&mb);

#if SUPPORT_ICAP_204 || ICAP_PREVIEW
    /*
     * make a copy of the response in case ICAP server gives us a 204
     */
    /*
     * This piece of code is problematic for 204 responces outside preview.
     * The icap->respmod.resp_copy continues to filled until we had responce
     * If the icap server waits to gets all data before sends its responce 
     * then we are puting all downloading object to the main system memory.
     * My opinion is that 204 responces outside preview must be disabled .....
     * /chtsanti
     */

    if (len && icap->flags.copy_response) {
	 if (memBufIsNull(&icap->respmod.resp_copy))
	      memBufDefInit(&icap->respmod.resp_copy);
	 memBufAppend(&icap->respmod.resp_copy, buf, len);
    }

#endif

    if (icap->sc == 0) {
	/* No data sent yet. Start with headers */
	 if((icap->sc = buildRespModHeader(&mb, icap, buf, len, theEnd))>0){
	      buf += icap->sc;
	      len -= icap->sc;
	 }
	 /*
	  * Then we do not have http responce headers. All data (previous and those in buf)
	  * now are exist to icap->respmod.req_hdr_copy. Lets get them back.......
	  */
	 if(icap->sc <0){
	      memBufAppend(&icap->respmod.buffer,
			   icap->respmod.req_hdr_copy.buf,
			   icap->respmod.req_hdr_copy.size);
	      icap->sc=icap->respmod.req_hdr_copy.size;
	      icap->respmod.req_hdr_copy.size=0;
	      buf=NULL;
	      len=0;
	 }
    }
    if (0 == icap->sc) {
	/* check again; bail if we're not ready to send ICAP/HTTP hdrs */
	debug(81, 5) ("icapSendRespMod: dont have full HTTP response hdrs\n");
	memBufClean(&mb);
	return;
    }
#if ICAP_PREVIEW
    if (preview_size < 0 || !Config.icapcfg.preview_enable)	/* preview feature off */
	icap->flags.preview_done = 1;

    if (!icap->flags.preview_done) {
	/* preview not yet sent */
	if (icap->sc > 0 && icap->respmod.buffer.size <= preview_size
	    && len > 0) {
	    /* Try to collect at least preview_size+1 bytes */
	    /* By collecting one more byte than needed for preview we know best */
	    /* whether we have to send the ieof chunk extension */
	    size = icap->respmod.buffer.size + len;
	    if (size > preview_size + 1)
		size = preview_size + 1;
	    size -= icap->respmod.buffer.size;
	    debug(81,
		3)
		("icapSendRespMod: FD %d: copy %d more bytes to preview buffer.\n",
		icap->icap_fd, size);
	    memBufAppend(&icap->respmod.buffer, buf, size);
	    buf = ((char *) buf) + size;
	    len -= size;
	}
	if (icap->respmod.buffer.size > preview_size || theEnd) {
	    /* we got enough bytes for preview or this is the last call */
	    /* add preview preview now */
	    if (icap->respmod.buffer.size > 0) {
		size = icap->respmod.buffer.size;
		if (size > preview_size)
		    size = preview_size;
		memBufPrintf(&mb, "%x\r\n", size);
		memBufAppend(&mb, icap->respmod.buffer.buf, size);
		memBufAppend(&mb, crlf, 2);
		icap->sc += size;
	    }
	    if (icap->respmod.buffer.size <= preview_size) {
		/* content length is less than preview size+1 */
		if (icap->respmod.res_body_sz)
		    memBufAppend(&mb, "0; ieof\r\n\r\n", 11);
		memBufReset(&icap->respmod.buffer);	/* will now be used for other data */
	    } else {
		char ch;
		memBufAppend(&mb, "0\r\n\r\n", 5);
		/* end of preview, wait for continue or 204 signal */
		/* copy the extra byte and all other data to the icap buffer */
		/* so that it can be handled next time */
		ch = icap->respmod.buffer.buf[preview_size];
		memBufReset(&icap->respmod.buffer);	/* will now be used for other data */
		memBufAppend(&icap->respmod.buffer, &ch, 1);
		debug(81,
		    3)
		    ("icapSendRespMod: FD %d: sending preview and keeping %d bytes in internal buf.\n",
		    icap->icap_fd, len + 1);
		if (len > 0)
		    memBufAppend(&icap->respmod.buffer, buf, len);
	    }
	    icap->flags.preview_done = 1;
	    icap->flags.wait_for_preview_reply = 1;
	}
    } else if (icap->flags.wait_for_preview_reply) {
	/* received new data while waiting for preview response */
	/* add data to internal buffer and send later */
	debug(81,
	    3)
	    ("icapSendRespMod: FD %d: add %d more bytes to internal buf while waiting for preview-response.\n",
	    icap->icap_fd, len);
	if (len > 0)
	    memBufAppend(&icap->respmod.buffer, buf, len);
	/* do not send any data now while waiting for preview response */
	/* but prepare for read more data on the HTTP connection */
	memBufClean(&mb);
	return;
    } else
#endif
    {
	/* after preview completed and ICAP preview response received */
	/* there may still be some data in the buffer */
	if (icap->respmod.buffer.size > 0) {
	    memBufPrintf(&mb, "%x\r\n", icap->respmod.buffer.size);
	    memBufAppend(&mb, icap->respmod.buffer.buf,
		icap->respmod.buffer.size);
	    memBufAppend(&mb, crlf, 2);
	    icap->sc += icap->respmod.buffer.size;
	    memBufReset(&icap->respmod.buffer);
	}
	if (len > 0) {
	    memBufPrintf(&mb, "%x\r\n", len);
	    memBufAppend(&mb, buf, len);
	    memBufAppend(&mb, crlf, 2);
	    icap->sc += len;
	}
	if (icap->flags.send_zero_chunk) {
	    /* send zero end chunk */
	    icap->flags.send_zero_chunk = 0;
	    icap->flags.http_server_eof = 1;
	    memBufAppend(&mb, "0\r\n\r\n", 5);
	}
	/* wait for data coming from ICAP server as soon as we sent something */
	/* but of course only until we got the response header */
	if (!icap->flags.got_reply)
	    icap->flags.wait_for_reply = 1;
    }
    commSetTimeout(icap->icap_fd, -1, NULL, NULL);

    if (!mb.size) {
	memBufClean(&mb);
	return;
    }
    debug(81, 5) ("icapSendRespMod: FD %d writing {%s}\n", icap->icap_fd,
	mb.buf);
    icap->flags.write_pending = 1;
    comm_write_mbuf(icap->icap_fd, mb, icapSendRespModDone, icap);
}
示例#20
0
static int
buildRespModHeader(MemBuf * mb, IcapStateData * icap, char *buf,
    ssize_t len, int theEnd)
{
    MemBuf mb_hdr;
    char *client_addr;
    int o2=0;
    int o3=0;
    int hlen;
    int consumed;
    icap_service *service;
    HttpReply *r;

    if (memBufIsNull(&icap->respmod.req_hdr_copy))
	memBufDefInit(&icap->respmod.req_hdr_copy);

    memBufAppend(&icap->respmod.req_hdr_copy, buf, len);

    if (icap->respmod.req_hdr_copy.size > 4 && strncmp(icap->respmod.req_hdr_copy.buf, "HTTP/", 5)) {
	debug(81, 3) ("buildRespModHeader: Non-HTTP-compliant header: '%s'\n", buf);
	/*
	 *Possible we can consider that we did not have http responce headers 
	 *(maybe HTTP 0.9 protocol), lets returning -1...
	 */
	consumed=-1;
	o2=-1;
	memBufDefInit(&mb_hdr);
    }
    else{

        hlen = headersEnd(icap->respmod.req_hdr_copy.buf,
			   icap->respmod.req_hdr_copy.size);
        debug(81, 3) ("buildRespModHeader: headersEnd = %d(%s)\n", hlen,buf);
        if (0 == hlen)
            return 0;

	/*
	 * calc how many bytes from this 'buf' went towards the
	 * reply header.
	 */
	consumed = hlen - (icap->respmod.req_hdr_copy.size - len);
	debug(81, 3) ("buildRespModHeader: consumed = %d\n", consumed);


	/*
	 * now, truncate our req_hdr_copy at the header end.
	 * this 'if' statement might be unncessary?
	 */
	if (hlen < icap->respmod.req_hdr_copy.size)
	     icap->respmod.req_hdr_copy.size = hlen;
	
	/* Copy request header */
	memBufDefInit(&mb_hdr);
	httpBuildRequestPrefix(icap->request, icap->request,
			       icap->respmod.entry, &mb_hdr, icap->http_flags);
	o2 = mb_hdr.size;
    }

    /* Copy response header - Append to request header mbuffer */
    memBufAppend(&mb_hdr,
	icap->respmod.req_hdr_copy.buf, icap->respmod.req_hdr_copy.size);
    o3 = mb_hdr.size;

    service = icap->current_service;
    assert(service);
    client_addr = inet_ntoa(icap->request->client_addr);

    r = httpReplyCreate();
    httpReplyParse(r, icap->respmod.req_hdr_copy.buf,
	icap->respmod.req_hdr_copy.size);
    icap->respmod.res_body_sz = httpReplyBodySize(icap->request->method, r);
    httpReplyDestroy(r);
    if (icap->respmod.res_body_sz)
	getICAPRespModString(mb, 0, o2, o3, client_addr, icap, service);
    else
	getICAPRespModString(mb, 0, o2, -o3, client_addr, icap, service);
    if (Config.icapcfg.preview_enable)
	if (icap->preview_size >= 0) {
	    memBufPrintf(mb, "Preview: %d\r\n", icap->preview_size);
	    icap->flags.preview_done = 0;
	}
    if(service->keep_alive){
	icap->flags.keep_alive = 1;
	memBufAppend(mb, "Connection: keep-alive\r\n", 24);
    }
    else{
	icap->flags.keep_alive = 0;
	memBufAppend(mb, "Connection: close\r\n", 19);
    }
    memBufAppend(mb, crlf, 2);
    memBufAppend(mb, mb_hdr.buf, mb_hdr.size);
    memBufClean(&mb_hdr);


    return consumed;
}