- if (!strchr(content_type, '/')) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING,
- "Content-Type '%s' doesn't seem to consist of a primary and a secondary part",
- content_type);
- return FAILURE;
- }
-
- /* remember for multiple ranges */
- if (HTTP_G(ctype)) {
- efree(HTTP_G(ctype));
- }
- HTTP_G(ctype) = estrndup(content_type, ct_len);
-
- ct_header = ecalloc(1, sizeof("Content-Type: ") + ct_len);
- sprintf(ct_header, "Content-Type: %s", content_type);
-
- if (SUCCESS != (status = http_send_header(ct_header))) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING,
- "Couldn't send '%s' header", ct_header);
- }
- efree(ct_header);
- return status;
-}
-/* }}} */
-
-/* {{{ STATUS http_send_content_disposition(char *, size_t, zend_bool) */
-PHP_HTTP_API STATUS _http_send_content_disposition(const char *filename,
- const size_t f_len, const int send_inline TSRMLS_DC)
-{
- STATUS status;
- char *cd_header;
-
- if (send_inline) {
- cd_header = ecalloc(1, sizeof("Content-Disposition: inline; filename=\"\"") + f_len);
- sprintf(cd_header, "Content-Disposition: inline; filename=\"%s\"", filename);
- } else {
- cd_header = ecalloc(1, sizeof("Content-Disposition: attachment; filename=\"\"") + f_len);
- sprintf(cd_header, "Content-Disposition: attachment; filename=\"%s\"", filename);
- }
-
- if (SUCCESS != (status = http_send_header(cd_header))) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Couldn't send '%s' header", cd_header);
- }
- efree(cd_header);
- return status;
-}
-/* }}} */
-
-/* {{{ STATUS http_cache_last_modified(time_t, time_t, char *, size_t) */
-PHP_HTTP_API STATUS _http_cache_last_modified(const time_t last_modified,
- const time_t send_modified, const char *cache_control, const size_t cc_len TSRMLS_DC)
-{
- if (cc_len) {
- http_send_cache_control(cache_control, cc_len);
- }
-
- if (http_modified_match("HTTP_IF_MODIFIED_SINCE", last_modified)) {
- if (SUCCESS == http_send_status(304)) {
- zend_bailout();
- } else {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not send 304 Not Modified");
- return FAILURE;
- }
- }
- return http_send_last_modified(send_modified);
-}
-/* }}} */
-
-/* {{{ STATUS http_cache_etag(char *, size_t, char *, size_t) */
-PHP_HTTP_API STATUS _http_cache_etag(const char *etag, const size_t etag_len,
- const char *cache_control, const size_t cc_len TSRMLS_DC)
-{
- if (cc_len) {
- http_send_cache_control(cache_control, cc_len);
- }
-
- if (etag_len) {
- http_send_etag(etag, etag_len);
- if (http_etag_match("HTTP_IF_NONE_MATCH", etag)) {
- if (SUCCESS == http_send_status(304)) {
- zend_bailout();
- } else {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not send 304 Not Modified");
- return FAILURE;
- }
- }
- }
-
- /* if no etag is given and we didn't already start ob_etaghandler -- start it */
- if (!HTTP_G(etag_started)) {
- if (SUCCESS == http_start_ob_handler(_http_ob_etaghandler, "ob_etaghandler", 4096, 1)) {
- HTTP_G(etag_started) = 1;
- return SUCCESS;
- } else {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not start ob_etaghandler");
- return FAILURE;
- }
- }
- return SUCCESS;
-}
-/* }}} */
-
-/* {{{ char *http_absolute_uri(char *) */
-PHP_HTTP_API char *_http_absolute_uri_ex(
- const char *url, size_t url_len,
- const char *proto, size_t proto_len,
- const char *host, size_t host_len,
- unsigned port TSRMLS_DC)
-{
-#if defined(PHP_WIN32) || defined(HAVE_NETDB_H)
- struct servent *se;
-#endif
- php_url *purl, furl = {NULL};
- size_t full_len = 0;
- zval *zhost = NULL;
- char *scheme = NULL, *URL = ecalloc(1, HTTP_URI_MAXLEN + 1);
-
- if ((!url || !url_len) && (
- (!(url = SG(request_info).request_uri)) ||
- (!(url_len = strlen(SG(request_info).request_uri))))) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING,
- "Cannot build an absolute URI if supplied URL and REQUEST_URI is empty");
- return NULL;
- }
-
- if (!(purl = php_url_parse((char *) url))) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not parse supplied URL");
- return NULL;
- }
-
- furl.user = purl->user;
- furl.pass = purl->pass;
- furl.path = purl->path;
- furl.query = purl->query;
- furl.fragment = purl->fragment;
-
- if (proto && proto_len) {
- furl.scheme = scheme = estrdup(proto);
- } else if (purl->scheme) {
- furl.scheme = purl->scheme;
-#if defined(PHP_WIN32) || defined(HAVE_NETDB_H)
- } else if (port && (se = getservbyport(port, "tcp"))) {
- furl.scheme = (scheme = estrdup(se->s_name));
-#endif
- } else {
- furl.scheme = "http";
- }
-
- if (port) {
- furl.port = port;
- } else if (purl->port) {
- furl.port = purl->port;
- } else if (strncmp(furl.scheme, "http", 4)) {
-#if defined(PHP_WIN32) || defined(HAVE_NETDB_H)
- if (se = getservbyname(furl.scheme, "tcp")) {
- furl.port = se->s_port;
- }
-#endif
- } else {
- furl.port = (furl.scheme[4] == 's') ? 443 : 80;
- }
-
- if (host) {
- furl.host = (char *) host;
- } else if (purl->host) {
- furl.host = purl->host;
- } else if ( (zhost = http_get_server_var("HTTP_HOST")) ||
- (zhost = http_get_server_var("SERVER_NAME"))) {
- furl.host = Z_STRVAL_P(zhost);
- } else {
- furl.host = "localhost";
- }
-
-#define HTTP_URI_STRLCATS(URL, full_len, add_string) HTTP_URI_STRLCAT(URL, full_len, add_string, sizeof(add_string)-1)
-#define HTTP_URI_STRLCATL(URL, full_len, add_string) HTTP_URI_STRLCAT(URL, full_len, add_string, strlen(add_string))
-#define HTTP_URI_STRLCAT(URL, full_len, add_string, add_len) \
- if ((full_len += add_len) > HTTP_URI_MAXLEN) { \
- php_error_docref(NULL TSRMLS_CC, E_NOTICE, \
- "Absolute URI would have exceeded max URI length (%d bytes) - " \
- "tried to add %d bytes ('%s')", \
- HTTP_URI_MAXLEN, add_len, add_string); \
- if (scheme) { \
- efree(scheme); \
- } \
- php_url_free(purl); \
- return URL; \
- } else { \
- strcat(URL, add_string); \
- }
-
- HTTP_URI_STRLCATL(URL, full_len, furl.scheme);
- HTTP_URI_STRLCATS(URL, full_len, "://");
-
- if (furl.user) {
- HTTP_URI_STRLCATL(URL, full_len, furl.user);
- if (furl.pass) {
- HTTP_URI_STRLCATS(URL, full_len, ":");
- HTTP_URI_STRLCATL(URL, full_len, furl.pass);
- }
- HTTP_URI_STRLCATS(URL, full_len, "@");
- }
-
- HTTP_URI_STRLCATL(URL, full_len, furl.host);
-
- if ( (!strcmp(furl.scheme, "http") && (furl.port != 80)) ||
- (!strcmp(furl.scheme, "https") && (furl.port != 443))) {
- char port_string[8] = {0};
- snprintf(port_string, 7, ":%u", furl.port);
- HTTP_URI_STRLCATL(URL, full_len, port_string);
- }
-
- if (furl.path) {
- if (furl.path[0] != '/') {
- HTTP_URI_STRLCATS(URL, full_len, "/");
- }
- HTTP_URI_STRLCATL(URL, full_len, furl.path);
- } else {
- HTTP_URI_STRLCATS(URL, full_len, "/");
- }
-
- if (furl.query) {
- HTTP_URI_STRLCATS(URL, full_len, "?");
- HTTP_URI_STRLCATL(URL, full_len, furl.query);
- }
-
- if (furl.fragment) {
- HTTP_URI_STRLCATS(URL, full_len, "#");
- HTTP_URI_STRLCATL(URL, full_len, furl.fragment);
- }
-
- if (scheme) {
- efree(scheme);
- }
- php_url_free(purl);
-
- return URL;
-}
-/* }}} */
-
-/* {{{ char *http_negotiate_q(char *, HashTable *, char *) */
-PHP_HTTP_API char *_http_negotiate_q(const char *entry, const HashTable *supported, const char *def TSRMLS_DC)
-{
- zval *zaccept, zdelim, zarray, zentries, **zentry, **zsupp;
- char *q_ptr = NULL, *key = NULL;
- int i = 0, idx = 0;
- double qual;
-
- HTTP_GSC(zaccept, entry, estrdup(def));
-
- array_init(&zarray);
- array_init(&zentries);
-
- Z_STRVAL(zdelim) = ",";
- Z_STRLEN(zdelim) = 1;
-
- php_explode(&zdelim, zaccept, &zarray, -1);
-
- FOREACH_HASH_VAL(Z_ARRVAL(zarray), zentry) {
- if (q_ptr = strrchr(Z_STRVAL_PP(zentry), ';')) {
- qual = strtod(q_ptr + 3, NULL);
- *q_ptr = 0;
- q_ptr = NULL;
- } else {
- qual = 1000.0 - i++;
- }
- FOREACH_HASH_VAL((HashTable *)supported, zsupp) {
- if (!strcasecmp(Z_STRVAL_PP(zsupp), Z_STRVAL_PP(zentry))) {
- add_assoc_double(&zentries, Z_STRVAL_PP(zsupp), qual);
- break;
- }
- }
- }
- zval_dtor(&zarray);
-
- zend_hash_sort(Z_ARRVAL(zentries), zend_qsort, http_sort_q, 0 TSRMLS_CC);
-
- FOREACH_HASH_KEY(Z_ARRVAL(zentries), key, idx) {
- if (key) {
- return estrdup(key);
- }
- }