Beispiel #1
0
/**
 * @brief settings_init Init the setting with default values.
 */
static void settings_init(void) {
    settings.L = NULL;
    settings.is_daemon = 0;
    str_lcpy(settings.ip, "0.0.0.0", sizeof(settings.ip));
    settings.port = 4869;
    settings.num_threads = get_cpu_cores();         /* N workers */
    settings.backlog = 1024;
    settings.max_keepalives = 1;
    settings.retry = 3;
    str_lcpy(settings.version, STR(PROJECT_VERSION), sizeof(settings.version));
    snprintf(settings.server_name, 128, "zimg/%s", settings.version);
    settings.headers = NULL;
    settings.etag = 0;
    settings.up_access = NULL;
    settings.down_access = NULL;
    settings.admin_access = NULL;
    settings.cache_on = 0;
    str_lcpy(settings.cache_ip, "127.0.0.1", sizeof(settings.cache_ip));
    settings.cache_port = 11211;
    settings.log_level = 6;
    str_lcpy(settings.log_name, "./log/zimg.log", sizeof(settings.log_name));
    str_lcpy(settings.root_path, "./www/index.html", sizeof(settings.root_path));
    str_lcpy(settings.admin_path, "./www/admin.html", sizeof(settings.admin_path));
    settings.disable_args = 0;
    settings.disable_type = 0;
    settings.disable_zoom_up = 0;
    settings.script_on = 0;
    settings.script_name[0] = '\0';
    str_lcpy(settings.format, "none", sizeof(settings.format));
    settings.quality = 75;
    settings.mode = 1;
    settings.save_new = 1;
    settings.max_size = 10485760;
    str_lcpy(settings.img_path, "./img", sizeof(settings.img_path));
    str_lcpy(settings.beansdb_ip, "127.0.0.1", sizeof(settings.beansdb_ip));
    settings.beansdb_port = 7905;
    str_lcpy(settings.ssdb_ip, "127.0.0.1", sizeof(settings.ssdb_ip));
    settings.ssdb_port = 6379;
    multipart_parser_settings *callbacks = (multipart_parser_settings *)malloc(sizeof(multipart_parser_settings));
    memset(callbacks, 0, sizeof(multipart_parser_settings));
    //callbacks->on_header_field = on_header_field;
    callbacks->on_header_value = on_header_value;
    callbacks->on_chunk_data = on_chunk_data;
    settings.mp_set = callbacks;
    settings.get_img = NULL;
    settings.info_img = NULL;
    settings.admin_img = NULL;
}
Beispiel #2
0
/**
 * @brief find_cache Connect to a memcached server and find a key's value.
 *
 * @param memc The connection to beansdb.
 * @param key The string of the key you want to find.
 * @param value It contains the string of the key's value.
 *
 * @return 1 for success and -1 for fail.
 */
int find_cache(memcached_st *memc, const char *key, char *value)
{
    int rst = -1;
    if(memc == NULL)
        return rst;

    size_t valueLen;
    uint32_t flags;
    memcached_return rc;

    char *pvalue = memcached_get(memc, key, strlen(key), &valueLen, &flags, &rc);

    if (rc == MEMCACHED_SUCCESS) 
    {
        LOG_PRINT(LOG_DEBUG, "Cache Find Key[%s] Value: %s", key, pvalue);
        str_lcpy(value, pvalue, sizeof(value));
        free(pvalue);
        rst = 1;
    }
    else if (rc == MEMCACHED_NOTFOUND)
    {
        LOG_PRINT(LOG_DEBUG, "Cache Key[%s] Not Find!", key);
        rst = -1;
    }
    else
    {
        const char *str_rc = memcached_strerror(memc, rc);
        LOG_PRINT(LOG_DEBUG, "Cache Result: %s", str_rc);
    }

    return rst;
}
Beispiel #3
0
/**
 * @brief load_conf load the conf of zimg
 *
 * @param conf conf name
 *
 * @return 1 for OK and -1 for fail
 */
