Esempio n. 1
0
/* **********************************
 * Websocket
 * **********************************/
static int do_ws_handshake(evhtp_request_t *req) {
    const char *upgrade = evhtp_header_find(req->headers_in, "Upgrade");
    const char *connection = evhtp_header_find(req->headers_in, "Connection");
    const char *ws_key = evhtp_header_find(req->headers_in, "Sec-WebSocket-Key");

    if (upgrade && connection && ws_key) {
        if (!strstrcase(upgrade, "websocket") ||
            !strstrcase(connection, "Upgrade")){
            return EVHTP_RES_ERROR;
        }
        static const char *magic = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
        unsigned char *str = calloc(strlen(ws_key)+strlen(magic)+1, sizeof(unsigned char));

        strcpy((char *)str, ws_key);
        strcat((char *)str, magic);

        unsigned char hash[SHA_DIGEST_LENGTH];
        SHA1(str, strlen((char *)str), hash);

        free(str);

        char ws_accept[29];
        ws_accept[28] = '\0';
        base64encode(&hash[0], sizeof(hash), &ws_accept[0], sizeof(ws_accept)-1);

        ws_headers_add_header(req->headers_out, "Connection", "Upgrade" );
        ws_headers_add_header(req->headers_out, "Sec-WebSocket-Accept", &ws_accept[0]);
        ws_headers_add_header(req->headers_out, "Upgrade", "websocket");
        evhtp_send_reply(req, EVHTP_RES_SWITCH_PROTO);
        return EVHTP_RES_SWITCH_PROTO;
    }
    return EVHTP_RES_OK;
}
Esempio n. 2
0
int binary_parse(evhtp_request_t *req, const char *content_type, const char *address, const char *buff, int post_size)
{
    int err_no = 0;
    if(is_img(content_type) != 1)
    {
        LOG_PRINT(LOG_DEBUG, "fileType[%s] is Not Supported!", content_type);
        LOG_PRINT(LOG_ERROR, "%s fail post type", address);
        err_no = 1;
        goto done;
    }
    char md5sum[33];
    evthr_t *thread = get_request_thr(req);
    thr_arg_t *thr_arg = (thr_arg_t *)evthr_get_aux(thread);
    const char *filename = evhtp_header_find(req->headers_in, "zimg-filename");
    LOG_PRINT(LOG_DEBUG, "Begin to Save Image %s...", filename);
    if(save_img(thr_arg, filename, buff, post_size, md5sum) == -1)
    {
        LOG_PRINT(LOG_DEBUG, "Image Save Failed!");
        LOG_PRINT(LOG_ERROR, "%s fail post save", address);
        goto done;
    }
    err_no = -1;
    LOG_PRINT(LOG_INFO, "%s succ post pic:%s size:%d", address, md5sum, post_size);
    json_return(req, err_no, md5sum, post_size);

done:
    return err_no;
}
Esempio n. 3
0
static void
send_reply_header(evhtp_request_t * req, const char * header) {
    evbuf_t   * buf   = evbuffer_new();
    const char* found = evhtp_header_find(req->headers_in, header);

    evhtp_send_reply_chunk_start(req, EVHTP_RES_OK);
    evbuffer_add(buf, found, strlen(found));
    evhtp_send_reply_chunk(req, buf);

    evbuffer_drain(buf, -1);

    evhtp_send_reply_chunk_end(req);
    evbuffer_free(buf);
}
Esempio n. 4
0
const std::string
zxy_get_http_header(
        zxy_request_context *context,
        const std::string& name
        )
{
    std::string result;
    evhtp_headers_t *headers = context->request->headers_in;
    const char *header_val = evhtp_header_find(headers, name.c_str());
    if ( header_val != NULL )
    {
        result = header_val;
    }
    return result;
}
Esempio n. 5
0
bool zxy_get_http_header(
        zxy_request_context *context,
        const std::string& key,
        std::string& value
        )
{
    bool ret = false;
    evhtp_headers_t *headers = context->request->headers_in;
    const char *header_val = evhtp_header_find(headers, key.c_str());
    if ( header_val != NULL )
    {
        ret = true;
        value = header_val;
    }
    return ret;
}
Esempio n. 6
0
/**
 * @brief zimg_etag_set set zimg response etag
 *
 * @param request the request of evhtp
 * @param buff response body buffer
 * @param len body buffer len
 *
 * @return 1 for set true and 2 for 304
 */
