Lines 32-39
Link Here
|
32 |
#include "apr_optional.h" |
32 |
#include "apr_optional.h" |
33 |
#include "apr_buckets.h" |
33 |
#include "apr_buckets.h" |
34 |
#include "apr_lib.h" |
34 |
#include "apr_lib.h" |
|
|
35 |
#include "apr_poll.h" |
35 |
|
36 |
|
36 |
#define APR_WANT_STRFUNC |
37 |
#define APR_WANT_STRFUNC |
|
|
38 |
#define APR_WANT_MEMFUNC |
37 |
#include "apr_want.h" |
39 |
#include "apr_want.h" |
38 |
|
40 |
|
39 |
#define CORE_PRIVATE |
41 |
#define CORE_PRIVATE |
Lines 191-203
Link Here
|
191 |
|
193 |
|
192 |
/* Soak up stderr from a script and redirect it to the error log. |
194 |
/* Soak up stderr from a script and redirect it to the error log. |
193 |
*/ |
195 |
*/ |
194 |
static void log_script_err(request_rec *r, apr_file_t *script_err) |
196 |
static apr_status_t log_script_err(request_rec *r, apr_file_t *script_err) |
195 |
{ |
197 |
{ |
196 |
char argsbuffer[HUGE_STRING_LEN]; |
198 |
char argsbuffer[HUGE_STRING_LEN]; |
197 |
char *newline; |
199 |
char *newline; |
|
|
200 |
apr_status_t rv; |
198 |
|
201 |
|
199 |
while (apr_file_gets(argsbuffer, HUGE_STRING_LEN, |
202 |
while ((rv = apr_file_gets(argsbuffer, HUGE_STRING_LEN, |
200 |
script_err) == APR_SUCCESS) { |
203 |
script_err)) == APR_SUCCESS) { |
201 |
newline = strchr(argsbuffer, '\n'); |
204 |
newline = strchr(argsbuffer, '\n'); |
202 |
if (newline) { |
205 |
if (newline) { |
203 |
*newline = '\0'; |
206 |
*newline = '\0'; |
Lines 205-210
Link Here
|
205 |
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, |
208 |
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, |
206 |
"%s", argsbuffer); |
209 |
"%s", argsbuffer); |
207 |
} |
210 |
} |
|
|
211 |
|
212 |
return rv; |
208 |
} |
213 |
} |
209 |
|
214 |
|
210 |
static int log_script(request_rec *r, cgi_server_conf * conf, int ret, |
215 |
static int log_script(request_rec *r, cgi_server_conf * conf, int ret, |
Lines 270-276
Link Here
|
270 |
apr_file_printf(f, "%s\n", sbuf); |
275 |
apr_file_printf(f, "%s\n", sbuf); |
271 |
|
276 |
|
272 |
first = 1; |
277 |
first = 1; |
273 |
APR_BRIGADE_FOREACH(e, bb) { |
278 |
for (e = APR_BRIGADE_FIRST(bb); |
|
|
279 |
e != APR_BRIGADE_SENTINEL(bb); |
280 |
e = APR_BUCKET_NEXT(e)) |
281 |
{ |
274 |
if (APR_BUCKET_IS_EOS(e)) { |
282 |
if (APR_BUCKET_IS_EOS(e)) { |
275 |
break; |
283 |
break; |
276 |
} |
284 |
} |
Lines 431-444
Link Here
|
431 |
} |
439 |
} |
432 |
else { |
440 |
else { |
433 |
procnew = apr_pcalloc(p, sizeof(*procnew)); |
441 |
procnew = apr_pcalloc(p, sizeof(*procnew)); |
434 |
if (e_info->prog_type == RUN_AS_SSI) { |
|
|
435 |
SPLIT_AND_PASS_PRETAG_BUCKETS(*(e_info->bb), e_info->ctx, |
436 |
e_info->next, rc); |
437 |
if (rc != APR_SUCCESS) { |
438 |
return rc; |
439 |
} |
440 |
} |
441 |
|
442 |
rc = ap_os_create_privileged_process(r, procnew, command, argv, env, |
442 |
rc = ap_os_create_privileged_process(r, procnew, command, argv, env, |
443 |
procattr, p); |
443 |
procattr, p); |
444 |
|
444 |
|
Lines 446-452
Link Here
|
446 |
/* Bad things happened. Everyone should have cleaned up. */ |
446 |
/* Bad things happened. Everyone should have cleaned up. */ |
447 |
ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_TOCLIENT, rc, r, |
447 |
ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_TOCLIENT, rc, r, |
448 |
"couldn't create child process: %d: %s", rc, |
448 |
"couldn't create child process: %d: %s", rc, |
449 |
apr_filename_of_pathname(r->filename)); |
449 |
apr_filepath_name_get(r->filename)); |
450 |
} |
450 |
} |
451 |
else { |
451 |
else { |
452 |
apr_pool_note_subprocess(p, procnew, APR_KILL_AFTER_TIMEOUT); |
452 |
apr_pool_note_subprocess(p, procnew, APR_KILL_AFTER_TIMEOUT); |
Lines 528-534
Link Here
|
528 |
const char *buf; |
528 |
const char *buf; |
529 |
apr_size_t len; |
529 |
apr_size_t len; |
530 |
apr_status_t rv; |
530 |
apr_status_t rv; |
531 |
APR_BRIGADE_FOREACH(e, bb) { |
531 |
|
|
|
532 |
for (e = APR_BRIGADE_FIRST(bb); |
533 |
e != APR_BRIGADE_SENTINEL(bb); |
534 |
e = APR_BUCKET_NEXT(e)) |
535 |
{ |
532 |
if (APR_BUCKET_IS_EOS(e)) { |
536 |
if (APR_BUCKET_IS_EOS(e)) { |
533 |
break; |
537 |
break; |
534 |
} |
538 |
} |
Lines 539-544
Link Here
|
539 |
} |
543 |
} |
540 |
} |
544 |
} |
541 |
|
545 |
|
|
|
546 |
#if APR_FILES_AS_SOCKETS |
547 |
|
548 |
/* A CGI bucket type is needed to catch any output to stderr from the |
549 |
* script; see PR 22030. */ |
550 |
static const apr_bucket_type_t bucket_type_cgi; |
551 |
|
552 |
struct cgi_bucket_data { |
553 |
apr_pollset_t *pollset; |
554 |
request_rec *r; |
555 |
}; |
556 |
|
557 |
/* Create a CGI bucket using pipes from script stdout 'out' |
558 |
* and stderr 'err', for request 'r'. */ |
559 |
static apr_bucket *cgi_bucket_create(request_rec *r, |
560 |
apr_file_t *out, apr_file_t *err, |
561 |
apr_bucket_alloc_t *list) |
562 |
{ |
563 |
apr_bucket *b = apr_bucket_alloc(sizeof(*b), list); |
564 |
apr_status_t rv; |
565 |
apr_pollfd_t fd; |
566 |
struct cgi_bucket_data *data = apr_palloc(r->pool, sizeof *data); |
567 |
|
568 |
APR_BUCKET_INIT(b); |
569 |
b->free = apr_bucket_free; |
570 |
b->list = list; |
571 |
b->type = &bucket_type_cgi; |
572 |
b->length = (apr_size_t)(-1); |
573 |
b->start = -1; |
574 |
|
575 |
/* Create the pollset */ |
576 |
rv = apr_pollset_create(&data->pollset, 2, r->pool, 0); |
577 |
AP_DEBUG_ASSERT(rv == APR_SUCCESS); |
578 |
|
579 |
fd.desc_type = APR_POLL_FILE; |
580 |
fd.reqevents = APR_POLLIN; |
581 |
fd.p = r->pool; |
582 |
fd.desc.f = out; /* script's stdout */ |
583 |
fd.client_data = (void *)1; |
584 |
rv = apr_pollset_add(data->pollset, &fd); |
585 |
AP_DEBUG_ASSERT(rv == APR_SUCCESS); |
586 |
|
587 |
fd.desc.f = err; /* script's stderr */ |
588 |
fd.client_data = (void *)2; |
589 |
rv = apr_pollset_add(data->pollset, &fd); |
590 |
AP_DEBUG_ASSERT(rv == APR_SUCCESS); |
591 |
|
592 |
data->r = r; |
593 |
b->data = data; |
594 |
return b; |
595 |
} |
596 |
|
597 |
/* Create a duplicate CGI bucket using given bucket data */ |
598 |
static apr_bucket *cgi_bucket_dup(struct cgi_bucket_data *data, |
599 |
apr_bucket_alloc_t *list) |
600 |
{ |
601 |
apr_bucket *b = apr_bucket_alloc(sizeof(*b), list); |
602 |
APR_BUCKET_INIT(b); |
603 |
b->free = apr_bucket_free; |
604 |
b->list = list; |
605 |
b->type = &bucket_type_cgi; |
606 |
b->length = (apr_size_t)(-1); |
607 |
b->start = -1; |
608 |
b->data = data; |
609 |
return b; |
610 |
} |
611 |
|
612 |
/* Handle stdout from CGI child. Duplicate of logic from the _read |
613 |
* method of the real APR pipe bucket implementation. */ |
614 |
static apr_status_t cgi_read_stdout(apr_bucket *a, apr_file_t *out, |
615 |
const char **str, apr_size_t *len) |
616 |
{ |
617 |
char *buf; |
618 |
apr_status_t rv; |
619 |
|
620 |
*str = NULL; |
621 |
*len = APR_BUCKET_BUFF_SIZE; |
622 |
buf = apr_bucket_alloc(*len, a->list); /* XXX: check for failure? */ |
623 |
|
624 |
rv = apr_file_read(out, buf, len); |
625 |
|
626 |
if (rv != APR_SUCCESS && rv != APR_EOF) { |
627 |
apr_bucket_free(buf); |
628 |
return rv; |
629 |
} |
630 |
|
631 |
if (*len > 0) { |
632 |
struct cgi_bucket_data *data = a->data; |
633 |
apr_bucket_heap *h; |
634 |
|
635 |
/* Change the current bucket to refer to what we read */ |
636 |
a = apr_bucket_heap_make(a, buf, *len, apr_bucket_free); |
637 |
h = a->data; |
638 |
h->alloc_len = APR_BUCKET_BUFF_SIZE; /* note the real buffer size */ |
639 |
*str = buf; |
640 |
APR_BUCKET_INSERT_AFTER(a, cgi_bucket_dup(data, a->list)); |
641 |
} |
642 |
else { |
643 |
apr_bucket_free(buf); |
644 |
a = apr_bucket_immortal_make(a, "", 0); |
645 |
*str = a->data; |
646 |
} |
647 |
return rv; |
648 |
} |
649 |
|
650 |
/* Read method of CGI bucket: polls on stderr and stdout of the child, |
651 |
* sending any stderr output immediately away to the error log. */ |
652 |
static apr_status_t cgi_bucket_read(apr_bucket *b, const char **str, |
653 |
apr_size_t *len, apr_read_type_e block) |
654 |
{ |
655 |
struct cgi_bucket_data *data = b->data; |
656 |
apr_interval_time_t timeout; |
657 |
apr_status_t rv; |
658 |
int gotdata = 0; |
659 |
|
660 |
timeout = block == APR_NONBLOCK_READ ? 0 : data->r->server->timeout; |
661 |
|
662 |
do { |
663 |
const apr_pollfd_t *results; |
664 |
apr_int32_t num; |
665 |
|
666 |
rv = apr_pollset_poll(data->pollset, timeout, &num, &results); |
667 |
if (APR_STATUS_IS_TIMEUP(rv)) { |
668 |
return timeout == 0 ? APR_EAGAIN : rv; |
669 |
} |
670 |
else if (APR_STATUS_IS_EINTR(rv)) { |
671 |
continue; |
672 |
} |
673 |
else if (rv != APR_SUCCESS) { |
674 |
ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, data->r, |
675 |
"poll failed waiting for CGI child"); |
676 |
return rv; |
677 |
} |
678 |
|
679 |
for (; num; num--, results++) { |
680 |
if (results[0].client_data == (void *)1) { |
681 |
/* stdout */ |
682 |
rv = cgi_read_stdout(b, results[0].desc.f, str, len); |
683 |
if (APR_STATUS_IS_EOF(rv)) { |
684 |
rv = APR_SUCCESS; |
685 |
} |
686 |
gotdata = 1; |
687 |
} else { |
688 |
/* stderr */ |
689 |
apr_status_t rv2 = log_script_err(data->r, results[0].desc.f); |
690 |
if (APR_STATUS_IS_EOF(rv2)) { |
691 |
apr_pollset_remove(data->pollset, &results[0]); |
692 |
} |
693 |
} |
694 |
} |
695 |
|
696 |
} while (!gotdata); |
697 |
|
698 |
return rv; |
699 |
} |
700 |
|
701 |
static const apr_bucket_type_t bucket_type_cgi = { |
702 |
"CGI", 5, APR_BUCKET_DATA, |
703 |
apr_bucket_destroy_noop, |
704 |
cgi_bucket_read, |
705 |
apr_bucket_setaside_notimpl, |
706 |
apr_bucket_split_notimpl, |
707 |
apr_bucket_copy_notimpl |
708 |
}; |
709 |
|
710 |
#endif |
711 |
|
542 |
static int cgi_handler(request_rec *r) |
712 |
static int cgi_handler(request_rec *r) |
543 |
{ |
713 |
{ |
544 |
int nph; |
714 |
int nph; |
Lines 556-561
Link Here
|
556 |
cgi_server_conf *conf; |
726 |
cgi_server_conf *conf; |
557 |
apr_status_t rv; |
727 |
apr_status_t rv; |
558 |
cgi_exec_info_t e_info; |
728 |
cgi_exec_info_t e_info; |
|
|
729 |
conn_rec *c = r->connection; |
559 |
|
730 |
|
560 |
if(strcmp(r->handler, CGI_MAGIC_TYPE) && strcmp(r->handler, "cgi-script")) |
731 |
if(strcmp(r->handler, CGI_MAGIC_TYPE) && strcmp(r->handler, "cgi-script")) |
561 |
return DECLINED; |
732 |
return DECLINED; |
Lines 571-577
Link Here
|
571 |
return DECLINED; |
742 |
return DECLINED; |
572 |
} |
743 |
} |
573 |
|
744 |
|
574 |
argv0 = apr_filename_of_pathname(r->filename); |
745 |
argv0 = apr_filepath_name_get(r->filename); |
575 |
nph = !(strncmp(argv0, "nph-", 4)); |
746 |
nph = !(strncmp(argv0, "nph-", 4)); |
576 |
conf = ap_get_module_config(r->server->module_config, &cgi_module); |
747 |
conf = ap_get_module_config(r->server->module_config, &cgi_module); |
577 |
|
748 |
|
Lines 637-643
Link Here
|
637 |
/* Transfer any put/post args, CERN style... |
808 |
/* Transfer any put/post args, CERN style... |
638 |
* Note that we already ignore SIGPIPE in the core server. |
809 |
* Note that we already ignore SIGPIPE in the core server. |
639 |
*/ |
810 |
*/ |
640 |
bb = apr_brigade_create(r->pool, r->connection->bucket_alloc); |
811 |
bb = apr_brigade_create(r->pool, c->bucket_alloc); |
641 |
seen_eos = 0; |
812 |
seen_eos = 0; |
642 |
child_stopped_reading = 0; |
813 |
child_stopped_reading = 0; |
643 |
if (conf->logname) { |
814 |
if (conf->logname) { |
Lines 654-660
Link Here
|
654 |
return rv; |
825 |
return rv; |
655 |
} |
826 |
} |
656 |
|
827 |
|
657 |
APR_BRIGADE_FOREACH(bucket, bb) { |
828 |
for (bucket = APR_BRIGADE_FIRST(bb); |
|
|
829 |
bucket != APR_BRIGADE_SENTINEL(bb); |
830 |
bucket = APR_BUCKET_NEXT(bucket)) |
831 |
{ |
658 |
const char *data; |
832 |
const char *data; |
659 |
apr_size_t len; |
833 |
apr_size_t len; |
660 |
|
834 |
|
Lines 710-727
Link Here
|
710 |
apr_file_flush(script_out); |
884 |
apr_file_flush(script_out); |
711 |
apr_file_close(script_out); |
885 |
apr_file_close(script_out); |
712 |
|
886 |
|
|
|
887 |
AP_DEBUG_ASSERT(script_in != NULL); |
888 |
|
889 |
apr_brigade_cleanup(bb); |
890 |
|
891 |
#if APR_FILES_AS_SOCKETS |
892 |
apr_file_pipe_timeout_set(script_in, 0); |
893 |
apr_file_pipe_timeout_set(script_err, 0); |
894 |
|
895 |
b = cgi_bucket_create(r, script_in, script_err, c->bucket_alloc); |
896 |
#else |
897 |
b = apr_bucket_pipe_create(script_in, c->bucket_alloc); |
898 |
#endif |
899 |
APR_BRIGADE_INSERT_TAIL(bb, b); |
900 |
b = apr_bucket_eos_create(c->bucket_alloc); |
901 |
APR_BRIGADE_INSERT_TAIL(bb, b); |
902 |
|
713 |
/* Handle script return... */ |
903 |
/* Handle script return... */ |
714 |
if (script_in && !nph) { |
904 |
if (!nph) { |
715 |
conn_rec *c = r->connection; |
|
|
716 |
const char *location; |
905 |
const char *location; |
717 |
char sbuf[MAX_STRING_LEN]; |
906 |
char sbuf[MAX_STRING_LEN]; |
718 |
int ret; |
907 |
int ret; |
719 |
|
908 |
|
720 |
b = apr_bucket_pipe_create(script_in, c->bucket_alloc); |
|
|
721 |
APR_BRIGADE_INSERT_TAIL(bb, b); |
722 |
b = apr_bucket_eos_create(c->bucket_alloc); |
723 |
APR_BRIGADE_INSERT_TAIL(bb, b); |
724 |
|
725 |
if ((ret = ap_scan_script_header_err_brigade(r, bb, sbuf))) { |
909 |
if ((ret = ap_scan_script_header_err_brigade(r, bb, sbuf))) { |
726 |
return log_script(r, conf, ret, dbuf, sbuf, bb, script_err); |
910 |
return log_script(r, conf, ret, dbuf, sbuf, bb, script_err); |
727 |
} |
911 |
} |
Lines 731-736
Link Here
|
731 |
if (location && location[0] == '/' && r->status == 200) { |
915 |
if (location && location[0] == '/' && r->status == 200) { |
732 |
discard_script_output(bb); |
916 |
discard_script_output(bb); |
733 |
apr_brigade_destroy(bb); |
917 |
apr_brigade_destroy(bb); |
|
|
918 |
apr_file_pipe_timeout_set(script_err, r->server->timeout); |
734 |
log_script_err(r, script_err); |
919 |
log_script_err(r, script_err); |
735 |
/* This redirect needs to be a GET no matter what the original |
920 |
/* This redirect needs to be a GET no matter what the original |
736 |
* method was. |
921 |
* method was. |
Lines 757-778
Link Here
|
757 |
} |
942 |
} |
758 |
|
943 |
|
759 |
rv = ap_pass_brigade(r->output_filters, bb); |
944 |
rv = ap_pass_brigade(r->output_filters, bb); |
760 |
|
|
|
761 |
/* don't soak up script output if errors occurred |
762 |
* writing it out... otherwise, we prolong the |
763 |
* life of the script when the connection drops |
764 |
* or we stopped sending output for some other |
765 |
* reason |
766 |
*/ |
767 |
if (rv == APR_SUCCESS && !r->connection->aborted) { |
768 |
log_script_err(r, script_err); |
769 |
} |
770 |
|
771 |
apr_file_close(script_err); |
772 |
} |
945 |
} |
773 |
|
946 |
else /* nph */ { |
774 |
if (script_in && nph) { |
|
|
775 |
conn_rec *c = r->connection; |
776 |
struct ap_filter_t *cur; |
947 |
struct ap_filter_t *cur; |
777 |
|
948 |
|
778 |
/* get rid of all filters up through protocol... since we |
949 |
/* get rid of all filters up through protocol... since we |
Lines 786-799
Link Here
|
786 |
} |
957 |
} |
787 |
r->output_filters = r->proto_output_filters = cur; |
958 |
r->output_filters = r->proto_output_filters = cur; |
788 |
|
959 |
|
789 |
bb = apr_brigade_create(r->pool, c->bucket_alloc); |
960 |
rv = ap_pass_brigade(r->output_filters, bb); |
790 |
b = apr_bucket_pipe_create(script_in, c->bucket_alloc); |
|
|
791 |
APR_BRIGADE_INSERT_TAIL(bb, b); |
792 |
b = apr_bucket_eos_create(c->bucket_alloc); |
793 |
APR_BRIGADE_INSERT_TAIL(bb, b); |
794 |
ap_pass_brigade(r->output_filters, bb); |
795 |
} |
961 |
} |
796 |
|
962 |
|
|
|
963 |
/* don't soak up script output if errors occurred writing it |
964 |
* out... otherwise, we prolong the life of the script when the |
965 |
* connection drops or we stopped sending output for some other |
966 |
* reason */ |
967 |
if (rv == APR_SUCCESS && !r->connection->aborted) { |
968 |
apr_file_pipe_timeout_set(script_err, r->server->timeout); |
969 |
log_script_err(r, script_err); |
970 |
} |
971 |
|
972 |
apr_file_close(script_err); |
973 |
|
797 |
return OK; /* NOT r->status, even if it has changed. */ |
974 |
return OK; /* NOT r->status, even if it has changed. */ |
798 |
} |
975 |
} |
799 |
|
976 |
|
Lines 803-894
Link Here
|
803 |
* is the code required to handle the "exec" SSI directive. |
980 |
* is the code required to handle the "exec" SSI directive. |
804 |
*============================================================================ |
981 |
*============================================================================ |
805 |
*============================================================================*/ |
982 |
*============================================================================*/ |
806 |
static int include_cgi(char *s, request_rec *r, ap_filter_t *next, |
983 |
static apr_status_t include_cgi(include_ctx_t *ctx, ap_filter_t *f, |
807 |
apr_bucket *head_ptr, apr_bucket **inserted_head) |
984 |
apr_bucket_brigade *bb, char *s) |
808 |
{ |
985 |
{ |
809 |
request_rec *rr = ap_sub_req_lookup_uri(s, r, next); |
986 |
request_rec *r = f->r; |
|
|
987 |
request_rec *rr = ap_sub_req_lookup_uri(s, r, f->next); |
810 |
int rr_status; |
988 |
int rr_status; |
811 |
apr_bucket *tmp_buck, *tmp2_buck; |
|
|
812 |
|
989 |
|
813 |
if (rr->status != HTTP_OK) { |
990 |
if (rr->status != HTTP_OK) { |
814 |
ap_destroy_sub_req(rr); |
991 |
ap_destroy_sub_req(rr); |
815 |
return -1; |
992 |
return APR_EGENERAL; |
816 |
} |
993 |
} |
817 |
|
994 |
|
818 |
/* No hardwired path info or query allowed */ |
995 |
/* No hardwired path info or query allowed */ |
819 |
|
|
|
820 |
if ((rr->path_info && rr->path_info[0]) || rr->args) { |
996 |
if ((rr->path_info && rr->path_info[0]) || rr->args) { |
821 |
ap_destroy_sub_req(rr); |
997 |
ap_destroy_sub_req(rr); |
822 |
return -1; |
998 |
return APR_EGENERAL; |
823 |
} |
999 |
} |
824 |
if (rr->finfo.filetype != APR_REG) { |
1000 |
if (rr->finfo.filetype != APR_REG) { |
825 |
ap_destroy_sub_req(rr); |
1001 |
ap_destroy_sub_req(rr); |
826 |
return -1; |
1002 |
return APR_EGENERAL; |
827 |
} |
1003 |
} |
828 |
|
1004 |
|
829 |
/* Script gets parameters of the *document*, for back compatibility */ |
1005 |
/* Script gets parameters of the *document*, for back compatibility */ |
830 |
|
|
|
831 |
rr->path_info = r->path_info; /* hard to get right; see mod_cgi.c */ |
1006 |
rr->path_info = r->path_info; /* hard to get right; see mod_cgi.c */ |
832 |
rr->args = r->args; |
1007 |
rr->args = r->args; |
833 |
|
1008 |
|
834 |
/* Force sub_req to be treated as a CGI request, even if ordinary |
1009 |
/* Force sub_req to be treated as a CGI request, even if ordinary |
835 |
* typing rules would have called it something else. |
1010 |
* typing rules would have called it something else. |
836 |
*/ |
1011 |
*/ |
837 |
|
|
|
838 |
ap_set_content_type(rr, CGI_MAGIC_TYPE); |
1012 |
ap_set_content_type(rr, CGI_MAGIC_TYPE); |
839 |
|
1013 |
|
840 |
/* Run it. */ |
1014 |
/* Run it. */ |
841 |
|
|
|
842 |
rr_status = ap_run_sub_req(rr); |
1015 |
rr_status = ap_run_sub_req(rr); |
843 |
if (ap_is_HTTP_REDIRECT(rr_status)) { |
1016 |
if (ap_is_HTTP_REDIRECT(rr_status)) { |
844 |
apr_size_t len_loc; |
|
|
845 |
const char *location = apr_table_get(rr->headers_out, "Location"); |
1017 |
const char *location = apr_table_get(rr->headers_out, "Location"); |
846 |
conn_rec *c = r->connection; |
|
|
847 |
|
1018 |
|
848 |
location = ap_escape_html(rr->pool, location); |
1019 |
if (location) { |
849 |
len_loc = strlen(location); |
1020 |
char *buffer; |
850 |
|
1021 |
|
851 |
/* XXX: if most of this stuff is going to get copied anyway, |
1022 |
location = ap_escape_html(rr->pool, location); |
852 |
* it'd be more efficient to pstrcat it into a single pool buffer |
1023 |
buffer = apr_pstrcat(ctx->pool, "<a href=\"", location, "\">", |
853 |
* and a single pool bucket */ |
1024 |
location, "</a>", NULL); |
854 |
|
1025 |
|
855 |
tmp_buck = apr_bucket_immortal_create("<A HREF=\"", |
1026 |
APR_BRIGADE_INSERT_TAIL(bb, apr_bucket_pool_create(buffer, |
856 |
sizeof("<A HREF=\"") - 1, |
1027 |
strlen(buffer), ctx->pool, |
857 |
c->bucket_alloc); |
1028 |
f->c->bucket_alloc)); |
858 |
APR_BUCKET_INSERT_BEFORE(head_ptr, tmp_buck); |
|
|
859 |
tmp2_buck = apr_bucket_heap_create(location, len_loc, NULL, |
860 |
c->bucket_alloc); |
861 |
APR_BUCKET_INSERT_BEFORE(head_ptr, tmp2_buck); |
862 |
tmp2_buck = apr_bucket_immortal_create("\">", sizeof("\">") - 1, |
863 |
c->bucket_alloc); |
864 |
APR_BUCKET_INSERT_BEFORE(head_ptr, tmp2_buck); |
865 |
tmp2_buck = apr_bucket_heap_create(location, len_loc, NULL, |
866 |
c->bucket_alloc); |
867 |
APR_BUCKET_INSERT_BEFORE(head_ptr, tmp2_buck); |
868 |
tmp2_buck = apr_bucket_immortal_create("</A>", sizeof("</A>") - 1, |
869 |
c->bucket_alloc); |
870 |
APR_BUCKET_INSERT_BEFORE(head_ptr, tmp2_buck); |
871 |
|
872 |
if (*inserted_head == NULL) { |
873 |
*inserted_head = tmp_buck; |
874 |
} |
1029 |
} |
875 |
} |
1030 |
} |
876 |
|
1031 |
|
877 |
ap_destroy_sub_req(rr); |
1032 |
ap_destroy_sub_req(rr); |
878 |
|
1033 |
|
879 |
return 0; |
1034 |
return APR_SUCCESS; |
880 |
} |
1035 |
} |
881 |
|
1036 |
|
882 |
|
1037 |
static apr_status_t include_cmd(include_ctx_t *ctx, ap_filter_t *f, |
883 |
static int include_cmd(include_ctx_t *ctx, apr_bucket_brigade **bb, |
1038 |
apr_bucket_brigade *bb, const char *command) |
884 |
const char *command, request_rec *r, ap_filter_t *f) |
|
|
885 |
{ |
1039 |
{ |
886 |
cgi_exec_info_t e_info; |
1040 |
cgi_exec_info_t e_info; |
887 |
const char **argv; |
1041 |
const char **argv; |
888 |
apr_file_t *script_out = NULL, *script_in = NULL, *script_err = NULL; |
1042 |
apr_file_t *script_out = NULL, *script_in = NULL, *script_err = NULL; |
889 |
apr_bucket_brigade *bcgi; |
|
|
890 |
apr_bucket *b; |
891 |
apr_status_t rv; |
1043 |
apr_status_t rv; |
|
|
1044 |
request_rec *r = f->r; |
892 |
|
1045 |
|
893 |
add_ssi_vars(r); |
1046 |
add_ssi_vars(r); |
894 |
|
1047 |
|
Lines 899-913
Link Here
|
899 |
e_info.out_pipe = APR_FULL_BLOCK; |
1052 |
e_info.out_pipe = APR_FULL_BLOCK; |
900 |
e_info.err_pipe = APR_NO_PIPE; |
1053 |
e_info.err_pipe = APR_NO_PIPE; |
901 |
e_info.prog_type = RUN_AS_SSI; |
1054 |
e_info.prog_type = RUN_AS_SSI; |
902 |
e_info.bb = bb; |
1055 |
e_info.bb = &bb; |
903 |
e_info.ctx = ctx; |
1056 |
e_info.ctx = ctx; |
904 |
e_info.next = f->next; |
1057 |
e_info.next = f->next; |
905 |
|
1058 |
|
906 |
if ((rv = cgi_build_command(&command, &argv, r, r->pool, &e_info)) != APR_SUCCESS) { |
1059 |
if ((rv = cgi_build_command(&command, &argv, r, r->pool, |
|
|
1060 |
&e_info)) != APR_SUCCESS) { |
907 |
ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, |
1061 |
ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, |
908 |
"don't know how to spawn cmd child process: %s", |
1062 |
"don't know how to spawn cmd child process: %s", |
909 |
r->filename); |
1063 |
r->filename); |
910 |
return HTTP_INTERNAL_SERVER_ERROR; |
1064 |
return rv; |
911 |
} |
1065 |
} |
912 |
|
1066 |
|
913 |
/* run the script in its own process */ |
1067 |
/* run the script in its own process */ |
Lines 916-1007
Link Here
|
916 |
&e_info)) != APR_SUCCESS) { |
1070 |
&e_info)) != APR_SUCCESS) { |
917 |
ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, |
1071 |
ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, |
918 |
"couldn't spawn child process: %s", r->filename); |
1072 |
"couldn't spawn child process: %s", r->filename); |
919 |
return HTTP_INTERNAL_SERVER_ERROR; |
1073 |
return rv; |
920 |
} |
1074 |
} |
921 |
|
1075 |
|
922 |
bcgi = apr_brigade_create(r->pool, f->c->bucket_alloc); |
1076 |
APR_BRIGADE_INSERT_TAIL(bb, apr_bucket_pipe_create(script_in, |
923 |
b = apr_bucket_pipe_create(script_in, f->c->bucket_alloc); |
1077 |
f->c->bucket_alloc)); |
924 |
APR_BRIGADE_INSERT_TAIL(bcgi, b); |
1078 |
ctx->flush_now = 1; |
925 |
ap_pass_brigade(f->next, bcgi); |
|
|
926 |
|
1079 |
|
927 |
/* We can't close the pipe here, because we may return before the |
1080 |
/* We can't close the pipe here, because we may return before the |
928 |
* full CGI has been sent to the network. That's okay though, |
1081 |
* full CGI has been sent to the network. That's okay though, |
929 |
* because we can rely on the pool to close the pipe for us. |
1082 |
* because we can rely on the pool to close the pipe for us. |
930 |
*/ |
1083 |
*/ |
931 |
|
1084 |
return APR_SUCCESS; |
932 |
return 0; |
|
|
933 |
} |
1085 |
} |
934 |
|
1086 |
|
935 |
static int handle_exec(include_ctx_t *ctx, apr_bucket_brigade **bb, |
1087 |
static apr_status_t handle_exec(include_ctx_t *ctx, ap_filter_t *f, |
936 |
request_rec *r, ap_filter_t *f, apr_bucket *head_ptr, |
1088 |
apr_bucket_brigade *bb) |
937 |
apr_bucket **inserted_head) |
|
|
938 |
{ |
1089 |
{ |
939 |
char *tag = NULL; |
1090 |
char *tag = NULL; |
940 |
char *tag_val = NULL; |
1091 |
char *tag_val = NULL; |
|
|
1092 |
request_rec *r = f->r; |
941 |
char *file = r->filename; |
1093 |
char *file = r->filename; |
942 |
apr_bucket *tmp_buck; |
|
|
943 |
char parsed_string[MAX_STRING_LEN]; |
1094 |
char parsed_string[MAX_STRING_LEN]; |
944 |
|
1095 |
|
945 |
*inserted_head = NULL; |
1096 |
if (!ctx->argc) { |
946 |
if (ctx->flags & FLAG_PRINTING) { |
1097 |
ap_log_rerror(APLOG_MARK, |
947 |
if (ctx->flags & FLAG_NO_EXEC) { |
1098 |
(ctx->flags & SSI_FLAG_PRINTING) |
948 |
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, |
1099 |
? APLOG_ERR : APLOG_WARNING, |
949 |
"exec used but not allowed in %s", r->filename); |
1100 |
0, r, "missing argument for exec element in %s", |
950 |
CREATE_ERROR_BUCKET(ctx, tmp_buck, head_ptr, *inserted_head); |
1101 |
r->filename); |
|
|
1102 |
} |
1103 |
|
1104 |
if (!(ctx->flags & SSI_FLAG_PRINTING)) { |
1105 |
return APR_SUCCESS; |
1106 |
} |
1107 |
|
1108 |
if (!ctx->argc) { |
1109 |
SSI_CREATE_ERROR_BUCKET(ctx, f, bb); |
1110 |
return APR_SUCCESS; |
1111 |
} |
1112 |
|
1113 |
if (ctx->flags & SSI_FLAG_NO_EXEC) { |
1114 |
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "exec used but not allowed " |
1115 |
"in %s", r->filename); |
1116 |
SSI_CREATE_ERROR_BUCKET(ctx, f, bb); |
1117 |
return APR_SUCCESS; |
1118 |
} |
1119 |
|
1120 |
while (1) { |
1121 |
cgi_pfn_gtv(ctx, &tag, &tag_val, SSI_VALUE_DECODED); |
1122 |
if (!tag || !tag_val) { |
1123 |
break; |
951 |
} |
1124 |
} |
952 |
else { |
|
|
953 |
while (1) { |
954 |
cgi_pfn_gtv(ctx, &tag, &tag_val, 1); |
955 |
if (tag_val == NULL) { |
956 |
if (tag == NULL) { |
957 |
return 0; |
958 |
} |
959 |
else { |
960 |
return 1; |
961 |
} |
962 |
} |
963 |
if (!strcmp(tag, "cmd")) { |
964 |
cgi_pfn_ps(r, ctx, tag_val, parsed_string, |
965 |
sizeof(parsed_string), 1); |
966 |
if (include_cmd(ctx, bb, parsed_string, r, f) == -1) { |
967 |
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, |
968 |
"execution failure for parameter \"%s\" " |
969 |
"to tag exec in file %s", tag, r->filename); |
970 |
CREATE_ERROR_BUCKET(ctx, tmp_buck, head_ptr, |
971 |
*inserted_head); |
972 |
} |
973 |
} |
974 |
else if (!strcmp(tag, "cgi")) { |
975 |
apr_status_t retval = APR_SUCCESS; |
976 |
|
1125 |
|
977 |
cgi_pfn_ps(r, ctx, tag_val, parsed_string, |
1126 |
if (!strcmp(tag, "cmd")) { |
978 |
sizeof(parsed_string), 0); |
1127 |
apr_status_t rv; |
979 |
|
1128 |
|
980 |
SPLIT_AND_PASS_PRETAG_BUCKETS(*bb, ctx, f->next, retval); |
1129 |
cgi_pfn_ps(ctx, tag_val, parsed_string, sizeof(parsed_string), |
981 |
if (retval != APR_SUCCESS) { |
1130 |
SSI_EXPAND_LEAVE_NAME); |
982 |
return retval; |
1131 |
|
983 |
} |
1132 |
rv = include_cmd(ctx, f, bb, parsed_string); |
984 |
|
1133 |
if (!APR_STATUS_IS_SUCCESS(rv)) { |
985 |
if (include_cgi(parsed_string, r, f->next, head_ptr, |
1134 |
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "execution failure " |
986 |
inserted_head) == -1) { |
1135 |
"for parameter \"%s\" to tag exec in file %s", |
987 |
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, |
1136 |
tag, r->filename); |
988 |
"invalid CGI ref \"%s\" in %s", |
1137 |
SSI_CREATE_ERROR_BUCKET(ctx, f, bb); |
989 |
tag_val, file); |
1138 |
break; |
990 |
CREATE_ERROR_BUCKET(ctx, tmp_buck, head_ptr, |
1139 |
} |
991 |
*inserted_head); |
1140 |
} |
992 |
} |
1141 |
else if (!strcmp(tag, "cgi")) { |
993 |
} |
1142 |
apr_status_t rv; |
994 |
else { |
1143 |
|
995 |
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, |
1144 |
cgi_pfn_ps(ctx, tag_val, parsed_string, sizeof(parsed_string), |
996 |
"unknown parameter \"%s\" to tag exec in %s", |
1145 |
SSI_EXPAND_DROP_NAME); |
997 |
tag, file); |
1146 |
|
998 |
CREATE_ERROR_BUCKET(ctx, tmp_buck, head_ptr, |
1147 |
rv = include_cgi(ctx, f, bb, parsed_string); |
999 |
*inserted_head); |
1148 |
if (!APR_STATUS_IS_SUCCESS(rv)) { |
1000 |
} |
1149 |
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "invalid CGI ref " |
|
|
1150 |
"\"%s\" in %s", tag_val, file); |
1151 |
SSI_CREATE_ERROR_BUCKET(ctx, f, bb); |
1152 |
break; |
1001 |
} |
1153 |
} |
1002 |
} |
1154 |
} |
|
|
1155 |
else { |
1156 |
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "unknown parameter " |
1157 |
"\"%s\" to tag exec in %s", tag, file); |
1158 |
SSI_CREATE_ERROR_BUCKET(ctx, f, bb); |
1159 |
break; |
1160 |
} |
1003 |
} |
1161 |
} |
1004 |
return 0; |
1162 |
|
|
|
1163 |
return APR_SUCCESS; |
1005 |
} |
1164 |
} |
1006 |
|
1165 |
|
1007 |
|
1166 |
|