php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Return to Bug #62807
Patch ssh2_scp_send_fix_send_large_file_bug_for_0.11.3 revision 2012-08-13 12:49 UTC by chopins dot xiao at gmail dot com
revision 2012-08-13 12:47 UTC by chopins dot xiao at gmail dot com
Patch ssh2_scp_send_path revision 2012-08-13 12:27 UTC by chopins dot xiao at gmail dot com

Patch ssh2_scp_send_path for ssh2 Bug #62807

Patch version 2012-08-13 12:27 UTC

Return to Bug #62807 | Download this patch
This patch is obsolete

Obsoleted by patches:

Patch Revisions:

Developer: chopins.xiao@gmail.com

Index: ssh2_fopen_wrappers.c
===================================================================
--- ssh2_fopen_wrappers.c	(版本 327101)
+++ ssh2_fopen_wrappers.c	(工作副本)
@@ -32,79 +32,21 @@
 static size_t php_ssh2_channel_stream_write(php_stream *stream, const char *buf, size_t count TSRMLS_DC)
 {
 	php_ssh2_channel_data *abstract = (php_ssh2_channel_data*)stream->abstract;
-	size_t writestate;
-	LIBSSH2_SESSION *session;
 
 	libssh2_channel_set_blocking(abstract->channel, abstract->is_blocking);
-	session = (LIBSSH2_SESSION *)zend_fetch_resource(NULL TSRMLS_CC, abstract->session_rsrc, PHP_SSH2_SESSION_RES_NAME, NULL, 1, le_ssh2_session);
-
-#ifdef PHP_SSH2_SESSION_TIMEOUT
-	if (abstract->is_blocking) {
-		libssh2_session_set_timeout(session, abstract->timeout);
-	}
-#endif
-
-	writestate = libssh2_channel_write_ex(abstract->channel, abstract->streamid, buf, count);
-
-#ifdef PHP_SSH2_SESSION_TIMEOUT
-	if (abstract->is_blocking) {
-		libssh2_session_set_timeout(session, 0);
-	}
-#endif
-	if (writestate == LIBSSH2_ERROR_EAGAIN) {
-		writestate = 0;
-	}
-
-	if (writestate < 0) {
-		char *error_msg = NULL;
-		if (libssh2_session_last_error(session, &error_msg, NULL, 0) == writestate) {
-			php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failure '%s' (%ld)", error_msg, writestate);
-		}
-
-		stream->eof = 1;
-		writestate = 0;
-	}
-
-	return writestate;
+	return libssh2_channel_write_ex(abstract->channel, abstract->streamid, buf, count);
 }
 
 static size_t php_ssh2_channel_stream_read(php_stream *stream, char *buf, size_t count TSRMLS_DC)
 {
 	php_ssh2_channel_data *abstract = (php_ssh2_channel_data*)stream->abstract;
 	ssize_t readstate;
-	LIBSSH2_SESSION *session;
 
 	stream->eof = libssh2_channel_eof(abstract->channel);
 	libssh2_channel_set_blocking(abstract->channel, abstract->is_blocking);
-	session = (LIBSSH2_SESSION *)zend_fetch_resource(NULL TSRMLS_CC, abstract->session_rsrc, PHP_SSH2_SESSION_RES_NAME, NULL, 1, le_ssh2_session);
-
-#ifdef PHP_SSH2_SESSION_TIMEOUT
-	if (abstract->is_blocking) {
-		libssh2_session_set_timeout(session, abstract->timeout);
-	}
-#endif
-
+		
 	readstate = libssh2_channel_read_ex(abstract->channel, abstract->streamid, buf, count);
-
-#ifdef PHP_SSH2_SESSION_TIMEOUT
-	if (abstract->is_blocking) {
-		libssh2_session_set_timeout(session, 0);
-	}
-#endif
-	if (readstate == LIBSSH2_ERROR_EAGAIN) {
-		readstate = 0;
-	}
-
-	if (readstate < 0) {
-		char *error_msg = NULL;
-		if (libssh2_session_last_error(session, &error_msg, NULL, 0) == readstate) {
-			php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failure '%s' (%ld)", error_msg, readstate);
-		}
-
-		stream->eof = 1;
-		readstate = 0;
-	}
-	return readstate;
+	return (readstate < 0 ? 0 : readstate);
 }
 
 static int php_ssh2_channel_stream_close(php_stream *stream, int close_handle TSRMLS_DC)
@@ -143,18 +85,6 @@
 			abstract->is_blocking = value;
 			return ret;
 			break;
