예제 #1
0
파일: abspath.c 프로젝트: Logout22/Escape
char *abspath(char *dst,size_t dstSize,const char *path) {
	if(*path != '/') {
		/* translate "abc://def" to "/dev/abc/def" */
		const char *p = path;
		while(*p) {
			if(p[0] == ':' && p[1] == '/' && p[2] == '/') {
				size_t slen = p - path;
				strncpy(dst,"/dev/",SSTRLEN("/dev/"));
				strncpy(dst + SSTRLEN("/dev/"),path,slen);
				strnzcpy(dst + SSTRLEN("/dev/") + slen,p + 2,dstSize - (SSTRLEN("/dev/") + slen));
				return dst;
			}
			p++;
		}

		/* prepend CWD */
		size_t len = getenvto(dst,dstSize,"CWD");
		if(len < dstSize - 1 && dst[len - 1] != '/') {
			dst[len++] = '/';
			dst[len] = '\0';
		}
		strnzcpy(dst + len,path,dstSize - len);
		return dst;
	}
	return (char*)path;
}
예제 #2
0
파일: ostream.cpp 프로젝트: Logout22/Escape
	ostream& ostream::operator <<(bool n) {
		if(ios_base::flags() & ios_base::boolalpha)
			write(n ? "true" : "false",n ? SSTRLEN("true") : SSTRLEN("false"));
		else
			writeUnsigned(n);
		return *this;
	}