static int load_conf(const char *conf) {
    lua_State *L = luaL_newstate();
    luaL_openlibs(L);
    if (luaL_loadfile(L, conf) || lua_pcall(L, 0, 0, 0)) {
        lua_close(L);
        return -1;
    }

    lua_getglobal(L, "is_daemon"); //stack index: -12
    if (lua_isnumber(L, -1))
        settings.is_daemon = (int)lua_tonumber(L, -1);
    lua_pop(L, 1);

    lua_getglobal(L, "ip");
    if (lua_isstring(L, -1))
        str_lcpy(settings.ip, lua_tostring(L, -1), sizeof(settings.ip));
    lua_pop(L, 1);

    lua_getglobal(L, "port");
    if (lua_isnumber(L, -1))
        settings.port = (int)lua_tonumber(L, -1);
    lua_pop(L, 1);

    lua_getglobal(L, "thread_num");
    if (lua_isnumber(L, -1))
        settings.num_threads = (int)lua_tonumber(L, -1);         /* N workers */
    lua_pop(L, 1);

    lua_getglobal(L, "backlog_num");
    if (lua_isnumber(L, -1))
        settings.backlog = (int)lua_tonumber(L, -1);
    lua_pop(L, 1);

    lua_getglobal(L, "max_keepalives");
    if (lua_isnumber(L, -1))
        settings.max_keepalives = (int)lua_tonumber(L, -1);
    lua_pop(L, 1);

    lua_getglobal(L, "retry");
    if (lua_isnumber(L, -1))
        settings.retry = (int)lua_tonumber(L, -1);
    lua_pop(L, 1);

    lua_getglobal(L, "system");
    if (lua_isstring(L, -1)) {
        char tmp[128];
        snprintf(tmp, 128, "%s %s", settings.server_name, lua_tostring(L, -1));
        snprintf(settings.server_name, 128, "%s", tmp);
    }
    lua_pop(L, 1);

    lua_getglobal(L, "headers");
    if (lua_isstring(L, -1)) {
        settings.headers = conf_get_headers(lua_tostring(L, -1));
    }
    lua_pop(L, 1);

    lua_getglobal(L, "etag");
    if (lua_isnumber(L, -1))
        settings.etag = (int)lua_tonumber(L, -1);
    lua_pop(L, 1);

    lua_getglobal(L, "upload_rule");
    if (lua_isstring(L, -1)) {
        settings.up_access = conf_get_rules(lua_tostring(L, -1));
    }
    lua_pop(L, 1);

    lua_getglobal(L, "download_rule");
    if (lua_isstring(L, -1)) {
        settings.down_access = conf_get_rules(lua_tostring(L, -1));
    }
    lua_pop(L, 1);

    lua_getglobal(L, "admin_rule");
    if (lua_isstring(L, -1)) {
        settings.admin_access = conf_get_rules(lua_tostring(L, -1));
    }
    lua_pop(L, 1);

    lua_getglobal(L, "cache");
    if (lua_isnumber(L, -1))
        settings.cache_on = (int)lua_tonumber(L, -1);
    lua_pop(L, 1);

    lua_getglobal(L, "mc_ip");
    if (lua_isstring(L, -1))
        str_lcpy(settings.cache_ip, lua_tostring(L, -1), sizeof(settings.cache_ip));
    lua_pop(L, 1);

    lua_getglobal(L, "mc_port");
    if (lua_isnumber(L, -1))
        settings.cache_port = (int)lua_tonumber(L, -1);
    lua_pop(L, 1);

    lua_getglobal(L, "log_level");
    if (lua_isnumber(L, -1))
        settings.log_level = (int)lua_tonumber(L, -1);
    lua_pop(L, 1);

    lua_getglobal(L, "log_name"); //stack index: -1
    if (lua_isstring(L, -1))
        str_lcpy(settings.log_name, lua_tostring(L, -1), sizeof(settings.log_name));
    lua_pop(L, 1);

    lua_getglobal(L, "root_path");
    if (lua_isstring(L, -1))
        str_lcpy(settings.root_path, lua_tostring(L, -1), sizeof(settings.root_path));
    lua_pop(L, 1);

    lua_getglobal(L, "admin_path");
    if (lua_isstring(L, -1))
        str_lcpy(settings.admin_path, lua_tostring(L, -1), sizeof(settings.admin_path));
    lua_pop(L, 1);

    lua_getglobal(L, "disable_args");
    if (lua_isnumber(L, -1))
        settings.disable_args = (int)lua_tonumber(L, -1);
    lua_pop(L, 1);

    lua_getglobal(L, "disable_type");
    if (lua_isnumber(L, -1))
        settings.disable_type = (int)lua_tonumber(L, -1);
    lua_pop(L, 1);

    lua_getglobal(L, "disable_zoom_up");
    if (lua_isnumber(L, -1))
        settings.disable_zoom_up = (int)lua_tonumber(L, -1);
    lua_pop(L, 1);

    lua_getglobal(L, "script_name"); //stack index: -1
    if (lua_isstring(L, -1))
        str_lcpy(settings.script_name, lua_tostring(L, -1), sizeof(settings.script_name));
    lua_pop(L, 1);

    lua_getglobal(L, "format");
    if (lua_isstring(L, -1))
        str_lcpy(settings.format, lua_tostring(L, -1), sizeof(settings.format));
    lua_pop(L, 1);

    lua_getglobal(L, "quality");
    if (lua_isnumber(L, -1))
        settings.quality = (int)lua_tonumber(L, -1);
    lua_pop(L, 1);

    lua_getglobal(L, "mode");
    if (lua_isnumber(L, -1))
        settings.mode = (int)lua_tonumber(L, -1);
    lua_pop(L, 1);

    set_callback(settings.mode);

    lua_getglobal(L, "save_new");
    if (lua_isnumber(L, -1))
        settings.save_new = (int)lua_tonumber(L, -1);
    lua_pop(L, 1);

    lua_getglobal(L, "max_size");
    if (lua_isnumber(L, -1))
        settings.max_size = (int)lua_tonumber(L, -1);
    lua_pop(L, 1);

    lua_getglobal(L, "img_path");
    if (lua_isstring(L, -1))
        str_lcpy(settings.img_path, lua_tostring(L, -1), sizeof(settings.img_path));
    lua_pop(L, 1);

    lua_getglobal(L, "beansdb_ip");
    if (lua_isstring(L, -1))
        str_lcpy(settings.beansdb_ip, lua_tostring(L, -1), sizeof(settings.beansdb_ip));
    lua_pop(L, 1);

    lua_getglobal(L, "beansdb_port");
    if (lua_isnumber(L, -1))
        settings.beansdb_port = (int)lua_tonumber(L, -1);
    lua_pop(L, 1);

    lua_getglobal(L, "ssdb_ip");
    if (lua_isstring(L, -1))
        str_lcpy(settings.ssdb_ip, lua_tostring(L, -1), sizeof(settings.ssdb_ip));
    lua_pop(L, 1);

    lua_getglobal(L, "ssdb_port");
    if (lua_isnumber(L, -1))
        settings.ssdb_port = (int)lua_tonumber(L, -1);
    lua_pop(L, 1);

    //settings.L = L;
    lua_close(L);

    return 1;
}
Beispiel #4
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);
}
Beispiel #5
0
int multipart_parse(evhtp_request_t *req, const char *content_type, const char *address, const char *buff, int post_size)
{
    int err_no = 0;
    char *boundary = NULL, *boundary_end = NULL;
    char *boundaryPattern = NULL;
    int boundary_len = 0;
    mp_arg_t *mp_arg = NULL;

    evbuffer_add_printf(req->buffer_out, 
            "<html>\n<head>\n"
            "<title>Upload Result</title>\n"
            "</head>\n"
            "<body>\n"
            );

    if(strstr(content_type, "boundary") == 0)
    {
        LOG_PRINT(LOG_DEBUG, "boundary NOT found!");
        LOG_PRINT(LOG_ERROR, "%s fail post parse", address);
        err_no = 6;
        goto done;
    }

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

    if(boundary[0] == '"') 
    {
        boundary++;
        boundary_end = strchr(boundary, '"');
        if (!boundary_end) 
        {
            LOG_PRINT(LOG_DEBUG, "Invalid boundary in multipart/form-data POST data");
            LOG_PRINT(LOG_ERROR, "%s fail post parse", address);
            err_no = 6;
            goto done;
        }
    } 
    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_DEBUG, "boundary Find. boundary = %s", boundary);
    boundaryPattern = (char *)malloc(boundary_len + 3);
    if(boundaryPattern == NULL)
    {
        LOG_PRINT(LOG_DEBUG, "boundarypattern malloc failed!");
        LOG_PRINT(LOG_ERROR, "%s fail malloc", address);
        err_no = 0;
        goto done;
    }
    snprintf(boundaryPattern, boundary_len + 3, "--%s", boundary);
    LOG_PRINT(LOG_DEBUG, "boundaryPattern = %s, strlen = %d", boundaryPattern, (int)strlen(boundaryPattern));

    multipart_parser* parser = multipart_parser_init(boundaryPattern);
    if(!parser)
    {
        LOG_PRINT(LOG_DEBUG, "Multipart_parser Init Failed!");
        LOG_PRINT(LOG_ERROR, "%s fail post save", address);
        err_no = 0;
        goto done;
    }
    mp_arg = (mp_arg_t *)malloc(sizeof(mp_arg_t));
    if(!mp_arg)
    {
        LOG_PRINT(LOG_DEBUG, "Multipart_parser Arg Malloc Failed!");
        LOG_PRINT(LOG_ERROR, "%s fail post save", address);
        err_no = 0;
        goto done;
    }

    evthr_t *thread = get_request_thr(req);
    thr_arg_t *thr_arg = (thr_arg_t *)evthr_get_aux(thread);
    mp_arg->req = req;
    mp_arg->thr_arg = thr_arg;
    str_lcpy(mp_arg->address, address, 16);
    mp_arg->partno = 0;
    mp_arg->succno = 0;
    mp_arg->check_name = 0;
    multipart_parser_set_data(parser, mp_arg);
    multipart_parser_execute(parser, buff, post_size);
    multipart_parser_free(parser);

    if(mp_arg->succno == 0)
    {
        evbuffer_add_printf(req->buffer_out, "<h1>Upload Failed!</h1>\n");
    }

    evbuffer_add_printf(req->buffer_out, "</body>\n</html>\n");
    evhtp_headers_add_header(req->headers_out, evhtp_header_new("Content-Type", "text/html", 0, 0));
    err_no = -1;

