- 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 *, char *) */
-PHP_HTTP_API char *_http_absolute_uri(const char *url,
- const char *proto TSRMLS_DC)
-{
- char *proto_ptr, *host, *path, *PTR, *URI = ecalloc(1, HTTP_URI_MAXLEN + 1);
- zval *zhost;
-
- if (!url || !strlen(url)) {
- if (!SG(request_info).request_uri) {
- return NULL;
- }
- url = SG(request_info).request_uri;
- }
- /* Mess around with already absolute URIs */
- else if (proto_ptr = strstr(url, "://")) {
- if (!proto || !strncmp(url, proto, strlen(proto))) {
- strncpy(URI, url, HTTP_URI_MAXLEN);
- return URI;
- } else {
- snprintf(URI, HTTP_URI_MAXLEN, "%s%s", proto, proto_ptr + 3);
- return URI;
- }
- }
-
- /* protocol defaults to http */
- if (!proto || !strlen(proto)) {
- proto = "http";
- }
-
- /* get host name */
- if ( (zhost = http_get_server_var("HTTP_HOST")) ||
- (zhost = http_get_server_var("SERVER_NAME"))) {
- host = Z_STRVAL_P(zhost);
- } else {
- host = "localhost";
- }
-
-
- /* glue together */
- if (url[0] == '/') {
- snprintf(URI, HTTP_URI_MAXLEN, "%s://%s%s", proto, host, url);
- } else if (SG(request_info).request_uri) {
- path = estrdup(SG(request_info).request_uri);
- php_dirname(path, strlen(path));
- snprintf(URI, HTTP_URI_MAXLEN, "%s://%s%s/%s", proto, host, path, url);
- efree(path);
- } else {
- snprintf(URI, HTTP_URI_MAXLEN, "%s://%s/%s", proto, host, url);
- }
-
- /* strip everything after a new line */
- if ((PTR = strchr(URI, '\r')) || (PTR = strchr(URI, '\n'))) {
- PTR = 0;
- }
-
- return URI;
-}
-/* }}} */
-
-/* {{{ char *http_negotiate_q(char *, zval *, char *, hash_entry_type) */
-PHP_HTTP_API char *_http_negotiate_q(const char *entry, const zval *supported,
- const char *def TSRMLS_DC)
-{
- zval *zaccept, *zarray, *zdelim, **zentry, *zentries, **zsupp;
- char *q_ptr, *result;
- int i, c;
- double qual;
-
- HTTP_GSC(zaccept, entry, estrdup(def));
-
- MAKE_STD_ZVAL(zarray);
- array_init(zarray);
-
- MAKE_STD_ZVAL(zdelim);
- ZVAL_STRING(zdelim, ",", 0);
- php_explode(zdelim, zaccept, zarray, -1);
- efree(zdelim);
-
- MAKE_STD_ZVAL(zentries);
- array_init(zentries);
-
- c = zend_hash_num_elements(Z_ARRVAL_P(zarray));
- for (i = 0; i < c; i++, zend_hash_move_forward(Z_ARRVAL_P(zarray))) {
-
- if (SUCCESS != zend_hash_get_current_data(
- Z_ARRVAL_P(zarray), (void **) &zentry)) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING,
- "Cannot parse %s header: %s", entry, Z_STRVAL_P(zaccept));
- break;
- }
-
- /* check for qualifier */
- if (NULL != (q_ptr = strrchr(Z_STRVAL_PP(zentry), ';'))) {
- qual = strtod(q_ptr + 3, NULL);
- } else {
- qual = 1000.0 - i;
- }
-
- /* walk through the supported array */
- FOREACH_VAL(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);
- efree(zarray);
-
- zend_hash_internal_pointer_reset(Z_ARRVAL_P(zentries));
-
- if ( (SUCCESS != zend_hash_sort(Z_ARRVAL_P(zentries), zend_qsort,
- http_sort_q, 0 TSRMLS_CC)) ||
- (HASH_KEY_NON_EXISTANT == zend_hash_get_current_key(
- Z_ARRVAL_P(zentries), &result, 0, 1))) {
- result = estrdup(def);
- }
-
- zval_dtor(zentries);
- efree(zentries);
-
- return result;
-}
-/* }}} */
-
-/* {{{ http_range_status http_get_request_ranges(HashTable *ranges, size_t) */
-PHP_HTTP_API http_range_status _http_get_request_ranges(HashTable *ranges,
- const size_t length TSRMLS_DC)
-{
- zval *zrange;
- char *range, c;
- long begin = -1, end = -1, *ptr;
-
- HTTP_GSC(zrange, "HTTP_RANGE", RANGE_NO);
- range = Z_STRVAL_P(zrange);
-
- if (strncmp(range, "bytes=", sizeof("bytes=") - 1)) {
- php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Range header misses bytes=");
- return RANGE_NO;
- }
-
- ptr = &begin;
- range += sizeof("bytes=") - 1;
-
- do {
- switch (c = *(range++))
- {
- case '0':
- *ptr *= 10;
- break;
-
- case '1': case '2': case '3':
- case '4': case '5': case '6':
- case '7': case '8': case '9':
- /*
- * If the value of the pointer is already set (non-negative)
- * then multiply its value by ten and add the current value,
- * else initialise the pointers value with the current value
- * --
- * This let us recognize empty fields when validating the
- * ranges, i.e. a "-10" for begin and "12345" for the end
- * was the following range request: "Range: bytes=0-12345";
- * While a "-1" for begin and "12345" for the end would
- * have been: "Range: bytes=-12345".
- */
- if (*ptr > 0) {
- *ptr *= 10;
- *ptr += c - '0';