int zimg_etag_set(evhtp_request_t *request, char *buff, size_t len)
{
    int result = 1;
    LOG_PRINT(LOG_DEBUG, "Begin to Caculate MD5...");
    md5_state_t mdctx;
    md5_byte_t md_value[16];
    char md5sum[33];
    int i;
    int h, l;
    md5_init(&mdctx);
    md5_append(&mdctx, (const unsigned char*)(buff), len);
    md5_finish(&mdctx, md_value);

    for(i=0; i<16; ++i)
    {
        h = md_value[i] & 0xf0;
        h >>= 4;
        l = md_value[i] & 0x0f;
        md5sum[i * 2] = (char)((h >= 0x0 && h <= 0x9) ? (h + 0x30) : (h + 0x57));
        md5sum[i * 2 + 1] = (char)((l >= 0x0 && l <= 0x9) ? (l + 0x30) : (l + 0x57));
    }
    md5sum[32] = '\0';
    LOG_PRINT(LOG_DEBUG, "md5: %s", md5sum);

    const char *etag_var = evhtp_header_find(request->headers_in, "If-None-Match");
    LOG_PRINT(LOG_DEBUG, "If-None-Match: %s", etag_var);
    if(etag_var == NULL)
    {
        evhtp_headers_add_header(request->headers_out, evhtp_header_new("Etag", md5sum, 0, 1));
    }
    else
    {
        if(strncmp(md5sum, etag_var, 32) == 0)
        {
            result = 2;
        }
        else
        {
            evhtp_headers_add_header(request->headers_out, evhtp_header_new("Etag", md5sum, 0, 1));
        }
    }
    return result;
}
int
mimetype_normalizer_int(evhtp_request_t *req, const char *header) {
    const char * accept_h = NULL;

    /* Search the HTTP headers for the 'accept:' tag */
    if ((accept_h = evhtp_header_find(req->headers_in, header))) {
        if (strncmp("application/json", accept_h, strlen("application/json")) == 0) {
            return TYPE_APP_JSON;
        } else if (strncmp("application/xml", accept_h, strlen("application/xml")) == 0) {
            return TYPE_APP_XML;
        } else if (strncmp("application/xacml+xml", accept_h, strlen("application/xacml+xml")) == 0) {
            return TYPE_APP_XACML_XML;
        } else if (strncmp("application/xacml+json", accept_h, strlen("application/xacml+json")) == 0) {
            return TYPE_APP_XACML_JSON;
        } else {
            return TYPE_APP_UNKNOWN;
        }
    }
    /* The default answer is *//* */
    return TYPE_APP_UNKNOWN;
}
Esempio n. 8
0
/**
 * @brief get_request_cb The callback function of get a image request.
 *
 * @param req The request with a list of params and the md5 of image.
 * @param arg It is not useful.
 */
