[-]
[+]
|
Changed |
php5-ssh2.spec
|
|
[-]
[+]
|
Deleted |
php5-ssh2-compile-fix.patch
^
|
@@ -1,14 +0,0 @@
---- ssh2.c.orig 2005-11-02 00:40:23.000000000 +0100
-+++ ssh2.c 2008-04-24 14:07:22.000000000 +0200
-@@ -477,8 +477,10 @@
-
- ZEND_FETCH_RESOURCE(session, LIBSSH2_SESSION*, &zsession, -1, PHP_SSH2_SESSION_RES_NAME, le_ssh2_session);
-
--#if LIBSSH2_APINO < 200412301450
-+#ifdef LIBSSH2_APINO
-+# if LIBSSH2_APINO < 200412301450
- libssh2_session_methods(session, &kex, &hostkey, &crypt_cs, &crypt_sc, &mac_cs, &mac_sc, &comp_cs, &comp_sc, &lang_cs, &lang_sc);
-+# endif
- #else
- kex = libssh2_session_methods(session, LIBSSH2_METHOD_KEX);
- hostkey = libssh2_session_methods(session, LIBSSH2_METHOD_HOSTKEY);
|
[-]
[+]
|
Deleted |
php5-ssh2-fixes.patch
^
|
@@ -1,143 +0,0 @@
-Index: ssh2_fopen_wrappers.c
-===================================================================
-RCS file: /repository/pecl/ssh2/ssh2_fopen_wrappers.c,v
-retrieving revision 1.11
-retrieving revision 1.13
-diff -u -r1.11 -r1.13
---- ssh2_fopen_wrappers.c 12 Jul 2005 03:24:20 -0000 1.11
-+++ ssh2_fopen_wrappers.c 7 Jun 2006 17:35:34 -0000 1.13
-@@ -2,6 +2,8 @@
- +----------------------------------------------------------------------+
- | PHP Version 4 |
- +----------------------------------------------------------------------+
-+ | Copyright (c) 1997-2006 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 |
-@@ -13,7 +15,7 @@
- | Author: Sara Golemon <pollita@php.net> |
- +----------------------------------------------------------------------+
-
-- $Id: ssh2_fopen_wrappers.c,v 1.11 2005/07/12 03:24:20 pollita Exp $
-+ $Id: ssh2_fopen_wrappers.c,v 1.13 2006/06/07 17:35:34 pollita Exp $
- */
-
- #ifdef HAVE_CONFIG_H
-@@ -48,7 +50,7 @@
- {
- php_ssh2_channel_data *abstract = (php_ssh2_channel_data*)stream->abstract;
-
-- if (!abstract->refcount || (--*(abstract->refcount) == 0)) {
-+ if (!abstract->refcount || (--(*(abstract->refcount)) == 0)) {
- /* Last one out, turn off the lights */
- if (abstract->refcount) {
- efree(abstract->refcount);
-@@ -1232,7 +1234,7 @@
- RETURN_FALSE;
- }
-
-- *(data->refcount)++;
-+ (*(data->refcount))++;
-
- stream_data = emalloc(sizeof(php_ssh2_channel_data));
- memcpy(stream_data, data, sizeof(php_ssh2_channel_data));
-Index: ssh2.c
-===================================================================
-RCS file: /repository/pecl/ssh2/ssh2.c,v
-retrieving revision 1.14
-retrieving revision 1.18
-diff -u -r1.14 -r1.18
---- ssh2.c 1 Nov 2005 23:40:23 -0000 1.14
-+++ ssh2.c 7 Jun 2006 17:35:34 -0000 1.18
-@@ -2,6 +2,8 @@
- +----------------------------------------------------------------------+
- | PHP Version 4 |
- +----------------------------------------------------------------------+
-+ | Copyright (c) 1997-2006 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 |
-@@ -13,7 +15,7 @@
- | Author: Sara Golemon <pollita@php.net> |
- +----------------------------------------------------------------------+
-
-- $Id: ssh2.c,v 1.14 2005/11/01 23:40:23 pollita Exp $
-+ $Id: ssh2.c,v 1.18 2006/06/07 17:35:34 pollita Exp $
- */
-
- #ifdef HAVE_CONFIG_H
-@@ -22,6 +24,7 @@
-
- #include "php.h"
- #include "ext/standard/info.h"
-+#include "ext/standard/file.h"
- #include "php_ssh2.h"
- #include "main/php_network.h"
-
-@@ -329,13 +332,17 @@
- LIBSSH2_SESSION *session;
- int socket;
- php_ssh2_session_data *data;
-+ struct timeval tv;
-+
-+ tv.tv_sec = FG(default_socket_timeout);
-+ tv.tv_usec = 0;
-
- #if PHP_MAJOR_VERSION > 5 || (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION > 0)
-- socket = php_network_connect_socket_to_host(host, port, SOCK_STREAM, 0, NULL, NULL, NULL, NULL, 0 TSRMLS_CC);
-+ socket = php_network_connect_socket_to_host(host, port, SOCK_STREAM, 0, &tv, NULL, NULL, NULL, 0 TSRMLS_CC);
- #elif PHP_MAJOR_VERSION == 5
-- socket = php_network_connect_socket_to_host(host, port, SOCK_STREAM, 0, NULL, NULL, NULL TSRMLS_CC);
-+ socket = php_network_connect_socket_to_host(host, port, SOCK_STREAM, 0, &tv, NULL, NULL TSRMLS_CC);
- #else
-- socket = php_hostconnect(host, port, SOCK_STREAM, NULL TSRMLS_CC);
-+ socket = php_hostconnect(host, port, SOCK_STREAM, &tv TSRMLS_CC);
- #endif
-
- if (socket <= 0) {
-@@ -469,7 +476,7 @@
- {
- LIBSSH2_SESSION *session;
- zval *zsession, *endpoint;
-- char *kex, *hostkey, *crypt_cs, *crypt_sc, *mac_cs, *mac_sc, *comp_cs, *comp_sc, *lang_cs, *lang_sc;
-+ const char *kex, *hostkey, *crypt_cs, *crypt_sc, *mac_cs, *mac_sc, *comp_cs, *comp_sc, *lang_cs, *lang_sc;
-
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zsession) == FAILURE) {
- RETURN_FALSE;
-@@ -522,7 +529,7 @@
- {
- LIBSSH2_SESSION *session;
- zval *zsession;
-- char *fingerprint;
-+ const char *fingerprint;
- long flags = 0;
- int i, fingerprint_len;
-
-@@ -1245,19 +1252,19 @@
- PHP_MINFO_FUNCTION(ssh2)
- {
- php_info_print_table_start();
-- php_info_print_table_header(2, "libssh2 version", LIBSSH2_VERSION);
-- php_info_print_table_header(2, "banner", LIBSSH2_SSH_BANNER);
-+ php_info_print_table_row(2, "libssh2 version", LIBSSH2_VERSION);
-+ php_info_print_table_row(2, "banner", LIBSSH2_SSH_BANNER);
- #ifdef PHP_SSH2_REMOTE_FORWARDING
-- php_info_print_table_header(2, "remote forwarding", "enabled");
-+ php_info_print_table_row(2, "remote forwarding", "enabled");
- #endif
- #ifdef PHP_SSH2_HOSTBASED_AUTH
-- php_info_print_table_header(2, "hostbased auth", "enabled");
-+ php_info_print_table_row(2, "hostbased auth", "enabled");
- #endif
- #ifdef PHP_SSH2_POLL
-- php_info_print_table_header(2, "polling support", "enabled");
-+ php_info_print_table_row(2, "polling support", "enabled");
- #endif
- #ifdef PHP_SSH2_PUBLICKEY_SUBSYSTEM
-- php_info_print_table_header(2, "publickey subsystem", "enabled");
-+ php_info_print_table_row(2, "publickey subsystem", "enabled");
- #endif
- php_info_print_table_end();
- }
|
[-]
[+]
|
Deleted |
php5-ssh2-lib64.patch
^
|
@@ -1,73 +0,0 @@
-Index: config.m4
-===================================================================
-RCS file: /repository/pecl/ssh2/config.m4,v
-retrieving revision 1.7
-diff -u -r1.7 config.m4
---- config.m4 21 Jul 2005 20:38:21 -0000 1.7
-+++ config.m4 22 Dec 2006 06:54:25 -0000
-@@ -1,4 +1,4 @@
--dnl $Id: config.m4,v 1.7 2005/07/21 20:38:21 pollita Exp $
-+dnl $Id: config.m4,v 1.10 2006/03/15 02:10:23 pollita Exp $
- dnl config.m4 for extension ssh2
-
- PHP_ARG_WITH(ssh2, for ssh2 support,
-@@ -7,7 +7,7 @@
- if test "$PHP_SSH2" != "no"; then
- SEARCH_PATH="/usr/local /usr"
- SEARCH_FOR="/include/libssh2.h"
-- if test -r $PHP_SSH2/; then # path given as parameter
-+ if test -r $PHP_SSH2/$SEARCH_FOR; then # path given as parameter
- SSH2_DIR=$PHP_SSH2
- else
- AC_MSG_CHECKING([for ssh2 files in default path])
-@@ -31,12 +31,12 @@
-
- PHP_CHECK_LIBRARY($LIBNAME,$LIBSYMBOL,
- [
-- PHP_ADD_LIBRARY_WITH_PATH($LIBNAME, $SSH2_DIR/lib, SSH2_SHARED_LIBADD)
-+ PHP_ADD_LIBRARY_WITH_PATH($LIBNAME, $SSH2_DIR/$PHP_LIBDIR, SSH2_SHARED_LIBADD)
- AC_DEFINE(HAVE_SSH2LIB,1,[Have libssh2])
- ],[
- AC_MSG_ERROR([libssh2 version >= 0.4 not found])
- ],[
-- -L$SSH2_DIR/lib -lm -ldl
-+ -L$SSH2_DIR/$PHP_LIBDIR -lm
- ])
-
- PHP_CHECK_LIBRARY($LIBNAME,libssh2_channel_forward_listen_ex,
-@@ -44,6 +44,8 @@
- AC_DEFINE(PHP_SSH2_REMOTE_FORWARDING, 1, [Have libssh2 with remote forwarding])
- ],[
- AC_MSG_WARN([libssh2 <= 0.4, remote forwarding not enabled])
-+ ],[
-+ -L$SSH2_DIR/$PHP_LIBDIR -lm
- ])
-
- PHP_CHECK_LIBRARY($LIBNAME,libssh2_userauth_hostbased_fromfile_ex,
-@@ -51,6 +53,8 @@
- AC_DEFINE(PHP_SSH2_HOSTBASED_AUTH, 1, [Have libssh2 with hostbased authentication])
- ],[
- AC_MSG_WARN([libssh2 <= 0.6, hostbased authentication not enabled])
-+ ],[
-+ -L$SSH2_DIR/$PHP_LIBDIR -lm
- ])
-
- PHP_CHECK_LIBRARY($LIBNAME,libssh2_poll,
-@@ -58,6 +62,8 @@
- AC_DEFINE(PHP_SSH2_POLL, 1, [Have libssh2 with poll() support])
- ],[
- AC_MSG_WARN([libssh2 <= 0.7, poll support not enabled])
-+ ],[
-+ -L$SSH2_DIR/$PHP_LIBDIR -lm
- ])
-
- PHP_CHECK_LIBRARY($LIBNAME,libssh2_publickey_init,
-@@ -65,6 +71,8 @@
- AC_DEFINE(PHP_SSH2_PUBLICKEY_SUBSYSTEM, 1, [Have libssh2 with publickey subsystem support])
- ],[
- AC_MSG_WARN([libssh2 <= 0.11, publickey subsystem support not enabled])
-+ ],[
-+ -L$SSH2_DIR/$PHP_LIBDIR -lm
- ])
-
- PHP_SUBST(SSH2_SHARED_LIBADD)
|
[-]
[+]
|
Deleted |
ssh2-php53.patch
^
|
@@ -1,10 +0,0 @@
---- ssh2.c.php53 2008-12-14 10:04:22.000000000 +0100
-+++ ssh2.c 2008-12-14 10:04:24.000000000 +0100
-@@ -48,7 +48,6 @@
- #endif
-
- #ifdef ZEND_ENGINE_2
--static
- ZEND_BEGIN_ARG_INFO(php_ssh2_first_arg_force_ref, 0)
- ZEND_ARG_PASS_INFO(1)
- ZEND_END_ARG_INFO()
|
[-]
[+]
|
Deleted |
ssh2-0.10.tgz/ssh2-0.10/config.m4
^
|
@@ -1,73 +0,0 @@
-dnl $Id: config.m4,v 1.7 2005/07/21 20:38:21 pollita Exp $
-dnl config.m4 for extension ssh2
-
-PHP_ARG_WITH(ssh2, for ssh2 support,
-[ --with-ssh2=[DIR] Include ssh2 support])
-
-if test "$PHP_SSH2" != "no"; then
- SEARCH_PATH="/usr/local /usr"
- SEARCH_FOR="/include/libssh2.h"
- if test -r $PHP_SSH2/; then # path given as parameter
- SSH2_DIR=$PHP_SSH2
- else
- AC_MSG_CHECKING([for ssh2 files in default path])
- for i in $SEARCH_PATH ; do
- if test -r $i/$SEARCH_FOR; then
- SSH2_DIR=$i
- AC_MSG_RESULT(found in $i)
- fi
- done
- fi
-
- if test -z "$SSH2_DIR"; then
- AC_MSG_RESULT([not found])
- AC_MSG_ERROR([The required libssh2 library was not found. You can obtain that package from http://sourceforge.net/projects/libssh2/])
- fi
-
- PHP_ADD_INCLUDE($SSH2_DIR/include)
-
- LIBNAME=ssh2
- LIBSYMBOL=libssh2_banner_set
-
- PHP_CHECK_LIBRARY($LIBNAME,$LIBSYMBOL,
- [
- PHP_ADD_LIBRARY_WITH_PATH($LIBNAME, $SSH2_DIR/lib, SSH2_SHARED_LIBADD)
- AC_DEFINE(HAVE_SSH2LIB,1,[Have libssh2])
- ],[
- AC_MSG_ERROR([libssh2 version >= 0.4 not found])
- ],[
- -L$SSH2_DIR/lib -lm -ldl
- ])
-
- PHP_CHECK_LIBRARY($LIBNAME,libssh2_channel_forward_listen_ex,
- [
- AC_DEFINE(PHP_SSH2_REMOTE_FORWARDING, 1, [Have libssh2 with remote forwarding])
- ],[
- AC_MSG_WARN([libssh2 <= 0.4, remote forwarding not enabled])
- ])
-
- PHP_CHECK_LIBRARY($LIBNAME,libssh2_userauth_hostbased_fromfile_ex,
- [
- AC_DEFINE(PHP_SSH2_HOSTBASED_AUTH, 1, [Have libssh2 with hostbased authentication])
- ],[
- AC_MSG_WARN([libssh2 <= 0.6, hostbased authentication not enabled])
- ])
-
- PHP_CHECK_LIBRARY($LIBNAME,libssh2_poll,
- [
- AC_DEFINE(PHP_SSH2_POLL, 1, [Have libssh2 with poll() support])
- ],[
- AC_MSG_WARN([libssh2 <= 0.7, poll support not enabled])
- ])
-
- PHP_CHECK_LIBRARY($LIBNAME,libssh2_publickey_init,
- [
- AC_DEFINE(PHP_SSH2_PUBLICKEY_SUBSYSTEM, 1, [Have libssh2 with publickey subsystem support])
- ],[
- AC_MSG_WARN([libssh2 <= 0.11, publickey subsystem support not enabled])
- ])
-
- PHP_SUBST(SSH2_SHARED_LIBADD)
-
- PHP_NEW_EXTENSION(ssh2, ssh2.c ssh2_fopen_wrappers.c ssh2_sftp.c, $ext_shared)
-fi
|
[-]
[+]
|
Deleted |
ssh2-0.10.tgz/ssh2-0.10/php_ssh2.h
^
|
@@ -1,177 +0,0 @@
-/*
- +----------------------------------------------------------------------+
- | 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: Sara Golemon <pollita@php.net> |
- +----------------------------------------------------------------------+
-
- $Id: php_ssh2.h,v 1.9 2005/11/01 23:31:07 pollita Exp $
-*/
-
-#ifndef PHP_SSH2_H
-#define PHP_SSH2_H
-
-#include <libssh2.h>
-#include <libssh2_sftp.h>
-#include "ext/standard/url.h"
-
-#define PHP_SSH2_VERSION "0.10"
-#define PHP_SSH2_DEFAULT_PORT 22
-
-/* Exported Constants */
-#define PHP_SSH2_FINGERPRINT_MD5 0x0000
-#define PHP_SSH2_FINGERPRINT_SHA1 0x0001
-#define PHP_SSH2_FINGERPRINT_HEX 0x0000
-#define PHP_SSH2_FINGERPRINT_RAW 0x0002
-
-#define PHP_SSH2_TERM_UNIT_CHARS 0x0000
-#define PHP_SSH2_TERM_UNIT_PIXELS 0x0001
-
-#define PHP_SSH2_DEFAULT_TERMINAL "vanilla"
-#define PHP_SSH2_DEFAULT_TERM_WIDTH 80
-#define PHP_SSH2_DEFAULT_TERM_HEIGHT 25
-#define PHP_SSH2_DEFAULT_TERM_UNIT PHP_SSH2_TERM_UNIT_CHARS
-
-#define PHP_SSH2_SESSION_RES_NAME "SSH2 Session"
-#define PHP_SSH2_CHANNEL_STREAM_NAME "SSH2 Channel"
-#define PHP_SSH2_LISTENER_RES_NAME "SSH2 Listener"
-#define PHP_SSH2_SFTP_RES_NAME "SSH2 SFTP"
-#define PHP_SSH2_PKEY_SUBSYS_RES_NAME "SSH2 Publickey Subsystem"
-
-#define PHP_SSH2_SFTP_STREAM_NAME "SSH2 SFTP File"
-#define PHP_SSH2_SFTP_DIRSTREAM_NAME "SSH2 SFTP Directory"
-#define PHP_SSH2_SFTP_WRAPPER_NAME "SSH2 SFTP"
-
-#define PHP_SSH2_LISTEN_MAX_QUEUED 16
-
-#define PHP_SSH2_DEFAULT_POLL_TIMEOUT 30
-
-extern zend_module_entry ssh2_module_entry;
-#define phpext_ssh2_ptr &ssh2_module_entry
-
-typedef struct _php_ssh2_session_data {
- /* Userspace callback functions */
- zval *ignore_cb;
- zval *debug_cb;
- zval *macerror_cb;
- zval *disconnect_cb;
-
- int socket;
-
-#ifdef ZTS
- /* Avoid unnecessary TSRMLS_FETCH() calls */
- TSRMLS_D;
-#endif
-} php_ssh2_session_data;
-
-typedef struct _php_ssh2_sftp_data {
- LIBSSH2_SESSION *session;
- LIBSSH2_SFTP *sftp;
-
- int session_rsrcid;
-} php_ssh2_sftp_data;
-
-#ifdef PHP_SSH2_REMOTE_FORWARDING
-typedef struct _php_ssh2_listener_data {
- LIBSSH2_SESSION *session;
- LIBSSH2_LISTENER *listener;
-
- int session_rsrcid;
-} php_ssh2_listener_data;
-#endif
-
-#ifdef PHP_SSH2_PUBLICKEY_SUBSYSTEM
-#include "libssh2_publickey.h"
-
-typedef struct _php_ssh2_pkey_subsys_data {
- LIBSSH2_SESSION *session;
- LIBSSH2_PUBLICKEY *pkey;
-
- int session_rsrcid;
-} php_ssh2_pkey_subsys_data;
-#endif
-
-#ifdef ZTS
-#define SSH2_TSRMLS_SET(datap) ((php_ssh2_session_data*)(datap))->tsrm_ls = TSRMLS_C
-#define SSH2_TSRMLS_FETCH(datap) TSRMLS_D = ((php_ssh2_session_data*)(datap))->tsrm_ls
-#else
-#define SSH2_TSRMLS_SET(datap)
-#define SSH2_TSRMLS_FETCH(datap)
-#endif
-
-
-typedef struct _php_ssh2_channel_data {
- LIBSSH2_CHANNEL *channel;
-
- /* Distinguish which stream we should read/write from/to */
- unsigned int streamid;
- char is_blocking;
-
- /* Resource ID, zend_list_addref() when opening, zend_list_delete() when closing */
- long session_rsrc;
-
- /* Allow one stream to be closed while the other is kept open */
- unsigned char *refcount;
-
-} php_ssh2_channel_data;
-
-/* In ssh2_fopen_wrappers.c */
-PHP_FUNCTION(ssh2_shell);
-PHP_FUNCTION(ssh2_exec);
-PHP_FUNCTION(ssh2_tunnel);
-PHP_FUNCTION(ssh2_scp_recv);
-PHP_FUNCTION(ssh2_scp_send);
-PHP_FUNCTION(ssh2_fetch_stream);
-
-/* In ssh2_sftp.c */
-PHP_FUNCTION(ssh2_sftp);
-
-PHP_FUNCTION(ssh2_sftp_rename);
-PHP_FUNCTION(ssh2_sftp_unlink);
-PHP_FUNCTION(ssh2_sftp_mkdir);
-PHP_FUNCTION(ssh2_sftp_rmdir);
-PHP_FUNCTION(ssh2_sftp_stat);
-PHP_FUNCTION(ssh2_sftp_lstat);
-PHP_FUNCTION(ssh2_sftp_symlink);
-PHP_FUNCTION(ssh2_sftp_readlink);
-PHP_FUNCTION(ssh2_sftp_realpath);
-
-LIBSSH2_SESSION *php_ssh2_session_connect(char *host, int port, zval *methods, zval *callbacks TSRMLS_DC);
-void php_ssh2_sftp_dtor(zend_rsrc_list_entry *rsrc TSRMLS_DC);
-php_url *php_ssh2_fopen_wraper_parse_path( char *path, char *type, php_stream_context *context,
- LIBSSH2_SESSION **psession, int *presource_id,
- LIBSSH2_SFTP **psftp, int *psftp_rsrcid
- TSRMLS_DC);
-
-extern php_stream_ops php_ssh2_channel_stream_ops;
-
-extern php_stream_wrapper php_ssh2_stream_wrapper_shell;
-extern php_stream_wrapper php_ssh2_stream_wrapper_exec;
-extern php_stream_wrapper php_ssh2_stream_wrapper_tunnel;
-extern php_stream_wrapper php_ssh2_stream_wrapper_scp;
-extern php_stream_wrapper php_ssh2_sftp_wrapper;
-
-/* Resource list entries */
-extern int le_ssh2_session;
-extern int le_ssh2_sftp;
-
-#endif /* PHP_SSH2_H */
-
-
-/*
- * Local variables:
- * tab-width: 4
- * c-basic-offset: 4
- * indent-tabs-mode: t
- * End:
- */
|
[-]
[+]
|
Deleted |
ssh2-0.10.tgz/ssh2-0.10/ssh2.c
^
|
@@ -1,1353 +0,0 @@
-/*
- +----------------------------------------------------------------------+
- | PHP Version 4 |
- +----------------------------------------------------------------------+
- | 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: Sara Golemon <pollita@php.net> |
- +----------------------------------------------------------------------+
-
- $Id: ssh2.c,v 1.14 2005/11/01 23:40:23 pollita Exp $
-*/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "php.h"
-#include "ext/standard/info.h"
-#include "php_ssh2.h"
-#include "main/php_network.h"
-
-/* Internal Constants */
-#ifndef SHA_DIGEST_LENGTH
-#define SHA_DIGEST_LENGTH 20
-#endif
-
-#ifndef MD5_DIGEST_LENGTH
-#define MD5_DIGEST_LENGTH 16
-#endif
-
-/* True global resources - no need for thread safety here */
-int le_ssh2_session;
-#ifdef PHP_SSH2_REMOTE_FORWARDING
-int le_ssh2_listener;
-#endif
-int le_ssh2_sftp;
-#ifdef PHP_SSH2_PUBLICKEY_SUBSYSTEM
-int le_ssh2_pkey_subsys;
-#endif
-
-#ifdef ZEND_ENGINE_2
-static
- ZEND_BEGIN_ARG_INFO(php_ssh2_first_arg_force_ref, 0)
- ZEND_ARG_PASS_INFO(1)
- ZEND_END_ARG_INFO()
-#else
-static unsigned char php_ssh2_first_arg_force_ref[] = { 1, BYREF_FORCE };
-#endif
-
-/* *************
- * Callbacks *
- ************* */
-
-#ifdef ZTS
-#define PHP_SSH2_TSRMLS_FETCH() TSRMLS_D = *(void****)abstract;
-#else
-#define PHP_SSH2_TSRMLS_FETCH()
-#endif
-
-/* {{{ php_ssh2_alloc_cb
- * Wrap emalloc()
- */
-static LIBSSH2_ALLOC_FUNC(php_ssh2_alloc_cb)
-{
- return emalloc(count);
-}
-/* }}} */
-
-/* {{{ php_ssh2_free_cb
- * Wrap efree()
- */
-static LIBSSH2_FREE_FUNC(php_ssh2_free_cb)
-{
- efree(ptr);
-}
-/* }}} */
-
-/* {{{ php_ssh2_realloc_cb
- * Wrap erealloc()
- */
-static LIBSSH2_REALLOC_FUNC(php_ssh2_realloc_cb)
-{
- return erealloc(ptr, count);
-}
-/* }}} */
-
-/* {{{ php_ssh2_debug_cb
- * Debug packets
- */
-LIBSSH2_DEBUG_FUNC(php_ssh2_debug_cb)
-{
- php_ssh2_session_data *data;
- zval *zdisplay, *zmessage, *zlanguage;
- zval **args[3];
- SSH2_TSRMLS_FETCH(*abstract);
-
- if (!abstract || !*abstract) {
- return;
- }
- data = (php_ssh2_session_data*)*abstract;
- if (!data->debug_cb) {
- return;
- }
-
- MAKE_STD_ZVAL(zmessage);
- ZVAL_STRINGL(zmessage, (char*)message, message_len, 1);
- args[0] = &zmessage;
-
- MAKE_STD_ZVAL(zlanguage);
- ZVAL_STRINGL(zlanguage, (char*)language, language_len, 1);
- args[1] = &zlanguage;
-
- MAKE_STD_ZVAL(zdisplay);
- ZVAL_LONG(zdisplay, always_display);
- args[2] = &zdisplay;
-
- if (FAILURE == call_user_function_ex(NULL, NULL, data->disconnect_cb, NULL, 3, args, 0, NULL TSRMLS_CC)) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failure calling disconnect callback");
- }
- zval_ptr_dtor(&zdisplay);
- zval_ptr_dtor(&zmessage);
- zval_ptr_dtor(&zlanguage);
-}
-/* }}} */
-
-/* {{{ php_ssh2_ignore_cb
- * Ignore packets
- */
-LIBSSH2_IGNORE_FUNC(php_ssh2_ignore_cb)
-{
- php_ssh2_session_data *data;
- zval *zretval = NULL, *zmessage;
- zval **args[1];
- SSH2_TSRMLS_FETCH(*abstract);
-
- if (!abstract || !*abstract) {
- return;
- }
- data = (php_ssh2_session_data*)*abstract;
- if (!data->ignore_cb) {
- return;
- }
-
- MAKE_STD_ZVAL(zmessage);
- ZVAL_STRINGL(zmessage, (char*)message, message_len, 1);
- args[0] = &zmessage;
-
- if (FAILURE == call_user_function_ex(NULL, NULL, data->ignore_cb, &zretval, 1, args, 0, NULL TSRMLS_CC)) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failure calling ignore callback");
- }
- zval_ptr_dtor(&zmessage);
- if (zretval) {
- zval_ptr_dtor(&zretval);
- }
-}
-/* }}} */
-
-/* {{{ php_ssh2_macerror_cb
- * Called when a MAC error occurs, offers the chance to ignore
- * WHY ARE YOU IGNORING MAC ERRORS??????
- */
-LIBSSH2_MACERROR_FUNC(php_ssh2_macerror_cb)
-{
- php_ssh2_session_data *data;
- zval *zretval = NULL, *zpacket;
- zval **args[1];
- int retval = -1;
- SSH2_TSRMLS_FETCH(*abstract);
-
- if (!abstract || !*abstract) {
- return -1;
- }
- data = (php_ssh2_session_data*)*abstract;
- if (!data->macerror_cb) {
- return -1;
- }
-
- MAKE_STD_ZVAL(zpacket);
- ZVAL_STRINGL(zpacket, (char*)packet, packet_len, 1);
- args[0] = &zpacket;
-
- if (FAILURE == call_user_function_ex(NULL, NULL, data->macerror_cb, &zretval, 1, args, 0, NULL TSRMLS_CC)) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failure calling macerror callback");
- } else {
- retval = zval_is_true(zretval) ? 0 : -1;
- }
- zval_ptr_dtor(&zpacket);
- if (zretval) {
- zval_ptr_dtor(&zretval);
- }
-
- return retval;
-}
-/* }}} */
-
-/* {{{ php_ssh2_disconnect_cb
- * Connection closed by foreign host
- */
-LIBSSH2_DISCONNECT_FUNC(php_ssh2_disconnect_cb)
-{
- php_ssh2_session_data *data;
- zval *zreason, *zmessage, *zlanguage;
- zval **args[3];
- SSH2_TSRMLS_FETCH(*abstract);
-
- if (!abstract || !*abstract) {
- return;
- }
- data = (php_ssh2_session_data*)*abstract;
- if (!data->disconnect_cb) {
- return;
- }
-
- MAKE_STD_ZVAL(zreason);
- ZVAL_LONG(zreason, reason);
- args[0] = &zreason;
-
- MAKE_STD_ZVAL(zmessage);
- ZVAL_STRINGL(zmessage, (char*)message, message_len, 1);
- args[1] = &zmessage;
-
- MAKE_STD_ZVAL(zlanguage);
- ZVAL_STRINGL(zlanguage, (char*)language, language_len, 1);
- args[2] = &zlanguage;
-
- if (FAILURE == call_user_function_ex(NULL, NULL, data->disconnect_cb, NULL, 3, args, 0, NULL TSRMLS_CC)) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failure calling disconnect callback");
- }
- zval_ptr_dtor(&zreason);
- zval_ptr_dtor(&zmessage);
- zval_ptr_dtor(&zlanguage);
-}
-/* }}} */
-
-/* *****************
- * Userspace API *
- ***************** */
-
-/* {{{ php_ssh2_set_callback
- * Try to set a method if it's passed in with the hash table
- */
-static int php_ssh2_set_callback(LIBSSH2_SESSION *session, HashTable *ht, char *callback, int callback_len, int callback_type, php_ssh2_session_data *data)
-{
- zval **handler, *copyval;
- void *internal_handler;
-
- if (zend_hash_find(ht, callback, callback_len + 1, (void**)&handler) == FAILURE) {
- return 0;
- }
-
- if (!handler || !*handler || !zend_is_callable(*handler, 0, NULL)) {
- return -1;
- }
-
- ALLOC_INIT_ZVAL(copyval);
- *copyval = **handler;
- zval_copy_ctor(copyval);
-
- switch (callback_type) {
- case LIBSSH2_CALLBACK_IGNORE:
- internal_handler = php_ssh2_ignore_cb;
- if (data->ignore_cb) {
- zval_ptr_dtor(&data->ignore_cb);
- }
- data->ignore_cb = copyval;
- break;
- case LIBSSH2_CALLBACK_DEBUG:
- internal_handler = php_ssh2_debug_cb;
- if (data->debug_cb) {
- zval_ptr_dtor(&data->debug_cb);
- }
- data->debug_cb = copyval;
- break;
- case LIBSSH2_CALLBACK_MACERROR:
- internal_handler = php_ssh2_macerror_cb;
- if (data->macerror_cb) {
- zval_ptr_dtor(&data->macerror_cb);
- }
- data->macerror_cb = copyval;
- break;
- case LIBSSH2_CALLBACK_DISCONNECT:
- internal_handler = php_ssh2_disconnect_cb;
- if (data->disconnect_cb) {
- zval_ptr_dtor(&data->disconnect_cb);
- }
- data->disconnect_cb = copyval;
- break;
- default:
- zval_ptr_dtor(©val);
- return -1;
- }
-
- libssh2_session_callback_set(session, callback_type, internal_handler);
-
- return 0;
-}
-/* }}} */
-
-/* {{{ php_ssh2_set_method
- * Try to set a method if it's passed in with the hash table
- */
-static int php_ssh2_set_method(LIBSSH2_SESSION *session, HashTable *ht, char *method, int method_len, int method_type)
-{
- zval **value;
-
- if (zend_hash_find(ht, method, method_len + 1, (void**)&value) == FAILURE) {
- return 0;
- }
-
- if (!value || !*value || (Z_TYPE_PP(value) != IS_STRING)) {
- return -1;
- }
-
- return libssh2_session_method_pref(session, method_type, Z_STRVAL_PP(value));
-}
-/* }}} */
-
-/* {{{ php_ssh2_session_connect
- * Connect to an SSH server with requested methods
- */
-LIBSSH2_SESSION *php_ssh2_session_connect(char *host, int port, zval *methods, zval *callbacks TSRMLS_DC)
-{
- LIBSSH2_SESSION *session;
- int socket;
- php_ssh2_session_data *data;
-
-#if PHP_MAJOR_VERSION > 5 || (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION > 0)
- socket = php_network_connect_socket_to_host(host, port, SOCK_STREAM, 0, NULL, NULL, NULL, NULL, 0 TSRMLS_CC);
-#elif PHP_MAJOR_VERSION == 5
- socket = php_network_connect_socket_to_host(host, port, SOCK_STREAM, 0, NULL, NULL, NULL TSRMLS_CC);
-#else
- socket = php_hostconnect(host, port, SOCK_STREAM, NULL TSRMLS_CC);
-#endif
-
- if (socket <= 0) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to connect to %s on port %d", host, port);
- return NULL;
- }
-
- data = ecalloc(1, sizeof(php_ssh2_session_data));
- SSH2_TSRMLS_SET(data);
- data->socket = socket;
-
- session = libssh2_session_init_ex(php_ssh2_alloc_cb, php_ssh2_free_cb, php_ssh2_realloc_cb, data);
- if (!session) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to initialize SSH2 session");
- efree(data);
- close(socket);
- return NULL;
- }
- libssh2_banner_set(session, LIBSSH2_SSH_DEFAULT_BANNER " PHP");
-
- /* Override method preferences */
- if (methods) {
- zval **container;
-
- if (php_ssh2_set_method(session, HASH_OF(methods), "kex", sizeof("kex") - 1, LIBSSH2_METHOD_KEX)) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed overriding KEX method");
- }
- if (php_ssh2_set_method(session, HASH_OF(methods), "hostkey", sizeof("hostkey") - 1, LIBSSH2_METHOD_HOSTKEY)) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed overriding HOSTKEY method");
- }
-
- if (zend_hash_find(HASH_OF(methods), "client_to_server", sizeof("client_to_server"), (void**)&container) == SUCCESS &&
- container && *container && Z_TYPE_PP(container) == IS_ARRAY) {
- if (php_ssh2_set_method(session, HASH_OF(*container), "crypt", sizeof("crypt") - 1, LIBSSH2_METHOD_CRYPT_CS)) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed overriding client to server CRYPT method");
- }
- if (php_ssh2_set_method(session, HASH_OF(*container), "mac", sizeof("mac") - 1, LIBSSH2_METHOD_MAC_CS)) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed overriding client to server MAC method");
- }
- if (php_ssh2_set_method(session, HASH_OF(*container), "comp", sizeof("comp") - 1, LIBSSH2_METHOD_COMP_CS)) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed overriding client to server COMP method");
- }
- if (php_ssh2_set_method(session, HASH_OF(*container), "lang", sizeof("lang") - 1, LIBSSH2_METHOD_LANG_CS)) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed overriding client to server LANG method");
- }
- }
-
- if (zend_hash_find(HASH_OF(methods), "server_to_client", sizeof("server_to_client"), (void**)&container) == SUCCESS &&
- container && *container && Z_TYPE_PP(container) == IS_ARRAY) {
- if (php_ssh2_set_method(session, HASH_OF(*container), "crypt", sizeof("crypt") - 1, LIBSSH2_METHOD_CRYPT_SC)) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed overriding server to client CRYPT method");
- }
- if (php_ssh2_set_method(session, HASH_OF(*container), "mac", sizeof("mac") - 1, LIBSSH2_METHOD_MAC_SC)) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed overriding server to client MAC method");
- }
- if (php_ssh2_set_method(session, HASH_OF(*container), "comp", sizeof("comp") - 1, LIBSSH2_METHOD_COMP_SC)) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed overriding server to client COMP method");
- }
- if (php_ssh2_set_method(session, HASH_OF(*container), "lang", sizeof("lang") - 1, LIBSSH2_METHOD_LANG_SC)) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed overriding server to client LANG method");
- }
- }
- }
-
- /* Register Callbacks */
- if (callbacks) {
- /* ignore debug disconnect macerror */
-
- if (php_ssh2_set_callback(session, HASH_OF(callbacks), "ignore", sizeof("ignore") - 1, LIBSSH2_CALLBACK_IGNORE, data)) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed setting IGNORE callback");
- }
-
- if (php_ssh2_set_callback(session, HASH_OF(callbacks), "debug", sizeof("debug") - 1, LIBSSH2_CALLBACK_DEBUG, data)) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed setting DEBUG callback");
- }
-
- if (php_ssh2_set_callback(session, HASH_OF(callbacks), "macerror", sizeof("macerror") - 1, LIBSSH2_CALLBACK_MACERROR, data)) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed setting MACERROR callback");
- }
-
- if (php_ssh2_set_callback(session, HASH_OF(callbacks), "disconnect", sizeof("disconnect") - 1, LIBSSH2_CALLBACK_DISCONNECT, data)) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed setting DISCONNECT callback");
- }
- }
-
- if (libssh2_session_startup(session, socket)) {
- int last_error = 0;
- char *error_msg = NULL;
-
- last_error = libssh2_session_last_error(session, &error_msg, NULL, 0);
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error starting up SSH connection(%d): %s", last_error, error_msg);
- close(socket);
- libssh2_session_free(session);
- efree(data);
- return NULL;
- }
-
- return session;
-}
-/* }}} */
-
-/* {{{ proto resource ssh2_connect(string host[, int port[, array methods[, array callbacks]]])
- * Establish a connection to a remote SSH server and return a resource on success, false on error
- */
-PHP_FUNCTION(ssh2_connect)
-{
- LIBSSH2_SESSION *session;
- zval *methods = NULL, *callbacks = NULL;
- char *host;
- long port = PHP_SSH2_DEFAULT_PORT;
- int host_len;
-
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|la!a!", &host, &host_len, &port, &methods, &callbacks) == FAILURE) {
- RETURN_FALSE;
- }
-
- session = php_ssh2_session_connect(host, port, methods, callbacks TSRMLS_CC);
- if (!session) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to connect to %s", host);
- RETURN_FALSE;
- }
-
- ZEND_REGISTER_RESOURCE(return_value, session, le_ssh2_session);
-}
-/* }}} */
-
-/* {{{ proto array ssh2_methods_negotiated(resource session)
- * Return list of negotiaed methods
- */
-PHP_FUNCTION(ssh2_methods_negotiated)
-{
- LIBSSH2_SESSION *session;
- zval *zsession, *endpoint;
- char *kex, *hostkey, *crypt_cs, *crypt_sc, *mac_cs, *mac_sc, *comp_cs, *comp_sc, *lang_cs, *lang_sc;
-
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zsession) == FAILURE) {
- RETURN_FALSE;
- }
-
- ZEND_FETCH_RESOURCE(session, LIBSSH2_SESSION*, &zsession, -1, PHP_SSH2_SESSION_RES_NAME, le_ssh2_session);
-
-#if LIBSSH2_APINO < 200412301450
- libssh2_session_methods(session, &kex, &hostkey, &crypt_cs, &crypt_sc, &mac_cs, &mac_sc, &comp_cs, &comp_sc, &lang_cs, &lang_sc);
-#else
- kex = libssh2_session_methods(session, LIBSSH2_METHOD_KEX);
- hostkey = libssh2_session_methods(session, LIBSSH2_METHOD_HOSTKEY);
- crypt_cs = libssh2_session_methods(session, LIBSSH2_METHOD_CRYPT_CS);
- crypt_sc = libssh2_session_methods(session, LIBSSH2_METHOD_CRYPT_SC);
- mac_cs = libssh2_session_methods(session, LIBSSH2_METHOD_MAC_CS);
- mac_sc = libssh2_session_methods(session, LIBSSH2_METHOD_MAC_SC);
- comp_cs = libssh2_session_methods(session, LIBSSH2_METHOD_COMP_CS);
- comp_sc = libssh2_session_methods(session, LIBSSH2_METHOD_COMP_SC);
- lang_cs = libssh2_session_methods(session, LIBSSH2_METHOD_LANG_CS);
- lang_sc = libssh2_session_methods(session, LIBSSH2_METHOD_LANG_SC);
-#endif
-
- array_init(return_value);
- add_assoc_string(return_value, "kex", kex, 1);
- add_assoc_string(return_value, "hostkey", hostkey, 1);
-
- ALLOC_INIT_ZVAL(endpoint);
- array_init(endpoint);
- add_assoc_string(endpoint, "crypt", crypt_cs, 1);
- add_assoc_string(endpoint, "mac", mac_cs, 1);
- add_assoc_string(endpoint, "comp", comp_cs, 1);
- add_assoc_string(endpoint, "lang", lang_cs, 1);
- add_assoc_zval(return_value, "client_to_server", endpoint);
-
- ALLOC_INIT_ZVAL(endpoint);
- array_init(endpoint);
- add_assoc_string(endpoint, "crypt", crypt_sc, 1);
- add_assoc_string(endpoint, "mac", mac_sc, 1);
- add_assoc_string(endpoint, "comp", comp_sc, 1);
- add_assoc_string(endpoint, "lang", lang_sc, 1);
- add_assoc_zval(return_value, "server_to_client", endpoint);
-}
-/* }}} */
-
-/* {{{ proto string ssh2_fingerprint(resource session[, int flags])
- * Returns a server hostkey hash from an active session
- * Defaults to MD5 fingerprint encoded as ASCII hex values
- */
-PHP_FUNCTION(ssh2_fingerprint)
-{
- LIBSSH2_SESSION *session;
- zval *zsession;
- char *fingerprint;
- long flags = 0;
- int i, fingerprint_len;
-
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|l", &zsession, &flags) == FAILURE) {
- RETURN_FALSE;
- }
- fingerprint_len = (flags & PHP_SSH2_FINGERPRINT_SHA1) ? SHA_DIGEST_LENGTH : MD5_DIGEST_LENGTH;
-
- ZEND_FETCH_RESOURCE(session, LIBSSH2_SESSION*, &zsession, -1, PHP_SSH2_SESSION_RES_NAME, le_ssh2_session);
-
- fingerprint = libssh2_hostkey_hash(session, (flags & PHP_SSH2_FINGERPRINT_SHA1) ? LIBSSH2_HOSTKEY_HASH_SHA1 : LIBSSH2_HOSTKEY_HASH_MD5);
- if (!fingerprint) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to retreive fingerprint from specified session");
- RETURN_FALSE;
- }
-
- for(i = 0; i < fingerprint_len; i++) {
- if (fingerprint[i] != '\0') {
- goto fingerprint_good;
- }
- }
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "No fingerprint available using specified hash");
- RETURN_NULL();
- fingerprint_good:
- if (flags & PHP_SSH2_FINGERPRINT_RAW) {
- RETURN_STRINGL(fingerprint, fingerprint_len, 1);
- } else {
- char *hexchars;
-
- hexchars = emalloc((fingerprint_len * 2) + 1);
- for(i = 0; i < fingerprint_len; i++) {
- snprintf(hexchars + (2 * i), 3, "%02X", (unsigned char)fingerprint[i]);
- }
- RETURN_STRINGL(hexchars, 2 * fingerprint_len, 0);
- }
-}
-/* }}} */
-
-/* {{{ proto array ssh2_auth_none(resource session, string username)
- * Attempt "none" authentication, returns a list of allowed methods on failed authentication,
- * false on utter failure, or true on success
- */
-PHP_FUNCTION(ssh2_auth_none)
-{
- LIBSSH2_SESSION *session;
- zval *zsession;
- char *username, *methods, *s, *p;
- int username_len;
-
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &zsession, &username, &username_len) == FAILURE) {
- RETURN_FALSE;
- }
-
- ZEND_FETCH_RESOURCE(session, LIBSSH2_SESSION*, &zsession, -1, PHP_SSH2_SESSION_RES_NAME, le_ssh2_session);
-
- s = methods = libssh2_userauth_list(session, username, username_len);
- if (!methods) {
- /* Either bad failure, or unexpected success */
- RETURN_BOOL(libssh2_userauth_authenticated(session));
- }
-
- array_init(return_value);
- while ((p = strchr(s, ','))) {
- if ((p - s) > 0) {
- add_next_index_stringl(return_value, s, p - s, 1);
- }
- s = p + 1;
- }
- if (strlen(s)) {
- add_next_index_string(return_value, s, 1);
- }
- efree(methods);
-}
-/* }}} */
-
-/* {{{ proto bool ssh2_auth_password(resource session, string username, string password)
- * Authenticate over SSH using a plain password
- */
-PHP_FUNCTION(ssh2_auth_password)
-{
- LIBSSH2_SESSION *session;
- zval *zsession;
- char *username, *password;
- int username_len, password_len;
-
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rss", &zsession, &username, &username_len, &password, &password_len) == FAILURE) {
- RETURN_FALSE;
- }
-
- ZEND_FETCH_RESOURCE(session, LIBSSH2_SESSION*, &zsession, -1, PHP_SSH2_SESSION_RES_NAME, le_ssh2_session);
-
- /* TODO: Support password change callback */
- if (libssh2_userauth_password_ex(session, username, username_len, password, password_len, NULL)) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Authentication failed for %s using password", username);
- RETURN_FALSE;
- }
-
- RETURN_TRUE;
-}
-/* }}} */
-
-/* {{{ proto bool ssh2_auth_pubkey_file(resource session, string username, string pubkeyfile, string privkeyfile[, string passphrase])
- * Authenticate using a public key
- */
-PHP_FUNCTION(ssh2_auth_pubkey_file)
-{
- LIBSSH2_SESSION *session;
- zval *zsession;
- char *username, *pubkey, *privkey, *passphrase = NULL;
- int username_len, pubkey_len, privkey_len, passphrase_len;
-
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rsss|s", &zsession, &username, &username_len,
- &pubkey, &pubkey_len,
- &privkey, &privkey_len,
- &passphrase, &passphrase_len) == FAILURE) {
- RETURN_FALSE;
- }
-
- if (PG(safe_mode) && !php_checkuid(pubkey, NULL, CHECKUID_CHECK_FILE_AND_DIR)) {
- RETURN_FALSE;
- }
- if (PG(safe_mode) && !php_checkuid(privkey, NULL, CHECKUID_CHECK_FILE_AND_DIR)) {
- RETURN_FALSE;
- }
-
- if (php_check_open_basedir(pubkey TSRMLS_CC)) {
- RETURN_FALSE;
- }
- if (php_check_open_basedir(privkey TSRMLS_CC)) {
- RETURN_FALSE;
- }
-
- ZEND_FETCH_RESOURCE(session, LIBSSH2_SESSION*, &zsession, -1, PHP_SSH2_SESSION_RES_NAME, le_ssh2_session);
-
- /* TODO: Support passphrase callback */
- if (libssh2_userauth_publickey_fromfile_ex(session, username, username_len, pubkey, privkey, passphrase)) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Authentication failed for %s using public key", username);
- RETURN_FALSE;
- }
-
- RETURN_TRUE;
-}
-/* }}} */
-
-#ifdef PHP_SSH2_HOSTBASED_AUTH
-/* {{{ proto bool ssh2_auth_hostbased_file(resource session, string username, string local_hostname, string pubkeyfile, string privkeyfile[, string passphrase[, string local_username]])
- * Authenticate using a hostkey
- */
-PHP_FUNCTION(ssh2_auth_hostbased_file)
-{
- LIBSSH2_SESSION *session;
- zval *zsession;
- char *username, *hostname, *pubkey, *privkey, *passphrase = NULL, *local_username = NULL;
- int username_len, hostname_len, pubkey_len, privkey_len, passphrase_len, local_username_len;
-
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rssss|s!s!", &zsession, &username, &username_len,
- &hostname, &hostname_len,
- &pubkey, &pubkey_len,
- &privkey, &privkey_len,
- &passphrase, &passphrase_len,
- &local_username, &local_username_len) == FAILURE) {
- RETURN_FALSE;
- }
-
- if (PG(safe_mode) && !php_checkuid(pubkey, NULL, CHECKUID_CHECK_FILE_AND_DIR)) {
- RETURN_FALSE;
- }
- if (PG(safe_mode) && !php_checkuid(privkey, NULL, CHECKUID_CHECK_FILE_AND_DIR)) {
- RETURN_FALSE;
- }
-
- if (php_check_open_basedir(pubkey TSRMLS_CC)) {
- RETURN_FALSE;
- }
- if (php_check_open_basedir(privkey TSRMLS_CC)) {
- RETURN_FALSE;
- }
-
- ZEND_FETCH_RESOURCE(session, LIBSSH2_SESSION*, &zsession, -1, PHP_SSH2_SESSION_RES_NAME, le_ssh2_session);
-
- if (!local_username) {
- local_username = username;
- local_username_len = username_len;
- }
-
- /* TODO: Support passphrase callback */
- if (libssh2_userauth_hostbased_fromfile_ex(session, username, username_len, pubkey, privkey, passphrase, hostname, hostname_len, local_username, local_username_len)) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Authentication failed for %s using hostbased public key", username);
- RETURN_FALSE;
- }
-
- RETURN_TRUE;
-}
-/* }}} */
-#endif /* PHP_SSH2_HOSTBASED_AUTH */
-
-#ifdef PHP_SSH2_REMOTE_FORWARDING
-/* {{{ proto resource ssh2_forward_listen(resource session, int port[, string host[, long max_connections]])
- * Bind a port on the remote server and listen for connections
- */
-PHP_FUNCTION(ssh2_forward_listen)
-{
- zval *zsession;
- LIBSSH2_SESSION *session;
- LIBSSH2_LISTENER *listener;
- php_ssh2_listener_data *data;
- long port;
- char *host = NULL;
- int host_len;
- long max_connections = PHP_SSH2_LISTEN_MAX_QUEUED;
-
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl|sl", &zsession, &port, &host, &host_len, &max_connections) == FAILURE) {
- RETURN_FALSE;
- }
-
- ZEND_FETCH_RESOURCE(session, LIBSSH2_SESSION*, &zsession, -1, PHP_SSH2_SESSION_RES_NAME, le_ssh2_session);
-
- listener = libssh2_channel_forward_listen_ex(session, host, port, NULL, max_connections);
-
- if (!listener) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failure listening on remote port");
- RETURN_FALSE;
- }
-
- data = emalloc(sizeof(php_ssh2_listener_data));
- data->session = session;
- data->session_rsrcid = Z_LVAL_P(zsession);
- zend_list_addref(data->session_rsrcid);
- data->listener = listener;
-
- ZEND_REGISTER_RESOURCE(return_value, data, le_ssh2_listener);
-}
-/* }}} */
-
-/* {{{ proto stream ssh2_forward_accept(resource listener[, string &shost[, long &sport]])
- * Accept a connection created by a listener
- */
-PHP_FUNCTION(ssh2_forward_accept)
-{
- zval *zlistener;
- php_ssh2_listener_data *data;
- LIBSSH2_CHANNEL *channel;
- php_ssh2_channel_data *channel_data;
- php_stream *stream;
-
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zlistener) == FAILURE) {
- RETURN_FALSE;
- }
-
- ZEND_FETCH_RESOURCE(data, php_ssh2_listener_data*, &zlistener, -1, PHP_SSH2_LISTENER_RES_NAME, le_ssh2_listener);
-
- channel = libssh2_channel_forward_accept(data->listener);
-
- if (!channel) {
- RETURN_FALSE;
- }
-
- channel_data = emalloc(sizeof(php_ssh2_channel_data));
- channel_data->channel = channel;
- channel_data->streamid = 0;
- channel_data->is_blocking = 0;
- channel_data->session_rsrc = data->session_rsrcid;
- channel_data->refcount = NULL;
-
- stream = php_stream_alloc(&php_ssh2_channel_stream_ops, channel_data, 0, "r+");
- if (!stream) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failure allocating stream");
- efree(channel_data);
- libssh2_channel_free(channel);
- RETURN_FALSE;
- }
- zend_list_addref(channel_data->session_rsrc);
-
- php_stream_to_zval(stream, return_value);
-}
-/* }}} */
-#endif /* PHP_SSH2_REMOTE_FORWARDING */
-
-#ifdef PHP_SSH2_POLL
-/* {{{ proto int ssh2_poll(array &polldes[, int timeout])
- * Poll the channels/listeners/streams for events
- * Returns number of descriptors which returned non-zero revents
- * Input array should be of the form:
- * array(
- * 0 => array(
- * [resource] => $channel,$listener, or $stream
- * [events] => SSH2_POLL* flags bitwise ORed together
- * ),
- * 1 => ...
- * )
- * Each subarray will be populated with an revents element on return
- */
-PHP_FUNCTION(ssh2_poll)
-{
- zval *zdesc, **subarray;
- long timeout = PHP_SSH2_DEFAULT_POLL_TIMEOUT;
- LIBSSH2_POLLFD *pollfds;
- int numfds, i = 0, fds_ready;
- int le_stream = php_file_le_stream();
- int le_pstream = php_file_le_pstream();
- zval ***pollmap;
-
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a|l", &zdesc, &timeout) == FAILURE) {
- RETURN_NULL();
- }
-
- numfds = zend_hash_num_elements(Z_ARRVAL_P(zdesc));
- pollfds = safe_emalloc(sizeof(LIBSSH2_POLLFD), numfds, 0);
- pollmap = safe_emalloc(sizeof(zval**), numfds, 0);
-
- for(zend_hash_internal_pointer_reset(Z_ARRVAL_P(zdesc));
- zend_hash_get_current_data(Z_ARRVAL_P(zdesc), (void**)&subarray) == SUCCESS;
- zend_hash_move_forward(Z_ARRVAL_P(zdesc))) {
- zval **tmpzval;
- int res_type = 0;
- void *res;
-
- if (Z_TYPE_PP(subarray) != IS_ARRAY) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid element in poll array, not a sub array");
- numfds--;
- continue;
- }
- if (zend_hash_find(Z_ARRVAL_PP(subarray), "events", sizeof("events"), (void**)&tmpzval) == FAILURE ||
- Z_TYPE_PP(tmpzval) != IS_LONG) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid data in subarray, no events element, or not a bitmask");
- numfds--;
- continue;
- }
- pollfds[i].events = Z_LVAL_PP(tmpzval);
- if (zend_hash_find(Z_ARRVAL_PP(subarray), "resource", sizeof("resource"), (void**)&tmpzval) == FAILURE ||
- Z_TYPE_PP(tmpzval) != IS_RESOURCE) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid data in subarray, no resource element, or not of type resource");
- numfds--;
- continue;
- }
- zend_list_find(Z_LVAL_PP(tmpzval), &res_type);
- res = zend_fetch_resource(tmpzval TSRMLS_CC, -1, "Poll Resource", NULL, 1, res_type);
- if (res_type == le_ssh2_listener) {
- pollfds[i].type = LIBSSH2_POLLFD_LISTENER;
- pollfds[i].fd.listener = ((php_ssh2_listener_data*)res)->listener;
- } else if ((res_type == le_stream || res_type == le_pstream) &&
- ((php_stream*)res)->ops == &php_ssh2_channel_stream_ops) {
- pollfds[i].type = LIBSSH2_POLLFD_CHANNEL;
- pollfds[i].fd.channel = ((php_ssh2_channel_data*)(((php_stream*)res)->abstract))->channel;
- /* TODO: Add the ability to select against other stream types */
- } else {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid resource type in subarray: %s", zend_rsrc_list_get_rsrc_type(Z_LVAL_PP(tmpzval) TSRMLS_CC));
- numfds--;
- continue;
- }
- pollmap[i] = subarray;
- i++;
- }
-
- fds_ready = libssh2_poll(pollfds, numfds, timeout * 1000);
-
- for(i = 0; i < numfds; i++) {
- zval *subarray = *pollmap[i];
-
- if (!subarray->is_ref && subarray->refcount > 1) {
- /* Make a new copy of the subarray zval* */
- MAKE_STD_ZVAL(subarray);
- *subarray = **pollmap[i];
-
- /* Point the pData to the new zval* and duplicate its resources */
- *pollmap[i] = subarray;
- zval_copy_ctor(subarray);
-
- /* Fixup its refcount */
- subarray->is_ref = 0;
- subarray->refcount = 1;
- }
- zend_hash_del(Z_ARRVAL_P(subarray), "revents", sizeof("revents"));
- add_assoc_long(subarray, "revents", pollfds[i].revents);
-
- }
- efree(pollmap);
- efree(pollfds);
-
- RETURN_LONG(fds_ready);
-}
-/* }}} */
-#endif /* PHP_SSH2_POLL */
-
-#ifdef PHP_SSH2_PUBLICKEY_SUBSYSTEM
-/* ***********************
- * Publickey Subsystem *
- *********************** */
-
-/* {{{ proto resource ssh2_publickey_init(resource connection)
-Initialize the publickey subsystem */
-PHP_FUNCTION(ssh2_publickey_init)
-{
- zval *zsession;
- LIBSSH2_SESSION *session;
- LIBSSH2_PUBLICKEY *pkey;
- php_ssh2_pkey_subsys_data *data;
-
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zsession) == FAILURE) {
- RETURN_FALSE;
- }
-
- ZEND_FETCH_RESOURCE(session, LIBSSH2_SESSION*, &zsession, -1, PHP_SSH2_SESSION_RES_NAME, le_ssh2_session);
-
- pkey = libssh2_publickey_init(session);
-
- if (!pkey) {
- int last_error = 0;
- char *error_msg = NULL;
-
- last_error = libssh2_session_last_error(session, &error_msg, NULL, 0);
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to initialize publickey subsystem(%d) %s", last_error, error_msg);
- RETURN_FALSE;
- }
-
- data = emalloc(sizeof(php_ssh2_pkey_subsys_data));
- data->session = session;
- data->session_rsrcid = Z_LVAL_P(zsession);
- zend_list_addref(data->session_rsrcid);
- data->pkey = pkey;
-
- ZEND_REGISTER_RESOURCE(return_value, data, le_ssh2_pkey_subsys);
-}
-/* }}} */
-
-/* {{{ proto bool ssh2_publickey_add(resource pkey, string algoname, string blob[, bool overwrite=FALSE [,array attributes=NULL]])
-Add an additional publickey */
-PHP_FUNCTION(ssh2_publickey_add)
-{
- zval *zpkey_data, *zattrs = NULL;
- php_ssh2_pkey_subsys_data *data;
- char *algo, *blob;
- int algo_len, blob_len;
- unsigned long num_attrs = 0;
- libssh2_publickey_attribute *attrs = NULL;
- zend_bool overwrite = 0;
-
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rss|ba", &zpkey_data, &algo, &algo_len, &blob, &blob_len, &overwrite, &zattrs) == FAILURE) {
- RETURN_FALSE;
- }
-
- ZEND_FETCH_RESOURCE(data, php_ssh2_pkey_subsys_data*, &zpkey_data, -1, PHP_SSH2_PKEY_SUBSYS_RES_NAME, le_ssh2_pkey_subsys);
-
- if (zattrs) {
- HashPosition pos;
- zval **attr_val;
- unsigned long current_attr = 0;
-
- num_attrs = zend_hash_num_elements(Z_ARRVAL_P(zattrs));
- attrs = safe_emalloc(num_attrs, sizeof(libssh2_publickey_attribute), 0);
-
- for(zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(zattrs), &pos);
- zend_hash_get_current_data_ex(Z_ARRVAL_P(zattrs), (void**)&attr_val, &pos) == SUCCESS;
- zend_hash_move_forward_ex(Z_ARRVAL_P(zattrs), &pos)) {
- char *key;
- int key_len, type;
- long idx;
- zval copyval = **attr_val;
-
- type = zend_hash_get_current_key_ex(Z_ARRVAL_P(zattrs), &key, &key_len, &idx, 0, &pos);
- if (type == HASH_KEY_NON_EXISTANT) {
- /* All but impossible */
- break;
- }
- if (type == HASH_KEY_IS_LONG) {
- /* Malformed, ignore */
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Malformed attirbute array, contains numeric index");
- num_attrs--;
- continue;
- }
-
- if (key_len == 0 || (key_len == 1 && *key == '*')) {
- /* Empty key, ignore */
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Empty attribute key");
- num_attrs--;
- continue;
- }
-
- zval_copy_ctor(©val);
- copyval.is_ref = 0;
- copyval.refcount = 1;
- convert_to_string(©val);
-
- if (*key == '*') {
- attrs[current_attr].mandatory = 1;
- attrs[current_attr].name = key + 1;
- attrs[current_attr].name_len = key_len - 2;
- } else {
- attrs[current_attr].mandatory = 0;
- attrs[current_attr].name = key;
- attrs[current_attr].name_len = key_len - 1;
- }
- attrs[current_attr].value_len = Z_STRLEN(copyval);
- attrs[current_attr].value = Z_STRVAL(copyval);
-
- /* copyval deliberately not dtor'd, we're stealing the string */
- current_attr++;
- }
- }
-
- if (libssh2_publickey_add_ex(data->pkey, algo, algo_len, blob, blob_len, overwrite, num_attrs, attrs)) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to add %s key", algo);
- RETVAL_FALSE;
- } else {
- RETVAL_TRUE;
- }
-
- if (attrs) {
- unsigned long i;
-
- for(i = 0; i < num_attrs; i++) {
- /* name doesn't need freeing */
- efree(attrs[i].value);
- }
- efree(attrs);
- }
-}
-/* }}} */
-
-/* {{{ proto bool ssh2_publickey_remove(resource pkey, string algoname, string blob)
-Remove a publickey entry */
-PHP_FUNCTION(ssh2_publickey_remove)
-{
- zval *zpkey_data;
- php_ssh2_pkey_subsys_data *data;
- char *algo, *blob;
- int algo_len, blob_len;
-
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rss", &zpkey_data, &algo, &algo_len, &blob, &blob_len) == FAILURE) {
- RETURN_FALSE;
- }
-
- ZEND_FETCH_RESOURCE(data, php_ssh2_pkey_subsys_data*, &zpkey_data, -1, PHP_SSH2_PKEY_SUBSYS_RES_NAME, le_ssh2_pkey_subsys);
-
- if (libssh2_publickey_remove_ex(data->pkey, algo, algo_len, blob, blob_len)) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to remove %s key", algo);
- RETURN_FALSE;
- }
-
- RETURN_TRUE;
-}
-/* }}} */
-
-/* {{{ proto array ssh2_publickey_list(resource pkey)
-List currently installed publickey entries */
-PHP_FUNCTION(ssh2_publickey_list)
-{
- zval *zpkey_data;
- php_ssh2_pkey_subsys_data *data;
- unsigned long num_keys, i;
- libssh2_publickey_list *keys;
-
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zpkey_data) == FAILURE) {
- RETURN_FALSE;
- }
-
- ZEND_FETCH_RESOURCE(data, php_ssh2_pkey_subsys_data*, &zpkey_data, -1, PHP_SSH2_PKEY_SUBSYS_RES_NAME, le_ssh2_pkey_subsys);
-
- if (libssh2_publickey_list_fetch(data->pkey, &num_keys, &keys)) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to list keys on remote server");
- RETURN_FALSE;
- }
-
- array_init(return_value);
- for(i = 0; i < num_keys; i++) {
- zval *key, *attrs;
- unsigned long j;
-
- MAKE_STD_ZVAL(key);
- array_init(key);
-
- add_assoc_stringl(key, "name", keys[i].name, keys[i].name_len, 1);
- add_assoc_stringl(key, "blob", keys[i].blob, keys[i].blob_len, 1);
-
- MAKE_STD_ZVAL(attrs);
- array_init(attrs);
- for(j = 0; j < keys[i].num_attrs; j++) {
- zval *attr;
-
- MAKE_STD_ZVAL(attr);
- ZVAL_STRINGL(attr, keys[i].attrs[j].value, keys[i].attrs[j].value_len, 1);
- zend_hash_add(Z_ARRVAL_P(attrs), keys[i].attrs[j].name, keys[i].attrs[j].name_len + 1, (void**)&attr, sizeof(zval*), NULL);
- }
- add_assoc_zval(key, "attrs", attrs);
-
- add_next_index_zval(return_value, key);
- }
-
- libssh2_publickey_list_free(data->pkey, keys);
-}
-/* }}} */
-#endif /* PHP_SSH2_PUBLICKEY_SUBSYSTEM */
-
-/* ***********************
- * Module Housekeeping *
- *********************** */
-
-static void php_ssh2_session_dtor(zend_rsrc_list_entry *rsrc TSRMLS_DC)
-{
- LIBSSH2_SESSION *session = (LIBSSH2_SESSION*)rsrc->ptr;
- php_ssh2_session_data **data = (php_ssh2_session_data**)libssh2_session_abstract(session);
-
- libssh2_session_disconnect(session, "PECL/ssh2 (http://pecl.php.net/packages/ssh2)");
-
- if (*data) {
- if ((*data)->ignore_cb) {
- zval_ptr_dtor(&(*data)->ignore_cb);
- }
- if ((*data)->debug_cb) {
- zval_ptr_dtor(&(*data)->debug_cb);
- }
- if ((*data)->macerror_cb) {
- zval_ptr_dtor(&(*data)->macerror_cb);
- }
- if ((*data)->disconnect_cb) {
- zval_ptr_dtor(&(*data)->disconnect_cb);
- }
-
- close((*data)->socket);
-
- efree(*data);
- *data = NULL;
- }
-
- libssh2_session_free(session);
-}
-
-#ifdef PHP_SSH2_REMOTE_FORWARDING
-static void php_ssh2_listener_dtor(zend_rsrc_list_entry *rsrc TSRMLS_DC)
-{
- php_ssh2_listener_data *data = (php_ssh2_listener_data*)rsrc->ptr;
- LIBSSH2_LISTENER *listener = data->listener;
-
- libssh2_channel_forward_cancel(listener);
- zend_list_delete(data->session_rsrcid);
- efree(data);
-}
-#endif /* PHP_SSH2_REMOTE_FORWARDING */
-
-#ifdef PHP_SSH2_PUBLICKEY_SUBSYSTEM
-static void php_ssh2_pkey_subsys_dtor(zend_rsrc_list_entry *rsrc TSRMLS_DC)
-{
- php_ssh2_pkey_subsys_data *data = (php_ssh2_pkey_subsys_data*)rsrc->ptr;
- LIBSSH2_PUBLICKEY *pkey = data->pkey;
-
- libssh2_publickey_shutdown(pkey);
- zend_list_delete(data->session_rsrcid);
- efree(data);
-}
-#endif /* PHP_SSH2_PUBLICKEY_SUBSYSTEM */
-
-/* {{{ PHP_MINIT_FUNCTION
- */
-PHP_MINIT_FUNCTION(ssh2)
-{
- le_ssh2_session = zend_register_list_destructors_ex(php_ssh2_session_dtor, NULL, PHP_SSH2_SESSION_RES_NAME, module_number);
-#ifdef PHP_SSH2_REMOTE_FORWARDING
- le_ssh2_listener = zend_register_list_destructors_ex(php_ssh2_listener_dtor, NULL, PHP_SSH2_LISTENER_RES_NAME, module_number);
-#endif /* PHP_SSH2_REMOTE_FORWARDING */
- le_ssh2_sftp = zend_register_list_destructors_ex(php_ssh2_sftp_dtor, NULL, PHP_SSH2_SFTP_RES_NAME, module_number);
-#ifdef PHP_SSH2_PUBLICKEY_SUBSYSTEM
- le_ssh2_pkey_subsys = zend_register_list_destructors_ex(php_ssh2_pkey_subsys_dtor, NULL, PHP_SSH2_PKEY_SUBSYS_RES_NAME, module_number);
-#endif /* PHP_SSH2_PUBLICKEY_SUBSYSTEM */
-
- REGISTER_LONG_CONSTANT("SSH2_FINGERPRINT_MD5", PHP_SSH2_FINGERPRINT_MD5, CONST_CS | CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("SSH2_FINGERPRINT_SHA1", PHP_SSH2_FINGERPRINT_SHA1, CONST_CS | CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("SSH2_FINGERPRINT_HEX", PHP_SSH2_FINGERPRINT_HEX, CONST_CS | CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("SSH2_FINGERPRINT_RAW", PHP_SSH2_FINGERPRINT_RAW, CONST_CS | CONST_PERSISTENT);
-
- REGISTER_LONG_CONSTANT("SSH2_TERM_UNIT_CHARS", PHP_SSH2_TERM_UNIT_CHARS, CONST_CS | CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("SSH2_TERM_UNIT_PIXELS", PHP_SSH2_TERM_UNIT_PIXELS, CONST_CS | CONST_PERSISTENT);
-
- REGISTER_STRING_CONSTANT("SSH2_DEFAULT_TERMINAL", PHP_SSH2_DEFAULT_TERMINAL, CONST_CS | CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("SSH2_DEFAULT_TERM_WIDTH", PHP_SSH2_DEFAULT_TERM_WIDTH, CONST_CS | CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("SSH2_DEFAULT_TERM_HEIGHT", PHP_SSH2_DEFAULT_TERM_HEIGHT, CONST_CS | CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("SSH2_DEFAULT_TERM_UNIT", PHP_SSH2_DEFAULT_TERM_UNIT, CONST_CS | CONST_PERSISTENT);
-
- REGISTER_LONG_CONSTANT("SSH2_STREAM_STDIO", 0, CONST_CS | CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("SSH2_STREAM_STDERR", SSH_EXTENDED_DATA_STDERR, CONST_CS | CONST_PERSISTENT);
-
-#ifdef PHP_SSH2_POLL
- /* events/revents */
- REGISTER_LONG_CONSTANT("SSH2_POLLIN", LIBSSH2_POLLFD_POLLIN, CONST_CS | CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("SSH2_POLLEXT", LIBSSH2_POLLFD_POLLEXT, CONST_CS | CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("SSH2_POLLOUT", LIBSSH2_POLLFD_POLLOUT, CONST_CS | CONST_PERSISTENT);
-
- /* revents only */
- REGISTER_LONG_CONSTANT("SSH2_POLLERR", LIBSSH2_POLLFD_POLLERR, CONST_CS | CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("SSH2_POLLHUP", LIBSSH2_POLLFD_POLLHUP, CONST_CS | CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("SSH2_POLLNVAL", LIBSSH2_POLLFD_POLLNVAL, CONST_CS | CONST_PERSISTENT);
-#if (LIBSSH2_APINO > 200503221619)
- REGISTER_LONG_CONSTANT("SSH2_POLL_SESSION_CLOSED", LIBSSH2_POLLFD_SESSION_CLOSED, CONST_CS | CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("SSH2_POLL_CHANNEL_CLOSED", LIBSSH2_POLLFD_CHANNEL_CLOSED, CONST_CS | CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("SSH2_POLL_LISTENER_CLOSED", LIBSSH2_POLLFD_LISTENER_CLOSED, CONST_CS | CONST_PERSISTENT);
-#endif /* >= LIBSSH2-0.9 */
-#endif /* POLL */
-
- return (php_register_url_stream_wrapper("ssh2.shell", &php_ssh2_stream_wrapper_shell TSRMLS_CC) == SUCCESS &&
- php_register_url_stream_wrapper("ssh2.exec", &php_ssh2_stream_wrapper_exec TSRMLS_CC) == SUCCESS &&
- php_register_url_stream_wrapper("ssh2.tunnel", &php_ssh2_stream_wrapper_tunnel TSRMLS_CC) == SUCCESS &&
- php_register_url_stream_wrapper("ssh2.scp", &php_ssh2_stream_wrapper_scp TSRMLS_CC) == SUCCESS &&
- php_register_url_stream_wrapper("ssh2.sftp", &php_ssh2_sftp_wrapper TSRMLS_CC) == SUCCESS) ? SUCCESS : FAILURE;
-}
-/* }}} */
-
-/* {{{ PHP_MSHUTDOWN_FUNCTION
- */
-PHP_MSHUTDOWN_FUNCTION(ssh2)
-{
- return (php_unregister_url_stream_wrapper("ssh2.shell" TSRMLS_CC) == SUCCESS &&
- php_unregister_url_stream_wrapper("ssh2.exec" TSRMLS_CC) == SUCCESS &&
- php_unregister_url_stream_wrapper("ssh2.tunnel" TSRMLS_CC) == SUCCESS &&
- php_unregister_url_stream_wrapper("ssh2.scp" TSRMLS_CC) == SUCCESS &&
- php_unregister_url_stream_wrapper("ssh2.sftp" TSRMLS_CC) == SUCCESS) ? SUCCESS : FAILURE;
-}
-/* }}} */
-
-/* {{{ PHP_MINFO_FUNCTION
- */
-PHP_MINFO_FUNCTION(ssh2)
-{
- php_info_print_table_start();
- php_info_print_table_header(2, "libssh2 version", LIBSSH2_VERSION);
- php_info_print_table_header(2, "banner", LIBSSH2_SSH_BANNER);
-#ifdef PHP_SSH2_REMOTE_FORWARDING
- php_info_print_table_header(2, "remote forwarding", "enabled");
-#endif
-#ifdef PHP_SSH2_HOSTBASED_AUTH
- php_info_print_table_header(2, "hostbased auth", "enabled");
-#endif
-#ifdef PHP_SSH2_POLL
- php_info_print_table_header(2, "polling support", "enabled");
-#endif
-#ifdef PHP_SSH2_PUBLICKEY_SUBSYSTEM
- php_info_print_table_header(2, "publickey subsystem", "enabled");
-#endif
- php_info_print_table_end();
-}
-/* }}} */
-
-/* {{{ ssh2_functions[]
- */
-function_entry ssh2_functions[] = {
- PHP_FE(ssh2_connect, NULL)
- PHP_FE(ssh2_methods_negotiated, NULL)
- PHP_FE(ssh2_fingerprint, NULL)
-
- PHP_FE(ssh2_auth_none, NULL)
- PHP_FE(ssh2_auth_password, NULL)
- PHP_FE(ssh2_auth_pubkey_file, NULL)
-#ifdef PHP_SSH2_HOSTBASED_AUTH
- PHP_FE(ssh2_auth_hostbased_file, NULL)
-#endif /* PHP_SSH2_HOSTBASED_AUTH */
-
-#ifdef PHP_SSH2_REMOTE_FORWARDING
- PHP_FE(ssh2_forward_listen, NULL)
- PHP_FE(ssh2_forward_accept, NULL)
-#endif /* PHP_SSH2_REMOTE_FORWARDING */
-
- /* Stream Stuff */
- PHP_FE(ssh2_shell, NULL)
- PHP_FE(ssh2_exec, NULL)
- PHP_FE(ssh2_tunnel, NULL)
- PHP_FE(ssh2_scp_recv, NULL)
- PHP_FE(ssh2_scp_send, NULL)
- PHP_FE(ssh2_fetch_stream, NULL)
-#ifdef PHP_SSH2_POLL
- PHP_FE(ssh2_poll, php_ssh2_first_arg_force_ref)
-#endif
-
- /* SFTP Stuff */
- PHP_FE(ssh2_sftp, NULL)
-
- /* SFTP Wrapper Ops */
- PHP_FE(ssh2_sftp_rename, NULL)
- PHP_FE(ssh2_sftp_unlink, NULL)
- PHP_FE(ssh2_sftp_mkdir, NULL)
- PHP_FE(ssh2_sftp_rmdir, NULL)
- PHP_FE(ssh2_sftp_stat, NULL)
- PHP_FE(ssh2_sftp_lstat, NULL)
- PHP_FE(ssh2_sftp_symlink, NULL)
- PHP_FE(ssh2_sftp_readlink, NULL)
- PHP_FE(ssh2_sftp_realpath, NULL)
-
- /* Publickey subsystem */
-#ifdef PHP_SSH2_PUBLICKEY_SUBSYSTEM
- PHP_FE(ssh2_publickey_init, NULL)
- PHP_FE(ssh2_publickey_add, NULL)
- PHP_FE(ssh2_publickey_remove, NULL)
- PHP_FE(ssh2_publickey_list, NULL)
-#endif
-
- {NULL, NULL, NULL}
-};
-/* }}} */
-
-/* {{{ ssh2_module_entry
- */
-zend_module_entry ssh2_module_entry = {
-#if ZEND_MODULE_API_NO >= 20010901
- STANDARD_MODULE_HEADER,
-#endif
- "ssh2",
- ssh2_functions,
- PHP_MINIT(ssh2),
- PHP_MSHUTDOWN(ssh2),
- NULL, /* RINIT */
- NULL, /* RSHUTDOWN */
- PHP_MINFO(ssh2),
-#if ZEND_MODULE_API_NO >= 20010901
- PHP_SSH2_VERSION,
-#endif
- STANDARD_MODULE_PROPERTIES
-};
-/* }}} */
-
-#ifdef COMPILE_DL_SSH2
-ZEND_GET_MODULE(ssh2)
-#endif
-
-/*
- * 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
- */
|
[-]
[+]
|
Deleted |
ssh2-0.10.tgz/ssh2-0.10/ssh2_fopen_wrappers.c
^
|
@@ -1,1260 +0,0 @@
-/*
- +----------------------------------------------------------------------+
- | PHP Version 4 |
- +----------------------------------------------------------------------+
- | 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: Sara Golemon <pollita@php.net> |
- +----------------------------------------------------------------------+
-
- $Id: ssh2_fopen_wrappers.c,v 1.11 2005/07/12 03:24:20 pollita Exp $
-*/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "php.h"
-#include "php_ssh2.h"
-
-/* **********************
- * channel_stream_ops *
- ********************** */
-
-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;
-
- libssh2_channel_set_blocking(abstract->channel, abstract->is_blocking);
- 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;
-
- stream->eof = libssh2_channel_eof(abstract->channel);
- libssh2_channel_set_blocking(abstract->channel, abstract->is_blocking);
- return libssh2_channel_read_ex(abstract->channel, abstract->streamid, buf, count);
-}
-
-static int php_ssh2_channel_stream_close(php_stream *stream, int close_handle TSRMLS_DC)
-{
- php_ssh2_channel_data *abstract = (php_ssh2_channel_data*)stream->abstract;
-
- if (!abstract->refcount || (--*(abstract->refcount) == 0)) {
- /* Last one out, turn off the lights */
- if (abstract->refcount) {
- efree(abstract->refcount);
- }
- libssh2_channel_eof(abstract->channel);
- libssh2_channel_free(abstract->channel);
- zend_list_delete(abstract->session_rsrc);
- }
- efree(abstract);
-
- return 0;
-}
-
-static int php_ssh2_channel_stream_flush(php_stream *stream TSRMLS_DC)
-{
- php_ssh2_channel_data *abstract = (php_ssh2_channel_data*)stream->abstract;
-
- return libssh2_channel_flush_ex(abstract->channel, abstract->streamid);
-}
-
-static int php_ssh2_channel_stream_set_option(php_stream *stream, int option, int value, void *ptrparam TSRMLS_DC)
-{
- php_ssh2_channel_data *abstract = (php_ssh2_channel_data*)stream->abstract;
- int ret;
-
- switch (option) {
- case PHP_STREAM_OPTION_BLOCKING:
- ret = abstract->is_blocking;
- abstract->is_blocking = value;
- return ret;
- break;
-#if PHP_MAJOR_VERSION >= 5
- case PHP_STREAM_OPTION_CHECK_LIVENESS:
- return stream->eof = libssh2_channel_eof(abstract->channel);
- break;
-#endif
- }
-
- return -1;
-}
-
-php_stream_ops php_ssh2_channel_stream_ops = {
- php_ssh2_channel_stream_write,
- php_ssh2_channel_stream_read,
- php_ssh2_channel_stream_close,
- php_ssh2_channel_stream_flush,
- PHP_SSH2_CHANNEL_STREAM_NAME,
- NULL, /* seek */
- NULL, /* cast */
- NULL, /* stat */
- php_ssh2_channel_stream_set_option,
-};
-
-/* *********************
- * Magic Path Helper *
- ********************* */
-
-/* {{{ php_ssh2_fopen_wraper_parse_path
- * Parse an ssh2.*:// path
- */
-php_url *php_ssh2_fopen_wraper_parse_path( char *path, char *type, php_stream_context *context,
- LIBSSH2_SESSION **psession, int *presource_id,
- LIBSSH2_SFTP **psftp, int *psftp_rsrcid
- TSRMLS_DC)
-{
- php_ssh2_sftp_data *sftp_data = NULL;
- LIBSSH2_SESSION *session;
- php_url *resource;
- zval *methods = NULL, *callbacks = NULL, zsession, **tmpzval;
- long resource_id;
- char *s, *username = NULL, *password = NULL, *pubkey_file = NULL, *privkey_file = NULL;
- int username_len = 0, password_len = 0;
-
- resource = php_url_parse(path);
-
- if (strncmp(resource->scheme, "ssh2.", sizeof("ssh2.") - 1)) {
- /* Not an ssh wrapper */
- php_url_free(resource);
- return NULL;
- }
-
- if (strcmp(resource->scheme + sizeof("ssh2.") - 1, type)) {
- /* Wrong ssh2. wrapper type */
- php_url_free(resource);
- return NULL;
- }
-
- if (!resource->host) {
- return NULL;
- }
-
- /* Look for a resource ID to reuse a session */
- s = resource->host;
- if (strncmp(resource->host, "Resource id #", sizeof("Resource id #") - 1) == 0) {
- s = resource->host + sizeof("Resource id #") - 1;
- }
- if (is_numeric_string(s, strlen(s), &resource_id, NULL, 0) == IS_LONG) {
- php_ssh2_sftp_data *sftp_data;
-
- if (psftp) {
- sftp_data = (php_ssh2_sftp_data*)zend_fetch_resource(NULL TSRMLS_CC, resource_id, PHP_SSH2_SFTP_RES_NAME, NULL, 1, le_ssh2_sftp);
- if (sftp_data) {
- /* Want the sftp layer */
- zend_list_addref(resource_id);
- *psftp_rsrcid = resource_id;
- *psftp = sftp_data->sftp;
- *presource_id = sftp_data->session_rsrcid;
- *psession = sftp_data->session;
- return resource;
- }
- }
- session = (LIBSSH2_SESSION *)zend_fetch_resource(NULL TSRMLS_CC, resource_id, PHP_SSH2_SESSION_RES_NAME, NULL, 1, le_ssh2_session);
- if (session) {
- if (psftp) {
- /* We need an sftp layer too */
- LIBSSH2_SFTP *sftp = libssh2_sftp_init(session);
-
- if (!sftp) {
- php_url_free(resource);
- return NULL;
- }
- sftp_data = emalloc(sizeof(php_ssh2_sftp_data));
- sftp_data->sftp = sftp;
- sftp_data->session = session;
- sftp_data->session_rsrcid = resource_id;
- zend_list_addref(resource_id);
- *psftp_rsrcid = ZEND_REGISTER_RESOURCE(NULL, sftp_data, le_ssh2_sftp);
- *psftp = sftp;
- *presource_id = resource_id;
- *psession = session;
- return resource;
- }
- zend_list_addref(resource_id);
- *presource_id = resource_id;
- *psession = session;
- return resource;
- }
- }
-
- /* Fallback on finding it in the context */
- if (resource->host[0] == 0 && context && psftp &&
- php_stream_context_get_option(context, "ssh2", "sftp", &tmpzval) == SUCCESS &&
- Z_TYPE_PP(tmpzval) == IS_RESOURCE) {
- php_ssh2_sftp_data *sftp_data;
- sftp_data = (php_ssh2_sftp_data *)zend_fetch_resource(tmpzval TSRMLS_CC, -1, PHP_SSH2_SFTP_RES_NAME, NULL, 1, le_ssh2_sftp);
- if (sftp_data) {
- zend_list_addref(Z_LVAL_PP(tmpzval));
- *psftp_rsrcid = Z_LVAL_PP(tmpzval);
- *psftp = sftp_data->sftp;
- *presource_id = sftp_data->session_rsrcid;
- *psession = sftp_data->session;
- return resource;
- }
- }
- if (resource->host[0] == 0 && context &&
- php_stream_context_get_option(context, "ssh2", "session", &tmpzval) == SUCCESS &&
- Z_TYPE_PP(tmpzval) == IS_RESOURCE) {
- session = (LIBSSH2_SESSION *)zend_fetch_resource(tmpzval TSRMLS_CC, -1, PHP_SSH2_SESSION_RES_NAME, NULL, 1, le_ssh2_session);
- if (session) {
- if (psftp) {
- /* We need an SFTP layer too! */
- LIBSSH2_SFTP *sftp = libssh2_sftp_init(session);
- php_ssh2_sftp_data *sftp_data;
-
- if (!sftp) {
- php_url_free(resource);
- return NULL;
- }
- sftp_data = emalloc(sizeof(php_ssh2_sftp_data));
- sftp_data->sftp = sftp;
- sftp_data->session = session;
- sftp_data->session_rsrcid = Z_LVAL_PP(tmpzval);
- zend_list_addref(Z_LVAL_PP(tmpzval));
- *psftp_rsrcid = ZEND_REGISTER_RESOURCE(NULL, sftp_data, le_ssh2_sftp);
- *psftp = sftp;
- *presource_id = Z_LVAL_PP(tmpzval);
- *psession = session;
- return resource;
- }
- zend_list_addref(Z_LVAL_PP(tmpzval));
- *psession = session;
- *presource_id = Z_LVAL_PP(tmpzval);
- return resource;
- }
- }
-
- /* Make our own connection then */
- if (!resource->port) {
- resource->port = 22;
- }
-
- if (context &&
- php_stream_context_get_option(context, "ssh2", "methods", &tmpzval) == SUCCESS &&
- Z_TYPE_PP(tmpzval) == IS_ARRAY) {
- methods = *tmpzval;
- }
-
- if (context &&
- php_stream_context_get_option(context, "ssh2", "callbacks", &tmpzval) == SUCCESS &&
- Z_TYPE_PP(tmpzval) == IS_ARRAY) {
- callbacks = *tmpzval;
- }
-
- if (context &&
- php_stream_context_get_option(context, "ssh2", "username", &tmpzval) == SUCCESS &&
- Z_TYPE_PP(tmpzval) == IS_STRING) {
- username = Z_STRVAL_PP(tmpzval);
- username_len = Z_STRLEN_PP(tmpzval);
- }
-
- if (context &&
- php_stream_context_get_option(context, "ssh2", "password", &tmpzval) == SUCCESS &&
- Z_TYPE_PP(tmpzval) == IS_STRING) {
- password = Z_STRVAL_PP(tmpzval);
- password_len = Z_STRLEN_PP(tmpzval);
- }
-
- if (context &&
- php_stream_context_get_option(context, "ssh2", "pubkey_file", &tmpzval) == SUCCESS &&
- Z_TYPE_PP(tmpzval) == IS_STRING) {
- pubkey_file = Z_STRVAL_PP(tmpzval);
- }
-
- if (context &&
- php_stream_context_get_option(context, "ssh2", "privkey_file", &tmpzval) == SUCCESS &&
- Z_TYPE_PP(tmpzval) == IS_STRING) {
- privkey_file = Z_STRVAL_PP(tmpzval);
- }
-
- if (resource->user) {
- int len = strlen(resource->user);
-
- if (len) {
- username = resource->user;
- username_len = len;
- }
- }
-
- if (resource->pass) {
- int len = strlen(resource->pass);
-
- if (len) {
- password = resource->pass;
- password_len = len;
- }
- }
-
- if (!username) {
- /* username is a minimum */
- php_url_free(resource);
- return NULL;
- }
-
- session = php_ssh2_session_connect(resource->host, resource->port, methods, callbacks TSRMLS_CC);
- if (!session) {
- /* Unable to connect! */
- php_url_free(resource);
- return NULL;
- }
- ZEND_REGISTER_RESOURCE(&zsession, session, le_ssh2_session);
-
- /* Authenticate */
- if (pubkey_file && privkey_file) {
- /* Attempt pubkey authentication */
- if ((!PG(safe_mode) || php_checkuid(pubkey_file, NULL, CHECKUID_CHECK_FILE_AND_DIR)) &&
- (!PG(safe_mode) || php_checkuid(privkey_file, NULL, CHECKUID_CHECK_FILE_AND_DIR)) &&
- !php_check_open_basedir(pubkey_file TSRMLS_CC) &&
- !php_check_open_basedir(privkey_file TSRMLS_CC) &&
- !libssh2_userauth_publickey_fromfile(session, username, pubkey_file, privkey_file, password)) {
- goto session_authed;
- }
- }
-
- if (password) {
- /* Attempt password authentication */
- if (libssh2_userauth_password_ex(session, username, username_len, password, password_len, NULL) == 0) {
- goto session_authed;
- }
- }
-
- /* Auth failure */
- php_url_free(resource);
- zend_list_delete(Z_LVAL(zsession));
- return NULL;
-
- session_authed:
-
- if (psftp) {
- LIBSSH2_SFTP *sftp;
- zval zsftp;
-
- sftp = libssh2_sftp_init(session);
- if (!sftp) {
- php_url_free(resource);
- zend_list_delete(Z_LVAL(zsession));
- return NULL;
- }
-
- sftp_data = emalloc(sizeof(php_ssh2_sftp_data));
- sftp_data->session = session;
- sftp_data->sftp = sftp;
- sftp_data->session_rsrcid = Z_LVAL(zsession);
-
- ZEND_REGISTER_RESOURCE(&zsftp, sftp_data, le_ssh2_sftp);
- *psftp_rsrcid = Z_LVAL(zsftp);
- *psftp = sftp;
- }
-
- *presource_id = Z_LVAL(zsession);
- *psession = session;
-
- return resource;
-}
-/* }}} */
-
-/* *****************
- * Shell Wrapper *
- ***************** */
-
-/* {{{ php_ssh2_shell_open
- * Make a stream from a session
- */
-static php_stream *php_ssh2_shell_open(LIBSSH2_SESSION *session, int resource_id, char *term, int term_len, zval *environment, long width, long height, long type TSRMLS_DC)
-{
- LIBSSH2_CHANNEL *channel;
- php_ssh2_channel_data *channel_data;
- php_stream *stream;
-
- channel = libssh2_channel_open_session(session);
- if (!channel) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to request a channel from remote host");
- return NULL;
- }
-
- if (environment) {
- char *key;
- int key_type, key_len;
- long idx;
-
- for(zend_hash_internal_pointer_reset(HASH_OF(environment));
- (key_type = zend_hash_get_current_key_ex(HASH_OF(environment), &key, &key_len, &idx, 0, NULL)) != HASH_KEY_NON_EXISTANT;
- zend_hash_move_forward(HASH_OF(environment))) {
- if (key_type == HASH_KEY_IS_STRING) {
- zval **value;
-
- if (zend_hash_get_current_data(HASH_OF(environment), (void**)&value) == SUCCESS) {
- zval copyval = **value;
-
- zval_copy_ctor(©val);
- convert_to_string(©val);
- if (libssh2_channel_setenv_ex(channel, key, key_len, Z_STRVAL(copyval), Z_STRLEN(copyval))) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed setting %s=%s on remote end", key, Z_STRVAL(copyval));
- }
- zval_dtor(©val);
- }
- } else {
- php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Skipping numeric index in environment array");
- }
- }
- }
-
- if (type == PHP_SSH2_TERM_UNIT_CHARS) {
- if (libssh2_channel_request_pty_ex(channel, term, term_len, NULL, 0, width, height, 0, 0)) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed allocating %s pty at %ldx%ld characters", term, width, height);
- libssh2_channel_free(channel);
- return NULL;
- }
- } else {
- if (libssh2_channel_request_pty_ex(channel, term, term_len, NULL, 0, 0, 0, width, height)) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed allocating %s pty at %ldx%ld pixels", term, width, height);
- libssh2_channel_free(channel);
- return NULL;
- }
- }
-
- if (libssh2_channel_shell(channel)) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to request shell from remote host");
- libssh2_channel_free(channel);
- return NULL;
- }
-
- /* Turn it into a stream */
- channel_data = emalloc(sizeof(php_ssh2_channel_data));
- channel_data->channel = channel;
- channel_data->streamid = 0;
- channel_data->is_blocking = 0;
- channel_data->session_rsrc = resource_id;
- channel_data->refcount = NULL;
-
- stream = php_stream_alloc(&php_ssh2_channel_stream_ops, channel_data, 0, "r+");
-
- return stream;
-}
-/* }}} */
-
-/* {{{ php_ssh2_fopen_wrapper_shell
- * ssh2.shell:// fopen wrapper
- */
-static php_stream *php_ssh2_fopen_wrapper_shell(php_stream_wrapper *wrapper, char *path, char *mode, int options, char **opened_path, php_stream_context *context STREAMS_DC TSRMLS_DC)
-{
- LIBSSH2_SESSION *session = NULL;
- php_stream *stream;
- zval **tmpzval, *environment = NULL;
- char *terminal = PHP_SSH2_DEFAULT_TERMINAL;
- long width = PHP_SSH2_DEFAULT_TERM_WIDTH;
- long height = PHP_SSH2_DEFAULT_TERM_HEIGHT;
- long type = PHP_SSH2_DEFAULT_TERM_UNIT;
- int resource_id = 0, terminal_len = sizeof(PHP_SSH2_DEFAULT_TERMINAL) - 1;
- php_url *resource;
- char *s, *e;
-
- resource = php_ssh2_fopen_wraper_parse_path(path, "shell", context, &session, &resource_id, NULL, NULL TSRMLS_CC);
- if (!resource || !session) {
- return NULL;
- }
-
- if (context &&
- php_stream_context_get_option(context, "ssh2", "env", &tmpzval) == SUCCESS &&
- tmpzval && *tmpzval && Z_TYPE_PP(tmpzval) == IS_ARRAY) {
- environment = *tmpzval;
- }
-
- if (context &&
- php_stream_context_get_option(context, "ssh2", "term", &tmpzval) == SUCCESS &&
- tmpzval && *tmpzval && Z_TYPE_PP(tmpzval) == IS_STRING) {
- terminal = Z_STRVAL_PP(tmpzval);
- terminal_len = Z_STRLEN_PP(tmpzval);
- }
-
- if (context &&
- php_stream_context_get_option(context, "ssh2", "term_width", &tmpzval) == SUCCESS &&
- tmpzval && *tmpzval) {
- zval *copyval;
- ALLOC_INIT_ZVAL(copyval);
- *copyval = **tmpzval;
- convert_to_long(copyval);
- width = Z_LVAL_P(copyval);
- zval_ptr_dtor(©val);
- }
-
- if (context &&
- php_stream_context_get_option(context, "ssh2", "term_height", &tmpzval) == SUCCESS &&
- tmpzval && *tmpzval) {
- zval *copyval;
- ALLOC_INIT_ZVAL(copyval);
- *copyval = **tmpzval;
- convert_to_long(copyval);
- height = Z_LVAL_P(copyval);
- zval_ptr_dtor(©val);
- }
-
- if (context &&
- php_stream_context_get_option(context, "ssh2", "term_units", &tmpzval) == SUCCESS &&
- tmpzval && *tmpzval) {
- zval *copyval;
- ALLOC_INIT_ZVAL(copyval);
- *copyval = **tmpzval;
- convert_to_long(copyval);
- type = Z_LVAL_P(copyval);
- zval_ptr_dtor(©val);
- }
-
- s = resource->path ? resource->path : NULL;
- e = s ? s + strlen(s) : NULL;
-
- if (s && s[0] == '/') {
- /* Terminal type encoded into URL overrides context terminal type */
- char *p;
-
- s++;
- p = strchr(s, '/');
- if (p) {
- if (p - s) {
- terminal = s;
- terminal_len = p - terminal;
- s += terminal_len + 1;
- } else {
- /* "null" terminal given, skip it */
- s++;
- }
- } else {
- int len;
-
- if ((len = strlen(path + 1))) {
- terminal = s;
- terminal_len = len;
- s += len;
- }
- }
- }
-
- /* TODO: Accept resolution and environment vars as URL style parameters
- * ssh2.shell://hostorresource/terminal/99x99c?envvar=envval&envvar=envval....
- */
- stream = php_ssh2_shell_open(session, resource_id, terminal, terminal_len, environment, width, height, type TSRMLS_CC);
- if (!stream) {
- zend_list_delete(resource_id);
- }
- php_url_free(resource);
-
- return stream;
-}
-/* }}} */
-
-static php_stream_wrapper_ops php_ssh2_shell_stream_wops = {
- php_ssh2_fopen_wrapper_shell,
- NULL, /* stream_close */
- NULL, /* stat */
- NULL, /* stat_url */
- NULL, /* opendir */
- "ssh2.shell"
-};
-
-php_stream_wrapper php_ssh2_stream_wrapper_shell = {
- &php_ssh2_shell_stream_wops,
- NULL,
- 0
-};
-
-/* {{{ proto stream ssh2_shell(resource session[, string term_type[, array env[, int width, int height[, int width_height_type]]]])
- * Open a shell at the remote end and allocate a channel for it
- */
-PHP_FUNCTION(ssh2_shell)
-{
- LIBSSH2_SESSION *session;
- php_stream *stream;
- zval *zsession;
- zval *environment = NULL;
- char *term = PHP_SSH2_DEFAULT_TERMINAL;
- int term_len = sizeof(PHP_SSH2_DEFAULT_TERMINAL) - 1;
- long width = PHP_SSH2_DEFAULT_TERM_WIDTH;
- long height = PHP_SSH2_DEFAULT_TERM_HEIGHT;
- long type = PHP_SSH2_DEFAULT_TERM_UNIT;
- int argc = ZEND_NUM_ARGS();
-
- if (argc == 5) {
- 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_FALSE;
- }
-
- ZEND_FETCH_RESOURCE(session, LIBSSH2_SESSION*, &zsession, -1, PHP_SSH2_SESSION_RES_NAME, le_ssh2_session);
-
- stream = php_ssh2_shell_open(session, Z_LVAL_P(zsession), term, term_len, environment, width, height, type TSRMLS_CC);
- if (!stream) {
- RETURN_FALSE;
- }
-
- /* Ensure that channels are freed BEFORE the sessions they belong to */
- zend_list_addref(Z_LVAL_P(zsession));
-
- php_stream_to_zval(stream, return_value);
-}
-/* }}} */
-
-/* ****************
- * Exec Wrapper *
- **************** */
-
-/* {{{ php_ssh2_exec_command
- * Make a stream from a session
- */
-static php_stream *php_ssh2_exec_command(LIBSSH2_SESSION *session, int resource_id, char *command, char *term, int term_len, zval *environment, long width, long height, long type TSRMLS_DC)
-{
- LIBSSH2_CHANNEL *channel;
- php_ssh2_channel_data *channel_data;
- php_stream *stream;
-
- channel = libssh2_channel_open_session(session);
- if (!channel) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to request a channel from remote host");
- return NULL;
- }
-
- if (environment) {
- char *key;
- int key_type, key_len;
- long idx;
-
- for(zend_hash_internal_pointer_reset(HASH_OF(environment));
- (key_type = zend_hash_get_current_key_ex(HASH_OF(environment), &key, &key_len, &idx, 0, NULL)) != HASH_KEY_NON_EXISTANT;
- zend_hash_move_forward(HASH_OF(environment))) {
- if (key_type == HASH_KEY_IS_STRING) {
- zval **value;
-
- if (zend_hash_get_current_data(HASH_OF(environment), (void**)&value) == SUCCESS) {
- zval copyval = **value;
-
- zval_copy_ctor(©val);
- convert_to_string(©val);
- if (libssh2_channel_setenv_ex(channel, key, key_len, Z_STRVAL(copyval), Z_STRLEN(copyval))) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed setting %s=%s on remote end", key, Z_STRVAL(copyval));
- }
- zval_dtor(©val);
- }
- } else {
- php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Skipping numeric index in environment array");
- }
- }
- }
-
- if (term) {
- if (type == PHP_SSH2_TERM_UNIT_CHARS) {
- if (libssh2_channel_request_pty_ex(channel, term, term_len, NULL, 0, width, height, 0, 0)) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed allocating %s pty at %ldx%ld characters", term, width, height);
- libssh2_channel_free(channel);
- return NULL;
- }
- } else {
- if (libssh2_channel_request_pty_ex(channel, term, term_len, NULL, 0, 0, 0, width, height)) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed allocating %s pty at %ldx%ld pixels", term, width, height);
- libssh2_channel_free(channel);
- return NULL;
- }
- }
- }
-
- if (libssh2_channel_exec(channel, command)) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to request command execution on remote host");
- libssh2_channel_free(channel);
- return NULL;
- }
-
- /* Turn it into a stream */
- channel_data = emalloc(sizeof(php_ssh2_channel_data));
- channel_data->channel = channel;
- channel_data->streamid = 0;
- channel_data->is_blocking = 0;
- channel_data->session_rsrc = resource_id;
- channel_data->refcount = NULL;
-
- stream = php_stream_alloc(&php_ssh2_channel_stream_ops, channel_data, 0, "r+");
-
- return stream;
-}
-/* }}} */
-
-/* {{{ php_ssh2_fopen_wrapper_exec
- * ssh2.exec:// fopen wrapper
- */
-static php_stream *php_ssh2_fopen_wrapper_exec(php_stream_wrapper *wrapper, char *path, char *mode, int options, char **opened_path, php_stream_context *context STREAMS_DC TSRMLS_DC)
-{
- LIBSSH2_SESSION *session = NULL;
- php_stream *stream;
- zval **tmpzval, *environment = NULL;
- int resource_id = 0;
- php_url *resource;
- char *terminal = NULL;
- int terminal_len = 0;
- long width = PHP_SSH2_DEFAULT_TERM_WIDTH;
- long height = PHP_SSH2_DEFAULT_TERM_HEIGHT;
- long type = PHP_SSH2_DEFAULT_TERM_UNIT;
-
- resource = php_ssh2_fopen_wraper_parse_path(path, "exec", context, &session, &resource_id, NULL, NULL TSRMLS_CC);
- if (!resource || !session) {
- return NULL;
- }
- if (!resource->path) {
- php_url_free(resource);
- zend_list_delete(resource_id);
- return NULL;
- }
-
- if (context &&
- php_stream_context_get_option(context, "ssh2", "env", &tmpzval) == SUCCESS &&
- tmpzval && *tmpzval && Z_TYPE_PP(tmpzval) == IS_ARRAY) {
- environment = *tmpzval;
- }
-
- if (context &&
- php_stream_context_get_option(context, "ssh2", "term", &tmpzval) == SUCCESS &&
- tmpzval && *tmpzval && Z_TYPE_PP(tmpzval) == IS_STRING) {
- terminal = Z_STRVAL_PP(tmpzval);
- terminal_len = Z_STRLEN_PP(tmpzval);
- }
-
- if (context &&
- php_stream_context_get_option(context, "ssh2", "term_width", &tmpzval) == SUCCESS &&
- tmpzval && *tmpzval) {
- zval *copyval;
- ALLOC_INIT_ZVAL(copyval);
- *copyval = **tmpzval;
- convert_to_long(copyval);
- width = Z_LVAL_P(copyval);
- zval_ptr_dtor(©val);
- }
-
- if (context &&
- php_stream_context_get_option(context, "ssh2", "term_height", &tmpzval) == SUCCESS &&
- tmpzval && *tmpzval) {
- zval *copyval;
- ALLOC_INIT_ZVAL(copyval);
- *copyval = **tmpzval;
- convert_to_long(copyval);
- height = Z_LVAL_P(copyval);
- zval_ptr_dtor(©val);
- }
-
- if (context &&
- php_stream_context_get_option(context, "ssh2", "term_units", &tmpzval) == SUCCESS &&
- tmpzval && *tmpzval) {
- zval *copyval;
- ALLOC_INIT_ZVAL(copyval);
- *copyval = **tmpzval;
- convert_to_long(copyval);
- type = Z_LVAL_P(copyval);
- zval_ptr_dtor(©val);
- }
-
- stream = php_ssh2_exec_command(session, resource_id, resource->path + 1, terminal, terminal_len, environment, width, height, type TSRMLS_CC);
- if (!stream) {
- zend_list_delete(resource_id);
- }
- php_url_free(resource);
-
- return stream;
-}
-/* }}} */
-
-static php_stream_wrapper_ops php_ssh2_exec_stream_wops = {
- php_ssh2_fopen_wrapper_exec,
- NULL, /* stream_close */
- NULL, /* stat */
- NULL, /* stat_url */
- NULL, /* opendir */
- "ssh2.exec"
-};
-
-php_stream_wrapper php_ssh2_stream_wrapper_exec = {
- &php_ssh2_exec_stream_wops,
- NULL,
- 0
-};
-
-/* {{{ proto stream ssh2_exec(resource session, string command[, string pty[, array env[, int width[, int heightp[, int width_height_type]]]]])
- * Execute a command at the remote end and allocate a channel for it
- *
- * This function has a dirty little secret.... pty and env can be in either order.... shhhh... don't tell anyone
- */
-PHP_FUNCTION(ssh2_exec)
-{
- LIBSSH2_SESSION *session;
- php_stream *stream;
- zval *zsession;
- zval *environment = NULL;
- zval *zpty = NULL;
- char *command;
- int command_len;
- long width = PHP_SSH2_DEFAULT_TERM_WIDTH;
- long height = PHP_SSH2_DEFAULT_TERM_HEIGHT;
- long type = PHP_SSH2_DEFAULT_TERM_UNIT;
- char *term = NULL;
- 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_FALSE;
- }
-
- if (zpty && Z_TYPE_P(zpty) == IS_ARRAY) {
- /* Swap pty and environment -- old call style */
- zval *tmp = zpty;
- zpty = environment;
- environment = tmp;
- }
-
- if (environment && Z_TYPE_P(environment) != IS_ARRAY) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "ssh2_exec() expects arg 4 to be of type array");
- RETURN_FALSE;
- }
-
- if (zpty) {
- convert_to_string(zpty);
- term = Z_STRVAL_P(zpty);
- term_len = Z_STRLEN_P(zpty);
- }
-
- ZEND_FETCH_RESOURCE(session, LIBSSH2_SESSION*, &zsession, -1, PHP_SSH2_SESSION_RES_NAME, le_ssh2_session);
-
- stream = php_ssh2_exec_command(session, Z_LVAL_P(zsession), command, term, term_len, environment, width, height, type TSRMLS_CC);
- if (!stream) {
- RETURN_FALSE;
- }
-
- /* Ensure that channels are freed BEFORE the sessions they belong to */
- zend_list_addref(Z_LVAL_P(zsession));
-
- php_stream_to_zval(stream, return_value);
-}
-/* }}} */
-
-/* ***************
- * SCP Wrapper *
- *************** */
-
-/* {{{ php_ssh2_scp_xfer
- * Make a stream from a session
- */
-static php_stream *php_ssh2_scp_xfer(LIBSSH2_SESSION *session, int resource_id, char *filename TSRMLS_DC)
-{
- LIBSSH2_CHANNEL *channel;
- php_ssh2_channel_data *channel_data;
- php_stream *stream;
-
- channel = libssh2_scp_recv(session, filename, NULL);
- if (!channel) {
- char *error = "";
- libssh2_session_last_error(session, &error, NULL, 0);
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to request a channel from remote host: %s", error);
- return NULL;
- }
-
- /* Turn it into a stream */
- channel_data = emalloc(sizeof(php_ssh2_channel_data));
- channel_data->channel = channel;
- channel_data->streamid = 0;
- channel_data->is_blocking = 0;
- channel_data->session_rsrc = resource_id;
- channel_data->refcount = NULL;
-
- stream = php_stream_alloc(&php_ssh2_channel_stream_ops, channel_data, 0, "r");
-
- return stream;
-}
-/* }}} */
-
-/* {{{ php_ssh2_fopen_wrapper_scp
- * ssh2.scp:// fopen wrapper (Read mode only, if you want to know why write mode isn't supported as a stream, take a look at the SCP protocol)
- */
-static php_stream *php_ssh2_fopen_wrapper_scp(php_stream_wrapper *wrapper, char *path, char *mode, int options, char **opened_path, php_stream_context *context STREAMS_DC TSRMLS_DC)
-{
- LIBSSH2_SESSION *session = NULL;
- php_stream *stream;
- int resource_id = 0;
- php_url *resource;
-
- if (strchr(mode, '+') || strchr(mode, 'a') || strchr(mode, 'w')) {
- return NULL;
- }
-
- resource = php_ssh2_fopen_wraper_parse_path(path, "scp", context, &session, &resource_id, NULL, NULL TSRMLS_CC);
- if (!resource || !session) {
- return NULL;
- }
- if (!resource->path) {
- php_url_free(resource);
- zend_list_delete(resource_id);
- return NULL;
- }
-
- stream = php_ssh2_scp_xfer(session, resource_id, resource->path TSRMLS_CC);
- if (!stream) {
- zend_list_delete(resource_id);
- }
- php_url_free(resource);
-
- return stream;
-}
-/* }}} */
-
-static php_stream_wrapper_ops php_ssh2_scp_stream_wops = {
- php_ssh2_fopen_wrapper_scp,
- NULL, /* stream_close */
- NULL, /* stat */
- NULL, /* stat_url */
- NULL, /* opendir */
- "ssh2.scp"
-};
-
-php_stream_wrapper php_ssh2_stream_wrapper_scp = {
- &php_ssh2_scp_stream_wops,
- NULL,
- 0
-};
-
-/* {{{ proto bool ssh2_scp_recv(resource session, string remote_file, string local_file)
- * Request a file via SCP
- */
-PHP_FUNCTION(ssh2_scp_recv)
-{
- LIBSSH2_SESSION *session;
- LIBSSH2_CHANNEL *remote_file;
- struct stat sb;
- php_stream *local_file;
- zval *zsession;
- char *remote_filename, *local_filename;
- int remote_filename_len, local_filename_len;
-
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rss", &zsession, &remote_filename, &remote_filename_len,
- &local_filename, &local_filename_len) == FAILURE) {
- RETURN_FALSE;
- }
-
- ZEND_FETCH_RESOURCE(session, LIBSSH2_SESSION*, &zsession, -1, PHP_SSH2_SESSION_RES_NAME, le_ssh2_session);
-
- remote_file = libssh2_scp_recv(session, remote_filename, &sb);
- if (!remote_file) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to receive remote file");
- RETURN_FALSE;
- }
- libssh2_channel_set_blocking(remote_file, 1);
-
- local_file = php_stream_open_wrapper(local_filename, "wb", ENFORCE_SAFE_MODE | REPORT_ERRORS, NULL);
- if (!local_file) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to write to local file");
- libssh2_channel_free(remote_file);
- RETURN_FALSE;
- }
-
- while (sb.st_size) {
- char buffer[8192];
- int bytes_read;
-
- bytes_read = libssh2_channel_read(remote_file, buffer, sb.st_size > 8192 ? 8192 : sb.st_size);
- if (bytes_read < 0) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error reading from remote file");
- libssh2_channel_free(remote_file);
- php_stream_close(local_file);
- RETURN_FALSE;
- }
- php_stream_write(local_file, buffer, bytes_read);
- sb.st_size -= bytes_read;
- }
-
- libssh2_channel_free(remote_file);
- php_stream_close(local_file);
-
- RETURN_TRUE;
-}
-/* }}} */
-
-/* {{{ proto stream ssh2_scp_send(resource session, string local_file, string remote_file[, int create_mode = 0644])
- * Send a file via SCP
- */
-PHP_FUNCTION(ssh2_scp_send)
-{
- LIBSSH2_SESSION *session;
- LIBSSH2_CHANNEL *remote_file;
- php_stream *local_file;
- zval *zsession;
- char *local_filename, *remote_filename;
- int local_filename_len, remote_filename_len;
- long create_mode = 0644;
- php_stream_statbuf ssb;
- int argc = ZEND_NUM_ARGS();
-
- if (zend_parse_parameters(argc TSRMLS_CC, "rss|l", &zsession, &local_filename, &local_filename_len,
- &remote_filename, &remote_filename_len, &create_mode) == FAILURE) {
- 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");
- RETURN_FALSE;
- }
-
- if (php_stream_stat(local_file, &ssb)) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed statting local file");
- php_stream_close(local_file);
- RETURN_FALSE;
- }
-
- if (argc < 4) {
- create_mode = ssb.sb.st_mode & 0777;
- }
-
- remote_file = libssh2_scp_send_ex(session, remote_filename, create_mode, ssb.sb.st_size, ssb.sb.st_atime, ssb.sb.st_mtime);
- if (!remote_file) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failure creating remote file");
- php_stream_close(local_file);
- RETURN_FALSE;
- }
- libssh2_channel_set_blocking(remote_file, 1);
-
- 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 (bytesread <= 0 || bytesread > toread) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed copying file");
- php_stream_close(local_file);
- libssh2_channel_free(remote_file);
- RETURN_FALSE;
- }
-
- if (bytesread != libssh2_channel_write(remote_file, buffer, 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;
- }
-
- php_stream_close(local_file);
- libssh2_channel_free(remote_file);
- RETURN_TRUE;
-}
-/* }}} */
-
-/* ***************************
- * Direct TCP/IP Transport *
- *************************** */
-
-/* {{{ php_ssh2_direct_tcpip
- * Make a stream from a session
- */
-static php_stream *php_ssh2_direct_tcpip(LIBSSH2_SESSION *session, int resource_id, char *host, int port TSRMLS_DC)
-{
- LIBSSH2_CHANNEL *channel;
- php_ssh2_channel_data *channel_data;
- php_stream *stream;
-
- channel = libssh2_channel_direct_tcpip(session, host, port);
- if (!channel) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to request a channel from remote host");
- return NULL;
- }
-
- /* Turn it into a stream */
- channel_data = emalloc(sizeof(php_ssh2_channel_data));
- channel_data->channel = channel;
- channel_data->streamid = 0;
- channel_data->is_blocking = 0;
- channel_data->session_rsrc = resource_id;
- channel_data->refcount = NULL;
-
- stream = php_stream_alloc(&php_ssh2_channel_stream_ops, channel_data, 0, "r+");
-
- return stream;
-}
-/* }}} */
-
-/* {{{ php_ssh2_fopen_wrapper_tunnel
- * ssh2.tunnel:// fopen wrapper
- */
-static php_stream *php_ssh2_fopen_wrapper_tunnel(php_stream_wrapper *wrapper, char *path, char *mode, int options, char **opened_path, php_stream_context *context STREAMS_DC TSRMLS_DC)
-{
- LIBSSH2_SESSION *session = NULL;
- php_stream *stream = NULL;
- php_url *resource;
- char *host = NULL;
- int port = 0;
- int resource_id = 0;
-
- resource = php_ssh2_fopen_wraper_parse_path(path, "tunnel", context, &session, &resource_id, NULL, NULL TSRMLS_CC);
- if (!resource || !session) {
- return NULL;
- }
-
- if (resource->path && resource->path[0] == '/') {
- char *colon;
-
- host = resource->path + 1;
- if (*host == '[') {
- /* IPv6 Encapsulated Format */
- host++;
- colon = strstr(host, "]:");
- if (colon) {
- *colon = 0;
- colon += 2;
- }
- } else {
- colon = strchr(host, ':');
- if (colon) {
- *(colon++) = 0;
- }
- }
- if (colon) {
- port = atoi(colon);
- }
- }
-
- if ((port <= 0) || (port > 65535) || !host || (strlen(host) == 0)) {
- /* Invalid connection criteria */
- php_url_free(resource);
- zend_list_delete(resource_id);
- return NULL;
- }
-
- stream = php_ssh2_direct_tcpip(session, resource_id, host, port TSRMLS_CC);
- if (!stream) {
- zend_list_delete(resource_id);
- }
- php_url_free(resource);
-
- return stream;
-}
-/* }}} */
-
-static php_stream_wrapper_ops php_ssh2_tunnel_stream_wops = {
- php_ssh2_fopen_wrapper_tunnel,
- NULL, /* stream_close */
- NULL, /* stat */
- NULL, /* stat_url */
- NULL, /* opendir */
- "ssh2.tunnel"
-};
-
-php_stream_wrapper php_ssh2_stream_wrapper_tunnel = {
- &php_ssh2_tunnel_stream_wops,
- NULL,
- 0
-};
-
-/* {{{ proto stream ssh2_tunnel(resource session, string host, int port)
- * Tunnel to remote TCP/IP host/port
- */
-PHP_FUNCTION(ssh2_tunnel)
-{
- LIBSSH2_SESSION *session;
- php_stream *stream;
- zval *zsession;
- char *host;
- int host_len;
- long port;
-
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rsl", &zsession, &host, &host_len, &port) == FAILURE) {
- RETURN_FALSE;
- }
-
- ZEND_FETCH_RESOURCE(session, LIBSSH2_SESSION*, &zsession, -1, PHP_SSH2_SESSION_RES_NAME, le_ssh2_session);
-
- stream = php_ssh2_direct_tcpip(session, Z_LVAL_P(zsession), host, port TSRMLS_CC);
- if (!stream) {
- RETURN_FALSE;
- }
-
- /* Ensure that channels are freed BEFORE the sessions they belong to */
- zend_list_addref(Z_LVAL_P(zsession));
-
- php_stream_to_zval(stream, return_value);
-}
-/* }}} */
-
-/* ******************
- * Generic Helper *
- ****************** */
-
-/* {{{ proto stream ssh2_fetch_stream(stream channel, int streamid)
- * Fetch an extended data stream
- */
-PHP_FUNCTION(ssh2_fetch_stream)
-{
- php_ssh2_channel_data *data, *stream_data;
- php_stream *parent, *stream;
- zval *zparent;
- long streamid;
-
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl", &zparent, &streamid) == FAILURE) {
- RETURN_FALSE;
- }
-
- if (streamid < 0) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid stream ID requested");
- RETURN_FALSE;
- }
-
- php_stream_from_zval(parent, &zparent);
-
- if (parent->ops != &php_ssh2_channel_stream_ops) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Provided stream is not of type " PHP_SSH2_CHANNEL_STREAM_NAME);
- RETURN_FALSE;
- }
-
- data = (php_ssh2_channel_data*)parent->abstract;
-
- if (!data->refcount) {
- data->refcount = emalloc(sizeof(unsigned char));
- *(data->refcount) = 1;
- }
-
- if (*(data->refcount) == 255) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Too many streams associated to a single channel");
- RETURN_FALSE;
- }
-
- *(data->refcount)++;
-
- stream_data = emalloc(sizeof(php_ssh2_channel_data));
- memcpy(stream_data, data, sizeof(php_ssh2_channel_data));
- stream_data->streamid = streamid;
-
- stream = php_stream_alloc(&php_ssh2_channel_stream_ops, stream_data, 0, "r+");
- if (!stream) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error opening substream");
- efree(stream_data);
- *(data->refcount)--;
- RETURN_FALSE;
- }
-
- php_stream_to_zval(stream, return_value);
-}
-/* }}} */
-
-/*
- * 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
- */
|
[-]
[+]
|
Deleted |
ssh2-0.10.tgz/ssh2-0.10/ssh2_sftp.c
^
|
@@ -1,828 +0,0 @@
-/*
- +----------------------------------------------------------------------+
- | PHP Version 4 |
- +----------------------------------------------------------------------+
- | 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: Sara Golemon <pollita@php.net> |
- +----------------------------------------------------------------------+
-
- $Id: ssh2_sftp.c,v 1.3 2005/07/12 03:24:20 pollita Exp $
-*/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "php.h"
-#include "php_ssh2.h"
-#include "ext/standard/php_string.h"
-
-/* *************************
- * Resource Housekeeping *
- ************************* */
-
-void php_ssh2_sftp_dtor(zend_rsrc_list_entry *rsrc TSRMLS_DC)
-{
- php_ssh2_sftp_data *data = (php_ssh2_sftp_data*)rsrc->ptr;
-
- if (!data) {
- return;
- }
-
- libssh2_sftp_shutdown(data->sftp);
-
- zend_list_delete(data->session_rsrcid);
-
- efree(data);
-}
-
-/* *****************
- * SFTP File Ops *
- ***************** */
-
-inline unsigned long php_ssh2_parse_fopen_modes(char *openmode) {
- unsigned long flags = 0;
-
- if (strchr(openmode, 'a')) {
- flags |= LIBSSH2_FXF_APPEND;
- }
-
- if (strchr(openmode, 'w')) {
- flags |= LIBSSH2_FXF_WRITE | LIBSSH2_FXF_TRUNC | LIBSSH2_FXF_CREAT;
- }
-
- if (strchr(openmode, 'r')) {
- flags |= LIBSSH2_FXF_READ;
- }
-
- if (strchr(openmode, '+')) {
- flags |= LIBSSH2_FXF_READ | LIBSSH2_FXF_WRITE;
- }
-
- if (strchr(openmode, 'x')) {
- flags |= LIBSSH2_FXF_WRITE | LIBSSH2_FXF_TRUNC | LIBSSH2_FXF_EXCL | LIBSSH2_FXF_CREAT;
- }
-
- return flags;
-}
-
-inline int php_ssh2_sftp_attr2ssb(php_stream_statbuf *ssb, LIBSSH2_SFTP_ATTRIBUTES *attrs)
-{
- memset(ssb, 0, sizeof(php_stream_statbuf));
- if (attrs->flags & LIBSSH2_SFTP_ATTR_SIZE) {
- ssb->sb.st_size = attrs->filesize;
- }
- if (attrs->flags & LIBSSH2_SFTP_ATTR_UIDGID) {
- ssb->sb.st_uid = attrs->uid;
- ssb->sb.st_gid = attrs->gid;
- }
- if (attrs->flags & LIBSSH2_SFTP_ATTR_PERMISSIONS) {
- ssb->sb.st_mode = attrs->permissions;
- }
- if (attrs->flags & LIBSSH2_SFTP_ATTR_ACMODTIME) {
- ssb->sb.st_atime = attrs->atime;
- ssb->sb.st_mtime = attrs->mtime;
- }
-
- return 0;
-}
-
-typedef struct _php_ssh2_sftp_handle_data {
- LIBSSH2_SFTP_HANDLE *handle;
-
- long sftp_rsrcid;
-} php_ssh2_sftp_handle_data;
-
-/* {{{ php_ssh2_sftp_stream_write
- */
-static size_t php_ssh2_sftp_stream_write(php_stream *stream, const char *buf, size_t count TSRMLS_DC)
-{
- php_ssh2_sftp_handle_data *data = (php_ssh2_sftp_handle_data*)stream->abstract;
-
- return libssh2_sftp_write(data->handle, buf, count);
-}
-/* }}} */
-
-/* {{{ php_ssh2_sftp_stream_read
- */
-static size_t php_ssh2_sftp_stream_read(php_stream *stream, char *buf, size_t count TSRMLS_DC)
-{
- php_ssh2_sftp_handle_data *data = (php_ssh2_sftp_handle_data*)stream->abstract;
-
- return libssh2_sftp_read(data->handle, buf, count);
-}
-/* }}} */
-
-/* {{{ php_ssh2_sftp_stream_close
- */
-static int php_ssh2_sftp_stream_close(php_stream *stream, int close_handle TSRMLS_DC)
-{
- php_ssh2_sftp_handle_data *data = (php_ssh2_sftp_handle_data*)stream->abstract;
-
- libssh2_sftp_close(data->handle);
- zend_list_delete(data->sftp_rsrcid);
- efree(data);
-
- return 0;
-}
-/* }}} */
-
-/* {{{ php_ssh2_sftp_stream_seek
- */
-static int php_ssh2_sftp_stream_seek(php_stream *stream, off_t offset, int whence, off_t *newoffset TSRMLS_DC)
-{
- php_ssh2_sftp_handle_data *data = (php_ssh2_sftp_handle_data*)stream->abstract;
-
- switch (whence) {
- case SEEK_END:
- {
- LIBSSH2_SFTP_ATTRIBUTES attrs;
-
- if (libssh2_sftp_fstat(data->handle, &attrs)) {
- return -1;
- }
- if ((attrs.flags & LIBSSH2_SFTP_ATTR_SIZE) == 0) {
- return -1;
- }
- offset += attrs.filesize;
- }
- case SEEK_CUR:
- {
- off_t current_offset = libssh2_sftp_tell(data->handle);
-
- if (current_offset < 0) {
- return -1;
- }
-
- offset += current_offset;
- }
- }
-
- libssh2_sftp_seek(data->handle, offset);
-
- if (newoffset) {
- *newoffset = offset;
- }
-
- return 0;
-}
-/* }}} */
-
-/* {{{ php_ssh2_sftp_stream_fstat
- */
-static int php_ssh2_sftp_stream_fstat(php_stream *stream, php_stream_statbuf *ssb TSRMLS_DC)
-{
- php_ssh2_sftp_handle_data *data = (php_ssh2_sftp_handle_data*)stream->abstract;
- LIBSSH2_SFTP_ATTRIBUTES attrs;
-
- if (libssh2_sftp_fstat(data->handle, &attrs)) {
- return -1;
- }
-
- return php_ssh2_sftp_attr2ssb(ssb, &attrs);
-}
-/* }}} */
-
-static php_stream_ops php_ssh2_sftp_stream_ops = {
- php_ssh2_sftp_stream_write,
- php_ssh2_sftp_stream_read,
- php_ssh2_sftp_stream_close,
- NULL, /* flush */
- PHP_SSH2_SFTP_STREAM_NAME,
- php_ssh2_sftp_stream_seek,
- NULL, /* cast */
- php_ssh2_sftp_stream_fstat,
- NULL, /* set_option */
-};
-
-/* {{{ php_ssh2_sftp_stream_opener
- */
-static php_stream *php_ssh2_sftp_stream_opener( php_stream_wrapper *wrapper, char *filename, char *mode,
- int options, char **opened_path, php_stream_context *context STREAMS_DC TSRMLS_DC)
-{
- php_ssh2_sftp_handle_data *data;
- LIBSSH2_SESSION *session = NULL;
- LIBSSH2_SFTP *sftp = NULL;
- LIBSSH2_SFTP_HANDLE *handle;
- php_stream *stream;
- int resource_id = 0, sftp_rsrcid = 0;
- php_url *resource;
- unsigned long flags;
- long perms = 0644;
-
- resource = php_ssh2_fopen_wraper_parse_path(filename, "sftp", context, &session, &resource_id, &sftp, &sftp_rsrcid TSRMLS_CC);
- if (!resource || !session || !sftp) {
- return NULL;
- }
-
- flags = php_ssh2_parse_fopen_modes(mode);
-
- handle = libssh2_sftp_open(sftp, resource->path, flags, perms);
- if (!handle) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to open %s on remote host", filename);
- php_url_free(resource);
- zend_list_delete(sftp_rsrcid);
- return NULL;
- }
-
- data = emalloc(sizeof(php_ssh2_sftp_handle_data));
- data->handle = handle;
- data->sftp_rsrcid = sftp_rsrcid;
-
- stream = php_stream_alloc(&php_ssh2_sftp_stream_ops, data, 0, mode);
- if (!stream) {
- libssh2_sftp_close(handle);
- zend_list_delete(sftp_rsrcid);
- efree(data);
- }
- php_url_free(resource);
-
- return stream;
-}
-/* }}} */
-
-/* **********************
- * SFTP Directory Ops *
- ********************** */
-
-/* {{{ php_ssh2_sftp_dirstream_read
- */
-static size_t php_ssh2_sftp_dirstream_read(php_stream *stream, char *buf, size_t count TSRMLS_DC)
-{
- php_ssh2_sftp_handle_data *data = (php_ssh2_sftp_handle_data*)stream->abstract;
- php_stream_dirent *ent = (php_stream_dirent*)buf;
- size_t bytesread = libssh2_sftp_readdir(data->handle, ent->d_name, sizeof(ent->d_name) - 1, NULL);
- char *basename = NULL;
- int basename_len = 0;
-
- if (bytesread <= 0) {
- return 0;
- }
- ent->d_name[bytesread] = 0;
-
-#ifdef ZEND_ENGINE_2
- php_basename(ent->d_name, bytesread, NULL, 0, &basename, &basename_len TSRMLS_CC);
-#else
-/* CURSE YOU BC BREAKS! */
- basename = php_basename(ent->d_name, bytesread, NULL, 0);
- if (basename) {
- basename_len = strlen(basename);
- }
-#endif
- if (!basename) {
- return 0;
- }
-
- if (!basename_len) {
- efree(basename);
- return 0;
- }
- bytesread = MIN(sizeof(ent->d_name) - 1, basename_len);
- memcpy(ent->d_name, basename, bytesread);
- ent->d_name[bytesread] = 0;
- efree(basename);
-
- /* Trim off trailing whitespace characters */
- bytesread--;
- while (bytesread >= 0 &&
- (ent->d_name[bytesread] == '\n' || ent->d_name[bytesread] == '\r' ||
- ent->d_name[bytesread] == '\t' || ent->d_name[bytesread] == ' ')) {
- ent->d_name[bytesread--] = '\0';
- }
-
- return sizeof(php_stream_dirent);
-}
-/* }}} */
-
-/* {{{ php_ssh2_sftp_dirstream_close
- */
-static int php_ssh2_sftp_dirstream_close(php_stream *stream, int close_handle TSRMLS_DC)
-{
- php_ssh2_sftp_handle_data *data = (php_ssh2_sftp_handle_data*)stream->abstract;
-
- libssh2_sftp_close(data->handle);
- zend_list_delete(data->sftp_rsrcid);
- efree(data);
-
- return 0;
-}
-/* }}} */
-
-static php_stream_ops php_ssh2_sftp_dirstream_ops = {
- NULL, /* write */
- php_ssh2_sftp_dirstream_read,
- php_ssh2_sftp_dirstream_close,
- NULL, /* flush */
- PHP_SSH2_SFTP_DIRSTREAM_NAME,
- NULL, /* seek */
- NULL, /* cast */
- NULL, /* fstat */
- NULL, /* set_option */
-};
-
-/* {{{ php_ssh2_sftp_dirstream_opener
- */
-static php_stream *php_ssh2_sftp_dirstream_opener( php_stream_wrapper *wrapper, char *filename, char *mode,
- int options, char **opened_path, php_stream_context *context STREAMS_DC TSRMLS_DC)
-{
- php_ssh2_sftp_handle_data *data;
- LIBSSH2_SESSION *session = NULL;
- LIBSSH2_SFTP *sftp = NULL;
- LIBSSH2_SFTP_HANDLE *handle;
- php_stream *stream;
- int resource_id = 0, sftp_rsrcid = 0;
- php_url *resource;
-
- resource = php_ssh2_fopen_wraper_parse_path(filename, "sftp", context, &session, &resource_id, &sftp, &sftp_rsrcid TSRMLS_CC);
- if (!resource || !session || !sftp) {
- return NULL;
- }
-
- handle = libssh2_sftp_opendir(sftp, resource->path);
- if (!handle) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to open %s on remote host", filename);
- php_url_free(resource);
- zend_list_delete(sftp_rsrcid);
- return NULL;
- }
-
- data = emalloc(sizeof(php_ssh2_sftp_handle_data));
- data->handle = handle;
- data->sftp_rsrcid = sftp_rsrcid;
-
- stream = php_stream_alloc(&php_ssh2_sftp_dirstream_ops, data, 0, mode);
- if (!stream) {
- libssh2_sftp_close(handle);
- zend_list_delete(sftp_rsrcid);
- efree(data);
- }
- php_url_free(resource);
-
- return stream;
-}
-/* }}} */
-
-/* ****************
- * SFTP Wrapper *
- **************** */
-
-#ifdef ZEND_ENGINE_2
-/* {{{ php_ssh2_sftp_urlstat
- */
-static int php_ssh2_sftp_urlstat(php_stream_wrapper *wrapper, char *url, int flags, php_stream_statbuf *ssb, php_stream_context *context TSRMLS_DC)
-{
- LIBSSH2_SFTP_ATTRIBUTES attrs;
- LIBSSH2_SESSION *session = NULL;
- LIBSSH2_SFTP *sftp = NULL;
- int resource_id = 0, sftp_rsrcid = 0;
- php_url *resource;
-
- resource = php_ssh2_fopen_wraper_parse_path(url, "sftp", context, &session, &resource_id, &sftp, &sftp_rsrcid TSRMLS_CC);
- if (!resource || !session || !sftp || !resource->path) {
- return -1;
- }
-
- if (libssh2_sftp_stat_ex(sftp, resource->path, strlen(resource->path),
- (flags & PHP_STREAM_URL_STAT_LINK) ? LIBSSH2_SFTP_LSTAT : LIBSSH2_SFTP_STAT, &attrs)) {
- php_url_free(resource);
- zend_list_delete(sftp_rsrcid);
- return -1;
- }
-
- /* parse_path addrefs the resource, but we're not holding on to it so we have to delref it before we leave */
- zend_list_delete(sftp_rsrcid);
-
- return php_ssh2_sftp_attr2ssb(ssb, &attrs);
-}
-/* }}} */
-
-/* {{{ php_ssh2_sftp_unlink
- */
-static int php_ssh2_sftp_unlink(php_stream_wrapper *wrapper, char *url, int options, php_stream_context *context TSRMLS_DC)
-{
- LIBSSH2_SESSION *session = NULL;
- LIBSSH2_SFTP *sftp = NULL;
- int resource_id = 0, sftp_rsrcid = 0;
- php_url *resource;
- int result;
-
- resource = php_ssh2_fopen_wraper_parse_path(url, "sftp", context, &session, &resource_id, &sftp, &sftp_rsrcid TSRMLS_CC);
- if (!resource || !session || !sftp || !resource->path) {
- return -1;
- }
-
- result = libssh2_sftp_unlink(sftp, resource->path);
- php_url_free(resource);
-
- zend_list_delete(sftp_rsrcid);
-
- return (result == 0) ? 0 : -1;
-}
-/* }}} */
-
-/* {{{ php_ssh2_sftp_rename
- */
-static int php_ssh2_sftp_rename(php_stream_wrapper *wrapper, char *url_from, char *url_to, int options, php_stream_context *context TSRMLS_DC)
-{
- LIBSSH2_SESSION *session = NULL;
- LIBSSH2_SFTP *sftp = NULL;
- int resource_id = 0, sftp_rsrcid = 0;
- php_url *resource, *resource_to;
- int result;
-
- if (strncmp(url_from, "ssh2.sftp://", sizeof("ssh2.sftp://") - 1) ||
- strncmp(url_to, "ssh2.sftp://", sizeof("ssh2.sftp://") - 1)) {
- return -1;
- }
-
- resource_to = php_url_parse(url_to);
- if (!resource_to || !resource_to->path) {
- return -1;
- }
-
- resource = php_ssh2_fopen_wraper_parse_path(url_from, "sftp", context, &session, &resource_id, &sftp, &sftp_rsrcid TSRMLS_CC);
- if (!resource || !session || !sftp || !resource->path) {
- php_url_free(resource_to);
- return -1;
- }
-
- result = libssh2_sftp_rename(sftp, resource->path, resource_to->path);
- php_url_free(resource);
-
- zend_list_delete(sftp_rsrcid);
-
- return (result == 0) ? 0 : -1;
-}
-/* }}} */
-
-/* {{{ php_ssh2_sftp_mkdir
- */
-static int php_ssh2_sftp_mkdir(php_stream_wrapper *wrapper, char *url, int mode, int options, php_stream_context *context TSRMLS_DC)
-{
- LIBSSH2_SESSION *session = NULL;
- LIBSSH2_SFTP *sftp = NULL;
- int resource_id = 0, sftp_rsrcid = 0;
- php_url *resource;
- int result;
-
- resource = php_ssh2_fopen_wraper_parse_path(url, "sftp", context, &session, &resource_id, &sftp, &sftp_rsrcid TSRMLS_CC);
- if (!resource || !session || !sftp || !resource->path) {
- return -1;
- }
-
- if (options & PHP_STREAM_MKDIR_RECURSIVE) {
- /* Just attempt to make every directory, some will fail, but we only care about the last success/failure */
- char *p = resource->path;
- while ((p = strchr(p + 1, '/'))) {
- libssh2_sftp_mkdir_ex(sftp, resource->path, p - resource->path, mode);
- }
- }
-
- result = libssh2_sftp_mkdir(sftp, resource->path, mode);
- php_url_free(resource);
-
- zend_list_delete(sftp_rsrcid);
-
- return (result == 0) ? 0 : -1;
-}
-/* }}} */
-
-/* {{{ php_ssh2_sftp_rmdir
- */
-static int php_ssh2_sftp_rmdir(php_stream_wrapper *wrapper, char *url, int options, php_stream_context *context TSRMLS_DC)
-{
- LIBSSH2_SESSION *session = NULL;
- LIBSSH2_SFTP *sftp = NULL;
- int resource_id = 0, sftp_rsrcid = 0;
- php_url *resource;
- int result;
-
- resource = php_ssh2_fopen_wraper_parse_path(url, "sftp", context, &session, &resource_id, &sftp, &sftp_rsrcid TSRMLS_CC);
- if (!resource || !session || !sftp || !resource->path) {
- return -1;
- }
-
- result = libssh2_sftp_rmdir(sftp, resource->path);
- php_url_free(resource);
-
- zend_list_delete(sftp_rsrcid);
-
- return (result == 0) ? 0 : -1;
-}
-/* }}} */
-#endif
-
-static php_stream_wrapper_ops php_ssh2_sftp_wrapper_ops = {
- php_ssh2_sftp_stream_opener,
- NULL, /* close */
- NULL, /* stat */
-#ifdef ZEND_ENGINE_2
- php_ssh2_sftp_urlstat,
-#else
- NULL, /* url_stat isn't actually functional prior to PHP5 */
-#endif
- php_ssh2_sftp_dirstream_opener,
- PHP_SSH2_SFTP_WRAPPER_NAME,
-#ifdef ZEND_ENGINE_2
- php_ssh2_sftp_unlink,
- php_ssh2_sftp_rename,
- php_ssh2_sftp_mkdir,
- php_ssh2_sftp_rmdir,
-#endif
-};
-
-php_stream_wrapper php_ssh2_sftp_wrapper = {
- &php_ssh2_sftp_wrapper_ops,
- NULL,
- 1,
- 0,
- NULL,
-};
-
-/* *****************
- * Userspace API *
- ***************** */
-
-
-/* {{{ proto resource ssh2_sftp(resource session)
- * Request the SFTP subsystem from an already connected SSH2 server
- */
-PHP_FUNCTION(ssh2_sftp)
-{
- LIBSSH2_SESSION *session;
- LIBSSH2_SFTP *sftp;
- php_ssh2_sftp_data *data;
- zval *zsession;
-
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zsession) == FAILURE) {
- RETURN_FALSE;
- }
-
- ZEND_FETCH_RESOURCE(session, LIBSSH2_SESSION*, &zsession, -1, PHP_SSH2_SESSION_RES_NAME, le_ssh2_session);
-
- sftp = libssh2_sftp_init(session);
- if (!sftp) {
- char *sess_err = "Unknown";
-
- libssh2_session_last_error(session, &sess_err, NULL, 0);
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to startup SFTP subsystem: %s", sess_err);
- RETURN_FALSE;
- }
-
- data = emalloc(sizeof(php_ssh2_sftp_data));
- data->session = session;
- data->sftp = sftp;
- data->session_rsrcid = Z_LVAL_P(zsession);
- zend_list_addref(Z_LVAL_P(zsession));
-
- ZEND_REGISTER_RESOURCE(return_value, data, le_ssh2_sftp);
-}
-/* }}} */
-
-/* Much of the stuff below can be done via wrapper ops as of PHP5, but is included here for PHP 4.3 users */
-
-/* {{{ proto bool ssh2_sftp_rename(resource sftp, string from, string to)
- */
-PHP_FUNCTION(ssh2_sftp_rename)
-{
- php_ssh2_sftp_data *data;
- zval *zsftp;
- char *src, *dst;
- int src_len, dst_len;
-
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rss", &zsftp, &src, &src_len, &dst, &dst_len) == FAILURE) {
- RETURN_FALSE;
- }
-
- ZEND_FETCH_RESOURCE(data, php_ssh2_sftp_data*, &zsftp, -1, PHP_SSH2_SFTP_RES_NAME, le_ssh2_sftp);
-
- RETURN_BOOL(!libssh2_sftp_rename_ex(data->sftp, src, src_len, dst, dst_len,
- LIBSSH2_SFTP_RENAME_OVERWRITE | LIBSSH2_SFTP_RENAME_ATOMIC | LIBSSH2_SFTP_RENAME_NATIVE));
-}
-/* }}} */
-
-/* {{{ proto bool ssh2_sftp_unlink(resource sftp, string filename)
- */
-PHP_FUNCTION(ssh2_sftp_unlink)
-{
- php_ssh2_sftp_data *data;
- zval *zsftp;
- char *filename;
- int filename_len;
-
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &zsftp, &filename, &filename_len) == FAILURE) {
- RETURN_FALSE;
- }
-
- ZEND_FETCH_RESOURCE(data, php_ssh2_sftp_data*, &zsftp, -1, PHP_SSH2_SFTP_RES_NAME, le_ssh2_sftp);
-
- RETURN_BOOL(!libssh2_sftp_unlink_ex(data->sftp, filename, filename_len));
-}
-/* }}} */
-
-/* {{{ proto bool ssh2_sftp_mkdir(resource sftp, string filename[, int mode[, int recursive]])
- */
-PHP_FUNCTION(ssh2_sftp_mkdir)
-{
- php_ssh2_sftp_data *data;
- zval *zsftp;
- char *filename;
- int filename_len;
- long mode = 0777;
- zend_bool recursive = 0;
- char *p;
-
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs|lb", &zsftp, &filename, &filename_len, &mode, &recursive) == FAILURE) {
- RETURN_FALSE;
- }
-
- if (filename_len < 1) {
- RETURN_FALSE;
- }
-
- ZEND_FETCH_RESOURCE(data, php_ssh2_sftp_data*, &zsftp, -1, PHP_SSH2_SFTP_RES_NAME, le_ssh2_sftp);
-
- if (recursive) {
- /* Just attempt to make every directory, some will fail, but we only care about the last success/failure */
- p = filename;
- while ((p = strchr(p + 1, '/'))) {
- libssh2_sftp_mkdir_ex(data->sftp, filename, p - filename, mode);
- }
- }
-
-
- RETURN_BOOL(!libssh2_sftp_mkdir_ex(data->sftp, filename, filename_len, mode));
-}
-/* }}} */
-
-/* {{{ proto bool ssh2_sftp_rmdir(resource sftp, string filename)
- */
-PHP_FUNCTION(ssh2_sftp_rmdir)
-{
- php_ssh2_sftp_data *data;
- zval *zsftp;
- char *filename;
- int filename_len;
-
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &zsftp, &filename, &filename_len) == FAILURE) {
- RETURN_FALSE;
- }
-
- ZEND_FETCH_RESOURCE(data, php_ssh2_sftp_data*, &zsftp, -1, PHP_SSH2_SFTP_RES_NAME, le_ssh2_sftp);
-
- RETURN_BOOL(!libssh2_sftp_rmdir_ex(data->sftp, filename, filename_len));
-}
-/* }}} */
-
-/* {{{ php_ssh2_sftp_stat_func
- * In PHP4.3 this is the only way to request stat into, in PHP >= 5 you can use the fopen wrapper approach
- * Both methods will return identical structures
- * (well, the other one will include other values set to 0 but they don't count)
- */
-static void php_ssh2_sftp_stat_func(INTERNAL_FUNCTION_PARAMETERS, int stat_type)
-{
- php_ssh2_sftp_data *data;
- LIBSSH2_SFTP_ATTRIBUTES attrs;
- zval *zsftp;
- char *path;
- int path_len;
-
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &zsftp, &path, &path_len) == FAILURE) {
- RETURN_FALSE;
- }
-
- ZEND_FETCH_RESOURCE(data, php_ssh2_sftp_data*, &zsftp, -1, PHP_SSH2_SFTP_RES_NAME, le_ssh2_sftp);
-
- if (libssh2_sftp_stat_ex(data->sftp, path, path_len, stat_type, &attrs)) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to stat remote file");
- RETURN_FALSE;
- }
-
- array_init(return_value);
-
- if (attrs.flags & LIBSSH2_SFTP_ATTR_SIZE) {
- add_index_long(return_value, 7, attrs.filesize);
- add_assoc_long(return_value, "size", attrs.filesize);
- }
- if (attrs.flags & LIBSSH2_SFTP_ATTR_UIDGID) {
- add_index_long(return_value, 4, attrs.uid);
- add_assoc_long(return_value, "uid", attrs.uid);
-
- add_index_long(return_value, 5, attrs.gid);
- add_assoc_long(return_value, "gid", attrs.gid);
- }
- if (attrs.flags & LIBSSH2_SFTP_ATTR_PERMISSIONS) {
- add_index_long(return_value, 2, attrs.permissions);
- add_assoc_long(return_value, "mode", attrs.permissions);
- }
- if (attrs.flags & LIBSSH2_SFTP_ATTR_ACMODTIME) {
- add_index_long(return_value, 8, attrs.atime);
- add_assoc_long(return_value, "atime", attrs.atime);
-
- add_index_long(return_value, 9, attrs.mtime);
- add_assoc_long(return_value, "mtime", attrs.mtime);
- }
-}
-/* }}} */
-
-/* {{{ proto array ssh2_sftp_stat(resource sftp, string path)
- */
-PHP_FUNCTION(ssh2_sftp_stat)
-{
- php_ssh2_sftp_stat_func(INTERNAL_FUNCTION_PARAM_PASSTHRU, LIBSSH2_SFTP_STAT);
-}
-/* }}} */
-
-/* {{{ proto array ssh2_sftp_lstat(resource sftp, string path)
- */
-PHP_FUNCTION(ssh2_sftp_lstat)
-{
- php_ssh2_sftp_stat_func(INTERNAL_FUNCTION_PARAM_PASSTHRU, LIBSSH2_SFTP_LSTAT);
-}
-/* }}} */
-
-/* {{{ proto bool ssh2_sftp_symlink(resource sftp, string target, string link)
- */
-PHP_FUNCTION(ssh2_sftp_symlink)
-{
- php_ssh2_sftp_data *data;
- zval *zsftp;
- char *targ, *link;
- int targ_len, link_len;
-
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rss", &zsftp, &targ, &targ_len, &link, &link_len) == FAILURE) {
- RETURN_FALSE;
- }
-
- ZEND_FETCH_RESOURCE(data, php_ssh2_sftp_data*, &zsftp, -1, PHP_SSH2_SFTP_RES_NAME, le_ssh2_sftp);
-
- RETURN_BOOL(!libssh2_sftp_symlink_ex(data->sftp, targ, targ_len, link, link_len, LIBSSH2_SFTP_SYMLINK));
-}
-/* }}} */
-
-/* {{{ proto string ssh2_sftp_readlink(resource sftp, string link)
- */
-PHP_FUNCTION(ssh2_sftp_readlink)
-{
- php_ssh2_sftp_data *data;
- zval *zsftp;
- char *link;
- int targ_len = 0, link_len;
- char targ[8192];
-
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &zsftp, &link, &link_len) == FAILURE) {
- RETURN_FALSE;
- }
-
- ZEND_FETCH_RESOURCE(data, php_ssh2_sftp_data*, &zsftp, -1, PHP_SSH2_SFTP_RES_NAME, le_ssh2_sftp);
-
- if ((targ_len = libssh2_sftp_symlink_ex(data->sftp, link, link_len, targ, 8192, LIBSSH2_SFTP_READLINK)) < 0) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to read link '%s'", link);
- RETURN_FALSE;
- }
-
- RETURN_STRINGL(targ, targ_len, 1);
-}
-/* }}} */
-
-/* {{{ proto string ssh2_sftp_realpath(resource sftp, string filename)
- */
-PHP_FUNCTION(ssh2_sftp_realpath)
-{
- php_ssh2_sftp_data *data;
- zval *zsftp;
- char *link;
- int targ_len = 0, link_len;
- char targ[8192];
-
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &zsftp, &link, &link_len) == FAILURE) {
- RETURN_FALSE;
- }
-
- ZEND_FETCH_RESOURCE(data, php_ssh2_sftp_data*, &zsftp, -1, PHP_SSH2_SFTP_RES_NAME, le_ssh2_sftp);
-
- if ((targ_len = libssh2_sftp_symlink_ex(data->sftp, link, link_len, targ, 8192, LIBSSH2_SFTP_REALPATH)) < 0) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to resolve realpath for '%s'", link);
- RETURN_FALSE;
- }
-
- RETURN_STRINGL(targ, targ_len, 1);
-}
-/* }}} */
-
-
-/*
- * Local variables:
- * tab-width: 4
- * c-basic-offset: 4
- * indent-tabs-mode: t
- * End:
- */
-
|
|
Deleted |
ssh2-0.11.0.tgz
^
|
[-]
[+]
|
Changed |
ssh2-0.11.3.tgz/package.xml
^
|
@@ -1,85 +1,142 @@
-<?xml version="1.0" encoding="ISO-8859-1" ?>
-<!DOCTYPE package SYSTEM "http://pear.php.net/dtd/package-1.0">
-<package version="1.0" packagerversion="1.4.0a11">
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<package packagerversion="1.9.4" version="2.0" xmlns="http://pear.php.net/dtd/package-2.0" xmlns:tasks="http://pear.php.net/dtd/tasks-1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://pear.php.net/dtd/tasks-1.0 http://pear.php.net/dtd/tasks-1.0.xsd http://pear.php.net/dtd/package-2.0 http://pear.php.net/dtd/package-2.0.xsd">
<name>ssh2</name>
+ <channel>pecl.php.net</channel>
<summary>Bindings for the libssh2 library</summary>
<description>Provides bindings to the functions of libssh2 which implements the SSH2 protocol.
-libssh2 is available from http://www.sourceforge.net/projects/libssh2
- </description>
- <maintainers>
- <maintainer>
- <user>pollita</user>
- <name>Sara Golemon</name>
- <email>pollita@php.net</email>
- <role>lead</role>
- </maintainer>
- </maintainers>
- <release>
- <version>0.10</version>
- <date>2005-11-01</date>
- <license>PHP</license>
- <state>beta</state>
- <notes>Added support for publickey subsystem.
- </notes>
- <filelist>
- <file role="src" md5sum="12b8ef1934148870119377dd4962d4af" name="config.m4"/>
- <file role="src" md5sum="200bf8829c3ff3135cb846cefa61a2d7" name="ssh2.c"/>
- <file role="src" md5sum="c85f481d22c64cdf886e678608fd5241" name="php_ssh2.h"/>
- <file role="src" md5sum="14b8e1cb196f67a1fa019229a8d35d6b" name="ssh2_fopen_wrappers.c"/>
- <file role="src" md5sum="cd55b1d8e108accdb4df7ee2036fba3b" name="ssh2_sftp.c"/>
- </filelist>
- </release>
+ libssh2 is available from http:/libssh2.org/</description>
+ <lead>
+ <name>Pierre Joye</name>
+ <user>pajoye</user>
+ <email>pierre@php.net</email>
+ <active>yes</active>
+ </lead>
+ <lead>
+ <name>Mike Sullivan</name>
+ <user>mikesul</user>
+ <email>mikesul@php.net</email>
+ <active>yes</active>
+ </lead>
+ <lead>
+ <name>Sara Golemon</name>
+ <user>pollita</user>
+ <email>pollita@php.net</email>
+ <active>no</active>
+ </lead>
+ <date>2011-09-27</date>
+ <time>20:05:05</time>
+ <version>
+ <release>0.11.3</release>
+ <api>0.11.0</api>
+ </version>
+ <stability>
+ <release>beta</release>
+ <api>beta</api>
+ </stability>
+ <license uri="http://www.php.net/license">PHP License</license>
+ <notes>
+- Fixed bug#24349 (ssh2_sftp_mkdir fails with trailing slash)
+- Fixed bug#22729 (using ssh2.sftp stream on 64bit vs. 32bit)
+- Fixed bug#22671 (trailing spaces trimmed from filenames)
+- Fixed bug#17142 (Missing EOF detection in ssh2.sftp:// streams)
+- Fixed bug#16944 (Segmentation fault SIGSEGV with protected variable with ssh2)
+ </notes>
+ <contents>
+ <dir name="/">
+ <file md5sum="caca90a751e033c1d8225a6497507b64" name="config.m4" role="src" />
+ <file md5sum="d9800f20e0598cbd97f736df5ed4e2ba" name="ssh2.c" role="src" />
+ <file md5sum="723e46cb3e17c21ac39f6fdf6b9ae241" name="php_ssh2.h" role="src" />
+ <file md5sum="44849685a0c28737e5162010e47149f4" name="ssh2_fopen_wrappers.c" role="src" />
+ <file md5sum="18f51ab86b10a5761da04ec3711bbef6" name="ssh2_sftp.c" role="src" />
+ </dir>
+ </contents>
+ <dependencies>
+ <required>
+ <php>
+ <min>4.0.0</min>
+ <max>6.0.0</max>
+ </php>
+ <pearinstaller>
+ <min>1.4.0</min>
+ </pearinstaller>
+ </required>
+ </dependencies>
+ <providesextension>ssh2</providesextension>
+ <extsrcrelease>
+ <configureoption default="autodetect" name="with-ssh2" prompt="libssh2 prefix?" />
+ </extsrcrelease>
<changelog>
- <release>
- <version>0.9</version>
- <date>2005-07-04</date>
- <state>beta</state>
- <notes>Fix version check bugs found in release 0.8.
-Add pty option to ssh2_exec().
- </notes>
- </release>
- <release>
- <version>0.8</version>
- <date>2005-05-17</date>
- <state>beta</state>
- <notes>Fixed feof() detection, removed unnecessary sleep() in channel shutdown, and simplified session detection.
-Note: All users are recommended to use libssh2 >= 0.10 as it contains important bugfixes (particularly in the SFTP layer).
- </notes>
- </release>
- <release>
- <version>0.7</version>
- <date>2005-02-24</date>
- <state>beta</state>
- <notes>Fixed socket leak bug. Connections wern't being closed like they were supposed to.
-Add ssh2_auth_hostbased_file() for hostkey authentication.
- </notes>
- </release>
- <release>
- <version>0.6</version>
- <date>2005-02-09</date>
- <state>beta</state>
- <notes>Minor fixes including some added error handling and more discriptive ./configure message.
-Users of PHP/SSH2 are recommended to upgrade their installation of libssh2 to version 0.6
-whether or not upgrading the PHP/SSH2 extension.
- </notes>
- </release>
- <release>
- <version>0.5</version>
- <date>2005-01-10</date>
- <state>beta</state>
- <notes>Added port forwarding support (requires libssh2-0.5) and
-modified ssh2_methods_negotiated() to work with modified libssh2 prototype.
-Note: Version PECL/ssh2 0.4.1 is incompatable with libssh2 >= 0.5
-Both should be upgraded in tandem, though PECL/ssh2 0.5 will work with libssh2 >= 0.4
- </notes>
- </release>
- <release>
- <version>0.4.1</version>
- <date>2004-12-24</date>
- <state>beta</state>
- <notes>Happy Holidays!
-Version 0.4 of the ssh2 extension requires libssh2 version 0.4 or higher
- </notes>
- </release>
+ <release>
+ <date>2009-11-28</date>
+ <version>
+ <release>0.11.1</release>
+ <api>0.11.0</api>
+ </version>
+ <stability>
+ <release>beta</release>
+ <api>beta</api>
+ </stability>
+ <license uri="http://www.php.net/license">PHP License</license>
+ <notes>
+- Fixed the extension version info
+. no other changes since 0.11.1
+ </notes>
+ </release>
+ <release>
+ <date>2009-11-28</date>
+ <version>
+ <release>0.11.1</release>
+ <api>0.11.0</api>
+ </version>
+ <stability>
+ <release>beta</release>
+ <api>beta</api>
+ </stability>
+ <license uri="http://www.php.net/license">PHP License</license>
+ <notes>
+- Fixed bug #9500, SSH2 sockets not being closed properly because of close vs closesocket difference
+- Fixed Windows support
+- Support for latest libssh2 release
+- Fix build with PHP 5.3
+- Fixed incorrect return values for rename/unlink/mkdir/rmdir with sftp functions/streams
+- Fixed various memory leaks and segfaults
+ </notes>
+ </release>
+ <release>
+ <date>2009-11-28</date>
+ <version>
+ <release>0.11.1-dev</release>
+ <api>0.11.0</api>
+ </version>
+ <stability>
+ <release>beta</release>
+ <api>beta</api>
+ </stability>
+ <license uri="http://www.php.net/license">PHP License</license>
+ <notes>
+- Support for latest libssh2 release
+- Fix build with PHP 5.3
+- Fixed incorrect return values for rename/unlink/mkdir/rmdir with sftp functions/streams
+- Fixed various memory leaks and segfaults
+ </notes>
+ </release>
+ <release>
+ <date>2008-12-08</date>
+ <version>
+ <release>0.11.0</release>
+ <api>0.11.0</api>
+ </version>
+ <stability>
+ <release>beta</release>
+ <api>beta</api>
+ </stability>
+ <license uri="http://www.php.net/license">PHP License</license>
+ <notes>
+- Support for latest libssh2 release
+- Fix build with PHP 5.3
+- Fixed incorrect return values for rename/unlink/mkdir/rmdir with sftp functions/streams
+- Fixed various memory leaks and segfaults
+ </notes>
+ </release>
</changelog>
</package>
|
[-]
[+]
|
Added |
ssh2-0.11.3.tgz/ssh2-0.11.3/config.m4
^
|
@@ -0,0 +1,81 @@
+dnl $Id: config.m4 209383 2006-03-15 02:10:23Z pollita $
+dnl config.m4 for extension ssh2
+
+PHP_ARG_WITH(ssh2, for ssh2 support,
+[ --with-ssh2=[DIR] Include ssh2 support])
+
+if test "$PHP_SSH2" != "no"; then
+ SEARCH_PATH="/usr/local /usr"
+ SEARCH_FOR="/include/libssh2.h"
+ if test -r $PHP_SSH2/$SEARCH_FOR; then # path given as parameter
+ SSH2_DIR=$PHP_SSH2
+ else
+ AC_MSG_CHECKING([for ssh2 files in default path])
+ for i in $SEARCH_PATH ; do
+ if test -r $i/$SEARCH_FOR; then
+ SSH2_DIR=$i
+ AC_MSG_RESULT(found in $i)
+ fi
+ done
+ fi
+
+ if test -z "$SSH2_DIR"; then
+ AC_MSG_RESULT([not found])
+ AC_MSG_ERROR([The required libssh2 library was not found. You can obtain that package from http://sourceforge.net/projects/libssh2/])
+ fi
+
+ PHP_ADD_INCLUDE($SSH2_DIR/include)
+
+ LIBNAME=ssh2
+ LIBSYMBOL=libssh2_banner_set
+
+ PHP_CHECK_LIBRARY($LIBNAME,$LIBSYMBOL,
+ [
+ PHP_ADD_LIBRARY_WITH_PATH($LIBNAME, $SSH2_DIR/lib, SSH2_SHARED_LIBADD)
+ AC_DEFINE(HAVE_SSH2LIB,1,[Have libssh2])
+ ],[
+ AC_MSG_ERROR([libssh2 version >= 0.4 not found])
+ ],[
+ -L$SSH2_DIR/lib -lm
+ ])
+
+ PHP_CHECK_LIBRARY($LIBNAME,libssh2_channel_forward_listen_ex,
+ [
+ AC_DEFINE(PHP_SSH2_REMOTE_FORWARDING, 1, [Have libssh2 with remote forwarding])
+ ],[
+ AC_MSG_WARN([libssh2 <= 0.4, remote forwarding not enabled])
+ ],[
+ -L$SSH2_DIR/lib -lm
+ ])
+
+ PHP_CHECK_LIBRARY($LIBNAME,libssh2_userauth_hostbased_fromfile_ex,
+ [
+ AC_DEFINE(PHP_SSH2_HOSTBASED_AUTH, 1, [Have libssh2 with hostbased authentication])
+ ],[
+ AC_MSG_WARN([libssh2 <= 0.6, hostbased authentication not enabled])
+ ],[
+ -L$SSH2_DIR/lib -lm
+ ])
+
+ PHP_CHECK_LIBRARY($LIBNAME,libssh2_poll,
+ [
+ AC_DEFINE(PHP_SSH2_POLL, 1, [Have libssh2 with poll() support])
+ ],[
+ AC_MSG_WARN([libssh2 <= 0.7, poll support not enabled])
+ ],[
+ -L$SSH2_DIR/lib -lm
+ ])
+
+ PHP_CHECK_LIBRARY($LIBNAME,libssh2_publickey_init,
+ [
+ AC_DEFINE(PHP_SSH2_PUBLICKEY_SUBSYSTEM, 1, [Have libssh2 with publickey subsystem support])
+ ],[
+ AC_MSG_WARN([libssh2 <= 0.11, publickey subsystem support not enabled])
+ ],[
+ -L$SSH2_DIR/lib -lm
+ ])
+
+ PHP_SUBST(SSH2_SHARED_LIBADD)
+
+ PHP_NEW_EXTENSION(ssh2, ssh2.c ssh2_fopen_wrappers.c ssh2_sftp.c, $ext_shared)
+fi
|
[-]
[+]
|
Added |
ssh2-0.11.3.tgz/ssh2-0.11.3/php_ssh2.h
^
|
@@ -0,0 +1,222 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 4 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997-2006 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: Sara Golemon <pollita@php.net> |
+ +----------------------------------------------------------------------+
+
+ $Id: php_ssh2.h 306892 2010-12-30 23:59:55Z pajoye $
+*/
+
+#ifndef PHP_SSH2_H
+#define PHP_SSH2_H
+
+#include <libssh2.h>
+#include <libssh2_sftp.h>
+#include "ext/standard/url.h"
+
+#define PHP_SSH2_VERSION "0.11.3-dev"
+#define PHP_SSH2_DEFAULT_PORT 22
+
+/* Exported Constants */
+#define PHP_SSH2_FINGERPRINT_MD5 0x0000
+#define PHP_SSH2_FINGERPRINT_SHA1 0x0001
+#define PHP_SSH2_FINGERPRINT_HEX 0x0000
+#define PHP_SSH2_FINGERPRINT_RAW 0x0002
+
+#define PHP_SSH2_TERM_UNIT_CHARS 0x0000
+#define PHP_SSH2_TERM_UNIT_PIXELS 0x0001
+
+#define PHP_SSH2_DEFAULT_TERMINAL "vanilla"
+#define PHP_SSH2_DEFAULT_TERM_WIDTH 80
+#define PHP_SSH2_DEFAULT_TERM_HEIGHT 25
+#define PHP_SSH2_DEFAULT_TERM_UNIT PHP_SSH2_TERM_UNIT_CHARS
+
+#define PHP_SSH2_SESSION_RES_NAME "SSH2 Session"
+#define PHP_SSH2_CHANNEL_STREAM_NAME "SSH2 Channel"
+#define PHP_SSH2_LISTENER_RES_NAME "SSH2 Listener"
+#define PHP_SSH2_SFTP_RES_NAME "SSH2 SFTP"
+#define PHP_SSH2_PKEY_SUBSYS_RES_NAME "SSH2 Publickey Subsystem"
+
+#define PHP_SSH2_SFTP_STREAM_NAME "SSH2 SFTP File"
+#define PHP_SSH2_SFTP_DIRSTREAM_NAME "SSH2 SFTP Directory"
+#define PHP_SSH2_SFTP_WRAPPER_NAME "SSH2 SFTP"
+
+#define PHP_SSH2_LISTEN_MAX_QUEUED 16
+
+#define PHP_SSH2_DEFAULT_POLL_TIMEOUT 30
+
+extern zend_module_entry ssh2_module_entry;
+#define phpext_ssh2_ptr &ssh2_module_entry
+
+typedef struct _php_ssh2_session_data {
+ /* Userspace callback functions */
+ zval *ignore_cb;
+ zval *debug_cb;
+ zval *macerror_cb;
+ zval *disconnect_cb;
+
+ int socket;
+
+#ifdef ZTS
+ /* Avoid unnecessary TSRMLS_FETCH() calls */
+ TSRMLS_D;
+#endif
+} php_ssh2_session_data;
+
+typedef struct _php_ssh2_sftp_data {
+ LIBSSH2_SESSION *session;
+ LIBSSH2_SFTP *sftp;
+
+ int session_rsrcid;
+} php_ssh2_sftp_data;
+
+#ifdef PHP_SSH2_REMOTE_FORWARDING
+typedef struct _php_ssh2_listener_data {
+ LIBSSH2_SESSION *session;
+ LIBSSH2_LISTENER *listener;
+
+ int session_rsrcid;
+} php_ssh2_listener_data;
+#endif
+
+#ifdef PHP_SSH2_PUBLICKEY_SUBSYSTEM
+#include "libssh2_publickey.h"
+
+typedef struct _php_ssh2_pkey_subsys_data {
+ LIBSSH2_SESSION *session;
+ LIBSSH2_PUBLICKEY *pkey;
+
+ int session_rsrcid;
+} php_ssh2_pkey_subsys_data;
+#endif
+
+#ifndef PHP_WIN32
+#define closesocket(s) close(s)
+#endif
+
+#ifdef ZTS
+#define SSH2_TSRMLS_SET(datap) ((php_ssh2_session_data*)(datap))->tsrm_ls = TSRMLS_C
+#define SSH2_TSRMLS_FETCH(datap) TSRMLS_D = ((php_ssh2_session_data*)(datap))->tsrm_ls
+#else
+#define SSH2_TSRMLS_SET(datap)
+#define SSH2_TSRMLS_FETCH(datap)
+#endif
+
+#if (PHP_MAJOR_VERSION == 5) && (PHP_MINOR_VERSION >= 3)
+#define ZEND_IS_CALLABLE_TSRMLS_CC TSRMLS_CC
+#else
+#define ZEND_IS_CALLABLE_TSRMLS_CC
+#endif
+
+/* < 5.3 compatibility */
+#ifndef Z_REFCOUNT_P
+#define Z_REFCOUNT_P(pz) (pz)->refcount
+#define Z_REFCOUNT_PP(ppz) Z_REFCOUNT_P(*(ppz))
+#endif
+
+#ifndef Z_SET_REFCOUNT_P
+#define Z_SET_REFCOUNT_P(pz, rc) (pz)->refcount = rc
+#define Z_SET_REFCOUNT_PP(ppz, rc) Z_SET_REFCOUNT_P(*(ppz), rc)
+#endif
+
+#ifndef Z_ISREF_P
+#define Z_ISREF_P(pz) (pz)->is_ref
+#define Z_ISREF_PP(ppz) Z_ISREF_P(*(ppz))
+#endif
+
+#ifndef Z_SET_ISREF_P
+#define Z_SET_ISREF_P(pz) (pz)->is_ref = 1
+#define Z_SET_ISREF_PP(ppz) Z_SET_ISREF_P(*(ppz))
+#endif
+
+#ifndef Z_UNSET_ISREF_P
+#define Z_UNSET_ISREF_P(pz) (pz)->is_ref = 0
+#define Z_UNSET_ISREF_PP(ppz) Z_UNSET_ISREF_P(*(ppz))
+#endif
+
+
+typedef struct _php_ssh2_channel_data {
+ LIBSSH2_CHANNEL *channel;
+
+ /* Distinguish which stream we should read/write from/to */
+ unsigned int streamid;
+ char is_blocking;
+
+ /* Resource ID, zend_list_addref() when opening, zend_list_delete() when closing */
+ long session_rsrc;
+
+ /* Allow one stream to be closed while the other is kept open */
+ unsigned char *refcount;
+
+} php_ssh2_channel_data;
+
+/* In ssh2_fopen_wrappers.c */
+PHP_FUNCTION(ssh2_shell);
+PHP_FUNCTION(ssh2_exec);
+PHP_FUNCTION(ssh2_tunnel);
+PHP_FUNCTION(ssh2_scp_recv);
+PHP_FUNCTION(ssh2_scp_send);
+PHP_FUNCTION(ssh2_fetch_stream);
+
+/* In ssh2_sftp.c */
+PHP_FUNCTION(ssh2_sftp);
+
+PHP_FUNCTION(ssh2_sftp_rename);
+PHP_FUNCTION(ssh2_sftp_unlink);
+PHP_FUNCTION(ssh2_sftp_mkdir);
+PHP_FUNCTION(ssh2_sftp_rmdir);
+PHP_FUNCTION(ssh2_sftp_stat);
+PHP_FUNCTION(ssh2_sftp_lstat);
+PHP_FUNCTION(ssh2_sftp_symlink);
+PHP_FUNCTION(ssh2_sftp_readlink);
+PHP_FUNCTION(ssh2_sftp_realpath);
+
+LIBSSH2_SESSION *php_ssh2_session_connect(char *host, int port, zval *methods, zval *callbacks TSRMLS_DC);
+void php_ssh2_sftp_dtor(zend_rsrc_list_entry *rsrc TSRMLS_DC);
+php_url *php_ssh2_fopen_wraper_parse_path( char *path, char *type, php_stream_context *context,
+ LIBSSH2_SESSION **psession, int *presource_id,
+ LIBSSH2_SFTP **psftp, int *psftp_rsrcid
+ TSRMLS_DC);
+
+extern php_stream_ops php_ssh2_channel_stream_ops;
+
+extern php_stream_wrapper php_ssh2_stream_wrapper_shell;
+extern php_stream_wrapper php_ssh2_stream_wrapper_exec;
+extern php_stream_wrapper php_ssh2_stream_wrapper_tunnel;
+extern php_stream_wrapper php_ssh2_stream_wrapper_scp;
+extern php_stream_wrapper php_ssh2_sftp_wrapper;
+
+/* Resource list entries */
+extern int le_ssh2_session;
+extern int le_ssh2_sftp;
+
+/* {{{ ZIP_OPENBASEDIR_CHECKPATH(filename) */
+#if PHP_API_VERSION < 20100412
+# define SSH2_OPENBASEDIR_CHECKPATH(filename) \
+ (PG(safe_mode) && (!php_checkuid(filename, NULL, CHECKUID_CHECK_FILE_AND_DIR))) || php_check_open_basedir(filename TSRMLS_CC)
+#else
+#define SSH2_OPENBASEDIR_CHECKPATH(filename) \
+ php_check_open_basedir(filename TSRMLS_CC)
+#endif
+/* }}} */
+#endif /* PHP_SSH2_H */
+
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * indent-tabs-mode: t
+ * End:
+ */
|
[-]
[+]
|
Added |
ssh2-0.11.3.tgz/ssh2-0.11.3/ssh2.c
^
|
@@ -0,0 +1,1343 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 4 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997-2006 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: Sara Golemon <pollita@php.net> |
+ +----------------------------------------------------------------------+
+
+ $Id: ssh2.c 317115 2011-09-21 17:40:23Z bjori $
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "php.h"
+#include "ext/standard/info.h"
+#include "ext/standard/file.h"
+#include "php_ssh2.h"
+#include "main/php_network.h"
+
+#if (OPENSSL_VERSION_NUMBER >= 0x00908000L)
+#include <openssl/applink.c>
+#endif
+
+/* Internal Constants */
+#ifndef SHA_DIGEST_LENGTH
+#define SHA_DIGEST_LENGTH 20
+#endif
+
+#ifndef MD5_DIGEST_LENGTH
+#define MD5_DIGEST_LENGTH 16
+#endif
+
+/* True global resources - no need for thread safety here */
+int le_ssh2_session;
+#ifdef PHP_SSH2_REMOTE_FORWARDING
+int le_ssh2_listener;
+#endif
+int le_ssh2_sftp;
+#ifdef PHP_SSH2_PUBLICKEY_SUBSYSTEM
+int le_ssh2_pkey_subsys;
+#endif
+
+ZEND_BEGIN_ARG_INFO(php_ssh2_first_arg_force_ref, 0)
+ ZEND_ARG_PASS_INFO(1)
+ZEND_END_ARG_INFO()
+
+/* *************
+ * Callbacks *
+ ************* */
+
+#ifdef ZTS
+#define PHP_SSH2_TSRMLS_FETCH() TSRMLS_D = *(void****)abstract;
+#else
+#define PHP_SSH2_TSRMLS_FETCH()
+#endif
+
+/* {{{ php_ssh2_alloc_cb
+ * Wrap emalloc()
+ */
+static LIBSSH2_ALLOC_FUNC(php_ssh2_alloc_cb)
+{
+ return emalloc(count);
+}
+/* }}} */
+
+/* {{{ php_ssh2_free_cb
+ * Wrap efree()
+ */
+static LIBSSH2_FREE_FUNC(php_ssh2_free_cb)
+{
+ efree(ptr);
+}
+/* }}} */
+
+/* {{{ php_ssh2_realloc_cb
+ * Wrap erealloc()
+ */
+static LIBSSH2_REALLOC_FUNC(php_ssh2_realloc_cb)
+{
+ return erealloc(ptr, count);
+}
+/* }}} */
+
+/* {{{ php_ssh2_debug_cb
+ * Debug packets
+ */
+LIBSSH2_DEBUG_FUNC(php_ssh2_debug_cb)
+{
+ php_ssh2_session_data *data;
+ zval *zdisplay, *zmessage, *zlanguage;
+ zval **args[3];
+ SSH2_TSRMLS_FETCH(*abstract);
+
+ if (!abstract || !*abstract) {
+ return;
+ }
+ data = (php_ssh2_session_data*)*abstract;
+ if (!data->debug_cb) {
+ return;
+ }
+
+ MAKE_STD_ZVAL(zmessage);
+ ZVAL_STRINGL(zmessage, (char*)message, message_len, 1);
+ args[0] = &zmessage;
+
+ MAKE_STD_ZVAL(zlanguage);
+ ZVAL_STRINGL(zlanguage, (char*)language, language_len, 1);
+ args[1] = &zlanguage;
+
+ MAKE_STD_ZVAL(zdisplay);
+ ZVAL_LONG(zdisplay, always_display);
+ args[2] = &zdisplay;
+
+ if (FAILURE == call_user_function_ex(NULL, NULL, data->disconnect_cb, NULL, 3, args, 0, NULL TSRMLS_CC)) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failure calling disconnect callback");
+ }
+ zval_ptr_dtor(&zdisplay);
+ zval_ptr_dtor(&zmessage);
+ zval_ptr_dtor(&zlanguage);
+}
+/* }}} */
+
+/* {{{ php_ssh2_ignore_cb
+ * Ignore packets
+ */
+LIBSSH2_IGNORE_FUNC(php_ssh2_ignore_cb)
+{
+ php_ssh2_session_data *data;
+ zval *zretval = NULL, *zmessage;
+ zval **args[1];
+ SSH2_TSRMLS_FETCH(*abstract);
+
+ if (!abstract || !*abstract) {
+ return;
+ }
+ data = (php_ssh2_session_data*)*abstract;
+ if (!data->ignore_cb) {
+ return;
+ }
+
+ MAKE_STD_ZVAL(zmessage);
+ ZVAL_STRINGL(zmessage, (char*)message, message_len, 1);
+ args[0] = &zmessage;
+
+ if (FAILURE == call_user_function_ex(NULL, NULL, data->ignore_cb, &zretval, 1, args, 0, NULL TSRMLS_CC)) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failure calling ignore callback");
+ }
+ zval_ptr_dtor(&zmessage);
+ if (zretval) {
+ zval_ptr_dtor(&zretval);
+ }
+}
+/* }}} */
+
+/* {{{ php_ssh2_macerror_cb
+ * Called when a MAC error occurs, offers the chance to ignore
+ * WHY ARE YOU IGNORING MAC ERRORS??????
+ */
+LIBSSH2_MACERROR_FUNC(php_ssh2_macerror_cb)
+{
+ php_ssh2_session_data *data;
+ zval *zretval = NULL, *zpacket;
+ zval **args[1];
+ int retval = -1;
+ SSH2_TSRMLS_FETCH(*abstract);
+
+ if (!abstract || !*abstract) {
+ return -1;
+ }
+ data = (php_ssh2_session_data*)*abstract;
+ if (!data->macerror_cb) {
+ return -1;
+ }
+
+ MAKE_STD_ZVAL(zpacket);
+ ZVAL_STRINGL(zpacket, (char*)packet, packet_len, 1);
+ args[0] = &zpacket;
+
+ if (FAILURE == call_user_function_ex(NULL, NULL, data->macerror_cb, &zretval, 1, args, 0, NULL TSRMLS_CC)) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failure calling macerror callback");
+ } else {
+ retval = zval_is_true(zretval) ? 0 : -1;
+ }
+ zval_ptr_dtor(&zpacket);
+ if (zretval) {
+ zval_ptr_dtor(&zretval);
+ }
+
+ return retval;
+}
+/* }}} */
+
+/* {{{ php_ssh2_disconnect_cb
+ * Connection closed by foreign host
+ */
+LIBSSH2_DISCONNECT_FUNC(php_ssh2_disconnect_cb)
+{
+ php_ssh2_session_data *data;
+ zval *zreason, *zmessage, *zlanguage;
+ zval **args[3];
+ SSH2_TSRMLS_FETCH(*abstract);
+
+ if (!abstract || !*abstract) {
+ return;
+ }
+ data = (php_ssh2_session_data*)*abstract;
+ if (!data->disconnect_cb) {
+ return;
+ }
+
+ MAKE_STD_ZVAL(zreason);
+ ZVAL_LONG(zreason, reason);
+ args[0] = &zreason;
+
+ MAKE_STD_ZVAL(zmessage);
+ ZVAL_STRINGL(zmessage, (char*)message, message_len, 1);
+ args[1] = &zmessage;
+
+ MAKE_STD_ZVAL(zlanguage);
+ ZVAL_STRINGL(zlanguage, (char*)language, language_len, 1);
+ args[2] = &zlanguage;
+
+ if (FAILURE == call_user_function_ex(NULL, NULL, data->disconnect_cb, NULL, 3, args, 0, NULL TSRMLS_CC)) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failure calling disconnect callback");
+ }
+ zval_ptr_dtor(&zreason);
+ zval_ptr_dtor(&zmessage);
+ zval_ptr_dtor(&zlanguage);
+}
+/* }}} */
+
+/* *****************
+ * Userspace API *
+ ***************** */
+
+/* {{{ php_ssh2_set_callback
+ * Try to set a method if it's passed in with the hash table
+ */
+static int php_ssh2_set_callback(LIBSSH2_SESSION *session, HashTable *ht, char *callback, int callback_len, int callback_type, php_ssh2_session_data *data TSRMLS_DC)
+{
+ zval **handler, *copyval;
+ void *internal_handler;
+
+ if (zend_hash_find(ht, callback, callback_len + 1, (void**)&handler) == FAILURE) {
+ return 0;
+ }
+
+ if (!handler || !*handler || !zend_is_callable(*handler, 0, NULL ZEND_IS_CALLABLE_TSRMLS_CC)) {
+ return -1;
+ }
+
+ ALLOC_INIT_ZVAL(copyval);
+ *copyval = **handler;
+ zval_copy_ctor(copyval);
+
+ switch (callback_type) {
+ case LIBSSH2_CALLBACK_IGNORE:
+ internal_handler = php_ssh2_ignore_cb;
+ if (data->ignore_cb) {
+ zval_ptr_dtor(&data->ignore_cb);
+ }
+ data->ignore_cb = copyval;
+ break;
+ case LIBSSH2_CALLBACK_DEBUG:
+ internal_handler = php_ssh2_debug_cb;
+ if (data->debug_cb) {
+ zval_ptr_dtor(&data->debug_cb);
+ }
+ data->debug_cb = copyval;
+ break;
+ case LIBSSH2_CALLBACK_MACERROR:
+ internal_handler = php_ssh2_macerror_cb;
+ if (data->macerror_cb) {
+ zval_ptr_dtor(&data->macerror_cb);
+ }
+ data->macerror_cb = copyval;
+ break;
+ case LIBSSH2_CALLBACK_DISCONNECT:
+ internal_handler = php_ssh2_disconnect_cb;
+ if (data->disconnect_cb) {
+ zval_ptr_dtor(&data->disconnect_cb);
+ }
+ data->disconnect_cb = copyval;
+ break;
+ default:
+ zval_ptr_dtor(©val);
+ return -1;
+ }
+
+ libssh2_session_callback_set(session, callback_type, internal_handler);
+
+ return 0;
+}
+/* }}} */
+
+/* {{{ php_ssh2_set_method
+ * Try to set a method if it's passed in with the hash table
+ */
+static int php_ssh2_set_method(LIBSSH2_SESSION *session, HashTable *ht, char *method, int method_len, int method_type)
+{
+ zval **value;
+
+ if (zend_hash_find(ht, method, method_len + 1, (void**)&value) == FAILURE) {
+ return 0;
+ }
+
+ if (!value || !*value || (Z_TYPE_PP(value) != IS_STRING)) {
+ return -1;
+ }
+
+ return libssh2_session_method_pref(session, method_type, Z_STRVAL_PP(value));
+}
+/* }}} */
+
+/* {{{ php_ssh2_session_connect
+ * Connect to an SSH server with requested methods
+ */
+LIBSSH2_SESSION *php_ssh2_session_connect(char *host, int port, zval *methods, zval *callbacks TSRMLS_DC)
+{
+ LIBSSH2_SESSION *session;
+ int socket;
+ php_ssh2_session_data *data;
+ struct timeval tv;
+
+ tv.tv_sec = FG(default_socket_timeout);
+ tv.tv_usec = 0;
+
+#if PHP_MAJOR_VERSION > 5 || (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION > 0)
+ socket = php_network_connect_socket_to_host(host, port, SOCK_STREAM, 0, &tv, NULL, NULL, NULL, 0 TSRMLS_CC);
+#elif PHP_MAJOR_VERSION == 5
+ socket = php_network_connect_socket_to_host(host, port, SOCK_STREAM, 0, &tv, NULL, NULL TSRMLS_CC);
+#else
+ socket = php_hostconnect(host, port, SOCK_STREAM, &tv TSRMLS_CC);
+#endif
+
+ if (socket <= 0) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to connect to %s on port %d", host, port);
+ return NULL;
+ }
+
+ data = ecalloc(1, sizeof(php_ssh2_session_data));
+ SSH2_TSRMLS_SET(data);
+ data->socket = socket;
+
+ session = libssh2_session_init_ex(php_ssh2_alloc_cb, php_ssh2_free_cb, php_ssh2_realloc_cb, data);
+ if (!session) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to initialize SSH2 session");
+ efree(data);
+ closesocket(socket);
+ return NULL;
+ }
+ libssh2_banner_set(session, LIBSSH2_SSH_DEFAULT_BANNER " PHP");
+
+ /* Override method preferences */
+ if (methods) {
+ zval **container;
+
+ if (php_ssh2_set_method(session, HASH_OF(methods), "kex", sizeof("kex") - 1, LIBSSH2_METHOD_KEX)) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed overriding KEX method");
+ }
+ if (php_ssh2_set_method(session, HASH_OF(methods), "hostkey", sizeof("hostkey") - 1, LIBSSH2_METHOD_HOSTKEY)) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed overriding HOSTKEY method");
+ }
+
+ if (zend_hash_find(HASH_OF(methods), "client_to_server", sizeof("client_to_server"), (void**)&container) == SUCCESS &&
+ container && *container && Z_TYPE_PP(container) == IS_ARRAY) {
+ if (php_ssh2_set_method(session, HASH_OF(*container), "crypt", sizeof("crypt") - 1, LIBSSH2_METHOD_CRYPT_CS)) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed overriding client to server CRYPT method");
+ }
+ if (php_ssh2_set_method(session, HASH_OF(*container), "mac", sizeof("mac") - 1, LIBSSH2_METHOD_MAC_CS)) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed overriding client to server MAC method");
+ }
+ if (php_ssh2_set_method(session, HASH_OF(*container), "comp", sizeof("comp") - 1, LIBSSH2_METHOD_COMP_CS)) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed overriding client to server COMP method");
+ }
+ if (php_ssh2_set_method(session, HASH_OF(*container), "lang", sizeof("lang") - 1, LIBSSH2_METHOD_LANG_CS)) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed overriding client to server LANG method");
+ }
+ }
+
+ if (zend_hash_find(HASH_OF(methods), "server_to_client", sizeof("server_to_client"), (void**)&container) == SUCCESS &&
+ container && *container && Z_TYPE_PP(container) == IS_ARRAY) {
+ if (php_ssh2_set_method(session, HASH_OF(*container), "crypt", sizeof("crypt") - 1, LIBSSH2_METHOD_CRYPT_SC)) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed overriding server to client CRYPT method");
+ }
+ if (php_ssh2_set_method(session, HASH_OF(*container), "mac", sizeof("mac") - 1, LIBSSH2_METHOD_MAC_SC)) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed overriding server to client MAC method");
+ }
+ if (php_ssh2_set_method(session, HASH_OF(*container), "comp", sizeof("comp") - 1, LIBSSH2_METHOD_COMP_SC)) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed overriding server to client COMP method");
+ }
+ if (php_ssh2_set_method(session, HASH_OF(*container), "lang", sizeof("lang") - 1, LIBSSH2_METHOD_LANG_SC)) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed overriding server to client LANG method");
+ }
+ }
+ }
+
+ /* Register Callbacks */
+ if (callbacks) {
+ /* ignore debug disconnect macerror */
+
+ if (php_ssh2_set_callback(session, HASH_OF(callbacks), "ignore", sizeof("ignore") - 1, LIBSSH2_CALLBACK_IGNORE, data TSRMLS_CC)) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed setting IGNORE callback");
+ }
+
+ if (php_ssh2_set_callback(session, HASH_OF(callbacks), "debug", sizeof("debug") - 1, LIBSSH2_CALLBACK_DEBUG, data TSRMLS_CC)) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed setting DEBUG callback");
+ }
+
+ if (php_ssh2_set_callback(session, HASH_OF(callbacks), "macerror", sizeof("macerror") - 1, LIBSSH2_CALLBACK_MACERROR, data TSRMLS_CC)) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed setting MACERROR callback");
+ }
+
+ if (php_ssh2_set_callback(session, HASH_OF(callbacks), "disconnect", sizeof("disconnect") - 1, LIBSSH2_CALLBACK_DISCONNECT, data TSRMLS_CC)) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed setting DISCONNECT callback");
+ }
+ }
+
+ if (libssh2_session_startup(session, socket)) {
+ int last_error = 0;
+ char *error_msg = NULL;
+
+ last_error = libssh2_session_last_error(session, &error_msg, NULL, 0);
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error starting up SSH connection(%d): %s", last_error, error_msg);
+ closesocket(socket);
+ libssh2_session_free(session);
+ efree(data);
+ return NULL;
+ }
+
+ return session;
+}
+/* }}} */
+
+/* {{{ proto resource ssh2_connect(string host[, int port[, array methods[, array callbacks]]])
+ * Establish a connection to a remote SSH server and return a resource on success, false on error
+ */
+PHP_FUNCTION(ssh2_connect)
+{
+ LIBSSH2_SESSION *session;
+ zval *methods = NULL, *callbacks = NULL;
+ char *host;
+ long port = PHP_SSH2_DEFAULT_PORT;
+ int host_len;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|la!a!", &host, &host_len, &port, &methods, &callbacks) == FAILURE) {
+ RETURN_FALSE;
+ }
+
+ session = php_ssh2_session_connect(host, port, methods, callbacks TSRMLS_CC);
+ if (!session) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to connect to %s", host);
+ RETURN_FALSE;
+ }
+
+ ZEND_REGISTER_RESOURCE(return_value, session, le_ssh2_session);
+}
+/* }}} */
+
+/* {{{ proto array ssh2_methods_negotiated(resource session)
+ * Return list of negotiaed methods
+ */
+PHP_FUNCTION(ssh2_methods_negotiated)
+{
+ LIBSSH2_SESSION *session;
+ zval *zsession, *endpoint;
+ char *kex, *hostkey, *crypt_cs, *crypt_sc, *mac_cs, *mac_sc, *comp_cs, *comp_sc, *lang_cs, *lang_sc;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zsession) == FAILURE) {
+ RETURN_FALSE;
+ }
+
+ ZEND_FETCH_RESOURCE(session, LIBSSH2_SESSION*, &zsession, -1, PHP_SSH2_SESSION_RES_NAME, le_ssh2_session);
+
+#if defined(LIBSSH2_APINO) && LIBSSH2_APINO < 200412301450
+ libssh2_session_methods(session, &kex, &hostkey, &crypt_cs, &crypt_sc, &mac_cs, &mac_sc, &comp_cs, &comp_sc, &lang_cs, &lang_sc);
+#else
+ kex = (char*)libssh2_session_methods(session, LIBSSH2_METHOD_KEX);
+ hostkey = (char*)libssh2_session_methods(session, LIBSSH2_METHOD_HOSTKEY);
+ crypt_cs = (char*)libssh2_session_methods(session, LIBSSH2_METHOD_CRYPT_CS);
+ crypt_sc = (char*)libssh2_session_methods(session, LIBSSH2_METHOD_CRYPT_SC);
+ mac_cs = (char*)libssh2_session_methods(session, LIBSSH2_METHOD_MAC_CS);
+ mac_sc = (char*)libssh2_session_methods(session, LIBSSH2_METHOD_MAC_SC);
+ comp_cs = (char*)libssh2_session_methods(session, LIBSSH2_METHOD_COMP_CS);
+ comp_sc = (char*)libssh2_session_methods(session, LIBSSH2_METHOD_COMP_SC);
+ lang_cs = (char*)libssh2_session_methods(session, LIBSSH2_METHOD_LANG_CS);
+ lang_sc = (char*)libssh2_session_methods(session, LIBSSH2_METHOD_LANG_SC);
+#endif
+
+ array_init(return_value);
+ add_assoc_string(return_value, "kex", kex, 1);
+ add_assoc_string(return_value, "hostkey", hostkey, 1);
+
+ ALLOC_INIT_ZVAL(endpoint);
+ array_init(endpoint);
+ add_assoc_string(endpoint, "crypt", crypt_cs, 1);
+ add_assoc_string(endpoint, "mac", mac_cs, 1);
+ add_assoc_string(endpoint, "comp", comp_cs, 1);
+ add_assoc_string(endpoint, "lang", lang_cs, 1);
+ add_assoc_zval(return_value, "client_to_server", endpoint);
+
+ ALLOC_INIT_ZVAL(endpoint);
+ array_init(endpoint);
+ add_assoc_string(endpoint, "crypt", crypt_sc, 1);
+ add_assoc_string(endpoint, "mac", mac_sc, 1);
+ add_assoc_string(endpoint, "comp", comp_sc, 1);
+ add_assoc_string(endpoint, "lang", lang_sc, 1);
+ add_assoc_zval(return_value, "server_to_client", endpoint);
+}
+/* }}} */
+
+/* {{{ proto string ssh2_fingerprint(resource session[, int flags])
+ * Returns a server hostkey hash from an active session
+ * Defaults to MD5 fingerprint encoded as ASCII hex values
+ */
+PHP_FUNCTION(ssh2_fingerprint)
+{
+ LIBSSH2_SESSION *session;
+ zval *zsession;
+ const char *fingerprint;
+ long flags = 0;
+ int i, fingerprint_len;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|l", &zsession, &flags) == FAILURE) {
+ RETURN_FALSE;
+ }
+ fingerprint_len = (flags & PHP_SSH2_FINGERPRINT_SHA1) ? SHA_DIGEST_LENGTH : MD5_DIGEST_LENGTH;
+
+ ZEND_FETCH_RESOURCE(session, LIBSSH2_SESSION*, &zsession, -1, PHP_SSH2_SESSION_RES_NAME, le_ssh2_session);
+
+ fingerprint = (char*)libssh2_hostkey_hash(session, (flags & PHP_SSH2_FINGERPRINT_SHA1) ? LIBSSH2_HOSTKEY_HASH_SHA1 : LIBSSH2_HOSTKEY_HASH_MD5);
+ if (!fingerprint) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to retreive fingerprint from specified session");
+ RETURN_FALSE;
+ }
+
+ for(i = 0; i < fingerprint_len; i++) {
+ if (fingerprint[i] != '\0') {
+ goto fingerprint_good;
+ }
+ }
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "No fingerprint available using specified hash");
+ RETURN_NULL();
+ fingerprint_good:
+ if (flags & PHP_SSH2_FINGERPRINT_RAW) {
+ RETURN_STRINGL(fingerprint, fingerprint_len, 1);
+ } else {
+ char *hexchars;
+
+ hexchars = emalloc((fingerprint_len * 2) + 1);
+ for(i = 0; i < fingerprint_len; i++) {
+ snprintf(hexchars + (2 * i), 3, "%02X", (unsigned char)fingerprint[i]);
+ }
+ RETURN_STRINGL(hexchars, 2 * fingerprint_len, 0);
+ }
+}
+/* }}} */
+
+/* {{{ proto array ssh2_auth_none(resource session, string username)
+ * Attempt "none" authentication, returns a list of allowed methods on failed authentication,
+ * false on utter failure, or true on success
+ */
+PHP_FUNCTION(ssh2_auth_none)
+{
+ LIBSSH2_SESSION *session;
+ zval *zsession;
+ char *username, *methods, *s, *p;
+ int username_len;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &zsession, &username, &username_len) == FAILURE) {
+ RETURN_FALSE;
+ }
+
+ ZEND_FETCH_RESOURCE(session, LIBSSH2_SESSION*, &zsession, -1, PHP_SSH2_SESSION_RES_NAME, le_ssh2_session);
+
+ s = methods = libssh2_userauth_list(session, username, username_len);
+ if (!methods) {
+ /* Either bad failure, or unexpected success */
+ RETURN_BOOL(libssh2_userauth_authenticated(session));
+ }
+
+ array_init(return_value);
+ while ((p = strchr(s, ','))) {
+ if ((p - s) > 0) {
+ add_next_index_stringl(return_value, s, p - s, 1);
+ }
+ s = p + 1;
+ }
+ if (strlen(s)) {
+ add_next_index_string(return_value, s, 1);
+ }
+}
+/* }}} */
+
+/* {{{ proto bool ssh2_auth_password(resource session, string username, string password)
+ * Authenticate over SSH using a plain password
+ */
+PHP_FUNCTION(ssh2_auth_password)
+{
+ LIBSSH2_SESSION *session;
+ zval *zsession;
+ char *username, *password;
+ int username_len, password_len;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rss", &zsession, &username, &username_len, &password, &password_len) == FAILURE) {
+ RETURN_FALSE;
+ }
+
+ ZEND_FETCH_RESOURCE(session, LIBSSH2_SESSION*, &zsession, -1, PHP_SSH2_SESSION_RES_NAME, le_ssh2_session);
+
+ /* TODO: Support password change callback */
+ if (libssh2_userauth_password_ex(session, username, username_len, password, password_len, NULL)) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Authentication failed for %s using password", username);
+ RETURN_FALSE;
+ }
+
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto bool ssh2_auth_pubkey_file(resource session, string username, string pubkeyfile, string privkeyfile[, string passphrase])
+ * Authenticate using a public key
+ */
+PHP_FUNCTION(ssh2_auth_pubkey_file)
+{
+ LIBSSH2_SESSION *session;
+ zval *zsession;
+ char *username, *pubkey, *privkey, *passphrase = NULL;
+ int username_len, pubkey_len, privkey_len, passphrase_len;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rsss|s", &zsession, &username, &username_len,
+ &pubkey, &pubkey_len,
+ &privkey, &privkey_len,
+ &passphrase, &passphrase_len) == FAILURE) {
+ RETURN_FALSE;
+ }
+
+ if (SSH2_OPENBASEDIR_CHECKPATH(pubkey) || SSH2_OPENBASEDIR_CHECKPATH(privkey)) {
+ RETURN_FALSE;
+ }
+
+ ZEND_FETCH_RESOURCE(session, LIBSSH2_SESSION*, &zsession, -1, PHP_SSH2_SESSION_RES_NAME, le_ssh2_session);
+
+ /* TODO: Support passphrase callback */
+ if (libssh2_userauth_publickey_fromfile_ex(session, username, username_len, pubkey, privkey, passphrase)) {
+ char *buf;
+ int len;
+ libssh2_session_last_error(session, &buf, &len, 0);
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Authentication failed for %s using public key: %s", username, buf);
+ RETURN_FALSE;
+ }
+
+ RETURN_TRUE;
+}
+/* }}} */
+
+#ifdef PHP_SSH2_HOSTBASED_AUTH
+/* {{{ proto bool ssh2_auth_hostbased_file(resource session, string username, string local_hostname, string pubkeyfile, string privkeyfile[, string passphrase[, string local_username]])
+ * Authenticate using a hostkey
+ */
+PHP_FUNCTION(ssh2_auth_hostbased_file)
+{
+ LIBSSH2_SESSION *session;
+ zval *zsession;
+ char *username, *hostname, *pubkey, *privkey, *passphrase = NULL, *local_username = NULL;
+ int username_len, hostname_len, pubkey_len, privkey_len, passphrase_len, local_username_len;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rssss|s!s!", &zsession, &username, &username_len,
+ &hostname, &hostname_len,
+ &pubkey, &pubkey_len,
+ &privkey, &privkey_len,
+ &passphrase, &passphrase_len,
+ &local_username, &local_username_len) == FAILURE) {
+ RETURN_FALSE;
+ }
+
+ if (SSH2_OPENBASEDIR_CHECKPATH(pubkey) || SSH2_OPENBASEDIR_CHECKPATH(privkey)) {
+ RETURN_FALSE;
+ }
+
+ ZEND_FETCH_RESOURCE(session, LIBSSH2_SESSION*, &zsession, -1, PHP_SSH2_SESSION_RES_NAME, le_ssh2_session);
+
+ if (!local_username) {
+ local_username = username;
+ local_username_len = username_len;
+ }
+
+ /* TODO: Support passphrase callback */
+ if (libssh2_userauth_hostbased_fromfile_ex(session, username, username_len, pubkey, privkey, passphrase, hostname, hostname_len, local_username, local_username_len)) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Authentication failed for %s using hostbased public key", username);
+ RETURN_FALSE;
+ }
+
+ RETURN_TRUE;
+}
+/* }}} */
+#endif /* PHP_SSH2_HOSTBASED_AUTH */
+
+#ifdef PHP_SSH2_REMOTE_FORWARDING
+/* {{{ proto resource ssh2_forward_listen(resource session, int port[, string host[, long max_connections]])
+ * Bind a port on the remote server and listen for connections
+ */
+PHP_FUNCTION(ssh2_forward_listen)
+{
+ zval *zsession;
+ LIBSSH2_SESSION *session;
+ LIBSSH2_LISTENER *listener;
+ php_ssh2_listener_data *data;
+ long port;
+ char *host = NULL;
+ int host_len;
+ long max_connections = PHP_SSH2_LISTEN_MAX_QUEUED;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl|sl", &zsession, &port, &host, &host_len, &max_connections) == FAILURE) {
+ RETURN_FALSE;
+ }
+
+ ZEND_FETCH_RESOURCE(session, LIBSSH2_SESSION*, &zsession, -1, PHP_SSH2_SESSION_RES_NAME, le_ssh2_session);
+
+ listener = libssh2_channel_forward_listen_ex(session, host, port, NULL, max_connections);
+
+ if (!listener) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failure listening on remote port");
+ RETURN_FALSE;
+ }
+
+ data = emalloc(sizeof(php_ssh2_listener_data));
+ data->session = session;
+ data->session_rsrcid = Z_LVAL_P(zsession);
+ zend_list_addref(data->session_rsrcid);
+ data->listener = listener;
+
+ ZEND_REGISTER_RESOURCE(return_value, data, le_ssh2_listener);
+}
+/* }}} */
+
+/* {{{ proto stream ssh2_forward_accept(resource listener[, string &shost[, long &sport]])
+ * Accept a connection created by a listener
+ */
+PHP_FUNCTION(ssh2_forward_accept)
+{
+ zval *zlistener;
+ php_ssh2_listener_data *data;
+ LIBSSH2_CHANNEL *channel;
+ php_ssh2_channel_data *channel_data;
+ php_stream *stream;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zlistener) == FAILURE) {
+ RETURN_FALSE;
+ }
+
+ ZEND_FETCH_RESOURCE(data, php_ssh2_listener_data*, &zlistener, -1, PHP_SSH2_LISTENER_RES_NAME, le_ssh2_listener);
+
+ channel = libssh2_channel_forward_accept(data->listener);
+
+ if (!channel) {
+ RETURN_FALSE;
+ }
+
+ channel_data = emalloc(sizeof(php_ssh2_channel_data));
+ channel_data->channel = channel;
+ channel_data->streamid = 0;
+ channel_data->is_blocking = 0;
+ channel_data->session_rsrc = data->session_rsrcid;
+ channel_data->refcount = NULL;
+
+ stream = php_stream_alloc(&php_ssh2_channel_stream_ops, channel_data, 0, "r+");
+ if (!stream) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failure allocating stream");
+ efree(channel_data);
+ libssh2_channel_free(channel);
+ RETURN_FALSE;
+ }
+ zend_list_addref(channel_data->session_rsrc);
+
+ php_stream_to_zval(stream, return_value);
+}
+/* }}} */
+#endif /* PHP_SSH2_REMOTE_FORWARDING */
+
+#ifdef PHP_SSH2_POLL
+/* {{{ proto int ssh2_poll(array &polldes[, int timeout])
+ * Poll the channels/listeners/streams for events
+ * Returns number of descriptors which returned non-zero revents
+ * Input array should be of the form:
+ * array(
+ * 0 => array(
+ * [resource] => $channel,$listener, or $stream
+ * [events] => SSH2_POLL* flags bitwise ORed together
+ * ),
+ * 1 => ...
+ * )
+ * Each subarray will be populated with an revents element on return
+ */
+PHP_FUNCTION(ssh2_poll)
+{
+ zval *zdesc, **subarray;
+ long timeout = PHP_SSH2_DEFAULT_POLL_TIMEOUT;
+ LIBSSH2_POLLFD *pollfds;
+ int numfds, i = 0, fds_ready;
+ int le_stream = php_file_le_stream();
+ int le_pstream = php_file_le_pstream();
+ zval ***pollmap;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a|l", &zdesc, &timeout) == FAILURE) {
+ RETURN_NULL();
+ }
+
+ numfds = zend_hash_num_elements(Z_ARRVAL_P(zdesc));
+ pollfds = safe_emalloc(sizeof(LIBSSH2_POLLFD), numfds, 0);
+ pollmap = safe_emalloc(sizeof(zval**), numfds, 0);
+
+ for(zend_hash_internal_pointer_reset(Z_ARRVAL_P(zdesc));
+ zend_hash_get_current_data(Z_ARRVAL_P(zdesc), (void**)&subarray) == SUCCESS;
+ zend_hash_move_forward(Z_ARRVAL_P(zdesc))) {
+ zval **tmpzval;
+ int res_type = 0;
+ void *res;
+
+ if (Z_TYPE_PP(subarray) != IS_ARRAY) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid element in poll array, not a sub array");
+ numfds--;
+ continue;
+ }
+ if (zend_hash_find(Z_ARRVAL_PP(subarray), "events", sizeof("events"), (void**)&tmpzval) == FAILURE ||
+ Z_TYPE_PP(tmpzval) != IS_LONG) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid data in subarray, no events element, or not a bitmask");
+ numfds--;
+ continue;
+ }
+ pollfds[i].events = Z_LVAL_PP(tmpzval);
+ if (zend_hash_find(Z_ARRVAL_PP(subarray), "resource", sizeof("resource"), (void**)&tmpzval) == FAILURE ||
+ Z_TYPE_PP(tmpzval) != IS_RESOURCE) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid data in subarray, no resource element, or not of type resource");
+ numfds--;
+ continue;
+ }
+ zend_list_find(Z_LVAL_PP(tmpzval), &res_type);
+ res = zend_fetch_resource(tmpzval TSRMLS_CC, -1, "Poll Resource", NULL, 1, res_type);
+ if (res_type == le_ssh2_listener) {
+ pollfds[i].type = LIBSSH2_POLLFD_LISTENER;
+ pollfds[i].fd.listener = ((php_ssh2_listener_data*)res)->listener;
+ } else if ((res_type == le_stream || res_type == le_pstream) &&
+ ((php_stream*)res)->ops == &php_ssh2_channel_stream_ops) {
+ pollfds[i].type = LIBSSH2_POLLFD_CHANNEL;
+ pollfds[i].fd.channel = ((php_ssh2_channel_data*)(((php_stream*)res)->abstract))->channel;
+ /* TODO: Add the ability to select against other stream types */
+ } else {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid resource type in subarray: %s", zend_rsrc_list_get_rsrc_type(Z_LVAL_PP(tmpzval) TSRMLS_CC));
+ numfds--;
+ continue;
+ }
+ pollmap[i] = subarray;
+ i++;
+ }
+
+ fds_ready = libssh2_poll(pollfds, numfds, timeout * 1000);
+
+ for(i = 0; i < numfds; i++) {
+ zval *subarray = *pollmap[i];
+
+ if (!Z_ISREF_P(subarray) && Z_REFCOUNT_P(subarray) > 1) {
+ /* Make a new copy of the subarray zval* */
+ MAKE_STD_ZVAL(subarray);
+ *subarray = **pollmap[i];
+
+ /* Point the pData to the new zval* and duplicate its resources */
+ *pollmap[i] = subarray;
+ zval_copy_ctor(subarray);
+
+ /* Fixup its refcount */
+ Z_UNSET_ISREF_P(subarray);
+ Z_SET_REFCOUNT_P(subarray, 1);
+ }
+ zend_hash_del(Z_ARRVAL_P(subarray), "revents", sizeof("revents"));
+ add_assoc_long(subarray, "revents", pollfds[i].revents);
+
+ }
+ efree(pollmap);
+ efree(pollfds);
+
+ RETURN_LONG(fds_ready);
+}
+/* }}} */
+#endif /* PHP_SSH2_POLL */
+
+#ifdef PHP_SSH2_PUBLICKEY_SUBSYSTEM
+/* ***********************
+ * Publickey Subsystem *
+ *********************** */
+
+/* {{{ proto resource ssh2_publickey_init(resource connection)
+Initialize the publickey subsystem */
+PHP_FUNCTION(ssh2_publickey_init)
+{
+ zval *zsession;
+ LIBSSH2_SESSION *session;
+ LIBSSH2_PUBLICKEY *pkey;
+ php_ssh2_pkey_subsys_data *data;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zsession) == FAILURE) {
+ RETURN_FALSE;
+ }
+
+ ZEND_FETCH_RESOURCE(session, LIBSSH2_SESSION*, &zsession, -1, PHP_SSH2_SESSION_RES_NAME, le_ssh2_session);
+
+ pkey = libssh2_publickey_init(session);
+
+ if (!pkey) {
+ int last_error = 0;
+ char *error_msg = NULL;
+
+ last_error = libssh2_session_last_error(session, &error_msg, NULL, 0);
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to initialize publickey subsystem(%d) %s", last_error, error_msg);
+ RETURN_FALSE;
+ }
+
+ data = emalloc(sizeof(php_ssh2_pkey_subsys_data));
+ data->session = session;
+ data->session_rsrcid = Z_LVAL_P(zsession);
+ zend_list_addref(data->session_rsrcid);
+ data->pkey = pkey;
+
+ ZEND_REGISTER_RESOURCE(return_value, data, le_ssh2_pkey_subsys);
+}
+/* }}} */
+
+/* {{{ proto bool ssh2_publickey_add(resource pkey, string algoname, string blob[, bool overwrite=FALSE [,array attributes=NULL]])
+Add an additional publickey */
+PHP_FUNCTION(ssh2_publickey_add)
+{
+ zval *zpkey_data, *zattrs = NULL;
+ php_ssh2_pkey_subsys_data *data;
+ char *algo, *blob;
+ int algo_len, blob_len;
+ unsigned long num_attrs = 0;
+ libssh2_publickey_attribute *attrs = NULL;
+ zend_bool overwrite = 0;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rss|ba", &zpkey_data, &algo, &algo_len, &blob, &blob_len, &overwrite, &zattrs) == FAILURE) {
+ RETURN_FALSE;
+ }
+
+ ZEND_FETCH_RESOURCE(data, php_ssh2_pkey_subsys_data*, &zpkey_data, -1, PHP_SSH2_PKEY_SUBSYS_RES_NAME, le_ssh2_pkey_subsys);
+
+ if (zattrs) {
+ HashPosition pos;
+ zval **attr_val;
+ unsigned long current_attr = 0;
+
+ num_attrs = zend_hash_num_elements(Z_ARRVAL_P(zattrs));
+ attrs = safe_emalloc(num_attrs, sizeof(libssh2_publickey_attribute), 0);
+
+ for(zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(zattrs), &pos);
+ zend_hash_get_current_data_ex(Z_ARRVAL_P(zattrs), (void**)&attr_val, &pos) == SUCCESS;
+ zend_hash_move_forward_ex(Z_ARRVAL_P(zattrs), &pos)) {
+ char *key;
+ int key_len, type;
+ long idx;
+ zval copyval = **attr_val;
+
+ type = zend_hash_get_current_key_ex(Z_ARRVAL_P(zattrs), &key, &key_len, &idx, 0, &pos);
+ if (type == HASH_KEY_NON_EXISTANT) {
+ /* All but impossible */
+ break;
+ }
+ if (type == HASH_KEY_IS_LONG) {
+ /* Malformed, ignore */
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Malformed attirbute array, contains numeric index");
+ num_attrs--;
+ continue;
+ }
+
+ if (key_len == 0 || (key_len == 1 && *key == '*')) {
+ /* Empty key, ignore */
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Empty attribute key");
+ num_attrs--;
+ continue;
+ }
+
+ zval_copy_ctor(©val);
+ Z_UNSET_ISREF_P(©val);
+ Z_SET_REFCOUNT_P(©val, 1);
+ convert_to_string(©val);
+
+ if (*key == '*') {
+ attrs[current_attr].mandatory = 1;
+ attrs[current_attr].name = key + 1;
+ attrs[current_attr].name_len = key_len - 2;
+ } else {
+ attrs[current_attr].mandatory = 0;
+ attrs[current_attr].name = key;
+ attrs[current_attr].name_len = key_len - 1;
+ }
+ attrs[current_attr].value_len = Z_STRLEN(copyval);
+ attrs[current_attr].value = Z_STRVAL(copyval);
+
+ /* copyval deliberately not dtor'd, we're stealing the string */
+ current_attr++;
+ }
+ }
+
+ if (libssh2_publickey_add_ex(data->pkey, algo, algo_len, blob, blob_len, overwrite, num_attrs, attrs)) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to add %s key", algo);
+ RETVAL_FALSE;
+ } else {
+ RETVAL_TRUE;
+ }
+
+ if (attrs) {
+ unsigned long i;
+
+ for(i = 0; i < num_attrs; i++) {
+ /* name doesn't need freeing */
+ efree(attrs[i].value);
+ }
+ efree(attrs);
+ }
+}
+/* }}} */
+
+/* {{{ proto bool ssh2_publickey_remove(resource pkey, string algoname, string blob)
+Remove a publickey entry */
+PHP_FUNCTION(ssh2_publickey_remove)
+{
+ zval *zpkey_data;
+ php_ssh2_pkey_subsys_data *data;
+ char *algo, *blob;
+ int algo_len, blob_len;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rss", &zpkey_data, &algo, &algo_len, &blob, &blob_len) == FAILURE) {
+ RETURN_FALSE;
+ }
+
+ ZEND_FETCH_RESOURCE(data, php_ssh2_pkey_subsys_data*, &zpkey_data, -1, PHP_SSH2_PKEY_SUBSYS_RES_NAME, le_ssh2_pkey_subsys);
+
+ if (libssh2_publickey_remove_ex(data->pkey, algo, algo_len, blob, blob_len)) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to remove %s key", algo);
+ RETURN_FALSE;
+ }
+
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto array ssh2_publickey_list(resource pkey)
+List currently installed publickey entries */
+PHP_FUNCTION(ssh2_publickey_list)
+{
+ zval *zpkey_data;
+ php_ssh2_pkey_subsys_data *data;
+ unsigned long num_keys, i;
+ libssh2_publickey_list *keys;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zpkey_data) == FAILURE) {
+ RETURN_FALSE;
+ }
+
+ ZEND_FETCH_RESOURCE(data, php_ssh2_pkey_subsys_data*, &zpkey_data, -1, PHP_SSH2_PKEY_SUBSYS_RES_NAME, le_ssh2_pkey_subsys);
+
+ if (libssh2_publickey_list_fetch(data->pkey, &num_keys, &keys)) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to list keys on remote server");
+ RETURN_FALSE;
+ }
+
+ array_init(return_value);
+ for(i = 0; i < num_keys; i++) {
+ zval *key, *attrs;
+ unsigned long j;
+
+ MAKE_STD_ZVAL(key);
+ array_init(key);
+
+ add_assoc_stringl(key, "name", keys[i].name, keys[i].name_len, 1);
+ add_assoc_stringl(key, "blob", keys[i].blob, keys[i].blob_len, 1);
+
+ MAKE_STD_ZVAL(attrs);
+ array_init(attrs);
+ for(j = 0; j < keys[i].num_attrs; j++) {
+ zval *attr;
+
+ MAKE_STD_ZVAL(attr);
+ ZVAL_STRINGL(attr, keys[i].attrs[j].value, keys[i].attrs[j].value_len, 1);
+ zend_hash_add(Z_ARRVAL_P(attrs), keys[i].attrs[j].name, keys[i].attrs[j].name_len + 1, (void**)&attr, sizeof(zval*), NULL);
+ }
+ add_assoc_zval(key, "attrs", attrs);
+
+ add_next_index_zval(return_value, key);
+ }
+
+ libssh2_publickey_list_free(data->pkey, keys);
+}
+/* }}} */
+#endif /* PHP_SSH2_PUBLICKEY_SUBSYSTEM */
+
+/* ***********************
+ * Module Housekeeping *
+ *********************** */
+
+static void php_ssh2_session_dtor(zend_rsrc_list_entry *rsrc TSRMLS_DC)
+{
+ LIBSSH2_SESSION *session = (LIBSSH2_SESSION*)rsrc->ptr;
+ php_ssh2_session_data **data = (php_ssh2_session_data**)libssh2_session_abstract(session);
+
+ libssh2_session_disconnect(session, "PECL/ssh2 (http://pecl.php.net/packages/ssh2)");
+
+ if (*data) {
+ if ((*data)->ignore_cb) {
+ zval_ptr_dtor(&(*data)->ignore_cb);
+ }
+ if ((*data)->debug_cb) {
+ zval_ptr_dtor(&(*data)->debug_cb);
+ }
+ if ((*data)->macerror_cb) {
+ zval_ptr_dtor(&(*data)->macerror_cb);
+ }
+ if ((*data)->disconnect_cb) {
+ zval_ptr_dtor(&(*data)->disconnect_cb);
+ }
+
+ closesocket((*data)->socket);
+
+ efree(*data);
+ *data = NULL;
+ }
+
+ libssh2_session_free(session);
+}
+
+#ifdef PHP_SSH2_REMOTE_FORWARDING
+static void php_ssh2_listener_dtor(zend_rsrc_list_entry *rsrc TSRMLS_DC)
+{
+ php_ssh2_listener_data *data = (php_ssh2_listener_data*)rsrc->ptr;
+ LIBSSH2_LISTENER *listener = data->listener;
+
+ libssh2_channel_forward_cancel(listener);
+ zend_list_delete(data->session_rsrcid);
+ efree(data);
+}
+#endif /* PHP_SSH2_REMOTE_FORWARDING */
+
+#ifdef PHP_SSH2_PUBLICKEY_SUBSYSTEM
+static void php_ssh2_pkey_subsys_dtor(zend_rsrc_list_entry *rsrc TSRMLS_DC)
+{
+ php_ssh2_pkey_subsys_data *data = (php_ssh2_pkey_subsys_data*)rsrc->ptr;
+ LIBSSH2_PUBLICKEY *pkey = data->pkey;
+
+ libssh2_publickey_shutdown(pkey);
+ zend_list_delete(data->session_rsrcid);
+ efree(data);
+}
+#endif /* PHP_SSH2_PUBLICKEY_SUBSYSTEM */
+
+/* {{{ PHP_MINIT_FUNCTION
+ */
+PHP_MINIT_FUNCTION(ssh2)
+{
+ le_ssh2_session = zend_register_list_destructors_ex(php_ssh2_session_dtor, NULL, PHP_SSH2_SESSION_RES_NAME, module_number);
+#ifdef PHP_SSH2_REMOTE_FORWARDING
+ le_ssh2_listener = zend_register_list_destructors_ex(php_ssh2_listener_dtor, NULL, PHP_SSH2_LISTENER_RES_NAME, module_number);
+#endif /* PHP_SSH2_REMOTE_FORWARDING */
+ le_ssh2_sftp = zend_register_list_destructors_ex(php_ssh2_sftp_dtor, NULL, PHP_SSH2_SFTP_RES_NAME, module_number);
+#ifdef PHP_SSH2_PUBLICKEY_SUBSYSTEM
+ le_ssh2_pkey_subsys = zend_register_list_destructors_ex(php_ssh2_pkey_subsys_dtor, NULL, PHP_SSH2_PKEY_SUBSYS_RES_NAME, module_number);
+#endif /* PHP_SSH2_PUBLICKEY_SUBSYSTEM */
+
+ REGISTER_LONG_CONSTANT("SSH2_FINGERPRINT_MD5", PHP_SSH2_FINGERPRINT_MD5, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("SSH2_FINGERPRINT_SHA1", PHP_SSH2_FINGERPRINT_SHA1, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("SSH2_FINGERPRINT_HEX", PHP_SSH2_FINGERPRINT_HEX, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("SSH2_FINGERPRINT_RAW", PHP_SSH2_FINGERPRINT_RAW, CONST_CS | CONST_PERSISTENT);
+
+ REGISTER_LONG_CONSTANT("SSH2_TERM_UNIT_CHARS", PHP_SSH2_TERM_UNIT_CHARS, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("SSH2_TERM_UNIT_PIXELS", PHP_SSH2_TERM_UNIT_PIXELS, CONST_CS | CONST_PERSISTENT);
+
+ REGISTER_STRING_CONSTANT("SSH2_DEFAULT_TERMINAL", PHP_SSH2_DEFAULT_TERMINAL, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("SSH2_DEFAULT_TERM_WIDTH", PHP_SSH2_DEFAULT_TERM_WIDTH, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("SSH2_DEFAULT_TERM_HEIGHT", PHP_SSH2_DEFAULT_TERM_HEIGHT, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("SSH2_DEFAULT_TERM_UNIT", PHP_SSH2_DEFAULT_TERM_UNIT, CONST_CS | CONST_PERSISTENT);
+
+ REGISTER_LONG_CONSTANT("SSH2_STREAM_STDIO", 0, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("SSH2_STREAM_STDERR", SSH_EXTENDED_DATA_STDERR, CONST_CS | CONST_PERSISTENT);
+
+#ifdef PHP_SSH2_POLL
+ /* events/revents */
+ REGISTER_LONG_CONSTANT("SSH2_POLLIN", LIBSSH2_POLLFD_POLLIN, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("SSH2_POLLEXT", LIBSSH2_POLLFD_POLLEXT, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("SSH2_POLLOUT", LIBSSH2_POLLFD_POLLOUT, CONST_CS | CONST_PERSISTENT);
+
+ /* revents only */
+ REGISTER_LONG_CONSTANT("SSH2_POLLERR", LIBSSH2_POLLFD_POLLERR, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("SSH2_POLLHUP", LIBSSH2_POLLFD_POLLHUP, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("SSH2_POLLNVAL", LIBSSH2_POLLFD_POLLNVAL, CONST_CS | CONST_PERSISTENT);
+#if (defined(LIBSSH2_APINO) && (LIBSSH2_APINO > 200503221619)) || (defined(LIBSSH2_VERSION_NUM) && LIBSSH2_VERSION_NUM >= 0x001000)
+ REGISTER_LONG_CONSTANT("SSH2_POLL_SESSION_CLOSED", LIBSSH2_POLLFD_SESSION_CLOSED, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("SSH2_POLL_CHANNEL_CLOSED", LIBSSH2_POLLFD_CHANNEL_CLOSED, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("SSH2_POLL_LISTENER_CLOSED", LIBSSH2_POLLFD_LISTENER_CLOSED, CONST_CS | CONST_PERSISTENT);
+#endif /* >= LIBSSH2-0.10 */
+#endif /* POLL */
+
+ return (php_register_url_stream_wrapper("ssh2.shell", &php_ssh2_stream_wrapper_shell TSRMLS_CC) == SUCCESS &&
+ php_register_url_stream_wrapper("ssh2.exec", &php_ssh2_stream_wrapper_exec TSRMLS_CC) == SUCCESS &&
+ php_register_url_stream_wrapper("ssh2.tunnel", &php_ssh2_stream_wrapper_tunnel TSRMLS_CC) == SUCCESS &&
+ php_register_url_stream_wrapper("ssh2.scp", &php_ssh2_stream_wrapper_scp TSRMLS_CC) == SUCCESS &&
+ php_register_url_stream_wrapper("ssh2.sftp", &php_ssh2_sftp_wrapper TSRMLS_CC) == SUCCESS) ? SUCCESS : FAILURE;
+}
+/* }}} */
+
+/* {{{ PHP_MSHUTDOWN_FUNCTION
+ */
+PHP_MSHUTDOWN_FUNCTION(ssh2)
+{
+ return (php_unregister_url_stream_wrapper("ssh2.shell" TSRMLS_CC) == SUCCESS &&
+ php_unregister_url_stream_wrapper("ssh2.exec" TSRMLS_CC) == SUCCESS &&
+ php_unregister_url_stream_wrapper("ssh2.tunnel" TSRMLS_CC) == SUCCESS &&
+ php_unregister_url_stream_wrapper("ssh2.scp" TSRMLS_CC) == SUCCESS &&
+ php_unregister_url_stream_wrapper("ssh2.sftp" TSRMLS_CC) == SUCCESS) ? SUCCESS : FAILURE;
+}
+/* }}} */
+
+/* {{{ PHP_MINFO_FUNCTION
+ */
+PHP_MINFO_FUNCTION(ssh2)
+{
+ php_info_print_table_start();
+ php_info_print_table_header(2, "SSH2 support", "enabled");
+ php_info_print_table_row(2, "extension version", PHP_SSH2_VERSION);
+ php_info_print_table_row(2, "libssh2 version", LIBSSH2_VERSION);
+ php_info_print_table_row(2, "banner", LIBSSH2_SSH_BANNER);
+#ifdef PHP_SSH2_REMOTE_FORWARDING
+ php_info_print_table_row(2, "remote forwarding", "enabled");
+#endif
+#ifdef PHP_SSH2_HOSTBASED_AUTH
+ php_info_print_table_row(2, "hostbased auth", "enabled");
+#endif
+#ifdef PHP_SSH2_POLL
+ php_info_print_table_row(2, "polling support", "enabled");
+#endif
+#ifdef PHP_SSH2_PUBLICKEY_SUBSYSTEM
+ php_info_print_table_row(2, "publickey subsystem", "enabled");
+#endif
+ php_info_print_table_end();
+}
+/* }}} */
+
+/* {{{ ssh2_functions[]
+ */
+zend_function_entry ssh2_functions[] = {
+ PHP_FE(ssh2_connect, NULL)
+ PHP_FE(ssh2_methods_negotiated, NULL)
+ PHP_FE(ssh2_fingerprint, NULL)
+
+ PHP_FE(ssh2_auth_none, NULL)
+ PHP_FE(ssh2_auth_password, NULL)
+ PHP_FE(ssh2_auth_pubkey_file, NULL)
+#ifdef PHP_SSH2_HOSTBASED_AUTH
+ PHP_FE(ssh2_auth_hostbased_file, NULL)
+#endif /* PHP_SSH2_HOSTBASED_AUTH */
+
+#ifdef PHP_SSH2_REMOTE_FORWARDING
+ PHP_FE(ssh2_forward_listen, NULL)
+ PHP_FE(ssh2_forward_accept, NULL)
+#endif /* PHP_SSH2_REMOTE_FORWARDING */
+
+ /* Stream Stuff */
+ PHP_FE(ssh2_shell, NULL)
+ PHP_FE(ssh2_exec, NULL)
+ PHP_FE(ssh2_tunnel, NULL)
+ PHP_FE(ssh2_scp_recv, NULL)
+ PHP_FE(ssh2_scp_send, NULL)
+ PHP_FE(ssh2_fetch_stream, NULL)
+#ifdef PHP_SSH2_POLL
+ PHP_FE(ssh2_poll, php_ssh2_first_arg_force_ref)
+#endif
+
+ /* SFTP Stuff */
+ PHP_FE(ssh2_sftp, NULL)
+
+ /* SFTP Wrapper Ops */
+ PHP_FE(ssh2_sftp_rename, NULL)
+ PHP_FE(ssh2_sftp_unlink, NULL)
+ PHP_FE(ssh2_sftp_mkdir, NULL)
+ PHP_FE(ssh2_sftp_rmdir, NULL)
+ PHP_FE(ssh2_sftp_stat, NULL)
+ PHP_FE(ssh2_sftp_lstat, NULL)
+ PHP_FE(ssh2_sftp_symlink, NULL)
+ PHP_FE(ssh2_sftp_readlink, NULL)
+ PHP_FE(ssh2_sftp_realpath, NULL)
+
+ /* Publickey subsystem */
+#ifdef PHP_SSH2_PUBLICKEY_SUBSYSTEM
+ PHP_FE(ssh2_publickey_init, NULL)
+ PHP_FE(ssh2_publickey_add, NULL)
+ PHP_FE(ssh2_publickey_remove, NULL)
+ PHP_FE(ssh2_publickey_list, NULL)
+#endif
+
+ {NULL, NULL, NULL}
+};
+/* }}} */
+
+/* {{{ ssh2_module_entry
+ */
+zend_module_entry ssh2_module_entry = {
+#if ZEND_MODULE_API_NO >= 20010901
+ STANDARD_MODULE_HEADER,
+#endif
+ "ssh2",
+ ssh2_functions,
+ PHP_MINIT(ssh2),
+ PHP_MSHUTDOWN(ssh2),
+ NULL, /* RINIT */
+ NULL, /* RSHUTDOWN */
+ PHP_MINFO(ssh2),
+#if ZEND_MODULE_API_NO >= 20010901
+ PHP_SSH2_VERSION,
+#endif
+ STANDARD_MODULE_PROPERTIES
+};
+/* }}} */
+
+#ifdef COMPILE_DL_SSH2
+ZEND_GET_MODULE(ssh2)
+#endif
+
+/*
+ * 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
+ */
|
[-]
[+]
|
Added |
ssh2-0.11.3.tgz/ssh2-0.11.3/ssh2_fopen_wrappers.c
^
|
@@ -0,0 +1,1273 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 4 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997-2006 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: Sara Golemon <pollita@php.net> |
+ +----------------------------------------------------------------------+
+
+ $Id: ssh2_fopen_wrappers.c 306892 2010-12-30 23:59:55Z pajoye $
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "php.h"
+#include "php_ssh2.h"
+
+/* **********************
+ * channel_stream_ops *
+ ********************** */
+
+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;
+
+ libssh2_channel_set_blocking(abstract->channel, abstract->is_blocking);
+ 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;
+
+ stream->eof = libssh2_channel_eof(abstract->channel);
+ libssh2_channel_set_blocking(abstract->channel, abstract->is_blocking);
+
+ readstate = libssh2_channel_read_ex(abstract->channel, abstract->streamid, buf, count);
+ return (readstate < 0 ? 0 : readstate);
+}
+
+static int php_ssh2_channel_stream_close(php_stream *stream, int close_handle TSRMLS_DC)
+{
+ php_ssh2_channel_data *abstract = (php_ssh2_channel_data*)stream->abstract;
+
+ if (!abstract->refcount || (--(*(abstract->refcount)) == 0)) {
+ /* Last one out, turn off the lights */
+ if (abstract->refcount) {
+ efree(abstract->refcount);
+ }
+ libssh2_channel_eof(abstract->channel);
+ libssh2_channel_free(abstract->channel);
+ zend_list_delete(abstract->session_rsrc);
+ }
+ efree(abstract);
+
+ return 0;
+}
+
+static int php_ssh2_channel_stream_flush(php_stream *stream TSRMLS_DC)
+{
+ php_ssh2_channel_data *abstract = (php_ssh2_channel_data*)stream->abstract;
+
+ return libssh2_channel_flush_ex(abstract->channel, abstract->streamid);
+}
+
+static int php_ssh2_channel_stream_set_option(php_stream *stream, int option, int value, void *ptrparam TSRMLS_DC)
+{
+ php_ssh2_channel_data *abstract = (php_ssh2_channel_data*)stream->abstract;
+ int ret;
+
+ switch (option) {
+ case PHP_STREAM_OPTION_BLOCKING:
+ ret = abstract->is_blocking;
+ abstract->is_blocking = value;
+ return ret;
+ break;
+#if PHP_MAJOR_VERSION >= 5
+ case PHP_STREAM_OPTION_CHECK_LIVENESS:
+ return stream->eof = libssh2_channel_eof(abstract->channel);
+ break;
+#endif
+ }
+
+ return -1;
+}
+
+php_stream_ops php_ssh2_channel_stream_ops = {
+ php_ssh2_channel_stream_write,
+ php_ssh2_channel_stream_read,
+ php_ssh2_channel_stream_close,
+ php_ssh2_channel_stream_flush,
+ PHP_SSH2_CHANNEL_STREAM_NAME,
+ NULL, /* seek */
+ NULL, /* cast */
+ NULL, /* stat */
+ php_ssh2_channel_stream_set_option,
+};
+
+/* *********************
+ * Magic Path Helper *
+ ********************* */
+
+/* {{{ php_ssh2_fopen_wraper_parse_path
+ * Parse an ssh2.*:// path
+ */
+php_url *php_ssh2_fopen_wraper_parse_path( char *path, char *type, php_stream_context *context,
+ LIBSSH2_SESSION **psession, int *presource_id,
+ LIBSSH2_SFTP **psftp, int *psftp_rsrcid
+ TSRMLS_DC)
+{
+ php_ssh2_sftp_data *sftp_data = NULL;
+ LIBSSH2_SESSION *session;
+ php_url *resource;
+ zval *methods = NULL, *callbacks = NULL, zsession, **tmpzval;
+ long resource_id;
+ char *s, *username = NULL, *password = NULL, *pubkey_file = NULL, *privkey_file = NULL;
+ int username_len = 0, password_len = 0;
+
+ resource = php_url_parse(path);
+ if (!resource) {
+ return NULL;
+ }
+
+ if (strncmp(resource->scheme, "ssh2.", sizeof("ssh2.") - 1)) {
+ /* Not an ssh wrapper */
+ php_url_free(resource);
+ return NULL;
+ }
+
+ if (strcmp(resource->scheme + sizeof("ssh2.") - 1, type)) {
+ /* Wrong ssh2. wrapper type */
+ php_url_free(resource);
+ return NULL;
+ }
+
+ if (!resource->host) {
+ return NULL;
+ }
+
+ /* Look for a resource ID to reuse a session */
+ s = resource->host;
+ if (strncmp(resource->host, "Resource id #", sizeof("Resource id #") - 1) == 0) {
+ s = resource->host + sizeof("Resource id #") - 1;
+ }
+ if (is_numeric_string(s, strlen(s), &resource_id, NULL, 0) == IS_LONG) {
+ php_ssh2_sftp_data *sftp_data;
+
+ if (psftp) {
+ sftp_data = (php_ssh2_sftp_data*)zend_fetch_resource(NULL TSRMLS_CC, resource_id, PHP_SSH2_SFTP_RES_NAME, NULL, 1, le_ssh2_sftp);
+ if (sftp_data) {
+ /* Want the sftp layer */
+ zend_list_addref(resource_id);
+ *psftp_rsrcid = resource_id;
+ *psftp = sftp_data->sftp;
+ *presource_id = sftp_data->session_rsrcid;
+ *psession = sftp_data->session;
+ return resource;
+ }
+ }
+ session = (LIBSSH2_SESSION *)zend_fetch_resource(NULL TSRMLS_CC, resource_id, PHP_SSH2_SESSION_RES_NAME, NULL, 1, le_ssh2_session);
+ if (session) {
+ if (psftp) {
+ /* We need an sftp layer too */
+ LIBSSH2_SFTP *sftp = libssh2_sftp_init(session);
+
+ if (!sftp) {
+ php_url_free(resource);
+ return NULL;
+ }
+ sftp_data = emalloc(sizeof(php_ssh2_sftp_data));
+ sftp_data->sftp = sftp;
+ sftp_data->session = session;
+ sftp_data->session_rsrcid = resource_id;
+ zend_list_addref(resource_id);
+ *psftp_rsrcid = ZEND_REGISTER_RESOURCE(NULL, sftp_data, le_ssh2_sftp);
+ *psftp = sftp;
+ *presource_id = resource_id;
+ *psession = session;
+ return resource;
+ }
+ zend_list_addref(resource_id);
+ *presource_id = resource_id;
+ *psession = session;
+ return resource;
+ }
+ }
+
+ /* Fallback on finding it in the context */
+ if (resource->host[0] == 0 && context && psftp &&
+ php_stream_context_get_option(context, "ssh2", "sftp", &tmpzval) == SUCCESS &&
+ Z_TYPE_PP(tmpzval) == IS_RESOURCE) {
+ php_ssh2_sftp_data *sftp_data;
+ sftp_data = (php_ssh2_sftp_data *)zend_fetch_resource(tmpzval TSRMLS_CC, -1, PHP_SSH2_SFTP_RES_NAME, NULL, 1, le_ssh2_sftp);
+ if (sftp_data) {
+ zend_list_addref(Z_LVAL_PP(tmpzval));
+ *psftp_rsrcid = Z_LVAL_PP(tmpzval);
+ *psftp = sftp_data->sftp;
+ *presource_id = sftp_data->session_rsrcid;
+ *psession = sftp_data->session;
+ return resource;
+ }
+ }
+ if (resource->host[0] == 0 && context &&
+ php_stream_context_get_option(context, "ssh2", "session", &tmpzval) == SUCCESS &&
+ Z_TYPE_PP(tmpzval) == IS_RESOURCE) {
+ session = (LIBSSH2_SESSION *)zend_fetch_resource(tmpzval TSRMLS_CC, -1, PHP_SSH2_SESSION_RES_NAME, NULL, 1, le_ssh2_session);
+ if (session) {
+ if (psftp) {
+ /* We need an SFTP layer too! */
+ LIBSSH2_SFTP *sftp = libssh2_sftp_init(session);
+ php_ssh2_sftp_data *sftp_data;
+
+ if (!sftp) {
+ php_url_free(resource);
+ return NULL;
+ }
+ sftp_data = emalloc(sizeof(php_ssh2_sftp_data));
+ sftp_data->sftp = sftp;
+ sftp_data->session = session;
+ sftp_data->session_rsrcid = Z_LVAL_PP(tmpzval);
+ zend_list_addref(Z_LVAL_PP(tmpzval));
+ *psftp_rsrcid = ZEND_REGISTER_RESOURCE(NULL, sftp_data, le_ssh2_sftp);
+ *psftp = sftp;
+ *presource_id = Z_LVAL_PP(tmpzval);
+ *psession = session;
+ return resource;
+ }
+ zend_list_addref(Z_LVAL_PP(tmpzval));
+ *psession = session;
+ *presource_id = Z_LVAL_PP(tmpzval);
+ return resource;
+ }
+ }
+
+ /* Make our own connection then */
+ if (!resource->port) {
+ resource->port = 22;
+ }
+
+ if (context &&
+ php_stream_context_get_option(context, "ssh2", "methods", &tmpzval) == SUCCESS &&
+ Z_TYPE_PP(tmpzval) == IS_ARRAY) {
+ methods = *tmpzval;
+ }
+
+ if (context &&
+ php_stream_context_get_option(context, "ssh2", "callbacks", &tmpzval) == SUCCESS &&
+ Z_TYPE_PP(tmpzval) == IS_ARRAY) {
+ callbacks = *tmpzval;
+ }
+
+ if (context &&
+ php_stream_context_get_option(context, "ssh2", "username", &tmpzval) == SUCCESS &&
+ Z_TYPE_PP(tmpzval) == IS_STRING) {
+ username = Z_STRVAL_PP(tmpzval);
+ username_len = Z_STRLEN_PP(tmpzval);
+ }
+
+ if (context &&
+ php_stream_context_get_option(context, "ssh2", "password", &tmpzval) == SUCCESS &&
+ Z_TYPE_PP(tmpzval) == IS_STRING) {
+ password = Z_STRVAL_PP(tmpzval);
+ password_len = Z_STRLEN_PP(tmpzval);
+ }
+
+ if (context &&
+ php_stream_context_get_option(context, "ssh2", "pubkey_file", &tmpzval) == SUCCESS &&
+ Z_TYPE_PP(tmpzval) == IS_STRING) {
+ pubkey_file = Z_STRVAL_PP(tmpzval);
+ }
+
+ if (context &&
+ php_stream_context_get_option(context, "ssh2", "privkey_file", &tmpzval) == SUCCESS &&
+ Z_TYPE_PP(tmpzval) == IS_STRING) {
+ privkey_file = Z_STRVAL_PP(tmpzval);
+ }
+
+ if (resource->user) {
+ int len = strlen(resource->user);
+
+ if (len) {
+ username = resource->user;
+ username_len = len;
+ }
+ }
+
+ if (resource->pass) {
+ int len = strlen(resource->pass);
+
+ if (len) {
+ password = resource->pass;
+ password_len = len;
+ }
+ }
+
+ if (!username) {
+ /* username is a minimum */
+ php_url_free(resource);
+ return NULL;
+ }
+
+ session = php_ssh2_session_connect(resource->host, resource->port, methods, callbacks TSRMLS_CC);
+ if (!session) {
+ /* Unable to connect! */
+ php_url_free(resource);
+ return NULL;
+ }
+
+ /* Authenticate */
+ if (pubkey_file && privkey_file) {
+ if (SSH2_OPENBASEDIR_CHECKPATH(pubkey_file) || SSH2_OPENBASEDIR_CHECKPATH(privkey_file)) {
+ php_url_free(resource);
+ return NULL;
+ }
+
+ /* Attempt pubkey authentication */
+ if (!libssh2_userauth_publickey_fromfile(session, username, pubkey_file, privkey_file, password)) {
+ goto session_authed;
+ }
+ }
+
+ if (password) {
+ /* Attempt password authentication */
+ if (libssh2_userauth_password_ex(session, username, username_len, password, password_len, NULL) == 0) {
+ goto session_authed;
+ }
+ }
+
+ /* Auth failure */
+ php_url_free(resource);
+ zend_list_delete(Z_LVAL(zsession));
+ return NULL;
+
+session_authed:
+ ZEND_REGISTER_RESOURCE(&zsession, session, le_ssh2_session);
+
+ if (psftp) {
+ LIBSSH2_SFTP *sftp;
+ zval zsftp;
+
+ sftp = libssh2_sftp_init(session);
+ if (!sftp) {
+ php_url_free(resource);
+ zend_list_delete(Z_LVAL(zsession));
+ return NULL;
+ }
+
+ sftp_data = emalloc(sizeof(php_ssh2_sftp_data));
+ sftp_data->session = session;
+ sftp_data->sftp = sftp;
+ sftp_data->session_rsrcid = Z_LVAL(zsession);
+
+ ZEND_REGISTER_RESOURCE(&zsftp, sftp_data, le_ssh2_sftp);
+ *psftp_rsrcid = Z_LVAL(zsftp);
+ *psftp = sftp;
+ }
+
+ *presource_id = Z_LVAL(zsession);
+ *psession = session;
+
+ return resource;
+}
+/* }}} */
+
+/* *****************
+ * Shell Wrapper *
+ ***************** */
+
+/* {{{ php_ssh2_shell_open
+ * Make a stream from a session
+ */
+static php_stream *php_ssh2_shell_open(LIBSSH2_SESSION *session, int resource_id, char *term, int term_len, zval *environment, long width, long height, long type TSRMLS_DC)
+{
+ LIBSSH2_CHANNEL *channel;
+ php_ssh2_channel_data *channel_data;
+ php_stream *stream;
+
+ channel = libssh2_channel_open_session(session);
+ if (!channel) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to request a channel from remote host");
+ return NULL;
+ }
+
+ if (environment) {
+ char *key;
+ int key_type, key_len;
+ long idx;
+
+ for(zend_hash_internal_pointer_reset(HASH_OF(environment));
+ (key_type = zend_hash_get_current_key_ex(HASH_OF(environment), &key, &key_len, &idx, 0, NULL)) != HASH_KEY_NON_EXISTANT;
+ zend_hash_move_forward(HASH_OF(environment))) {
+ if (key_type == HASH_KEY_IS_STRING) {
+ zval **value;
+
+ if (zend_hash_get_current_data(HASH_OF(environment), (void**)&value) == SUCCESS) {
+ zval copyval = **value;
+
+ zval_copy_ctor(©val);
+ convert_to_string(©val);
+ if (libssh2_channel_setenv_ex(channel, key, key_len, Z_STRVAL(copyval), Z_STRLEN(copyval))) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed setting %s=%s on remote end", key, Z_STRVAL(copyval));
+ }
+ zval_dtor(©val);
+ }
+ } else {
+ php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Skipping numeric index in environment array");
+ }
+ }
+ }
+
+ if (type == PHP_SSH2_TERM_UNIT_CHARS) {
+ if (libssh2_channel_request_pty_ex(channel, term, term_len, NULL, 0, width, height, 0, 0)) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed allocating %s pty at %ldx%ld characters", term, width, height);
+ libssh2_channel_free(channel);
+ return NULL;
+ }
+ } else {
+ if (libssh2_channel_request_pty_ex(channel, term, term_len, NULL, 0, 0, 0, width, height)) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed allocating %s pty at %ldx%ld pixels", term, width, height);
+ libssh2_channel_free(channel);
+ return NULL;
+ }
+ }
+
+ if (libssh2_channel_shell(channel)) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to request shell from remote host");
+ libssh2_channel_free(channel);
+ return NULL;
+ }
+
+ /* Turn it into a stream */
+ channel_data = emalloc(sizeof(php_ssh2_channel_data));
+ channel_data->channel = channel;
+ channel_data->streamid = 0;
+ channel_data->is_blocking = 0;
+ channel_data->session_rsrc = resource_id;
+ channel_data->refcount = NULL;
+
+ stream = php_stream_alloc(&php_ssh2_channel_stream_ops, channel_data, 0, "r+");
+
+ return stream;
+}
+/* }}} */
+
+/* {{{ php_ssh2_fopen_wrapper_shell
+ * ssh2.shell:// fopen wrapper
+ */
+static php_stream *php_ssh2_fopen_wrapper_shell(php_stream_wrapper *wrapper, char *path, char *mode, int options, char **opened_path, php_stream_context *context STREAMS_DC TSRMLS_DC)
+{
+ LIBSSH2_SESSION *session = NULL;
+ php_stream *stream;
+ zval **tmpzval, *environment = NULL;
+ char *terminal = PHP_SSH2_DEFAULT_TERMINAL;
+ long width = PHP_SSH2_DEFAULT_TERM_WIDTH;
+ long height = PHP_SSH2_DEFAULT_TERM_HEIGHT;
+ long type = PHP_SSH2_DEFAULT_TERM_UNIT;
+ int resource_id = 0, terminal_len = sizeof(PHP_SSH2_DEFAULT_TERMINAL) - 1;
+ php_url *resource;
+ char *s, *e;
+
+ resource = php_ssh2_fopen_wraper_parse_path(path, "shell", context, &session, &resource_id, NULL, NULL TSRMLS_CC);
+ if (!resource || !session) {
+ return NULL;
+ }
+
+ if (context &&
+ php_stream_context_get_option(context, "ssh2", "env", &tmpzval) == SUCCESS &&
+ tmpzval && *tmpzval && Z_TYPE_PP(tmpzval) == IS_ARRAY) {
+ environment = *tmpzval;
+ }
+
+ if (context &&
+ php_stream_context_get_option(context, "ssh2", "term", &tmpzval) == SUCCESS &&
+ tmpzval && *tmpzval && Z_TYPE_PP(tmpzval) == IS_STRING) {
+ terminal = Z_STRVAL_PP(tmpzval);
+ terminal_len = Z_STRLEN_PP(tmpzval);
+ }
+
+ if (context &&
+ php_stream_context_get_option(context, "ssh2", "term_width", &tmpzval) == SUCCESS &&
+ tmpzval && *tmpzval) {
+ zval *copyval;
+ ALLOC_INIT_ZVAL(copyval);
+ *copyval = **tmpzval;
+ convert_to_long(copyval);
+ width = Z_LVAL_P(copyval);
+ zval_ptr_dtor(©val);
+ }
+
+ if (context &&
+ php_stream_context_get_option(context, "ssh2", "term_height", &tmpzval) == SUCCESS &&
+ tmpzval && *tmpzval) {
+ zval *copyval;
+ ALLOC_INIT_ZVAL(copyval);
+ *copyval = **tmpzval;
+ convert_to_long(copyval);
+ height = Z_LVAL_P(copyval);
+ zval_ptr_dtor(©val);
+ }
+
+ if (context &&
+ php_stream_context_get_option(context, "ssh2", "term_units", &tmpzval) == SUCCESS &&
+ tmpzval && *tmpzval) {
+ zval *copyval;
+ ALLOC_INIT_ZVAL(copyval);
+ *copyval = **tmpzval;
+ convert_to_long(copyval);
+ type = Z_LVAL_P(copyval);
+ zval_ptr_dtor(©val);
+ }
+
+ s = resource->path ? resource->path : NULL;
+ e = s ? s + strlen(s) : NULL;
+
+ if (s && s[0] == '/') {
+ /* Terminal type encoded into URL overrides context terminal type */
+ char *p;
+
+ s++;
+ p = strchr(s, '/');
+ if (p) {
+ if (p - s) {
+ terminal = s;
+ terminal_len = p - terminal;
+ s += terminal_len + 1;
+ } else {
+ /* "null" terminal given, skip it */
+ s++;
+ }
+ } else {
+ int len;
+
+ if ((len = strlen(path + 1))) {
+ terminal = s;
+ terminal_len = len;
+ s += len;
+ }
+ }
+ }
+
+ /* TODO: Accept resolution and environment vars as URL style parameters
+ * ssh2.shell://hostorresource/terminal/99x99c?envvar=envval&envvar=envval....
+ */
+ stream = php_ssh2_shell_open(session, resource_id, terminal, terminal_len, environment, width, height, type TSRMLS_CC);
+ if (!stream) {
+ zend_list_delete(resource_id);
+ }
+ php_url_free(resource);
+
+ return stream;
+}
+/* }}} */
+
+static php_stream_wrapper_ops php_ssh2_shell_stream_wops = {
+ php_ssh2_fopen_wrapper_shell,
+ NULL, /* stream_close */
+ NULL, /* stat */
+ NULL, /* stat_url */
+ NULL, /* opendir */
+ "ssh2.shell"
+};
+
+php_stream_wrapper php_ssh2_stream_wrapper_shell = {
+ &php_ssh2_shell_stream_wops,
+ NULL,
+ 0
+};
+
+/* {{{ proto stream ssh2_shell(resource session[, string term_type[, array env[, int width, int height[, int width_height_type]]]])
+ * Open a shell at the remote end and allocate a channel for it
+ */
+PHP_FUNCTION(ssh2_shell)
+{
+ LIBSSH2_SESSION *session;
+ php_stream *stream;
+ zval *zsession;
+ zval *environment = NULL;
+ char *term = PHP_SSH2_DEFAULT_TERMINAL;
+ int term_len = sizeof(PHP_SSH2_DEFAULT_TERMINAL) - 1;
+ long width = PHP_SSH2_DEFAULT_TERM_WIDTH;
+ long height = PHP_SSH2_DEFAULT_TERM_HEIGHT;
+ long type = PHP_SSH2_DEFAULT_TERM_UNIT;
+ int argc = ZEND_NUM_ARGS();
+
+ if (argc == 5) {
+ 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_FALSE;
+ }
+
+ ZEND_FETCH_RESOURCE(session, LIBSSH2_SESSION*, &zsession, -1, PHP_SSH2_SESSION_RES_NAME, le_ssh2_session);
+
+ stream = php_ssh2_shell_open(session, Z_LVAL_P(zsession), term, term_len, environment, width, height, type TSRMLS_CC);
+ if (!stream) {
+ RETURN_FALSE;
+ }
+
+ /* Ensure that channels are freed BEFORE the sessions they belong to */
+ zend_list_addref(Z_LVAL_P(zsession));
+
+ php_stream_to_zval(stream, return_value);
+}
+/* }}} */
+
+/* ****************
+ * Exec Wrapper *
+ **************** */
+
+/* {{{ php_ssh2_exec_command
+ * Make a stream from a session
+ */
+static php_stream *php_ssh2_exec_command(LIBSSH2_SESSION *session, int resource_id, char *command, char *term, int term_len, zval *environment, long width, long height, long type TSRMLS_DC)
+{
+ LIBSSH2_CHANNEL *channel;
+ php_ssh2_channel_data *channel_data;
+ php_stream *stream;
+
+ channel = libssh2_channel_open_session(session);
+ if (!channel) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to request a channel from remote host");
+ return NULL;
+ }
+
+ if (environment) {
+ char *key;
+ int key_type, key_len;
+ long idx;
+
+ for(zend_hash_internal_pointer_reset(HASH_OF(environment));
+ (key_type = zend_hash_get_current_key_ex(HASH_OF(environment), &key, &key_len, &idx, 0, NULL)) != HASH_KEY_NON_EXISTANT;
+ zend_hash_move_forward(HASH_OF(environment))) {
+ if (key_type == HASH_KEY_IS_STRING) {
+ zval **value;
+
+ if (zend_hash_get_current_data(HASH_OF(environment), (void**)&value) == SUCCESS) {
+ zval copyval = **value;
+
+ zval_copy_ctor(©val);
+ convert_to_string(©val);
+ if (libssh2_channel_setenv_ex(channel, key, key_len, Z_STRVAL(copyval), Z_STRLEN(copyval))) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed setting %s=%s on remote end", key, Z_STRVAL(copyval));
+ }
+ zval_dtor(©val);
+ }
+ } else {
+ php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Skipping numeric index in environment array");
+ }
+ }
+ }
+
+ if (term) {
+ if (type == PHP_SSH2_TERM_UNIT_CHARS) {
+ if (libssh2_channel_request_pty_ex(channel, term, term_len, NULL, 0, width, height, 0, 0)) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed allocating %s pty at %ldx%ld characters", term, width, height);
+ libssh2_channel_free(channel);
+ return NULL;
+ }
+ } else {
+ if (libssh2_channel_request_pty_ex(channel, term, term_len, NULL, 0, 0, 0, width, height)) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed allocating %s pty at %ldx%ld pixels", term, width, height);
+ libssh2_channel_free(channel);
+ return NULL;
+ }
+ }
+ }
+
+ if (libssh2_channel_exec(channel, command)) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to request command execution on remote host");
+ libssh2_channel_free(channel);
+ return NULL;
+ }
+
+ /* Turn it into a stream */
+ channel_data = emalloc(sizeof(php_ssh2_channel_data));
+ channel_data->channel = channel;
+ channel_data->streamid = 0;
+ channel_data->is_blocking = 0;
+ channel_data->session_rsrc = resource_id;
+ channel_data->refcount = NULL;
+
+ stream = php_stream_alloc(&php_ssh2_channel_stream_ops, channel_data, 0, "r+");
+
+ return stream;
+}
+/* }}} */
+
+/* {{{ php_ssh2_fopen_wrapper_exec
+ * ssh2.exec:// fopen wrapper
+ */
+static php_stream *php_ssh2_fopen_wrapper_exec(php_stream_wrapper *wrapper, char *path, char *mode, int options, char **opened_path, php_stream_context *context STREAMS_DC TSRMLS_DC)
+{
+ LIBSSH2_SESSION *session = NULL;
+ php_stream *stream;
+ zval **tmpzval, *environment = NULL;
+ int resource_id = 0;
+ php_url *resource;
+ char *terminal = NULL;
+ int terminal_len = 0;
+ long width = PHP_SSH2_DEFAULT_TERM_WIDTH;
+ long height = PHP_SSH2_DEFAULT_TERM_HEIGHT;
+ long type = PHP_SSH2_DEFAULT_TERM_UNIT;
+
+ resource = php_ssh2_fopen_wraper_parse_path(path, "exec", context, &session, &resource_id, NULL, NULL TSRMLS_CC);
+ if (!resource || !session) {
+ return NULL;
+ }
+ if (!resource->path) {
+ php_url_free(resource);
+ zend_list_delete(resource_id);
+ return NULL;
+ }
+
+ if (context &&
+ php_stream_context_get_option(context, "ssh2", "env", &tmpzval) == SUCCESS &&
+ tmpzval && *tmpzval && Z_TYPE_PP(tmpzval) == IS_ARRAY) {
+ environment = *tmpzval;
+ }
+
+ if (context &&
+ php_stream_context_get_option(context, "ssh2", "term", &tmpzval) == SUCCESS &&
+ tmpzval && *tmpzval && Z_TYPE_PP(tmpzval) == IS_STRING) {
+ terminal = Z_STRVAL_PP(tmpzval);
+ terminal_len = Z_STRLEN_PP(tmpzval);
+ }
+
+ if (context &&
+ php_stream_context_get_option(context, "ssh2", "term_width", &tmpzval) == SUCCESS &&
+ tmpzval && *tmpzval) {
+ zval *copyval;
+ ALLOC_INIT_ZVAL(copyval);
+ *copyval = **tmpzval;
+ convert_to_long(copyval);
+ width = Z_LVAL_P(copyval);
+ zval_ptr_dtor(©val);
+ }
+
+ if (context &&
+ php_stream_context_get_option(context, "ssh2", "term_height", &tmpzval) == SUCCESS &&
+ tmpzval && *tmpzval) {
+ zval *copyval;
+ ALLOC_INIT_ZVAL(copyval);
+ *copyval = **tmpzval;
+ convert_to_long(copyval);
+ height = Z_LVAL_P(copyval);
+ zval_ptr_dtor(©val);
+ }
+
+ if (context &&
+ php_stream_context_get_option(context, "ssh2", "term_units", &tmpzval) == SUCCESS &&
+ tmpzval && *tmpzval) {
+ zval *copyval;
+ ALLOC_INIT_ZVAL(copyval);
+ *copyval = **tmpzval;
+ convert_to_long(copyval);
+ type = Z_LVAL_P(copyval);
+ zval_ptr_dtor(©val);
+ }
+
+ stream = php_ssh2_exec_command(session, resource_id, resource->path + 1, terminal, terminal_len, environment, width, height, type TSRMLS_CC);
+ if (!stream) {
+ zend_list_delete(resource_id);
+ }
+ php_url_free(resource);
+
+ return stream;
+}
+/* }}} */
+
+static php_stream_wrapper_ops php_ssh2_exec_stream_wops = {
+ php_ssh2_fopen_wrapper_exec,
+ NULL, /* stream_close */
+ NULL, /* stat */
+ NULL, /* stat_url */
+ NULL, /* opendir */
+ "ssh2.exec"
+};
+
+php_stream_wrapper php_ssh2_stream_wrapper_exec = {
+ &php_ssh2_exec_stream_wops,
+ NULL,
+ 0
+};
+
+/* {{{ proto stream ssh2_exec(resource session, string command[, string pty[, array env[, int width[, int heightp[, int width_height_type]]]]])
+ * Execute a command at the remote end and allocate a channel for it
+ *
+ * This function has a dirty little secret.... pty and env can be in either order.... shhhh... don't tell anyone
+ */
+PHP_FUNCTION(ssh2_exec)
+{
+ LIBSSH2_SESSION *session;
+ php_stream *stream;
+ zval *zsession;
+ zval *environment = NULL;
+ zval *zpty = NULL;
+ char *command;
+ int command_len;
+ long width = PHP_SSH2_DEFAULT_TERM_WIDTH;
+ long height = PHP_SSH2_DEFAULT_TERM_HEIGHT;
+ long type = PHP_SSH2_DEFAULT_TERM_UNIT;
+ char *term = NULL;
+ 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_FALSE;
+ }
+
+ if (zpty && Z_TYPE_P(zpty) == IS_ARRAY) {
+ /* Swap pty and environment -- old call style */
+ zval *tmp = zpty;
+ zpty = environment;
+ environment = tmp;
+ }
+
+ if (environment && Z_TYPE_P(environment) != IS_ARRAY) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "ssh2_exec() expects arg 4 to be of type array");
+ RETURN_FALSE;
+ }
+
+ if (zpty) {
+ convert_to_string(zpty);
+ term = Z_STRVAL_P(zpty);
+ term_len = Z_STRLEN_P(zpty);
+ }
+
+ ZEND_FETCH_RESOURCE(session, LIBSSH2_SESSION*, &zsession, -1, PHP_SSH2_SESSION_RES_NAME, le_ssh2_session);
+
+ stream = php_ssh2_exec_command(session, Z_LVAL_P(zsession), command, term, term_len, environment, width, height, type TSRMLS_CC);
+ if (!stream) {
+ RETURN_FALSE;
+ }
+
+ /* Ensure that channels are freed BEFORE the sessions they belong to */
+ zend_list_addref(Z_LVAL_P(zsession));
+
+ php_stream_to_zval(stream, return_value);
+}
+/* }}} */
+
+/* ***************
+ * SCP Wrapper *
+ *************** */
+
+/* {{{ php_ssh2_scp_xfer
+ * Make a stream from a session
+ */
+static php_stream *php_ssh2_scp_xfer(LIBSSH2_SESSION *session, int resource_id, char *filename TSRMLS_DC)
+{
+ LIBSSH2_CHANNEL *channel;
+ php_ssh2_channel_data *channel_data;
+ php_stream *stream;
+
+ channel = libssh2_scp_recv(session, filename, NULL);
+ if (!channel) {
+ char *error = "";
+ libssh2_session_last_error(session, &error, NULL, 0);
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to request a channel from remote host: %s", error);
+ return NULL;
+ }
+
+ /* Turn it into a stream */
+ channel_data = emalloc(sizeof(php_ssh2_channel_data));
+ channel_data->channel = channel;
+ channel_data->streamid = 0;
+ channel_data->is_blocking = 0;
+ channel_data->session_rsrc = resource_id;
+ channel_data->refcount = NULL;
+
+ stream = php_stream_alloc(&php_ssh2_channel_stream_ops, channel_data, 0, "r");
+
+ return stream;
+}
+/* }}} */
+
+/* {{{ php_ssh2_fopen_wrapper_scp
+ * ssh2.scp:// fopen wrapper (Read mode only, if you want to know why write mode isn't supported as a stream, take a look at the SCP protocol)
+ */
+static php_stream *php_ssh2_fopen_wrapper_scp(php_stream_wrapper *wrapper, char *path, char *mode, int options, char **opened_path, php_stream_context *context STREAMS_DC TSRMLS_DC)
+{
+ LIBSSH2_SESSION *session = NULL;
+ php_stream *stream;
+ int resource_id = 0;
+ php_url *resource;
+
+ if (strchr(mode, '+') || strchr(mode, 'a') || strchr(mode, 'w')) {
+ return NULL;
+ }
+
+ resource = php_ssh2_fopen_wraper_parse_path(path, "scp", context, &session, &resource_id, NULL, NULL TSRMLS_CC);
+ if (!resource || !session) {
+ return NULL;
+ }
+ if (!resource->path) {
+ php_url_free(resource);
+ zend_list_delete(resource_id);
+ return NULL;
+ }
+
+ stream = php_ssh2_scp_xfer(session, resource_id, resource->path TSRMLS_CC);
+ if (!stream) {
+ zend_list_delete(resource_id);
+ }
+ php_url_free(resource);
+
+ return stream;
+}
+/* }}} */
+
+static php_stream_wrapper_ops php_ssh2_scp_stream_wops = {
+ php_ssh2_fopen_wrapper_scp,
+ NULL, /* stream_close */
+ NULL, /* stat */
+ NULL, /* stat_url */
+ NULL, /* opendir */
+ "ssh2.scp"
+};
+
+php_stream_wrapper php_ssh2_stream_wrapper_scp = {
+ &php_ssh2_scp_stream_wops,
+ NULL,
+ 0
+};
+
+/* {{{ proto bool ssh2_scp_recv(resource session, string remote_file, string local_file)
+ * Request a file via SCP
+ */
+PHP_FUNCTION(ssh2_scp_recv)
+{
+ LIBSSH2_SESSION *session;
+ LIBSSH2_CHANNEL *remote_file;
+ struct stat sb;
+ php_stream *local_file;
+ zval *zsession;
+ char *remote_filename, *local_filename;
+ int remote_filename_len, local_filename_len;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rss", &zsession, &remote_filename, &remote_filename_len,
+ &local_filename, &local_filename_len) == FAILURE) {
+ RETURN_FALSE;
+ }
+
+ ZEND_FETCH_RESOURCE(session, LIBSSH2_SESSION*, &zsession, -1, PHP_SSH2_SESSION_RES_NAME, le_ssh2_session);
+
+ remote_file = libssh2_scp_recv(session, remote_filename, &sb);
+ if (!remote_file) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to receive remote file");
+ RETURN_FALSE;
+ }
+ libssh2_channel_set_blocking(remote_file, 1);
+
+ local_file = php_stream_open_wrapper(local_filename, "wb", ENFORCE_SAFE_MODE | REPORT_ERRORS, NULL);
+ if (!local_file) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to write to local file");
+ libssh2_channel_free(remote_file);
+ RETURN_FALSE;
+ }
+
+ while (sb.st_size) {
+ char buffer[8192];
+ int bytes_read;
+
+ bytes_read = libssh2_channel_read(remote_file, buffer, sb.st_size > 8192 ? 8192 : sb.st_size);
+ if (bytes_read < 0) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error reading from remote file");
+ libssh2_channel_free(remote_file);
+ php_stream_close(local_file);
+ RETURN_FALSE;
+ }
+ php_stream_write(local_file, buffer, bytes_read);
+ sb.st_size -= bytes_read;
+ }
+
+ libssh2_channel_free(remote_file);
+ php_stream_close(local_file);
+
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto stream ssh2_scp_send(resource session, string local_file, string remote_file[, int create_mode = 0644])
+ * Send a file via SCP
+ */
+PHP_FUNCTION(ssh2_scp_send)
+{
+ LIBSSH2_SESSION *session;
+ LIBSSH2_CHANNEL *remote_file;
+ php_stream *local_file;
+ zval *zsession;
+ char *local_filename, *remote_filename;
+ int local_filename_len, remote_filename_len;
+ long create_mode = 0644;
+ php_stream_statbuf ssb;
+ int argc = ZEND_NUM_ARGS();
+
+ if (zend_parse_parameters(argc TSRMLS_CC, "rss|l", &zsession, &local_filename, &local_filename_len,
+ &remote_filename, &remote_filename_len, &create_mode) == FAILURE) {
+ 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");
+ RETURN_FALSE;
+ }
+
+ if (php_stream_stat(local_file, &ssb)) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed statting local file");
+ php_stream_close(local_file);
+ RETURN_FALSE;
+ }
+
+ if (argc < 4) {
+ create_mode = ssb.sb.st_mode & 0777;
+ }
+
+ remote_file = libssh2_scp_send_ex(session, remote_filename, create_mode, ssb.sb.st_size, ssb.sb.st_atime, ssb.sb.st_mtime);
+ if (!remote_file) {
+ int last_error = 0;
+ char *error_msg = NULL;
+
+ last_error = libssh2_session_last_error(session, &error_msg, NULL, 0);
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failure creating remote file: %s", error_msg);
+ php_stream_close(local_file);
+ RETURN_FALSE;
+ }
+ libssh2_channel_set_blocking(remote_file, 1);
+
+ 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 (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;
+ }
+
+ if (bytesread != libssh2_channel_write(remote_file, buffer, 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;
+ }
+
+ php_stream_close(local_file);
+ libssh2_channel_free(remote_file);
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* ***************************
+ * Direct TCP/IP Transport *
+ *************************** */
+
+/* {{{ php_ssh2_direct_tcpip
+ * Make a stream from a session
+ */
+static php_stream *php_ssh2_direct_tcpip(LIBSSH2_SESSION *session, int resource_id, char *host, int port TSRMLS_DC)
+{
+ LIBSSH2_CHANNEL *channel;
+ php_ssh2_channel_data *channel_data;
+ php_stream *stream;
+
+ channel = libssh2_channel_direct_tcpip(session, host, port);
+ if (!channel) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to request a channel from remote host");
+ return NULL;
+ }
+
+ /* Turn it into a stream */
+ channel_data = emalloc(sizeof(php_ssh2_channel_data));
+ channel_data->channel = channel;
+ channel_data->streamid = 0;
+ channel_data->is_blocking = 0;
+ channel_data->session_rsrc = resource_id;
+ channel_data->refcount = NULL;
+
+ stream = php_stream_alloc(&php_ssh2_channel_stream_ops, channel_data, 0, "r+");
+
+ return stream;
+}
+/* }}} */
+
+/* {{{ php_ssh2_fopen_wrapper_tunnel
+ * ssh2.tunnel:// fopen wrapper
+ */
+static php_stream *php_ssh2_fopen_wrapper_tunnel(php_stream_wrapper *wrapper, char *path, char *mode, int options, char **opened_path, php_stream_context *context STREAMS_DC TSRMLS_DC)
+{
+ LIBSSH2_SESSION *session = NULL;
+ php_stream *stream = NULL;
+ php_url *resource;
+ char *host = NULL;
+ int port = 0;
+ int resource_id = 0;
+
+ resource = php_ssh2_fopen_wraper_parse_path(path, "tunnel", context, &session, &resource_id, NULL, NULL TSRMLS_CC);
+ if (!resource || !session) {
+ return NULL;
+ }
+
+ if (resource->path && resource->path[0] == '/') {
+ char *colon;
+
+ host = resource->path + 1;
+ if (*host == '[') {
+ /* IPv6 Encapsulated Format */
+ host++;
+ colon = strstr(host, "]:");
+ if (colon) {
+ *colon = 0;
+ colon += 2;
+ }
+ } else {
+ colon = strchr(host, ':');
+ if (colon) {
+ *(colon++) = 0;
+ }
+ }
+ if (colon) {
+ port = atoi(colon);
+ }
+ }
+
+ if ((port <= 0) || (port > 65535) || !host || (strlen(host) == 0)) {
+ /* Invalid connection criteria */
+ php_url_free(resource);
+ zend_list_delete(resource_id);
+ return NULL;
+ }
+
+ stream = php_ssh2_direct_tcpip(session, resource_id, host, port TSRMLS_CC);
+ if (!stream) {
+ zend_list_delete(resource_id);
+ }
+ php_url_free(resource);
+
+ return stream;
+}
+/* }}} */
+
+static php_stream_wrapper_ops php_ssh2_tunnel_stream_wops = {
+ php_ssh2_fopen_wrapper_tunnel,
+ NULL, /* stream_close */
+ NULL, /* stat */
+ NULL, /* stat_url */
+ NULL, /* opendir */
+ "ssh2.tunnel"
+};
+
+php_stream_wrapper php_ssh2_stream_wrapper_tunnel = {
+ &php_ssh2_tunnel_stream_wops,
+ NULL,
+ 0
+};
+
+/* {{{ proto stream ssh2_tunnel(resource session, string host, int port)
+ * Tunnel to remote TCP/IP host/port
+ */
+PHP_FUNCTION(ssh2_tunnel)
+{
+ LIBSSH2_SESSION *session;
+ php_stream *stream;
+ zval *zsession;
+ char *host;
+ int host_len;
+ long port;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rsl", &zsession, &host, &host_len, &port) == FAILURE) {
+ RETURN_FALSE;
+ }
+
+ ZEND_FETCH_RESOURCE(session, LIBSSH2_SESSION*, &zsession, -1, PHP_SSH2_SESSION_RES_NAME, le_ssh2_session);
+
+ stream = php_ssh2_direct_tcpip(session, Z_LVAL_P(zsession), host, port TSRMLS_CC);
+ if (!stream) {
+ RETURN_FALSE;
+ }
+
+ /* Ensure that channels are freed BEFORE the sessions they belong to */
+ zend_list_addref(Z_LVAL_P(zsession));
+
+ php_stream_to_zval(stream, return_value);
+}
+/* }}} */
+
+/* ******************
+ * Generic Helper *
+ ****************** */
+
+/* {{{ proto stream ssh2_fetch_stream(stream channel, int streamid)
+ * Fetch an extended data stream
+ */
+PHP_FUNCTION(ssh2_fetch_stream)
+{
+ php_ssh2_channel_data *data, *stream_data;
+ php_stream *parent, *stream;
+ zval *zparent;
+ long streamid;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl", &zparent, &streamid) == FAILURE) {
+ RETURN_FALSE;
+ }
+
+ if (streamid < 0) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid stream ID requested");
+ RETURN_FALSE;
+ }
+
+ php_stream_from_zval(parent, &zparent);
+
+ if (parent->ops != &php_ssh2_channel_stream_ops) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Provided stream is not of type " PHP_SSH2_CHANNEL_STREAM_NAME);
+ RETURN_FALSE;
+ }
+
+ data = (php_ssh2_channel_data*)parent->abstract;
+
+ if (!data->refcount) {
+ data->refcount = emalloc(sizeof(unsigned char));
+ *(data->refcount) = 1;
+ }
+
+ if (*(data->refcount) == 255) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Too many streams associated to a single channel");
+ RETURN_FALSE;
+ }
+
+ (*(data->refcount))++;
+
+ stream_data = emalloc(sizeof(php_ssh2_channel_data));
+ memcpy(stream_data, data, sizeof(php_ssh2_channel_data));
+ stream_data->streamid = streamid;
+
+ stream = php_stream_alloc(&php_ssh2_channel_stream_ops, stream_data, 0, "r+");
+ if (!stream) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error opening substream");
+ efree(stream_data);
+ *(data->refcount)--;
+ RETURN_FALSE;
+ }
+
+ php_stream_to_zval(stream, return_value);
+}
+/* }}} */
+
+/*
+ * 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
+ */
|
[-]
[+]
|
Added |
ssh2-0.11.3.tgz/ssh2-0.11.3/ssh2_sftp.c
^
|
@@ -0,0 +1,856 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 4 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997-2006 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: Sara Golemon <pollita@php.net> |
+ +----------------------------------------------------------------------+
+
+ $Id: ssh2_sftp.c 317118 2011-09-21 19:05:21Z bjori $
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "php.h"
+#include "php_ssh2.h"
+#include "ext/standard/php_string.h"
+
+/* *************************
+ * Resource Housekeeping *
+ ************************* */
+
+void php_ssh2_sftp_dtor(zend_rsrc_list_entry *rsrc TSRMLS_DC)
+{
+ php_ssh2_sftp_data *data = (php_ssh2_sftp_data*)rsrc->ptr;
+
+ if (!data) {
+ return;
+ }
+
+ libssh2_sftp_shutdown(data->sftp);
+
+ zend_list_delete(data->session_rsrcid);
+
+ efree(data);
+}
+
+/* *****************
+ * SFTP File Ops *
+ ***************** */
+
+inline unsigned long php_ssh2_parse_fopen_modes(char *openmode) {
+ unsigned long flags = 0;
+
+ if (strchr(openmode, 'a')) {
+ flags |= LIBSSH2_FXF_APPEND;
+ }
+
+ if (strchr(openmode, 'w')) {
+ flags |= LIBSSH2_FXF_WRITE | LIBSSH2_FXF_TRUNC | LIBSSH2_FXF_CREAT;
+ }
+
+ if (strchr(openmode, 'r')) {
+ flags |= LIBSSH2_FXF_READ;
+ }
+
+ if (strchr(openmode, '+')) {
+ flags |= LIBSSH2_FXF_READ | LIBSSH2_FXF_WRITE;
+ }
+
+ if (strchr(openmode, 'x')) {
+ flags |= LIBSSH2_FXF_WRITE | LIBSSH2_FXF_TRUNC | LIBSSH2_FXF_EXCL | LIBSSH2_FXF_CREAT;
+ }
+
+ return flags;
+}
+
+inline int php_ssh2_sftp_attr2ssb(php_stream_statbuf *ssb, LIBSSH2_SFTP_ATTRIBUTES *attrs)
+{
+ memset(ssb, 0, sizeof(php_stream_statbuf));
+ if (attrs->flags & LIBSSH2_SFTP_ATTR_SIZE) {
+ ssb->sb.st_size = attrs->filesize;
+ }
+
+ if (attrs->flags & LIBSSH2_SFTP_ATTR_UIDGID) {
+ ssb->sb.st_uid = attrs->uid;
+ ssb->sb.st_gid = attrs->gid;
+ }
+ if (attrs->flags & LIBSSH2_SFTP_ATTR_PERMISSIONS) {
+ ssb->sb.st_mode = attrs->permissions;
+ }
+ if (attrs->flags & LIBSSH2_SFTP_ATTR_ACMODTIME) {
+ ssb->sb.st_atime = attrs->atime;
+ ssb->sb.st_mtime = attrs->mtime;
+ }
+
+ return 0;
+}
+
+typedef struct _php_ssh2_sftp_handle_data {
+ LIBSSH2_SFTP_HANDLE *handle;
+
+ long sftp_rsrcid;
+} php_ssh2_sftp_handle_data;
+
+/* {{{ php_ssh2_sftp_stream_write
+ */
+static size_t php_ssh2_sftp_stream_write(php_stream *stream, const char *buf, size_t count TSRMLS_DC)
+{
+ php_ssh2_sftp_handle_data *data = (php_ssh2_sftp_handle_data*)stream->abstract;
+ ssize_t bytes_written;
+
+ bytes_written = libssh2_sftp_write(data->handle, buf, count);
+
+ return (size_t)(bytes_written<0 ? 0 : bytes_written);
+}
+/* }}} */
+
+/* {{{ php_ssh2_sftp_stream_read
+ */
+static size_t php_ssh2_sftp_stream_read(php_stream *stream, char *buf, size_t count TSRMLS_DC)
+{
+ php_ssh2_sftp_handle_data *data = (php_ssh2_sftp_handle_data*)stream->abstract;
+ ssize_t bytes_read;
+
+ bytes_read = libssh2_sftp_read(data->handle, buf, count);
+
+ stream->eof = (bytes_read <= 0 && bytes_read != LIBSSH2_ERROR_EAGAIN);
+
+ return (size_t)(bytes_read<0 ? 0 : bytes_read);
+}
+/* }}} */
+
+/* {{{ php_ssh2_sftp_stream_close
+ */
+static int php_ssh2_sftp_stream_close(php_stream *stream, int close_handle TSRMLS_DC)
+{
+ php_ssh2_sftp_handle_data *data = (php_ssh2_sftp_handle_data*)stream->abstract;
+
+ libssh2_sftp_close(data->handle);
+ zend_list_delete(data->sftp_rsrcid);
+ efree(data);
+
+ return 0;
+}
+/* }}} */
+
+/* {{{ php_ssh2_sftp_stream_seek
+ */
+static int php_ssh2_sftp_stream_seek(php_stream *stream, off_t offset, int whence, off_t *newoffset TSRMLS_DC)
+{
+ php_ssh2_sftp_handle_data *data = (php_ssh2_sftp_handle_data*)stream->abstract;
+
+ switch (whence) {
+ case SEEK_END:
+ {
+ LIBSSH2_SFTP_ATTRIBUTES attrs;
+
+ if (libssh2_sftp_fstat(data->handle, &attrs)) {
+ return -1;
+ }
+ if ((attrs.flags & LIBSSH2_SFTP_ATTR_SIZE) == 0) {
+ return -1;
+ }
+ offset += attrs.filesize;
+ }
+ case SEEK_CUR:
+ {
+ off_t current_offset = libssh2_sftp_tell(data->handle);
+
+ if (current_offset < 0) {
+ return -1;
+ }
+
+ offset += current_offset;
+ }
+ }
+
+ libssh2_sftp_seek(data->handle, offset);
+
+ if (newoffset) {
+ *newoffset = offset;
+ }
+
+ return 0;
+}
+/* }}} */
+
+/* {{{ php_ssh2_sftp_stream_fstat
+ */
+static int php_ssh2_sftp_stream_fstat(php_stream *stream, php_stream_statbuf *ssb TSRMLS_DC)
+{
+ php_ssh2_sftp_handle_data *data = (php_ssh2_sftp_handle_data*)stream->abstract;
+ LIBSSH2_SFTP_ATTRIBUTES attrs;
+
+ if (libssh2_sftp_fstat(data->handle, &attrs)) {
+ return -1;
+ }
+
+ return php_ssh2_sftp_attr2ssb(ssb, &attrs);
+}
+/* }}} */
+
+static php_stream_ops php_ssh2_sftp_stream_ops = {
+ php_ssh2_sftp_stream_write,
+ php_ssh2_sftp_stream_read,
+ php_ssh2_sftp_stream_close,
+ NULL, /* flush */
+ PHP_SSH2_SFTP_STREAM_NAME,
+ php_ssh2_sftp_stream_seek,
+ NULL, /* cast */
+ php_ssh2_sftp_stream_fstat,
+ NULL, /* set_option */
+};
+
+/* {{{ php_ssh2_sftp_stream_opener
+ */
+static php_stream *php_ssh2_sftp_stream_opener( php_stream_wrapper *wrapper, char *filename, char *mode,
+ int options, char **opened_path, php_stream_context *context STREAMS_DC TSRMLS_DC)
+{
+ php_ssh2_sftp_handle_data *data;
+ LIBSSH2_SESSION *session = NULL;
+ LIBSSH2_SFTP *sftp = NULL;
+ LIBSSH2_SFTP_HANDLE *handle;
+ php_stream *stream;
+ int resource_id = 0, sftp_rsrcid = 0;
+ php_url *resource;
+ unsigned long flags;
+ long perms = 0644;
+
+ resource = php_ssh2_fopen_wraper_parse_path(filename, "sftp", context, &session, &resource_id, &sftp, &sftp_rsrcid TSRMLS_CC);
+ if (!resource || !session || !sftp) {
+ return NULL;
+ }
+
+ flags = php_ssh2_parse_fopen_modes(mode);
+
+ handle = libssh2_sftp_open(sftp, resource->path, flags, perms);
+ if (!handle) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to open %s on remote host", filename);
+ php_url_free(resource);
+ zend_list_delete(sftp_rsrcid);
+ return NULL;
+ }
+
+ data = emalloc(sizeof(php_ssh2_sftp_handle_data));
+ data->handle = handle;
+ data->sftp_rsrcid = sftp_rsrcid;
+
+ stream = php_stream_alloc(&php_ssh2_sftp_stream_ops, data, 0, mode);
+ if (!stream) {
+ libssh2_sftp_close(handle);
+ zend_list_delete(sftp_rsrcid);
+ efree(data);
+ }
+ php_url_free(resource);
+
+ return stream;
+}
+/* }}} */
+
+/* **********************
+ * SFTP Directory Ops *
+ ********************** */
+
+/* {{{ php_ssh2_sftp_dirstream_read
+ */
+static size_t php_ssh2_sftp_dirstream_read(php_stream *stream, char *buf, size_t count TSRMLS_DC)
+{
+ php_ssh2_sftp_handle_data *data = (php_ssh2_sftp_handle_data*)stream->abstract;
+ php_stream_dirent *ent = (php_stream_dirent*)buf;
+ size_t bytesread = libssh2_sftp_readdir(data->handle, ent->d_name, sizeof(ent->d_name) - 1, NULL);
+ char *basename = NULL;
+ size_t basename_len = 0;
+
+ if (bytesread <= 0) {
+ return 0;
+ }
+ ent->d_name[bytesread] = 0;
+
+#ifdef ZEND_ENGINE_2
+ php_basename(ent->d_name, bytesread, NULL, 0, &basename, &basename_len TSRMLS_CC);
+#else
+/* CURSE YOU BC BREAKS! */
+ basename = php_basename(ent->d_name, bytesread, NULL, 0);
+ if (basename) {
+ basename_len = strlen(basename);
+ }
+#endif
+ if (!basename) {
+ return 0;
+ }
+
+ if (!basename_len) {
+ efree(basename);
+ return 0;
+ }
+ bytesread = MIN(sizeof(ent->d_name) - 1, basename_len);
+ memcpy(ent->d_name, basename, bytesread);
+ ent->d_name[bytesread] = 0;
+ efree(basename);
+
+ return sizeof(php_stream_dirent);
+}
+/* }}} */
+
+/* {{{ php_ssh2_sftp_dirstream_close
+ */
+static int php_ssh2_sftp_dirstream_close(php_stream *stream, int close_handle TSRMLS_DC)
+{
+ php_ssh2_sftp_handle_data *data = (php_ssh2_sftp_handle_data*)stream->abstract;
+
+ libssh2_sftp_close(data->handle);
+ zend_list_delete(data->sftp_rsrcid);
+ efree(data);
+
+ return 0;
+}
+/* }}} */
+
+static php_stream_ops php_ssh2_sftp_dirstream_ops = {
+ NULL, /* write */
+ php_ssh2_sftp_dirstream_read,
+ php_ssh2_sftp_dirstream_close,
+ NULL, /* flush */
+ PHP_SSH2_SFTP_DIRSTREAM_NAME,
+ NULL, /* seek */
+ NULL, /* cast */
+ NULL, /* fstat */
+ NULL, /* set_option */
+};
+
+/* {{{ php_ssh2_sftp_dirstream_opener
+ */
+static php_stream *php_ssh2_sftp_dirstream_opener( php_stream_wrapper *wrapper, char *filename, char *mode,
+ int options, char **opened_path, php_stream_context *context STREAMS_DC TSRMLS_DC)
+{
+ php_ssh2_sftp_handle_data *data;
+ LIBSSH2_SESSION *session = NULL;
+ LIBSSH2_SFTP *sftp = NULL;
+ LIBSSH2_SFTP_HANDLE *handle;
+ php_stream *stream;
+ int resource_id = 0, sftp_rsrcid = 0;
+ php_url *resource;
+
+ resource = php_ssh2_fopen_wraper_parse_path(filename, "sftp", context, &session, &resource_id, &sftp, &sftp_rsrcid TSRMLS_CC);
+ if (!resource || !session || !sftp) {
+ return NULL;
+ }
+
+ handle = libssh2_sftp_opendir(sftp, resource->path);
+ if (!handle) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to open %s on remote host", filename);
+ php_url_free(resource);
+ zend_list_delete(sftp_rsrcid);
+ return NULL;
+ }
+
+ data = emalloc(sizeof(php_ssh2_sftp_handle_data));
+ data->handle = handle;
+ data->sftp_rsrcid = sftp_rsrcid;
+
+ stream = php_stream_alloc(&php_ssh2_sftp_dirstream_ops, data, 0, mode);
+ if (!stream) {
+ libssh2_sftp_close(handle);
+ zend_list_delete(sftp_rsrcid);
+ efree(data);
+ }
+ php_url_free(resource);
+
+ return stream;
+}
+/* }}} */
+
+/* ****************
+ * SFTP Wrapper *
+ **************** */
+
+#ifdef ZEND_ENGINE_2
+/* {{{ php_ssh2_sftp_urlstat
+ */
+static int php_ssh2_sftp_urlstat(php_stream_wrapper *wrapper, char *url, int flags, php_stream_statbuf *ssb, php_stream_context *context TSRMLS_DC)
+{
+ LIBSSH2_SFTP_ATTRIBUTES attrs;
+ LIBSSH2_SESSION *session = NULL;
+ LIBSSH2_SFTP *sftp = NULL;
+ int resource_id = 0, sftp_rsrcid = 0;
+ php_url *resource;
+
+ resource = php_ssh2_fopen_wraper_parse_path(url, "sftp", context, &session, &resource_id, &sftp, &sftp_rsrcid TSRMLS_CC);
+ if (!resource || !session || !sftp || !resource->path) {
+ return -1;
+ }
+
+ if (libssh2_sftp_stat_ex(sftp, resource->path, strlen(resource->path),
+ (flags & PHP_STREAM_URL_STAT_LINK) ? LIBSSH2_SFTP_LSTAT : LIBSSH2_SFTP_STAT, &attrs)) {
+ php_url_free(resource);
+ zend_list_delete(sftp_rsrcid);
+ return -1;
+ }
+
+ php_url_free(resource);
+
+ /* parse_path addrefs the resource, but we're not holding on to it so we have to delref it before we leave */
+ zend_list_delete(sftp_rsrcid);
+
+ return php_ssh2_sftp_attr2ssb(ssb, &attrs);
+}
+/* }}} */
+
+/* {{{ php_ssh2_sftp_unlink
+ */
+static int php_ssh2_sftp_unlink(php_stream_wrapper *wrapper, char *url, int options, php_stream_context *context TSRMLS_DC)
+{
+ LIBSSH2_SESSION *session = NULL;
+ LIBSSH2_SFTP *sftp = NULL;
+ int resource_id = 0, sftp_rsrcid = 0;
+ php_url *resource;
+ int result;
+
+ resource = php_ssh2_fopen_wraper_parse_path(url, "sftp", context, &session, &resource_id, &sftp, &sftp_rsrcid TSRMLS_CC);
+ if (!resource || !session || !sftp || !resource->path) {
+ if (resource) {
+ php_url_free(resource);
+ }
+ return 0;
+ }
+
+ result = libssh2_sftp_unlink(sftp, resource->path);
+ php_url_free(resource);
+
+ zend_list_delete(sftp_rsrcid);
+
+ /* libssh2 uses 0 for success and the streams API uses 0 for failure, so invert */
+ return (result == 0) ? -1 : 0;
+}
+/* }}} */
+
+/* {{{ php_ssh2_sftp_rename
+ */
+static int php_ssh2_sftp_rename(php_stream_wrapper *wrapper, char *url_from, char *url_to, int options, php_stream_context *context TSRMLS_DC)
+{
+ LIBSSH2_SESSION *session = NULL;
+ LIBSSH2_SFTP *sftp = NULL;
+ int resource_id = 0, sftp_rsrcid = 0;
+ php_url *resource, *resource_to;
+ int result;
+
+ if (strncmp(url_from, "ssh2.sftp://", sizeof("ssh2.sftp://") - 1) ||
+ strncmp(url_to, "ssh2.sftp://", sizeof("ssh2.sftp://") - 1)) {
+ return 0;
+ }
+
+ resource_to = php_url_parse(url_to);
+ if (!resource_to || !resource_to->path) {
+ if (resource_to) {
+ php_url_free(resource_to);
+ }
+ return 0;
+ }
+
+ resource = php_ssh2_fopen_wraper_parse_path(url_from, "sftp", context, &session, &resource_id, &sftp, &sftp_rsrcid TSRMLS_CC);
+ if (!resource || !session || !sftp || !resource->path) {
+ if (resource) {
+ php_url_free(resource);
+ }
+ php_url_free(resource_to);
+ return 0;
+ }
+
+ result = libssh2_sftp_rename(sftp, resource->path, resource_to->path);
+ php_url_free(resource);
+ php_url_free(resource_to);
+
+ zend_list_delete(sftp_rsrcid);
+
+ /* libssh2 uses 0 for success and the streams API uses 0 for failure, so invert */
+ return (result == 0) ? -1 : 0;
+}
+/* }}} */
+
+/* {{{ php_ssh2_sftp_mkdir
+ */
+static int php_ssh2_sftp_mkdir(php_stream_wrapper *wrapper, char *url, int mode, int options, php_stream_context *context TSRMLS_DC)
+{
+ LIBSSH2_SESSION *session = NULL;
+ LIBSSH2_SFTP *sftp = NULL;
+ int resource_id = 0, sftp_rsrcid = 0;
+ php_url *resource;
+ int result;
+
+ resource = php_ssh2_fopen_wraper_parse_path(url, "sftp", context, &session, &resource_id, &sftp, &sftp_rsrcid TSRMLS_CC);
+ if (!resource || !session || !sftp || !resource->path) {
+ if (resource) {
+ php_url_free(resource);
+ }
+ return 0;
+ }
+
+ if (options & PHP_STREAM_MKDIR_RECURSIVE) {
+ /* Just attempt to make every directory, some will fail, but we only care about the last success/failure */
+ char *p = resource->path;
+ while ((p = strchr(p + 1, '/'))) {
+ libssh2_sftp_mkdir_ex(sftp, resource->path, p - resource->path, mode);
+ }
+ }
+
+ result = libssh2_sftp_mkdir(sftp, resource->path, mode);
+ php_url_free(resource);
+
+ zend_list_delete(sftp_rsrcid);
+
+ /* libssh2 uses 0 for success and the streams API uses 0 for failure, so invert */
+ return (result == 0) ? -1 : 0;
+}
+/* }}} */
+
+/* {{{ php_ssh2_sftp_rmdir
+ */
+static int php_ssh2_sftp_rmdir(php_stream_wrapper *wrapper, char *url, int options, php_stream_context *context TSRMLS_DC)
+{
+ LIBSSH2_SESSION *session = NULL;
+ LIBSSH2_SFTP *sftp = NULL;
+ int resource_id = 0, sftp_rsrcid = 0;
+ php_url *resource;
+ int result;
+
+ resource = php_ssh2_fopen_wraper_parse_path(url, "sftp", context, &session, &resource_id, &sftp, &sftp_rsrcid TSRMLS_CC);
+ if (!resource || !session || !sftp || !resource->path) {
+ if (resource) {
+ php_url_free(resource);
+ }
+ return 0;
+ }
+
+ result = libssh2_sftp_rmdir(sftp, resource->path);
+ php_url_free(resource);
+
+ zend_list_delete(sftp_rsrcid);
+
+ /* libssh2 uses 0 for success and the streams API uses 0 for failure, so invert */
+ return (result == 0) ? -1 : 0;
+}
+/* }}} */
+#endif
+
+static php_stream_wrapper_ops php_ssh2_sftp_wrapper_ops = {
+ php_ssh2_sftp_stream_opener,
+ NULL, /* close */
+ NULL, /* stat */
+#ifdef ZEND_ENGINE_2
+ php_ssh2_sftp_urlstat,
+#else
+ NULL, /* url_stat isn't actually functional prior to PHP5 */
+#endif
+ php_ssh2_sftp_dirstream_opener,
+ PHP_SSH2_SFTP_WRAPPER_NAME,
+#ifdef ZEND_ENGINE_2
+ php_ssh2_sftp_unlink,
+ php_ssh2_sftp_rename,
+ php_ssh2_sftp_mkdir,
+ php_ssh2_sftp_rmdir,
+#endif
+};
+
+php_stream_wrapper php_ssh2_sftp_wrapper = {
+ &php_ssh2_sftp_wrapper_ops,
+ NULL,
+ 1,
+ 0,
+ NULL,
+};
+
+/* *****************
+ * Userspace API *
+ ***************** */
+
+
+/* {{{ proto resource ssh2_sftp(resource session)
+ * Request the SFTP subsystem from an already connected SSH2 server
+ */
+PHP_FUNCTION(ssh2_sftp)
+{
+ LIBSSH2_SESSION *session;
+ LIBSSH2_SFTP *sftp;
+ php_ssh2_sftp_data *data;
+ zval *zsession;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zsession) == FAILURE) {
+ RETURN_FALSE;
+ }
+
+ ZEND_FETCH_RESOURCE(session, LIBSSH2_SESSION*, &zsession, -1, PHP_SSH2_SESSION_RES_NAME, le_ssh2_session);
+
+ sftp = libssh2_sftp_init(session);
+ if (!sftp) {
+ char *sess_err = "Unknown";
+
+ libssh2_session_last_error(session, &sess_err, NULL, 0);
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to startup SFTP subsystem: %s", sess_err);
+ RETURN_FALSE;
+ }
+
+ data = emalloc(sizeof(php_ssh2_sftp_data));
+ data->session = session;
+ data->sftp = sftp;
+ data->session_rsrcid = Z_LVAL_P(zsession);
+ zend_list_addref(Z_LVAL_P(zsession));
+
+ ZEND_REGISTER_RESOURCE(return_value, data, le_ssh2_sftp);
+}
+/* }}} */
+
+/* Much of the stuff below can be done via wrapper ops as of PHP5, but is included here for PHP 4.3 users */
+
+/* {{{ proto bool ssh2_sftp_rename(resource sftp, string from, string to)
+ */
+PHP_FUNCTION(ssh2_sftp_rename)
+{
+ php_ssh2_sftp_data *data;
+ zval *zsftp;
+ char *src, *dst;
+ int src_len, dst_len;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rss", &zsftp, &src, &src_len, &dst, &dst_len) == FAILURE) {
+ RETURN_FALSE;
+ }
+
+ ZEND_FETCH_RESOURCE(data, php_ssh2_sftp_data*, &zsftp, -1, PHP_SSH2_SFTP_RES_NAME, le_ssh2_sftp);
+
+ RETURN_BOOL(!libssh2_sftp_rename_ex(data->sftp, src, src_len, dst, dst_len,
+ LIBSSH2_SFTP_RENAME_OVERWRITE | LIBSSH2_SFTP_RENAME_ATOMIC | LIBSSH2_SFTP_RENAME_NATIVE));
+}
+/* }}} */
+
+/* {{{ proto bool ssh2_sftp_unlink(resource sftp, string filename)
+ */
+PHP_FUNCTION(ssh2_sftp_unlink)
+{
+ php_ssh2_sftp_data *data;
+ zval *zsftp;
+ char *filename;
+ int filename_len;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &zsftp, &filename, &filename_len) == FAILURE) {
+ RETURN_FALSE;
+ }
+
+ ZEND_FETCH_RESOURCE(data, php_ssh2_sftp_data*, &zsftp, -1, PHP_SSH2_SFTP_RES_NAME, le_ssh2_sftp);
+
+ RETURN_BOOL(!libssh2_sftp_unlink_ex(data->sftp, filename, filename_len));
+}
+/* }}} */
+
+/* {{{ proto bool ssh2_sftp_mkdir(resource sftp, string filename[, int mode[, int recursive]])
+ */
+PHP_FUNCTION(ssh2_sftp_mkdir)
+{
+ php_ssh2_sftp_data *data;
+ zval *zsftp;
+ char *filename;
+ int filename_len;
+ long mode = 0777;
+ zend_bool recursive = 0;
+ char *p;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs|lb", &zsftp, &filename, &filename_len, &mode, &recursive) == FAILURE) {
+ RETURN_FALSE;
+ }
+
+ if (filename_len < 1) {
+ RETURN_FALSE;
+ }
+
+ ZEND_FETCH_RESOURCE(data, php_ssh2_sftp_data*, &zsftp, -1, PHP_SSH2_SFTP_RES_NAME, le_ssh2_sftp);
+
+ if (recursive) {
+ /* Just attempt to make every directory, some will fail, but we only care about the last success/failure */
+ p = filename;
+ while ((p = strchr(p + 1, '/'))) {
+ if ((p - filename) + 1 == filename_len) {
+ break;
+ }
+ libssh2_sftp_mkdir_ex(data->sftp, filename, p - filename, mode);
+ }
+ }
+
+
+ RETURN_BOOL(!libssh2_sftp_mkdir_ex(data->sftp, filename, filename_len, mode));
+}
+/* }}} */
+
+/* {{{ proto bool ssh2_sftp_rmdir(resource sftp, string filename)
+ */
+PHP_FUNCTION(ssh2_sftp_rmdir)
+{
+ php_ssh2_sftp_data *data;
+ zval *zsftp;
+ char *filename;
+ int filename_len;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &zsftp, &filename, &filename_len) == FAILURE) {
+ RETURN_FALSE;
+ }
+
+ ZEND_FETCH_RESOURCE(data, php_ssh2_sftp_data*, &zsftp, -1, PHP_SSH2_SFTP_RES_NAME, le_ssh2_sftp);
+
+ RETURN_BOOL(!libssh2_sftp_rmdir_ex(data->sftp, filename, filename_len));
+}
+/* }}} */
+
+/* {{{ php_ssh2_sftp_stat_func
+ * In PHP4.3 this is the only way to request stat into, in PHP >= 5 you can use the fopen wrapper approach
+ * Both methods will return identical structures
+ * (well, the other one will include other values set to 0 but they don't count)
+ */
+static void php_ssh2_sftp_stat_func(INTERNAL_FUNCTION_PARAMETERS, int stat_type)
+{
+ php_ssh2_sftp_data *data;
+ LIBSSH2_SFTP_ATTRIBUTES attrs;
+ zval *zsftp;
+ char *path;
+ int path_len;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &zsftp, &path, &path_len) == FAILURE) {
+ RETURN_FALSE;
+ }
+
+ ZEND_FETCH_RESOURCE(data, php_ssh2_sftp_data*, &zsftp, -1, PHP_SSH2_SFTP_RES_NAME, le_ssh2_sftp);
+
+ if (libssh2_sftp_stat_ex(data->sftp, path, path_len, stat_type, &attrs)) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to stat remote file");
+ RETURN_FALSE;
+ }
+
+ array_init(return_value);
+
+ if (attrs.flags & LIBSSH2_SFTP_ATTR_SIZE) {
+ add_index_long(return_value, 7, attrs.filesize);
+ add_assoc_long(return_value, "size", attrs.filesize);
+ }
+ if (attrs.flags & LIBSSH2_SFTP_ATTR_UIDGID) {
+ add_index_long(return_value, 4, attrs.uid);
+ add_assoc_long(return_value, "uid", attrs.uid);
+
+ add_index_long(return_value, 5, attrs.gid);
+ add_assoc_long(return_value, "gid", attrs.gid);
+ }
+ if (attrs.flags & LIBSSH2_SFTP_ATTR_PERMISSIONS) {
+ add_index_long(return_value, 2, attrs.permissions);
+ add_assoc_long(return_value, "mode", attrs.permissions);
+ }
+ if (attrs.flags & LIBSSH2_SFTP_ATTR_ACMODTIME) {
+ add_index_long(return_value, 8, attrs.atime);
+ add_assoc_long(return_value, "atime", attrs.atime);
+
+ add_index_long(return_value, 9, attrs.mtime);
+ add_assoc_long(return_value, "mtime", attrs.mtime);
+ }
+}
+/* }}} */
+
+/* {{{ proto array ssh2_sftp_stat(resource sftp, string path)
+ */
+PHP_FUNCTION(ssh2_sftp_stat)
+{
+ php_ssh2_sftp_stat_func(INTERNAL_FUNCTION_PARAM_PASSTHRU, LIBSSH2_SFTP_STAT);
+}
+/* }}} */
+
+/* {{{ proto array ssh2_sftp_lstat(resource sftp, string path)
+ */
+PHP_FUNCTION(ssh2_sftp_lstat)
+{
+ php_ssh2_sftp_stat_func(INTERNAL_FUNCTION_PARAM_PASSTHRU, LIBSSH2_SFTP_LSTAT);
+}
+/* }}} */
+
+/* {{{ proto bool ssh2_sftp_symlink(resource sftp, string target, string link)
+ */
+PHP_FUNCTION(ssh2_sftp_symlink)
+{
+ php_ssh2_sftp_data *data;
+ zval *zsftp;
+ char *targ, *link;
+ int targ_len, link_len;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rss", &zsftp, &targ, &targ_len, &link, &link_len) == FAILURE) {
+ RETURN_FALSE;
+ }
+
+ ZEND_FETCH_RESOURCE(data, php_ssh2_sftp_data*, &zsftp, -1, PHP_SSH2_SFTP_RES_NAME, le_ssh2_sftp);
+
+ RETURN_BOOL(!libssh2_sftp_symlink_ex(data->sftp, targ, targ_len, link, link_len, LIBSSH2_SFTP_SYMLINK));
+}
+/* }}} */
+
+/* {{{ proto string ssh2_sftp_readlink(resource sftp, string link)
+ */
+PHP_FUNCTION(ssh2_sftp_readlink)
+{
+ php_ssh2_sftp_data *data;
+ zval *zsftp;
+ char *link;
+ int targ_len = 0, link_len;
+ char targ[8192];
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &zsftp, &link, &link_len) == FAILURE) {
+ RETURN_FALSE;
+ }
+
+ ZEND_FETCH_RESOURCE(data, php_ssh2_sftp_data*, &zsftp, -1, PHP_SSH2_SFTP_RES_NAME, le_ssh2_sftp);
+
+ if ((targ_len = libssh2_sftp_symlink_ex(data->sftp, link, link_len, targ, 8192, LIBSSH2_SFTP_READLINK)) < 0) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to read link '%s'", link);
+ RETURN_FALSE;
+ }
+
+ RETURN_STRINGL(targ, targ_len, 1);
+}
+/* }}} */
+
+/* {{{ proto string ssh2_sftp_realpath(resource sftp, string filename)
+ */
+PHP_FUNCTION(ssh2_sftp_realpath)
+{
+ php_ssh2_sftp_data *data;
+ zval *zsftp;
+ char *link;
+ int targ_len = 0, link_len;
+ char targ[8192];
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &zsftp, &link, &link_len) == FAILURE) {
+ RETURN_FALSE;
+ }
+
+ ZEND_FETCH_RESOURCE(data, php_ssh2_sftp_data*, &zsftp, -1, PHP_SSH2_SFTP_RES_NAME, le_ssh2_sftp);
+
+ if ((targ_len = libssh2_sftp_symlink_ex(data->sftp, link, link_len, targ, 8192, LIBSSH2_SFTP_REALPATH)) < 0) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to resolve realpath for '%s'", link);
+ RETURN_FALSE;
+ }
+
+ RETURN_STRINGL(targ, targ_len, 1);
+}
+/* }}} */
+
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * indent-tabs-mode: t
+ * End:
+ */
+
|