PHPAPI void destroy_uploaded_files_hash(void) /* {{{ */ { zend_hash_apply(SG(rfc1867_uploaded_files), unlink_filename); zend_hash_destroy(SG(rfc1867_uploaded_files)); FREE_HASHTABLE(SG(rfc1867_uploaded_files)); }
SAPI_API int sapi_header_op(sapi_header_op_enum op, void *arg) { sapi_header_struct sapi_header; char *colon_offset; char *header_line; size_t header_line_len; int http_response_code; if (SG(headers_sent) && !SG(request_info).no_headers) { const char *output_start_filename = php_output_get_start_filename(); int output_start_lineno = php_output_get_start_lineno(); if (output_start_filename) { sapi_module.sapi_error(E_WARNING, "Cannot modify header information - headers already sent by (output started at %s:%d)", output_start_filename, output_start_lineno); } else { sapi_module.sapi_error(E_WARNING, "Cannot modify header information - headers already sent"); } return FAILURE; } switch (op) { case SAPI_HEADER_SET_STATUS: sapi_update_response_code((int)(zend_intptr_t) arg); return SUCCESS; case SAPI_HEADER_ADD: case SAPI_HEADER_REPLACE: case SAPI_HEADER_DELETE: { sapi_header_line *p = arg; if (!p->line || !p->line_len) { return FAILURE; } header_line = p->line; header_line_len = p->line_len; http_response_code = p->response_code; break; } case SAPI_HEADER_DELETE_ALL: if (sapi_module.header_handler) { sapi_module.header_handler(&sapi_header, op, &SG(sapi_headers)); } zend_llist_clean(&SG(sapi_headers).headers); return SUCCESS; default: return FAILURE; } header_line = estrndup(header_line, header_line_len); /* cut off trailing spaces, linefeeds and carriage-returns */ if (header_line_len && isspace(header_line[header_line_len-1])) { do { header_line_len--; } while(header_line_len && isspace(header_line[header_line_len-1])); header_line[header_line_len]='\0'; } if (op == SAPI_HEADER_DELETE) { if (strchr(header_line, ':')) { efree(header_line); sapi_module.sapi_error(E_WARNING, "Header to delete may not contain colon."); return FAILURE; } if (sapi_module.header_handler) { sapi_header.header = header_line; sapi_header.header_len = header_line_len; sapi_module.header_handler(&sapi_header, op, &SG(sapi_headers)); } sapi_remove_header(&SG(sapi_headers).headers, header_line, header_line_len); efree(header_line); return SUCCESS; } else { /* new line/NUL character safety check */ uint32_t i; for (i = 0; i < header_line_len; i++) { /* RFC 7230 ch. 3.2.4 deprecates folding support */ if (header_line[i] == '\n' || header_line[i] == '\r') { efree(header_line); sapi_module.sapi_error(E_WARNING, "Header may not contain " "more than a single header, new line detected"); return FAILURE; } if (header_line[i] == '\0') { efree(header_line); sapi_module.sapi_error(E_WARNING, "Header may not contain NUL bytes"); return FAILURE; } } } sapi_header.header = header_line; sapi_header.header_len = header_line_len; /* Check the header for a few cases that we have special support for in SAPI */ if (header_line_len>=5 && !strncasecmp(header_line, "HTTP/", 5)) { /* filter out the response code */ sapi_update_response_code(sapi_extract_response_code(header_line)); /* sapi_update_response_code doesn't free the status line if the code didn't change */ if (SG(sapi_headers).http_status_line) { efree(SG(sapi_headers).http_status_line); } SG(sapi_headers).http_status_line = header_line; return SUCCESS; } else { colon_offset = strchr(header_line, ':'); if (colon_offset) { *colon_offset = 0; if (!strcasecmp(header_line, "Content-Type")) { char *ptr = colon_offset+1, *mimetype = NULL, *newheader; size_t len = header_line_len - (ptr - header_line), newlen; while (*ptr == ' ') { ptr++; len--; } /* Disable possible output compression for images */ if (!strncmp(ptr, "image/", sizeof("image/")-1)) { zend_string *key = zend_string_init("zlib.output_compression", sizeof("zlib.output_compression")-1, 0); zend_alter_ini_entry_chars(key, "0", sizeof("0") - 1, PHP_INI_USER, PHP_INI_STAGE_RUNTIME); zend_string_release(key); } mimetype = estrdup(ptr); newlen = sapi_apply_default_charset(&mimetype, len); if (!SG(sapi_headers).mimetype){ SG(sapi_headers).mimetype = estrdup(mimetype); } if (newlen != 0) { newlen += sizeof("Content-type: "); newheader = emalloc(newlen); PHP_STRLCPY(newheader, "Content-type: ", newlen, sizeof("Content-type: ")-1); strlcat(newheader, mimetype, newlen); sapi_header.header = newheader; sapi_header.header_len = (uint32_t)(newlen - 1); efree(header_line); } efree(mimetype); SG(sapi_headers).send_default_content_type = 0; } else if (!strcasecmp(header_line, "Content-Length")) { /* Script is setting Content-length. The script cannot reasonably * know the size of the message body after compression, so it's best * do disable compression altogether. This contributes to making scripts * portable between setups that have and don't have zlib compression * enabled globally. See req #44164 */ zend_string *key = zend_string_init("zlib.output_compression", sizeof("zlib.output_compression")-1, 0); zend_alter_ini_entry_chars(key, "0", sizeof("0") - 1, PHP_INI_USER, PHP_INI_STAGE_RUNTIME); zend_string_release(key); } else if (!strcasecmp(header_line, "Location")) { if ((SG(sapi_headers).http_response_code < 300 || SG(sapi_headers).http_response_code > 399) && SG(sapi_headers).http_response_code != 201) { /* Return a Found Redirect if one is not already specified */ if (http_response_code) { /* user specified redirect code */ sapi_update_response_code(http_response_code); } else if (SG(request_info).proto_num > 1000 && SG(request_info).request_method && strcmp(SG(request_info).request_method, "HEAD") && strcmp(SG(request_info).request_method, "GET")) { sapi_update_response_code(303); } else { sapi_update_response_code(302); } } } else if (!strcasecmp(header_line, "WWW-Authenticate")) { /* HTTP Authentication */ sapi_update_response_code(401); /* authentication-required */ } if (sapi_header.header==header_line) { *colon_offset = ':'; } } } if (http_response_code) { sapi_update_response_code(http_response_code); } sapi_header_add_op(op, &sapi_header); return SUCCESS; }
/* }}} */ /* {{{ sapi_apache_read_cookies */ static char *sapi_apache_read_cookies(TSRMLS_D) { return (char *) table_get(((request_rec *) SG(server_context))->subprocess_env, "HTTP_COOKIE"); } /* }}} */ /* {{{ sapi_apache_header_handler */ static int sapi_apache_header_handler(sapi_header_struct *sapi_header, sapi_header_op_enum op, sapi_headers_struct *sapi_headers TSRMLS_DC) { char *header_name, *header_content, *p; request_rec *r = (request_rec *) SG(server_context); if(!r) { return 0; } switch(op) { case SAPI_HEADER_DELETE_ALL: clear_table(r->headers_out); return 0; case SAPI_HEADER_DELETE: table_unset(r->headers_out, sapi_header->header); return 0; case SAPI_HEADER_ADD: case SAPI_HEADER_REPLACE:
SAPI_API SAPI_POST_READER_FUNC(sapi_read_standard_form_data) { if ((SG(post_max_size) > 0) && (SG(request_info).content_length > SG(post_max_size))) { php_error_docref(NULL, E_WARNING, "POST Content-Length of " ZEND_LONG_FMT " bytes exceeds the limit of " ZEND_LONG_FMT " bytes", SG(request_info).content_length, SG(post_max_size)); return; } SG(request_info).request_body = php_stream_temp_create_ex(TEMP_STREAM_DEFAULT, SAPI_POST_BLOCK_SIZE, PG(upload_tmp_dir)); if (sapi_module.read_post) { size_t read_bytes; for (;;) { char buffer[SAPI_POST_BLOCK_SIZE]; read_bytes = sapi_read_post_block(buffer, SAPI_POST_BLOCK_SIZE); if (read_bytes > 0) { if (php_stream_write(SG(request_info).request_body, buffer, read_bytes) != read_bytes) { /* if parts of the stream can't be written, purge it completely */ php_stream_truncate_set_size(SG(request_info).request_body, 0); php_error_docref(NULL, E_WARNING, "POST data can't be buffered; all data discarded"); break; } } if ((SG(post_max_size) > 0) && (SG(read_post_bytes) > SG(post_max_size))) { php_error_docref(NULL, E_WARNING, "Actual POST length does not match Content-Length, and exceeds " ZEND_LONG_FMT " bytes", SG(post_max_size)); break; } if (read_bytes < SAPI_POST_BLOCK_SIZE) { /* done */ break; } } php_stream_rewind(SG(request_info).request_body); } }
SAPI_API void sapi_activate(void) { zend_llist_init(&SG(sapi_headers).headers, sizeof(sapi_header_struct), (void (*)(void *)) sapi_free_header, 0); SG(sapi_headers).send_default_content_type = 1; /* SG(sapi_headers).http_response_code = 200; */ SG(sapi_headers).http_status_line = NULL; SG(sapi_headers).mimetype = NULL; SG(headers_sent) = 0; ZVAL_UNDEF(&SG(callback_func)); SG(read_post_bytes) = 0; SG(request_info).request_body = NULL; SG(request_info).current_user = NULL; SG(request_info).current_user_length = 0; SG(request_info).no_headers = 0; SG(request_info).post_entry = NULL; SG(request_info).proto_num = 1000; /* Default to HTTP 1.0 */ SG(global_request_time) = 0; SG(post_read) = 0; /* It's possible to override this general case in the activate() callback, if necessary. */ if (SG(request_info).request_method && !strcmp(SG(request_info).request_method, "HEAD")) { SG(request_info).headers_only = 1; } else { SG(request_info).headers_only = 0; } SG(rfc1867_uploaded_files) = NULL; /* Handle request method */ if (SG(server_context)) { if (PG(enable_post_data_reading) && SG(request_info).content_type && SG(request_info).request_method && !strcmp(SG(request_info).request_method, "POST")) { /* HTTP POST may contain form data to be processed into variables * depending on given content type */ sapi_read_post_data(); } else { SG(request_info).content_type_dup = NULL; } /* Cookies */ SG(request_info).cookie_data = sapi_module.read_cookies(); } if (sapi_module.activate) { sapi_module.activate(); } if (sapi_module.input_filter_init) { sapi_module.input_filter_init(); } }
int fpm_log_write(char *log_format) /* {{{ */ { char *s, *b; char buffer[FPM_LOG_BUFFER+1]; int token, test; size_t len, len2; struct fpm_scoreboard_proc_s proc, *proc_p; struct fpm_scoreboard_s *scoreboard; char tmp[129]; char format[129]; time_t now_epoch; #ifdef HAVE_TIMES clock_t tms_total; #endif if (!log_format && (!fpm_log_format || fpm_log_fd == -1)) { return -1; } if (!log_format) { log_format = fpm_log_format; test = 0; } else { test = 1; } now_epoch = time(NULL); if (!test) { scoreboard = fpm_scoreboard_get(); if (!scoreboard) { zlog(ZLOG_WARNING, "unable to get scoreboard while preparing the access log"); return -1; } proc_p = fpm_scoreboard_proc_acquire(NULL, -1, 0); if (!proc_p) { zlog(ZLOG_WARNING, "[pool %s] Unable to acquire shm slot while preparing the access log", scoreboard->pool); return -1; } proc = *proc_p; fpm_scoreboard_proc_release(proc_p); } token = 0; memset(buffer, '\0', sizeof(buffer)); b = buffer; len = 0; s = log_format; while (*s != '\0') { /* Test is we have place for 1 more char. */ if (len >= FPM_LOG_BUFFER) { zlog(ZLOG_NOTICE, "the log buffer is full (%d). The access log request has been truncated.", FPM_LOG_BUFFER); len = FPM_LOG_BUFFER; break; } if (!token && *s == '%') { token = 1; memset(format, '\0', sizeof(format)); /* reset format */ s++; continue; } if (token) { token = 0; len2 = 0; switch (*s) { case '%': /* '%' */ *b = '%'; len2 = 1; break; #ifdef HAVE_TIMES case 'C': /* %CPU */ if (format[0] == '\0' || !strcasecmp(format, "total")) { if (!test) { tms_total = proc.last_request_cpu.tms_utime + proc.last_request_cpu.tms_stime + proc.last_request_cpu.tms_cutime + proc.last_request_cpu.tms_cstime; } } else if (!strcasecmp(format, "user")) { if (!test) { tms_total = proc.last_request_cpu.tms_utime + proc.last_request_cpu.tms_cutime; } } else if (!strcasecmp(format, "system")) { if (!test) { tms_total = proc.last_request_cpu.tms_stime + proc.last_request_cpu.tms_cstime; } } else { zlog(ZLOG_WARNING, "only 'total', 'user' or 'system' are allowed as a modifier for %%%c ('%s')", *s, format); return -1; } format[0] = '\0'; if (!test) { len2 = snprintf(b, FPM_LOG_BUFFER - len, "%.2f", tms_total / fpm_scoreboard_get_tick() / (proc.cpu_duration.tv_sec + proc.cpu_duration.tv_usec / 1000000.) * 100.); } break; #endif case 'd': /* duration µs */ /* seconds */ if (format[0] == '\0' || !strcasecmp(format, "seconds")) { if (!test) { len2 = snprintf(b, FPM_LOG_BUFFER - len, "%.3f", proc.duration.tv_sec + proc.duration.tv_usec / 1000000.); } /* miliseconds */ } else if (!strcasecmp(format, "miliseconds") || !strcasecmp(format, "mili")) { if (!test) { len2 = snprintf(b, FPM_LOG_BUFFER - len, "%.3f", proc.duration.tv_sec * 1000. + proc.duration.tv_usec / 1000.); } /* microseconds */ } else if (!strcasecmp(format, "microseconds") || !strcasecmp(format, "micro")) { if (!test) { len2 = snprintf(b, FPM_LOG_BUFFER - len, "%lu", proc.duration.tv_sec * 1000000UL + proc.duration.tv_usec); } } else { zlog(ZLOG_WARNING, "only 'seconds', 'mili', 'miliseconds', 'micro' or 'microseconds' are allowed as a modifier for %%%c ('%s')", *s, format); return -1; } format[0] = '\0'; break; case 'e': /* fastcgi env */ if (format[0] == '\0') { zlog(ZLOG_WARNING, "the name of the environment variable must be set between embraces for %%%c", *s); return -1; } if (!test) { char *env = fcgi_getenv((fcgi_request*) SG(server_context), format, strlen(format)); len2 = snprintf(b, FPM_LOG_BUFFER - len, "%s", env ? env : "-"); } format[0] = '\0'; break; case 'f': /* script */ if (!test) { len2 = snprintf(b, FPM_LOG_BUFFER - len, "%s", *proc.script_filename ? proc.script_filename : "-"); } break; case 'l': /* content length */ if (!test) { len2 = snprintf(b, FPM_LOG_BUFFER - len, "%zu", proc.content_length); } break; case 'm': /* method */ if (!test) { len2 = snprintf(b, FPM_LOG_BUFFER - len, "%s", *proc.request_method ? proc.request_method : "-"); } break; case 'M': /* memory */ /* seconds */ if (format[0] == '\0' || !strcasecmp(format, "bytes")) { if (!test) { len2 = snprintf(b, FPM_LOG_BUFFER - len, "%zu", proc.memory); } /* kilobytes */ } else if (!strcasecmp(format, "kilobytes") || !strcasecmp(format, "kilo")) { if (!test) { len2 = snprintf(b, FPM_LOG_BUFFER - len, "%lu", proc.memory / 1024); } /* megabytes */ } else if (!strcasecmp(format, "megabytes") || !strcasecmp(format, "mega")) { if (!test) { len2 = snprintf(b, FPM_LOG_BUFFER - len, "%lu", proc.memory / 1024 / 1024); } } else { zlog(ZLOG_WARNING, "only 'bytes', 'kilo', 'kilobytes', 'mega' or 'megabytes' are allowed as a modifier for %%%c ('%s')", *s, format); return -1; } format[0] = '\0'; break; case 'n': /* pool name */ if (!test) { len2 = snprintf(b, FPM_LOG_BUFFER - len, "%s", scoreboard->pool[0] ? scoreboard->pool : "-"); } break; case 'o': /* header output */ if (format[0] == '\0') { zlog(ZLOG_WARNING, "the name of the header must be set between embraces for %%%c", *s); return -1; } if (!test) { sapi_header_struct *h; zend_llist_position pos; sapi_headers_struct *sapi_headers = &SG(sapi_headers); size_t format_len = strlen(format); h = (sapi_header_struct*)zend_llist_get_first_ex(&sapi_headers->headers, &pos); while (h) { char *header; if (!h->header_len) { h = (sapi_header_struct*)zend_llist_get_next_ex(&sapi_headers->headers, &pos); continue; } if (!strstr(h->header, format)) { h = (sapi_header_struct*)zend_llist_get_next_ex(&sapi_headers->headers, &pos); continue; } /* test if enought char after the header name + ': ' */ if (h->header_len <= format_len + 2) { h = (sapi_header_struct*)zend_llist_get_next_ex(&sapi_headers->headers, &pos); continue; } if (h->header[format_len] != ':' || h->header[format_len + 1] != ' ') { h = (sapi_header_struct*)zend_llist_get_next_ex(&sapi_headers->headers, &pos); continue; } header = h->header + format_len + 2; len2 = snprintf(b, FPM_LOG_BUFFER - len, "%s", header && *header ? header : "-"); /* found, done */ break; } if (!len2) { len2 = 1; *b = '-'; } } format[0] = '\0'; break; case 'p': /* PID */ if (!test) { len2 = snprintf(b, FPM_LOG_BUFFER - len, "%ld", (long)getpid()); } break; case 'P': /* PID */ if (!test) { len2 = snprintf(b, FPM_LOG_BUFFER - len, "%ld", (long)getppid()); } break; case 'q': /* query_string */ if (!test) { len2 = snprintf(b, FPM_LOG_BUFFER - len, "%s", proc.query_string); } break; case 'Q': /* '?' */ if (!test) { len2 = snprintf(b, FPM_LOG_BUFFER - len, "%s", *proc.query_string ? "?" : ""); } break; case 'r': /* request URI */ if (!test) { len2 = snprintf(b, FPM_LOG_BUFFER - len, "%s", proc.request_uri); } break; case 'R': /* remote IP address */ if (!test) { const char *tmp = fcgi_get_last_client_ip(); len2 = snprintf(b, FPM_LOG_BUFFER - len, "%s", tmp ? tmp : "-"); } break; case 's': /* status */ if (!test) { len2 = snprintf(b, FPM_LOG_BUFFER - len, "%d", SG(sapi_headers).http_response_code); } break; case 'T': case 't': /* time */ if (!test) { time_t *t; if (*s == 't') { t = &proc.accepted_epoch; } else { t = &now_epoch; } if (format[0] == '\0') { strftime(tmp, sizeof(tmp) - 1, "%d/%b/%Y:%H:%M:%S %z", localtime(t)); } else { strftime(tmp, sizeof(tmp) - 1, format, localtime(t)); } len2 = snprintf(b, FPM_LOG_BUFFER - len, "%s", tmp); } format[0] = '\0'; break; case 'u': /* remote user */ if (!test) { len2 = snprintf(b, FPM_LOG_BUFFER - len, "%s", proc.auth_user); } break; case '{': /* complex var */ token = 1; { char *start; size_t l; start = ++s; while (*s != '\0') { if (*s == '}') { l = s - start; if (l >= sizeof(format) - 1) { l = sizeof(format) - 1; } memcpy(format, start, l); format[l] = '\0'; break; } s++; } if (s[1] == '\0') { zlog(ZLOG_WARNING, "missing closing embrace in the access.format"); return -1; } } break; default: zlog(ZLOG_WARNING, "Invalid token in the access.format (%%%c)", *s); return -1; } if (*s != '}' && format[0] != '\0') { zlog(ZLOG_WARNING, "embrace is not allowed for modifier %%%c", *s); return -1; } s++; if (!test) { b += len2; len += len2; } continue; } if (!test) { // push the normal char to the output buffer *b = *s; b++; len++; } s++; } if (!test && strlen(buffer) > 0) { buffer[len] = '\n'; write(fpm_log_fd, buffer, len + 1); } return 0; }
static int sapi_uwsgi_send_headers(sapi_headers_struct *sapi_headers) { sapi_header_struct *h; zend_llist_position pos; struct iovec iov[6]; char status[4]; struct http_status_codes *http_sc; if (SG(request_info).no_headers == 1) { return SAPI_HEADER_SENT_SUCCESSFULLY; } struct wsgi_request *wsgi_req = (struct wsgi_request *) SG(server_context); wsgi_req->status = SG(sapi_headers).http_response_code; if (!wsgi_req->status) wsgi_req->status = 200; if (!SG(sapi_headers).http_status_line) { iov[0].iov_base = wsgi_req->protocol; iov[0].iov_len = wsgi_req->protocol_len; iov[1].iov_base = " "; iov[1].iov_len = 1; uwsgi_num2str2n(wsgi_req->status, status, 4); iov[2].iov_base = status; iov[2].iov_len = 3; iov[3].iov_base = " "; iov[3].iov_len = 1; // get the status code for (http_sc = hsc; http_sc->message != NULL; http_sc++) { if (!strncmp(http_sc->key, status, 3)) { iov[4].iov_base = (char *) http_sc->message; iov[4].iov_len = http_sc->message_size; break; } } if (iov[4].iov_len == 0) { iov[4].iov_base = "Unknown"; iov[4].iov_len = 7; } iov[5].iov_base = "\r\n"; iov[5].iov_len = 2; wsgi_req->headers_size += wsgi_req->socket->proto_writev_header(wsgi_req, iov, 6); } else { iov[0].iov_base = SG(sapi_headers).http_status_line; iov[0].iov_len = strlen(iov[0].iov_base); iov[1].iov_base = "\r\n"; iov[1].iov_len = 2; wsgi_req->headers_size += wsgi_req->socket->proto_writev_header(wsgi_req, iov, 2); } h = zend_llist_get_first_ex(&sapi_headers->headers, &pos); while (h) { iov[0].iov_base = h->header; iov[0].iov_len = h->header_len; iov[1].iov_base = "\r\n"; iov[1].iov_len = 2; wsgi_req->headers_size += wsgi_req->socket->proto_writev_header(wsgi_req, iov, 2); wsgi_req->header_cnt++; h = zend_llist_get_next_ex(&sapi_headers->headers, &pos); } struct uwsgi_string_list *ah = uwsgi.additional_headers; while(ah) { iov[0].iov_base = ah->value; iov[0].iov_len = ah->len; iov[1].iov_base = "\r\n"; iov[1].iov_len = 2; wsgi_req->headers_size += wsgi_req->socket->proto_writev_header(wsgi_req, iov, 2); wsgi_req->header_cnt++; ah = ah->next; } ah = wsgi_req->additional_headers; while(ah) { iov[0].iov_base = ah->value; iov[0].iov_len = ah->len; iov[1].iov_base = "\r\n"; iov[1].iov_len = 2; wsgi_req->headers_size += wsgi_req->socket->proto_writev_header(wsgi_req, iov, 2); wsgi_req->header_cnt++; ah = ah->next; } wsgi_req->headers_size += wsgi_req->socket->proto_write_header(wsgi_req, "\r\n", 2); return SAPI_HEADER_SENT_SUCCESSFULLY; }
/* {{{ entity_charset determine_charset * returns the charset identifier based on current locale or a hint. * defaults to UTF-8 */ static enum entity_charset determine_charset(char *charset_hint) { size_t i; enum entity_charset charset = cs_utf_8; size_t len = 0; const zend_encoding *zenc; /* Default is now UTF-8 */ if (charset_hint == NULL) return cs_utf_8; if ((len = strlen(charset_hint)) != 0) { goto det_charset; } zenc = zend_multibyte_get_internal_encoding(); if (zenc != NULL) { charset_hint = (char *)zend_multibyte_get_encoding_name(zenc); if (charset_hint != NULL && (len=strlen(charset_hint)) != 0) { if ((len == 4) /* sizeof (auto|pass) */ && /* XXX should the "wchar" be ignored as well?? */ (!memcmp("pass", charset_hint, 4) || !memcmp("auto", charset_hint, 4))) { charset_hint = NULL; len = 0; } else { goto det_charset; } } } charset_hint = SG(default_charset); if (charset_hint != NULL && (len=strlen(charset_hint)) != 0) { goto det_charset; } /* try to detect the charset for the locale */ #if HAVE_NL_LANGINFO && HAVE_LOCALE_H && defined(CODESET) charset_hint = nl_langinfo(CODESET); if (charset_hint != NULL && (len=strlen(charset_hint)) != 0) { goto det_charset; } #endif #if HAVE_LOCALE_H /* try to figure out the charset from the locale */ { char *localename; char *dot, *at; /* lang[_territory][.codeset][@modifier] */ localename = setlocale(LC_CTYPE, NULL); dot = strchr(localename, '.'); if (dot) { dot++; /* locale specifies a codeset */ at = strchr(dot, '@'); if (at) len = at - dot; else len = strlen(dot); charset_hint = dot; } else { /* no explicit name; see if the name itself * is the charset */ charset_hint = localename; len = strlen(charset_hint); } } #endif det_charset: if (charset_hint) { int found = 0; /* now walk the charset map and look for the codeset */ for (i = 0; i < sizeof(charset_map)/sizeof(charset_map[0]); i++) { if (len == charset_map[i].codeset_len && zend_binary_strcasecmp(charset_hint, len, charset_map[i].codeset, len) == 0) { charset = charset_map[i].charset; found = 1; break; } } if (!found) { php_error_docref(NULL, E_WARNING, "charset `%s' not supported, assuming utf-8", charset_hint); } } return charset; }
int fpm_status_handle_request(void) /* {{{ */ { struct fpm_scoreboard_s scoreboard, *scoreboard_p; struct fpm_scoreboard_proc_s proc; char *buffer, *time_format, time_buffer[64]; time_t now_epoch; int full, encode; char *short_syntax, *short_post; char *full_pre, *full_syntax, *full_post, *full_separator; zend_string *_GET_str; if (!SG(request_info).request_uri) { return 0; } /* PING */ if (fpm_status_ping_uri && fpm_status_ping_response && !strcmp(fpm_status_ping_uri, SG(request_info).request_uri)) { fpm_request_executing(); sapi_add_header_ex(ZEND_STRL("Content-Type: text/plain"), 1, 1); sapi_add_header_ex(ZEND_STRL("Expires: Thu, 01 Jan 1970 00:00:00 GMT"), 1, 1); sapi_add_header_ex(ZEND_STRL("Cache-Control: no-cache, no-store, must-revalidate, max-age=0"), 1, 1); SG(sapi_headers).http_response_code = 200; /* handle HEAD */ if (SG(request_info).headers_only) { return 1; } PUTS(fpm_status_ping_response); return 1; } /* STATUS */ if (fpm_status_uri && !strcmp(fpm_status_uri, SG(request_info).request_uri)) { fpm_request_executing(); scoreboard_p = fpm_scoreboard_get(); if (!scoreboard_p) { zlog(ZLOG_ERROR, "status: unable to find or access status shared memory"); SG(sapi_headers).http_response_code = 500; sapi_add_header_ex(ZEND_STRL("Content-Type: text/plain"), 1, 1); sapi_add_header_ex(ZEND_STRL("Expires: Thu, 01 Jan 1970 00:00:00 GMT"), 1, 1); sapi_add_header_ex(ZEND_STRL("Cache-Control: no-cache, no-store, must-revalidate, max-age=0"), 1, 1); PUTS("Internal error. Please review log file for errors."); return 1; } if (!fpm_spinlock(&scoreboard_p->lock, 1)) { zlog(ZLOG_NOTICE, "[pool %s] status: scoreboard already in used.", scoreboard_p->pool); SG(sapi_headers).http_response_code = 503; sapi_add_header_ex(ZEND_STRL("Content-Type: text/plain"), 1, 1); sapi_add_header_ex(ZEND_STRL("Expires: Thu, 01 Jan 1970 00:00:00 GMT"), 1, 1); sapi_add_header_ex(ZEND_STRL("Cache-Control: no-cache, no-store, must-revalidate, max-age=0"), 1, 1); PUTS("Server busy. Please try again later."); return 1; } /* copy the scoreboard not to bother other processes */ scoreboard = *scoreboard_p; fpm_unlock(scoreboard_p->lock); if (scoreboard.idle < 0 || scoreboard.active < 0) { zlog(ZLOG_ERROR, "[pool %s] invalid status values", scoreboard.pool); SG(sapi_headers).http_response_code = 500; sapi_add_header_ex(ZEND_STRL("Content-Type: text/plain"), 1, 1); sapi_add_header_ex(ZEND_STRL("Expires: Thu, 01 Jan 1970 00:00:00 GMT"), 1, 1); sapi_add_header_ex(ZEND_STRL("Cache-Control: no-cache, no-store, must-revalidate, max-age=0"), 1, 1); PUTS("Internal error. Please review log file for errors."); return 1; } /* send common headers */ sapi_add_header_ex(ZEND_STRL("Expires: Thu, 01 Jan 1970 00:00:00 GMT"), 1, 1); sapi_add_header_ex(ZEND_STRL("Cache-Control: no-cache, no-store, must-revalidate, max-age=0"), 1, 1); SG(sapi_headers).http_response_code = 200; /* handle HEAD */ if (SG(request_info).headers_only) { return 1; } /* full status ? */ _GET_str = zend_string_init("_GET", sizeof("_GET")-1, 0); full = (fpm_php_get_string_from_table(_GET_str, "full") != NULL); short_syntax = short_post = NULL; full_separator = full_pre = full_syntax = full_post = NULL; encode = 0; /* HTML */ if (fpm_php_get_string_from_table(_GET_str, "html")) { sapi_add_header_ex(ZEND_STRL("Content-Type: text/html"), 1, 1); time_format = "%d/%b/%Y:%H:%M:%S %z"; encode = 1; short_syntax = "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n" "<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\">\n" "<head><title>PHP-FPM Status Page</title></head>\n" "<body>\n" "<table>\n" "<tr><th>pool</th><td>%s</td></tr>\n" "<tr><th>process manager</th><td>%s</td></tr>\n" "<tr><th>start time</th><td>%s</td></tr>\n" "<tr><th>start since</th><td>%lu</td></tr>\n" "<tr><th>accepted conn</th><td>%lu</td></tr>\n" #ifdef HAVE_FPM_LQ "<tr><th>listen queue</th><td>%u</td></tr>\n" "<tr><th>max listen queue</th><td>%u</td></tr>\n" "<tr><th>listen queue len</th><td>%d</td></tr>\n" #endif "<tr><th>idle processes</th><td>%d</td></tr>\n" "<tr><th>active processes</th><td>%d</td></tr>\n" "<tr><th>total processes</th><td>%d</td></tr>\n" "<tr><th>max active processes</th><td>%d</td></tr>\n" "<tr><th>max children reached</th><td>%u</td></tr>\n" "<tr><th>slow requests</th><td>%lu</td></tr>\n" "</table>\n"; if (!full) { short_post = "</body></html>"; } else { full_pre = "<table border=\"1\">\n" "<tr>" "<th>pid</th>" "<th>state</th>" "<th>start time</th>" "<th>start since</th>" "<th>requests</th>" "<th>request duration</th>" "<th>request method</th>" "<th>request uri</th>" "<th>content length</th>" "<th>user</th>" "<th>script</th>" #ifdef HAVE_FPM_LQ "<th>last request cpu</th>" #endif "<th>last request memory</th>" "</tr>\n"; full_syntax = "<tr>" "<td>%d</td>" "<td>%s</td>" "<td>%s</td>" "<td>%lu</td>" "<td>%lu</td>" "<td>%lu</td>" "<td>%s</td>" "<td>%s%s%s</td>" "<td>%zu</td>" "<td>%s</td>" "<td>%s</td>" #ifdef HAVE_FPM_LQ "<td>%.2f</td>" #endif "<td>%zu</td>" "</tr>\n"; full_post = "</table></body></html>"; } /* XML */ } else if (fpm_php_get_string_from_table(_GET_str, "xml")) { sapi_add_header_ex(ZEND_STRL("Content-Type: text/xml"), 1, 1); time_format = "%s"; encode = 1; short_syntax = "<?xml version=\"1.0\" ?>\n" "<status>\n" "<pool>%s</pool>\n" "<process-manager>%s</process-manager>\n" "<start-time>%s</start-time>\n" "<start-since>%lu</start-since>\n" "<accepted-conn>%lu</accepted-conn>\n" #ifdef HAVE_FPM_LQ "<listen-queue>%u</listen-queue>\n" "<max-listen-queue>%u</max-listen-queue>\n" "<listen-queue-len>%d</listen-queue-len>\n" #endif "<idle-processes>%d</idle-processes>\n" "<active-processes>%d</active-processes>\n" "<total-processes>%d</total-processes>\n" "<max-active-processes>%d</max-active-processes>\n" "<max-children-reached>%u</max-children-reached>\n" "<slow-requests>%lu</slow-requests>\n"; if (!full) { short_post = "</status>"; } else { full_pre = "<processes>\n"; full_syntax = "<process>" "<pid>%d</pid>" "<state>%s</state>" "<start-time>%s</start-time>" "<start-since>%lu</start-since>" "<requests>%lu</requests>" "<request-duration>%lu</request-duration>" "<request-method>%s</request-method>" "<request-uri>%s%s%s</request-uri>" "<content-length>%zu</content-length>" "<user>%s</user>" "<script>%s</script>" #ifdef HAVE_FPM_LQ "<last-request-cpu>%.2f</last-request-cpu>" #endif "<last-request-memory>%zu</last-request-memory>" "</process>\n" ; full_post = "</processes>\n</status>"; } /* JSON */ } else if (fpm_php_get_string_from_table(_GET_str, "json")) { sapi_add_header_ex(ZEND_STRL("Content-Type: application/json"), 1, 1); time_format = "%s"; short_syntax = "{" "\"pool\":\"%s\"," "\"process manager\":\"%s\"," "\"start time\":%s," "\"start since\":%lu," "\"accepted conn\":%lu," #ifdef HAVE_FPM_LQ "\"listen queue\":%u," "\"max listen queue\":%u," "\"listen queue len\":%d," #endif "\"idle processes\":%d," "\"active processes\":%d," "\"total processes\":%d," "\"max active processes\":%d," "\"max children reached\":%u," "\"slow requests\":%lu"; if (!full) { short_post = "}"; } else { full_separator = ","; full_pre = ", \"processes\":["; full_syntax = "{" "\"pid\":%d," "\"state\":\"%s\"," "\"start time\":%s," "\"start since\":%lu," "\"requests\":%lu," "\"request duration\":%lu," "\"request method\":\"%s\"," "\"request uri\":\"%s%s%s\"," "\"content length\":%zu," "\"user\":\"%s\"," "\"script\":\"%s\"," #ifdef HAVE_FPM_LQ "\"last request cpu\":%.2f," #endif "\"last request memory\":%zu" "}"; full_post = "]}"; } /* TEXT */ } else { sapi_add_header_ex(ZEND_STRL("Content-Type: text/plain"), 1, 1); time_format = "%d/%b/%Y:%H:%M:%S %z"; short_syntax = "pool: %s\n" "process manager: %s\n" "start time: %s\n" "start since: %lu\n" "accepted conn: %lu\n" #ifdef HAVE_FPM_LQ "listen queue: %u\n" "max listen queue: %u\n" "listen queue len: %d\n" #endif "idle processes: %d\n" "active processes: %d\n" "total processes: %d\n" "max active processes: %d\n" "max children reached: %u\n" "slow requests: %lu\n"; if (full) { full_syntax = "\n" "************************\n" "pid: %d\n" "state: %s\n" "start time: %s\n" "start since: %lu\n" "requests: %lu\n" "request duration: %lu\n" "request method: %s\n" "request URI: %s%s%s\n" "content length: %zu\n" "user: %s\n" "script: %s\n" #ifdef HAVE_FPM_LQ "last request cpu: %.2f\n" #endif "last request memory: %zu\n"; } } strftime(time_buffer, sizeof(time_buffer) - 1, time_format, localtime(&scoreboard.start_epoch)); now_epoch = time(NULL); spprintf(&buffer, 0, short_syntax, scoreboard.pool, PM2STR(scoreboard.pm), time_buffer, now_epoch - scoreboard.start_epoch, scoreboard.requests, #ifdef HAVE_FPM_LQ scoreboard.lq, scoreboard.lq_max, scoreboard.lq_len, #endif scoreboard.idle, scoreboard.active, scoreboard.idle + scoreboard.active, scoreboard.active_max, scoreboard.max_children_reached, scoreboard.slow_rq); PUTS(buffer); efree(buffer); zend_string_release(_GET_str); if (short_post) { PUTS(short_post); } /* no need to test the var 'full' */ if (full_syntax) { unsigned int i; int first; zend_string *tmp_query_string; char *query_string; struct timeval duration, now; #ifdef HAVE_FPM_LQ float cpu; #endif fpm_clock_get(&now); if (full_pre) { PUTS(full_pre); } first = 1; for (i=0; i<scoreboard_p->nprocs; i++) { if (!scoreboard_p->procs[i] || !scoreboard_p->procs[i]->used) { continue; } proc = *scoreboard_p->procs[i]; if (first) { first = 0; } else { if (full_separator) { PUTS(full_separator); } } query_string = NULL; tmp_query_string = NULL; if (proc.query_string[0] != '\0') { if (!encode) { query_string = proc.query_string; } else { tmp_query_string = php_escape_html_entities_ex((unsigned char *)proc.query_string, strlen(proc.query_string), 1, ENT_HTML_IGNORE_ERRORS & ENT_COMPAT, NULL, 1); query_string = ZSTR_VAL(tmp_query_string); } } #ifdef HAVE_FPM_LQ /* prevent NaN */ if (proc.cpu_duration.tv_sec == 0 && proc.cpu_duration.tv_usec == 0) { cpu = 0.; } else { cpu = (proc.last_request_cpu.tms_utime + proc.last_request_cpu.tms_stime + proc.last_request_cpu.tms_cutime + proc.last_request_cpu.tms_cstime) / fpm_scoreboard_get_tick() / (proc.cpu_duration.tv_sec + proc.cpu_duration.tv_usec / 1000000.) * 100.; } #endif if (proc.request_stage == FPM_REQUEST_ACCEPTING) { duration = proc.duration; } else { timersub(&now, &proc.accepted, &duration); } strftime(time_buffer, sizeof(time_buffer) - 1, time_format, localtime(&proc.start_epoch)); spprintf(&buffer, 0, full_syntax, proc.pid, fpm_request_get_stage_name(proc.request_stage), time_buffer, now_epoch - proc.start_epoch, proc.requests, duration.tv_sec * 1000000UL + duration.tv_usec, proc.request_method[0] != '\0' ? proc.request_method : "-", proc.request_uri[0] != '\0' ? proc.request_uri : "-", query_string ? "?" : "", query_string ? query_string : "", proc.content_length, proc.auth_user[0] != '\0' ? proc.auth_user : "******", proc.script_filename[0] != '\0' ? proc.script_filename : "-", #ifdef HAVE_FPM_LQ proc.request_stage == FPM_REQUEST_ACCEPTING ? cpu : 0., #endif proc.request_stage == FPM_REQUEST_ACCEPTING ? proc.memory : 0); PUTS(buffer); efree(buffer); if (tmp_query_string) { zend_string_free(tmp_query_string); } } if (full_post) { PUTS(full_post); } } return 1; } return 0; }
static int php_apache_request_ctor(request_rec *r, php_struct *ctx) { char *content_length; const char *auth; SG(sapi_headers).http_response_code = !r->status ? HTTP_OK : r->status; SG(request_info).content_type = apr_table_get(r->headers_in, "Content-Type"); SG(request_info).query_string = apr_pstrdup(r->pool, r->args); SG(request_info).request_method = r->method; SG(request_info).proto_num = r->proto_num; SG(request_info).request_uri = apr_pstrdup(r->pool, r->uri); SG(request_info).path_translated = apr_pstrdup(r->pool, r->filename); r->no_local_copy = 1; content_length = (char *) apr_table_get(r->headers_in, "Content-Length"); if (content_length) { ZEND_ATOL(SG(request_info).content_length, content_length); } else { SG(request_info).content_length = 0; } apr_table_unset(r->headers_out, "Content-Length"); apr_table_unset(r->headers_out, "Last-Modified"); apr_table_unset(r->headers_out, "Expires"); apr_table_unset(r->headers_out, "ETag"); auth = apr_table_get(r->headers_in, "Authorization"); php_handle_auth_data(auth); if (SG(request_info).auth_user == NULL && r->user) { SG(request_info).auth_user = estrdup(r->user); } ctx->r->user = apr_pstrdup(ctx->r->pool, SG(request_info).auth_user); return php_request_startup(); }
/* {{{ SAPI_POST_READER_FUNC */ SAPI_API SAPI_POST_READER_FUNC(php_default_post_reader) { char *data; int length; /* $HTTP_RAW_POST_DATA registration */ if (!strcmp(SG(request_info).request_method, "POST")) { if (NULL == SG(request_info).post_entry) { /* no post handler registered, so we just swallow the data */ sapi_read_standard_form_data(TSRMLS_C); } /* For unknown content types we create HTTP_RAW_POST_DATA even if always_populate_raw_post_data off, * this is in-effecient, but we need to keep doing it for BC reasons (for now) */ if ((PG(always_populate_raw_post_data) || NULL == SG(request_info).post_entry) && SG(request_info).post_data) { length = SG(request_info).post_data_length; data = estrndup(SG(request_info).post_data, length); SET_VAR_STRINGL("HTTP_RAW_POST_DATA", data, length); } } /* for php://input stream: some post handlers modify the content of request_info.post_data so for now we need a copy for the php://input stream in the long run post handlers should be changed to not touch request_info.post_data for memory preservation reasons */ if (SG(request_info).post_data) { SG(request_info).raw_post_data = estrndup(SG(request_info).post_data, SG(request_info).post_data_length); SG(request_info).raw_post_data_length = SG(request_info).post_data_length; } }
static double php_apache_sapi_get_request_time(void) { php_struct *ctx = SG(server_context); return ((double) apr_time_as_msec(ctx->r->request_time)) / 1000.0; }
static int php_apache_sapi_header_handler(sapi_header_struct *sapi_header, sapi_header_op_enum op, sapi_headers_struct *sapi_headers) { php_struct *ctx; char *val, *ptr; ctx = SG(server_context); switch (op) { case SAPI_HEADER_DELETE: apr_table_unset(ctx->r->headers_out, sapi_header->header); return 0; case SAPI_HEADER_DELETE_ALL: apr_table_clear(ctx->r->headers_out); return 0; case SAPI_HEADER_ADD: case SAPI_HEADER_REPLACE: val = strchr(sapi_header->header, ':'); if (!val) { return 0; } ptr = val; *val = '\0'; do { val++; } while (*val == ' '); if (!strcasecmp(sapi_header->header, "content-type")) { if (ctx->content_type) { efree(ctx->content_type); } ctx->content_type = estrdup(val); } else if (!strcasecmp(sapi_header->header, "content-length")) { apr_off_t clen = 0; if (APR_SUCCESS != apr_strtoff(&clen, val, (char **) NULL, 10)) { /* We'll fall back to strtol, since that's what we used to * do anyway. */ clen = (apr_off_t) strtol(val, (char **) NULL, 10); } ap_set_content_length(ctx->r, clen); } else if (op == SAPI_HEADER_REPLACE) { apr_table_set(ctx->r->headers_out, sapi_header->header, val); } else { apr_table_add(ctx->r->headers_out, sapi_header->header, val); } *ptr = ':'; return SAPI_HEADER_ADD; default: return 0; } }
SAPI_API SAPI_POST_HANDLER_FUNC(suhosin_rfc1867_post_handler) /* {{{ */ { char *boundary, *s = NULL, *boundary_end = NULL, *start_arr = NULL, *array_index = NULL; char *lbuf = NULL, *abuf = NULL; zend_string *temp_filename = NULL; int boundary_len = 0, cancel_upload = 0, is_arr_upload = 0, array_len = 0; int64_t total_bytes = 0, max_file_size = 0; int skip_upload = 0, anonindex = 0, is_anonymous; HashTable *uploaded_files = NULL; multipart_buffer *mbuff; zval *array_ptr = (zval *) arg; int fd = -1; zend_llist header; void *event_extra_data = NULL; unsigned int llen = 0; int upload_cnt = INI_INT("max_file_uploads"); const zend_encoding *internal_encoding = zend_multibyte_get_internal_encoding(); php_rfc1867_getword_t getword; php_rfc1867_getword_conf_t getword_conf; php_rfc1867_basename_t _basename; zend_long count = 0; if (php_rfc1867_encoding_translation() && internal_encoding) { getword = php_rfc1867_getword; getword_conf = php_rfc1867_getword_conf; _basename = php_rfc1867_basename; } else { getword = php_ap_getword; getword_conf = php_ap_getword_conf; _basename = php_ap_basename; } if (SG(post_max_size) > 0 && SG(request_info).content_length > SG(post_max_size)) { sapi_module.sapi_error(E_WARNING, "POST Content-Length of " ZEND_LONG_FMT " bytes exceeds the limit of " ZEND_LONG_FMT " bytes", SG(request_info).content_length, SG(post_max_size)); return; } /* Get the boundary */ boundary = strstr(content_type_dup, "boundary"); if (!boundary) { int content_type_len = (int)strlen(content_type_dup); char *content_type_lcase = estrndup(content_type_dup, content_type_len); php_strtolower(content_type_lcase, content_type_len); boundary = strstr(content_type_lcase, "boundary"); if (boundary) { boundary = content_type_dup + (boundary - content_type_lcase); } efree(content_type_lcase); } if (!boundary || !(boundary = strchr(boundary, '='))) { sapi_module.sapi_error(E_WARNING, "Missing boundary in multipart/form-data POST data"); return; } boundary++; boundary_len = (int)strlen(boundary); if (boundary[0] == '"') { boundary++; boundary_end = strchr(boundary, '"'); if (!boundary_end) { sapi_module.sapi_error(E_WARNING, "Invalid boundary in multipart/form-data POST data"); return; } } else { /* search for the end of the boundary */ boundary_end = strpbrk(boundary, ",;"); } if (boundary_end) { boundary_end[0] = '\0'; boundary_len = boundary_end-boundary; } /* Initialize the buffer */ if (!(mbuff = multipart_buffer_new(boundary, boundary_len))) { sapi_module.sapi_error(E_WARNING, "Unable to initialize the input buffer"); return; } /* Initialize $_FILES[] */ zend_hash_init(&PG(rfc1867_protected_variables), 8, NULL, NULL, 0); ALLOC_HASHTABLE(uploaded_files); zend_hash_init(uploaded_files, 8, NULL, free_filename, 0); SG(rfc1867_uploaded_files) = uploaded_files; if (Z_TYPE(PG(http_globals)[TRACK_VARS_FILES]) != IS_ARRAY) { /* php_auto_globals_create_files() might have already done that */ array_init(&PG(http_globals)[TRACK_VARS_FILES]); } zend_llist_init(&header, sizeof(mime_header_entry), (llist_dtor_func_t) php_free_hdr_entry, 0); if (php_rfc1867_callback != NULL) { multipart_event_start event_start; event_start.content_length = SG(request_info).content_length; if (php_rfc1867_callback(MULTIPART_EVENT_START, &event_start, &event_extra_data) == FAILURE) { goto fileupload_done; } } while (!multipart_buffer_eof(mbuff)) { char buff[FILLUNIT]; char *cd = NULL, *param = NULL, *filename = NULL, *tmp = NULL; size_t blen = 0, wlen = 0; zend_off_t offset; zend_llist_clean(&header); if (!multipart_buffer_headers(mbuff, &header)) { goto fileupload_done; } if ((cd = php_mime_get_hdr_value(header, "Content-Disposition"))) { char *pair = NULL; int end = 0; while (isspace(*cd)) { ++cd; } while (*cd && (pair = getword(mbuff->input_encoding, &cd, ';'))) { char *key = NULL, *word = pair; while (isspace(*cd)) { ++cd; } if (strchr(pair, '=')) { key = getword(mbuff->input_encoding, &pair, '='); if (!strcasecmp(key, "name")) { if (param) { efree(param); } param = getword_conf(mbuff->input_encoding, pair); if (mbuff->input_encoding && internal_encoding) { unsigned char *new_param; size_t new_param_len; if ((size_t)-1 != zend_multibyte_encoding_converter(&new_param, &new_param_len, (unsigned char *)param, strlen(param), internal_encoding, mbuff->input_encoding)) { efree(param); param = (char *)new_param; } } } else if (!strcasecmp(key, "filename")) { if (filename) { efree(filename); } filename = getword_conf(mbuff->input_encoding, pair); if (mbuff->input_encoding && internal_encoding) { unsigned char *new_filename; size_t new_filename_len; if ((size_t)-1 != zend_multibyte_encoding_converter(&new_filename, &new_filename_len, (unsigned char *)filename, strlen(filename), internal_encoding, mbuff->input_encoding)) { efree(filename); filename = (char *)new_filename; } } } } if (key) { efree(key); } efree(word); } /* Normal form variable, safe to read all data into memory */ if (!filename && param) { size_t value_len; char *value = multipart_buffer_read_body(mbuff, &value_len); size_t new_val_len; /* Dummy variable */ if (!value) { value = estrdup(""); value_len = 0; } if (mbuff->input_encoding && internal_encoding) { unsigned char *new_value; size_t new_value_len; if ((size_t)-1 != zend_multibyte_encoding_converter(&new_value, &new_value_len, (unsigned char *)value, value_len, internal_encoding, mbuff->input_encoding)) { efree(value); value = (char *)new_value; value_len = new_value_len; } } if (++count <= PG(max_input_vars) && sapi_module.input_filter(PARSE_POST, param, &value, value_len, &new_val_len)) { if (php_rfc1867_callback != NULL) { multipart_event_formdata event_formdata; size_t newlength = new_val_len; event_formdata.post_bytes_processed = SG(read_post_bytes); event_formdata.name = param; event_formdata.value = &value; event_formdata.length = new_val_len; event_formdata.newlength = &newlength; if (php_rfc1867_callback(MULTIPART_EVENT_FORMDATA, &event_formdata, &event_extra_data) == FAILURE) { efree(param); efree(value); continue; } new_val_len = newlength; } safe_php_register_variable(param, value, new_val_len, array_ptr, 0); } else { if (count == PG(max_input_vars) + 1) { php_error_docref(NULL, E_WARNING, "Input variables exceeded " ZEND_LONG_FMT ". To increase the limit change max_input_vars in php.ini.", PG(max_input_vars)); } if (php_rfc1867_callback != NULL) { multipart_event_formdata event_formdata; event_formdata.post_bytes_processed = SG(read_post_bytes); event_formdata.name = param; event_formdata.value = &value; event_formdata.length = value_len; event_formdata.newlength = NULL; php_rfc1867_callback(MULTIPART_EVENT_FORMDATA, &event_formdata, &event_extra_data); } } if (!strcasecmp(param, "MAX_FILE_SIZE")) { #ifdef HAVE_ATOLL max_file_size = atoll(value); #else max_file_size = strtoll(value, NULL, 10); #endif } efree(param); efree(value); continue; } /* If file_uploads=off, skip the file part */ if (!PG(file_uploads)) { skip_upload = 1; } else if (upload_cnt <= 0) { skip_upload = 1; sapi_module.sapi_error(E_WARNING, "Maximum number of allowable file uploads has been exceeded"); } /* Return with an error if the posted data is garbled */ if (!param && !filename) { sapi_module.sapi_error(E_WARNING, "File Upload Mime headers garbled"); goto fileupload_done; } if (!param) { is_anonymous = 1; param = emalloc(MAX_SIZE_ANONNAME); snprintf(param, MAX_SIZE_ANONNAME, "%u", anonindex++); } else { is_anonymous = 0; } /* New Rule: never repair potential malicious user input */ if (!skip_upload) { long c = 0; tmp = param; while (*tmp) { if (*tmp == '[') { c++; } else if (*tmp == ']') { c--; if (tmp[1] && tmp[1] != '[') { skip_upload = 1; break; } } if (c < 0) { skip_upload = 1; break; } tmp++; } /* Brackets should always be closed */ if(c != 0) { skip_upload = 1; } } total_bytes = cancel_upload = 0; temp_filename = NULL; fd = -1; if (!skip_upload && php_rfc1867_callback != NULL) { multipart_event_file_start event_file_start; event_file_start.post_bytes_processed = SG(read_post_bytes); event_file_start.name = param; event_file_start.filename = &filename; if (php_rfc1867_callback(MULTIPART_EVENT_FILE_START, &event_file_start, &event_extra_data) == FAILURE) { temp_filename = NULL; efree(param); efree(filename); continue; } } if (skip_upload) { efree(param); efree(filename); continue; } if (filename[0] == '\0') { #if DEBUG_FILE_UPLOAD sapi_module.sapi_error(E_NOTICE, "No file uploaded"); #endif cancel_upload = UPLOAD_ERROR_D; } offset = 0; end = 0; if (!cancel_upload) { /* only bother to open temp file if we have data */ blen = multipart_buffer_read(mbuff, buff, sizeof(buff), &end); #if DEBUG_FILE_UPLOAD if (blen > 0) { #else /* in non-debug mode we have no problem with 0-length files */ { #endif fd = php_open_temporary_fd_ex(PG(upload_tmp_dir), "php", &temp_filename, 1); upload_cnt--; if (fd == -1) { sapi_module.sapi_error(E_WARNING, "File upload error - unable to create a temporary file"); cancel_upload = UPLOAD_ERROR_E; } } } while (!cancel_upload && (blen > 0)) { if (php_rfc1867_callback != NULL) { multipart_event_file_data event_file_data; event_file_data.post_bytes_processed = SG(read_post_bytes); event_file_data.offset = offset; event_file_data.data = buff; event_file_data.length = blen; event_file_data.newlength = &blen; if (php_rfc1867_callback(MULTIPART_EVENT_FILE_DATA, &event_file_data, &event_extra_data) == FAILURE) { cancel_upload = UPLOAD_ERROR_X; continue; } } if (PG(upload_max_filesize) > 0 && (zend_long)(total_bytes+blen) > PG(upload_max_filesize)) { #if DEBUG_FILE_UPLOAD sapi_module.sapi_error(E_NOTICE, "upload_max_filesize of " ZEND_LONG_FMT " bytes exceeded - file [%s=%s] not saved", PG(upload_max_filesize), param, filename); #endif cancel_upload = UPLOAD_ERROR_A; } else if (max_file_size && ((zend_long)(total_bytes+blen) > max_file_size)) { #if DEBUG_FILE_UPLOAD sapi_module.sapi_error(E_NOTICE, "MAX_FILE_SIZE of " ZEND_LONG_FMT " bytes exceeded - file [%s=%s] not saved", max_file_size, param, filename); #endif cancel_upload = UPLOAD_ERROR_B; } else if (blen > 0) { #ifdef PHP_WIN32 wlen = write(fd, buff, (unsigned int)blen); #else wlen = write(fd, buff, blen); #endif if (wlen == -1) { /* write failed */ #if DEBUG_FILE_UPLOAD sapi_module.sapi_error(E_NOTICE, "write() failed - %s", strerror(errno)); #endif cancel_upload = UPLOAD_ERROR_F; } else if (wlen < blen) { #if DEBUG_FILE_UPLOAD sapi_module.sapi_error(E_NOTICE, "Only %d bytes were written, expected to write %d", wlen, blen); #endif cancel_upload = UPLOAD_ERROR_F; } else { total_bytes += wlen; } offset += wlen; } /* read data for next iteration */ blen = multipart_buffer_read(mbuff, buff, sizeof(buff), &end); } if (fd != -1) { /* may not be initialized if file could not be created */ close(fd); } if (!cancel_upload && !end) { #if DEBUG_FILE_UPLOAD sapi_module.sapi_error(E_NOTICE, "Missing mime boundary at the end of the data for file %s", filename[0] != '\0' ? filename : ""); #endif cancel_upload = UPLOAD_ERROR_C; } #if DEBUG_FILE_UPLOAD if (filename[0] != '\0' && total_bytes == 0 && !cancel_upload) { sapi_module.sapi_error(E_WARNING, "Uploaded file size 0 - file [%s=%s] not saved", param, filename); cancel_upload = 5; } #endif if (php_rfc1867_callback != NULL) { multipart_event_file_end event_file_end; event_file_end.post_bytes_processed = SG(read_post_bytes); event_file_end.temp_filename = ZSTR_VAL(temp_filename); event_file_end.cancel_upload = cancel_upload; if (php_rfc1867_callback(MULTIPART_EVENT_FILE_END, &event_file_end, &event_extra_data) == FAILURE) { cancel_upload = UPLOAD_ERROR_X; } } if (cancel_upload) { if (temp_filename) { if (cancel_upload != UPLOAD_ERROR_E) { /* file creation failed */ unlink(ZSTR_VAL(temp_filename)); } zend_string_release(temp_filename); } temp_filename = NULL; } else { zend_hash_add_ptr(SG(rfc1867_uploaded_files), temp_filename, temp_filename); } /* is_arr_upload is true when name of file upload field * ends in [.*] * start_arr is set to point to 1st [ */ is_arr_upload = (start_arr = strchr(param,'[')) && (param[strlen(param)-1] == ']'); if (is_arr_upload) { array_len = (int)strlen(start_arr); if (array_index) { efree(array_index); } array_index = estrndup(start_arr + 1, array_len - 2); } /* Add $foo_name */ if (llen < strlen(param) + MAX_SIZE_OF_INDEX + 1) { llen = (int)strlen(param); lbuf = (char *) safe_erealloc(lbuf, llen, 1, MAX_SIZE_OF_INDEX + 1); llen += MAX_SIZE_OF_INDEX + 1; } if (is_arr_upload) { if (abuf) efree(abuf); abuf = estrndup(param, strlen(param)-array_len); snprintf(lbuf, llen, "%s_name[%s]", abuf, array_index); } else { snprintf(lbuf, llen, "%s_name", param); } /* The \ check should technically be needed for win32 systems only where * it is a valid path separator. However, IE in all it's wisdom always sends * the full path of the file on the user's filesystem, which means that unless * the user does basename() they get a bogus file name. Until IE's user base drops * to nill or problem is fixed this code must remain enabled for all systems. */ s = _basename(internal_encoding, filename); if (!s) { s = filename; } if (!is_anonymous) { safe_php_register_variable(lbuf, s, strlen(s), NULL, 0); } /* Add $foo[name] */ if (is_arr_upload) { snprintf(lbuf, llen, "%s[name][%s]", abuf, array_index); } else { snprintf(lbuf, llen, "%s[name]", param); } register_http_post_files_variable(lbuf, s, &PG(http_globals)[TRACK_VARS_FILES], 0); efree(filename); s = NULL; /* Possible Content-Type: */ if (cancel_upload || !(cd = php_mime_get_hdr_value(header, "Content-Type"))) { cd = ""; } else { /* fix for Opera 6.01 */ s = strchr(cd, ';'); if (s != NULL) { *s = '\0'; } } /* Add $foo_type */ if (is_arr_upload) { snprintf(lbuf, llen, "%s_type[%s]", abuf, array_index); } else { snprintf(lbuf, llen, "%s_type", param); } if (!is_anonymous) { safe_php_register_variable(lbuf, cd, strlen(cd), NULL, 0); } /* Add $foo[type] */ if (is_arr_upload) { snprintf(lbuf, llen, "%s[type][%s]", abuf, array_index); } else { snprintf(lbuf, llen, "%s[type]", param); } register_http_post_files_variable(lbuf, cd, &PG(http_globals)[TRACK_VARS_FILES], 0); /* Restore Content-Type Header */ if (s != NULL) { *s = ';'; } s = ""; { /* store temp_filename as-is (in case upload_tmp_dir * contains escapeable characters. escape only the variable name.) */ zval zfilename; /* Initialize variables */ add_protected_variable(param); /* if param is of form xxx[.*] this will cut it to xxx */ if (!is_anonymous) { if (temp_filename) { ZVAL_STR_COPY(&zfilename, temp_filename); } else { ZVAL_EMPTY_STRING(&zfilename); } safe_php_register_variable_ex(param, &zfilename, NULL, 1); } /* Add $foo[tmp_name] */ if (is_arr_upload) { snprintf(lbuf, llen, "%s[tmp_name][%s]", abuf, array_index); } else { snprintf(lbuf, llen, "%s[tmp_name]", param); } add_protected_variable(lbuf); if (temp_filename) { ZVAL_STR_COPY(&zfilename, temp_filename); } else { ZVAL_EMPTY_STRING(&zfilename); } register_http_post_files_variable_ex(lbuf, &zfilename, &PG(http_globals)[TRACK_VARS_FILES], 1); } { zval file_size, error_type; int size_overflow = 0; char file_size_buf[65]; ZVAL_LONG(&error_type, cancel_upload); /* Add $foo[error] */ if (cancel_upload) { ZVAL_LONG(&file_size, 0); } else { if (total_bytes > ZEND_LONG_MAX) { #ifdef PHP_WIN32 if (_i64toa_s(total_bytes, file_size_buf, 65, 10)) { file_size_buf[0] = '0'; file_size_buf[1] = '\0'; } #else { int __len = snprintf(file_size_buf, 65, "%lld", total_bytes); file_size_buf[__len] = '\0'; } #endif size_overflow = 1; } else { ZVAL_LONG(&file_size, total_bytes); } } if (is_arr_upload) { snprintf(lbuf, llen, "%s[error][%s]", abuf, array_index); } else { snprintf(lbuf, llen, "%s[error]", param); } register_http_post_files_variable_ex(lbuf, &error_type, &PG(http_globals)[TRACK_VARS_FILES], 0); /* Add $foo_size */ if (is_arr_upload) { snprintf(lbuf, llen, "%s_size[%s]", abuf, array_index); } else { snprintf(lbuf, llen, "%s_size", param); } if (!is_anonymous) { if (size_overflow) { ZVAL_STRING(&file_size, file_size_buf); } safe_php_register_variable_ex(lbuf, &file_size, NULL, size_overflow); } /* Add $foo[size] */ if (is_arr_upload) { snprintf(lbuf, llen, "%s[size][%s]", abuf, array_index); } else { snprintf(lbuf, llen, "%s[size]", param); } if (size_overflow) { ZVAL_STRING(&file_size, file_size_buf); } register_http_post_files_variable_ex(lbuf, &file_size, &PG(http_globals)[TRACK_VARS_FILES], size_overflow); } efree(param); } } fileupload_done: if (php_rfc1867_callback != NULL) { multipart_event_end event_end; event_end.post_bytes_processed = SG(read_post_bytes); php_rfc1867_callback(MULTIPART_EVENT_END, &event_end, &event_extra_data); } if (lbuf) efree(lbuf); if (abuf) efree(abuf); if (array_index) efree(array_index); zend_hash_destroy(&PG(rfc1867_protected_variables)); zend_llist_destroy(&header); if (mbuff->boundary_next) efree(mbuff->boundary_next); if (mbuff->boundary) efree(mbuff->boundary); if (mbuff->buffer) efree(mbuff->buffer); if (mbuff) efree(mbuff); }
EMBED_SAPI_API int php_embed_init(int argc, char **argv) { zend_llist global_vars; #ifdef HAVE_SIGNAL_H #if defined(SIGPIPE) && defined(SIG_IGN) signal(SIGPIPE, SIG_IGN); /* ignore SIGPIPE in standalone mode so that sockets created via fsockopen() don't kill PHP if the remote site closes it. in apache|apxs mode apache does that for us! [email protected] 20000419 */ #endif #endif #ifdef ZTS tsrm_startup(1, 1, 0, NULL); (void)ts_resource(0); ZEND_TSRMLS_CACHE_UPDATE(); #endif #ifdef ZEND_SIGNALS zend_signal_startup(); #endif sapi_startup(&php_embed_module); #ifdef PHP_WIN32 _fmode = _O_BINARY; /*sets default for file streams to binary */ setmode(_fileno(stdin), O_BINARY); /* make the stdio mode be binary */ setmode(_fileno(stdout), O_BINARY); /* make the stdio mode be binary */ setmode(_fileno(stderr), O_BINARY); /* make the stdio mode be binary */ #endif php_embed_module.ini_entries = malloc(sizeof(HARDCODED_INI)); memcpy(php_embed_module.ini_entries, HARDCODED_INI, sizeof(HARDCODED_INI)); php_embed_module.additional_functions = additional_functions; if (argv) { php_embed_module.executable_location = argv[0]; } if (php_embed_module.startup(&php_embed_module)==FAILURE) { return FAILURE; } zend_llist_init(&global_vars, sizeof(char *), NULL, 0); /* Set some Embedded PHP defaults */ SG(options) |= SAPI_OPTION_NO_CHDIR; SG(request_info).argc=argc; SG(request_info).argv=argv; if (php_request_startup()==FAILURE) { php_module_shutdown(); return FAILURE; } SG(headers_sent) = 1; SG(request_info).no_headers = 1; php_register_variable("PHP_SELF", "-", NULL); return SUCCESS; }
virtm_client_clone (void *cli, char *err, int max_err_len) { return cli; } _VPLUGIN_ void virtm_client_free (void *ptr) { } static char * virt_get_env (const char *name TSRMLS_DC) { vreq_t *r = ((vreq_t *) SG (server_context)); int i; /* XXX hashtable */ for (i = 0; i < r->n_options; i += 2) { if (!strcmp (r->options[i], name)) { const char *ret = r->options[i + 1]; if (ret && ret[0]) return (char *) ret; break; } } return NULL;
#include "unixd.h" #endif #include "php_apache.h" #ifdef ZTS int php_apache2_info_id; #else php_apache2_info_struct php_apache2_info; #endif #define SECTION(name) PUTS("<h2>" name "</h2>\n") static request_rec *php_apache_lookup_uri(char *filename TSRMLS_DC) { php_struct *ctx = SG(server_context); if (!filename || !ctx || !ctx->r) { return NULL; } return ap_sub_req_lookup_uri(filename, ctx->r, ctx->r->output_filters); } /* {{{ proto bool virtual(string uri) Perform an apache sub-request */ PHP_FUNCTION(virtual) { char *filename; size_t filename_len; request_rec *rr;
/* {{{ php_zlib_output_handler() */ static int php_zlib_output_handler(void **handler_context, php_output_context *output_context) { php_zlib_context *ctx = *(php_zlib_context **) handler_context; int flags = Z_SYNC_FLUSH; PHP_OUTPUT_TSRMLS(output_context); if (!php_zlib_output_encoding(TSRMLS_C)) { /* "Vary: Accept-Encoding" header sent along uncompressed content breaks caching in MSIE, so let's just send it with successfully compressed content or unless the complete buffer gets discarded, see http://bugs.php.net/40325; Test as follows: +Vary: $ HTTP_ACCEPT_ENCODING=gzip ./sapi/cgi/php <<<'<?php ob_start("ob_gzhandler"); echo "foo\n";' +Vary: $ HTTP_ACCEPT_ENCODING= ./sapi/cgi/php <<<'<?php ob_start("ob_gzhandler"); echo "foo\n";' -Vary: $ HTTP_ACCEPT_ENCODING=gzip ./sapi/cgi/php <<<'<?php ob_start("ob_gzhandler"); echo "foo\n"; ob_end_clean();' -Vary: $ HTTP_ACCEPT_ENCODING= ./sapi/cgi/php <<<'<?php ob_start("ob_gzhandler"); echo "foo\n"; ob_end_clean();' */ if (output_context->op != (PHP_OUTPUT_HANDLER_START|PHP_OUTPUT_HANDLER_CLEAN|PHP_OUTPUT_HANDLER_FINAL)) { sapi_add_header_ex(ZEND_STRL("Vary: Accept-Encoding"), 1, 1 TSRMLS_CC); } return FAILURE; } if (output_context->op & PHP_OUTPUT_HANDLER_START) { /* start up */ if (Z_OK != deflateInit2(&ctx->Z, ZLIBG(output_compression_level), Z_DEFLATED, ZLIBG(compression_coding), MAX_MEM_LEVEL, Z_DEFAULT_STRATEGY)) { return FAILURE; } } if (output_context->op & PHP_OUTPUT_HANDLER_CLEAN) { /* free buffers */ deflateEnd(&ctx->Z); if (output_context->op & PHP_OUTPUT_HANDLER_FINAL) { /* discard */ return SUCCESS; } else { /* restart */ if (Z_OK != deflateInit2(&ctx->Z, ZLIBG(output_compression_level), Z_DEFLATED, ZLIBG(compression_coding), MAX_MEM_LEVEL, Z_DEFAULT_STRATEGY)) { return FAILURE; } ctx->buffer.used = 0; } } else { if (output_context->in.used) { /* append input */ if (ctx->buffer.free < output_context->in.used) { if (!(ctx->buffer.aptr = erealloc_recoverable(ctx->buffer.data, ctx->buffer.used + ctx->buffer.free + output_context->in.used))) { deflateEnd(&ctx->Z); return FAILURE; } ctx->buffer.data = ctx->buffer.aptr; ctx->buffer.free += output_context->in.used; } memcpy(ctx->buffer.data + ctx->buffer.used, output_context->in.data, output_context->in.used); ctx->buffer.free -= output_context->in.used; ctx->buffer.used += output_context->in.used; } output_context->out.size = PHP_ZLIB_BUFFER_SIZE_GUESS(output_context->in.used); output_context->out.data = emalloc(output_context->out.size); output_context->out.free = 1; output_context->out.used = 0; ctx->Z.avail_in = ctx->buffer.used; ctx->Z.next_in = (Bytef *) ctx->buffer.data; ctx->Z.avail_out = output_context->out.size; ctx->Z.next_out = (Bytef *) output_context->out.data; if (output_context->op & PHP_OUTPUT_HANDLER_FINAL) { flags = Z_FINISH; } else if (output_context->op & PHP_OUTPUT_HANDLER_FLUSH) { flags = Z_FULL_FLUSH; } switch (deflate(&ctx->Z, flags)) { case Z_OK: if (flags == Z_FINISH) { deflateEnd(&ctx->Z); return FAILURE; } case Z_STREAM_END: if (ctx->Z.avail_in) { memmove(ctx->buffer.data, ctx->buffer.data + ctx->buffer.used - ctx->Z.avail_in, ctx->Z.avail_in); } ctx->buffer.free += ctx->buffer.used - ctx->Z.avail_in; ctx->buffer.used = ctx->Z.avail_in; output_context->out.used = output_context->out.size - ctx->Z.avail_out; break; default: deflateEnd(&ctx->Z); return FAILURE; } php_output_handler_hook(PHP_OUTPUT_HANDLER_HOOK_GET_FLAGS, &flags TSRMLS_CC); if (!(flags & PHP_OUTPUT_HANDLER_STARTED)) { if (SG(headers_sent) || !ZLIBG(output_compression)) { deflateEnd(&ctx->Z); return FAILURE; } switch (ZLIBG(compression_coding)) { case PHP_ZLIB_ENCODING_GZIP: sapi_add_header_ex(ZEND_STRL("Content-Encoding: gzip"), 1, 1 TSRMLS_CC); break; case PHP_ZLIB_ENCODING_DEFLATE: sapi_add_header_ex(ZEND_STRL("Content-Encoding: deflate"), 1, 1 TSRMLS_CC); break; default: deflateEnd(&ctx->Z); return FAILURE; } sapi_add_header_ex(ZEND_STRL("Vary: Accept-Encoding"), 1, 1 TSRMLS_CC); php_output_handler_hook(PHP_OUTPUT_HANDLER_HOOK_IMMUTABLE, NULL TSRMLS_CC); } if (output_context->op & PHP_OUTPUT_HANDLER_FINAL) { deflateEnd(&ctx->Z); } } return SUCCESS; }
{ uint16_t len = 0; struct wsgi_request *wsgi_req = (struct wsgi_request *) SG(server_context); char *cookie = uwsgi_get_var(wsgi_req, (char *)"HTTP_COOKIE", 11, &len); if (cookie) { return estrndup(cookie, len); } return NULL; } static void sapi_uwsgi_register_variables(zval *track_vars_array TSRMLS_DC) { int i; struct wsgi_request *wsgi_req = (struct wsgi_request *) SG(server_context); php_import_environment_variables(track_vars_array TSRMLS_CC); if (uphp.server_software) { if (!uphp.server_software_len) uphp.server_software_len = strlen(uphp.server_software); php_register_variable_safe("SERVER_SOFTWARE", uphp.server_software, uphp.server_software_len, track_vars_array TSRMLS_CC); } else { php_register_variable_safe("SERVER_SOFTWARE", "uWSGI", 5, track_vars_array TSRMLS_CC); } for (i = 0; i < wsgi_req->var_cnt; i += 2) { php_register_variable_safe( estrndup(wsgi_req->hvec[i].iov_base, wsgi_req->hvec[i].iov_len), wsgi_req->hvec[i + 1].iov_base, wsgi_req->hvec[i + 1].iov_len, track_vars_array TSRMLS_CC); }
if (sent_bytes == -1) { php_handle_aborted_connection(); } return sent_bytes; } static int php_phttpd_sapi_header_handler(sapi_header_struct *sapi_header, sapi_headers_struct *sapi_headers TSRMLS_DC) { char *header_name, *header_content; char *p; TSRMLS_FETCH(); http_sendheaders(PHG(cip)->fd, PHG(cip), SG(sapi_headers).http_response_code, NULL); header_name = sapi_header->header; header_content = p = strchr(header_name, ':'); if (p) { *p = '\0'; do { header_content++; } while (*header_content == ' '); fd_printf(PHG(cip)->fd,"%s: %s\n", header_name, header_content); *p = ':'; }
r = ctx->r; if (ap_rwrite(str, str_length, r) < 0) { php_handle_aborted_connection(); } return str_length; /* we always consume all the data passed to us. */ } static int php_apache_sapi_header_handler(sapi_header_struct *sapi_header, sapi_header_op_enum op, sapi_headers_struct *sapi_headers TSRMLS_DC) { php_struct *ctx; char *val, *ptr; ctx = SG(server_context); switch (op) { case SAPI_HEADER_DELETE: apr_table_unset(ctx->r->headers_out, sapi_header->header); return 0; case SAPI_HEADER_DELETE_ALL: apr_table_clear(ctx->r->headers_out); return 0; case SAPI_HEADER_ADD: case SAPI_HEADER_REPLACE: val = strchr(sapi_header->header, ':'); if (!val) {
/* {{{ MBSTRING_API SAPI_TREAT_DATA_FUNC(mbstr_treat_data) * http input processing */ MBSTRING_API SAPI_TREAT_DATA_FUNC(mbstr_treat_data) { char *res = NULL, *separator=NULL; const char *c_var; zval *array_ptr; int free_buffer=0; const mbfl_encoding *detected; php_mb_encoding_handler_info_t info; if (arg != PARSE_STRING) { char *value = MBSTRG(internal_encoding_name); _php_mb_ini_mbstring_internal_encoding_set(value, value ? strlen(value): 0 TSRMLS_CC); } if (!MBSTRG(encoding_translation)) { php_default_treat_data(arg, str, destArray TSRMLS_CC); return; } switch (arg) { case PARSE_POST: case PARSE_GET: case PARSE_COOKIE: ALLOC_ZVAL(array_ptr); array_init(array_ptr); INIT_PZVAL(array_ptr); switch (arg) { case PARSE_POST: PG(http_globals)[TRACK_VARS_POST] = array_ptr; break; case PARSE_GET: PG(http_globals)[TRACK_VARS_GET] = array_ptr; break; case PARSE_COOKIE: PG(http_globals)[TRACK_VARS_COOKIE] = array_ptr; break; } break; default: array_ptr=destArray; break; } if (arg==PARSE_POST) { sapi_handle_post(array_ptr TSRMLS_CC); return; } if (arg == PARSE_GET) { /* GET data */ c_var = SG(request_info).query_string; if (c_var && *c_var) { res = (char *) estrdup(c_var); free_buffer = 1; } else { free_buffer = 0; } } else if (arg == PARSE_COOKIE) { /* Cookie data */ c_var = SG(request_info).cookie_data; if (c_var && *c_var) { res = (char *) estrdup(c_var); free_buffer = 1; } else { free_buffer = 0; } } else if (arg == PARSE_STRING) { /* String data */ res = str; free_buffer = 1; } if (!res) { return; } switch (arg) { case PARSE_POST: case PARSE_GET: case PARSE_STRING: separator = (char *) estrdup(PG(arg_separator).input); break; case PARSE_COOKIE: separator = ";\0"; break; } switch(arg) { case PARSE_POST: MBSTRG(http_input_identify_post) = NULL; break; case PARSE_GET: MBSTRG(http_input_identify_get) = NULL; break; case PARSE_COOKIE: MBSTRG(http_input_identify_cookie) = NULL; break; case PARSE_STRING: MBSTRG(http_input_identify_string) = NULL; break; } info.data_type = arg; info.separator = separator; info.report_errors = 0; info.to_encoding = MBSTRG(internal_encoding); info.to_language = MBSTRG(language); info.from_encodings = MBSTRG(http_input_list); info.num_from_encodings = MBSTRG(http_input_list_size); info.from_language = MBSTRG(language); MBSTRG(illegalchars) = 0; detected = _php_mb_encoding_handler_ex(&info, array_ptr, res TSRMLS_CC); MBSTRG(http_input_identify) = detected; if (detected) { switch(arg){ case PARSE_POST: MBSTRG(http_input_identify_post) = detected; break; case PARSE_GET: MBSTRG(http_input_identify_get) = detected; break; case PARSE_COOKIE: MBSTRG(http_input_identify_cookie) = detected; break; case PARSE_STRING: MBSTRG(http_input_identify_string) = detected; break; } } if (arg != PARSE_COOKIE) { efree(separator); } if (free_buffer) { efree(res); } }
SAPI_API void sapi_activate_headers_only(void) { if (SG(request_info).headers_read == 1) return; SG(request_info).headers_read = 1; zend_llist_init(&SG(sapi_headers).headers, sizeof(sapi_header_struct), (void (*)(void *)) sapi_free_header, 0); SG(sapi_headers).send_default_content_type = 1; /* SG(sapi_headers).http_response_code = 200; */ SG(sapi_headers).http_status_line = NULL; SG(sapi_headers).mimetype = NULL; SG(read_post_bytes) = 0; SG(request_info).request_body = NULL; SG(request_info).current_user = NULL; SG(request_info).current_user_length = 0; SG(request_info).no_headers = 0; SG(request_info).post_entry = NULL; SG(global_request_time) = 0; /* * It's possible to override this general case in the activate() callback, * if necessary. */ if (SG(request_info).request_method && !strcmp(SG(request_info).request_method, "HEAD")) { SG(request_info).headers_only = 1; } else { SG(request_info).headers_only = 0; } if (SG(server_context)) { SG(request_info).cookie_data = sapi_module.read_cookies(); if (sapi_module.activate) { sapi_module.activate(); } } if (sapi_module.input_filter_init ) { sapi_module.input_filter_init(); } }
static void php_ns_request_ctor(void) { char *server; Ns_DString ds; char *root; int index; char *tmp; server = Ns_ConnServer(NSG(conn)); #define safe_strdup(x) ((x)?strdup((x)):NULL) SG(request_info).query_string = safe_strdup(NSG(conn->request->query)); Ns_DStringInit(&ds); Ns_UrlToFile(&ds, server, NSG(conn->request->url)); /* path_translated is the absolute path to the file */ SG(request_info).path_translated = safe_strdup(Ns_DStringValue(&ds)); Ns_DStringFree(&ds); root = Ns_PageRoot(server); SG(request_info).request_uri = strdup(SG(request_info).path_translated + strlen(root)); SG(request_info).request_method = NSG(conn)->request->method; if(NSG(conn)->request->version > 1.0) SG(request_info).proto_num = 1001; else SG(request_info).proto_num = 1000; SG(request_info).content_length = Ns_ConnContentLength(NSG(conn)); index = Ns_SetIFind(NSG(conn)->headers, "content-type"); SG(request_info).content_type = index == -1 ? NULL : Ns_SetValue(NSG(conn)->headers, index); SG(sapi_headers).http_response_code = 200; tmp = Ns_ConnAuthUser(NSG(conn)); if (tmp) tmp = estrdup(tmp); SG(request_info).auth_user = tmp; tmp = Ns_ConnAuthPasswd(NSG(conn)); if (tmp) tmp = estrdup(tmp); SG(request_info).auth_password = tmp; NSG(data_avail) = SG(request_info).content_length; }
SAPI_API void sapi_deactivate(void) { zend_llist_destroy(&SG(sapi_headers).headers); if (SG(request_info).request_body) { SG(request_info).request_body = NULL; } else if (SG(server_context)) { if (!SG(post_read)) { /* make sure we've consumed all request input data */ char dummy[SAPI_POST_BLOCK_SIZE]; size_t read_bytes; do { read_bytes = sapi_read_post_block(dummy, SAPI_POST_BLOCK_SIZE); } while (SAPI_POST_BLOCK_SIZE == read_bytes); } } if (SG(request_info).auth_user) { efree(SG(request_info).auth_user); } if (SG(request_info).auth_password) { efree(SG(request_info).auth_password); } if (SG(request_info).auth_digest) { efree(SG(request_info).auth_digest); } if (SG(request_info).content_type_dup) { efree(SG(request_info).content_type_dup); } if (SG(request_info).current_user) { efree(SG(request_info).current_user); } if (sapi_module.deactivate) { sapi_module.deactivate(); } if (SG(rfc1867_uploaded_files)) { destroy_uploaded_files_hash(); } if (SG(sapi_headers).mimetype) { efree(SG(sapi_headers).mimetype); SG(sapi_headers).mimetype = NULL; } sapi_send_headers_free(); SG(sapi_started) = 0; SG(headers_sent) = 0; SG(request_info).headers_read = 0; SG(global_request_time) = 0; }
int main( int argc, char * argv[] ) { int ret; int bindFd; char * php_ini_path = NULL; char * php_bind = NULL; int n; int climode = 0; struct timeval tv_req_begin; struct timeval tv_req_end; int slow_script_msec = 0; char time_buf[40]; #ifdef HAVE_SIGNAL_H #if defined(SIGPIPE) && defined(SIG_IGN) signal(SIGPIPE, SIG_IGN); #endif #endif #ifdef ZTS tsrm_startup(1, 1, 0, NULL); #endif #if PHP_MAJOR_VERSION >= 7 #if defined(ZEND_SIGNALS) || PHP_MINOR_VERSION > 0 zend_signal_startup(); #endif #endif if (argc > 1 ) { if ( parse_opt( argc, argv, &climode, &php_ini_path, &php_bind ) == -1 ) { return 1; } } if ( climode ) { lsapi_sapi_module.phpinfo_as_text = 1; } else { setArgv0(argc, argv ); } sapi_startup(&lsapi_sapi_module); #ifdef ZTS compiler_globals = ts_resource(compiler_globals_id); executor_globals = ts_resource(executor_globals_id); core_globals = ts_resource(core_globals_id); sapi_globals = ts_resource(sapi_globals_id); tsrm_ls = ts_resource(0); SG(request_info).path_translated = NULL; #endif lsapi_sapi_module.executable_location = argv[0]; /* Initialize from environment variables before processing command-line * options: the latter override the former. */ init_sapi_from_env(&lsapi_sapi_module); if ( ignore_php_ini ) lsapi_sapi_module.php_ini_ignore = 1; if ( php_ini_path ) { lsapi_sapi_module.php_ini_path_override = php_ini_path; } lsapi_sapi_module.ini_defaults = sapi_lsapi_ini_defaults; if (php_module_startup(&lsapi_sapi_module, &litespeed_module_entry, 1) == FAILURE) { #ifdef ZTS tsrm_shutdown(); #endif return FAILURE; } if ( climode ) { return cli_main(argc, argv); } if ( php_bind ) { bindFd = LSAPI_CreateListenSock( php_bind, 10 ); if ( bindFd == -1 ) { fprintf( stderr, "Failed to bind socket [%s]: %s\n", php_bind, strerror( errno ) ); exit( 2 ); } if ( bindFd != 0 ) { dup2( bindFd, 0 ); close( bindFd ); } } LSAPI_Init(); #if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__) int is_criu = LSCRIU_Init(); // Must be called before the regular init as it unsets the parameters. #endif LSAPI_Init_Env_Parameters( NULL ); lsapi_mode = 1; slow_script_msec = LSAPI_Get_Slow_Req_Msecs(); if ( php_bind ) { LSAPI_No_Check_ppid(); free( php_bind ); php_bind = NULL; } int result; while( ( result = LSAPI_Prefork_Accept_r( &g_req )) >= 0 ) { #if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__) if (is_criu && !result) { LSCRIU_inc_req_procssed(); } #endif if ( slow_script_msec ) { gettimeofday( &tv_req_begin, NULL ); } ret = processReq(); if ( slow_script_msec ) { gettimeofday( &tv_req_end, NULL ); n = ((long) tv_req_end.tv_sec - tv_req_begin.tv_sec ) * 1000 + (tv_req_end.tv_usec - tv_req_begin.tv_usec) / 1000; if ( n > slow_script_msec ) { strftime( time_buf, 30, "%d/%b/%Y:%H:%M:%S", localtime( &tv_req_end.tv_sec ) ); fprintf( stderr, "[%s] Slow PHP script: %d ms\n URL: %s %s\n Query String: %s\n Script: %s\n", time_buf, n, LSAPI_GetRequestMethod(), LSAPI_GetScriptName(), LSAPI_GetQueryString(), LSAPI_GetScriptFileName() ); } } LSAPI_Finish(); if ( ret ) { break; } } php_module_shutdown(); #ifdef ZTS tsrm_shutdown(); #endif return ret; }
SAPI_API int sapi_send_headers(void) { int retval; int ret = FAILURE; if (SG(headers_sent) || SG(request_info).no_headers) { return SUCCESS; } /* Success-oriented. We set headers_sent to 1 here to avoid an infinite loop * in case of an error situation. */ if (SG(sapi_headers).send_default_content_type && sapi_module.send_headers) { uint32_t len = 0; char *default_mimetype = get_default_content_type(0, &len); if (default_mimetype && len) { sapi_header_struct default_header; SG(sapi_headers).mimetype = default_mimetype; default_header.header_len = sizeof("Content-type: ") - 1 + len; default_header.header = emalloc(default_header.header_len + 1); memcpy(default_header.header, "Content-type: ", sizeof("Content-type: ") - 1); memcpy(default_header.header + sizeof("Content-type: ") - 1, SG(sapi_headers).mimetype, len + 1); sapi_header_add_op(SAPI_HEADER_ADD, &default_header); } else { efree(default_mimetype); } SG(sapi_headers).send_default_content_type = 0; } if (Z_TYPE(SG(callback_func)) != IS_UNDEF) { zval cb; ZVAL_COPY_VALUE(&cb, &SG(callback_func)); ZVAL_UNDEF(&SG(callback_func)); sapi_run_header_callback(&cb); zval_ptr_dtor(&cb); } SG(headers_sent) = 1; if (sapi_module.send_headers) { retval = sapi_module.send_headers(&SG(sapi_headers)); } else { retval = SAPI_HEADER_DO_SEND; } switch (retval) { case SAPI_HEADER_SENT_SUCCESSFULLY: ret = SUCCESS; break; case SAPI_HEADER_DO_SEND: { sapi_header_struct http_status_line; char buf[255]; if (SG(sapi_headers).http_status_line) { http_status_line.header = SG(sapi_headers).http_status_line; http_status_line.header_len = (uint32_t)strlen(SG(sapi_headers).http_status_line); } else { http_status_line.header = buf; http_status_line.header_len = slprintf(buf, sizeof(buf), "HTTP/1.0 %d X", SG(sapi_headers).http_response_code); } sapi_module.send_header(&http_status_line, SG(server_context)); } zend_llist_apply_with_argument(&SG(sapi_headers).headers, (llist_apply_with_arg_func_t) sapi_module.send_header, SG(server_context)); if(SG(sapi_headers).send_default_content_type) { sapi_header_struct default_header; sapi_get_default_content_type_header(&default_header); sapi_module.send_header(&default_header, SG(server_context)); sapi_free_header(&default_header); } sapi_module.send_header(NULL, SG(server_context)); ret = SUCCESS; break; case SAPI_HEADER_SEND_FAILED: SG(headers_sent) = 0; ret = FAILURE; break; } sapi_send_headers_free(); return ret; }
static int cli_main( int argc, char * argv[] ) { static const char * ini_defaults[] = { "report_zend_debug", "0", "display_errors", "1", "register_argc_argv", "1", "html_errors", "0", "implicit_flush", "1", "output_buffering", "0", "max_execution_time", "0", "max_input_time", "-1", NULL }; const char ** ini; char ** p = &argv[1]; char ** argend= &argv[argc]; int ret = -1; int c; zend_string *psKey; lsapi_mode = 0; /* enter CLI mode */ #ifdef PHP_WIN32 _fmode = _O_BINARY; /*sets default for file streams to binary */ setmode(_fileno(stdin), O_BINARY); /* make the stdio mode be binary */ setmode(_fileno(stdout), O_BINARY); /* make the stdio mode be binary */ setmode(_fileno(stderr), O_BINARY); /* make the stdio mode be binary */ #endif zend_first_try { SG(server_context) = (void *) 1; zend_uv.html_errors = 0; /* tell the engine we're in non-html mode */ CG(in_compilation) = 0; /* not initialized but needed for several options */ SG(options) |= SAPI_OPTION_NO_CHDIR; #if PHP_MAJOR_VERSION < 7 EG(uninitialized_zval_ptr) = NULL; #endif for( ini = ini_defaults; *ini; ini+=2 ) { psKey = zend_string_init(*ini, strlen( *ini ), 1); zend_alter_ini_entry_chars(psKey, (char *)*(ini+1), strlen( *(ini+1) ), PHP_INI_SYSTEM, PHP_INI_STAGE_ACTIVATE); zend_string_release(psKey); } while (( p < argend )&&(**p == '-' )) { c = *((*p)+1); ++p; switch( c ) { case 'q': break; case 'i': if (php_request_startup() != FAILURE) { php_print_info(0xFFFFFFFF); #ifdef PHP_OUTPUT_NEWAPI php_output_end_all(); #else php_end_ob_buffers(1); #endif php_request_shutdown( NULL ); ret = 0; } break; case 'v': if (php_request_startup() != FAILURE) { #if ZEND_DEBUG php_printf("PHP %s (%s) (built: %s %s) (DEBUG)\nCopyright (c) 1997-2018 The PHP Group\n%s", PHP_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version()); #else php_printf("PHP %s (%s) (built: %s %s)\nCopyright (c) 1997-2018 The PHP Group\n%s", PHP_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version()); #endif #ifdef PHP_OUTPUT_NEWAPI php_output_end_all(); #else php_end_ob_buffers(1); #endif php_request_shutdown( NULL ); ret = 0; } break; case 'c': ++p; /* fall through */ case 's': break; case 'l': source_highlight = 2; break; case 'h': case '?': default: cli_usage(); ret = 0; break; } } if ( ret == -1 ) { if ( *p ) { zend_file_handle file_handle; memset(&file_handle, 0, sizeof(file_handle)); file_handle.type = ZEND_HANDLE_FP; file_handle.handle.fp = VCWD_FOPEN(*p, "rb"); if ( file_handle.handle.fp ) { script_filename = *p; php_self = *p; SG(request_info).path_translated = estrdup(*p); SG(request_info).argc = argc - (p - argv); SG(request_info).argv = p; if (php_request_startup() == FAILURE ) { fclose( file_handle.handle.fp ); ret = 2; } else { if (source_highlight == 1) { zend_syntax_highlighter_ini syntax_highlighter_ini; php_get_highlight_struct(&syntax_highlighter_ini); highlight_file(SG(request_info).path_translated, &syntax_highlighter_ini); } else if (source_highlight == 2) { file_handle.filename = *p; file_handle.free_filename = 0; file_handle.opened_path = NULL; ret = php_lint_script(&file_handle); if (ret==SUCCESS) { zend_printf("No syntax errors detected in %s\n", file_handle.filename); } else { zend_printf("Errors parsing %s\n", file_handle.filename); } } else { file_handle.filename = *p; file_handle.free_filename = 0; file_handle.opened_path = NULL; php_execute_script(&file_handle); ret = EG(exit_status); } php_request_shutdown( NULL ); } } else { php_printf("Could not open input file: %s.\n", *p); } } else { cli_usage(); } } }zend_end_try(); php_module_shutdown(); #ifdef ZTS tsrm_shutdown(); #endif return ret; }
/* {{{ sapi_apache_read_cookies */ static char *sapi_apache_read_cookies(TSRMLS_D) { return (char *) table_get(((request_rec *) SG(server_context))->subprocess_env, "HTTP_COOKIE"); }
static void php_info_print_request_uri(TSRMLS_D) /* {{{ */ { if (SG(request_info).request_uri) { php_info_print_html_esc(SG(request_info).request_uri, strlen(SG(request_info).request_uri)); } }