void get_request_cb(evhtp_request_t *req, void *arg)
{
    char *md5 = NULL, *fmt = NULL, *type = NULL;
    zimg_req_t *zimg_req = NULL;
	char *buff = NULL;
	size_t len;

    evhtp_connection_t *ev_conn = evhtp_request_get_connection(req);
    struct sockaddr *saddr = ev_conn->saddr;
    struct sockaddr_in *ss = (struct sockaddr_in *)saddr;
    char address[16];

    const char *xff_address = evhtp_header_find(req->headers_in, "X-Forwarded-For");
    if(xff_address)
    {
        inet_aton(xff_address, &ss->sin_addr);
    }
    strncpy(address, inet_ntoa(ss->sin_addr), 16);

    int req_method = evhtp_request_get_method(req);
    if(req_method >= 16)
        req_method = 16;
    LOG_PRINT(LOG_DEBUG, "Method: %d", req_method);
    if(strcmp(method_strmap[req_method], "POST") == 0)
    {
        LOG_PRINT(LOG_DEBUG, "POST Request.");
        post_request_cb(req, NULL);
        return;
    }
	else if(strcmp(method_strmap[req_method], "GET") != 0)
    {
        LOG_PRINT(LOG_DEBUG, "Request Method Not Support.");
        LOG_PRINT(LOG_INFO, "%s refuse method", address);
        goto err;
    }

    if(settings.down_access != NULL)
    {
        int acs = zimg_access_inet(settings.down_access, ss->sin_addr.s_addr);
        LOG_PRINT(LOG_DEBUG, "access check: %d", acs);

        if(acs == ZIMG_FORBIDDEN)
        {
            LOG_PRINT(LOG_DEBUG, "check access: ip[%s] forbidden!", address);
            LOG_PRINT(LOG_INFO, "%s refuse get forbidden", address);
            goto forbidden;
        }
        else if(acs == ZIMG_ERROR)
        {
            LOG_PRINT(LOG_DEBUG, "check access: check ip[%s] failed!", address);
            LOG_PRINT(LOG_ERROR, "%s fail get access", address);
            goto err;
        }
    }

	const char *uri;
	uri = req->uri->path->full;

    if(strlen(uri) == 1 && uri[0] == '/')
    {
        LOG_PRINT(LOG_DEBUG, "Root Request.");
        int fd = -1;
        struct stat st;
        if((fd = open(settings.root_path, O_RDONLY)) == -1)
        {
            LOG_PRINT(LOG_DEBUG, "Root_page Open Failed. Return Default Page.");
            evbuffer_add_printf(req->buffer_out, "<html>\n<body>\n<h1>\nWelcome To zimg World!</h1>\n</body>\n</html>\n");
        }
        else
        {
            if (fstat(fd, &st) < 0)
            {
                /* Make sure the length still matches, now that we
                 * opened the file :/ */
                LOG_PRINT(LOG_DEBUG, "Root_page Length fstat Failed. Return Default Page.");
                evbuffer_add_printf(req->buffer_out, "<html>\n<body>\n<h1>\nWelcome To zimg World!</h1>\n</body>\n</html>\n");
            }
            else
            {
                evbuffer_add_file(req->buffer_out, fd, 0, st.st_size);
            }
        }
        //evbuffer_add_printf(req->buffer_out, "<html>\n </html>\n");
        evhtp_headers_add_header(req->headers_out, evhtp_header_new("Server", settings.server_name, 0, 1));
        evhtp_headers_add_header(req->headers_out, evhtp_header_new("Content-Type", "text/html", 0, 0));
        evhtp_send_reply(req, EVHTP_RES_OK);
        LOG_PRINT(LOG_DEBUG, "============get_request_cb() DONE!===============");
        LOG_PRINT(LOG_INFO, "%s succ root page", address);
        goto done;
    }

    if(strstr(uri, "favicon.ico"))
    {
        LOG_PRINT(LOG_DEBUG, "favicon.ico Request, Denied.");
        evhtp_headers_add_header(req->headers_out, evhtp_header_new("Server", settings.server_name, 0, 1));
        evhtp_headers_add_header(req->headers_out, evhtp_header_new("Content-Type", "text/html", 0, 0));
        zimg_headers_add(req, settings.headers);
        evhtp_send_reply(req, EVHTP_RES_OK);
        goto done;
    }
	LOG_PRINT(LOG_DEBUG, "Got a GET request for <%s>",  uri);

	/* Don't allow any ".."s in the path, to avoid exposing stuff outside
	 * of the docroot.  This test is both overzealous and underzealous:
	 * it forbids aceptable paths like "/this/one..here", but it doesn't
	 * do anything to prevent symlink following." */
	if (strstr(uri, ".."))
    {
        LOG_PRINT(LOG_DEBUG, "attempt to upper dir!");
        LOG_PRINT(LOG_INFO, "%s refuse directory", address);
		goto forbidden;
    }

    size_t md5_len = strlen(uri) + 1;
    md5 = (char *)malloc(md5_len);
    if(md5 == NULL)
    {
        LOG_PRINT(LOG_DEBUG, "md5 malloc failed!");
        LOG_PRINT(LOG_ERROR, "%s fail malloc", address);
        goto err;
    }
    if(uri[0] == '/')
        str_lcpy(md5, uri+1, md5_len);
    else
        str_lcpy(md5, uri, md5_len);
	LOG_PRINT(LOG_DEBUG, "md5 of request is <%s>",  md5);
    if(is_md5(md5) == -1)
    {
        LOG_PRINT(LOG_DEBUG, "Url is Not a zimg Request.");
        LOG_PRINT(LOG_INFO, "%s refuse url illegal", address);
        goto err;
    }
	/* This holds the content we're sending. */

    evthr_t *thread = get_request_thr(req);
    thr_arg_t *thr_arg = (thr_arg_t *)evthr_get_aux(thread);

    int width, height, proportion, gray, x, y, rotate, quality, sv;
    width = 0;
    height = 0;
    proportion = 1;
    gray = 0;
    x = -1;
    y = -1;
    rotate = 0;
    quality = 0;
    sv = 0;

    evhtp_kvs_t *params;
    params = req->uri->query;
    if(params != NULL)
    {
        if(settings.disable_args != 1)
        {
            const char *str_w = evhtp_kv_find(params, "w");
            const char *str_h = evhtp_kv_find(params, "h");
            width = (str_w) ? atoi(str_w) : 0;
            height = (str_h) ? atoi(str_h) : 0;

            const char *str_p = evhtp_kv_find(params, "p");
            proportion = (str_p) ? atoi(str_p) : 1;

            const char *str_g = evhtp_kv_find(params, "g");
            gray = (str_g) ? atoi(str_g) : 0;

            const char *str_x = evhtp_kv_find(params, "x");
            const char *str_y = evhtp_kv_find(params, "y");
            x = (str_x) ? atoi(str_x) : -1;
            y = (str_y) ? atoi(str_y) : -1;

            if(x != -1 || y != -1)
            {
                proportion = 1;
            }

            const char *str_r = evhtp_kv_find(params, "r");
            rotate = (str_r) ? atoi(str_r) : 0;

            const char *str_q = evhtp_kv_find(params, "q");
            quality = (str_q) ? atoi(str_q) : 0;

            const char *str_f = evhtp_kv_find(params, "f");
            if(str_f)
            {
                size_t fmt_len = strlen(str_f) + 1;
                fmt = (char *)malloc(fmt_len);
                if(fmt != NULL)
                    str_lcpy(fmt, str_f, fmt_len);
                LOG_PRINT(LOG_DEBUG, "fmt = %s", fmt);
            }
        }

        if(settings.disable_type != 1)
        {
            const char *str_t = evhtp_kv_find(params, "t");
            if(str_t)
            {
                size_t type_len = strlen(str_t) + 1;
                type = (char *)malloc(type_len);
                if(type != NULL)
                    str_lcpy(type, str_t, type_len);
                LOG_PRINT(LOG_DEBUG, "type = %s", type);
            }
        }
    }
    else
    {
        sv = 1;
    }

    quality = (quality != 0 ? quality : settings.quality);
    zimg_req = (zimg_req_t *)malloc(sizeof(zimg_req_t)); 
    if(zimg_req == NULL)
    {
        LOG_PRINT(LOG_DEBUG, "zimg_req malloc failed!");
        LOG_PRINT(LOG_ERROR, "%s fail malloc", address);
        goto err;
    }
    zimg_req -> md5 = md5;
    zimg_req -> type = type;
    zimg_req -> width = width;
    zimg_req -> height = height;
    zimg_req -> proportion = proportion;
    zimg_req -> gray = gray;
    zimg_req -> x = x;
    zimg_req -> y = y;
    zimg_req -> rotate = rotate;
    zimg_req -> quality = quality;
    zimg_req -> fmt = (fmt != NULL ? fmt : settings.format);
    zimg_req -> sv = sv;
    zimg_req -> thr_arg = thr_arg;

    int get_img_rst = -1;
    get_img_rst = settings.get_img(zimg_req, req);

    if(get_img_rst == -1)
    {
        LOG_PRINT(LOG_DEBUG, "zimg Requset Get Image[MD5: %s] Failed!", zimg_req->md5);
        if(type)
            LOG_PRINT(LOG_ERROR, "%s fail pic:%s t:%s", address, md5, type);
        else
            LOG_PRINT(LOG_ERROR, "%s fail pic:%s w:%d h:%d p:%d g:%d x:%d y:%d r:%d q:%d f:%s",
                address, md5, width, height, proportion, gray, x, y, rotate, quality, zimg_req->fmt); 
        goto err;
    }
    if(get_img_rst == 2)
    {
        LOG_PRINT(LOG_DEBUG, "Etag Matched Return 304 EVHTP_RES_NOTMOD.");
        if(type)
            LOG_PRINT(LOG_INFO, "%s succ 304 pic:%s t:%s", address, md5, type);
        else
            LOG_PRINT(LOG_INFO, "%s succ 304 pic:%s w:%d h:%d p:%d g:%d x:%d y:%d r:%d q:%d f:%s",
                address, md5, width, height, proportion, gray, x, y, rotate, quality, zimg_req->fmt); 
        evhtp_send_reply(req, EVHTP_RES_NOTMOD);
        goto done;
    }

    len = evbuffer_get_length(req->buffer_out);
    LOG_PRINT(LOG_DEBUG, "get buffer length: %d", len);

    LOG_PRINT(LOG_DEBUG, "Got the File!");
    evhtp_headers_add_header(req->headers_out, evhtp_header_new("Server", settings.server_name, 0, 1));
    evhtp_headers_add_header(req->headers_out, evhtp_header_new("Content-Type", "image/jpeg", 0, 0));
    zimg_headers_add(req, settings.headers);
    evhtp_send_reply(req, EVHTP_RES_OK);
    if(type)
        LOG_PRINT(LOG_INFO, "%s succ pic:%s t:%s size:%d", address, md5, type, len); 
    else
        LOG_PRINT(LOG_INFO, "%s succ pic:%s w:%d h:%d p:%d g:%d x:%d y:%d r:%d q:%d f:%s size:%d", 
                address, md5, width, height, proportion, gray, x, y, rotate, quality, zimg_req->fmt, 
                len);
    LOG_PRINT(LOG_DEBUG, "============get_request_cb() DONE!===============");
    goto done;

forbidden:
    evbuffer_add_printf(req->buffer_out, "<html><body><h1>403 Forbidden!</h1></body></html>"); 
    evhtp_headers_add_header(req->headers_out, evhtp_header_new("Server", settings.server_name, 0, 1));
    evhtp_headers_add_header(req->headers_out, evhtp_header_new("Content-Type", "text/html", 0, 0));
    evhtp_send_reply(req, EVHTP_RES_FORBIDDEN);
    LOG_PRINT(LOG_DEBUG, "============get_request_cb() FORBIDDEN!===============");
    goto done;

err:
    evbuffer_add_printf(req->buffer_out, "<html><body><h1>404 Not Found!</h1></body></html>");
    evhtp_headers_add_header(req->headers_out, evhtp_header_new("Server", settings.server_name, 0, 1));
    evhtp_headers_add_header(req->headers_out, evhtp_header_new("Content-Type", "text/html", 0, 0));
    evhtp_send_reply(req, EVHTP_RES_NOTFOUND);
    LOG_PRINT(LOG_DEBUG, "============get_request_cb() ERROR!===============");

done:
    free(fmt);
    free(md5);
    free(type);
    free(zimg_req);
    free(buff);
}
Esempio n. 9
0
/**
 * @brief post_request_cb The callback function of a POST request to upload a image.
 *
 * @param req The request with image buffer.
 * @param arg It is not useful.
 */
