Beispiel #1
0
void
httpReplySetHeaders(HttpReply * reply, http_version_t ver, http_status status, const char *reason,
    const char *ctype, squid_off_t clen, time_t lmt, time_t expires)
{
    HttpHeader *hdr;
    assert(reply);
    httpStatusLineSet(&reply->sline, ver, status, reason);
    hdr = &reply->header;
    httpHeaderPutStr(hdr, HDR_SERVER, full_appname_string);
    httpHeaderPutStr(hdr, HDR_MIME_VERSION, "1.0");
    httpHeaderPutTime(hdr, HDR_DATE, squid_curtime);
    if (ctype) {
	httpHeaderPutStr(hdr, HDR_CONTENT_TYPE, ctype);
	stringInit(&reply->content_type, ctype);
    } else
	reply->content_type = StringNull;
    if (clen >= 0)
	httpHeaderPutSize(hdr, HDR_CONTENT_LENGTH, clen);
    if (expires >= 0)
	httpHeaderPutTime(hdr, HDR_EXPIRES, expires);
    if (lmt > 0)		/* this used to be lmt != 0 @?@ */
	httpHeaderPutTime(hdr, HDR_LAST_MODIFIED, lmt);
    reply->date = squid_curtime;
    reply->content_length = clen;
    reply->expires = expires;
    reply->last_modified = lmt;
}
Beispiel #2
0
int
errorMapStart(const errormap * map, request_t * client_req, HttpReply * reply, const char *aclname, ERRMAPCB * callback, void *callback_data)
{
    char squid_error[100];
    int len = 0;
    const char *errorUrl;
    ErrorMapState *state;
    const char *tmp;
    http_status status;
    request_t *req;
    HttpHeaderPos hdrpos;
    HttpHeaderEntry *hdr;

    if (!client_req || !reply)
	return 0;

    status = reply->sline.status;

    tmp = httpHeaderGetStr(&reply->header, HDR_X_SQUID_ERROR);
    squid_error[0] = '\0';
    if (tmp) {
	xstrncpy(squid_error, tmp, sizeof(squid_error));
	len = strcspn(squid_error, " ");
    }
    squid_error[len] = '\0';
    errorUrl = getErrorMap(map, status, squid_error, aclname);
    if (!errorUrl)
	return 0;
    req = urlParse(urlMethodGetKnownByCode(METHOD_GET), (char *) errorUrl);
    if (!req) {
	debug(0, 0) ("errorMapStart: Invalid error URL '%s'\n", errorUrl);
	return 0;
    }
    req->urlgroup = xstrdup("error");

    state = cbdataAlloc(ErrorMapState);
    state->req = requestLink(req);
    state->e = storeCreateEntry(errorUrl, req->flags, req->method);
    state->sc = storeClientRegister(state->e, state);
    state->callback = callback;
    state->callback_data = callback_data;
    cbdataLock(callback_data);

    hdrpos = HttpHeaderInitPos;
    while ((hdr = httpHeaderGetEntry(&client_req->header, &hdrpos)) != NULL) {
	if (CBIT_TEST(client_headers, hdr->id))
	    httpHeaderAddClone(&req->header, hdr);
    }
    hdrpos = HttpHeaderInitPos;
    while ((hdr = httpHeaderGetEntry(&reply->header, &hdrpos)) != NULL) {
	if (CBIT_TEST(server_headers, hdr->id))
	    httpHeaderAddClone(&req->header, hdr);
    }
    httpHeaderPutInt(&req->header, HDR_X_ERROR_STATUS, (int) reply->sline.status);
    httpHeaderPutStr(&req->header, HDR_X_REQUEST_URI, urlCanonical(client_req));

    fwdStart(-1, state->e, req);
    storeClientRef(state->sc, state->e, 0, 0, SM_PAGE_SIZE, errorMapFetchHeaders, state);
    return 1;
}
Beispiel #3
0
void
httpRedirectReply(HttpReply * reply, http_status status, const char *loc)
{
    HttpHeader *hdr;
    http_version_t ver;
    assert(reply);
    httpBuildVersion(&ver, 1, 0);
    httpStatusLineSet(&reply->sline, ver, status, httpStatusString(status));
    hdr = &reply->header;
    httpHeaderPutStr(hdr, HDR_SERVER, full_appname_string);
    httpHeaderPutTime(hdr, HDR_DATE, squid_curtime);
    httpHeaderPutSize(hdr, HDR_CONTENT_LENGTH, 0);
    httpHeaderPutStr(hdr, HDR_LOCATION, loc);
    reply->date = squid_curtime;
    reply->content_length = 0;
}
/* create MIME Header for Gopher Data */
static void
gopherMimeCreate(GopherStateData * gopherState)
{
    StoreEntry *e = gopherState->entry;
    HttpReply *reply = e->mem_obj->reply;
    http_version_t version;
    const char *mime_type = NULL;
    const char *mime_enc = NULL;

    switch (gopherState->type_id) {
    case GOPHER_DIRECTORY:
    case GOPHER_INDEX:
    case GOPHER_HTML:
    case GOPHER_WWW:
    case GOPHER_CSO:
	mime_type = "text/html";
	break;
    case GOPHER_GIF:
    case GOPHER_IMAGE:
    case GOPHER_PLUS_IMAGE:
	mime_type = "image/gif";
	break;
    case GOPHER_SOUND:
    case GOPHER_PLUS_SOUND:
	mime_type = "audio/basic";
	break;
    case GOPHER_PLUS_MOVIE:
	mime_type = "video/mpeg";
	break;
    case GOPHER_MACBINHEX:
	mime_type = "application/macbinary";
	break;
    case GOPHER_DOSBIN:
    case GOPHER_UUENCODED:
    case GOPHER_BIN:
    case GOPHER_FILE:
    default:
	/* Rightnow We have no idea what it is. */
	mime_type = mimeGetContentType(gopherState->request);
	mime_enc = mimeGetContentEncoding(gopherState->request);
	break;
    }

    storeBuffer(e);
    httpReplyReset(reply);
    EBIT_CLR(gopherState->entry->flags, ENTRY_FWD_HDR_WAIT);
    httpBuildVersion(&version, 1, 0);
    httpReplySetHeaders(reply, version, HTTP_OK, "Gatewaying", mime_type, -1, -1, -1);
    if (mime_enc)
	httpHeaderPutStr(&reply->header, HDR_CONTENT_ENCODING, mime_enc);
    httpReplySwapOut(reply, e);
    reply->hdr_sz = e->mem_obj->inmem_hi;
    storeTimestampsSet(e);
    if (EBIT_TEST(e->flags, ENTRY_CACHABLE)) {
	storeSetPublicKey(e);
    } else {
	storeRelease(e);
    }
}
Beispiel #5
0
void
urnStart(request_t * r, StoreEntry * e)
{
    LOCAL_ARRAY(char, urlres, 4096);
    request_t *urlres_r = NULL;
    const char *t;
    char *host;
    UrnState *urnState;
    StoreEntry *urlres_e;
    ErrorState *err;
    debug(52, 3) ("urnStart: '%s'\n", storeUrl(e));
    CBDATA_INIT_TYPE(UrnState);
    urnState = cbdataAlloc(UrnState);
    urnState->entry = e;
    urnState->request = requestLink(r);
    storeLockObject(urnState->entry);
    if (strncasecmp(strBuf(r->urlpath), "menu.", 5) == 0) {
	char *new_path = xstrdup(strBuf(r->urlpath) + 5);
	urnState->flags.force_menu = 1;
	stringReset(&r->urlpath, new_path);
	xfree(new_path);
    }
    if ((t = strChr(r->urlpath, ':')) != NULL) {
	strSet(r->urlpath, t, '\0');
	host = xstrdup(strBuf(r->urlpath));
	strSet(r->urlpath, t, ':');
    } else {
	host = xstrdup(strBuf(r->urlpath));
    }
    snprintf(urlres, 4096, "http://%s/uri-res/N2L?urn:%s", host, strBuf(r->urlpath));
    safe_free(host);
    urlres_r = urlParse(METHOD_GET, urlres);
    if (urlres_r == NULL) {
	debug(52, 3) ("urnStart: Bad uri-res URL %s\n", urlres);
	err = errorCon(ERR_URN_RESOLVE, HTTP_NOT_FOUND);
	err->url = xstrdup(urlres);
	errorAppendEntry(e, err);
	return;
    }
    httpHeaderPutStr(&urlres_r->header, HDR_ACCEPT, "text/plain");
    if ((urlres_e = storeGetPublic(urlres, METHOD_GET)) == NULL) {
	urlres_e = storeCreateEntry(urlres, urlres, null_request_flags, METHOD_GET);
	urnState->sc = storeClientListAdd(urlres_e, urnState);
	fwdStart(-1, urlres_e, urlres_r);
    } else {
	storeLockObject(urlres_e);
	urnState->sc = storeClientListAdd(urlres_e, urnState);
    }
    urnState->urlres_e = urlres_e;
    urnState->urlres_r = requestLink(urlres_r);
    storeClientCopy(urnState->sc, urlres_e,
	0,
	0,
	4096,
	memAllocate(MEM_4K_BUF),
	urnHandleReply,
	urnState);
}
/* used by httpHeaderPutStrf */
static void
httpHeaderPutStrvf(HttpHeader * hdr, http_hdr_type id, const char *fmt, va_list vargs)
{
    MemBuf mb;
    memBufDefInit(&mb);
    memBufVPrintf(&mb, fmt, vargs);
    httpHeaderPutStr(hdr, id, mb.buf);
    memBufClean(&mb);
}
Beispiel #7
0
static void
peerMonitorRequest(void *data)
{
	PeerMonitor *pm = data;
	char *url;
	request_t *req;

	if (!cbdataValid(pm->peer))
	{
		cbdataFree(pm);
		return;
	}
	url = pm->peer->monitor.url;
	if (!url)
	{
		cbdataFree(pm);
		return;
	}
	req = urlParse(METHOD_GET, url);
	if (!req)
	{
		debug(DBG, 1) ("peerMonitorRequest: Failed to parse URL '%s' for cache_peer %s\n", url, pm->peer->name);
		cbdataFree(pm);
		return;
	}
	pm->last_probe = squid_curtime;
	pm->running.timeout_set = 1;
	eventAdd(pm->name, peerMonitorTimeout, pm, (double) (pm->peer->monitor.timeout ? pm->peer->monitor.timeout : pm->peer->monitor.interval), 0);

	httpHeaderPutStr(&req->header, HDR_ACCEPT, "*/*");
	httpHeaderPutStr(&req->header, HDR_USER_AGENT, full_appname_string);
	if (pm->peer->login)
		xstrncpy(req->login, pm->peer->login, MAX_LOGIN_SZ);
	pm->running.req = requestLink(req);
	pm->running.e = storeCreateEntry(url, req->flags, req->method);
	pm->running.sc = storeClientRegister(pm->running.e, pm);
	pm->running.buf = memAllocate(MEM_4K_BUF);
	fwdStartPeer(pm->peer, pm->running.e, pm->running.req);
	storeClientCopy(pm->running.sc, pm->running.e, 0, 0, 4096, pm->running.buf, peerMonitorFetchReplyHeaders, pm);
	return;
}
/* ask store for a digest */
static void
peerDigestRequest(PeerDigest * pd)
{
    peer *p = pd->peer;
    StoreEntry *e, *old_e;
    char *url;
    const cache_key *key;
    request_t *req;
    DigestFetchState *fetch = NULL;

    pd->req_result = NULL;
    pd->flags.requested = 1;

    /* compute future request components */
    if (p->digest_url)
	url = xstrdup(p->digest_url);
    else
	url = internalRemoteUri(p->host, p->http_port,
	    "/squid-internal-periodic/", StoreDigestFileName);

    key = storeKeyPublic(url, METHOD_GET);
    debug(72, 2) ("peerDigestRequest: %s key: %s\n", url, storeKeyText(key));
    req = urlParse(METHOD_GET, url);
    assert(req);

    /* add custom headers */
    assert(!req->header.len);
    httpHeaderPutStr(&req->header, HDR_ACCEPT, StoreDigestMimeStr);
    httpHeaderPutStr(&req->header, HDR_ACCEPT, "text/html");
    if (p->login)
	xstrncpy(req->login, p->login, MAX_LOGIN_SZ);
    /* create fetch state structure */
    fetch = memAllocate(MEM_DIGEST_FETCH_STATE);
    cbdataAdd(fetch, memFree, MEM_DIGEST_FETCH_STATE);
    fetch->request = requestLink(req);
    fetch->pd = pd;
    fetch->offset = 0;

    /* update timestamps */
    fetch->start_time = squid_curtime;
    pd->times.requested = squid_curtime;
    pd_last_req_time = squid_curtime;

    req->flags.cachable = 1;
    /* the rest is based on clientProcessExpired() */
    req->flags.refresh = 1;
    old_e = fetch->old_entry = storeGet(key);
    if (old_e) {
	debug(72, 5) ("peerDigestRequest: found old entry\n");
	storeLockObject(old_e);
	storeCreateMemObject(old_e, url, url);
	storeClientListAdd(old_e, fetch);
    }
    e = fetch->entry = storeCreateEntry(url, url, req->flags, req->method);
    assert(EBIT_TEST(e->flags, KEY_PRIVATE));
    storeClientListAdd(e, fetch);
    /* set lastmod to trigger IMS request if possible */
    if (old_e)
	e->lastmod = old_e->lastmod;

    /* push towards peer cache */
    debug(72, 3) ("peerDigestRequest: forwarding to fwdStart...\n");
    fwdStart(-1, e, req);
    cbdataLock(fetch);
    cbdataLock(fetch->pd);
    storeClientCopy(e, 0, 0, 4096, memAllocate(MEM_4K_BUF),
	peerDigestFetchReply, fetch);
}
Beispiel #9
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);
}