Skip to content

Commit cae2717

Browse files
author
Hartmut Holzgraefe
committed
fopen wrappers cleanup
- comfiguration is now done by an ini parameter instead of a compile time option - the implementations of the three standard wrappers now live in seperate files in ext/standard - the compiler is happy again, no more warnings
1 parent e07e515 commit cae2717

15 files changed

+718
-496
lines changed

configure.in

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -543,16 +543,6 @@ else
543543
AC_DEFINE(DEFAULT_SHORT_OPEN_TAG,0,[ ])
544544
fi
545545
546-
PHP_ARG_ENABLE(url-fopen-wrapper,whether to enable the URL-aware fopen wrapper,
547-
[ --disable-url-fopen-wrapper
548-
Disable the URL-aware fopen wrapper that allows
549-
accessing files via http or ftp.], yes)
550-
551-
if test "$PHP_URL_FOPEN_WRAPPER" = "yes"; then
552-
AC_DEFINE(PHP_URL_FOPEN, 1, [ ])
553-
else
554-
AC_DEFINE(PHP_URL_FOPEN, 0, [ ])
555-
fi
556546
557547
PHP_ARG_ENABLE(pic,whether to enable PIC for shared objects,
558548
[ --disable-pic Disable PIC for shared objects], yes)

ext/standard/Makefile.in

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@ LTLIBRARY_SOURCES=\
77
link.c mail.c math.c md5.c metaphone.c microtime.c pack.c pageinfo.c \
88
parsedate.c quot_print.c rand.c reg.c soundex.c string.c scanf.c \
99
syslog.c type.c uniqid.c url.c url_scanner.c var.c output.c assert.c \
10-
strnatcmp.c levenshtein.c incomplete_class.c url_scanner_ex.c
10+
strnatcmp.c levenshtein.c incomplete_class.c url_scanner_ex.c \
11+
ftp_fopen_wrapper.c http_fopen_wrapper.c php_fopen_wrapper.c
1112

1213
include $(top_srcdir)/build/dynlib.mk
1314

ext/standard/basic_functions.c

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,8 @@ int basic_globals_id;
6262
php_basic_globals basic_globals;
6363
#endif
6464

65+
#include "php_fopen_wrappers.h"
66+
6567
static unsigned char second_and_third_args_force_ref[] = { 3, BYREF_NONE, BYREF_FORCE, BYREF_FORCE };
6668
static unsigned char second_args_force_ref[] = { 2, BYREF_NONE, BYREF_FORCE };
6769
static unsigned char third_argument_force_ref[] = { 3, BYREF_NONE, BYREF_NONE, BYREF_FORCE };
@@ -669,6 +671,8 @@ static void basic_globals_dtor(BLS_D)
669671

670672
PHP_MINIT_FUNCTION(basic)
671673
{
674+
PLS_FETCH();
675+
672676
#ifdef ZTS
673677
basic_globals_id = ts_allocate_id(sizeof(php_basic_globals), (ts_allocate_ctor) basic_globals_ctor, (ts_allocate_dtor) basic_globals_dtor);
674678
#else
@@ -714,6 +718,18 @@ PHP_MINIT_FUNCTION(basic)
714718
PHP_MINIT(array)(INIT_FUNC_ARGS_PASSTHRU);
715719
PHP_MINIT(assert)(INIT_FUNC_ARGS_PASSTHRU);
716720

721+
if(PG(allow_url_fopen)) {
722+
if(FAILURE==php_register_url_wrapper("http",php_fopen_url_wrap_http)) {
723+
return FAILURE;
724+
}
725+
if(FAILURE==php_register_url_wrapper("ftp",php_fopen_url_wrap_ftp)) {
726+
return FAILURE;
727+
}
728+
if(FAILURE==php_register_url_wrapper("php",php_fopen_url_wrap_ftp)) {
729+
return FAILURE;
730+
}
731+
}
732+
717733
return SUCCESS;
718734
}
719735

