34#define O_RDONLY _O_RDONLY
43#ifdef HAVE_SYS_SOCKET_H
44#include <sys/socket.h>
50#include <netinet/in.h>
52#ifdef HAVE_ARPA_INET_H
57#if defined(PHP_WIN32) || defined(__riscos__)
67#define FTPS_ENCRYPT_DATA 1
68#define GET_FTP_RESULT(stream) get_ftp_result((stream), tmp_line, sizeof(tmp_line))
77static inline int get_ftp_result(
php_stream *stream,
char *
buffer,
size_t buffer_size)
81 !(isdigit((
int)
buffer[0]) && isdigit((
int)
buffer[1]) &&
127 php_url **presource,
int *puse_ssl,
int *puse_ssl_on_data)
131 int result, use_ssl, use_ssl_on_data = 0;
138 if (resource && presource) {
139 *presource = resource;
147 if (resource->
port == 0)
153 if (stream ==
NULL) {
155 goto connect_errexit;
165 goto connect_errexit;
183 goto connect_errexit;
204 goto connect_errexit;
219 use_ssl_on_data = (
result >= 200 &&
result<=299) || reuseid;
228#define PHP_FTP_CNTRL_CHK(val, val_len, err_msg) { \
229 unsigned char *s = (unsigned char *) val, *e = (unsigned char *) s + val_len; \
232 php_stream_wrapper_log_error(wrapper, options, err_msg, val); \
233 goto connect_errexit; \
266 if (
FG(from_address)) {
283 goto connect_errexit;
289 if (puse_ssl_on_data) {
290 *puse_ssl_on_data = use_ssl_on_data;
296 *presource = resource;
313static unsigned short php_fopen_do_pasv(
php_stream *stream,
char *ip,
size_t ip_size,
char **phoststart)
317 unsigned short portno;
318 char *tpath, *ttpath, *hoststart=
NULL;
340 for (tpath += 4; *tpath && !isdigit((
int) *tpath); tpath++);
346 for (i = 0; i < 4; i++) {
347 for (; isdigit((
int) *tpath); tpath++);
355 memcpy(ip, hoststart, ip_size);
356 ip[ip_size-1] =
'\0';
360 portno = (
unsigned short) strtoul(tpath, &ttpath, 10) * 256;
361 if (ttpath ==
NULL) {
371 portno += (
unsigned short) strtoul(tpath, &ttpath, 10);
375 for (i = 0, tpath = tmp_line + 4; *tpath; tpath++) {
386 portno = (
unsigned short) strtoul(tpath + 1, &ttpath, 10);
389 if (ttpath ==
NULL) {
395 *phoststart = hoststart;
409 char ip[
sizeof(
"123.123.123.123")];
410 unsigned short portno;
411 char *hoststart =
NULL;
412 int result = 0, use_ssl, use_ssl_on_data=0;
414 size_t file_size = 0;
416 bool allow_overwrite = 0;
417 int8_t read_write = 0;
446 if (read_write == 1) {
456 stream = php_ftp_fopen_connect(wrapper, path,
mode,
options, opened_path,
context, &reuseid, &resource, &use_ssl, &use_ssl_on_data);
472 if (read_write == 1) {
482 sizestr =
strchr(tmp_line,
' ');
485 file_size = atoi(sizestr);
488 }
else if (read_write == 2) {
494 if (allow_overwrite) {
511 portno = php_fopen_do_pasv(stream, ip,
sizeof(ip), &hoststart);
518 if (read_write == 1) {
533 memcpy(tmp_line,
"RETR",
sizeof(
"RETR"));
534 }
else if (read_write == 2) {
536 memcpy(tmp_line,
"STOR",
sizeof(
"STOR"));
539 memcpy(tmp_line,
"APPE",
sizeof(
"APPE"));
544 if (hoststart ==
NULL) {
547 transport_len = (int)
spprintf(&transport, 0,
"tcp://%s:%d", hoststart, portno);
550 if (datastream ==
NULL) {
580 datastream->wrapperthis = stream;
593 if (tmp_line[0] !=
'\0')
598 zend_string_release(error_message);
630 ent->
d_name[tmp_len - 1] =
'\0';
635 while (tmp_len > 0 &&
636 (ent->
d_name[tmp_len - 1] ==
'\n' || ent->
d_name[tmp_len - 1] ==
'\r' ||
637 ent->
d_name[tmp_len - 1] ==
'\t' || ent->
d_name[tmp_len - 1] ==
' ')) {
638 ent->
d_name[--tmp_len] =
'\0';
646static int php_ftp_dirstream_close(
php_stream *stream,
int close_handle)
651 if (
data->controlstream) {
670 php_ftp_dirstream_read,
671 php_ftp_dirstream_close,
687 int result = 0, use_ssl, use_ssl_on_data = 0;
688 char *hoststart =
NULL, tmp_line[512];
689 char ip[
sizeof(
"123.123.123.123")];
690 unsigned short portno;
694 stream = php_ftp_fopen_connect(wrapper, path,
mode,
options, opened_path,
context, &reuseid, &resource, &use_ssl, &use_ssl_on_data);
696 goto opendir_errexit;
703 goto opendir_errexit;
709 portno = php_fopen_do_pasv(stream, ip,
sizeof(ip), &hoststart);
712 goto opendir_errexit;
716 if (hoststart ==
NULL) {
721 if (datastream ==
NULL) {
722 goto opendir_errexit;
734 goto opendir_errexit;
745 goto opendir_errexit;
750 dirsdata =
emalloc(
sizeof *dirsdata);
765 if (tmp_line[0] !=
'\0') {
788 ssb->
sb.st_mode = 0644;
792 ssb->
sb.st_mode |= S_IFREG;
794 ssb->
sb.st_mode |= S_IFDIR | S_IXUSR | S_IXGRP | S_IXOTH;
811 if (ssb->
sb.st_mode & S_IFDIR) {
817 ssb->
sb.st_size = atoi(tmp_line + 4);
823 char *
p = tmp_line + 4;
825 struct tm tm, tmbuf, *gmt;
828 while ((
size_t)(
p - tmp_line) <
sizeof(tmp_line) && !isdigit(*
p)) {
832 if ((
size_t)(
p - tmp_line) >
sizeof(tmp_line)) {
836 n =
sscanf(
p,
"%4d%2d%2d%2d%2d%2d", &tm.tm_year, &tm.tm_mon, &tm.tm_mday, &tm.tm_hour, &tm.tm_min, &tm.tm_sec);
854 tm.tm_sec += (long)(stamp -
mktime(gmt));
855 tm.tm_isdst = gmt->tm_isdst;
861 ssb->
sb.st_mtime = -1;
868 ssb->
sb.st_atime = -1;
869 ssb->
sb.st_ctime = -1;
871 ssb->
sb.st_nlink = 1;
872 ssb->
sb.st_rdev = -1;
873#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
874 ssb->
sb.st_blksize = 4096;
875#ifdef HAVE_STRUCT_STAT_ST_BLOCKS
876 ssb->
sb.st_blocks = (int)((4095 + ssb->
sb.st_size) / ssb->
sb.st_blksize);
956 if (!resource_from ||
959 !resource_to->scheme ||
960 !zend_string_equals(resource_from->
scheme, resource_to->scheme) ||
961 !resource_from->
host ||
962 !resource_to->host ||
963 !zend_string_equals(resource_from->
host, resource_to->host) ||
964 (resource_from->
port != resource_to->port &&
965 resource_from->
port * resource_to->port != 0 &&
966 resource_from->
port + resource_to->port != 21) ||
967 !resource_from->
path ||
968 !resource_to->path) {
1008 if (resource_from) {
1074 if (*
p ==
'\0' && *(
p + 1) !=
'\0') {
1164 php_stream_ftp_stream_close,
1165 php_stream_ftp_stream_stat,
1166 php_stream_ftp_url_stat,
1167 php_stream_ftp_opendir,
1169 php_stream_ftp_unlink,
1170 php_stream_ftp_rename,
1171 php_stream_ftp_mkdir,
1172 php_stream_ftp_rmdir,
sscanf(string $string, string $format, mixed &... $vars)
strrchr(string $haystack, string $needle, bool $before_needle=false)
strpbrk(string $string, string $characters)
count(Countable|array $value, int $mode=COUNT_NORMAL)
basename(string $path, string $suffix="")
strchr(string $haystack, string $needle, bool $before_needle=false)
zend_ffi_ctype_name_buf buf
#define GET_FTP_RESULT(stream)
PHPAPI const php_stream_wrapper php_stream_ftp_wrapper
struct _php_ftp_dirstream_data php_ftp_dirstream_data
#define PHP_FTP_CNTRL_CHK(val, val_len, err_msg)
php_stream * php_stream_url_wrap_ftp(php_stream_wrapper *wrapper, const char *path, const char *mode, int options, zend_string **opened_path, php_stream_context *context STREAMS_DC)
#define pass(a, b, c, mul)
php_stream * php_stream_url_wrap_http(php_stream_wrapper *wrapper, const char *path, const char *mode, int options, zend_string **opened_path, php_stream_context *context STREAMS_DC)
PHPAPI ZEND_COLD void php_error_docref(const char *docref, int type, const char *format,...)
mktime(int $hour, ?int $minute=null, ?int $second=null, ?int $month=null, ?int $day=null, ?int $year=null)
PHP_JSON_API size_t int options
#define php_stream_sock_open_host(host, port, socktype, timeout, persistent)
PHPAPI struct tm * php_gmtime_r(const time_t *const timep, struct tm *p_tm)
#define php_stream_notify_file_size(context, file_size, xmsg, xcode)
PHPAPI php_stream_context * php_stream_context_set(php_stream *stream, php_stream_context *context)
#define php_stream_notify_info(context, code, xmsg, xcode)
#define PHP_STREAM_NOTIFY_AUTH_REQUIRED
#define PHP_STREAM_NOTIFY_FAILURE
#define php_stream_notify_progress_init(context, sofar, bmax)
PHPAPI zval * php_stream_context_get_option(php_stream_context *context, const char *wrappername, const char *optionname)
#define PHP_STREAM_NOTIFY_AUTH_RESULT
#define PHP_STREAM_NOTIFY_CONNECT
#define php_stream_notify_error(context, code, xmsg, xcode)
#define php_stream_xport_create(name, namelen, options, flags, persistent_id, timeout, context, estr, ecode)
PHPAPI int php_stream_xport_crypto_enable(php_stream *stream, int activate)
@ STREAM_CRYPTO_METHOD_SSLv23_CLIENT
#define STREAM_XPORT_CONNECT
PHPAPI int php_stream_xport_crypto_setup(php_stream *stream, php_stream_xport_crypt_method_t crypto_method, php_stream *session_stream)
#define STREAM_XPORT_CLIENT
struct _php_stream_wrapper_ops php_stream_wrapper_ops
struct _php_stream php_stream
struct _php_stream_context php_stream_context
struct _php_stream_dirent php_stream_dirent
#define php_stream_gets(stream, buf, maxlen)
#define php_stream_get_line(stream, buf, maxlen, retlen)
#define PHP_STREAM_MKDIR_RECURSIVE
#define php_stream_eof(stream)
#define php_stream_printf
#define php_stream_close(stream)
struct _php_stream_ops php_stream_ops
#define php_stream_write_string(stream, str)
struct _php_stream_wrapper php_stream_wrapper
#define php_stream_alloc(ops, thisptr, persistent_id, mode)
struct _php_stream_statbuf php_stream_statbuf
PHPAPI void php_stream_wrapper_log_error(const php_stream_wrapper *wrapper, int options, const char *fmt,...) PHP_ATTRIBUTE_FORMAT(printf
PHPAPI zend_string * php_basename(const char *s, size_t len, const char *suffix, size_t sufflen)
php_stream * controlstream
PHPAPI php_url * php_url_parse(char const *str)
PHPAPI size_t php_raw_url_decode(char *str, size_t len)
PHPAPI void php_url_free(php_url *theurl)
#define estrndup(s, length)
zend_string_release_ex(func->internal_function.function_name, 0)
struct _zend_string zend_string
ZEND_API bool ZEND_FASTCALL zend_is_true(const zval *op)