Esempio n. 1
0
int
httpSpecialRequest(ObjectPtr object, int method, int from, int to,
		   HTTPRequestPtr requestor, void *closure)
{
	char buffer[1024];
	int hlen;

	if (method >= METHOD_POST) {
		return httpSpecialSideRequest(object, method, from, to,
					      requestor, closure);
	}

	if (!(object->flags & OBJECT_INITIAL)) {
		privatiseObject(object, 0);
		supersedeObject(object);
		object->flags &= ~(OBJECT_VALIDATING | OBJECT_INPROGRESS);
		notifyObject(object);
		return 1;
	}

	hlen = snnprintf(buffer, 0, 1024,
			 "\r\nServer: s_server" "\r\nContent-Type: text/html");
	object->date = current_time.tv_sec;
	object->age = current_time.tv_sec;
	object->headers = internAtomN(buffer, hlen);
	object->code = 200;
	object->message = internAtom("Okay");
	object->flags &= ~OBJECT_INITIAL;
	object->flags |= OBJECT_DYNAMIC;

	if (object->key_size == 8 && memcmp(object->key, "/s_server/", 8) == 0) {
		objectPrintf(object, 0,
			     "<!DOCTYPE HTML PUBLIC "
			     "\"-//W3C//DTD HTML 4.01 Transitional//EN\" "
			     "\"http://www.w3.org/TR/html4/loose.dtd\">\n"
			     "<html><head>\n"
			     "<title>Polipo</title>\n"
			     "</head><body>\n"
			     "<h1>Polipo</h1>\n"
			     "<p><a href=\"status?\">Status report</a>.</p>\n"
			     "<p><a href=\"config?\">Current configuration</a>.</p>\n"
			     "<p><a href=\"servers?\">Known servers</a>.</p>\n"
#ifndef NO_DISK_CACHE
			     "<p><a href=\"index?\">Disk cache index</a>.</p>\n"
#endif
			     "</body></html>\n");
		object->length = object->size;
	} else if (matchUrl("/s_server/status", object)) {
		objectPrintf(object, 0,
			     "<!DOCTYPE HTML PUBLIC "
			     "\"-//W3C//DTD HTML 4.01 Transitional//EN\" "
			     "\"http://www.w3.org/TR/html4/loose.dtd\">\n"
			     "<html><head>\n"
			     "<title>Polipo status report</title>\n"
			     "</head><body>\n"
			     "<h1>Polipo proxy on %s:%d: status report</h1>\n"
			     "<p>The %s proxy on %s:%d is %s.</p>\n"
			     "<p>There are %d public and %d private objects "
			     "currently in memory using %d KB in %d chunks "
			     "(%d KB allocated).</p>\n"
			     "<p>There are %d atoms.</p>"
			     "<p><form method=POST action=\"/s_server/status?\">"
			     "<input type=submit name=\"init-forbidden\" "
			     "value=\"Read forbidden file\"></form>\n"
			     "<form method=POST action=\"/s_server/status?\">"
			     "<input type=submit name=\"writeout-objects\" "
			     "value=\"Write out in-memory cache\"></form>\n"
			     "<form method=POST action=\"/s_server/status?\">"
			     "<input type=submit name=\"discard-objects\" "
			     "value=\"Discard in-memory cache\"></form>\n"
			     "<form method=POST action=\"/s_server/status?\">"
			     "<input type=submit name=\"reopen-log\" "
			     "value=\"Reopen log file\"></form>\n"
			     "<form method=POST action=\"/s_server/status?\">"
			     "<input type=submit name=\"free-chunk-arenas\" "
			     "value=\"Free chunk arenas\"></form></p>\n"
			     "<p><a href=\"/s_server/\">back</a></p>"
			     "</body></html>\n",
			     proxyName->string, proxyPort,
			     cacheIsShared ? "shared" : "private",
			     proxyName->string, proxyPort,
			     proxyOffline ? "off line" :
			     (relaxTransparency ?
			      "on line (transparency relaxed)" :
			      "on line"),
			     publicObjectCount, privateObjectCount,
			     used_chunks * CHUNK_SIZE / 1024, used_chunks,
			     totalChunkArenaSize() / 1024, used_atoms);
		object->expires = current_time.tv_sec;
		object->length = object->size;
	} else if (matchUrl("/s_server/config", object)) {
		fillSpecialObject(object, printConfig, NULL);
		object->expires = current_time.tv_sec + 5;
#ifndef NO_DISK_CACHE
	} else if (matchUrl("/s_server/index", object)) {
		int len;
		char *root;
		if (disableIndexing) {
			abortObject(object, 403,
				    internAtom("Action not allowed"));
			notifyObject(object);
			return 1;
		}
		len = MAX(0, object->key_size - 14);
		root = strdup_n((char *)object->key + 14, len);
		if (root == NULL) {
			abortObject(object, 503,
				    internAtom("Couldn't allocate root"));
			notifyObject(object);
			return 1;
		}
		writeoutObjects(1);
		fillSpecialObject(object, plainIndexDiskObjects, root);
		free(root);
		object->expires = current_time.tv_sec + 5;
	} else if (matchUrl("/s_server/recursive-index", object)) {
		int len;
		char *root;
		if (disableIndexing) {
			abortObject(object, 403,
				    internAtom("Action not allowed"));
			notifyObject(object);
			return 1;
		}
		len = MAX(0, object->key_size - 24);
		root = strdup_n((char *)object->key + 24, len);
		if (root == NULL) {
			abortObject(object, 503,
				    internAtom("Couldn't allocate root"));
			notifyObject(object);
			return 1;
		}
		writeoutObjects(1);
		fillSpecialObject(object, recursiveIndexDiskObjects, root);
		free(root);
		object->expires = current_time.tv_sec + 20;
#endif
	} else if (matchUrl("/s_server/servers", object)) {
		if (disableServersList) {
			abortObject(object, 403,
				    internAtom("Action not allowed"));
			notifyObject(object);
			return 1;
		}
		fillSpecialObject(object, serversList, NULL);
		object->expires = current_time.tv_sec + 2;
	} else {
		abortObject(object, 404, internAtom("Not found"));
	}

	object->flags &= ~OBJECT_VALIDATING;
	notifyObject(object);
	return 1;
}
Esempio n. 2
0
int
do_gethostbyname(char *origname,
                 int count,
                 int (*handler)(int, GethostbynameRequestPtr),
                 void *data)
{
    ObjectPtr object;
    int n = strlen(origname);
    AtomPtr name;
    GethostbynameRequestRec request;
    int done, rc;

    memset(&request, 0, sizeof(request));
    request.name = NULL;
    request.addr = NULL;
    request.error_message = NULL;
    request.count = count;
    request.handler = handler;
    request.data = data;

    if(n <= 0 || n > 131) {
        if(n <= 0) {
            request.error_message = internAtom("empty name");
            do_log(L_ERROR, "Empty DNS name.\n");
            done = handler(-EINVAL, &request);
        } else {
            request.error_message = internAtom("name too long");
            do_log(L_ERROR, "DNS name too long.\n");
            done = handler(-ENAMETOOLONG, &request);
        }
        assert(done);
        releaseAtom(request.error_message);
        return 1;
    }

    if(origname[n - 1] == '.')
        n--;

    name = internAtomLowerN(origname, n);

    if(name == NULL) {
        request.error_message = internAtom("couldn't allocate name");
        do_log(L_ERROR, "Couldn't allocate DNS name.\n");
        done = handler(-ENOMEM, &request);
        assert(done);
        releaseAtom(request.error_message);
        return 1;
    }

    request.name = name;
    request.addr = NULL;
    request.error_message = NULL;
    request.count = count;
    request.object = NULL;
    request.handler = handler;
    request.data = data;

    object = findObject(OBJECT_DNS, name->string, name->length);
    if(object == NULL || objectMustRevalidate(object, NULL)) {
        if(object) {
            privatiseObject(object, 0);
            releaseObject(object);
        }
        object = makeObject(OBJECT_DNS, name->string, name->length, 1, 0,
                            NULL, NULL);
        if(object == NULL) {
            request.error_message = internAtom("Couldn't allocate object");
            do_log(L_ERROR, "Couldn't allocate DNS object.\n");
            done = handler(-ENOMEM, &request);
            assert(done);
            releaseAtom(name);
            releaseAtom(request.error_message);
            return 1;
        }
    }

    if((object->flags & (OBJECT_INITIAL | OBJECT_INPROGRESS)) ==
       OBJECT_INITIAL) {
        if(dnsUseGethostbyname >= 3)
            rc = really_do_gethostbyname(name, object);
        else
            rc = really_do_dns(name, object);
        if(rc < 0) {
            assert(!(object->flags & (OBJECT_INITIAL | OBJECT_INPROGRESS)));
            goto fail;
        }
    }

    if(dnsUseGethostbyname >= 3)
        assert(!(object->flags & OBJECT_INITIAL));

#ifndef NO_FANCY_RESOLVER    
    if(object->flags & OBJECT_INITIAL) {
        ConditionHandlerPtr chandler;
        assert(object->flags & OBJECT_INPROGRESS);
        request.object = object;
        chandler = conditionWait(&object->condition, dnsHandler,
                                 sizeof(request), &request);
        if(chandler == NULL)
            goto fail;
        return 1;
    }
#endif

    if(object->headers && object->headers->length > 0) {
        if(object->headers->string[0] == DNS_A)
            assert(((object->headers->length - 1) % 
                    sizeof(HostAddressRec)) == 0);
        else
            assert(object->headers->string[0] == DNS_CNAME);
        request.addr = retainAtom(object->headers);
    } else if(object->message) {
        request.error_message = retainAtom(object->message);
    }

    releaseObject(object);

    if(request.addr && request.addr->length > 0)
        done = handler(1, &request);
    else
        done = handler(-EDNS_HOST_NOT_FOUND, &request);
    assert(done);

    releaseAtom(request.addr); request.addr = NULL;
    releaseAtom(request.name); request.name = NULL;
    releaseAtom(request.error_message); request.error_message = NULL;
    return 1;

 fail:
    releaseNotifyObject(object);
    done = handler(-errno, &request);
    assert(done);
    releaseAtom(name);
    return 1;
}