summaryrefslogtreecommitdiff
path: root/ext
diff options
context:
space:
mode:
authorWez Furlong <wez@php.net>2003-02-27 17:43:38 +0000
committerWez Furlong <wez@php.net>2003-02-27 17:43:38 +0000
commitfd61f69077f6156ca71dde60ecfd9ed9765a02db (patch)
tree7285ad393cdb5a85107a3329d1ab2bcafe89f051 /ext
parent560e33968de93250377606782949f5004affca83 (diff)
downloadphp-git-fd61f69077f6156ca71dde60ecfd9ed9765a02db.tar.gz
Another big commit (tm).
Main Changes: - Implement a socket transport layer for use by all code that needs to open some kind of "special" socket for network or IPC. - Extensions can register (and override) transports. - Implement ftruncate() on streams via the ioctl-alike option interface. - Implement mmap() on streams via the ioctl-alike option interface. - Implement generic crypto API via the ioctl-alike option interface. (currently only supports OpenSSL, but could support other SSL toolkits, and other crypto transport protocols). Impact: - tcp sockets can be overloaded by the openssl capable sockets at runtime, removing the link-time requirement for ssl:// and https:// sockets and streams. - checking stream types using PHP_STREAM_IS_SOCKET is deprecated, since there are now a range of possible socket-type streams. Working towards: - socket servers using the new transport layer - mmap support under win32 - Cleaner code. # I will be updating the win32 build to add the new files shortly # after this commit.
Diffstat (limited to 'ext')
-rw-r--r--ext/dba/libinifile/inifile.c6
-rw-r--r--ext/openssl/config.m42
-rw-r--r--ext/openssl/openssl.c14
-rw-r--r--ext/openssl/php_openssl.h2
-rw-r--r--ext/openssl/xp_ssl.c498
-rw-r--r--ext/standard/basic_functions.c10
-rw-r--r--ext/standard/file.c17
-rw-r--r--ext/standard/fsock.c218
-rw-r--r--ext/standard/fsock.h4
-rw-r--r--ext/standard/ftp_fopen_wrapper.c16
-rw-r--r--ext/standard/http_fopen_wrapper.c29
11 files changed, 574 insertions, 242 deletions
diff --git a/ext/dba/libinifile/inifile.c b/ext/dba/libinifile/inifile.c
index 2a50c9e884..6e3d94dc4a 100644
--- a/ext/dba/libinifile/inifile.c
+++ b/ext/dba/libinifile/inifile.c
@@ -87,8 +87,8 @@ inifile * inifile_alloc(php_stream *fp, int readonly, int persistent TSRMLS_DC)
int fd = 0;
if (!readonly) {
- if (php_stream_is(fp, PHP_STREAM_IS_SOCKET)) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Can't truncate sockets");
+ if (!php_stream_truncate_supported(fp)) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Can't truncate this stream");
return NULL;
}
if (SUCCESS != php_stream_cast(fp, PHP_STREAM_AS_FD, (void*)&fd, 1)) {
@@ -320,7 +320,7 @@ static int inifile_truncate(inifile *dba, size_t size TSRMLS_DC)
{
int res;
- if ((res=ftruncate(dba->fd, size)) != 0) {
+ if ((res=php_stream_truncate_set_size(dba->fp, size)) != 0) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error in ftruncate: %d", res);
return FAILURE;
}
diff --git a/ext/openssl/config.m4 b/ext/openssl/config.m4
index 93c5d052fd..6cc9568428 100644
--- a/ext/openssl/config.m4
+++ b/ext/openssl/config.m4
@@ -3,7 +3,7 @@ dnl $Id$
dnl
if test "$PHP_OPENSSL" != "no"; then
- PHP_NEW_EXTENSION(openssl, openssl.c, $ext_openssl_shared)
+ PHP_NEW_EXTENSION(openssl, openssl.c xp_ssl.c, $ext_openssl_shared)
OPENSSL_SHARED_LIBADD="-lcrypto -lssl"
PHP_SUBST(OPENSSL_SHARED_LIBADD)
AC_DEFINE(HAVE_OPENSSL_EXT,1,[ ])
diff --git a/ext/openssl/openssl.c b/ext/openssl/openssl.c
index 976023e329..7fc9da3f5d 100644
--- a/ext/openssl/openssl.c
+++ b/ext/openssl/openssl.c
@@ -608,6 +608,13 @@ PHP_MINIT_FUNCTION(openssl)
} else {
strlcpy(default_ssl_conf_filename, config_filename, sizeof(default_ssl_conf_filename));
}
+
+ php_stream_xport_register("ssl", php_openssl_ssl_socket_factory TSRMLS_CC);
+ php_stream_xport_register("tls", php_openssl_ssl_socket_factory TSRMLS_CC);
+
+ /* override the default tcp socket provider */
+ php_stream_xport_register("tcp", php_openssl_ssl_socket_factory TSRMLS_CC);
+
return SUCCESS;
}
/* }}} */
@@ -628,6 +635,13 @@ PHP_MINFO_FUNCTION(openssl)
PHP_MSHUTDOWN_FUNCTION(openssl)
{
EVP_cleanup();
+
+ php_stream_xport_unregister("ssl" TSRMLS_CC);
+ php_stream_xport_unregister("tls" TSRMLS_CC);
+
+ /* reinstate the default tcp handler */
+ php_stream_xport_register("tcp", php_stream_generic_socket_factory TSRMLS_CC);
+
return SUCCESS;
}
/* }}} */
diff --git a/ext/openssl/php_openssl.h b/ext/openssl/php_openssl.h
index 89da3167e1..2c7dde6bb6 100644
--- a/ext/openssl/php_openssl.h
+++ b/ext/openssl/php_openssl.h
@@ -26,6 +26,8 @@
extern zend_module_entry openssl_module_entry;
#define phpext_openssl_ptr &openssl_module_entry
+php_stream_transport_factory_func php_openssl_ssl_socket_factory;
+
PHP_MINIT_FUNCTION(openssl);
PHP_MSHUTDOWN_FUNCTION(openssl);
PHP_MINFO_FUNCTION(openssl);
diff --git a/ext/openssl/xp_ssl.c b/ext/openssl/xp_ssl.c
new file mode 100644
index 0000000000..eb449274d9
--- /dev/null
+++ b/ext/openssl/xp_ssl.c
@@ -0,0 +1,498 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 4 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997-2003 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 2.02 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available at through the world-wide-web at |
+ | http://www.php.net/license/2_02.txt. |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Author: Wez Furlong <wez@thebrainroom.com> |
+ +----------------------------------------------------------------------+
+*/
+
+/* $Id$ */
+
+#include "php.h"
+#include "ext/standard/file.h"
+#include "streams/php_streams_int.h"
+#include "php_network.h"
+#include "php_openssl.h"
+#include <openssl/err.h>
+
+
+/* This implementation is very closely tied to the that of the native
+ * sockets implemented in the core.
+ * Don't try this technique in other extensions!
+ * */
+
+typedef struct _php_openssl_netstream_data_t {
+ php_netstream_data_t s;
+ SSL *ssl_handle;
+ int enable_on_connect;
+ int is_client;
+ int ssl_active;
+ php_stream_xport_crypt_method_t method;
+} php_openssl_netstream_data_t;
+
+php_stream_ops php_openssl_socket_ops;
+
+static int handle_ssl_error(php_stream *stream, int nr_bytes TSRMLS_DC)
+{
+ php_openssl_netstream_data_t *sslsock = (php_openssl_netstream_data_t*)stream->abstract;
+ int err = SSL_get_error(sslsock->ssl_handle, nr_bytes);
+ char esbuf[512];
+ char *ebuf = NULL, *wptr = NULL;
+ size_t ebuf_size = 0;
+ unsigned long code;
+ int retry = 1;
+
+ switch(err) {
+ case SSL_ERROR_ZERO_RETURN:
+ /* SSL terminated (but socket may still be active) */
+ retry = 0;
+ break;
+ case SSL_ERROR_WANT_READ:
+ case SSL_ERROR_WANT_WRITE:
+ /* re-negotiation, or perhaps the SSL layer needs more
+ * packets: retry in next iteration */
+ break;
+ case SSL_ERROR_SYSCALL:
+ if (ERR_peek_error() == 0) {
+ if (nr_bytes == 0) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING,
+ "SSL: fatal protocol error");
+ stream->eof = 1;
+ retry = 0;
+ } else {
+ char *estr = php_socket_strerror(php_socket_errno(), NULL, 0);
+
+ php_error_docref(NULL TSRMLS_CC, E_WARNING,
+ "SSL: %s", estr);
+
+ efree(estr);
+ retry = 0;
+ }
+ break;
+ }
+ /* fall through */
+ default:
+ /* some other error */
+ while ((code = ERR_get_error()) != 0) {
+ /* allow room for a NUL and an optional \n */
+ if (ebuf) {
+ esbuf[0] = '\n';
+ esbuf[1] = '\0';
+ ERR_error_string_n(code, esbuf + 1, sizeof(esbuf) - 2);
+ } else {
+ esbuf[0] = '\0';
+ ERR_error_string_n(code, esbuf, sizeof(esbuf) - 1);
+ }
+ code = strlen(esbuf);
+ esbuf[code] = '\0';
+
+ ebuf = erealloc(ebuf, ebuf_size + code + 1);
+ if (wptr == NULL) {
+ wptr = ebuf;
+ }
+
+ /* also copies the NUL */
+ memcpy(wptr, esbuf, code + 1);
+ wptr += code;
+ }
+
+ php_error_docref(NULL TSRMLS_CC, E_WARNING,
+ "SSL operation failed with code %d.%s%s",
+ err,
+ ebuf ? "OpenSSL Error messages:\n" : "",
+ ebuf ? ebuf : "");
+
+ retry = 0;
+ }
+ return retry;
+}
+
+
+static size_t php_openssl_sockop_write(php_stream *stream, const char *buf, size_t count TSRMLS_DC)
+{
+ php_openssl_netstream_data_t *sslsock = (php_openssl_netstream_data_t*)stream->abstract;
+ size_t didwrite;
+
+ if (sslsock->ssl_active) {
+ int retry = 1;
+
+ do {
+ didwrite = SSL_write(sslsock->ssl_handle, buf, count);
+
+ if (didwrite <= 0) {
+ retry = handle_ssl_error(stream, didwrite TSRMLS_CC);
+ } else {
+ break;
+ }
+ } while(retry);
+
+ } else {
+ didwrite = php_stream_socket_ops.write(stream, buf, count TSRMLS_CC);
+ }
+
+ if (didwrite > 0)
+ php_stream_notify_progress_increment(stream->context, didwrite, 0);
+
+ return didwrite;
+}
+
+static size_t php_openssl_sockop_read(php_stream *stream, char *buf, size_t count TSRMLS_DC)
+{
+ php_openssl_netstream_data_t *sslsock = (php_openssl_netstream_data_t*)stream->abstract;
+ int nr_bytes = 0;
+
+ if (sslsock->ssl_active) {
+ int retry = 1;
+
+ do {
+ nr_bytes = SSL_read(sslsock->ssl_handle, buf, count);
+
+ if (nr_bytes <= 0) {
+ retry = handle_ssl_error(stream, nr_bytes TSRMLS_CC);
+ if (retry == 0 && !SSL_pending(sslsock->ssl_handle)) {
+ stream->eof = 1;
+ }
+ } else {
+ /* we got the data */
+ break;
+ }
+ } while (retry);
+ }
+ else
+ {
+ nr_bytes = php_stream_socket_ops.read(stream, buf, count TSRMLS_CC);
+ }
+
+ if (nr_bytes > 0)
+ php_stream_notify_progress_increment(stream->context, nr_bytes, 0);
+
+ return nr_bytes;
+}
+
+
+static int php_openssl_sockop_close(php_stream *stream, int close_handle TSRMLS_DC)
+{
+ php_openssl_netstream_data_t *sslsock = (php_openssl_netstream_data_t*)stream->abstract;
+ fd_set wrfds, efds;
+ int n;
+ struct timeval timeout;
+
+ if (close_handle) {
+ if (sslsock->ssl_active) {
+ SSL_shutdown(sslsock->ssl_handle);
+ sslsock->ssl_active = 0;
+ }
+ if (sslsock->ssl_handle) {
+ SSL_free(sslsock->ssl_handle);
+ sslsock->ssl_handle = NULL;
+ }
+ if (sslsock->s.socket != -1) {
+ /* prevent more data from coming in */
+ shutdown(sslsock->s.socket, SHUT_RD);
+
+ /* try to make sure that the OS sends all data before we close the connection.
+ * Essentially, we are waiting for the socket to become writeable, which means
+ * that all pending data has been sent.
+ * We use a small timeout which should encourage the OS to send the data,
+ * but at the same time avoid hanging indefintely.
+ * */
+ do {
+ FD_ZERO(&wrfds);
+ FD_SET(sslsock->s.socket, &wrfds);
+ efds = wrfds;
+
+ timeout.tv_sec = 0;
+ timeout.tv_usec = 5000; /* arbitrary */
+
+ n = select(sslsock->s.socket + 1, NULL, &wrfds, &efds, &timeout);
+ } while (n == -1 && php_socket_errno() == EINTR);
+
+ closesocket(sslsock->s.socket);
+ sslsock->s.socket = -1;
+ }
+ }
+
+ pefree(sslsock, php_stream_is_persistent(stream));
+
+ return 0;
+}
+
+static int php_openssl_sockop_flush(php_stream *stream TSRMLS_DC)
+{
+ return php_stream_socket_ops.flush(stream TSRMLS_CC);
+}
+
+static int php_openssl_sockop_stat(php_stream *stream, php_stream_statbuf *ssb TSRMLS_DC)
+{
+ return php_stream_socket_ops.stat(stream, ssb TSRMLS_CC);
+}
+
+static inline int php_openssl_setup_crypto(php_stream *stream,
+ php_openssl_netstream_data_t *sslsock,
+ php_stream_xport_crypto_param *cparam
+ TSRMLS_DC)
+{
+ SSL_CTX *ctx;
+ SSL_METHOD *method;
+
+ if (sslsock->ssl_handle) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "SSL/TLS already set-up for this stream");
+ return -1;
+ }
+
+ /* need to do slightly different things, based on client/server method,
+ * so lets remember which method was selected */
+
+ switch (cparam->inputs.method) {
+ case STREAM_CRYPTO_METHOD_SSLv23_CLIENT:
+ sslsock->is_client = 1;
+ method = SSLv23_client_method();
+ break;
+ case STREAM_CRYPTO_METHOD_SSLv2_CLIENT:
+ sslsock->is_client = 1;
+ method = SSLv2_client_method();
+ break;
+ case STREAM_CRYPTO_METHOD_SSLv3_CLIENT:
+ sslsock->is_client = 1;
+ method = SSLv3_client_method();
+ break;
+ case STREAM_CRYPTO_METHOD_TLS_CLIENT:
+ sslsock->is_client = 1;
+ method = TLSv1_client_method();
+ break;
+ case STREAM_CRYPTO_METHOD_SSLv23_SERVER:
+ sslsock->is_client = 0;
+ method = SSLv23_server_method();
+ break;
+ case STREAM_CRYPTO_METHOD_SSLv3_SERVER:
+ sslsock->is_client = 0;
+ method = SSLv3_server_method();
+ break;
+ case STREAM_CRYPTO_METHOD_SSLv2_SERVER:
+ sslsock->is_client = 0;
+ method = SSLv2_server_method();
+ break;
+ case STREAM_CRYPTO_METHOD_TLS_SERVER:
+ sslsock->is_client = 0;
+ method = TLSv1_server_method();
+ break;
+ default:
+ printf("unknown method\n");
+ return -1;
+
+ }
+
+ ctx = SSL_CTX_new(method);
+ if (ctx == NULL) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "failed to create an SSL context");
+ return -1;
+ }
+
+ sslsock->ssl_handle = SSL_new(ctx);
+ if (sslsock->ssl_handle == NULL) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "failed to create an SSL handle");
+ SSL_CTX_free(ctx);
+ return -1;
+ }
+
+ if (!SSL_set_fd(sslsock->ssl_handle, sslsock->s.socket)) {
+ printf("failed to set fd %d\n", sslsock->s.socket);
+ handle_ssl_error(stream, 0 TSRMLS_CC);
+ }
+
+ if (cparam->inputs.session) {
+ printf("sess=%p\n", cparam->inputs.session);
+ if (cparam->inputs.session->ops != &php_openssl_socket_ops) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "supplied session stream must be an SSL enabled stream");
+ } else {
+ SSL_copy_session_id(sslsock->ssl_handle, ((php_openssl_netstream_data_t*)cparam->inputs.session->abstract)->ssl_handle);
+ }
+ }
+printf("crypto prepared for fd=%d\n", sslsock->s.socket);
+ return 0;
+}
+
+static inline int php_openssl_enable_crypto(php_stream *stream,
+ php_openssl_netstream_data_t *sslsock,
+ php_stream_xport_crypto_param *cparam
+ TSRMLS_DC)
+{
+ int n, retry = 1;
+
+ if (cparam->inputs.activate) {
+ if (sslsock->is_client) {
+ do {
+ n = SSL_connect(sslsock->ssl_handle);
+
+ if (n <= 0) {
+ retry = handle_ssl_error(stream, n TSRMLS_CC);
+ printf("error; retry = %d\n", retry);
+ } else {
+ break;
+ }
+ } while (retry);
+
+ printf("enabled_crypto: n=%d\n", n);
+ if (n == 1) {
+ sslsock->ssl_active = 1;
+ }
+
+ return n;
+
+ } else {
+
+ }
+ } else {
+ /* deactivate - common for server/client */
+ }
+ return -1;
+}
+
+static int php_openssl_sockop_set_option(php_stream *stream, int option, int value, void *ptrparam TSRMLS_DC)
+{
+ php_openssl_netstream_data_t *sslsock = (php_openssl_netstream_data_t*)stream->abstract;
+ php_stream_xport_crypto_param *cparam = (php_stream_xport_crypto_param *)ptrparam;
+ php_stream_xport_param *xparam = (php_stream_xport_param *)ptrparam;
+
+ switch (option) {
+ case PHP_STREAM_OPTION_CRYPTO_API:
+
+ switch(cparam->op) {
+
+ case STREAM_XPORT_CRYPTO_OP_SETUP:
+ cparam->outputs.returncode = php_openssl_setup_crypto(stream, sslsock, cparam TSRMLS_CC);
+ return PHP_STREAM_OPTION_RETURN_OK;
+ case STREAM_XPORT_CRYPTO_OP_ENABLE:
+ cparam->outputs.returncode = php_openssl_enable_crypto(stream, sslsock, cparam TSRMLS_CC);
+ return PHP_STREAM_OPTION_RETURN_OK;
+ default:
+ /* fall through */
+ }
+
+ break;
+
+ case PHP_STREAM_OPTION_XPORT_API:
+ switch(xparam->op) {
+
+ case STREAM_XPORT_OP_CONNECT:
+ case STREAM_XPORT_OP_CONNECT_ASYNC:
+ /* TODO: Async connects need to check the enable_on_connect option when
+ * we notice that the connect has actually been established */
+ php_stream_socket_ops.set_option(stream, option, value, ptrparam TSRMLS_CC);
+
+ if (xparam->outputs.returncode == 0 && sslsock->enable_on_connect) {
+ if (php_stream_xport_crypto_setup(stream, sslsock->method, NULL TSRMLS_CC) < 0 ||
+ php_stream_xport_crypto_enable(stream, 1 TSRMLS_CC) < 0) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to enable crypto");
+ xparam->outputs.returncode = -1;
+ }
+ }
+ return PHP_STREAM_OPTION_RETURN_OK;
+ default:
+ /* fall through */
+ }
+ }
+
+ return php_stream_socket_ops.set_option(stream, option, value, ptrparam TSRMLS_CC);
+}
+
+static int php_openssl_sockop_cast(php_stream *stream, int castas, void **ret TSRMLS_DC)
+{
+ php_openssl_netstream_data_t *sslsock = (php_openssl_netstream_data_t*)stream->abstract;
+
+ switch(castas) {
+ case PHP_STREAM_AS_STDIO:
+ if (sslsock->ssl_active) {
+ return FAILURE;
+ }
+ if (ret) {
+ *ret = fdopen(sslsock->s.socket, stream->mode);
+ if (*ret) {
+ return SUCCESS;
+ }
+ return FAILURE;
+ }
+ return SUCCESS;
+ case PHP_STREAM_AS_FD:
+ case PHP_STREAM_AS_SOCKETD:
+ if (sslsock->ssl_active) {
+ return FAILURE;
+ }
+ if (ret) {
+ *ret = (void*)sslsock->s.socket;
+ }
+ return SUCCESS;
+ default:
+ return FAILURE;
+ }
+}
+
+php_stream_ops php_openssl_socket_ops = {
+ php_openssl_sockop_write, php_openssl_sockop_read,
+ php_openssl_sockop_close, php_openssl_sockop_flush,
+ "tcp_socket/ssl",
+ NULL, /* seek */
+ php_openssl_sockop_cast,
+ php_openssl_sockop_stat,
+ php_openssl_sockop_set_option,
+};
+
+
+PHPAPI php_stream *php_openssl_ssl_socket_factory(const char *proto, long protolen,
+ char *resourcename, long resourcenamelen,
+ const char *persistent_id, int options, int flags,
+ struct timeval *timeout,
+ php_stream_context *context STREAMS_DC TSRMLS_DC)
+{
+ php_stream *stream = NULL;
+ php_openssl_netstream_data_t *sslsock = NULL;
+
+ sslsock = pemalloc(sizeof(php_openssl_netstream_data_t), persistent_id ? 1 : 0);
+ memset(sslsock, 0, sizeof(php_openssl_netstream_data_t));
+
+ sslsock->s.is_blocked = 1;
+ sslsock->s.timeout.tv_sec = FG(default_socket_timeout);
+ sslsock->s.timeout.tv_usec = 0;
+
+ /* we don't know the socket until we have determined if we are binding or
+ * connecting */
+ sslsock->s.socket = -1;
+
+ stream = php_stream_alloc_rel(&php_openssl_socket_ops, sslsock, persistent_id, "r+");
+
+ if (stream == NULL) {
+ pefree(sslsock, persistent_id ? 1 : 0);
+ return NULL;
+ }
+
+ if (strncmp(proto, "ssl", protolen) == 0) {
+ sslsock->enable_on_connect = 1;
+ sslsock->method = STREAM_CRYPTO_METHOD_SSLv23_CLIENT;
+ } else if (strncmp(proto, "tls", protolen) == 0) {
+ sslsock->enable_on_connect = 1;
+ sslsock->method = STREAM_CRYPTO_METHOD_TLS_CLIENT;
+ }
+
+ return stream;
+}
+
+
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim600: noet sw=4 ts=4 fdm=marker
+ * vim<600: noet sw=4 ts=4
+ */
diff --git a/ext/standard/basic_functions.c b/ext/standard/basic_functions.c
index 9a14905b3a..84c1347f50 100644
--- a/ext/standard/basic_functions.c
+++ b/ext/standard/basic_functions.c
@@ -1166,9 +1166,6 @@ PHP_RINIT_FUNCTION(basic)
BG(locale_string) = NULL;
BG(user_compare_func_name) = NULL;
BG(array_walk_func_name) = NULL;
-#ifdef HAVE_MMAP
- BG(mmap_file) = NULL;
-#endif
BG(page_uid) = -1;
BG(page_gid) = -1;
BG(page_inode) = -1;
@@ -1219,7 +1216,6 @@ PHP_RSHUTDOWN_FUNCTION(basic)
}
STR_FREE(BG(locale_string));
- PHP_RSHUTDOWN(fsock)(SHUTDOWN_FUNC_ARGS_PASSTHRU);
PHP_RSHUTDOWN(filestat)(SHUTDOWN_FUNC_ARGS_PASSTHRU);
#ifdef HAVE_SYSLOG_H
PHP_RSHUTDOWN(syslog)(SHUTDOWN_FUNC_ARGS_PASSTHRU);
@@ -1246,12 +1242,6 @@ PHP_RSHUTDOWN_FUNCTION(basic)
BG(user_filter_map) = NULL;
}
-#ifdef HAVE_MMAP
- if (BG(mmap_file)) {
- munmap(BG(mmap_file), BG(mmap_len));
- }
-#endif
-
return SUCCESS;
}
diff --git a/ext/standard/file.c b/ext/standard/file.c
index 0674f4b3fd..9da076e08a 100644
--- a/ext/standard/file.c
+++ b/ext/standard/file.c
@@ -647,6 +647,7 @@ PHP_FUNCTION(stream_get_meta_data)
add_assoc_long(return_value, "unread_bytes", stream->writepos - stream->readpos);
+#if 0
if (php_stream_is(stream, PHP_STREAM_IS_SOCKET)) {
php_netstream_data_t *sock = PHP_NETSTREAM_DATA_FROM_STREAM(stream);
@@ -654,10 +655,13 @@ PHP_FUNCTION(stream_get_meta_data)
add_assoc_bool(return_value, "blocked", sock->is_blocked);
add_assoc_bool(return_value, "eof", stream->eof);
} else {
+#endif
add_assoc_bool(return_value, "timed_out", 0);
add_assoc_bool(return_value, "blocked", 1);
add_assoc_bool(return_value, "eof", php_stream_eof(stream));
+#if 0
}
+#endif
}
/* }}} */
@@ -2237,7 +2241,7 @@ PHP_FUNCTION(unlink)
}
/* }}} */
-/* {{{ proto int ftruncate(resource fp, int size)
+/* {{{ proto bool ftruncate(resource fp, int size)
Truncate file to 'size' length */
PHP_NAMED_FUNCTION(php_if_ftruncate)
{
@@ -2254,15 +2258,12 @@ PHP_NAMED_FUNCTION(php_if_ftruncate)
convert_to_long_ex(size);
- if (php_stream_is(stream, PHP_STREAM_IS_SOCKET)) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Can't truncate sockets!");
+ if (!php_stream_truncate_supported(stream)) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Can't truncate this stream!");
RETURN_FALSE;
}
- if (SUCCESS == php_stream_cast(stream, PHP_STREAM_AS_FD, (void*)&fd, 1)) {
- ret = ftruncate(fd, Z_LVAL_PP(size));
- RETURN_LONG(ret + 1);
- }
- RETURN_FALSE;
+
+ RETURN_BOOL(0 == php_stream_truncate_set_size(stream, Z_LVAL_PP(size)));
}
/* }}} */
diff --git a/ext/standard/fsock.c b/ext/standard/fsock.c
index bbe6d7debb..8f41cf4d3f 100644
--- a/ext/standard/fsock.c
+++ b/ext/standard/fsock.c
@@ -20,122 +20,19 @@
/* $Id$ */
-/* converted to PHP Streams and moved much code to main/network.c [wez] */
-
-/* Synced with php 3.0 revision 1.121 1999-06-18 [ssb] */
-/* Synced with php 3.0 revision 1.133 1999-07-21 [sas] */
-
#include "php.h"
#include "php_globals.h"
#include <stdlib.h>
#include <stddef.h>
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-
-#ifdef HAVE_FCNTL_H
-# include <fcntl.h>
-#endif
-
-#ifdef HAVE_SYS_TIME_H
-# include <sys/time.h>
-#endif
-
-#include <sys/types.h>
-#ifdef HAVE_SYS_SOCKET_H
-#include <sys/socket.h>
-#endif
-#ifdef PHP_WIN32
-#include <winsock2.h>
-#elif defined(NETWARE)
-#ifdef NEW_LIBC
-#ifdef USE_WINSOCK
-#include <novsock2.h>
-#else
-#include <netinet/in.h>
-#include <netdb.h>
-/*#include <sys/socket.h>*/
-#include <sys/select.h>
-/*#else
-#include <sys/socket.h>*/
-#endif
-#endif
-#else
-#include <netinet/in.h>
-#include <netdb.h>
-#if HAVE_ARPA_INET_H
-#include <arpa/inet.h>
-#endif
-#endif
-#if defined(PHP_WIN32) || defined(__riscos__) || defined(NETWARE)
-#undef AF_UNIX
-#endif
-#if defined(AF_UNIX)
-#include <sys/un.h>
-#endif
-#ifdef HAVE_SYS_SELECT_H
-#include <sys/select.h>
-#endif
-
-#ifndef PF_INET
-#define PF_INET AF_INET
-#endif
-
-#ifndef PF_UNIX
-#define PF_UNIX AF_UNIX
-#endif
-
-#include <string.h>
-#include <errno.h>
-
-#include "base64.h"
-#include "file.h"
-#include "url.h"
-#include "fsock.h"
-
#include "php_network.h"
-
-#ifdef ZTS
-static int fsock_globals_id;
-#endif
-
-#ifdef PHP_WIN32
-#define EWOULDBLOCK WSAEWOULDBLOCK
-#elif defined(NETWARE)
-#ifdef USE_WINSOCK
-#define EWOULDBLOCK WSAEWOULDBLOCK
-#endif
-#endif
-
-/* {{{ php_lookup_hostname */
-
-/*
- * Converts a host name to an IP address.
- * TODO: This looks like unused code suitable for nuking.
- */
-PHPAPI int php_lookup_hostname(const char *addr, struct in_addr *in)
-{
- struct hostent *host_info;
-
- if (!inet_aton(addr, in)) {
- /* XXX NOT THREAD SAFE */
- host_info = gethostbyname(addr);
- if (host_info == 0) {
- /* Error: unknown host */
- return -1;
- }
- *in = *((struct in_addr *) host_info->h_addr);
- }
- return 0;
-}
-/* }}} */
+#include "file.h"
/* {{{ php_fsockopen() */
static void php_fsockopen_stream(INTERNAL_FUNCTION_PARAMETERS, int persistent)
{
char *host;
- int host_len;
+ long host_len;
int port = -1;
zval *zerrno = NULL, *zerrstr = NULL;
double timeout = FG(default_socket_timeout);
@@ -144,6 +41,9 @@ static void php_fsockopen_stream(INTERNAL_FUNCTION_PARAMETERS, int persistent)
char *hashkey = NULL;
php_stream *stream = NULL;
int err;
+ char *hostname = NULL;
+ long hostname_len;
+ char *errstr = NULL;
RETVAL_FALSE;
@@ -151,22 +51,17 @@ static void php_fsockopen_stream(INTERNAL_FUNCTION_PARAMETERS, int persistent)
RETURN_FALSE;
}
-
if (persistent) {
spprintf(&hashkey, 0, "pfsockopen__%s:%d", host, port);
-
- switch(php_stream_from_persistent_id(hashkey, &stream TSRMLS_CC)) {
- case PHP_STREAM_PERSISTENT_SUCCESS:
- /* TODO: could check if the socket is still alive here */
- php_stream_to_zval(stream, return_value);
-
- /* fall through */
- case PHP_STREAM_PERSISTENT_FAILURE:
- efree(hashkey);
- return;
- }
}
+ if (port > 0) {
+ hostname_len = spprintf(&hostname, 0, "%s:%d", host, port);
+ } else {
+ hostname_len = host_len;
+ hostname = host;
+ }
+
/* prepare the timeout value for use */
conv = (unsigned long) (timeout * 1000000.0);
tv.tv_sec = conv / 1000000;
@@ -181,88 +76,29 @@ static void php_fsockopen_stream(INTERNAL_FUNCTION_PARAMETERS, int persistent)
ZVAL_STRING(zerrstr, "", 1);
}
- if (port > 0) { /* connect to a host */
- enum php_sslflags_t { php_ssl_none, php_ssl_v23, php_ssl_tls };
- enum php_sslflags_t ssl_flags = php_ssl_none;
- struct {
- char *proto;
- int protolen;
- int socktype;
- enum php_sslflags_t ssl_flags;
- /* more flags to be added here */
- } sockmodes[] = {
- { "udp://", 6, SOCK_DGRAM, php_ssl_none },
- { "tcp://", 6, SOCK_STREAM, php_ssl_none },
- { "ssl://", 6, SOCK_STREAM, php_ssl_v23 },
- { "tls://", 6, SOCK_STREAM, php_ssl_tls },
- /* more modes to be added here */
- { NULL, 0, 0 }
- };
- int socktype = SOCK_STREAM;
- int i;
-
- for (i = 0; sockmodes[i].proto != NULL; i++) {
- if (strncmp(host, sockmodes[i].proto, sockmodes[i].protolen) == 0) {
- ssl_flags = sockmodes[i].ssl_flags;
- socktype = sockmodes[i].socktype;
- host += sockmodes[i].protolen;
- break;
- }
- }
-#if !HAVE_OPENSSL_EXT
- if (ssl_flags != php_ssl_none) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "no SSL support in this build");
- }
- else
-#endif
- stream = php_stream_sock_open_host(host, (unsigned short)port, socktype, &tv, hashkey);
-
- /* Preserve error */
- err = php_socket_errno();
+ stream = php_stream_xport_create(hostname, hostname_len, ENFORCE_SAFE_MODE | REPORT_ERRORS,
+ STREAM_XPORT_CLIENT | STREAM_XPORT_CONNECT, hashkey, &tv, NULL, &errstr, &err);
- if (stream == NULL) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "unable to connect to %s:%d", host, port);
- }
-
-#if HAVE_OPENSSL_EXT
- if (stream && ssl_flags != php_ssl_none) {
- int ssl_ret = FAILURE;
- switch(ssl_flags) {
- case php_ssl_v23:
- ssl_ret = php_stream_sock_ssl_activate_with_method(stream, 1, SSLv23_client_method(), NULL TSRMLS_CC);
- break;
- case php_ssl_tls:
- ssl_ret = php_stream_sock_ssl_activate_with_method(stream, 1, TLSv1_client_method(), NULL TSRMLS_CC);
- break;
- default:
- /* unknown ?? */
- break;
- }
- if (ssl_ret == FAILURE)
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "failed to activate SSL mode %d", ssl_flags);
- }
-#endif
-
- } else {
- /* FIXME: Win32 - this probably does not return sensible errno and errstr */
- stream = php_stream_sock_open_unix(host, host_len, hashkey, &tv);
- err = php_socket_errno();
+ if (port > 0) {
+ efree(hostname);
+ }
+ if (stream == NULL) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "unable to connect to %s:%d", host, port);
}
- if (hashkey)
+ if (hashkey) {
efree(hashkey);
+ }
if (stream == NULL) {
if (zerrno) {
zval_dtor(zerrno);
ZVAL_LONG(zerrno, err);
}
- if (zerrstr) {
- char *buf = php_socket_strerror(err, NULL, 0);
-
- /* no need to dup; we would only need to efree buf anyway */
+ if (zerrstr && errstr) {
+ /* no need to dup; we need to efree buf anyway */
zval_dtor(zerrstr);
- ZVAL_STRING(zerrstr, buf, 0);
+ ZVAL_STRING(zerrstr, errstr, 0);
}
RETURN_FALSE;
}
@@ -287,12 +123,6 @@ PHP_FUNCTION(pfsockopen)
}
/* }}} */
-/* {{{ RSHUTDOWN_FUNCTION(fsock) */
-PHP_RSHUTDOWN_FUNCTION(fsock)
-{
- return SUCCESS;
-}
-/* }}} */
/*
* Local variables:
* tab-width: 4
diff --git a/ext/standard/fsock.h b/ext/standard/fsock.h
index 966fc1ecec..7d263c31e1 100644
--- a/ext/standard/fsock.h
+++ b/ext/standard/fsock.h
@@ -40,10 +40,6 @@
PHP_FUNCTION(fsockopen);
PHP_FUNCTION(pfsockopen);
-PHPAPI int php_lookup_hostname(const char *addr, struct in_addr *in);
-
-PHP_RSHUTDOWN_FUNCTION(fsock);
-
/*
* Local variables:
* tab-width: 4
diff --git a/ext/standard/ftp_fopen_wrapper.c b/ext/standard/ftp_fopen_wrapper.c
index 98b5a27892..192786058d 100644
--- a/ext/standard/ftp_fopen_wrapper.c
+++ b/ext/standard/ftp_fopen_wrapper.c
@@ -142,10 +142,8 @@ php_stream * php_stream_url_wrap_ftp(php_stream_wrapper *wrapper, char *path, ch
char *scratch;
int result;
int i, use_ssl;
-#if HAVE_OPENSSL_EXT
int use_ssl_on_data=0;
php_stream *reuseid=NULL;
-#endif
char *tpath, *ttpath, *hoststart=NULL;
size_t file_size = 0;
@@ -182,7 +180,6 @@ php_stream * php_stream_url_wrap_ftp(php_stream_wrapper *wrapper, char *path, ch
goto errexit;
}
-#if HAVE_OPENSSL_EXT
if (use_ssl) {
/* send the AUTH TLS request name */
@@ -212,7 +209,9 @@ php_stream * php_stream_url_wrap_ftp(php_stream_wrapper *wrapper, char *path, ch
}
if (use_ssl) {
- if (use_ssl && php_stream_sock_ssl_activate(stream, 1) == FAILURE) {
+ if (php_stream_xport_crypto_setup(stream,
+ STREAM_CRYPTO_METHOD_SSLv23_CLIENT, NULL TSRMLS_CC) < 0
+ || php_stream_xport_crypto_enable(stream, 1 TSRMLS_CC) < 0) {
php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "Unable to activate SSL mode");
php_stream_close(stream);
stream = NULL;
@@ -240,8 +239,6 @@ php_stream * php_stream_url_wrap_ftp(php_stream_wrapper *wrapper, char *path, ch
#endif
}
-#endif
-
/* send the user name */
php_stream_write_string(stream, "USER ");
if (resource->user != NULL) {
@@ -433,14 +430,15 @@ php_stream * php_stream_url_wrap_ftp(php_stream_wrapper *wrapper, char *path, ch
php_stream_context_set(datastream, context);
php_stream_notify_progress_init(context, 0, file_size);
-#if HAVE_OPENSSL_EXT
- if (use_ssl_on_data && php_stream_sock_ssl_activate_with_method(datastream, 1, SSLv23_method(), reuseid TSRMLS_CC) == FAILURE) {
+ if (use_ssl_on_data && (php_stream_xport_crypto_setup(stream,
+ STREAM_CRYPTO_METHOD_SSLv23_CLIENT, NULL TSRMLS_CC) < 0 ||
+ php_stream_xport_crypto_enable(stream, 1 TSRMLS_CC) < 0)) {
+
php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "Unable to activate SSL mode");
php_stream_close(datastream);
datastream = NULL;
goto errexit;
}
-#endif
/* remember control stream */
datastream->wrapperdata = (zval *)stream;
diff --git a/ext/standard/http_fopen_wrapper.c b/ext/standard/http_fopen_wrapper.c
index e6da657882..dbe7340a9a 100644
--- a/ext/standard/http_fopen_wrapper.c
+++ b/ext/standard/http_fopen_wrapper.c
@@ -99,6 +99,8 @@ php_stream *php_stream_url_wrap_http(php_stream_wrapper *wrapper, char *path, ch
char tmp_line[128];
size_t chunk_size = 0, file_size = 0;
int eol_detect;
+ char *transport_string, *errstr = NULL;
+ int transport_len;
if (strpbrk(mode, "awx+")) {
php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "HTTP wrapper does not support writeable connections.");
@@ -110,14 +112,26 @@ php_stream *php_stream_url_wrap_http(php_stream_wrapper *wrapper, char *path, ch
return NULL;
use_ssl = resource->scheme && (strlen(resource->scheme) > 4) && resource->scheme[4] == 's';
-
/* choose default ports */
if (use_ssl && resource->port == 0)
resource->port = 443;
else if (resource->port == 0)
resource->port = 80;
- stream = php_stream_sock_open_host(resource->host, resource->port, SOCK_STREAM, NULL, 0);
+ transport_len = spprintf(&transport_string, 0, "%s://%s:%d", use_ssl ? "ssl" : "tcp", resource->host, resource->port);
+
+ stream = php_stream_xport_create(transport_string, transport_len, options,
+ STREAM_XPORT_CLIENT | STREAM_XPORT_CONNECT,
+ NULL, NULL, context, &errstr, NULL);
+
+ if (errstr) {
+ php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "%s", errstr);
+ efree(errstr);
+ errstr = NULL;
+ }
+
+ efree(transport_string);
+
if (stream == NULL)
goto out;
@@ -133,17 +147,6 @@ php_stream *php_stream_url_wrap_http(php_stream_wrapper *wrapper, char *path, ch
php_stream_context_set(stream, context);
php_stream_notify_info(context, PHP_STREAM_NOTIFY_CONNECT, NULL, 0);
-
-#if HAVE_OPENSSL_EXT
- if (use_ssl) {
- if (php_stream_sock_ssl_activate(stream, 1) == FAILURE) {
- php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "Unable to activate SSL mode");
- php_stream_close(stream);
- stream = NULL;
- goto out;
- }
- }
-#endif
scratch_len = strlen(path) + 32;
scratch = emalloc(scratch_len);