@@ -736,6 +752,12 @@ PHP_MSHUTDOWN_FUNCTION(basic)
736752
PHP_MSHUTDOWN(array)(SHUTDOWN_FUNC_ARGS_PASSTHRU);
737753
PHP_MSHUTDOWN(assert)(SHUTDOWN_FUNC_ARGS_PASSTHRU);
738754

755+
if(PG(allow_url_fopen)) {
756+
php_unregister_url_wrapper("http");
757+
php_unregister_url_wrapper("ftp");
758+
php_unregister_url_wrapper("php");
759+
}
760+
739761
return SUCCESS;
740762
}
741763

ext/standard/ftp_fopen_wrapper.c

Lines changed: 310 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,310 @@
1+
/*
2+
+----------------------------------------------------------------------+
3+
| PHP version 4.0 |
4+
+----------------------------------------------------------------------+
5+
| Copyright (c) 1997, 1998, 1999, 2000 The PHP Group |
6+
+----------------------------------------------------------------------+
7+
| This source file is subject to version 2.02 of the PHP license, |
8+
| that is bundled with this package in the file LICENSE, and is |
9+
| available at through the world-wide-web at |
10+
| http://www.php.net/license/2_02.txt. |
11+
| If you did not receive a copy of the PHP license and are unable to |
12+
| obtain it through the world-wide-web, please send a note to |
13+
| [email protected] so we can mail you a copy immediately. |
14+
+----------------------------------------------------------------------+
15+
| Authors: Rasmus Lerdorf <[email protected]> |
16+
| Jim Winstead <[email protected]> |
17+
| Hartmut Holzgraefe <[email protected]> |
18+
+----------------------------------------------------------------------+
19+
*/
20+
/* $Id$ */
21+
22+
#include "php.h"
23+
#include "php_globals.h"
24+
25+
#include <stdio.h>
26+
#include <stdlib.h>
27+
#include <errno.h>
28+
#include <sys/types.h>
29+
#include <sys/stat.h>
30+
#include <fcntl.h>
31+
32+
#ifdef PHP_WIN32
33+
#include <windows.h>
34+
#include <winsock.h>
35+
#define O_RDONLY _O_RDONLY
36+
#include "win32/param.h"
37+
#else
38+
#include <sys/param.h>
39+
#endif
40+
41+
#include "php_standard.h"
42+
43+
#include <sys/types.h>
44+
#if HAVE_SYS_SOCKET_H
45+
#include <sys/socket.h>
46+
#endif
47+
48+
#ifdef PHP_WIN32
49+
#include <winsock.h>
50+
#else
51+
#include <netinet/in.h>
52+
#include <netdb.h>
53+
#include <arpa/inet.h>
54+
#endif
55+
56+
#ifdef PHP_WIN32
57+
#undef AF_UNIX
58+
#endif
59+
60+
#if defined(AF_UNIX)
61+
#include <sys/un.h>
62+
#endif
63+
64+
#include "php_fopen_wrappers.h"
65+
66+
static int php_get_ftp_result(int socketd)
67+
{
68+
char tmp_line[513];
69+
70+
while (SOCK_FGETS(tmp_line, sizeof(tmp_line)-1, socketd) &&
71+
!(isdigit((int) tmp_line[0]) && isdigit((int) tmp_line[1]) &&
72+
isdigit((int) tmp_line[2]) && tmp_line[3] == ' '));
73+
74+
return strtol(tmp_line, NULL, 10);
75+
}
76+
77+
78+
FILE *php_fopen_url_wrap_ftp(char *path, char *mode, int options, int *issock, int *socketd, char **opened_path)
79+
{
80+
FILE *fp=NULL;
81+
php_url *resource=NULL;
82+
char tmp_line[512];
83+
unsigned short portno;
84+
char *scratch;
85+
int result;
86+
int i;
87+
char *tpath, *ttpath;
88+
89+
resource = url_parse((char *) path);
90+
if (resource == NULL) {
91+
php_error(E_WARNING, "Invalid URL specified, %s", path);
92+
*issock = BAD_URL;
93+
return NULL;
94+
} else if (resource->path == NULL) {
95+
php_error(E_WARNING, "No file-path specified");
96+
free_url(resource);
97+
*issock = BAD_URL;
98+
return NULL;
99+
}
100+
/* use port 21 if one wasn't specified */
101+
if (resource->port == 0)
102+
resource->port = 21;
103+
104+
*socketd = php_hostconnect(resource->host, resource->port, SOCK_STREAM, 0);
105+
if (*socketd == -1)
106+
goto errexit;
107+
#if 0
108+
if ((fpc = fdopen(*socketd, "r+")) == NULL) {
109+
free_url(resource);
110+
return NULL;
111+
}
112+
#ifdef HAVE_SETVBUF
113+
if ((setvbuf(fpc, NULL, _IONBF, 0)) != 0) {
114+
free_url(resource);
115+
fclose(fpc);
116+
return NULL;
117+
}
118+
#endif
119+
#endif
120+
121+
/* Start talking to ftp server */
122+
result = php_get_ftp_result(*socketd);
123+
if (result > 299 || result < 200)
124+
goto errexit;
125+
126+
/* send the user name */
127+
SOCK_WRITE("USER ", *socketd);
128+
if (resource->user != NULL) {
129+
php_raw_url_decode(resource->user, strlen(resource->user));
130+
SOCK_WRITE(resource->user, *socketd);
131+
} else {
132+
SOCK_WRITE("anonymous", *socketd);
133+
}
134+
SOCK_WRITE("\r\n", *socketd);
135+
136+
/* get the response */
137+
result = php_get_ftp_result(*socketd);
138+
139+
/* if a password is required, send it */
140+
if (result >= 300 && result <= 399) {
141+
SOCK_WRITE("PASS ", *socketd);
142+
if (resource->pass != NULL) {
143+
php_raw_url_decode(resource->pass, strlen(resource->pass));
144+
SOCK_WRITE(resource->pass, *socketd);
145+
} else {
146+
/* if the user has configured who they are,
147+
send that as the password */
148+
if (cfg_get_string("from", &scratch) == SUCCESS) {
149+
SOCK_WRITE(scratch, *socketd);
150+
} else {
151+
SOCK_WRITE("anonymous", *socketd);
152+
}
153+
}
154+
SOCK_WRITE("\r\n", *socketd);
155+
156+
/* read the response */
157+
result = php_get_ftp_result(*socketd);
158+
}
159+
if (result > 299 || result < 200)
160+
goto errexit;
161+
162+
/* set the connection to be binary */
163+
SOCK_WRITE("TYPE I\r\n", *socketd);
164+
result = php_get_ftp_result(*socketd);
165+
if (result > 299 || result < 200)
166+
goto errexit;
167+
168+
/* find out the size of the file (verifying it exists) */
169+
SOCK_WRITE("SIZE ", *socketd);
170+
SOCK_WRITE(resource->path, *socketd);
171+
SOCK_WRITE("\r\n", *socketd);
172+
173+
/* read the response */
174+
result = php_get_ftp_result(*socketd);
175+
if (mode[0] == 'r') {
176+
/* when reading file, it must exist */
177+
if (result > 299 || result < 200) {
178+
php_error(E_WARNING, "File not found");
179+
free_url(resource);
180+
SOCK_FCLOSE(*socketd);
181+
*socketd = 0;
182+
errno = ENOENT;
183+
return NULL;
184+
}
185+
} else {
186+
/* when writing file, it must NOT exist */
187+
if (result <= 299 && result >= 200) {
188+
php_error(E_WARNING, "File already exists");
189+
free_url(resource);
190+
SOCK_FCLOSE(*socketd);
191+
*socketd = 0;
192+
errno = EEXIST;
193+
return NULL;
194+
}
195+
}
196+
197+
/* set up the passive connection */
198+
199+
/* We try EPSV first, needed for IPv6 and works on some IPv4 servers */
200+
SOCK_WRITE("EPSV\r\n", *socketd);
201+
while (SOCK_FGETS(tmp_line, sizeof(tmp_line)-1, *socketd) &&
202+
!(isdigit((int) tmp_line[0]) && isdigit((int) tmp_line[1]) &&
203+
isdigit((int) tmp_line[2]) && tmp_line[3] == ' '));
204+
205+
/* check if we got a 229 response */
206+
if (strncmp(tmp_line, "229", 3)) {
207+
/* EPSV failed, let's try PASV */
208+
SOCK_WRITE("PASV\r\n", *socketd);
209+
while (SOCK_FGETS(tmp_line, sizeof(tmp_line)-1, *socketd) &&
210+
!(isdigit((int) tmp_line[0]) && isdigit((int) tmp_line[1]) &&
211+
isdigit((int) tmp_line[2]) && tmp_line[3] == ' '));
212+
/* make sure we got a 227 response */
213+
if (strncmp(tmp_line, "227", 3))
214+
goto errexit;
215+
/* parse pasv command (129,80,95,25,13,221) */
216+
tpath = tmp_line;
217+
/* skip over the "227 Some message " part */
218+
for (tpath += 4; *tpath && !isdigit((int) *tpath); tpath++);
219+
if (!*tpath)
220+
goto errexit;
221+
/* skip over the host ip, we just assume it's the same */
222+
for (i = 0; i < 4; i++) {
223+
for (; isdigit((int) *tpath); tpath++);
224+
if (*tpath != ',')
225+
goto errexit;
226+
tpath++;
227+
}
228+
/* pull out the MSB of the port */
229+
portno = (unsigned short) strtol(tpath, &ttpath, 10) * 256;
230+
if (ttpath == NULL) {
231+
/* didn't get correct response from PASV */
232+
goto errexit;
233+
}
234+
tpath = ttpath;
235+
if (*tpath != ',')
236+
goto errexit;
237+
tpath++;
238+
/* pull out the LSB of the port */
239+
portno += (unsigned short) strtol(tpath, &ttpath, 10);
240+
} else {
241+
/* parse epsv command (|||6446|) */
242+
for (i = 0, tpath = tmp_line + 4; *tpath; tpath++) {
243+
if (*tpath == '|') {
244+
i++;
245+
if (i == 3)
246+
break;
247+
}
248+
}
249+
if (i < 3)
250+
goto errexit;
251+
/* pull out the port */
252+
portno = (unsigned short) strtol(tpath + 1, &ttpath, 10);
253+
}
254+
255+
if (ttpath == NULL) {
256+
/* didn't get correct response from EPSV/PASV */
257+
goto errexit;
258+
}
259+
260+
if (mode[0] == 'r') {
261+
/* retrieve file */
262+
SOCK_WRITE("RETR ", *socketd);
263+
} else {
264+
/* store file */
265+
SOCK_WRITE("STOR ", *socketd);
266+
}
267+
if (resource->path != NULL) {
268+
SOCK_WRITE(resource->path, *socketd);
269+
} else {
270+
SOCK_WRITE("/", *socketd);
271+
}
272+
273+
/* close control connection */
274+
SOCK_WRITE("\r\nQUIT\r\n", *socketd);
275+
SOCK_FCLOSE(*socketd);
276+
277+
/* open the data channel */
278+
*socketd = php_hostconnect(resource->host, portno, SOCK_STREAM, 0);
279+
if (*socketd == -1)
280+
goto errexit;
281+
#if 0
282+
if (mode[0] == 'r') {
283+
if ((fp = fdopen(*socketd, "r+")) == NULL) {
284+
free_url(resource);
285+
return NULL;
286+
}
287+
} else {
288+
if ((fp = fdopen(*socketd, "w+")) == NULL) {
289+
free_url(resource);
290+
return NULL;
291+
}
292+
}
293+
#ifdef HAVE_SETVBUF
294+
if ((setvbuf(fp, NULL, _IONBF, 0)) != 0) {
295+
free_url(resource);
296+
fclose(fp);
297+
return NULL;
298+
}
299+
#endif
300+
#endif
301+
free_url(resource);
302+
*issock = 1;
303+
return (fp);
304+
305+
errexit:
306+
free_url(resource);
307+
SOCK_FCLOSE(*socketd);
308+
*socketd = 0;
309+
return NULL;
310+
}

0 commit comments

Comments
 (0)