Esempio n. 1
0
static char * __cvt(double value, int ndigit, int *decpt, int *sign, int fmode, int pad) /* {{{ */
{
  register char *s = NULL;
  char *p, *rve, c;
  size_t siz;

  if (ndigit < 0) {
    siz = -ndigit + 1;
  } else {
    siz = ndigit + 1;
  }

  /* __dtoa() doesn't allocate space for 0 so we do it by hand */
  if (value == 0.0) {
    *decpt = 1 - fmode; /* 1 for 'e', 0 for 'f' */
    *sign = 0;
    if ((rve = s = (char *)malloc(ndigit?siz:2)) == NULL) {
      return(NULL);
    }
    *rve++ = '0';
    *rve = '\0';
    if (!ndigit) {
      return(s);
    }
  } else {
    p = HPHP::zend_dtoa(value, fmode + 2, ndigit, decpt, sign, &rve);
    if (*decpt == 9999) {
      /* Infinity or Nan, convert to inf or nan like printf */
      *decpt = 0;
      c = *p;
      HPHP::zend_freedtoa(p);
      return strdup((c == 'I' ? "INF" : "NAN"));
    }
    /* Make a local copy and adjust rve to be in terms of s */
    if (pad && fmode) {
      siz += *decpt;
    }
    if ((s = (char *)malloc(siz+1)) == NULL) {
      HPHP::zend_freedtoa(p);
      return(NULL);
    }
    PHP_STRLCPY(s, p, siz, siz);
    rve = s + (rve - p);
    HPHP::zend_freedtoa(p);
  }

  /* Add trailing zeros */
  if (pad) {
    siz -= rve - s;
    while (--siz) {
      *rve++ = '0';
    }
    *rve = '\0';
  }

  return(s);
}
Esempio n. 2
0
/*
 * Add charset on content-type header if the MIME type starts with
 * "text/", the default_charset directive is not empty and
 * there is not already a charset option in there.
 *
 * If "mimetype" is non-NULL, it should point to a pointer allocated
 * with emalloc().  If a charset is added, the string will be
 * re-allocated and the new length is returned.  If mimetype is
 * unchanged, 0 is returned.
 *
 */
SAPI_API size_t sapi_apply_default_charset(char **mimetype, size_t len)
{
	char *charset, *newtype;
	size_t newlen;
	charset = SG(default_charset) ? SG(default_charset) : SAPI_DEFAULT_CHARSET;

	if (*mimetype != NULL) {
		if (*charset && strncmp(*mimetype, "text/", 5) == 0 && strstr(*mimetype, "charset=") == NULL) {
			newlen = len + (sizeof(";charset=")-1) + strlen(charset);
			newtype = emalloc(newlen + 1);
	 		PHP_STRLCPY(newtype, *mimetype, newlen + 1, len);
			strlcat(newtype, ";charset=", newlen + 1);
			strlcat(newtype, charset, newlen + 1);
			efree(*mimetype);
			*mimetype = newtype;
			return newlen;
		}
	}
	return 0;
}
Esempio n. 3
0
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;
}