done:
    free(boundaryPattern);
    free(mp_arg);
    return err_no;
}
Beispiel #6
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));
    }
Beispiel #7
0
/**
 * @brief save_img Save buffer from POST requests
 *
 * @param thr_arg Thread arg struct.
 * @param buff The char * from POST request
 * @param len The length of buff
 * @param md5 Parsed md5 from url
 *
 * @return 1 for success and -1 for fail
 */
int save_img(thr_arg_t *thr_arg, const char *buff, const int len, char *md5)
{
    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';
    str_lcpy(md5, md5sum, 33);
    LOG_PRINT(LOG_DEBUG, "md5: %s", md5sum);

    char save_path[512];
    char save_name[512];

    if(settings.mode != 1)
    {
        if(exist_db(thr_arg, md5sum) == 1)
        {
            LOG_PRINT(LOG_DEBUG, "File Exist, Needn't Save.");
            result = 1;
            goto done;
        }
        LOG_PRINT(LOG_DEBUG, "exist_db not found. Begin to Save File.");


        if(save_img_db(thr_arg, md5sum, buff, len) == -1)
        {
            LOG_PRINT(LOG_DEBUG, "save_img_db failed.");
            goto done;
        }
        else
        {
            LOG_PRINT(LOG_DEBUG, "save_img_db succ.");
            result = 1;
            goto done;
        }
    }

    //caculate 2-level path
    int lvl1 = str_hash(md5sum);
    int lvl2 = str_hash(md5sum + 3);

    snprintf(save_path, 512, "%s/%d/%d/%s", settings.img_path, lvl1, lvl2, md5sum);
    LOG_PRINT(LOG_DEBUG, "save_path: %s", save_path);

    if(is_dir(save_path) != 1)
    {
        if(mk_dirs(save_path) == -1)
        {
            LOG_PRINT(LOG_DEBUG, "save_path[%s] Create Failed!", save_path);
            goto done;
        }
        LOG_PRINT(LOG_DEBUG, "save_path[%s] Create Finish.", save_path);
    }

    snprintf(save_name, 512, "%s/0*0", save_path);
    LOG_PRINT(LOG_DEBUG, "save_name-->: %s", save_name);

    if(is_file(save_name) == 1)
    {
        LOG_PRINT(LOG_DEBUG, "Check File Exist. Needn't Save.");
        goto cache;
    }

    if(new_img(buff, len, save_name) == -1)
    {
        LOG_PRINT(LOG_DEBUG, "Save Image[%s] Failed!", save_name);
        goto done;
    }

cache:
    if(len < CACHE_MAX_SIZE)
    {
        set_cache_bin(thr_arg, md5sum, buff, len);
    }
    result = 1;

done:
    return result;
}
Beispiel #8
0
/**
 * @brief get_img get image from disk mode through the request
 *
 * @param req the zimg request
 * @param request the evhtp request
 *
 * @return 1 for OK, 2 for 304 needn't response buffer and -1 for failed
 */