-
-		case PHP_STREAM_OPTION_READ_TIMEOUT:
-			ret = abstract->timeout;
-#ifdef PHP_SSH2_SESSION_TIMEOUT
-			struct timeval tv = *(struct timeval*)ptrparam;
-			abstract->timeout = tv.tv_sec * 1000 + (tv.tv_usec / 1000);
-#else
-			php_error_docref(NULL TSRMLS_CC, E_WARNING, "No support for ssh2 stream timeout. Please recompile with libssh2 >= 1.2.9");
-#endif
-			return ret;
-			break;
-
 #if PHP_MAJOR_VERSION >= 5
 		case PHP_STREAM_OPTION_CHECK_LIVENESS:
 			return stream->eof = libssh2_channel_eof(abstract->channel);
@@ -217,15 +147,7 @@
 	if (!resource->host) {
 		return NULL;
 	}
-
-	/*
-		Find resource->path in the path string, then copy the entire string from the original path.
-		This includes ?query#fragment in the path string
-	*/
-	s = resource->path;
-	resource->path = estrdup(strstr(path, resource->path));
-	efree(s);
-
+	
 	/* Look for a resource ID to reuse a session */
 	s = resource->host;
 	if (strncmp(resource->host, "Resource id #", sizeof("Resource id #") - 1) == 0) {
@@ -522,7 +444,6 @@
 	channel_data->channel = channel;
 	channel_data->streamid = 0;
 	channel_data->is_blocking = 0;
-	channel_data->timeout = 0;
 	channel_data->session_rsrc = resource_id;
 	channel_data->refcount = NULL;
 
@@ -673,12 +594,12 @@
 	int argc = ZEND_NUM_ARGS();
 
 	if (argc == 5) {
-		php_error_docref(NULL TSRMLS_CC, E_ERROR, "width specified without height parameter");
+		php_error_docref(NULL TSRMLS_CC, E_ERROR, "width specified without height paramter");
 		RETURN_FALSE;
 	}
 
 	if (zend_parse_parameters(argc TSRMLS_CC, "r|sa!lll", &zsession, &term, &term_len, &environment, &width, &height, &type) == FAILURE) {
-		return;
+		RETURN_FALSE;
 	}
 
 	ZEND_FETCH_RESOURCE(session, LIBSSH2_SESSION*, &zsession, -1, PHP_SSH2_SESSION_RES_NAME, le_ssh2_session);
@@ -768,7 +689,6 @@
 	channel_data->channel = channel;
 	channel_data->streamid = 0;
 	channel_data->is_blocking = 0;
-	channel_data->timeout = 0;
 	channel_data->session_rsrc = resource_id;
 	channel_data->refcount = NULL;
 
@@ -896,7 +816,7 @@
 	int term_len = 0;
 
 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs|z!z!lll", &zsession, &command, &command_len, &zpty, &environment, &width, &height, &type) == FAILURE) {
-		return;
+		RETURN_FALSE;
 	}
 
 	if (zpty && Z_TYPE_P(zpty) == IS_ARRAY) {
@@ -957,7 +877,6 @@
 	channel_data->channel = channel;
 	channel_data->streamid = 0;
 	channel_data->is_blocking = 0;
-	channel_data->timeout = 0;
 	channel_data->session_rsrc = resource_id;
 	channel_data->refcount = NULL;
 
@@ -1031,7 +950,7 @@
 
 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rss", &zsession,  &remote_filename, &remote_filename_len, 
 																			&local_filename, &local_filename_len) == FAILURE) {
-		return;
+		RETURN_FALSE;
 	}
 
 	ZEND_FETCH_RESOURCE(session, LIBSSH2_SESSION*, &zsession, -1, PHP_SSH2_SESSION_RES_NAME, le_ssh2_session);
@@ -1086,14 +1005,19 @@
 	long create_mode = 0644;
 	php_stream_statbuf ssb;
 	int argc = ZEND_NUM_ARGS();
+	ssize_t write_size;
+	int nfds = 1;
+	struct timeval timeout;
+	int select_number;
+	fd_set writefd;
+	int ssh_fd;
 
 	if (zend_parse_parameters(argc TSRMLS_CC, "rss|l", &zsession, &local_filename, &local_filename_len, 
 													   &remote_filename, &remote_filename_len, &create_mode) == FAILURE) {
-		return;
+		RETURN_FALSE;
 	}
 
 	ZEND_FETCH_RESOURCE(session, LIBSSH2_SESSION*, &zsession, -1, PHP_SSH2_SESSION_RES_NAME, le_ssh2_session);