void post_request_cb(evhtp_request_t *req, void *arg)
{
    int post_size = 0;
    char *buff = NULL;
    int err_no = 0;
    int ret_json = 1;

    evhtp_connection_t *ev_conn = evhtp_request_get_connection(req);
    struct sockaddr *saddr = ev_conn->saddr;
    struct sockaddr_in *ss = (struct sockaddr_in *)saddr;
    char address[16];

    const char *xff_address = evhtp_header_find(req->headers_in, "X-Forwarded-For");
    if(xff_address)
    {
        inet_aton(xff_address, &ss->sin_addr);
    }
    strncpy(address, inet_ntoa(ss->sin_addr), 16);

    int req_method = evhtp_request_get_method(req);
    if(req_method >= 16)
        req_method = 16;
    LOG_PRINT(LOG_DEBUG, "Method: %d", req_method);
    if(strcmp(method_strmap[req_method], "POST") != 0)
    {
        LOG_PRINT(LOG_DEBUG, "Request Method Not Support.");
        LOG_PRINT(LOG_INFO, "%s refuse post method", address);
        err_no = 2;
        goto err;
    }

    if(settings.up_access != NULL)
    {
        int acs = zimg_access_inet(settings.up_access, ss->sin_addr.s_addr);
        LOG_PRINT(LOG_DEBUG, "access check: %d", acs);
        if(acs == ZIMG_FORBIDDEN)
        {
            LOG_PRINT(LOG_DEBUG, "check access: ip[%s] forbidden!", address);
            LOG_PRINT(LOG_INFO, "%s refuse post forbidden", address);
            err_no = 3;
            goto forbidden;
        }
        else if(acs == ZIMG_ERROR)
        {
            LOG_PRINT(LOG_DEBUG, "check access: check ip[%s] failed!", address);
            LOG_PRINT(LOG_ERROR, "%s fail post access %s", address);
            err_no = 0;
            goto err;
        }
    }

    const char *content_len = evhtp_header_find(req->headers_in, "Content-Length");
    if(!content_len)
    {
        LOG_PRINT(LOG_DEBUG, "Get Content-Length error!");
        LOG_PRINT(LOG_ERROR, "%s fail post content-length", address);
        err_no = 5;
        goto err;
    }
    post_size = atoi(content_len);
    if(post_size <= 0)
    {
        LOG_PRINT(LOG_DEBUG, "Image Size is Zero!");
        LOG_PRINT(LOG_ERROR, "%s fail post empty", address);
        err_no = 5;
        goto err;
    }
    if(post_size > settings.max_size)
    {
        LOG_PRINT(LOG_DEBUG, "Image Size Too Large!");
        LOG_PRINT(LOG_ERROR, "%s fail post large", address);
        err_no = 7;
        goto err;
    }
    const char *content_type = evhtp_header_find(req->headers_in, "Content-Type");
    if(!content_type)
    {
        LOG_PRINT(LOG_DEBUG, "Get Content-Type error!");
        LOG_PRINT(LOG_ERROR, "%s fail post content-type", address);
        err_no = 6;
        goto err;
    }
	evbuf_t *buf;
    buf = req->buffer_in;
    buff = (char *)malloc(post_size);
    if(buff == NULL)
    {
        LOG_PRINT(LOG_DEBUG, "buff malloc failed!");
        LOG_PRINT(LOG_ERROR, "%s fail malloc buff", address);
        err_no = 0;
        goto err;
    }
    int rmblen, evblen;
    if(evbuffer_get_length(buf) <= 0)
    {
        LOG_PRINT(LOG_DEBUG, "Empty Request!");
        LOG_PRINT(LOG_ERROR, "%s fail post empty", address);
        err_no = 4;
        goto err;
    }
    while((evblen = evbuffer_get_length(buf)) > 0)
    {
        LOG_PRINT(LOG_DEBUG, "evblen = %d", evblen);
        rmblen = evbuffer_remove(buf, buff, evblen);
        LOG_PRINT(LOG_DEBUG, "rmblen = %d", rmblen);
        if(rmblen < 0)
        {
            LOG_PRINT(LOG_DEBUG, "evbuffer_remove failed!");
            LOG_PRINT(LOG_ERROR, "%s fail post parse", address);
            err_no = 4;
            goto err;
        }
    }
    if(strstr(content_type, "multipart/form-data") == NULL)
    {
        err_no = binary_parse(req, content_type, address, buff, post_size);
    }
    else
    {
        ret_json = 0;
        err_no = multipart_parse(req, content_type, address, buff, post_size);
    }
    if(err_no != -1)
    {
        goto err;
    }
    evhtp_headers_add_header(req->headers_out, evhtp_header_new("Server", settings.server_name, 0, 1));
    evhtp_send_reply(req, EVHTP_RES_OK);
    LOG_PRINT(LOG_DEBUG, "============post_request_cb() DONE!===============");
    goto done;

forbidden:
    json_return(req, err_no, NULL, 0);
    evhtp_headers_add_header(req->headers_out, evhtp_header_new("Server", settings.server_name, 0, 1));
    evhtp_send_reply(req, EVHTP_RES_OK);
    LOG_PRINT(LOG_DEBUG, "============post_request_cb() FORBIDDEN!===============");
    goto done;

err:
    if(ret_json == 0)
    {
        evbuffer_add_printf(req->buffer_out, "<h1>Upload Failed!</h1></body></html>"); 
        evhtp_headers_add_header(req->headers_out, evhtp_header_new("Content-Type", "text/html", 0, 0));
    }
    else
    {
        json_return(req, err_no, NULL, 0);
    }
    evhtp_headers_add_header(req->headers_out, evhtp_header_new("Server", settings.server_name, 0, 1));
    evhtp_send_reply(req, EVHTP_RES_OK);
    LOG_PRINT(LOG_DEBUG, "============post_request_cb() ERROR!===============");

done:
    free(buff);
}
Esempio n. 10
0
/**
 * @brief admin_request_cb the callback function of admin requests
 *
 * @param req the evhtp request
 * @param arg the arg of request
 */
