static ngx_int_t
ngx_http_redis_pack_get(ngx_http_request_t *r, u_char* p, u_char* last,
        ngx_variable_value_t *v, ngx_chain_t **cl)
{
    ngx_array_t redis_array;
    ngx_int_t escape = 0;
    ngx_http_redis_buf_t *item;

    if (ngx_array_init(&redis_array, r->pool, 8, sizeof(ngx_http_redis_buf_t))
        != NGX_OK)
    {
        return NGX_ERROR;
    }

    item = ngx_array_push(&redis_array);
    item->type = NGX_HTTP_REDIS_BUF_STR;
    item->val.data = (u_char*)"get";
    item->val.len = sizeof("get") - 1;

    item = ngx_array_push(&redis_array);
    item->type = NGX_HTTP_REDIS_BUF_STR;
    escape = 2 * ngx_escape_uri(NULL, v->data, v->len, NGX_ESCAPE_MEMCACHED);
    if (escape) {
        item->val.data = (u_char*)ngx_palloc(r->pool, escape + v->len);
        u_char *end = (u_char*)ngx_escape_uri(item->val.data, v->data, v->len, NGX_ESCAPE_MEMCACHED);
       
        item->val.len = end - item->val.data;
    } else {
        item->val.data = (u_char*)ngx_palloc(r->pool, v->len);
        u_char* end = ngx_copy(item->val.data, v->data, v->len);
        item->val.len = end - item->val.data;
    }

    return ngx_http_redis_pack(r, &redis_array, cl);
}
static ngx_int_t
ngx_mail_auth_http_escape(ngx_pool_t *pool, ngx_str_t *text, ngx_str_t *escaped)
{
    u_char     *p;
    uintptr_t   n;

    n = ngx_escape_uri(NULL, text->data, text->len, NGX_ESCAPE_MAIL_AUTH);

    if (n == 0) {
        *escaped = *text;
        return NGX_OK;
    }

    escaped->len = text->len + n * 2;

    p = ngx_palloc(pool, escaped->len);
    if (p == NULL) {
        return NGX_ERROR;
    }

    (void) ngx_escape_uri(p, text->data, text->len, NGX_ESCAPE_MAIL_AUTH);

    escaped->data = p;

    return NGX_OK;
}
Пример #3
0
static ngx_int_t 
sc_for_req_get_uri(ngx_http_request_t *r, ngx_str_t *uri)
{
    uintptr_t escape;

    escape = 0;

    if (r->quoted_uri || r->space_in_uri || r->internal) {
        escape = 2 * ngx_escape_uri(NULL, r->uri.data, 
                r->uri.len, NGX_ESCAPE_URI);
    }

    if (escape) {
        uri->len = r->uri.len + escape;
        uri->data = ngx_palloc(r->pool, uri->len);

        if (uri->data == NULL) {
            return -1;
        }

        ngx_escape_uri(uri->data, r->uri.data, r->uri.len, NGX_ESCAPE_URI);
    }
    else {
        uri->len = r->uri.len;
        uri->data = r->uri.data;
    }

    return 0;
}
static ngx_chain_t *
ngx_rtmp_notify_record_done_create(ngx_rtmp_session_t *s, void *arg,
                                   ngx_pool_t *pool)
{
    ngx_rtmp_record_done_t         *v = arg;

    ngx_rtmp_notify_ctx_t          *ctx;
    ngx_chain_t                    *pl;
    ngx_buf_t                      *b;
    size_t                          name_len, args_len;

    ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_notify_module);

    pl = ngx_alloc_chain_link(pool);
    if (pl == NULL) {
        return NULL;
    }

    name_len  = ngx_strlen(ctx->name);
    args_len  = ngx_strlen(ctx->args);

    b = ngx_create_temp_buf(pool,
                            sizeof("&call=record_done") +
                            sizeof("&recorder=") + v->recorder.len +
                            sizeof("&name=") + name_len * 3 +
                            sizeof("&path=") + v->path.len * 3 +
                            1 + args_len);
    if (b == NULL) {
        return NULL;
    }

    pl->buf = b;
    pl->next = NULL;

    b->last = ngx_cpymem(b->last, (u_char*) "&call=record_done",
                         sizeof("&call=record_done") - 1);

    b->last = ngx_cpymem(b->last, (u_char *) "&recorder=",
                         sizeof("&recorder=") - 1);
    b->last = (u_char*) ngx_escape_uri(b->last, v->recorder.data,
                                       v->recorder.len, NGX_ESCAPE_ARGS);

    b->last = ngx_cpymem(b->last, (u_char*) "&name=", sizeof("&name=") - 1);
    b->last = (u_char*) ngx_escape_uri(b->last, ctx->name, name_len,
                                       NGX_ESCAPE_ARGS);

    b->last = ngx_cpymem(b->last, (u_char*) "&path=", sizeof("&path=") - 1);
    b->last = (u_char*) ngx_escape_uri(b->last, v->path.data, v->path.len,
                                       NGX_ESCAPE_ARGS);

    if (args_len) {
        *b->last++ = '&';
        b->last = (u_char *) ngx_cpymem(b->last, ctx->args, args_len);
    }

    return ngx_rtmp_notify_create_request(s, pool, NGX_RTMP_NOTIFY_RECORD_DONE,
                                          pl);
}
static ngx_chain_t *
ngx_rtmp_notify_done_create(ngx_rtmp_session_t *s, void *arg,
        ngx_pool_t *pool)
{
    ngx_rtmp_notify_done_t         *ds = arg;

    ngx_chain_t                    *pl;
    ngx_buf_t                      *b;
    size_t                          cbname_len, name_len, args_len;
    ngx_rtmp_notify_ctx_t          *ctx;

    ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_notify_module);

    pl = ngx_alloc_chain_link(pool);
    if (pl == NULL) {
        return NULL;
    }

    cbname_len = ngx_strlen(ds->cbname);
    name_len = ctx ? ngx_strlen(ctx->name) : 0;
    args_len = ctx ? ngx_strlen(ctx->args) : 0;

    b = ngx_create_temp_buf(pool,
                            sizeof("&call=") + cbname_len +
                            sizeof("&app=") + s->app.len * 3 +
                            sizeof("&name=") + name_len * 3 +
                            1 + args_len);
    if (b == NULL) {
        return NULL;
    }

    pl->buf = b;
    pl->next = NULL;

    b->last = ngx_cpymem(b->last, (u_char*) "&call=", sizeof("&call=") - 1);
    b->last = ngx_cpymem(b->last, ds->cbname, cbname_len);

    b->last = ngx_cpymem(b->last, (u_char*) "&app=", sizeof("&app=") - 1);
    b->last = (u_char*) ngx_escape_uri(b->last, s->app.data, s->app.len,
                                       NGX_ESCAPE_ARGS);

    if (name_len) {
        b->last = ngx_cpymem(b->last, (u_char*) "&name=", sizeof("&name=") - 1);
        b->last = (u_char*) ngx_escape_uri(b->last, ctx->name, name_len,
                                           NGX_ESCAPE_ARGS);
    }

    if (args_len) {
        *b->last++ = '&';
        b->last = (u_char *) ngx_cpymem(b->last, ctx->args, args_len);
    }

    return ngx_rtmp_notify_create_request(s, pool, ds->url_idx, pl);
}
static ngx_chain_t *
ngx_rtmp_notify_play_create(ngx_rtmp_session_t *s, void *arg,
        ngx_pool_t *pool)
{
    ngx_rtmp_play_t                *v = arg;

    ngx_chain_t                    *pl;
    ngx_buf_t                      *b;
    size_t                          name_len, args_len;

    pl = ngx_alloc_chain_link(pool);
    if (pl == NULL) {
        return NULL;
    }

    name_len = ngx_strlen(v->name);
    args_len = ngx_strlen(v->args);

    b = ngx_create_temp_buf(pool,
                            sizeof("&call=play") +
                            sizeof("&app=") + s->app.len * 3 +
                            sizeof("&name=") + name_len * 3 +
                            sizeof("&start=&duration=&reset=") +
                            NGX_INT32_LEN * 3 + 1 + args_len);
    if (b == NULL) {
        return NULL;
    }

    pl->buf = b;
    pl->next = NULL;

    b->last = ngx_cpymem(b->last, (u_char*) "&call=play",
                         sizeof("&call=play") - 1);

    b->last = ngx_cpymem(b->last, (u_char*) "&app=", sizeof("&app=") - 1);
    b->last = (u_char*) ngx_escape_uri(b->last, s->app.data, s->app.len,
                                       NGX_ESCAPE_ARGS);

    b->last = ngx_cpymem(b->last, (u_char*) "&name=", sizeof("&name=") - 1);
    b->last = (u_char*) ngx_escape_uri(b->last, v->name, name_len,
                                       NGX_ESCAPE_ARGS);

    b->last = ngx_snprintf(b->last, b->end - b->last,
                           "&start=%uD&duration=%uD&reset=%d",
                           (uint32_t) v->start, (uint32_t) v->duration,
                           v->reset & 1);

    if (args_len) {
        *b->last++ = '&';
        b->last = (u_char *) ngx_cpymem(b->last, v->args, args_len);
    }

    return ngx_rtmp_notify_create_request(s, pool, NGX_RTMP_NOTIFY_PLAY, pl);
}
static ngx_chain_t *
ngx_rtmp_notify_publish_create(ngx_rtmp_session_t *s, void *arg,
        ngx_pool_t *pool)
{
    ngx_rtmp_publish_t             *v = arg;

    ngx_chain_t                    *pl;
    ngx_buf_t                      *b;
    size_t                          name_len, type_len, args_len;

    pl = ngx_alloc_chain_link(pool);
    if (pl == NULL) {
        return NULL;
    }

    name_len = ngx_strlen(v->name);
    type_len = ngx_strlen(v->type);
    args_len = ngx_strlen(v->args);

    b = ngx_create_temp_buf(pool,
                            sizeof("&call=publish") +
                            sizeof("&app=") + s->app.len * 3 +
                            sizeof("&name=") + name_len * 3 +
                            sizeof("&type=") + type_len * 3 +
                            1 + args_len);
    if (b == NULL) {
        return NULL;
    }

    pl->buf = b;
    pl->next = NULL;

    b->last = ngx_cpymem(b->last, (u_char*) "&call=publish",
                         sizeof("&call=publish") - 1);

    b->last = ngx_cpymem(b->last, (u_char*) "&app=", sizeof("&app=") - 1);
    b->last = (u_char*) ngx_escape_uri(b->last, s->app.data, s->app.len,
                                       NGX_ESCAPE_ARGS);

    b->last = ngx_cpymem(b->last, (u_char*) "&name=", sizeof("&name=") - 1);
    b->last = (u_char*) ngx_escape_uri(b->last, v->name, name_len,
                                       NGX_ESCAPE_ARGS);

    b->last = ngx_cpymem(b->last, (u_char*) "&type=", sizeof("&type=") - 1);
    b->last = (u_char*) ngx_escape_uri(b->last, v->type, type_len,
                                       NGX_ESCAPE_ARGS);

    if (args_len) {
        *b->last++ = '&';
        b->last = (u_char *) ngx_cpymem(b->last, v->args, args_len);
    }

    return ngx_rtmp_notify_create_request(s, pool, NGX_RTMP_NOTIFY_PUBLISH, pl);
}
static ngx_int_t
ngx_http_token_create_request(ngx_http_request_t *r)
{
	
	size_t                          len;
	uintptr_t                       escape;
	ngx_buf_t						*b;
	ngx_chain_t						*cl;
	ngx_http_token_ctx_t			*ctx;
	ngx_http_token_loc_conf_t		*tlcf;

	ngx_str_t args = r->args;

	tlcf = ngx_http_get_module_loc_conf(r, ngx_http_token_module);
	ctx = ngx_http_get_module_ctx(r, ngx_http_token_module);

	escape = 2 * ngx_escape_uri(NULL, args.data + (ctx->index + 1), tlcf->token_len, NGX_ESCAPE_MEMCACHED);

	len = sizeof("get ") - 1 + tlcf->token_len + escape + sizeof(CRLF) - 1;

	b = ngx_create_temp_buf(r->pool, len);
	if (b == NULL) {
		return NGX_ERROR;
	}

	cl = ngx_alloc_chain_link(r->pool);
	if (cl == NULL) {
		return NGX_ERROR;
	}

	cl->buf = b;
	cl->next = NULL;

	r->upstream->request_bufs = cl;

	*b->last++ = 'g'; *b->last++ = 'e'; *b->last++ = 't'; *b->last++ = ' ';

	ctx->key.data = b->last;

	if (escape == 0) {
		b->last = ngx_copy(b->last, args.data + (ctx->index + 1), tlcf->token_len);
	} else {
		b->last = (u_char *) ngx_escape_uri(b->last, args.data + (ctx->index + 1), tlcf->token_len, NGX_ESCAPE_MEMCACHED);
	}

	ctx->key.len = b->last - ctx->key.data;

	*b->last++ = CR; *b->last++ = LF;

	return NGX_OK;
}
ngx_chain_t *
ngx_rtmp_netcall_http_format_session(ngx_rtmp_session_t *s, ngx_pool_t *pool)
{
    ngx_chain_t                    *cl;
    ngx_buf_t                      *b;

    cl = ngx_alloc_chain_link(pool);
    if (cl == NULL) {
        return NULL;
    }

    b = ngx_create_temp_buf(pool,
            sizeof("app=") - 1 + s->app.len * 3 +
            sizeof("&flashver=") - 1 + s->flashver.len * 3 +
            sizeof("&swfurl=") - 1 + s->swf_url.len * 3 +
            sizeof("&tcurl=") - 1 + s->tc_url.len * 3 + 
            sizeof("&pageurl=") - 1 + s->page_url.len * 3
        );

    if (b == NULL) {
        return NULL;
    }

    cl->buf = b;

    b->last = ngx_cpymem(b->last, (u_char*)"app=", sizeof("app=") - 1);
    b->last = (u_char*)ngx_escape_uri(b->last, s->app.data, s->app.len, 0);

    b->last = ngx_cpymem(b->last, (u_char*)"&flashver=", 
            sizeof("&flashver=") - 1);
    b->last = (u_char*)ngx_escape_uri(b->last, s->flashver.data, 
            s->flashver.len, 0);

    b->last = ngx_cpymem(b->last, (u_char*)"&swfurl=", 
            sizeof("&swfurl=") - 1);
    b->last = (u_char*)ngx_escape_uri(b->last, s->swf_url.data, 
            s->swf_url.len, 0);

    b->last = ngx_cpymem(b->last, (u_char*)"&tcurl=", 
            sizeof("&tcurl=") - 1);
    b->last = (u_char*)ngx_escape_uri(b->last, s->tc_url.data, 
            s->tc_url.len, 0);

    b->last = ngx_cpymem(b->last, (u_char*)"&pageurl=", 
            sizeof("&pageurl=") - 1);
    b->last = (u_char*)ngx_escape_uri(b->last, s->page_url.data, 
            s->page_url.len, 0);

    return cl;
}
/* This funcion returns pointer to a static buffer */
static u_char *
ngx_rtmp_record_make_path(ngx_rtmp_session_t *s)
{
    ngx_rtmp_record_ctx_t          *ctx;
    ngx_rtmp_record_app_conf_t     *racf;
    u_char                         *p, *l;
    static u_char                   buf[NGX_TIME_T_LEN + 1];
    static u_char                   path[NGX_MAX_PATH + 1];

    racf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_record_module);
    ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_record_module);

    /* create file path */
    p = path;
    l = path + sizeof(path) - 1;
    p = ngx_cpymem(p, racf->path.data, 
                ngx_min(racf->path.len, (size_t)(l - p - 1)));
    *p++ = '/';
    p = (u_char *)ngx_escape_uri(p, ctx->name, ngx_min(ngx_strlen(ctx->name),
                (size_t)(l - p)), NGX_ESCAPE_URI_COMPONENT);
    if (racf->unique) {
        /* append timestamp */
        p = ngx_cpymem(p, buf, ngx_min(ngx_sprintf(buf, "-%T", 
                        ctx->timestamp) - buf, l - p));
    }
    p = ngx_cpymem(p, racf->suffix.data, 
            ngx_min(racf->suffix.len, (size_t)(l - p)));
    *p = 0;

    return path;
}
static ngx_chain_t *
ngx_rtmp_notify_disconnect_create(ngx_rtmp_session_t *s, void *arg,
        ngx_pool_t *pool)
{
    ngx_rtmp_notify_srv_conf_t     *nscf;
    ngx_url_t                      *url;
    ngx_chain_t                    *al, *bl, *pl;
    ngx_buf_t                      *b;

    nscf = ngx_rtmp_get_module_srv_conf(s, ngx_rtmp_notify_module);

    pl = ngx_alloc_chain_link(pool);
    if (pl == NULL) {
        return NULL;
    }

    b = ngx_create_temp_buf(pool,
                            sizeof("&call=disconnect") +
                            sizeof("&app=") + s->app.len * 3 +
                            1 + s->args.len);
    if (b == NULL) {
        return NULL;
    }

    pl->buf = b;
    pl->next = NULL;

    b->last = ngx_cpymem(b->last, (u_char*) "&call=disconnect",
                         sizeof("&call=disconnect") - 1);

    b->last = ngx_cpymem(b->last, (u_char*) "&app=", sizeof("&app=") - 1);
    b->last = (u_char*) ngx_escape_uri(b->last, s->app.data, s->app.len,
                                       NGX_ESCAPE_ARGS);

    if (s->args.len) {
        *b->last++ = '&';
        b->last = (u_char *) ngx_cpymem(b->last, s->args.data, s->args.len);
    }

    url = nscf->url[NGX_RTMP_NOTIFY_DISCONNECT];

    al = ngx_rtmp_netcall_http_format_session(s, pool);
    if (al == NULL) {
        return NULL;
    }

    al->next = pl;

    bl = NULL;

    if (nscf->method == NGX_RTMP_NETCALL_HTTP_POST) {
        bl = al;
        al = NULL;
    }

    return ngx_rtmp_netcall_http_format_request(nscf->method, &url->host,
                                                &url->uri, al, bl, pool,
                                                &ngx_rtmp_notify_urlencoded);
}
Пример #12
0
static ngx_chain_t *
ngx_rtmp_authen_connect_create(ngx_rtmp_session_t *s, void *arg,
        ngx_pool_t *pool)
{
    ngx_rtmp_authen_app_conf_t    *aacf;
    ngx_chain_t                   *hl, *cl, *pl;
    ngx_buf_t                     *b;
    ngx_str_t                     *addr_text;

    aacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_authen_module);

    /* common variables */
    cl = ngx_rtmp_netcall_http_format_session(s, pool);

    if (cl == NULL) {
        return NULL;
    }

    /* connect variables */
    pl = ngx_alloc_chain_link(pool);

    if (pl == NULL) {
        return NULL;
    }

    addr_text = &s->connection->addr_text;

    b = ngx_create_temp_buf(pool,
            sizeof("&call=connect") +
            sizeof("&addr=") + addr_text->len);
    if (b == NULL) {
        return NULL;
    }

    pl->buf = b;

    b->last = ngx_cpymem(b->last, (u_char *)"&call=connect",
            sizeof("&call=connect") - 1);

    b->last = ngx_cpymem(b->last, (u_char *)"&addr=", sizeof("&addr=") - 1);
    b->last = (u_char *)ngx_escape_uri(b->last, addr_text->data,
            addr_text->len, 0);

    /* HTTP header */
    hl = ngx_rtmp_netcall_http_format_header(NGX_RTMP_NETCALL_HTTP_POST,
            &aacf->connect_url->uri, &aacf->connect_url->host,
            pool, cl->buf->last - cl->buf->pos + (pl->buf->last - pl->buf->pos),
            &ngx_rtmp_authen_urlencoded);

    if (hl == NULL) {
        return NULL;
    }

    hl->next = cl;
    cl->next = pl;
    pl->next = NULL;

    return hl;
}
static ngx_chain_t *
ngx_rtmp_play_remote_create(ngx_rtmp_session_t *s, void *arg, ngx_pool_t *pool)
{
    ngx_rtmp_play_t                *v = arg;

    ngx_rtmp_play_ctx_t            *ctx;
    ngx_rtmp_play_entry_t          *pe;
    ngx_str_t                      *addr_text, uri;
    u_char                         *p, *name;
    size_t                          args_len, name_len, len;
    static ngx_str_t                text_plain = ngx_string("text/plain");

    ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_play_module);

    pe = ngx_rtmp_play_get_current_entry(s);

    name = v->name + ctx->pfx_size;

    name_len = ngx_strlen(name);
    args_len = ngx_strlen(v->args);
    addr_text = &s->connection->addr_text;

    len = pe->url->uri.len + 1 +
          name_len + ctx->sfx.len +
          sizeof("?addr=") + addr_text->len * 3 +
          1 + args_len;

    uri.data = ngx_palloc(pool, len);
    if (uri.data == NULL) {
        return NULL;
    }

    p = uri.data;

    p = ngx_cpymem(p, pe->url->uri.data, pe->url->uri.len);

    if (p == uri.data || p[-1] != '/') {
        *p++ = '/';
    }

    p = ngx_cpymem(p, name, name_len);
    p = ngx_cpymem(p, ctx->sfx.data, ctx->sfx.len);
    p = ngx_cpymem(p, (u_char*)"?addr=", sizeof("&addr=") -1);
    p = (u_char*)ngx_escape_uri(p, addr_text->data, addr_text->len,
                                NGX_ESCAPE_ARGS);
    if (args_len) {
        *p++ = '&';
        p = (u_char *) ngx_cpymem(p, v->args, args_len);
    }

    uri.len = p - uri.data;

    return ngx_rtmp_netcall_http_format_request(NGX_RTMP_NETCALL_HTTP_GET,
                                                &pe->url->host, &uri,
                                                NULL, NULL, pool, &text_plain);
}
Пример #14
0
static ngx_str_t
ngx_mail_throttle_get_user_throttle_key (
    ngx_pool_t      *pool,
    ngx_log_t       *log,
    ngx_str_t        user
)
{
    ngx_str_t       k;
    u_char         *p;
    size_t          l;
    uintptr_t       escape;

    escape = 2 * ngx_escape_uri(NULL, user.data, user.len,
            NGX_ESCAPE_MEMCACHED);

    l = sizeof("throttle:") - 1 +
        sizeof("user="******"throttle:", sizeof("throttle:") - 1);
    p = ngx_cpymem(p, "user="******"user=") - 1);

    if (escape == 0) {
        p = ngx_cpymem(p, user.data, user.len);
    } else {
        p = (u_char *)ngx_escape_uri(p, user.data, user.len,
                NGX_ESCAPE_MEMCACHED);
    }

    k.len = p - k.data;

    return k;
}
Пример #15
0
int main()
{
    u_char *p = NULL;
    ngx_uint_t size;
    ngx_str_t dst;
    ngx_str_t mystr = ngx_string("hello, world !");
    ngx_keyval_t pair = {ngx_string("url"), ngx_string("http://rainx.cn/index.php?test=1")};
    int dst_len = ngx_base64_encoded_length(mystr.len);
    printf("source length is %d, destination length is %d\n", mystr.len, dst_len);
    p = malloc(ngx_base64_encoded_length(mystr.len) + 1);
    dst.data = p;
    ngx_encode_base64(&dst, &mystr);
    printf("source str is %s\ndestination str is %s\n", mystr.data, dst.data);
    free(p);
    size = pair.value.len + 2 * ngx_escape_uri(NULL, pair.value.data, pair.value.len, NGX_ESCAPE_URI);
    p = malloc(size * sizeof(u_char));
    ngx_escape_uri(p, pair.value.data, pair.value.len, NGX_ESCAPE_URI);
    printf("escaped %s is : %s (%d)\noriginal url size is %d\n", pair.key.data, p, size, pair.value.len);
    free(p);
    return 0;
}
/* This funcion returns pointer to a static buffer */
static void
ngx_rtmp_record_make_path(ngx_rtmp_session_t *s,
                          ngx_rtmp_record_rec_ctx_t *rctx, ngx_str_t *path)
{
    ngx_rtmp_record_ctx_t          *ctx;
    ngx_rtmp_record_app_conf_t     *rracf;
    u_char                         *p, *l;
    struct tm                       tm;

    static u_char                   buf[NGX_TIME_T_LEN + 1];
    static u_char                   pbuf[NGX_MAX_PATH + 1];

    ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_record_module);

    rracf = rctx->conf;

    /* create file path */
    p = pbuf;
    l = pbuf + sizeof(pbuf) - 1;

    p = ngx_cpymem(p, rracf->path.data,
                ngx_min(rracf->path.len, (size_t)(l - p - 1)));
    *p++ = '/';
    p = (u_char *)ngx_escape_uri(p, ctx->name, ngx_min(ngx_strlen(ctx->name),
                (size_t)(l - p)), NGX_ESCAPE_URI_COMPONENT);

    /* append timestamp */
    if (rracf->unique) {
        p = ngx_cpymem(p, buf, ngx_min(ngx_sprintf(buf, "-%T",
                       rctx->timestamp) - buf, l - p));
    }

    if (ngx_strchr(rracf->suffix.data, '%')) {
        ngx_libc_localtime(rctx->timestamp, &tm);
        p += strftime((char *) p, l - p, (char *) rracf->suffix.data, &tm);
    } else {
        p = ngx_cpymem(p, rracf->suffix.data,
                ngx_min(rracf->suffix.len, (size_t)(l - p)));
    }

    *p = 0;
    path->data = pbuf;
    path->len  = p - pbuf;

    ngx_log_debug2(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
                   "record: %V path: '%V'", &rracf->id, path);
}
Пример #17
0
void naxsi_log_offending(ngx_str_t *name, ngx_str_t *val, ngx_http_request_t *req, ngx_http_rule_t *rule,
			 enum DUMMY_MATCH_ZONE	zone, ngx_int_t target_name) {
  ngx_str_t			tmp_uri, tmp_val, tmp_name;
  ngx_str_t			empty=ngx_string("");
  
  //encode uri
  tmp_uri.len = req->uri.len + (2 * ngx_escape_uri(NULL, req->uri.data, req->uri.len,
						   NGX_ESCAPE_ARGS));
  tmp_uri.data = ngx_pcalloc(req->pool, tmp_uri.len+1);
  if (tmp_uri.data == NULL)
    return ;
  ngx_escape_uri(tmp_uri.data, req->uri.data, req->uri.len, NGX_ESCAPE_ARGS);
  //encode val
  if (val->len <= 0)
    tmp_val = empty;
  else {
    tmp_val.len = val->len + (2 * ngx_escape_uri(NULL, val->data, val->len,
						 NGX_ESCAPE_ARGS));
    tmp_val.data = ngx_pcalloc(req->pool, tmp_val.len+1);
    if (tmp_val.data == NULL)
      return ;
    ngx_escape_uri(tmp_val.data, val->data, val->len, NGX_ESCAPE_ARGS);
  }
  //encode name
  if (name->len <= 0)
    tmp_name = empty;
  else {
    tmp_name.len = name->len + (2 * ngx_escape_uri(NULL, name->data, name->len,
						   NGX_ESCAPE_ARGS));
    tmp_name.data = ngx_pcalloc(req->pool, tmp_name.len+1);
    if (tmp_name.data == NULL)
      return ;
    ngx_escape_uri(tmp_name.data, name->data, name->len, NGX_ESCAPE_ARGS);
  }
  
  ngx_log_error(NGX_LOG_ERR, req->connection->log, 0, 
		"NAXSI_EXLOG: ip=%V&server=%V&uri=%V&id=%d&zone=%s%s&var_name=%V&content=%V", 
		&(req->connection->addr_text), &(req->headers_in.server),
		&(tmp_uri), rule->rule_id, dummy_match_zones[zone], target_name?"|NAME":"", &(tmp_name), &(tmp_val));
  
  if (tmp_val.len > 0)
    ngx_pfree(req->pool, tmp_val.data);
  if (tmp_name.len > 0)
    ngx_pfree(req->pool, tmp_name.data);
  if (tmp_uri.len > 0)
    ngx_pfree(req->pool, tmp_uri.data);
  
}
Пример #18
0
/* This funcion returns pointer to a static buffer */
static u_char *
ngx_rtmp_record_make_path(ngx_rtmp_session_t *s,
                          ngx_rtmp_record_node_ctx_t *rctx)
{
    ngx_rtmp_record_ctx_t          *ctx;
    u_char                         *p, *l;
    ngx_rtmp_record_node_t         *rc;

    static u_char                   buf[NGX_TIME_T_LEN + 1];
    static u_char                   path[NGX_MAX_PATH + 1];

    ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_record_module);

    rc = rctx->conf;

    /* create file path */
    p = path;
    l = path + sizeof(path) - 1;

    p = ngx_cpymem(p, rc->path.data, 
                ngx_min(rc->path.len, (size_t)(l - p - 1)));
    *p++ = '/';
    p = (u_char *)ngx_escape_uri(p, ctx->name, ngx_min(ngx_strlen(ctx->name),
                (size_t)(l - p)), NGX_ESCAPE_URI_COMPONENT);

    /* append timestamp */
    if (rc->unique) {
        p = ngx_cpymem(p, buf, ngx_min(ngx_sprintf(buf, "-%T", 
                       rctx->timestamp) - buf, l - p));
    }

    p = ngx_cpymem(p, rc->suffix.data, 
                   ngx_min(rc->suffix.len, (size_t)(l - p)));
    *p = 0;

    ngx_log_debug2(NGX_LOG_DEBUG_RTMP, s->connection->log, 0, 
                   "record: %V path: '%s'", &rc->id, path);

    return path;
}
ngx_int_t
ngx_http_memc_create_storage_cmd_request(ngx_http_request_t *r)
{
    size_t                          len;
    off_t                           bytes;
    size_t                          bytes_len;
    uintptr_t                       escape;
    ngx_buf_t                      *b;
    ngx_chain_t                    *cl, *in;
    ngx_chain_t                   **ll;
    ngx_http_memc_ctx_t            *ctx;

    ngx_http_variable_value_t      *key_vv;
    ngx_http_variable_value_t      *flags_vv;
    ngx_http_variable_value_t      *exptime_vv;
    ngx_http_variable_value_t      *memc_value_vv;

    u_char                          bytes_buf[NGX_UINT32_LEN];

    /* TODO add support for the "cas" command */

    ctx = ngx_http_get_module_ctx(r, ngx_http_memc_module);

    /* prepare the "key" argument */

    key_vv = ctx->memc_key_vv;

    if (key_vv == NULL || key_vv->not_found || key_vv->len == 0) {
        ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
                      "the \"$memc_key\" variable is not set");
        return NGX_ERROR;
    }

    escape = 2 * ngx_escape_uri(NULL, key_vv->data, key_vv->len,
            NGX_ESCAPE_MEMCACHED);

    /* prepare the "bytes" argument */

    if (ctx->memc_value_vv && !ctx->memc_value_vv->not_found) {
        dd("found variable $memc_value");

        memc_value_vv = ctx->memc_value_vv;

        bytes = memc_value_vv->len;

    } else if (r->request_body == NULL || r->request_body->bufs == NULL) {
        ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
                      "neither the \"$memc_value\" variable "
                      "nor the request body is available");
        return NGX_HTTP_INTERNAL_SERVER_ERROR;

    } else {
        memc_value_vv = NULL;

        bytes = 0;
        for (cl = r->request_body->bufs; cl; cl = cl->next) {
            bytes += ngx_buf_size(cl->buf);
        }
    }

    bytes_len = ngx_snprintf(bytes_buf, sizeof(bytes_buf), "%O", bytes)
        - bytes_buf;

    /* prepare the "flags" argument */

    flags_vv = ctx->memc_flags_vv;

    if (flags_vv == NULL) {
        return NGX_ERROR;
    }

    if (flags_vv->not_found) {
        flags_vv->not_found = 0;
        flags_vv->valid = 1;
        flags_vv->no_cacheable = 0;
        flags_vv->len = sizeof("0") - 1;
        flags_vv->data = (u_char *) "0";
    } else if (flags_vv->len == 0) {
        flags_vv->len = sizeof("0") - 1;
        flags_vv->data = (u_char *) "0";
    }

    /* prepare the "exptime" argument */

    exptime_vv = ctx->memc_exptime_vv;

    if (exptime_vv == NULL) {
        return NGX_HTTP_INTERNAL_SERVER_ERROR;
    }

    if (exptime_vv->not_found || exptime_vv->len == 0) {
        dd("setting exptime to its default value 0...");

        exptime_vv->not_found = 0;
        exptime_vv->valid = 1;
        exptime_vv->no_cacheable = 0;
        exptime_vv->len = sizeof("0") - 1;
        exptime_vv->data = (u_char *) "0";
    }

    /* calculate the total length of the command */

    len = ctx->cmd_str.len + sizeof(" ") - 1
        + key_vv->len + escape + sizeof(" ") - 1
        + flags_vv->len + sizeof(" ") - 1
        + exptime_vv->len + sizeof(" ") - 1
        + bytes_len
        + sizeof(CRLF) - 1;

    b = ngx_create_temp_buf(r->pool, len);
    if (b == NULL) {
        return NGX_ERROR;
    }

    cl = ngx_alloc_chain_link(r->pool);
    if (cl == NULL) {
        return NGX_ERROR;
    }

    cl->buf = b;
    cl->next = NULL;

    ll = &cl->next;

    r->upstream->request_bufs = cl;

    /* copy the memcached command over */

    b->last = ngx_copy(b->last, ctx->cmd_str.data, ctx->cmd_str.len);

    *b->last++ = ' ';

    /* copy the memcached key over */

    ctx->key.data = b->last;

    if (escape == 0) {
        b->last = ngx_copy(b->last, key_vv->data, key_vv->len);

    } else {
        b->last = (u_char *) ngx_escape_uri(b->last, key_vv->data, key_vv->len,
                NGX_ESCAPE_MEMCACHED);
    }

    ctx->key.len = b->last - ctx->key.data;

    ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                   "http memcached request: \"%V\"", &ctx->key);

    *b->last++ = ' ';

    /* copy the memcached flags over */

    b->last = ngx_copy(b->last, flags_vv->data, flags_vv->len);

    *b->last++ = ' ';

    /* copy the memcached exptime over */

    b->last = ngx_copy(b->last, exptime_vv->data, exptime_vv->len);

    *b->last++ = ' ';

    /* copy the memcached bytes over */

    b->last = ngx_copy(b->last, bytes_buf, bytes_len);

    *b->last++ = CR; *b->last++ = LF;

    if (memc_value_vv) {
        if (memc_value_vv->len) {
            dd("copy $memc_value to the request");
            b = ngx_calloc_buf(r->pool);

            if (b == NULL) {
                return NGX_ERROR;
            }

            b->memory = 1;

            b->start = b->pos = memc_value_vv->data;
            b->last  = b->end = b->start + memc_value_vv->len;

            cl = ngx_alloc_chain_link(r->pool);
            if (cl == NULL) {
                return NGX_ERROR;
            }

            cl->buf = b;
            cl->next = NULL;

            *ll = cl;
            ll = &cl->next;
        }

    } else {
        /* to preserve the r->request_body->bufs untouched */

        in = r->request_body->bufs;

        while (in) {
            cl = ngx_alloc_chain_link(r->pool);
            if (cl == NULL) {
                return NGX_ERROR;
            }

            cl->buf = ngx_calloc_buf(r->pool);
            if (cl->buf == NULL) {
                return NGX_ERROR;
            }

            cl->buf->memory = 1;
            *cl->buf = *in->buf;

            *ll = cl;
            ll = &cl->next;
            in = in->next;
        }
    }

    /* append the trailing CRLF */

    b = ngx_calloc_buf(r->pool);

    if (b == NULL) {
        return NGX_ERROR;
    }

    b->start = b->pos = (u_char *) CRLF;
    b->last  = b->end = b->start + sizeof(CRLF) - 1;

    b->memory = 1;

    cl = ngx_alloc_chain_link(r->pool);
    if (cl == NULL) {
        return NGX_ERROR;
    }

    cl->buf = b;
    cl->next = NULL;

    *ll = cl;

    return NGX_OK;
}
static ngx_int_t
ngx_http_redis_handler(ngx_http_request_t *r)
{
    ngx_int_t                       rc;
    ngx_http_upstream_t            *u;
    ngx_http_redis_ctx_t           *ctx;
    ngx_http_redis_loc_conf_t      *rlcf;

    if (!(r->method & (NGX_HTTP_GET|NGX_HTTP_HEAD))) {
        return NGX_HTTP_NOT_ALLOWED;
    }

    rc = ngx_http_discard_request_body(r);

    if (rc != NGX_OK) {
        return rc;
    }

    if (ngx_http_set_content_type(r) != NGX_OK) {
        return NGX_HTTP_INTERNAL_SERVER_ERROR;
    }

#if defined nginx_version && nginx_version >= 8011
    if (ngx_http_upstream_create(r) != NGX_OK) {
#else
    rlcf = ngx_http_get_module_loc_conf(r, ngx_http_redis_module);

    u = ngx_pcalloc(r->pool, sizeof(ngx_http_upstream_t));
    if (u == NULL) {
#endif
        return NGX_HTTP_INTERNAL_SERVER_ERROR;
    }

#if defined nginx_version && nginx_version >= 8011
    u = r->upstream;
#endif

    u->schema.len = sizeof("redis://") - 1;
    u->schema.data = (u_char *) "redis://";

#if defined nginx_version && nginx_version >= 8011
    u->output.tag = (ngx_buf_tag_t) &ngx_http_redis_module;
#else
    u->peer.log = r->connection->log;
    u->peer.log_error = NGX_ERROR_ERR;
#endif

#if defined nginx_version && nginx_version >= 8011
    rlcf = ngx_http_get_module_loc_conf(r, ngx_http_redis_module);
#else
    u->output.tag = (ngx_buf_tag_t) &ngx_http_redis_module;
#endif

    u->conf = &rlcf->upstream;

    u->create_request = ngx_http_redis_create_request;
    u->reinit_request = ngx_http_redis_reinit_request;
    u->process_header = ngx_http_redis_process_header;
    u->abort_request = ngx_http_redis_abort_request;
    u->finalize_request = ngx_http_redis_finalize_request;

#if defined nginx_version && nginx_version < 8011
    r->upstream = u;
#endif

    ctx = ngx_palloc(r->pool, sizeof(ngx_http_redis_ctx_t));
    if (ctx == NULL) {
        return NGX_HTTP_INTERNAL_SERVER_ERROR;
    }

    ctx->rest = NGX_HTTP_REDIS_END;
    ctx->request = r;

    ngx_http_set_ctx(r, ctx, ngx_http_redis_module);

    u->input_filter_init = ngx_http_redis_filter_init;
    u->input_filter = ngx_http_redis_filter;
    u->input_filter_ctx = ctx;

#if defined nginx_version && nginx_version >= 8011
    r->main->count++;
#endif

    ngx_http_upstream_init(r);

    return NGX_DONE;
}


static ngx_int_t
ngx_http_redis_create_request(ngx_http_request_t *r)
{
    size_t                          len;
    uintptr_t                       escape;
    ngx_buf_t                      *b;
    ngx_chain_t                    *cl;
    ngx_http_redis_ctx_t           *ctx;
    ngx_http_variable_value_t      *vv[2];
    ngx_http_redis_loc_conf_t      *rlcf;

    rlcf = ngx_http_get_module_loc_conf(r, ngx_http_redis_module);

    vv[0] = ngx_http_get_indexed_variable(r, rlcf->db);

    if (vv[0] == NULL || vv[0]->not_found || vv[0]->len == 0) {
        ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                       "select 0 redis database" );
        len = sizeof("select 0") - 1;
    } else {
        len = sizeof("select ") - 1 + vv[0]->len;
    }
    len += sizeof(CRLF) - 1;

    vv[1] = ngx_http_get_indexed_variable(r, rlcf->index);

    if (vv[1] == NULL || vv[1]->not_found || vv[1]->len == 0) {
        ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
                      "the \"$redis_key\" variable is not set");
        return NGX_ERROR;
    }

    escape = 2 * ngx_escape_uri(NULL, vv[1]->data, vv[1]->len, NGX_ESCAPE_REDIS);

    len += sizeof("get ") - 1 + vv[1]->len + escape + sizeof(CRLF) - 1;

    b = ngx_create_temp_buf(r->pool, len);
    if (b == NULL) {
        return NGX_ERROR;
    }

    cl = ngx_alloc_chain_link(r->pool);
    if (cl == NULL) {
        return NGX_ERROR;
    }

    cl->buf = b;
    cl->next = NULL;

    r->upstream->request_bufs = cl;

    *b->last++ = 's'; *b->last++ = 'e'; *b->last++ = 'l'; *b->last++ = 'e';
    *b->last++ = 'c'; *b->last++ = 't'; *b->last++ = ' ';

    ctx = ngx_http_get_module_ctx(r, ngx_http_redis_module);

    ctx->key.data = b->last;

    if (vv[0] == NULL || vv[0]->not_found || vv[0]->len == 0) {
        ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                       "select 0 redis database" );
        *b->last++ = '0';
    } else {
        b->last = ngx_copy(b->last, vv[0]->data, vv[0]->len);
        ctx->key.len = b->last - ctx->key.data;
    }

    *b->last++ = CR; *b->last++ = LF;


    *b->last++ = 'g'; *b->last++ = 'e'; *b->last++ = 't'; *b->last++ = ' ';

    ctx = ngx_http_get_module_ctx(r, ngx_http_redis_module);

    ctx->key.data = b->last;

    if (escape == 0) {
        b->last = ngx_copy(b->last, vv[1]->data, vv[1]->len);

    } else {
        b->last = (u_char *) ngx_escape_uri(b->last, vv[1]->data, vv[1]->len,
                                            NGX_ESCAPE_REDIS);
    }

    ctx->key.len = b->last - ctx->key.data;

    ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                   "http redis request: \"%V\"", &ctx->key);

    *b->last++ = CR; *b->last++ = LF;

    return NGX_OK;
}
static ngx_chain_t *
ngx_rtmp_notify_update_create(ngx_rtmp_session_t *s, void *arg,
        ngx_pool_t *pool)
{
    ngx_chain_t                    *pl;
    ngx_buf_t                      *b;
    size_t                          name_len, args_len;
    ngx_rtmp_notify_ctx_t          *ctx;
    ngx_str_t                       sfx;

    ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_notify_module);

    pl = ngx_alloc_chain_link(pool);
    if (pl == NULL) {
        return NULL;
    }

    if (ctx->flags & NGX_RTMP_NOTIFY_PUBLISHING) {
        ngx_str_set(&sfx, "_publish");
    } else if (ctx->flags & NGX_RTMP_NOTIFY_PLAYING) {
        ngx_str_set(&sfx, "_play");
    } else {
        ngx_str_null(&sfx);
    }

    name_len = ctx ? ngx_strlen(ctx->name) : 0;
    args_len = ctx ? ngx_strlen(ctx->args) : 0;

    b = ngx_create_temp_buf(pool,
                            sizeof("&call=update") + sfx.len +
                            sizeof("&time=") + NGX_TIME_T_LEN +
                            sizeof("&timestamp=") + NGX_INT32_LEN +
                            sizeof("&name=") + name_len * 3 +
                            1 + args_len);
    if (b == NULL) {
        return NULL;
    }

    pl->buf = b;
    pl->next = NULL;

    b->last = ngx_cpymem(b->last, (u_char*) "&call=update",
                         sizeof("&call=update") - 1);
    b->last = ngx_cpymem(b->last, sfx.data, sfx.len);

    b->last = ngx_cpymem(b->last, (u_char *) "&time=",
                         sizeof("&time=") - 1);
    b->last = ngx_sprintf(b->last, "%T", ngx_cached_time->sec - ctx->start);

    b->last = ngx_cpymem(b->last, (u_char *) "&timestamp=",
                         sizeof("&timestamp=") - 1);
    b->last = ngx_sprintf(b->last, "%D", s->current_time);

    if (name_len) {
        b->last = ngx_cpymem(b->last, (u_char*) "&name=", sizeof("&name=") - 1);
        b->last = (u_char*) ngx_escape_uri(b->last, ctx->name, name_len,
                                           NGX_ESCAPE_ARGS);
    }

    if (args_len) {
        *b->last++ = '&';
        b->last = (u_char *) ngx_cpymem(b->last, ctx->args, args_len);
    }

    return ngx_rtmp_notify_create_request(s, pool, NGX_RTMP_NOTIFY_UPDATE, pl);
}
static ngx_chain_t *
ngx_rtmp_notify_connect_create(ngx_rtmp_session_t *s, void *arg,
        ngx_pool_t *pool)
{
    ngx_rtmp_connect_t             *v = arg;

    ngx_rtmp_notify_srv_conf_t     *nscf;
    ngx_url_t                      *url;
    ngx_chain_t                    *al, *bl;
    ngx_buf_t                      *b;
    ngx_str_t                      *addr_text;
    size_t                          app_len, args_len, flashver_len,
                                    swf_url_len, tc_url_len, page_url_len;

    nscf = ngx_rtmp_get_module_srv_conf(s, ngx_rtmp_notify_module);

    al = ngx_alloc_chain_link(pool);
    if (al == NULL) {
        return NULL;
    }

    /* these values are still missing in session
     * so we have to construct the request from
     * connection struct */

    app_len = ngx_strlen(v->app);
    args_len = ngx_strlen(v->args);
    flashver_len = ngx_strlen(v->flashver);
    swf_url_len = ngx_strlen(v->swf_url);
    tc_url_len = ngx_strlen(v->tc_url);
    page_url_len = ngx_strlen(v->page_url);

    addr_text = &s->connection->addr_text;

    b = ngx_create_temp_buf(pool,
            sizeof("call=connect") - 1 +
            sizeof("&app=") - 1 + app_len * 3 +
            sizeof("&flashver=") - 1 + flashver_len * 3 +
            sizeof("&swfurl=") - 1 + swf_url_len * 3 +
            sizeof("&tcurl=") - 1 + tc_url_len * 3 +
            sizeof("&pageurl=") - 1 + page_url_len * 3 +
            sizeof("&addr=") - 1 + addr_text->len * 3 +
            1 + args_len
        );

    if (b == NULL) {
        return NULL;
    }

    al->buf = b;
    al->next = NULL;

    b->last = ngx_cpymem(b->last, (u_char*) "app=", sizeof("app=") - 1);
    b->last = (u_char*) ngx_escape_uri(b->last, v->app, app_len,
                                       NGX_ESCAPE_ARGS);

    b->last = ngx_cpymem(b->last, (u_char*) "&flashver=",
                         sizeof("&flashver=") - 1);
    b->last = (u_char*) ngx_escape_uri(b->last, v->flashver, flashver_len,
                                       NGX_ESCAPE_ARGS);

    b->last = ngx_cpymem(b->last, (u_char*) "&swfurl=",
                         sizeof("&swfurl=") - 1);
    b->last = (u_char*) ngx_escape_uri(b->last, v->swf_url, swf_url_len,
                                       NGX_ESCAPE_ARGS);

    b->last = ngx_cpymem(b->last, (u_char*) "&tcurl=",
                         sizeof("&tcurl=") - 1);
    b->last = (u_char*) ngx_escape_uri(b->last, v->tc_url, tc_url_len,
                                       NGX_ESCAPE_ARGS);

    b->last = ngx_cpymem(b->last, (u_char*) "&pageurl=",
                         sizeof("&pageurl=") - 1);
    b->last = (u_char*) ngx_escape_uri(b->last, v->page_url, page_url_len,
                                       NGX_ESCAPE_ARGS);

    b->last = ngx_cpymem(b->last, (u_char*) "&addr=", sizeof("&addr=") -1);
    b->last = (u_char*) ngx_escape_uri(b->last, addr_text->data,
                                       addr_text->len, NGX_ESCAPE_ARGS);

    b->last = ngx_cpymem(b->last, (u_char*) "&call=connect",
                         sizeof("&call=connect") - 1);

    if (args_len) {
        *b->last++ = '&';
        b->last = (u_char *) ngx_cpymem(b->last, v->args, args_len);
    }

    url = nscf->url[NGX_RTMP_NOTIFY_CONNECT];

    bl = NULL;

    if (nscf->method == NGX_RTMP_NETCALL_HTTP_POST) {
        bl = al;
        al = NULL;
    }

    return ngx_rtmp_netcall_http_format_request(nscf->method, &url->host,
                                                &url->uri, al, bl, pool,
                                                &ngx_rtmp_notify_urlencoded);
}
static ngx_int_t
ngx_ssl_ocsp_create_request(ngx_ssl_ocsp_ctx_t *ctx)
{
    int            len;
    u_char        *p;
    uintptr_t      escape;
    ngx_str_t      binary, base64;
    ngx_buf_t     *b;
    OCSP_CERTID   *id;
    OCSP_REQUEST  *ocsp;

    ocsp = OCSP_REQUEST_new();
    if (ocsp == NULL) {
        ngx_ssl_error(NGX_LOG_CRIT, ctx->log, 0,
                      "OCSP_REQUEST_new() failed");
        return NGX_ERROR;
    }

    id = OCSP_cert_to_id(NULL, ctx->cert, ctx->issuer);
    if (id == NULL) {
        ngx_ssl_error(NGX_LOG_CRIT, ctx->log, 0,
                      "OCSP_cert_to_id() failed");
        goto failed;
    }

    if (OCSP_request_add0_id(ocsp, id) == NULL) {
        ngx_ssl_error(NGX_LOG_CRIT, ctx->log, 0,
                      "OCSP_request_add0_id() failed");
        OCSP_CERTID_free(id);
        goto failed;
    }

    len = i2d_OCSP_REQUEST(ocsp, NULL);
    if (len <= 0) {
        ngx_ssl_error(NGX_LOG_CRIT, ctx->log, 0,
                      "i2d_OCSP_REQUEST() failed");
        goto failed;
    }

    binary.len = len;
    binary.data = ngx_palloc(ctx->pool, len);
    if (binary.data == NULL) {
        goto failed;
    }

    p = binary.data;
    len = i2d_OCSP_REQUEST(ocsp, &p);
    if (len <= 0) {
        ngx_ssl_error(NGX_LOG_EMERG, ctx->log, 0,
                      "i2d_OCSP_REQUEST() failed");
        goto failed;
    }

    base64.len = ngx_base64_encoded_length(binary.len);
    base64.data = ngx_palloc(ctx->pool, base64.len);
    if (base64.data == NULL) {
        goto failed;
    }

    ngx_encode_base64(&base64, &binary);

    escape = ngx_escape_uri(NULL, base64.data, base64.len,
                            NGX_ESCAPE_URI_COMPONENT);

    ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
                   "ssl ocsp request length %z, escape %d",
                   base64.len, (int) escape);

    len = sizeof("GET ") - 1 + ctx->uri.len + sizeof("/") - 1
          + base64.len + 2 * escape + sizeof(" HTTP/1.0" CRLF) - 1
          + sizeof("Host: ") - 1 + ctx->host.len + sizeof(CRLF) - 1
          + sizeof(CRLF) - 1;

    b = ngx_create_temp_buf(ctx->pool, len);
    if (b == NULL) {
        goto failed;
    }

    p = b->last;

    p = ngx_cpymem(p, "GET ", sizeof("GET ") - 1);
    p = ngx_cpymem(p, ctx->uri.data, ctx->uri.len);

    if (ctx->uri.data[ctx->uri.len - 1] != '/') {
        *p++ = '/';
    }

    if (escape == 0) {
        p = ngx_cpymem(p, base64.data, base64.len);

    } else {
        p = (u_char *) ngx_escape_uri(p, base64.data, base64.len,
                                      NGX_ESCAPE_URI_COMPONENT);
    }

    p = ngx_cpymem(p, " HTTP/1.0" CRLF, sizeof(" HTTP/1.0" CRLF) - 1);
    p = ngx_cpymem(p, "Host: ", sizeof("Host: ") - 1);
    p = ngx_cpymem(p, ctx->host.data, ctx->host.len);
    *p++ = CR; *p++ = LF;

    /* add "\r\n" at the header end */
    *p++ = CR; *p++ = LF;

    b->last = p;
    ctx->request = b;

    OCSP_REQUEST_free(ocsp);

    return NGX_OK;