예제 #3
0
static int check_persistent(char *p) {
    char *conn = strstr(p, CONNECTION);
    char *h1_1 = strstr(p, " HTTP/1.1");
    // HTTP/1.1
    if ((NULL != h1_1 &&
         (NULL == conn ||
          0 != SSTRNCMPI(CONNECTION_CLOSE, conn + SSTRLEN(CONNECTION)))) ||
        // HTTP/1.0
        (NULL == h1_1 &&
         NULL != conn &&
         0 == SSTRNCMPI(CONNECTION_KEEPALIVE, conn + SSTRLEN(CONNECTION))))
        return 1;
    else
        return 0;
}
예제 #4
0
파일: http_server.cpp 프로젝트: Adaptv/ribs
inline void http_server::checkPersistent(char *p)
{
    char *conn = strstr(p, CONNECTION);
    char *h1_1 = strstr(p, " HTTP/1.1");
    // HTTP/1.1
    if ((NULL != h1_1 &&
         (NULL == conn ||
          0 != SSTRNCMPI(CONNECTION_CLOSE, conn + SSTRLEN(CONNECTION)))) ||
        // HTTP/1.0
        (NULL == h1_1 &&
         NULL != conn &&
         0 == SSTRNCMPI(CONNECTION_KEEPALIVE, conn + SSTRLEN(CONNECTION))))
        persistent = true;
    else
        persistent = false;
}
예제 #5
0
static void http_server_process_request(char *uri, char *headers) {
    struct http_server_context *ctx = http_server_get_context();
    ctx->headers = headers;
    char *query = strchrnul(uri, '?');
    if (*query)
        *query++ = 0;
    ctx->query = query;
    static const char HTTP[] = "http://";
    if (0 == SSTRNCMP(HTTP, uri)) {
        uri += SSTRLEN(HTTP);
        uri = strchrnul(uri, '/');
    }
    ctx->uri = uri;
    epoll_worker_ignore_events(ctx->fd);
    ctx->server->user_func();
}
예제 #6
0
void http_client_fiber_main(void) {
    struct http_client_context *ctx = (struct http_client_context *)current_ctx->reserved;
    int fd = current_ctx->fd;
    struct epoll_worker_fd_data *fd_data = epoll_worker_fd_map + fd;
    TIMEOUT_HANDLER_REMOVE_FD_DATA(fd_data);

    int persistent = 0;
    epoll_worker_set_last_fd(fd); /* needed in the case where epoll_wait never occured */

    /*
     * write request
     */
    int res;
    for (; (res = vmbuf_write(&ctx->request, fd)) == 0; http_client_yield());
    if (0 > res) {
        LOGGER_PERROR("write");
        CLIENT_ERROR();
    }
    /*
     * HTTP header
     */
    uint32_t eoh_ofs;
    char *data;
    char *eoh;
    res = vmbuf_read(&ctx->response, fd);
    *vmbuf_wloc(&ctx->response) = 0;
    READ_MORE_DATA_STR(NULL == (eoh = strstr(data = vmbuf_data(&ctx->response), CRLFCRLF)));
    eoh_ofs = eoh - data + SSTRLEN(CRLFCRLF);
    *eoh = 0;
    char *p = strstr(data, CONNECTION);
    if (p != NULL) {
        p += SSTRLEN(CONNECTION);
        persistent = (0 == SSTRNCMPI(CONNECTION_CLOSE, p) ? 0 : 1);
    }
    SSTRL(HTTP, "HTTP/");
    if (0 != SSTRNCMP(HTTP, data))
        CLIENT_ERROR();

    p = strchrnul(data, ' ');
    int code = (*p ? atoi(p + 1) : 0);
    if (0 == code)
        CLIENT_ERROR();
    do {
        if (code == 204 || code == 304) /* No Content,  Not Modified */
            break;
        /*
         * content length
         */
        char *content_len_str = strstr(data, CONTENT_LENGTH);
        if (NULL != content_len_str) {
            content_len_str += SSTRLEN(CONTENT_LENGTH);
            size_t content_end = eoh_ofs + atoi(content_len_str);
            READ_MORE_DATA(vmbuf_wlocpos(&ctx->response) < content_end);
            break;
        }
        /*
         * chunked encoding
         */
        char *transfer_encoding_str = strstr(data, TRANSFER_ENCODING);
        if (NULL != transfer_encoding_str &&
                0 == SSTRNCMP(transfer_encoding_str + SSTRLEN(TRANSFER_ENCODING), "chunked")) {
            size_t chunk_start = eoh_ofs;
            size_t data_start = eoh_ofs;
            char *p;
            for (;;) {
                READ_MORE_DATA_STR(*(p = strchrnul((data = vmbuf_data(&ctx->response)) + chunk_start, '\r')) == 0);
                if (0 != SSTRNCMP(CRLF, p))
                    CLIENT_ERROR();
                uint32_t s = strtoul(data + chunk_start, NULL, 16);
                if (0 == s) {
                    vmbuf_wlocset(&ctx->response, data_start);
                    break;
                }
                chunk_start = p - data + SSTRLEN(CRLF);
                size_t chunk_end = chunk_start + s + SSTRLEN(CRLF);
                READ_MORE_DATA(vmbuf_wlocpos(&ctx->response) < chunk_end);
                memmove(vmbuf_data(&ctx->response) + data_start, vmbuf_data(&ctx->response) + chunk_start, s);
                data_start += s;
                chunk_start = chunk_end;
            }
            break;
        }
        /*
         * older versions of HTTP, terminated by disconnect
         */
        for (;; yield()) {
            if ((res = vmbuf_read(&ctx->response, fd)) < 0)
                CLIENT_ERROR();
            if (0 == res)
                break; /* remote side closed connection */
        }
    } while (0);
    ctx->content = vmbuf_data_ofs(&ctx->response, eoh_ofs);
    ctx->content_length = vmbuf_wlocpos(&ctx->response) - eoh_ofs;
    ctx->http_status_code = code;
    vmbuf_data_ofs(&ctx->response, eoh_ofs - SSTRLEN(CRLFCRLF))[0] = CR;
    *vmbuf_wloc(&ctx->response) = 0;
    ctx->persistent = persistent;
    if (!persistent)
        close(fd);
}
예제 #7
0
void http_server_fiber_main(void) {
    struct http_server_context *ctx = http_server_get_context();
    struct http_server *server = ctx->server;
    int fd = ctx->fd;

    char *URI;
    char *headers;
    char *content;
    size_t content_length;
    int res;
    ctx->persistent = 0;

    vmbuf_init(&ctx->request, server->init_request_size);
    vmbuf_init(&ctx->header, server->init_header_size);
    vmbuf_init(&ctx->payload, server->init_payload_size);
    size_t max_req_size = server->max_req_size;

    for (;; http_server_yield()) {
        READ_FROM_SOCKET();
        if (vmbuf_wlocpos(&ctx->request) > MIN_HTTP_REQ_SIZE)
            break;
    }
    do {
        if (0 == SSTRNCMP(GET, vmbuf_data(&ctx->request)) || 0 == SSTRNCMP(HEAD, vmbuf_data(&ctx->request))) {
            /* GET or HEAD */
            while (0 != SSTRNCMP(CRLFCRLF,  vmbuf_wloc(&ctx->request) - SSTRLEN(CRLFCRLF))) {
                http_server_yield();
                READ_FROM_SOCKET();
            }
            /* make sure the string is \0 terminated */
            /* this will overwrite the first CR */
            *(vmbuf_wloc(&ctx->request) - SSTRLEN(CRLFCRLF)) = 0;
            char *p = vmbuf_data(&ctx->request);
            ctx->persistent = check_persistent(p);
            URI = strchrnul(p, ' '); /* can't be NULL GET and HEAD constants have space at the end */
            *URI = 0;
            ++URI; // skip the space
            p = strchrnul(URI, '\r'); /* HTTP/1.0 */
            headers = p;
            if (0 != *headers) /* are headers present? */
                headers += SSTRLEN(CRLF); /* skip the new line */
            *p = 0;
            p = strchrnul(URI, ' '); /* truncate the version part */
            *p = 0; /* \0 at the end of URI */

            ctx->content = NULL;
            ctx->content_len = 0;

            /* minimal parsing and call user function */
            http_server_process_request(URI, headers);
        } else if (0 == SSTRNCMP(POST, vmbuf_data(&ctx->request)) || 0 == SSTRNCMP(PUT, vmbuf_data(&ctx->request))) {
            /* POST or PUT */
            for (;;) {
                *vmbuf_wloc(&ctx->request) = 0;
                /* wait until we have the header */
                if (NULL != (content = strstr(vmbuf_data(&ctx->request), CRLFCRLF)))
                    break;
                http_server_yield();
                READ_FROM_SOCKET();
            }
            *content = 0; /* terminate at the first CR like in GET */
            content += SSTRLEN(CRLFCRLF);
            size_t content_ofs = content - vmbuf_data(&ctx->request);

            if (strstr(vmbuf_data(&ctx->request), EXPECT_100)) {
                vmbuf_sprintf(&ctx->header, "%s %s\r\n\r\n", HTTP_SERVER_VER, HTTP_STATUS_100);
                if (0 > vmbuf_write(&ctx->header, fd)) {
                    close(fd);
                    return;
                }
                vmbuf_reset(&ctx->header);
            }
            ctx->persistent = check_persistent(vmbuf_data(&ctx->request));

            /* parse the content length */
            char *p = strcasestr(vmbuf_data(&ctx->request), CONTENT_LENGTH);
            if (NULL == p) {
                http_server_response(HTTP_STATUS_411, HTTP_CONTENT_TYPE_TEXT_PLAIN);
                break;
            }

            p += SSTRLEN(CONTENT_LENGTH);
            content_length = atoi(p);
            for (;;) {
                if (content_ofs + content_length <= vmbuf_wlocpos(&ctx->request))
                    break;
                http_server_yield();
                READ_FROM_SOCKET();
            }
            p = vmbuf_data(&ctx->request);
            URI = strchrnul(p, ' '); /* can't be NULL PUT and POST constants have space at the end */
            *URI = 0;
            ++URI; /* skip the space */
            p = strchrnul(URI, '\r'); /* HTTP/1.0 */
            headers = p;
            if (0 != *headers) /* are headers present? */
                headers += SSTRLEN(CRLF); /* skip the new line */
            *p = 0;
            p = strchrnul(URI, ' '); /* truncate http version */
            *p = 0; /* \0 at the end of URI */
            ctx->content = vmbuf_data_ofs(&ctx->request, content_ofs);
            *(ctx->content + content_length) = 0;
            ctx->content_len = content_length;

            /* minimal parsing and call user function */
            http_server_process_request(URI, headers);
        } else {
            http_server_response(HTTP_STATUS_501, HTTP_CONTENT_TYPE_TEXT_PLAIN);
            break;
        }
    } while(0);

    if (vmbuf_wlocpos(&ctx->header) > 0) {
        epoll_worker_resume_events(fd);
        http_server_write();
    }

    if (ctx->persistent) {
        struct epoll_worker_fd_data *fd_data = epoll_worker_fd_map + fd;
        fd_data->ctx = server->idle_ctx;
        timeout_handler_add_fd_data(&server->timeout_handler, fd_data);
    } else
        close(fd);
}
예제 #8
0
파일: tdir.c 프로젝트: Nils-TUD/Escape
static void test_canonpath(void) {
	char path[MAX_PATH_LEN];
	size_t count;

	test_caseStart("Testing canonpath");

	setenv("CWD","/");

	count = canonpath(path,sizeof(path),"/");
	test_assertUInt(count,SSTRLEN("/"));
	test_assertStr(path,"/");

	count = canonpath(path,sizeof(path),"/bin/ls");
	test_assertUInt(count,SSTRLEN("/bin/ls"));
	test_assertStr(path,"/bin/ls");

	count = canonpath(path,sizeof(path),"/../bin/../.././home");
	test_assertUInt(count,SSTRLEN("/home"));
	test_assertStr(path,"/home");

	count = canonpath(path,sizeof(path),"bin/..///.././home");
	test_assertUInt(count,SSTRLEN("/home"));
	test_assertStr(path,"/home");

	count = canonpath(path,sizeof(path),"bin/./ls");
	test_assertUInt(count,SSTRLEN("/bin/ls"));
	test_assertStr(path,"/bin/ls");

	setenv("CWD","/home");

	count = canonpath(path,sizeof(path),"hrniels/./scripts");
	test_assertUInt(count,SSTRLEN("/home/hrniels/scripts"));
	test_assertStr(path,"/home/hrniels/scripts");

	setenv("CWD","/home/");

	count = canonpath(path,sizeof(path),"hrniels/./scripts");
	test_assertUInt(count,SSTRLEN("/home/hrniels/scripts"));
	test_assertStr(path,"/home/hrniels/scripts");

	count = canonpath(path,sizeof(path),"..");
	test_assertUInt(count,SSTRLEN("/"));
	test_assertStr(path,"/");

	count = canonpath(path,sizeof(path),"../../.");
	test_assertUInt(count,SSTRLEN("/"));
	test_assertStr(path,"/");

	count = canonpath(path,sizeof(path),"./../bin");
	test_assertUInt(count,SSTRLEN("/bin"));
	test_assertStr(path,"/bin");

	count = canonpath(path,3,"/");
	if(count > 3)
		test_caseFailed("Copied too much");

	count = canonpath(path,8,"/bin/ls");
	if(count > 8)
		test_caseFailed("Copied too much");

	count = canonpath(path,8,"/bin/../home");
	if(count > 8)
		test_caseFailed("Copied too much");

	count = canonpath(path,8,"///../bin/ls");
	if(count > 8)
		test_caseFailed("Copied too much");

	test_caseSucceeded();
}
예제 #9
0
파일: tsort.c 프로젝트: jarn0x/Escape
static void test_qsort(void) {
	test_caseStart("Testing qsort");

	{
		int ints[] = {};
		qsort(ints,ARRAY_SIZE(ints),sizeof(int),intCompare);
	}

	{
		int ints[] = {1,1,1};
		qsort(ints,ARRAY_SIZE(ints),sizeof(int),intCompare);
		test_assertInt(ints[0],1);
		test_assertInt(ints[1],1);
		test_assertInt(ints[2],1);
	}

	{
		int ints[] = {1,2,3};
		qsort(ints,ARRAY_SIZE(ints),sizeof(int),intCompare);
		test_assertInt(ints[0],1);
		test_assertInt(ints[1],2);
		test_assertInt(ints[2],3);
	}

	{
		int ints[] = {6,7,3,4,2,1,5};
		qsort(ints,ARRAY_SIZE(ints),sizeof(int),intCompare);
		test_assertInt(ints[0],1);
		test_assertInt(ints[1],2);
		test_assertInt(ints[2],3);
		test_assertInt(ints[3],4);
		test_assertInt(ints[4],5);
		test_assertInt(ints[5],6);
		test_assertInt(ints[6],7);
	}

	{
		const char *strs[] = {
			"m3/m3-11.png",
			"m3/m3-03.png",
			"m3/m3-09.png",
			"m3/m3-20.png",
			"m3/m3-22.png",
			"m3/m3-17.png",
			"m3/m3-24.png",
			"m3/m3-12.png",
			"m3/m3-04.png",
			"m3/m3-23.png",
			"m3/m3-18.png",
			"m3/m3-01.png",
			"m3/m3-28.png",
			"m3/m3-14.png",
			"m3/m3-07.png",
			"m3/m3-26.png",
			"m3/m3-00.png",
			"m3/m3-05.png",
			"m3/m3-21.png",
			"m3/m3-16.png",
			"m3/m3-25.png",
			"m3/m3-08.png",
			"m3/m3-10.png",
			"m3/m3-02.png",
			"m3/m3-19.png",
			"m3/m3-06.png",
			"m3/m3-13.png",
			"m3/m3-15.png",
			"m3/m3-27.png",
		};
		qsort(strs,ARRAY_SIZE(strs),sizeof(int),strCompare);
		for(size_t i = 0; i < ARRAY_SIZE(strs); ++i) {
			const char *sno = strs[i] + SSTRLEN("m3/m3-");
			int no = atoi(sno);
			test_assertInt(no,i);
		}
	}

	test_caseSucceeded();
}
예제 #10
0
파일: http_server.cpp 프로젝트: Adaptv/ribs
struct basic_epoll_event *http_server::headerClose()
{
    header.memcpy(CRLFCRLF, SSTRLEN(CRLFCRLF));
    return startWrite();
}
예제 #11
0
파일: http_server.cpp 프로젝트: Adaptv/ribs
struct basic_epoll_event *http_server::onRead()
{
    int res = inbuf.read(fd);
    if (0 >= res)
        return this->close(); // remote side closed or other error occured
    if (inbuf.wlocpos() > max_req_size)
        return response(HTTP_STATUS_413, HTTP_CONTENT_TYPE_TEXT_PLAIN);
    // parse http request
    //
    if (inbuf.wlocpos() > MIN_HTTP_REQ_SIZE)
    {
        if (0 == SSTRNCMP(GET, inbuf.data()) || 0 == SSTRNCMP(HEAD, inbuf.data()))
        {
            if (0 == SSTRNCMP(CRLFCRLF,  inbuf.wloc() - SSTRLEN(CRLFCRLF)))
            {
                // GET or HEAD requests
                // make sure the string is \0 terminated
                // this will overwrite the first CR
                *(inbuf.wloc() - SSTRLEN(CRLFCRLF)) = 0;
                char *p = inbuf.data();
                checkPersistent(p);
                URI = strchrnul(p, ' '); // can't be NULL GET and HEAD constants have space at the end
                *URI = 0;
                ++URI; // skip the space
                p = strchrnul(URI, '\r'); // HTTP/1.0
                headers = p;
                if (0 != *headers) // are headers present?
                    headers += SSTRLEN(CRLF); // skip the new line
                *p = 0;
                p = strchrnul(URI, ' '); // truncate the version part
                *p = 0; // \0 at the end of URI
                content = NULL;
                content_length = 0;
                return process_request();
            }
        } else if (0 == SSTRNCMP(POST, inbuf.data()) || 0 == SSTRNCMP(PUT, inbuf.data()))
        {
            // POST
            if (0 == eoh)
            {
                *inbuf.wloc() = 0;
                content = strstr(inbuf.data(), CRLFCRLF);
                if (NULL != content)
                {
                    eoh = content - inbuf.data() + SSTRLEN(CRLFCRLF);
                    *content = 0; // terminate at the first CR like in GET
                    content += SSTRLEN(CRLFCRLF);
                    if (strstr(inbuf.data(), EXPECT_100))
                    {
                        header.sprintf("%s %s%s", HTTP_SERVER_VER, HTTP_STATUS_100, CRLFCRLF);
                        if (0 > header.write(fd))
                            return this->close();
                        header.reset();
                    }
                    checkPersistent(inbuf.data());
                        
                    // parse the content length
                    char *p = strcasestr(inbuf.data(), CONTENT_LENGTH);
                    if (NULL == p)
                        return response(HTTP_STATUS_411, HTTP_CONTENT_TYPE_TEXT_PLAIN);
                        
                    p += SSTRLEN(CONTENT_LENGTH);
                    content_length = atoi(p);
                } else
                    return epoll::yield(epoll::server_timeout_chain, this); // back to epoll, wait for more data
            } else
                content = inbuf.data() + eoh;
                
            if (content + content_length <= inbuf.wloc())
            {
                // POST or PUT requests
                char *p = inbuf.data();
                URI = strchrnul(p, ' '); // can't be NULL PUT and POST constants have space at the end
                *URI = 0;
                ++URI; // skip the space
                p = strchrnul(URI, '\r'); // HTTP/1.0
                headers = p;
                if (0 != *headers) // are headers present?
                    headers += SSTRLEN(CRLF); // skip the new line
                *p = 0;
                p = strchrnul(URI, ' '); // truncate http version
                *p = 0; // \0 at the end of URI
                *(content + content_length) = 0;
                return process_request();
            }
        } else
        {
            return response(HTTP_STATUS_501, HTTP_CONTENT_TYPE_TEXT_PLAIN);
        }
    }
    // wait for more data
    return epoll::yield(epoll::server_timeout_chain, this);
}