FU

 view release on metacpan or  search on metacpan

c/fcgi.c  view on Meta::CPAN

            default:
                memset(tmp+8, 0, 8);
                tmp[8] = rec->type;
                rec->type = FCGI_UNKNOWN_TYPE;
                rec->len = 8;
                rec->id = 0;
                if ((r = fufcgi_write_record(ctx, rec, tmp)) != FUFE_OK) return r;
                break;
        }
    }
}

static int fufcgi_read_params(pTHX_ fufcgi *ctx, fufcgi_rec *rec) {
    int r;
    fufcgi_param p;
    p.state = FUFC_INIT;

    SV *valsv = NULL;
    char *val = NULL;
    int valleft = 0;

    while (1) {
        if ((r = fufcgi_read_req_record(ctx, rec)) != FUFE_OK) return r;
        if (rec->type == FCGI_ABORT_REQUEST) return FUFE_OK;
        if (rec->type != FCGI_PARAMS) return FUFE_PROTO;
        if (rec->len == 0) return p.state != FUFC_INIT || valleft ? FUFE_PROTO : FUFE_OK;

        char *buf = rec->data;
        char *end = rec->data + rec->len;
        while (buf < end) {
            if (valleft) {
                r = valleft > end - buf ? end - buf : valleft;
                if (val) {
                    memcpy(val, buf, r);
                    val += r;
                }
                valleft -= r;
                buf += r;
                if (val && !valleft) {
                    *val = 0;
                    SvCUR_set(valsv, p.vallen);
                }
                continue;
            }
            if ((buf = fufcgi_param_parse(&p, buf, end)) == NULL) return FUFE_PLEN;
            if (p.state != FUFC_INIT) break;

            valsv = NULL;
            val = NULL;
            valleft = p.vallen;

            /* https://www.rfc-editor.org/rfc/rfc3875 */

            /* Request header */
            if (p.namelen > 5 && memcmp(p.name, "HTTP_", 5) == 0) {
                p.namelen -= 5;
                p.name += 5;
                for (r=0; r<p.namelen; r++)
                    p.name[r] = p.name[r] == '_' ? '-' : p.name[r] >= 'A' && p.name[r] <= 'Z' ? p.name[r] | 0x20 : p.name[r];
                if (!(p.namelen == 14 && memcmp(p.name, "content-length", 14) == 0)
                        && !(p.namelen == 12 && memcmp(p.name, "content-type", 12) == 0)) {
                    valsv = newSV(p.vallen+1);
                    hv_store(ctx->headers, p.name, p.namelen, valsv, 0);
                }

            } else if (p.namelen == 14 && memcmp(p.name, "CONTENT_LENGTH", 14) == 0) {
                valsv = newSV(p.vallen+1);
                hv_stores(ctx->headers, "content-length", valsv);

            } else if (p.namelen == 12 && memcmp(p.name, "CONTENT_TYPE", 12) == 0) {
                valsv = newSV(p.vallen+1);
                hv_stores(ctx->headers, "content-type", valsv);

            } else if (p.namelen == 11 && memcmp(p.name, "REMOTE_ADDR", 11) == 0) {
                valsv = newSV(p.vallen+1);
                hv_stores(ctx->params, "ip", valsv);

            } else if (p.namelen == 12 && memcmp(p.name, "QUERY_STRING", 12) == 0) {
                valsv = newSV(p.vallen+1);
                hv_stores(ctx->params, "qs", valsv);

            } else if (p.namelen == 14 && memcmp(p.name, "REQUEST_METHOD", 14) == 0) {
                valsv = newSV(p.vallen+1);
                hv_stores(ctx->params, "method", valsv);

            /* Not in rfc3875; there's no standardized parameter for the URI,
             * but every FastCGI-capable web server includes this one */
            } else if (p.namelen == 11 && memcmp(p.name, "REQUEST_URI", 11) == 0) {
                valsv = newSV(p.vallen+1);
                hv_stores(ctx->params, "path", valsv);

            } else { /* ignore */ }

            if (valsv) {
                SvPOK_only(valsv);
                val = SvPVX(valsv);
                *val = 0; /* in case vallen = 0 */
            }
        }
    }
}

static int fufcgi_read_req(pTHX_ fufcgi *ctx, SV *headers, SV *params) {
    if (ctx->reqid) fu_confess("Invalid attempt to read FastCGI request before finishing the previous one");
    fufcgi_rec rec;
    int r;

    ctx->off = ctx->len = 0;
    ctx->headers = (HV *)SvRV(headers);
    ctx->params = (HV *)SvRV(params);
    if ((r = fufcgi_read_params(aTHX_ ctx, &rec)) != FUFE_OK) return r;

    int stdinlen = 0;
    SV **contentlength = hv_fetchs(ctx->headers, "content-length", 0);
    if (contentlength && *contentlength) {
        UV uv = 0;
        char *v = SvPV_nolen(*contentlength);
        if (*v && !grok_atoUV(v, &uv, NULL)) return FUFE_CLEN;
        if (uv >= INT_MAX) return FUFE_CLEN;
        stdinlen = uv;
    }

    SV *sv = newSV(stdinlen+1);
    hv_stores(ctx->params, "body", sv);
    SvPOK_only(sv);
    char *stdinbuf = SvPVX(sv);
    int stdinleft = stdinlen;

    while (1) {
        if (rec.type == FCGI_ABORT_REQUEST) return FUFE_ABORT;
        else if (rec.type == FCGI_PARAMS) {
            if (rec.len != 0) return FUFE_PROTO;



( run in 0.599 second using v1.01-cache-2.11-cpan-d7f47b0818f )