void admin_request_cb(evhtp_request_t *req, void *arg)
{
    char md5[33];

    evhtp_connection_t *ev_conn = evhtp_request_get_connection(req);
    struct sockaddr *saddr = ev_conn->saddr;
    struct sockaddr_in *ss = (struct sockaddr_in *)saddr;
    char address[16];

    const char *xff_address = evhtp_header_find(req->headers_in, "X-Forwarded-For");
    if(xff_address)
    {
        inet_aton(xff_address, &ss->sin_addr);
    }
    strncpy(address, inet_ntoa(ss->sin_addr), 16);

    int req_method = evhtp_request_get_method(req);
    if(req_method >= 16)
        req_method = 16;
    LOG_PRINT(LOG_DEBUG, "Method: %d", req_method);
    if(strcmp(method_strmap[req_method], "POST") == 0)
    {
        LOG_PRINT(LOG_DEBUG, "POST Request.");
        post_request_cb(req, NULL);
        return;
    }
	else if(strcmp(method_strmap[req_method], "GET") != 0)
    {
        LOG_PRINT(LOG_DEBUG, "Request Method Not Support.");
        LOG_PRINT(LOG_INFO, "%s refuse method", address);
        goto err;
    }

    if(settings.admin_access != NULL)
    {
        int acs = zimg_access_inet(settings.admin_access, ss->sin_addr.s_addr);
        LOG_PRINT(LOG_DEBUG, "access check: %d", acs);

        if(acs == ZIMG_FORBIDDEN)
        {
            LOG_PRINT(LOG_DEBUG, "check access: ip[%s] forbidden!", address);
            LOG_PRINT(LOG_INFO, "%s refuse admin forbidden", address);
            goto forbidden;
        }
        else if(acs == ZIMG_ERROR)
        {
            LOG_PRINT(LOG_DEBUG, "check access: check ip[%s] failed!", address);
            LOG_PRINT(LOG_ERROR, "%s fail admin access", address);
            goto err;
        }
    }

	const char *uri;
	uri = req->uri->path->full;

    if(strstr(uri, "favicon.ico"))
    {
        LOG_PRINT(LOG_DEBUG, "favicon.ico Request, Denied.");
        evhtp_headers_add_header(req->headers_out, evhtp_header_new("Server", settings.server_name, 0, 1));
        evhtp_headers_add_header(req->headers_out, evhtp_header_new("Content-Type", "text/html", 0, 0));
        zimg_headers_add(req, settings.headers);
        evhtp_send_reply(req, EVHTP_RES_OK);
        return;
    }

	LOG_PRINT(LOG_DEBUG, "Got a Admin request for <%s>",  uri);
    int t;
    evhtp_kvs_t *params;
    params = req->uri->query;
    if(!params)
    {
        LOG_PRINT(LOG_DEBUG, "Admin Root Request.");
        int fd = -1;
        struct stat st;
        //TODO: use admin_path
        if((fd = open(settings.admin_path, O_RDONLY)) == -1)
        {
            LOG_PRINT(LOG_DEBUG, "Admin_page Open Failed. Return Default Page.");
            evbuffer_add_printf(req->buffer_out, "<html>\n<body>\n<h1>\nWelcome To zimg Admin!</h1>\n</body>\n</html>\n");
        }
        else
        {
            if (fstat(fd, &st) < 0)
            {
                /* Make sure the length still matches, now that we
                 * opened the file :/ */
                LOG_PRINT(LOG_DEBUG, "Root_page Length fstat Failed. Return Default Page.");
                evbuffer_add_printf(req->buffer_out, "<html>\n<body>\n<h1>\nWelcome To zimg Admin!</h1>\n</body>\n</html>\n");
            }
            else
            {
                evbuffer_add_file(req->buffer_out, fd, 0, st.st_size);
            }
        }
        //evbuffer_add_printf(req->buffer_out, "<html>\n </html>\n");
        evhtp_headers_add_header(req->headers_out, evhtp_header_new("Server", settings.server_name, 0, 1));
        evhtp_headers_add_header(req->headers_out, evhtp_header_new("Content-Type", "text/html", 0, 0));
        evhtp_send_reply(req, EVHTP_RES_OK);
        LOG_PRINT(LOG_DEBUG, "============admin_request_cb() DONE!===============");
        LOG_PRINT(LOG_INFO, "%s succ admin root page", address);
        return;
    }
    else
    {
        const char *str_md5, *str_t;
        str_md5 = evhtp_kv_find(params, "md5");
        if(str_md5 == NULL)
        {
            LOG_PRINT(LOG_DEBUG, "md5() = NULL return");
            goto err;
        }

        str_lcpy(md5, str_md5, sizeof(md5));
        if(is_md5(md5) == -1)
        {
            LOG_PRINT(LOG_DEBUG, "Admin Request MD5 Error.");
            LOG_PRINT(LOG_INFO, "%s refuse admin url illegal", address);
            goto err;
        }
        str_t = evhtp_kv_find(params, "t");
        LOG_PRINT(LOG_DEBUG, "md5() = %s; t() = %s;", str_md5, str_t);
        t = (str_t) ? atoi(str_t) : 0;
    }

    evthr_t *thread = get_request_thr(req);
    thr_arg_t *thr_arg = (thr_arg_t *)evthr_get_aux(thread);

    int admin_img_rst = -1;
    admin_img_rst = settings.admin_img(req, thr_arg, md5, t);

    if(admin_img_rst == -1)
    {
        evbuffer_add_printf(req->buffer_out, 
            "<html><body><h1>Admin Command Failed!</h1> \
            <p>MD5: %s</p> \
            <p>Command Type: %d</p> \
            <p>Command Failed.</p> \
            </body></html>",
            md5, t);
        LOG_PRINT(LOG_ERROR, "%s fail admin pic:%s t:%d", address, md5, t); 
        evhtp_headers_add_header(req->headers_out, evhtp_header_new("Content-Type", "text/html", 0, 0));
    }
Esempio n. 11
0
const char *wshtp_request_get_header(wshtp_conn_t *conn, const char *key) {
    return evhtp_header_find(conn->request->headers_in, key);
}
Esempio n. 12
0
/**
 * @brief post_request_cb The callback function of a POST request to upload a image.
 *
 * @param req The request with image buffer.
 * @param arg It is not useful.
 */
void post_request_cb(evhtp_request_t *req, void *arg)
{
    int post_size = 0;
    char *boundary = NULL, *boundary_end = NULL;
    int boundary_len = 0;
    char *fileName = NULL;
    char *boundaryPattern = NULL;
    char *buff = NULL;

    int req_method = evhtp_request_get_method(req);
    if(req_method >= 16)
        req_method = 16;
    LOG_PRINT(LOG_INFO, "Method: %d", req_method);
    if(strcmp(method_strmap[req_method], "POST") != 0)
    {
        LOG_PRINT(LOG_INFO, "Request Method Not Support.");
        goto err;
    }


    const char *content_len = evhtp_header_find(req->headers_in, "Content-Length");
    post_size = atoi(content_len);
    const char *content_type = evhtp_header_find(req->headers_in, "Content-Type");
    if(strstr(content_type, "multipart/form-data") == 0)
    {
        LOG_PRINT(LOG_ERROR, "POST form error!");
        goto err;
    }
    else if(strstr(content_type, "boundary") == 0)
    {
        LOG_PRINT(LOG_ERROR, "boundary NOT found!");
        goto err;
    }

    boundary = strchr(content_type, '=');
    boundary++;
    boundary_len = strlen(boundary);

    if (boundary[0] == '"') 
    {
        boundary++;
        boundary_end = strchr(boundary, '"');
        if (!boundary_end) 
        {
            LOG_PRINT(LOG_ERROR, "Invalid boundary in multipart/form-data POST data");
            goto err;
        }
    } 
    else 
    {
        /* search for the end of the boundary */
        boundary_end = strpbrk(boundary, ",;");
    }
    if (boundary_end) 
    {
        boundary_end[0] = '\0';
        boundary_len = boundary_end-boundary;
    }

    LOG_PRINT(LOG_INFO, "boundary Find. boundary = %s", boundary);
            
    /* 依靠evbuffer自己实现php处理函数 */
	evbuf_t *buf;
    buf = req->buffer_in;
    buff = (char *)malloc(post_size);
    int rmblen, evblen;
    int img_size = 0;

    if(evbuffer_get_length(buf) <= 0)
    {
        LOG_PRINT(LOG_ERROR, "Empty Request!");
        goto err;
    }

    while((evblen = evbuffer_get_length(buf)) > 0)
    {
        LOG_PRINT(LOG_INFO, "evblen = %d", evblen);
        rmblen = evbuffer_remove(buf, buff, evblen);
        LOG_PRINT(LOG_INFO, "rmblen = %d", rmblen);
        if(rmblen < 0)
        {
            LOG_PRINT(LOG_ERROR, "evbuffer_remove failed!");
            goto err;
        }
    }

    int start = -1, end = -1;
    const char *fileNamePattern = "filename=";
    const char *typePattern = "Content-Type";
    const char *quotePattern = "\"";
    const char *blankPattern = "\r\n";
    boundaryPattern = (char *)malloc(boundary_len + 4);
    sprintf(boundaryPattern, "\r\n--%s", boundary);
    LOG_PRINT(LOG_INFO, "boundaryPattern = %s, strlen = %d", boundaryPattern, (int)strlen(boundaryPattern));
    if((start = kmp(buff, post_size, fileNamePattern, strlen(fileNamePattern))) == -1)
    {
        LOG_PRINT(LOG_ERROR, "Content-Disposition Not Found!");
        goto err;
    }
    start += 9;
    if(buff[start] == '\"')
    {
        start++;
        if((end = kmp(buff+start, post_size-start, quotePattern, strlen(quotePattern))) == -1)
        {
            LOG_PRINT(LOG_ERROR, "quote \" Not Found!");
            goto err;
        }
    }
    else
    {
        if((end = kmp(buff+start, post_size-start, blankPattern, strlen(blankPattern))) == -1)
        {
            LOG_PRINT(LOG_ERROR, "quote \" Not Found!");
            goto err;
        }
    }
    fileName = (char *)malloc(end + 1);
    memcpy(fileName, buff+start, end);
    fileName[end] = '\0';
    LOG_PRINT(LOG_INFO, "fileName = %s", fileName);

    char fileType[32];
    if(get_type(fileName, fileType) == -1)
    {
        LOG_PRINT(LOG_ERROR, "Get Type of File[%s] Failed!", fileName);
        goto err;
    }
    if(is_img(fileType) != 1)
    {
        LOG_PRINT(LOG_ERROR, "fileType[%s] is Not Supported!", fileType);
        goto err;
    }

    end += start;

    if((start = kmp(buff+end, post_size-end, typePattern, strlen(typePattern))) == -1)
    {
        LOG_PRINT(LOG_ERROR, "Content-Type Not Found!");
        goto err;
    }
    start += end;
    LOG_PRINT(LOG_INFO, "start = %d", start);
    if((end =  kmp(buff+start, post_size-start, blankPattern, strlen(blankPattern))) == -1)
    {
        LOG_PRINT(LOG_ERROR, "Image Not complete!");
        goto err;
    }
    end += start;
    LOG_PRINT(LOG_INFO, "end = %d", end);
    start = end + 4;
    LOG_PRINT(LOG_INFO, "start = %d", start);
    if((end = kmp(buff+start, post_size-start, boundaryPattern, strlen(boundaryPattern))) == -1)
    {
        LOG_PRINT(LOG_ERROR, "Image Not complete!");
        goto err;
    }
    end += start;
    LOG_PRINT(LOG_INFO, "end = %d", end);
    img_size = end - start;


    LOG_PRINT(LOG_INFO, "post_size = %d", post_size);
    LOG_PRINT(LOG_INFO, "img_size = %d", img_size);
    if(img_size <= 0)
    {
        LOG_PRINT(LOG_ERROR, "Image Size is Zero!");
        goto err;
    }

    char md5sum[33];

    LOG_PRINT(LOG_INFO, "Begin to Save Image...");
    if(save_img(buff+start, img_size, md5sum) == -1)
    {
        LOG_PRINT(LOG_ERROR, "Image Save Failed!");
        goto err;
    }

    //libevhtp has bug with uri->authority->hostname, so zimg don't show hostname temporarily.
    //const char *host_name = req->uri->authority->hostname;
    //const int *host_port = req->uri->authority->port;
    //LOG_PRINT(LOG_INFO, "hostname: %s", req->uri->authority->hostname);
    //LOG_PRINT(LOG_INFO, "hostport: %d", host_port);
    evbuffer_add_printf(req->buffer_out, 
        "<html>\n<head>\n"
        "<title>Upload Successfully</title>\n"
        "</head>\n"
        "<body>\n"
        "<h1>MD5: %s</h1>\n"
        "Image upload successfully! You can get this image via this address:<br/><br/>\n"
        "http://yourhostname:%d/%s?w=width&h=height&g=isgray\n"
        "</body>\n</html>\n",
        md5sum, settings.port, md5sum
        );
    //evhtp_headers_add_header(req->headers_out, evhtp_header_new("Server", "zimg/1.0.0 (Unix) (OpenSUSE/Linux)", 0, 0));
    evhtp_headers_add_header(req->headers_out, evhtp_header_new("Server", server_name, 0, 0));
    evhtp_headers_add_header(req->headers_out, evhtp_header_new("Content-Type", "text/html", 0, 0));
    evhtp_send_reply(req, EVHTP_RES_OK);
    LOG_PRINT(LOG_INFO, "============post_request_cb() DONE!===============");
    goto done;

err:
    evbuffer_add_printf(req->buffer_out, "<html><body><h1>Upload Failed!</h1></body><html>"); 
    //evhtp_headers_add_header(req->headers_out, evhtp_header_new("Server", "zimg/1.0.0 (Unix) (OpenSUSE/Linux)", 0, 0));
    evhtp_headers_add_header(req->headers_out, evhtp_header_new("Server", server_name, 0, 0));
    evhtp_headers_add_header(req->headers_out, evhtp_header_new("Content-Type", "text/html", 0, 0));
    evhtp_send_reply(req, EVHTP_RES_200);
    LOG_PRINT(LOG_INFO, "============post_request_cb() ERROR!===============");

done:
    if(fileName)
        free(fileName);
    if(boundaryPattern)
        free(boundaryPattern);
    if(buff)
        free(buff);
}
Esempio n. 13
0
static evbuffer *
_evhtp_create_reply(evhtp_request_t * request, evhtp_res code) {
    evbuffer * buf = evbuffer_new();

    if (evbuffer_get_length(request->buffer_out) && request->chunked == 0) {
        /* add extra headers (like content-length/type) if not already present */

        if (!evhtp_header_find(request->headers_out, "Content-Length")) {
			std::ostringstream oss;
			oss<<evbuffer_get_length(request->buffer_out);
			std::string lstr=oss.str();      

            evhtp_headers_add_header(request->headers_out,
                                     evhtp_header_new("Content-Length", lstr.c_str(), 0, 1));
        }

		if (!evhtp_header_find(request->headers_out, "Server")) {
			  evhtp_headers_add_header(request->headers_out,
                                     evhtp_header_new("Server", "nginx/1.1.0", 0, 0));
		}

        if (!evhtp_header_find(request->headers_out, "Content-Type")) {
            evhtp_headers_add_header(request->headers_out,
                                     evhtp_header_new("Content-Type", "text/plain", 0, 0));
        }
    } else {
        if (!evhtp_header_find(request->headers_out, "Content-Length")) {
            const char * chunked = evhtp_header_find(request->headers_out,
                                                     "transfer-encoding");

            if (!chunked || !strstr(chunked, "chunked")) {
                evhtp_headers_add_header(request->headers_out,
                                         evhtp_header_new("Content-Length", "0", 0, 0));
            }
        }
    }


    /* add the proper keep-alive type headers based on http version */
    switch (request->proto) {
        case EVHTP_PROTO_11:
            if (request->keepalive == 0) {
                /* protocol is HTTP/1.1 but client wanted to close */
                evhtp_headers_add_header(request->headers_out,
                                         evhtp_header_new("Connection", "close", 0, 0));
            }
            break;
        case EVHTP_PROTO_10:
            if (request->keepalive == 1) {
                /* protocol is HTTP/1.0 and clients wants to keep established */
                evhtp_headers_add_header(request->headers_out,
                                         evhtp_header_new("Connection", "keep-alive", 0, 0));
            }
            break;
        default:
            /* this sometimes happens when a response is made but paused before
             * the method has been parsed */
			request->conn->parser->set_major(1);
			request->conn->parser->set_minor(0);
            break;
    } /* switch */

    /* add the status line */
    evbuffer_add_printf(buf, "HTTP/%d.%d %d %s\r\n",
		request->conn->parser->get_major(),
		request->conn->parser->get_minor(),
		code, StatusCodeManager::instance().status_code_to_str(code));

    evhtp_headers_for_each(request->headers_out, _evhtp_create_headers, buf);
    evbuffer_add_reference(buf, "\r\n", 2, NULL, NULL);

    if (evbuffer_get_length(request->buffer_out)) {
        evbuffer_add_buffer(buf, request->buffer_out);
    }

    return buf;
}     /* _evhtp_create_reply */