int get_img(zimg_req_t *req, evhtp_request_t *request)
{
    int result = -1;
    char rsp_cache_key[CACHE_KEY_SIZE];
    int fd = -1;
    struct stat f_stat;
    char *buff = NULL;
    char *orig_buff = NULL;
    MagickWand *im = NULL;
    size_t len = 0;
    bool to_save = true;

    LOG_PRINT(LOG_DEBUG, "get_img() start processing zimg request...");

    int lvl1 = str_hash(req->md5);
    int lvl2 = str_hash(req->md5 + 3);

    char whole_path[512];
    snprintf(whole_path, 512, "%s/%d/%d/%s", settings.img_path, lvl1, lvl2, req->md5);
    LOG_PRINT(LOG_DEBUG, "whole_path: %s", whole_path);
    
    if(is_dir(whole_path) == -1)
    {
        LOG_PRINT(LOG_DEBUG, "Image %s is not existed!", req->md5);
        goto err;
    }

    if(settings.script_on == 1 && req->type != NULL)
        snprintf(rsp_cache_key, CACHE_KEY_SIZE, "%s:%s", req->md5, req->type);
    else
    {
        if(req->proportion == 0 && req->width == 0 && req->height == 0)
            str_lcpy(rsp_cache_key, req->md5, CACHE_KEY_SIZE);
        else
            gen_key(rsp_cache_key, req->md5, 9, req->width, req->height, req->proportion, req->gray, req->x, req->y, req->rotate, req->quality, req->fmt);
    }

    if(find_cache_bin(req->thr_arg, rsp_cache_key, &buff, &len) == 1)
    {
        LOG_PRINT(LOG_DEBUG, "Hit Cache[Key: %s].", rsp_cache_key);
        to_save = false;
        goto done;
    }
    LOG_PRINT(LOG_DEBUG, "Start to Find the Image...");

    char orig_path[512];
    snprintf(orig_path, 512, "%s/0*0", whole_path);
    LOG_PRINT(LOG_DEBUG, "0rig File Path: %s", orig_path);

    char rsp_path[512];
    if(settings.script_on == 1 && req->type != NULL)
        snprintf(rsp_path, 512, "%s/t_%s", whole_path, req->type);
    else
    {
        char name[128];
        snprintf(name, 128, "%d*%d_p%d_g%d_%d*%d_r%d_q%d.%s", req->width, req->height,
                req->proportion, 
                req->gray, 
                req->x, req->y, 
                req->rotate, 
                req->quality,
                req->fmt);

        if(req->width == 0 && req->height == 0 && req->proportion == 0)
        {
            LOG_PRINT(LOG_DEBUG, "Return original image.");
            strncpy(rsp_path, orig_path, 512);
        }
        else
        {
            snprintf(rsp_path, 512, "%s/%s", whole_path, name);
        }
    }
    LOG_PRINT(LOG_DEBUG, "Got the rsp_path: %s", rsp_path);

    if((fd = open(rsp_path, O_RDONLY)) == -1)
    {
        im = NewMagickWand();
        if (im == NULL) goto err;

        int ret;
        if(find_cache_bin(req->thr_arg, req->md5, &orig_buff, &len) == 1)
        {
            LOG_PRINT(LOG_DEBUG, "Hit Orignal Image Cache[Key: %s].", req->md5);

            ret = MagickReadImageBlob(im, (const unsigned char *)orig_buff, len);
            if (ret != MagickTrue)
            {
                LOG_PRINT(LOG_DEBUG, "Open Original Image From Blob Failed! Begin to Open it From Disk.");
                del_cache(req->thr_arg, req->md5);
                ret = MagickReadImage(im, orig_path);
                if (ret != MagickTrue)
                {
                    LOG_PRINT(LOG_DEBUG, "Open Original Image From Disk Failed!");
                    goto err;
                }
                else
                {
                    MagickSizeType size = MagickGetImageSize(im);
                    LOG_PRINT(LOG_DEBUG, "image size = %d", size);
                    if(size < CACHE_MAX_SIZE)
                    {
                        MagickResetIterator(im);
                        char *new_buff = (char *)MagickWriteImageBlob(im, &len);
                        if (new_buff == NULL) {
                            LOG_PRINT(LOG_DEBUG, "Webimg Get Original Blob Failed!");
                            goto err;
                        }
                        set_cache_bin(req->thr_arg, req->md5, new_buff, len);
                        free(new_buff);
                    }
                }
            }
        }
        else
        {
            LOG_PRINT(LOG_DEBUG, "Not Hit Original Image Cache. Begin to Open it.");
            ret = MagickReadImage(im, orig_path);
            if (ret != MagickTrue)
            {
                LOG_PRINT(LOG_DEBUG, "Open Original Image From Disk Failed! %d != %d", ret, MagickTrue);
                LOG_PRINT(LOG_DEBUG, "Open Original Image From Disk Failed!");
                goto err;
            }
            else
            {
                MagickSizeType size = MagickGetImageSize(im);
                LOG_PRINT(LOG_DEBUG, "image size = %d", size);
                if(size < CACHE_MAX_SIZE)
                {
                    MagickResetIterator(im);
                    char *new_buff = (char *)MagickWriteImageBlob(im, &len);
                    if (new_buff == NULL) {
                        LOG_PRINT(LOG_DEBUG, "Webimg Get Original Blob Failed!");
                        goto err;
                    }
                    set_cache_bin(req->thr_arg, req->md5, new_buff, len);
                    free(new_buff);
                }
            }
        }

        if(settings.script_on == 1 && req->type != NULL)
            ret = lua_convert(im, req);
        else
            ret = convert(im, req);
        if(ret == -1) goto err;
        if(ret == 0) to_save = false;

        buff = (char *)MagickWriteImageBlob(im, &len);
        if (buff == NULL) {
            LOG_PRINT(LOG_DEBUG, "Webimg Get Blob Failed!");
            goto err;
        }
    }
    else
    {
        to_save = false;
        fstat(fd, &f_stat);
        size_t rlen = 0;
        len = f_stat.st_size;
        if(len <= 0)
        {
            LOG_PRINT(LOG_DEBUG, "File[%s] is Empty.", rsp_path);
            goto err;
        }
        if((buff = (char *)malloc(len)) == NULL)
        {
            LOG_PRINT(LOG_DEBUG, "buff Malloc Failed!");
            goto err;
        }
        LOG_PRINT(LOG_DEBUG, "img_size = %d", len);
        if((rlen = read(fd, buff, len)) == -1)
        {
            LOG_PRINT(LOG_DEBUG, "File[%s] Read Failed: %s", rsp_path, strerror(errno));
            goto err;
        }
        else if(rlen < len)
        {
            LOG_PRINT(LOG_DEBUG, "File[%s] Read Not Compeletly.", rsp_path);
            goto err;
        }
    }

    //LOG_PRINT(LOG_INFO, "New Image[%s]", rsp_path);
    int save_new = 0;
    if(to_save == true)
    {
        if(req->sv == 1 || settings.save_new == 1 || (settings.save_new == 2 && req->type != NULL)) 
        {
            save_new = 1;
        }
    }

    if(save_new == 1)
    {
        LOG_PRINT(LOG_DEBUG, "Image[%s] is Not Existed. Begin to Save it.", rsp_path);
        if(new_img(buff, len, rsp_path) == -1)
        {
            LOG_PRINT(LOG_DEBUG, "New Image[%s] Save Failed!", rsp_path);
            LOG_PRINT(LOG_WARNING, "fail save %s", rsp_path);
        }
    }
    else
        LOG_PRINT(LOG_DEBUG, "Image [%s] Needn't to Storage.", rsp_path);

    if(len < CACHE_MAX_SIZE)
    {
        set_cache_bin(req->thr_arg, rsp_cache_key, buff, len);
    }

done:
    if(settings.etag == 1)
    {
        result = zimg_etag_set(request, buff, len);
        if(result == 2)
            goto err;
    }
    result = evbuffer_add(request->buffer_out, buff, len);
    if(result != -1)
    {
        result = 1;
    }

err:
    if(fd != -1)
        close(fd);
    if(im != NULL)
        DestroyMagickWand(im);
    free(buff);
    free(orig_buff);
    return result;
}