failed:

    OCSP_REQUEST_free(ocsp);

    return NGX_ERROR;
}
static ngx_int_t
ngx_http_autoindex_handler(ngx_http_request_t *r)
{
    u_char                         *last, *filename;
    size_t                          len, allocated, root;
    ngx_err_t                       err;
    ngx_buf_t                      *b;
    ngx_int_t                       rc, size;
    ngx_str_t                       path;
    ngx_dir_t                       dir;
    ngx_uint_t                      level, utf8;
    ngx_pool_t                     *pool;
    ngx_time_t                     *tp;
    ngx_chain_t                     out;
    ngx_array_t                     entries;
    ngx_http_autoindex_entry_t     *entry;
    ngx_http_autoindex_loc_conf_t  *alcf;

    static char  *months[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
                               "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };

    if (r->uri.data[r->uri.len - 1] != '/') {
        return NGX_DECLINED;
    }

    if (!(r->method & (NGX_HTTP_GET|NGX_HTTP_HEAD))) {
        return NGX_DECLINED;
    }

    alcf = ngx_http_get_module_loc_conf(r, ngx_http_autoindex_module);

    if (!alcf->enable) {
        return NGX_DECLINED;
    }

    /* NGX_DIR_MASK_LEN is lesser than NGX_HTTP_AUTOINDEX_PREALLOCATE */

    last = ngx_http_map_uri_to_path(r, &path, &root,
                                    NGX_HTTP_AUTOINDEX_PREALLOCATE);
    if (last == NULL) {
        return NGX_HTTP_INTERNAL_SERVER_ERROR;
    }

    allocated = path.len;
    path.len = last - path.data;
    if (path.len > 1) {
        path.len--;
    }
    path.data[path.len] = '\0';

    ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                   "http autoindex: \"%s\"", path.data);

    if (ngx_open_dir(&path, &dir) == NGX_ERROR) {
        err = ngx_errno;

        if (err == NGX_ENOENT
            || err == NGX_ENOTDIR
            || err == NGX_ENAMETOOLONG)
        {
            level = NGX_LOG_ERR;
            rc = NGX_HTTP_NOT_FOUND;

        } else if (err == NGX_EACCES) {
            level = NGX_LOG_ERR;
            rc = NGX_HTTP_FORBIDDEN;

        } else {
            level = NGX_LOG_CRIT;
            rc = NGX_HTTP_INTERNAL_SERVER_ERROR;
        }

        ngx_log_error(level, r->connection->log, err,
                      ngx_open_dir_n " \"%s\" failed", path.data);

        return rc;
    }

#if (NGX_SUPPRESS_WARN)

    /* MSVC thinks 'entries' may be used without having been initialized */
    ngx_memzero(&entries, sizeof(ngx_array_t));

#endif

    /* TODO: pool should be temporary pool */
    pool = r->pool;

    if (ngx_array_init(&entries, pool, 40, sizeof(ngx_http_autoindex_entry_t))
        != NGX_OK)
    {
        return ngx_http_autoindex_error(r, &dir, &path);
    }

    r->headers_out.status = NGX_HTTP_OK;
    r->headers_out.content_type_len = sizeof("application/javascript") - 1;
	r->headers_out.content_type.len = sizeof("application/javascript") - 1;
	r->headers_out.content_type.data = (u_char *) "application/javascript";

    rc = ngx_http_send_header(r);

    if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) {
        if (ngx_close_dir(&dir) == NGX_ERROR) {
            ngx_log_error(NGX_LOG_ALERT, r->connection->log, ngx_errno,
                          ngx_close_dir_n " \"%V\" failed", &path);
        }

        return rc;
    }

    filename = path.data;
    filename[path.len] = '/';

    if (r->headers_out.charset.len == 5
        && ngx_strncasecmp(r->headers_out.charset.data, (u_char *) "utf-8", 5)
           == 0)
    {
        utf8 = 1;

    } else {
        utf8 = 0;
    }

    for ( ;; ) {
        ngx_set_errno(0);

        if (ngx_read_dir(&dir) == NGX_ERROR) {
            err = ngx_errno;

            if (err != NGX_ENOMOREFILES) {
                ngx_log_error(NGX_LOG_CRIT, r->connection->log, err,
                              ngx_read_dir_n " \"%V\" failed", &path);
                return ngx_http_autoindex_error(r, &dir, &path);
            }

            break;
        }

        ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                       "http autoindex file: \"%s\"", ngx_de_name(&dir));

        len = ngx_de_namelen(&dir);

        if (ngx_de_name(&dir)[0] == '.') {
            continue;
        }

        if (!dir.valid_info) {

            /* 1 byte for '/' and 1 byte for terminating '\0' */

            if (path.len + 1 + len + 1 > allocated) {
                allocated = path.len + 1 + len + 1
                                     + NGX_HTTP_AUTOINDEX_PREALLOCATE;

                filename = ngx_pnalloc(pool, allocated);
                if (filename == NULL) {
                    return ngx_http_autoindex_error(r, &dir, &path);
                }

                last = ngx_cpystrn(filename, path.data, path.len + 1);
                *last++ = '/';
            }

            ngx_cpystrn(last, ngx_de_name(&dir), len + 1);

            if (ngx_de_info(filename, &dir) == NGX_FILE_ERROR) {
                err = ngx_errno;

                if (err != NGX_ENOENT) {
                    ngx_log_error(NGX_LOG_CRIT, r->connection->log, err,
                                  ngx_de_info_n " \"%s\" failed", filename);

                    if (err == NGX_EACCES) {
                        continue;
                    }

                    return ngx_http_autoindex_error(r, &dir, &path);
                }

                if (ngx_de_link_info(filename, &dir) == NGX_FILE_ERROR) {
                    ngx_log_error(NGX_LOG_CRIT, r->connection->log, ngx_errno,
                                  ngx_de_link_info_n " \"%s\" failed",
                                  filename);
                    return ngx_http_autoindex_error(r, &dir, &path);
                }
            }
        }

        entry = ngx_array_push(&entries);
        if (entry == NULL) {
            return ngx_http_autoindex_error(r, &dir, &path);
        }

        entry->name.len = len;

        entry->name.data = ngx_pnalloc(pool, len + 1);
        if (entry->name.data == NULL) {
            return ngx_http_autoindex_error(r, &dir, &path);
        }

        ngx_cpystrn(entry->name.data, ngx_de_name(&dir), len + 1);

        entry->escape = 2 * ngx_escape_uri(NULL, ngx_de_name(&dir), len,
                                           NGX_ESCAPE_URI_COMPONENT);

        entry->escape_html = ngx_escape_html(NULL, entry->name.data,
                                             entry->name.len);

        if (utf8) {
            entry->utf_len = ngx_utf8_length(entry->name.data, entry->name.len);
        } else {
            entry->utf_len = len;
        }

        entry->dir = ngx_de_is_dir(&dir);
        entry->mtime = ngx_de_mtime(&dir);
        entry->size = ngx_de_size(&dir);
    }

    if (ngx_close_dir(&dir) == NGX_ERROR) {
        ngx_log_error(NGX_LOG_ALERT, r->connection->log, ngx_errno,
                      ngx_close_dir_n " \"%s\" failed", &path);
    }

    b = autoindex_generate_html(r, entries, alcf);


    if (r == r->main) {
        b->last_buf = 1;
    }

    b->last_in_chain = 1;

    out.buf = b;
    out.next = NULL;

    return ngx_http_output_filter(r, &out);
}
Пример #25
0
static ngx_int_t
prepare_request_buffer_construction(ngx_http_request_t *r, passenger_context_t *context,
    buffer_construction_state *state)
{
    unsigned int          len;
    ngx_uint_t            port;
    struct sockaddr_in   *sin;
#if (NGX_HAVE_INET6)
    struct sockaddr_in6  *sin6;
#endif

    switch (r->method) {
    case NGX_HTTP_GET:
        SET_NGX_STR(&state->method, "GET ");
        break;
    case NGX_HTTP_HEAD:
        SET_NGX_STR(&state->method, "HEAD ");
        break;
    case NGX_HTTP_POST:
        SET_NGX_STR(&state->method, "POST ");
        break;
    case NGX_HTTP_PUT:
        SET_NGX_STR(&state->method, "PUT ");
        break;
    case NGX_HTTP_DELETE:
        SET_NGX_STR(&state->method, "DELETE ");
        break;
    case NGX_HTTP_MKCOL:
        SET_NGX_STR(&state->method, "MKCOL ");
        break;
    case NGX_HTTP_COPY:
        SET_NGX_STR(&state->method, "COPY ");
        break;
    case NGX_HTTP_MOVE:
        SET_NGX_STR(&state->method, "MOVE ");
        break;
    case NGX_HTTP_OPTIONS:
        SET_NGX_STR(&state->method, "OPTIONS ");
        break;
    case NGX_HTTP_PROPFIND:
        SET_NGX_STR(&state->method, "PROPFIND ");
        break;
    case NGX_HTTP_PROPPATCH:
        SET_NGX_STR(&state->method, "PROPPATCH ");
        break;
    case NGX_HTTP_LOCK:
        SET_NGX_STR(&state->method, "LOCK ");
        break;
    case NGX_HTTP_UNLOCK:
        SET_NGX_STR(&state->method, "UNLOCK ");
        break;
    case NGX_HTTP_PATCH:
        SET_NGX_STR(&state->method, "PATCH ");
        break;
    case NGX_HTTP_TRACE:
        SET_NGX_STR(&state->method, "TRACE ");
        break;
    default:
        SET_NGX_STR(&state->method, "UNKNOWN ");
        break;
    }

    state->app_type.data = (u_char *) pp_get_app_type_name(context->app_type);
    /* Include null terminator */
    state->app_type.len  = strlen((const char *) state->app_type.data);

    /*
     * Nginx unescapes URI's before passing them to Phusion Passenger,
     * but backend processes expect the escaped version.
     * http://code.google.com/p/phusion-passenger/issues/detail?id=404
     *
     * Here we check whether Nginx has rewritten the URI or not. If not,
     * we can use the raw, unparsed URI as sent by the client.
     */
    if (r->valid_unparsed_uri && r->main) {
        state->escaped_uri = r->unparsed_uri;
        const char *pos = memchr((const char *) r->unparsed_uri.data, '?', r->unparsed_uri.len);
        if (pos != NULL) {
            state->escaped_uri.len = pos - (const char *) r->unparsed_uri.data;
        }
    } else {
        state->escaped_uri.len =
            2 * ngx_escape_uri(NULL, r->uri.data, r->uri.len, NGX_ESCAPE_URI)
            + r->uri.len;
        state->escaped_uri.data = ngx_pnalloc(r->pool, state->escaped_uri.len);
        if (state->escaped_uri.data == NULL) {
            return NGX_ERROR;
        }
        ngx_escape_uri(state->escaped_uri.data, r->uri.data, r->uri.len,
            NGX_ESCAPE_URI);
    }

    if (r->headers_in.chunked) {
        /* If the request body is chunked, then Nginx sets r->headers_in.content_length_n
         * but does not set r->headers_in.headers, so we add this header ourselves.
         */
        state->content_length.data = ngx_pnalloc(r->pool, sizeof("4294967295") - 1);
        state->content_length.len = ngx_snprintf(state->content_length.data,
            sizeof("4294967295") - 1, "%O", r->headers_in.content_length_n)
            - state->content_length.data;
    }

    state->core_password.data = (u_char *) pp_agents_starter_get_core_password(
        pp_agents_starter, &len);
    state->core_password.len  = len;

    switch (r->connection->sockaddr->sa_family) {
    #if (NGX_HAVE_INET6)
    case AF_INET6:
        sin6 = (struct sockaddr_in6 *) r->connection->sockaddr;
        port = ntohs(sin6->sin6_port);
        break;
    #endif

    #if (NGX_HAVE_UNIX_DOMAIN)
    case AF_UNIX:
        port = 0;
        break;
    #endif

    default: /* AF_INET */
        sin = (struct sockaddr_in *) r->connection->sockaddr;
        port = ntohs(sin->sin_port);
        break;
    }

    state->remote_port.data = ngx_pnalloc(r->pool, sizeof("65535") - 1);
    if (state->remote_port.data == NULL) {
        return NGX_ERROR;
    }

    if (port > 0 && port < 65536) {
        state->remote_port.len = ngx_snprintf(state->remote_port.data,
            sizeof("65535") - 1, "%ui", port) - state->remote_port.data;
    } else {
        state->remote_port.len = 0;
    }

    return NGX_OK;
}
static ngx_buf_t *
autoindex_generate_html(ngx_http_request_t *r, ngx_array_t entries,
    ngx_http_autoindex_loc_conf_t  *alcf)
{
    size_t                          len = 0;
    ngx_http_autoindex_entry_t     *entry;
    ngx_uint_t                      i;
    ngx_buf_t *b;

    entry = entries.elts;

    len = MAX_NAME_LEN * entries.nelts + 1024;

    b = ngx_create_temp_buf(r->pool, len);
    if (b == NULL) return NULL;

    *b->last++ = '[';
    *b->last++ = '"';
    b->last = ngx_cpymem(b->last, r->uri.data, r->uri.len);

    *b->last++ = '"';
    *b->last++ = ',';
    *b->last++ = '[';

    for (i = 0; i < entries.nelts; i++) {
        if(entry[i].name.len >= MAX_NAME_LEN) {
            // this name is too long, it's illegal
            continue;
        }

        *b->last++ = '"';
		/*
        if (entry[i].colon) {
             *b->last++ = '.';
             *b->last++ = '/';
        }
		*/
        if (entry[i].escape) {
             ngx_escape_uri(b->last, entry[i].name.data, entry[i].name.len,
                            NGX_ESCAPE_HTML);

             b->last += entry[i].name.len + entry[i].escape;

             // needs to be escaped
        } else {
             b->last = ngx_cpymem(b->last, entry[i].name.data,
                                  entry[i].name.len);
             // otherwise, it's done
        }

        if (entry[i].dir) {
            *b->last++ = '/';
        }

        *b->last++ = '"';

        if(i < entries.nelts-1) {
            *b->last++ = ',';
        }
    }

    *b->last++ = ']';
    *b->last++ = ']';

    return b;
}
static ngx_buf_t *
ngx_http_autoindex_html(ngx_http_request_t *r, ngx_array_t *entries)
{
    u_char                         *last, scale;
    off_t                           length;
    size_t                          len, char_len, escape_html;
    ngx_tm_t                        tm;
    ngx_buf_t                      *b;
    ngx_int_t                       size;
    ngx_uint_t                      i, utf8;
    ngx_time_t                     *tp;
    ngx_http_autoindex_entry_t     *entry;
    ngx_http_autoindex_loc_conf_t  *alcf;

    static u_char  title[] =
        "<html>" CRLF
        "<head><title>Index of "
    ;

    static u_char  header[] =
        "</title></head>" CRLF
        "<body bgcolor=\"white\">" CRLF
        "<h1>Index of "
    ;

    static u_char  tail[] =
        "</body>" CRLF
        "</html>" CRLF
    ;

    static char  *months[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
                               "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };

    if (r->headers_out.charset.len == 5
        && ngx_strncasecmp(r->headers_out.charset.data, (u_char *) "utf-8", 5)
           == 0)
    {
        utf8 = 1;

    } else {
        utf8 = 0;
    }

    escape_html = ngx_escape_html(NULL, r->uri.data, r->uri.len);

    len = sizeof(title) - 1
          + r->uri.len + escape_html
          + sizeof(header) - 1
          + r->uri.len + escape_html
          + sizeof("</h1>") - 1
          + sizeof("<hr><pre><a href=\"../\">../</a>" CRLF) - 1
          + sizeof("</pre><hr>") - 1
          + sizeof(tail) - 1;

    entry = entries->elts;
    for (i = 0; i < entries->nelts; i++) {
        entry[i].escape = 2 * ngx_escape_uri(NULL, entry[i].name.data,
                                             entry[i].name.len,
                                             NGX_ESCAPE_URI_COMPONENT);

        entry[i].escape_html = ngx_escape_html(NULL, entry[i].name.data,
                                               entry[i].name.len);

        if (utf8) {
            entry[i].utf_len = ngx_utf8_length(entry[i].name.data,
                                               entry[i].name.len);
        } else {
            entry[i].utf_len = entry[i].name.len;
        }

        len += sizeof("<a href=\"") - 1
            + entry[i].name.len + entry[i].escape
            + 1                                          /* 1 is for "/" */
            + sizeof("\">") - 1
            + entry[i].name.len - entry[i].utf_len
            + entry[i].escape_html
            + NGX_HTTP_AUTOINDEX_NAME_LEN + sizeof("&gt;") - 2
            + sizeof("</a>") - 1
            + sizeof(" 28-Sep-1970 12:00 ") - 1
            + 20                                         /* the file size */
            + 2;
    }

    b = ngx_create_temp_buf(r->pool, len);
    if (b == NULL) {
        return NULL;
    }

    b->last = ngx_cpymem(b->last, title, sizeof(title) - 1);

    if (escape_html) {
        b->last = (u_char *) ngx_escape_html(b->last, r->uri.data, r->uri.len);
        b->last = ngx_cpymem(b->last, header, sizeof(header) - 1);
        b->last = (u_char *) ngx_escape_html(b->last, r->uri.data, r->uri.len);

    } else {
        b->last = ngx_cpymem(b->last, r->uri.data, r->uri.len);
        b->last = ngx_cpymem(b->last, header, sizeof(header) - 1);
        b->last = ngx_cpymem(b->last, r->uri.data, r->uri.len);
    }

    b->last = ngx_cpymem(b->last, "</h1>", sizeof("</h1>") - 1);

    b->last = ngx_cpymem(b->last, "<hr><pre><a href=\"../\">../</a>" CRLF,
                         sizeof("<hr><pre><a href=\"../\">../</a>" CRLF) - 1);

    alcf = ngx_http_get_module_loc_conf(r, ngx_http_autoindex_module);
    tp = ngx_timeofday();

    for (i = 0; i < entries->nelts; i++) {
        b->last = ngx_cpymem(b->last, "<a href=\"", sizeof("<a href=\"") - 1);

        if (entry[i].escape) {
            ngx_escape_uri(b->last, entry[i].name.data, entry[i].name.len,
                           NGX_ESCAPE_URI_COMPONENT);

            b->last += entry[i].name.len + entry[i].escape;

        } else {
            b->last = ngx_cpymem(b->last, entry[i].name.data,
                                 entry[i].name.len);
        }

        if (entry[i].dir) {
            *b->last++ = '/';
        }

        *b->last++ = '"';
        *b->last++ = '>';

        len = entry[i].utf_len;

        if (entry[i].name.len != len) {
            if (len > NGX_HTTP_AUTOINDEX_NAME_LEN) {
                char_len = NGX_HTTP_AUTOINDEX_NAME_LEN - 3 + 1;

            } else {
                char_len = NGX_HTTP_AUTOINDEX_NAME_LEN + 1;
            }

            last = b->last;
            b->last = ngx_utf8_cpystrn(b->last, entry[i].name.data,
                                       char_len, entry[i].name.len + 1);

            if (entry[i].escape_html) {
                b->last = (u_char *) ngx_escape_html(last, entry[i].name.data,
                                                     b->last - last);
            }

            last = b->last;

        } else {
            if (entry[i].escape_html) {
                if (len > NGX_HTTP_AUTOINDEX_NAME_LEN) {
                    char_len = NGX_HTTP_AUTOINDEX_NAME_LEN - 3;

                } else {
                    char_len = len;
                }

                b->last = (u_char *) ngx_escape_html(b->last,
                                                  entry[i].name.data, char_len);
                last = b->last;

            } else {
                b->last = ngx_cpystrn(b->last, entry[i].name.data,
                                      NGX_HTTP_AUTOINDEX_NAME_LEN + 1);
                last = b->last - 3;
            }
        }

        if (len > NGX_HTTP_AUTOINDEX_NAME_LEN) {
            b->last = ngx_cpymem(last, "..&gt;</a>", sizeof("..&gt;</a>") - 1);

        } else {
            if (entry[i].dir && NGX_HTTP_AUTOINDEX_NAME_LEN - len > 0) {
                *b->last++ = '/';
                len++;
            }

            b->last = ngx_cpymem(b->last, "</a>", sizeof("</a>") - 1);

            if (NGX_HTTP_AUTOINDEX_NAME_LEN - len > 0) {
                ngx_memset(b->last, ' ', NGX_HTTP_AUTOINDEX_NAME_LEN - len);
                b->last += NGX_HTTP_AUTOINDEX_NAME_LEN - len;
            }
        }

        *b->last++ = ' ';

        ngx_gmtime(entry[i].mtime + tp->gmtoff * 60 * alcf->localtime, &tm);

        b->last = ngx_sprintf(b->last, "%02d-%s-%d %02d:%02d ",
                              tm.ngx_tm_mday,
                              months[tm.ngx_tm_mon - 1],
                              tm.ngx_tm_year,
                              tm.ngx_tm_hour,
                              tm.ngx_tm_min);

        if (alcf->exact_size) {
            if (entry[i].dir) {
                b->last = ngx_cpymem(b->last,  "                  -",
                                     sizeof("                  -") - 1);
            } else {
                b->last = ngx_sprintf(b->last, "%19O", entry[i].size);
            }

        } else {
            if (entry[i].dir) {
                b->last = ngx_cpymem(b->last,  "      -",
                                     sizeof("      -") - 1);

            } else {
                length = entry[i].size;

                if (length > 1024 * 1024 * 1024 - 1) {
                    size = (ngx_int_t) (length / (1024 * 1024 * 1024));
                    if ((length % (1024 * 1024 * 1024))
                                                > (1024 * 1024 * 1024 / 2 - 1))
                    {
                        size++;
                    }
                    scale = 'G';

                } else if (length > 1024 * 1024 - 1) {
                    size = (ngx_int_t) (length / (1024 * 1024));
                    if ((length % (1024 * 1024)) > (1024 * 1024 / 2 - 1)) {
                        size++;
                    }
                    scale = 'M';

                } else if (length > 9999) {
                    size = (ngx_int_t) (length / 1024);
                    if (length % 1024 > 511) {
                        size++;
                    }
                    scale = 'K';

                } else {
                    size = (ngx_int_t) length;
                    scale = '\0';
                }

                if (scale) {
                    b->last = ngx_sprintf(b->last, "%6i%c", size, scale);

                } else {
                    b->last = ngx_sprintf(b->last, " %6i", size);
                }
            }
        }

        *b->last++ = CR;
        *b->last++ = LF;
    }

    b->last = ngx_cpymem(b->last, "</pre><hr>", sizeof("</pre><hr>") - 1);

    b->last = ngx_cpymem(b->last, tail, sizeof(tail) - 1);

    return b;
}
ngx_int_t
ngx_http_memc_create_incr_decr_cmd_request(ngx_http_request_t *r)
{
    size_t                          len;
    ngx_buf_t                      *b;
    ngx_http_memc_ctx_t            *ctx;
    ngx_chain_t                    *cl;
    uintptr_t                       escape;
    ngx_http_variable_value_t      *key_vv;
    ngx_http_variable_value_t      *value_vv;

    ctx = ngx_http_get_module_ctx(r, ngx_http_memc_module);

    /* prepare the "key" argument */

    key_vv = ctx->memc_key_vv;

    if (key_vv == NULL || key_vv->not_found || key_vv->len == 0) {
        ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
                      "the \"$memc_key\" variable is not set");
        return NGX_ERROR;
    }

    escape = 2 * ngx_escape_uri(NULL, key_vv->data, key_vv->len,
            NGX_ESCAPE_MEMCACHED);

    /* prepare the "value" argument */

    value_vv = ctx->memc_value_vv;

    /* XXX validate if $memc_value_vv is a valid uint64 string */

    len = ctx->cmd_str.len + sizeof(' ') + key_vv->len + escape
        + sizeof(' ') + value_vv->len + sizeof(CRLF) - 1;

    b = ngx_create_temp_buf(r->pool, len);
    if (b == NULL) {
        return NGX_ERROR;
    }

    cl = ngx_alloc_chain_link(r->pool);
    if (cl == NULL) {
        return NGX_ERROR;
    }

    cl->buf = b;
    cl->next = NULL;

    r->upstream->request_bufs = cl;

    b->last = ngx_copy(b->last, ctx->cmd_str.data, ctx->cmd_str.len);

    *b->last++ = ' ';

    if (escape == 0) {
        b->last = ngx_copy(b->last, key_vv->data, key_vv->len);

    } else {
        b->last = (u_char *) ngx_escape_uri(b->last, key_vv->data, key_vv->len,
                                        NGX_ESCAPE_MEMCACHED);
    }

    *b->last++ = ' ';

    b->last = ngx_copy(b->last, value_vv->data, value_vv->len);

    *b->last++ = CR; *b->last++ = LF;

    return NGX_OK;
}
ngx_int_t
ngx_http_memc_create_delete_cmd_request(ngx_http_request_t *r)
{
    size_t                          len;
    ngx_buf_t                      *b;
    ngx_http_memc_ctx_t            *ctx;
    ngx_chain_t                    *cl;
    uintptr_t                       escape;
    ngx_http_variable_value_t      *key_vv;
    ngx_http_variable_value_t      *exptime_vv;

    ctx = ngx_http_get_module_ctx(r, ngx_http_memc_module);

    /* prepare the "key" argument */

    key_vv = ctx->memc_key_vv;

    if (key_vv == NULL || key_vv->not_found || key_vv->len == 0) {
        ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
                      "the \"$memc_key\" variable is not set");
        return NGX_ERROR;
    }

    escape = 2 * ngx_escape_uri(NULL, key_vv->data, key_vv->len,
            NGX_ESCAPE_MEMCACHED);

    /* prepare the (optional) "exptime" argument */

    exptime_vv = ctx->memc_exptime_vv;

    if (exptime_vv == NULL) {
        return NGX_HTTP_INTERNAL_SERVER_ERROR;
    }

    len = ctx->cmd_str.len + sizeof(' ') + key_vv->len + escape;

    if ( ! exptime_vv->not_found && exptime_vv->len) {
        dd("found exptime: %s", exptime_vv->data);

        len += sizeof(' ') + exptime_vv->len;
    }

    len += sizeof(CRLF) - 1;

    b = ngx_create_temp_buf(r->pool, len);
    if (b == NULL) {
        return NGX_ERROR;
    }

    cl = ngx_alloc_chain_link(r->pool);
    if (cl == NULL) {
        return NGX_ERROR;
    }

    cl->buf = b;
    cl->next = NULL;

    r->upstream->request_bufs = cl;

    b->last = ngx_copy(b->last, ctx->cmd_str.data, ctx->cmd_str.len);

    *b->last++ = ' ';

    if (escape == 0) {
        b->last = ngx_copy(b->last, key_vv->data, key_vv->len);

    } else {
        b->last = (u_char *) ngx_escape_uri(b->last, key_vv->data, key_vv->len,
                                        NGX_ESCAPE_MEMCACHED);
    }

    if ( ! exptime_vv->not_found && exptime_vv->len) {
        *b->last++ = ' ';
        b->last = ngx_copy(b->last, exptime_vv->data, exptime_vv->len);
    }

    *b->last++ = CR; *b->last++ = LF;

    return NGX_OK;
}
ngx_int_t
ngx_http_memc_create_get_cmd_request(ngx_http_request_t *r)
{
    size_t                          len;
    uintptr_t                       escape;
    ngx_buf_t                      *b;
    ngx_chain_t                    *cl;
    ngx_http_memc_ctx_t            *ctx;
    ngx_http_variable_value_t      *vv;

    ctx = ngx_http_get_module_ctx(r, ngx_http_memc_module);

    vv = ctx->memc_key_vv;

    if (vv == NULL || vv->not_found || vv->len == 0) {
        ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
                      "the \"$memc_key\" variable is not set");
        return NGX_ERROR;
    }

    escape = 2 * ngx_escape_uri(NULL, vv->data, vv->len, NGX_ESCAPE_MEMCACHED);

    len = sizeof("get ") - 1 + vv->len + escape + sizeof(CRLF) - 1;

    b = ngx_create_temp_buf(r->pool, len);
    if (b == NULL) {
        return NGX_ERROR;
    }

    cl = ngx_alloc_chain_link(r->pool);
    if (cl == NULL) {
        return NGX_ERROR;
    }

    cl->buf = b;
    cl->next = NULL;

    r->upstream->request_bufs = cl;

    *b->last++ = 'g'; *b->last++ = 'e'; *b->last++ = 't'; *b->last++ = ' ';

    ctx->key.data = b->last;

    if (escape == 0) {
        b->last = ngx_copy(b->last, vv->data, vv->len);

    } else {
        b->last = (u_char *) ngx_escape_uri(b->last, vv->data, vv->len,
                                            NGX_ESCAPE_MEMCACHED);
    }

    ctx->key.len = b->last - ctx->key.data;

    ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                   "http memcached request: \"%V\"", &ctx->key);

    *b->last++ = CR; *b->last++ = LF;

    ctx->parser_state = NGX_ERROR;

    return NGX_OK;
}