-
 	local_file = php_stream_open_wrapper(local_filename, "rb", ENFORCE_SAFE_MODE | REPORT_ERRORS, NULL);
 	if (!local_file) {
 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to read source file");
@@ -1120,36 +1044,60 @@
 		php_stream_close(local_file);
 		RETURN_FALSE;
 	}
-	libssh2_channel_set_blocking(remote_file, 1);
 
+	libssh2_channel_set_blocking(remote_file, 1);
+	int send_none = 1;
+	char buffer[8192];
+	size_t toread;
+	size_t bytesread;
 	while (ssb.sb.st_size) {
-		char buffer[8192];
-		size_t toread = MIN(8192, ssb.sb.st_size);
-		size_t bytesread = php_stream_read(local_file, buffer, toread);
-
+		if(send_none == 1) {
+			toread = MIN(8192, ssb.sb.st_size);
+			bytesread = php_stream_read(local_file, buffer, toread);
+		}
 		if (bytesread <= 0 || bytesread > toread) {
 			php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed copying file 2");
 			php_stream_close(local_file);
 			libssh2_channel_free(remote_file);
 			RETURN_FALSE;
 		}
-
-		size_t sent = 0;
-		size_t justsent = 0;
-
-		while (bytesread - sent > 0) {
-			if ((justsent = libssh2_channel_write(remote_file, (buffer + sent), bytesread - sent)) < 0) {
-				php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed copying file");
-				php_stream_close(local_file);
-				libssh2_channel_free(remote_file);
-				RETURN_FALSE;
+		write_size = libssh2_channel_write(remote_file, buffer, bytesread);
+		if(write_size < 0) {
+			switch(write_size) {
+				case LIBSSH2_ERROR_EAGAIN:
+					php_error_docref(NULL TSRMLS_CC, E_WARNING,"System tcpsendspace is full");
+				break;
+				case LIBSSH2_ERROR_ALLOC:
+					php_error_docref(NULL TSRMLS_CC,E_WARNING,"An internal memory allocation call failed");
+				break;
+				case LIBSSH2_ERROR_SOCKET_SEND:
+					php_error_docref(NULL TSRMLS_CC,E_WARNING,"Unable to send data on socket");
+				break;
+				case LIBSSH2_ERROR_CHANNEL_CLOSED:
+					php_error_docref(NULL TSRMLS_CC,E_WARNING,"The channel has been closed");
+				break;
+				case LIBSSH2_ERROR_CHANNEL_EOF_SENT:
+					php_error_docref(NULL TSRMLS_CC,E_WARNING,"The channel has been requested to be closed");
+				break;
+				break;
 			}
-			sent = sent + justsent;
+			RETURN_FALSE;
 		}
+		if(LIBSSH2_ERROR_NONE == write_size || LIBSSH2_ERROR_EAGAIN == write_size) {
+			send_none = 0;
+			continue;
+		} else {
+			send_none = 1;
+		}
+		if (write_size != bytesread) {
+			php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed copying file");
+			php_stream_close(local_file);
+			libssh2_channel_free(remote_file);
+			RETURN_FALSE;
+		}
 		ssb.sb.st_size -= bytesread;
 	}
 
-	libssh2_channel_flush_ex(remote_file, LIBSSH2_CHANNEL_FLUSH_ALL);
 	php_stream_close(local_file);
 	libssh2_channel_free(remote_file);
 	RETURN_TRUE;
@@ -1180,7 +1128,6 @@
 	channel_data->channel = channel;
 	channel_data->streamid = 0;
 	channel_data->is_blocking = 0;
-	channel_data->timeout = 0;
 	channel_data->session_rsrc = resource_id;
 	channel_data->refcount = NULL;
 
@@ -1275,7 +1222,7 @@
 	long port;
 
 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rsl", &zsession, &host, &host_len, &port) == FAILURE) {
-		return;
+		RETURN_FALSE;
 	}
 
 	ZEND_FETCH_RESOURCE(session, LIBSSH2_SESSION*, &zsession, -1, PHP_SSH2_SESSION_RES_NAME, le_ssh2_session);
@@ -1307,7 +1254,7 @@
 	long streamid;
 
 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl", &zparent, &streamid) == FAILURE) {
-		return;
+		RETURN_FALSE;
 	}
 
 	if (streamid < 0) {
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Mon Apr 29 06:01:29 2024 UTC