char *php_http_url_authority_to_string(const php_http_url_t *url, char **url_str, size_t *url_len) { php_http_buffer_t buf; php_http_buffer_init(&buf); if (url->user && *url->user) { php_http_buffer_appendl(&buf, url->user); if (url->pass && *url->pass) { php_http_buffer_appends(&buf, ":"); php_http_buffer_appendl(&buf, url->pass); } php_http_buffer_appends(&buf, "@"); } if (url->host && *url->host) { php_http_buffer_appendl(&buf, url->host); if (url->port) { php_http_buffer_appendf(&buf, ":%hu", url->port); } } php_http_buffer_shrink(&buf); php_http_buffer_fix(&buf); if (url_len) { *url_len = buf.used; } if (url_str) { *url_str = buf.data; } return buf.data; }
static PHP_HTTP_FILTER_FUNCTION(chunked_decode) { int out_avail = 0; php_stream_bucket *ptr, *nxt; PHP_HTTP_FILTER_BUFFER(chunked_decode) *buffer = Z_PTR(this->abstract); if (bytes_consumed) { *bytes_consumed = 0; } /* fetch available bucket data */ for (ptr = buckets_in->head; ptr; ptr = nxt) { if (bytes_consumed) { *bytes_consumed += ptr->buflen; } if (PHP_HTTP_BUFFER_NOMEM == php_http_buffer_append(PHP_HTTP_BUFFER(buffer), ptr->buf, ptr->buflen)) { return PSFS_ERR_FATAL; } nxt = ptr->next; php_stream_bucket_unlink(ptr); php_stream_bucket_delref(ptr); } if (!php_http_buffer_fix(PHP_HTTP_BUFFER(buffer))) { return PSFS_ERR_FATAL; } /* we have data in our buffer */ while (PHP_HTTP_BUFFER(buffer)->used) { /* we already know the size of the chunk and are waiting for data */ if (buffer->hexlen) { /* not enough data buffered */ if (PHP_HTTP_BUFFER(buffer)->used < buffer->hexlen) { /* flush anyway? */ if (flags & PSFS_FLAG_FLUSH_INC) { /* flush all data (should only be chunk data) */ out_avail = 1; NEW_BUCKET(PHP_HTTP_BUFFER(buffer)->data, PHP_HTTP_BUFFER(buffer)->used); /* waiting for less data now */ buffer->hexlen -= PHP_HTTP_BUFFER(buffer)->used; /* no more buffered data */ php_http_buffer_reset(PHP_HTTP_BUFFER(buffer)); /* break */ } /* we have too less data and don't need to flush */ else { break; } } /* we seem to have all data of the chunk */ else { out_avail = 1; NEW_BUCKET(PHP_HTTP_BUFFER(buffer)->data, buffer->hexlen); /* remove outgoing data from the buffer */ php_http_buffer_cut(PHP_HTTP_BUFFER(buffer), 0, buffer->hexlen); /* reset hexlen */ buffer->hexlen = 0; /* continue */ } } /* we don't know the length of the chunk yet */ else { size_t off = 0; /* ignore preceeding CRLFs (too loose?) */ while (off < PHP_HTTP_BUFFER(buffer)->used && ( PHP_HTTP_BUFFER(buffer)->data[off] == '\n' || PHP_HTTP_BUFFER(buffer)->data[off] == '\r')) { ++off; } if (off) { php_http_buffer_cut(PHP_HTTP_BUFFER(buffer), 0, off); } /* still data there? */ if (PHP_HTTP_BUFFER(buffer)->used) { int eollen; const char *eolstr; /* we need eol, so we can be sure we have all hex digits */ php_http_buffer_fix(PHP_HTTP_BUFFER(buffer)); if ((eolstr = php_http_locate_bin_eol(PHP_HTTP_BUFFER(buffer)->data, PHP_HTTP_BUFFER(buffer)->used, &eollen))) { char *stop = NULL; /* read in chunk size */ buffer->hexlen = strtoul(PHP_HTTP_BUFFER(buffer)->data, &stop, 16); /* if strtoul() stops at the beginning of the buffered data there's something oddly wrong, i.e. bad input */ if (stop == PHP_HTTP_BUFFER(buffer)->data) { return PSFS_ERR_FATAL; } /* cut out <chunk size hex><chunk extension><eol> */ php_http_buffer_cut(PHP_HTTP_BUFFER(buffer), 0, eolstr + eollen - PHP_HTTP_BUFFER(buffer)->data); /* buffer->hexlen is 0 now or contains the size of the next chunk */ if (!buffer->hexlen) { php_stream_notify_info(PHP_STREAM_CONTEXT(stream), PHP_STREAM_NOTIFY_COMPLETED, NULL, 0); break; } /* continue */ } else { /* we have not enough data buffered to read in chunk size */ break; } } /* break */ } } /* flush before close, but only if we are already waiting for more data */ if (PHP_HTTP_FILTER_IS_CLOSING(stream, flags) && buffer->hexlen && PHP_HTTP_BUFFER(buffer)->used) { out_avail = 1; NEW_BUCKET(PHP_HTTP_BUFFER(buffer)->data, PHP_HTTP_BUFFER(buffer)->used); php_http_buffer_reset(PHP_HTTP_BUFFER(buffer)); buffer->hexlen = 0; } return out_avail ? PSFS_PASS_ON : PSFS_FEED_ME; }
char *php_http_url_to_string(const php_http_url_t *url, char **url_str, size_t *url_len, zend_bool persistent) { php_http_buffer_t buf; php_http_buffer_init_ex(&buf, PHP_HTTP_BUFFER_DEFAULT_SIZE, persistent ? PHP_HTTP_BUFFER_INIT_PERSISTENT : 0); if (url->scheme && *url->scheme) { php_http_buffer_appendl(&buf, url->scheme); php_http_buffer_appends(&buf, "://"); } else if ((url->user && *url->user) || (url->host && *url->host)) { php_http_buffer_appends(&buf, "//"); } if (url->user && *url->user) { php_http_buffer_appendl(&buf, url->user); if (url->pass && *url->pass) { php_http_buffer_appends(&buf, ":"); php_http_buffer_appendl(&buf, url->pass); } php_http_buffer_appends(&buf, "@"); } if (url->host && *url->host) { php_http_buffer_appendl(&buf, url->host); if (url->port) { php_http_buffer_appendf(&buf, ":%hu", url->port); } } if (url->path && *url->path) { if (*url->path != '/') { php_http_buffer_appends(&buf, "/"); } php_http_buffer_appendl(&buf, url->path); } else if (buf.used) { php_http_buffer_appends(&buf, "/"); } if (url->query && *url->query) { php_http_buffer_appends(&buf, "?"); php_http_buffer_appendl(&buf, url->query); } if (url->fragment && *url->fragment) { php_http_buffer_appends(&buf, "#"); php_http_buffer_appendl(&buf, url->fragment); } php_http_buffer_shrink(&buf); php_http_buffer_fix(&buf); if (url_len) { *url_len = buf.used; } if (url_str) { *url_str = buf.data; } return buf.data; }