@@ -974,14 +974,84 @@ ftp_get(ftpbuf_t *ftp, php_stream *outstream, const char *path, const size_t pat
974
974
}
975
975
/* }}} */
976
976
977
+ static zend_result ftp_send_stream_to_data_socket (ftpbuf_t * ftp , databuf_t * data , php_stream * instream , ftptype_t type , bool send_once_and_return )
978
+ {
979
+ if (type == FTPTYPE_ASCII ) {
980
+ /* Change (and later restore) flags to make sure php_stream_get_line() searches '\n'. */
981
+ const uint32_t flags_mask = PHP_STREAM_FLAG_EOL_UNIX | PHP_STREAM_FLAG_DETECT_EOL | PHP_STREAM_FLAG_EOL_MAC ;
982
+ uint32_t old_flags = instream -> flags & flags_mask ;
983
+ instream -> flags = (instream -> flags & ~flags_mask ) | PHP_STREAM_FLAG_EOL_UNIX ;
984
+
985
+ char * ptr = data -> buf ;
986
+ const char * end = data -> buf + FTP_BUFSIZE ;
987
+ while (!php_stream_eof (instream )) {
988
+ size_t line_length ;
989
+ if (!php_stream_get_line (instream , ptr , end - ptr , & line_length )) {
990
+ break ;
991
+ }
992
+
993
+ ZEND_ASSERT (line_length != 0 );
994
+
995
+ ptr += line_length - 1 ;
996
+ /* Replace \n with \r\n */
997
+ if (* ptr == '\n' ) {
998
+ * ptr = '\r' ;
999
+ /* The streams layer always puts a \0 byte at the end of a line,
1000
+ * so there is always place to add an extra byte. */
1001
+ * ++ ptr = '\n' ;
1002
+ }
1003
+
1004
+ ptr ++ ;
1005
+
1006
+ /* If less than 2 bytes remain, either the buffer is completely full or there is a single byte left to put a '\0'
1007
+ * which isn't really useful, in this case send and reset the buffer. */
1008
+ if (end - ptr < 2 ) {
1009
+ size_t send_size = FTP_BUFSIZE - (end - ptr );
1010
+ if (UNEXPECTED (my_send (ftp , data -> fd , data -> buf , send_size ) != send_size )) {
1011
+ instream -> flags = (instream -> flags & ~flags_mask ) | old_flags ;
1012
+ return FAILURE ;
1013
+ }
1014
+ ptr = data -> buf ;
1015
+ if (send_once_and_return ) {
1016
+ break ;
1017
+ }
1018
+ }
1019
+ }
1020
+
1021
+ instream -> flags = (instream -> flags & ~flags_mask ) | old_flags ;
1022
+
1023
+ if (end - ptr < FTP_BUFSIZE ) {
1024
+ size_t send_size = FTP_BUFSIZE - (end - ptr );
1025
+ if (UNEXPECTED (my_send (ftp , data -> fd , data -> buf , send_size ) != send_size )) {
1026
+ return FAILURE ;
1027
+ }
1028
+ }
1029
+ } else {
1030
+ while (!php_stream_eof (instream )) {
1031
+ ssize_t size = php_stream_read (instream , data -> buf , FTP_BUFSIZE );
1032
+ if (size == 0 ) {
1033
+ break ;
1034
+ }
1035
+ if (UNEXPECTED (size < 0 )) {
1036
+ return FAILURE ;
1037
+ }
1038
+ if (UNEXPECTED (my_send (ftp , data -> fd , data -> buf , size ) != size )) {
1039
+ return FAILURE ;
1040
+ }
1041
+ if (send_once_and_return ) {
1042
+ break ;
1043
+ }
1044
+ }
1045
+ }
1046
+
1047
+ return SUCCESS ;
1048
+ }
1049
+
977
1050
/* {{{ ftp_put */
978
1051
int
979
1052
ftp_put (ftpbuf_t * ftp , const char * path , const size_t path_len , php_stream * instream , ftptype_t type , zend_long startpos )
980
1053
{
981
1054
databuf_t * data = NULL ;
982
- zend_long size ;
983
- char * ptr ;
984
- int ch ;
985
1055
char arg [MAX_LENGTH_OF_LONG ];
986
1056
987
1057
if (ftp == NULL ) {
@@ -1018,30 +1088,10 @@ ftp_put(ftpbuf_t *ftp, const char *path, const size_t path_len, php_stream *inst
1018
1088
goto bail ;
1019
1089
}
1020
1090
1021
- size = 0 ;
1022
- ptr = data -> buf ;
1023
- while (!php_stream_eof (instream ) && (ch = php_stream_getc (instream ))!= EOF ) {
1024
- /* flush if necessary */
1025
- if (FTP_BUFSIZE - size < 2 ) {
1026
- if (my_send (ftp , data -> fd , data -> buf , size ) != size ) {
1027
- goto bail ;
1028
- }
1029
- ptr = data -> buf ;
1030
- size = 0 ;
1031
- }
1032
-
1033
- if (ch == '\n' && type == FTPTYPE_ASCII ) {
1034
- * ptr ++ = '\r' ;
1035
- size ++ ;
1036
- }
1037
-
1038
- * ptr ++ = ch ;
1039
- size ++ ;
1040
- }
1041
-
1042
- if (size && my_send (ftp , data -> fd , data -> buf , size ) != size ) {
1091
+ if (ftp_send_stream_to_data_socket (ftp , data , instream , type , false) != SUCCESS ) {
1043
1092
goto bail ;
1044
1093
}
1094
+
1045
1095
data_close (ftp );
1046
1096
1047
1097
if (!ftp_getresp (ftp ) || (ftp -> resp != 226 && ftp -> resp != 250 && ftp -> resp != 200 )) {
@@ -1060,9 +1110,6 @@ int
1060
1110
ftp_append (ftpbuf_t * ftp , const char * path , const size_t path_len , php_stream * instream , ftptype_t type )
1061
1111
{
1062
1112
databuf_t * data = NULL ;
1063
- zend_long size ;
1064
- char * ptr ;
1065
- int ch ;
1066
1113
1067
1114
if (ftp == NULL ) {
1068
1115
return 0 ;
@@ -1085,30 +1132,10 @@ ftp_append(ftpbuf_t *ftp, const char *path, const size_t path_len, php_stream *i
1085
1132
goto bail ;
1086
1133
}
1087
1134
1088
- size = 0 ;
1089
- ptr = data -> buf ;
1090
- while (!php_stream_eof (instream ) && (ch = php_stream_getc (instream ))!= EOF ) {
1091
- /* flush if necessary */
1092
- if (FTP_BUFSIZE - size < 2 ) {
1093
- if (my_send (ftp , data -> fd , data -> buf , size ) != size ) {
1094
- goto bail ;
1095
- }
1096
- ptr = data -> buf ;
1097
- size = 0 ;
1098
- }
1099
-
1100
- if (ch == '\n' && type == FTPTYPE_ASCII ) {
1101
- * ptr ++ = '\r' ;
1102
- size ++ ;
1103
- }
1104
-
1105
- * ptr ++ = ch ;
1106
- size ++ ;
1107
- }
1108
-
1109
- if (size && my_send (ftp , data -> fd , data -> buf , size ) != size ) {
1135
+ if (ftp_send_stream_to_data_socket (ftp , data , instream , type , false) != SUCCESS ) {
1110
1136
goto bail ;
1111
1137
}
1138
+
1112
1139
data_close (ftp );
1113
1140
1114
1141
if (!ftp_getresp (ftp ) || (ftp -> resp != 226 && ftp -> resp != 250 && ftp -> resp != 200 )) {
@@ -2256,39 +2283,19 @@ ftp_nb_put(ftpbuf_t *ftp, const char *path, const size_t path_len, php_stream *i
2256
2283
int
2257
2284
ftp_nb_continue_write (ftpbuf_t * ftp )
2258
2285
{
2259
- long size ;
2260
- char * ptr ;
2261
- int ch ;
2262
-
2263
2286
/* check if we can write more data */
2264
2287
if (!data_writeable (ftp , ftp -> data -> fd )) {
2265
2288
return PHP_FTP_MOREDATA ;
2266
2289
}
2267
2290
2268
- size = 0 ;
2269
- ptr = ftp -> data -> buf ;
2270
- while (!php_stream_eof (ftp -> stream ) && (ch = php_stream_getc (ftp -> stream )) != EOF ) {
2271
-
2272
- if (ch == '\n' && ftp -> type == FTPTYPE_ASCII ) {
2273
- * ptr ++ = '\r' ;
2274
- size ++ ;
2275
- }
2276
-
2277
- * ptr ++ = ch ;
2278
- size ++ ;
2279
-
2280
- /* flush if necessary */
2281
- if (FTP_BUFSIZE - size < 2 ) {
2282
- if (my_send (ftp , ftp -> data -> fd , ftp -> data -> buf , size ) != size ) {
2283
- goto bail ;
2284
- }
2285
- return PHP_FTP_MOREDATA ;
2286
- }
2291
+ if (ftp_send_stream_to_data_socket (ftp , ftp -> data , ftp -> stream , ftp -> type , true) != SUCCESS ) {
2292
+ goto bail ;
2287
2293
}
2288
2294
2289
- if (size && my_send (ftp , ftp -> data -> fd , ftp -> data -> buf , size ) != size ) {
2290
- goto bail ;
2295
+ if (! php_stream_eof (ftp -> stream ) ) {
2296
+ return PHP_FTP_MOREDATA ;
2291
2297
}
2298
+
2292
2299
data_close (ftp );
2293
2300
2294
2301
if (!ftp_getresp (ftp ) || (ftp -> resp != 226 && ftp -> resp != 250 )) {
0 commit comments