Annotation of embedaddon/nginx/src/http/modules/perl/nginx.xs, revision 1.1.1.1

1.1       misho       1: 
                      2: /*
                      3:  * Copyright (C) Igor Sysoev
                      4:  * Copyright (C) Nginx, Inc.
                      5:  */
                      6: 
                      7: 
                      8: #define PERL_NO_GET_CONTEXT
                      9: 
                     10: #include <ngx_config.h>
                     11: #include <ngx_core.h>
                     12: #include <ngx_http.h>
                     13: #include <ngx_http_perl_module.h>
                     14: 
                     15: #include "XSUB.h"
                     16: 
                     17: 
                     18: #define ngx_http_perl_set_request(r)                                          \
                     19:     r = INT2PTR(ngx_http_request_t *, SvIV((SV *) SvRV(ST(0))))
                     20: 
                     21: 
                     22: #define ngx_http_perl_set_targ(p, len)                                        \
                     23:                                                                               \
                     24:     SvUPGRADE(TARG, SVt_PV);                                                  \
                     25:     SvPOK_on(TARG);                                                           \
                     26:     sv_setpvn(TARG, (char *) p, len)
                     27: 
                     28: 
                     29: static ngx_int_t
                     30: ngx_http_perl_sv2str(pTHX_ ngx_http_request_t *r, ngx_str_t *s, SV *sv)
                     31: {
                     32:     u_char  *p;
                     33:     STRLEN   len;
                     34: 
                     35:     if (SvROK(sv) && SvTYPE(SvRV(sv)) == SVt_PV) {
                     36:         sv = SvRV(sv);
                     37:     }
                     38: 
                     39:     p = (u_char *) SvPV(sv, len);
                     40: 
                     41:     s->len = len;
                     42: 
                     43:     if (SvREADONLY(sv) && SvPOK(sv)) {
                     44:         s->data = p;
                     45: 
                     46:         ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                     47:                        "perl sv2str: %08XD \"%V\"", sv->sv_flags, s);
                     48: 
                     49:         return NGX_OK;
                     50:     }
                     51: 
                     52:     s->data = ngx_pnalloc(r->pool, len);
                     53:     if (s->data == NULL) {
                     54:         return NGX_ERROR;
                     55:     }
                     56: 
                     57:     ngx_memcpy(s->data, p, len);
                     58: 
                     59:     ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                     60:                    "perl sv2str: %08XD \"%V\"", sv->sv_flags, s);
                     61: 
                     62:     return NGX_OK;
                     63: }
                     64: 
                     65: 
                     66: static ngx_int_t
                     67: ngx_http_perl_output(ngx_http_request_t *r, ngx_buf_t *b)
                     68: {
                     69:     ngx_chain_t           out;
                     70: #if (NGX_HTTP_SSI)
                     71:     ngx_chain_t          *cl;
                     72:     ngx_http_perl_ctx_t  *ctx;
                     73: 
                     74:     ctx = ngx_http_get_module_ctx(r, ngx_http_perl_module);
                     75: 
                     76:     if (ctx->ssi) {
                     77:         cl = ngx_alloc_chain_link(r->pool);
                     78:         if (cl == NULL) {
                     79:             return NGX_ERROR;
                     80:         }
                     81: 
                     82:         cl->buf = b;
                     83:         cl->next = NULL;
                     84:         *ctx->ssi->last_out = cl;
                     85:         ctx->ssi->last_out = &cl->next;
                     86: 
                     87:         return NGX_OK;
                     88:     }
                     89: #endif
                     90: 
                     91:     out.buf = b;
                     92:     out.next = NULL;
                     93: 
                     94:     return ngx_http_output_filter(r, &out);
                     95: }
                     96: 
                     97: 
                     98: MODULE = nginx    PACKAGE = nginx
                     99: 
                    100: 
                    101: void
                    102: status(r, code)
                    103:     CODE:
                    104: 
                    105:     ngx_http_request_t  *r;
                    106: 
                    107:     ngx_http_perl_set_request(r);
                    108: 
                    109:     r->headers_out.status = SvIV(ST(1));
                    110: 
                    111:     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                    112:                    "perl status: %d", r->headers_out.status);
                    113: 
                    114:     XSRETURN_UNDEF;
                    115: 
                    116: 
                    117: void
                    118: send_http_header(r, ...)
                    119:     CODE:
                    120: 
                    121:     ngx_http_request_t  *r;
                    122:     SV                  *sv;
                    123: 
                    124:     ngx_http_perl_set_request(r);
                    125: 
                    126:     if (r->headers_out.status == 0) {
                    127:         r->headers_out.status = NGX_HTTP_OK;
                    128:     }
                    129: 
                    130:     if (items != 1) {
                    131:         sv = ST(1);
                    132: 
                    133:         if (ngx_http_perl_sv2str(aTHX_ r, &r->headers_out.content_type, sv)
                    134:             != NGX_OK)
                    135:         {
                    136:             XSRETURN_EMPTY;
                    137:         }
                    138: 
                    139:         r->headers_out.content_type_len = r->headers_out.content_type.len;
                    140: 
                    141:     } else {
                    142:         if (ngx_http_set_content_type(r) != NGX_OK) {
                    143:             XSRETURN_EMPTY;
                    144:         }
                    145:     }
                    146: 
                    147:     (void) ngx_http_send_header(r);
                    148: 
                    149: 
                    150: void
                    151: header_only(r)
                    152:     CODE:
                    153: 
                    154:     dXSTARG;
                    155:     ngx_http_request_t  *r;
                    156: 
                    157:     ngx_http_perl_set_request(r);
                    158: 
                    159:     sv_upgrade(TARG, SVt_IV);
                    160:     sv_setiv(TARG, r->header_only);
                    161: 
                    162:     ST(0) = TARG;
                    163: 
                    164: 
                    165: void
                    166: uri(r)
                    167:     CODE:
                    168: 
                    169:     dXSTARG;
                    170:     ngx_http_request_t  *r;
                    171: 
                    172:     ngx_http_perl_set_request(r);
                    173:     ngx_http_perl_set_targ(r->uri.data, r->uri.len);
                    174: 
                    175:     ST(0) = TARG;
                    176: 
                    177: 
                    178: void
                    179: args(r)
                    180:     CODE:
                    181: 
                    182:     dXSTARG;
                    183:     ngx_http_request_t  *r;
                    184: 
                    185:     ngx_http_perl_set_request(r);
                    186:     ngx_http_perl_set_targ(r->args.data, r->args.len);
                    187: 
                    188:     ST(0) = TARG;
                    189: 
                    190: 
                    191: void
                    192: request_method(r)
                    193:     CODE:
                    194: 
                    195:     dXSTARG;
                    196:     ngx_http_request_t  *r;
                    197: 
                    198:     ngx_http_perl_set_request(r);
                    199:     ngx_http_perl_set_targ(r->method_name.data, r->method_name.len);
                    200: 
                    201:     ST(0) = TARG;
                    202: 
                    203: 
                    204: void
                    205: remote_addr(r)
                    206:     CODE:
                    207: 
                    208:     dXSTARG;
                    209:     ngx_http_request_t  *r;
                    210: 
                    211:     ngx_http_perl_set_request(r);
                    212:     ngx_http_perl_set_targ(r->connection->addr_text.data,
                    213:                            r->connection->addr_text.len);
                    214: 
                    215:     ST(0) = TARG;
                    216: 
                    217: 
                    218: void
                    219: header_in(r, key)
                    220:     CODE:
                    221: 
                    222:     dXSTARG;
                    223:     ngx_http_request_t         *r;
                    224:     SV                         *key;
                    225:     u_char                     *p, *lowcase_key, *value, sep;
                    226:     STRLEN                      len;
                    227:     ssize_t                     size;
                    228:     ngx_uint_t                  i, n, hash;
                    229:     ngx_array_t                *a;
                    230:     ngx_list_part_t            *part;
                    231:     ngx_table_elt_t            *h, **ph;
                    232:     ngx_http_header_t          *hh;
                    233:     ngx_http_core_main_conf_t  *cmcf;
                    234: 
                    235:     ngx_http_perl_set_request(r);
                    236: 
                    237:     key = ST(1);
                    238: 
                    239:     if (SvROK(key) && SvTYPE(SvRV(key)) == SVt_PV) {
                    240:         key = SvRV(key);
                    241:     }
                    242: 
                    243:     p = (u_char *) SvPV(key, len);
                    244: 
                    245:     /* look up hashed headers */
                    246: 
                    247:     lowcase_key = ngx_pnalloc(r->pool, len);
                    248:     if (lowcase_key == NULL) {
                    249:         XSRETURN_UNDEF;
                    250:     }
                    251: 
                    252:     hash = ngx_hash_strlow(lowcase_key, p, len);
                    253: 
                    254:     cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
                    255: 
                    256:     hh = ngx_hash_find(&cmcf->headers_in_hash, hash, lowcase_key, len);
                    257: 
                    258:     if (hh) {
                    259: 
                    260:         if (hh->offset == offsetof(ngx_http_headers_in_t, cookies)) {
                    261:             sep = ';';
                    262:             goto multi;
                    263:         }
                    264: 
                    265:     #if (NGX_HTTP_X_FORWARDED_FOR)
                    266:         if (hh->offset == offsetof(ngx_http_headers_in_t, x_forwarded_for)) {
                    267:             sep = ',';
                    268:             goto multi;
                    269:         }
                    270:     #endif
                    271: 
                    272:         if (hh->offset) {
                    273: 
                    274:             ph = (ngx_table_elt_t **) ((char *) &r->headers_in + hh->offset);
                    275: 
                    276:             if (*ph) {
                    277:                 ngx_http_perl_set_targ((*ph)->value.data, (*ph)->value.len);
                    278: 
                    279:                 goto done;
                    280:             }
                    281: 
                    282:             XSRETURN_UNDEF;
                    283:         }
                    284: 
                    285:     multi:
                    286: 
                    287:         /* Cookie, X-Forwarded-For */
                    288: 
                    289:         a = (ngx_array_t *) ((char *) &r->headers_in + hh->offset);
                    290: 
                    291:         n = a->nelts;
                    292: 
                    293:         if (n == 0) {
                    294:             XSRETURN_UNDEF;
                    295:         }
                    296: 
                    297:         ph = a->elts;
                    298: 
                    299:         if (n == 1) {
                    300:             ngx_http_perl_set_targ((*ph)->value.data, (*ph)->value.len);
                    301: 
                    302:             goto done;
                    303:         }
                    304: 
                    305:         size = - (ssize_t) (sizeof("; ") - 1);
                    306: 
                    307:         for (i = 0; i < n; i++) {
                    308:             size += ph[i]->value.len + sizeof("; ") - 1;
                    309:         }
                    310: 
                    311:         value = ngx_pnalloc(r->pool, size);
                    312:         if (value == NULL) {
                    313:             XSRETURN_UNDEF;
                    314:         }
                    315: 
                    316:         p = value;
                    317: 
                    318:         for (i = 0; /* void */ ; i++) {
                    319:             p = ngx_copy(p, ph[i]->value.data, ph[i]->value.len);
                    320: 
                    321:             if (i == n - 1) {
                    322:                 break;
                    323:             }
                    324: 
                    325:             *p++ = sep; *p++ = ' ';
                    326:         }
                    327: 
                    328:         ngx_http_perl_set_targ(value, size);
                    329: 
                    330:         goto done;
                    331:     }
                    332: 
                    333:     /* iterate over all headers */
                    334: 
                    335:     part = &r->headers_in.headers.part;
                    336:     h = part->elts;
                    337: 
                    338:     for (i = 0; /* void */ ; i++) {
                    339: 
                    340:         if (i >= part->nelts) {
                    341:             if (part->next == NULL) {
                    342:                 break;
                    343:             }
                    344: 
                    345:             part = part->next;
                    346:             h = part->elts;
                    347:             i = 0;
                    348:         }
                    349: 
                    350:         if (len != h[i].key.len
                    351:             || ngx_strcasecmp(p, h[i].key.data) != 0)
                    352:         {
                    353:             continue;
                    354:         }
                    355: 
                    356:         ngx_http_perl_set_targ(h[i].value.data, h[i].value.len);
                    357: 
                    358:         goto done;
                    359:     }
                    360: 
                    361:     XSRETURN_UNDEF;
                    362: 
                    363:     done:
                    364: 
                    365:     ST(0) = TARG;
                    366: 
                    367: 
                    368: void
                    369: has_request_body(r, next)
                    370:     CODE:
                    371: 
                    372:     dXSTARG;
                    373:     ngx_http_request_t   *r;
                    374:     ngx_http_perl_ctx_t  *ctx;
                    375: 
                    376:     ngx_http_perl_set_request(r);
                    377: 
                    378:     if (r->headers_in.content_length_n <= 0 && !r->headers_in.chunked) {
                    379:         XSRETURN_UNDEF;
                    380:     }
                    381: 
                    382:     ctx = ngx_http_get_module_ctx(r, ngx_http_perl_module);
                    383:     ctx->next = SvRV(ST(1));
                    384: 
                    385:     r->request_body_in_single_buf = 1;
                    386:     r->request_body_in_persistent_file = 1;
                    387:     r->request_body_in_clean_file = 1;
                    388: 
                    389:     if (r->request_body_in_file_only) {
                    390:         r->request_body_file_log_level = 0;
                    391:     }
                    392: 
                    393:     ngx_http_read_client_request_body(r, ngx_http_perl_handle_request);
                    394: 
                    395:     sv_upgrade(TARG, SVt_IV);
                    396:     sv_setiv(TARG, 1);
                    397: 
                    398:     ST(0) = TARG;
                    399: 
                    400: 
                    401: void
                    402: request_body(r)
                    403:     CODE:
                    404: 
                    405:     dXSTARG;
                    406:     ngx_http_request_t  *r;
                    407:     u_char              *p, *data;
                    408:     size_t               len;
                    409:     ngx_buf_t           *buf;
                    410:     ngx_chain_t         *cl;
                    411: 
                    412:     ngx_http_perl_set_request(r);
                    413: 
                    414:     if (r->request_body == NULL
                    415:         || r->request_body->temp_file
                    416:         || r->request_body->bufs == NULL)
                    417:     {
                    418:         XSRETURN_UNDEF;
                    419:     }
                    420: 
                    421:     cl = r->request_body->bufs;
                    422:     buf = cl->buf;
                    423: 
                    424:     if (cl->next == NULL) {
                    425:         len = buf->last - buf->pos;
                    426:         data = buf->pos;
                    427:         goto done;
                    428:     }
                    429: 
                    430:     len = buf->last - buf->pos;
                    431:     cl = cl->next;
                    432: 
                    433:     for ( /* void */ ; cl; cl = cl->next) {
                    434:         buf = cl->buf;
                    435:         len += buf->last - buf->pos;
                    436:     }
                    437: 
                    438:     p = ngx_pnalloc(r->pool, len);
                    439:     if (p == NULL) {
                    440:         XSRETURN_UNDEF;
                    441:     }
                    442: 
                    443:     data = p;
                    444:     cl = r->request_body->bufs;
                    445: 
                    446:     for ( /* void */ ; cl; cl = cl->next) {
                    447:         buf = cl->buf;
                    448:         p = ngx_cpymem(p, buf->pos, buf->last - buf->pos);
                    449:     }
                    450: 
                    451:     done:
                    452: 
                    453:     if (len == 0) {
                    454:         XSRETURN_UNDEF;
                    455:     }
                    456: 
                    457:     ngx_http_perl_set_targ(data, len);
                    458: 
                    459:     ST(0) = TARG;
                    460: 
                    461: 
                    462: void
                    463: request_body_file(r)
                    464:     CODE:
                    465: 
                    466:     dXSTARG;
                    467:     ngx_http_request_t  *r;
                    468: 
                    469:     ngx_http_perl_set_request(r);
                    470: 
                    471:     if (r->request_body == NULL || r->request_body->temp_file == NULL) {
                    472:         XSRETURN_UNDEF;
                    473:     }
                    474: 
                    475:     ngx_http_perl_set_targ(r->request_body->temp_file->file.name.data,
                    476:                            r->request_body->temp_file->file.name.len);
                    477: 
                    478:     ST(0) = TARG;
                    479: 
                    480: 
                    481: void
                    482: discard_request_body(r)
                    483:     CODE:
                    484: 
                    485:     ngx_http_request_t  *r;
                    486: 
                    487:     ngx_http_perl_set_request(r);
                    488: 
                    489:     ngx_http_discard_request_body(r);
                    490: 
                    491: 
                    492: void
                    493: header_out(r, key, value)
                    494:     CODE:
                    495: 
                    496:     ngx_http_request_t  *r;
                    497:     SV                  *key;
                    498:     SV                  *value;
                    499:     ngx_table_elt_t     *header;
                    500: 
                    501:     ngx_http_perl_set_request(r);
                    502: 
                    503:     key = ST(1);
                    504:     value = ST(2);
                    505: 
                    506:     header = ngx_list_push(&r->headers_out.headers);
                    507:     if (header == NULL) {
                    508:         XSRETURN_EMPTY;
                    509:     }
                    510: 
                    511:     header->hash = 1;
                    512: 
                    513:     if (ngx_http_perl_sv2str(aTHX_ r, &header->key, key) != NGX_OK) {
                    514:         XSRETURN_EMPTY;
                    515:     }
                    516: 
                    517:     if (ngx_http_perl_sv2str(aTHX_ r, &header->value, value) != NGX_OK) {
                    518:         XSRETURN_EMPTY;
                    519:     }
                    520: 
                    521:     if (header->key.len == sizeof("Content-Length") - 1
                    522:         && ngx_strncasecmp(header->key.data, (u_char *) "Content-Length",
                    523:                            sizeof("Content-Length") - 1) == 0)
                    524:     {
                    525:         r->headers_out.content_length_n = (off_t) SvIV(value);
                    526:         r->headers_out.content_length = header;
                    527:     }
                    528: 
                    529:     if (header->key.len == sizeof("Content-Encoding") - 1
                    530:         && ngx_strncasecmp(header->key.data, (u_char *) "Content-Encoding",
                    531:                            sizeof("Content-Encoding") - 1) == 0)
                    532:     {
                    533:         r->headers_out.content_encoding = header;
                    534:     }
                    535: 
                    536: 
                    537: void
                    538: filename(r)
                    539:     CODE:
                    540: 
                    541:     dXSTARG;
                    542:     size_t                root;
                    543:     ngx_http_request_t   *r;
                    544:     ngx_http_perl_ctx_t  *ctx;
                    545: 
                    546:     ngx_http_perl_set_request(r);
                    547: 
                    548:     ctx = ngx_http_get_module_ctx(r, ngx_http_perl_module);
                    549:     if (ctx->filename.data) {
                    550:         goto done;
                    551:     }
                    552: 
                    553:     if (ngx_http_map_uri_to_path(r, &ctx->filename, &root, 0) == NULL) {
                    554:         XSRETURN_UNDEF;
                    555:     }
                    556: 
                    557:     ctx->filename.len--;
                    558:     sv_setpv(PL_statname, (char *) ctx->filename.data);
                    559: 
                    560:     done:
                    561: 
                    562:     ngx_http_perl_set_targ(ctx->filename.data, ctx->filename.len);
                    563: 
                    564:     ST(0) = TARG;
                    565: 
                    566: 
                    567: void
                    568: print(r, ...)
                    569:     CODE:
                    570: 
                    571:     ngx_http_request_t  *r;
                    572:     SV                  *sv;
                    573:     int                  i;
                    574:     u_char              *p;
                    575:     size_t               size;
                    576:     STRLEN               len;
                    577:     ngx_buf_t           *b;
                    578: 
                    579:     ngx_http_perl_set_request(r);
                    580: 
                    581:     if (items == 2) {
                    582: 
                    583:         /*
                    584:          * do zero copy for prolate single read-only SV:
                    585:          *     $r->print("some text\n");
                    586:          */
                    587: 
                    588:         sv = ST(1);
                    589: 
                    590:         if (SvROK(sv) && SvTYPE(SvRV(sv)) == SVt_PV) {
                    591:             sv = SvRV(sv);
                    592:         }
                    593: 
                    594:         if (SvREADONLY(sv) && SvPOK(sv)) {
                    595: 
                    596:             p = (u_char *) SvPV(sv, len);
                    597: 
                    598:             if (len == 0) {
                    599:                 XSRETURN_EMPTY;
                    600:             }
                    601: 
                    602:             b = ngx_calloc_buf(r->pool);
                    603:             if (b == NULL) {
                    604:                 XSRETURN_EMPTY;
                    605:             }
                    606: 
                    607:             b->memory = 1;
                    608:             b->pos = p;
                    609:             b->last = p + len;
                    610:             b->start = p;
                    611:             b->end = b->last;
                    612: 
                    613:             ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                    614:                            "$r->print: read-only SV: %z", len);
                    615: 
                    616:             goto out;
                    617:         }
                    618:     }
                    619: 
                    620:     size = 0;
                    621: 
                    622:     for (i = 1; i < items; i++) {
                    623: 
                    624:         sv = ST(i);
                    625: 
                    626:         if (SvROK(sv) && SvTYPE(SvRV(sv)) == SVt_PV) {
                    627:             sv = SvRV(sv);
                    628:         }
                    629: 
                    630:         (void) SvPV(sv, len);
                    631: 
                    632:         ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                    633:                        "$r->print: copy SV: %z", len);
                    634: 
                    635:         size += len;
                    636:     }
                    637: 
                    638:     if (size == 0) {
                    639:         XSRETURN_EMPTY;
                    640:     }
                    641: 
                    642:     b = ngx_create_temp_buf(r->pool, size);
                    643:     if (b == NULL) {
                    644:         XSRETURN_EMPTY;
                    645:     }
                    646: 
                    647:     for (i = 1; i < items; i++) {
                    648:         sv = ST(i);
                    649: 
                    650:         if (SvROK(sv) && SvTYPE(SvRV(sv)) == SVt_PV) {
                    651:             sv = SvRV(sv);
                    652:         }
                    653: 
                    654:         p = (u_char *) SvPV(sv, len);
                    655:         b->last = ngx_cpymem(b->last, p, len);
                    656:     }
                    657: 
                    658:     out:
                    659: 
                    660:     (void) ngx_http_perl_output(r, b);
                    661: 
                    662: 
                    663: void
                    664: sendfile(r, filename, offset = -1, bytes = 0)
                    665:     CODE:
                    666: 
                    667:     ngx_http_request_t        *r;
                    668:     char                      *filename;
                    669:     off_t                      offset;
                    670:     size_t                     bytes;
                    671:     ngx_str_t                  path;
                    672:     ngx_buf_t                 *b;
                    673:     ngx_open_file_info_t       of;
                    674:     ngx_http_core_loc_conf_t  *clcf;
                    675: 
                    676:     ngx_http_perl_set_request(r);
                    677: 
                    678:     filename = SvPV_nolen(ST(1));
                    679: 
                    680:     if (filename == NULL) {
                    681:         croak("sendfile(): NULL filename");
                    682:     }
                    683: 
                    684:     offset = items < 3 ? -1 : SvIV(ST(2));
                    685:     bytes = items < 4 ? 0 : SvIV(ST(3));
                    686: 
                    687:     b = ngx_calloc_buf(r->pool);
                    688:     if (b == NULL) {
                    689:         XSRETURN_EMPTY;
                    690:     }
                    691: 
                    692:     b->file = ngx_pcalloc(r->pool, sizeof(ngx_file_t));
                    693:     if (b->file == NULL) {
                    694:         XSRETURN_EMPTY;
                    695:     }
                    696: 
                    697:     path.len = ngx_strlen(filename);
                    698: 
                    699:     path.data = ngx_pnalloc(r->pool, path.len + 1);
                    700:     if (path.data == NULL) {
                    701:         XSRETURN_EMPTY;
                    702:     }
                    703: 
                    704:     (void) ngx_cpystrn(path.data, (u_char *) filename, path.len + 1);
                    705: 
                    706:     clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
                    707: 
                    708:     ngx_memzero(&of, sizeof(ngx_open_file_info_t));
                    709: 
                    710:     of.read_ahead = clcf->read_ahead;
                    711:     of.directio = clcf->directio;
                    712:     of.valid = clcf->open_file_cache_valid;
                    713:     of.min_uses = clcf->open_file_cache_min_uses;
                    714:     of.errors = clcf->open_file_cache_errors;
                    715:     of.events = clcf->open_file_cache_events;
                    716: 
                    717:     if (ngx_http_set_disable_symlinks(r, clcf, &path, &of) != NGX_OK) {
                    718:         XSRETURN_EMPTY;
                    719:     }
                    720: 
                    721:     if (ngx_open_cached_file(clcf->open_file_cache, &path, &of, r->pool)
                    722:         != NGX_OK)
                    723:     {
                    724:         if (of.err == 0) {
                    725:             XSRETURN_EMPTY;
                    726:         }
                    727: 
                    728:         ngx_log_error(NGX_LOG_CRIT, r->connection->log, ngx_errno,
                    729:                       "%s \"%s\" failed", of.failed, filename);
                    730:         XSRETURN_EMPTY;
                    731:     }
                    732: 
                    733:     if (offset == -1) {
                    734:         offset = 0;
                    735:     }
                    736: 
                    737:     if (bytes == 0) {
                    738:         bytes = of.size - offset;
                    739:     }
                    740: 
                    741:     b->in_file = 1;
                    742: 
                    743:     b->file_pos = offset;
                    744:     b->file_last = offset + bytes;
                    745: 
                    746:     b->file->fd = of.fd;
                    747:     b->file->log = r->connection->log;
                    748:     b->file->directio = of.is_directio;
                    749: 
                    750:     (void) ngx_http_perl_output(r, b);
                    751: 
                    752: 
                    753: void
                    754: flush(r)
                    755:     CODE:
                    756: 
                    757:     ngx_http_request_t  *r;
                    758:     ngx_buf_t           *b;
                    759: 
                    760:     ngx_http_perl_set_request(r);
                    761: 
                    762:     b = ngx_calloc_buf(r->pool);
                    763:     if (b == NULL) {
                    764:         XSRETURN_EMPTY;
                    765:     }
                    766: 
                    767:     b->flush = 1;
                    768: 
                    769:     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "$r->flush");
                    770: 
                    771:     (void) ngx_http_perl_output(r, b);
                    772: 
                    773:     XSRETURN_EMPTY;
                    774: 
                    775: 
                    776: void
                    777: internal_redirect(r, uri)
                    778:     CODE:
                    779: 
                    780:     ngx_http_request_t   *r;
                    781:     SV                   *uri;
                    782:     ngx_uint_t            i;
                    783:     ngx_http_perl_ctx_t  *ctx;
                    784: 
                    785:     ngx_http_perl_set_request(r);
                    786: 
                    787:     uri = ST(1);
                    788: 
                    789:     ctx = ngx_http_get_module_ctx(r, ngx_http_perl_module);
                    790: 
                    791:     if (ngx_http_perl_sv2str(aTHX_ r, &ctx->redirect_uri, uri) != NGX_OK) {
                    792:         XSRETURN_EMPTY;
                    793:     }
                    794: 
                    795:     for (i = 0; i < ctx->redirect_uri.len; i++) {
                    796:         if (ctx->redirect_uri.data[i] == '?') {
                    797: 
                    798:             ctx->redirect_args.len = ctx->redirect_uri.len - (i + 1);
                    799:             ctx->redirect_args.data = &ctx->redirect_uri.data[i + 1];
                    800:             ctx->redirect_uri.len = i;
                    801: 
                    802:             XSRETURN_EMPTY;
                    803:         }
                    804:     }
                    805: 
                    806: 
                    807: void
                    808: allow_ranges(r)
                    809:     CODE:
                    810: 
                    811:     ngx_http_request_t  *r;
                    812: 
                    813:     ngx_http_perl_set_request(r);
                    814: 
                    815:     r->allow_ranges = 1;
                    816: 
                    817: 
                    818: void
                    819: unescape(r, text, type = 0)
                    820:     CODE:
                    821: 
                    822:     dXSTARG;
                    823:     ngx_http_request_t  *r;
                    824:     SV                  *text;
                    825:     int                  type;
                    826:     u_char              *p, *dst, *src;
                    827:     STRLEN               len;
                    828: 
                    829:     ngx_http_perl_set_request(r);
                    830: 
                    831:     text = ST(1);
                    832: 
                    833:     src = (u_char *) SvPV(text, len);
                    834: 
                    835:     p = ngx_pnalloc(r->pool, len + 1);
                    836:     if (p == NULL) {
                    837:         XSRETURN_UNDEF;
                    838:     }
                    839: 
                    840:     dst = p;
                    841: 
                    842:     type = items < 3 ? 0 : SvIV(ST(2));
                    843: 
                    844:     ngx_unescape_uri(&dst, &src, len, (ngx_uint_t) type);
                    845:     *dst = '\0';
                    846: 
                    847:     ngx_http_perl_set_targ(p, dst - p);
                    848: 
                    849:     ST(0) = TARG;
                    850: 
                    851: 
                    852: void
                    853: variable(r, name, value = NULL)
                    854:     CODE:
                    855: 
                    856:     dXSTARG;
                    857:     ngx_http_request_t         *r;
                    858:     SV                         *name, *value;
                    859:     u_char                     *p, *lowcase;
                    860:     STRLEN                      len;
                    861:     ngx_str_t                   var, val;
                    862:     ngx_uint_t                  i, hash;
                    863:     ngx_http_perl_var_t        *v;
                    864:     ngx_http_perl_ctx_t        *ctx;
                    865:     ngx_http_variable_value_t  *vv;
                    866: 
                    867:     ngx_http_perl_set_request(r);
                    868: 
                    869:     name = ST(1);
                    870: 
                    871:     if (SvROK(name) && SvTYPE(SvRV(name)) == SVt_PV) {
                    872:         name = SvRV(name);
                    873:     }
                    874: 
                    875:     if (items == 2) {
                    876:         value = NULL;
                    877: 
                    878:     } else {
                    879:         value = ST(2);
                    880: 
                    881:         if (SvROK(value) && SvTYPE(SvRV(value)) == SVt_PV) {
                    882:             value = SvRV(value);
                    883:         }
                    884: 
                    885:         if (ngx_http_perl_sv2str(aTHX_ r, &val, value) != NGX_OK) {
                    886:             XSRETURN_UNDEF;
                    887:         }
                    888:     }
                    889: 
                    890:     p = (u_char *) SvPV(name, len);
                    891: 
                    892:     lowcase = ngx_pnalloc(r->pool, len);
                    893:     if (lowcase == NULL) {
                    894:         XSRETURN_UNDEF;
                    895:     }
                    896: 
                    897:     hash = ngx_hash_strlow(lowcase, p, len);
                    898: 
                    899:     var.len = len;
                    900:     var.data = lowcase;
                    901: 
                    902:     #if (NGX_DEBUG)
                    903: 
                    904:     if (value) {
                    905:         ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                    906:                        "perl variable: \"%V\"=\"%V\"", &var, &val);
                    907:     } else {
                    908:         ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                    909:                        "perl variable: \"%V\"", &var);
                    910:     }
                    911: 
                    912:     #endif
                    913: 
                    914:     vv = ngx_http_get_variable(r, &var, hash);
                    915:     if (vv == NULL) {
                    916:         XSRETURN_UNDEF;
                    917:     }
                    918: 
                    919:     if (vv->not_found) {
                    920: 
                    921:         ctx = ngx_http_get_module_ctx(r, ngx_http_perl_module);
                    922: 
                    923:         if (ctx->variables) {
                    924: 
                    925:             v = ctx->variables->elts;
                    926:             for (i = 0; i < ctx->variables->nelts; i++) {
                    927: 
                    928:                 if (hash != v[i].hash
                    929:                     || len != v[i].name.len
                    930:                     || ngx_strncmp(lowcase, v[i].name.data, len) != 0)
                    931:                 {
                    932:                     continue;
                    933:                 }
                    934: 
                    935:                 if (value) {
                    936:                     v[i].value = val;
                    937:                     XSRETURN_UNDEF;
                    938:                 }
                    939: 
                    940:                 ngx_http_perl_set_targ(v[i].value.data, v[i].value.len);
                    941: 
                    942:                 goto done;
                    943:             }
                    944:         }
                    945: 
                    946:         if (value) {
                    947:             if (ctx->variables == NULL) {
                    948:                 ctx->variables = ngx_array_create(r->pool, 1,
                    949:                                                   sizeof(ngx_http_perl_var_t));
                    950:                 if (ctx->variables == NULL) {
                    951:                     XSRETURN_UNDEF;
                    952:                 }
                    953:             }
                    954: 
                    955:             v = ngx_array_push(ctx->variables);
                    956:             if (v == NULL) {
                    957:                 XSRETURN_UNDEF;
                    958:             }
                    959: 
                    960:             v->hash = hash;
                    961:             v->name.len = len;
                    962:             v->name.data = lowcase;
                    963:             v->value = val;
                    964: 
                    965:             XSRETURN_UNDEF;
                    966:         }
                    967: 
                    968:         XSRETURN_UNDEF;
                    969:     }
                    970: 
                    971:     if (value) {
                    972:         vv->len = val.len;
                    973:         vv->valid = 1;
                    974:         vv->no_cacheable = 0;
                    975:         vv->not_found = 0;
                    976:         vv->data = val.data;
                    977: 
                    978:         XSRETURN_UNDEF;
                    979:     }
                    980: 
                    981:     ngx_http_perl_set_targ(vv->data, vv->len);
                    982: 
                    983:     done:
                    984: 
                    985:     ST(0) = TARG;
                    986: 
                    987: 
                    988: void
                    989: sleep(r, sleep, next)
                    990:     CODE:
                    991: 
                    992:     ngx_http_request_t   *r;
                    993:     ngx_msec_t            sleep;
                    994:     ngx_http_perl_ctx_t  *ctx;
                    995: 
                    996:     ngx_http_perl_set_request(r);
                    997: 
                    998:     sleep = (ngx_msec_t) SvIV(ST(1));
                    999: 
                   1000:     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                   1001:                    "perl sleep: %M", sleep);
                   1002: 
                   1003:     ctx = ngx_http_get_module_ctx(r, ngx_http_perl_module);
                   1004: 
                   1005:     ctx->next = SvRV(ST(2));
                   1006: 
                   1007:     ngx_add_timer(r->connection->write, sleep);
                   1008: 
                   1009:     r->write_event_handler = ngx_http_perl_sleep_handler;
                   1010:     r->main->count++;
                   1011: 
                   1012: 
                   1013: void
                   1014: log_error(r, err, msg)
                   1015:     CODE:
                   1016: 
                   1017:     ngx_http_request_t  *r;
                   1018:     SV                  *err, *msg;
                   1019:     u_char              *p;
                   1020:     STRLEN               len;
                   1021:     ngx_err_t            e;
                   1022: 
                   1023:     ngx_http_perl_set_request(r);
                   1024: 
                   1025:     err = ST(1);
                   1026: 
                   1027:     if (SvROK(err) && SvTYPE(SvRV(err)) == SVt_PV) {
                   1028:         err = SvRV(err);
                   1029:     }
                   1030: 
                   1031:     e = SvIV(err);
                   1032: 
                   1033:     msg = ST(2);
                   1034: 
                   1035:     if (SvROK(msg) && SvTYPE(SvRV(msg)) == SVt_PV) {
                   1036:         msg = SvRV(msg);
                   1037:     }
                   1038: 
                   1039:     p = (u_char *) SvPV(msg, len);
                   1040: 
                   1041:     ngx_log_error(NGX_LOG_ERR, r->connection->log, e, "perl: %s", p);

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>