proposed fopen_wrappers generalization / patch v.2

[email protected] (Hartmut Holzgraefe) Wed, 07 Jun 2000 09:19:26 +0200
Newsgroups php.version4
Message-ID <[email protected]>
- will now do file:/path urls right 
- functions that allow extension modules to add
  additional url type handlers are in
- works for me (linux)

todo: have fopen wrappers enabled/disabled by ini file
      instead of compile time #ifdefs

please have a look at it

if i get no negative feedback (no feedback at all will
be treated as positive feedback) i'll check it in this
weekend
fopen-wrappers.patch (text/plain, 7.3 KB)
Index: fopen-wrappers.c
===================================================================
RCS file: /repository/php4/fopen-wrappers.c,v
retrieving revision 1.60
diff -u -b -w -B -r1.60 fopen-wrappers.c
--- fopen-wrappers.c	2000/05/27 16:38:49	1.60
+++ fopen-wrappers.c	2000/06/07 07:08:45
@@ -77,10 +77,71 @@
 #include <sys/un.h>
 #endif
 
-static FILE *php_fopen_url_wrapper(const char *path, char *mode, int options, int *issock, int *socketd, char **opened_path);
 
+typedef FILE * (*php_fopen_url_wrapper_t) (const char *, char *, int, int *, int *, char **) ;
+
+static FILE *php_fopen_url_wrapper(const char *, char *, int, int *, int *, char **);
+static FILE *php_fopen_url_wrap_http(const char *, char *, int, int *, int *, char **);
+static FILE *php_fopen_url_wrap_ftp(const char *, char *, int, int *, int *, char **);
+static FILE *php_fopen_url_wrap_php(const char *, char *, int, int *, int *, char **);
+
 int php_get_ftp_result(int socketd);
 
+
+
+HashTable fopen_url_wrappers_hash;
+
+PHPAPI int php_register_url_wrapper(char *protocol, FILE * (*wrapper)(const char *path, char *mode, int options, int *issock, int *socketd, char **opened_path)) {
+#if PHP_URL_FOPEN
+	return zend_hash_add(&fopen_url_wrappers_hash, protocol, strlen(protocol)+1, &wrapper, sizeof(wrapper), NULL);
+#else
+	return FAILURE;
+#endif
+}
+
+PHPAPI int php_unregister_url_wrapper(char *protocol) {
+#if PHP_URL_FOPEN
+	return zend_hash_del(&fopen_url_wrappers_hash, protocol, strlen(protocol)+1);
+#else
+	return SUCCESS;
+#endif
+}
+
+int php_init_fopen_wrappers(void) 
+{
+	int status = SUCCESS;
+#if PHP_URL_FOPEN
+	if (zend_hash_init(&fopen_url_wrappers_hash, 0, NULL, NULL, 1)==FAILURE) {
+		return FAILURE;
+	}
+
+ 	if(FAILURE==php_register_url_wrapper("http",php_fopen_url_wrap_http)) {
+		status = FAILURE;
+	} else
+	if(FAILURE==php_register_url_wrapper("ftp",php_fopen_url_wrap_ftp)) {
+		status = FAILURE;
+	} else
+	if(FAILURE==php_register_url_wrapper("php",php_fopen_url_wrap_php)) {
+		status = FAILURE;
+	}
+
+	if(FAILURE==status) {
+		zend_hash_destroy(&fopen_url_wrappers_hash);
+	}
+#endif
+	return status;
+}
+
+int php_shutdown_fopen_wrappers(void) 
+{
+#if PHP_URL_FOPEN
+		zend_hash_destroy(&fopen_url_wrappers_hash);
+#endif
+
+	return SUCCESS;
+}
+
+
 /*
 	When open_basedir is not NULL, check if the given filename is located in
 	open_basedir. Returns -1 if error or not in the open_basedir, else 0
@@ -446,26 +507,21 @@
  * Otherwise, fopen is called as usual and the file pointer is returned.
  */
 
-static FILE *php_fopen_url_wrapper(const char *path, char *mode, int options, int *issock, int *socketd, char **opened_path)
-{
-	url *resource;
-	int result;
-	char *scratch;
-	unsigned char *tmp;
 
+static FILE *php_fopen_url_wrap_http(const char *path, char *mode, int options, int *issock, int *socketd, char **opened_path)
+{
+	FILE *fp=NULL;
+	url *resource=NULL;
+	struct sockaddr_in server;
 	char tmp_line[512];
 	char location[512];
 	char hdr_line[8192];
-	char *tpath, *ttpath;
 	int body = 0;
+	char *scratch;
+	unsigned char *tmp;
+	int len;
 	int reqok = 0;
-	int i, len;
 
-	FILE *fp = NULL;
-	struct sockaddr_in server;
-	unsigned short portno;
-
-	if (!strncasecmp(path, "http://", 7)) {
 		resource = url_parse((char *) path);
 		if (resource == NULL) {
 			php_error(E_WARNING, "Invalid URL specified, %s", path);
@@ -617,17 +673,20 @@
 		free_url(resource);
 		*issock = 1;
 		return (fp);
-	} else if (!strncasecmp(path, "php://", 6)) {
-		const char *res = path + 6;
-
-		if (!strcasecmp(res, "stdin")) {
-			return fdopen(STDIN_FILENO, mode);
-		} else if (!strcasecmp(res, "stdout")) {
-			return fdopen(STDOUT_FILENO, mode);
-		} else if (!strcasecmp(res, "stderr")) {
-			return fdopen(STDERR_FILENO, mode);
 		}
-	} else if (!strncasecmp(path, "ftp://", 6)) {
+ 
+ static FILE *php_fopen_url_wrap_ftp(const char *path, char *mode, int options, int *issock, int *socketd, char **opened_path)
+{
+	FILE *fp=NULL;
+	url *resource=NULL;
+	struct sockaddr_in server;
+	char tmp_line[512];
+	unsigned short portno;
+	char *scratch;
+	int result;
+	int i;
+	char *tpath, *ttpath;
+	
 		resource = url_parse((char *) path);
 		if (resource == NULL) {
 			php_error(E_WARNING, "Invalid URL specified, %s", path);
@@ -902,9 +961,69 @@
 		free_url(resource);
 		*issock = 1;
 		return (fp);
-	} else {
+}
+
+static FILE *php_fopen_url_wrap_php(const char *path, char *mode, int options, int *issock, int *socketd, char **opened_path)
+{
+	const char *res = path + 6;
+
+	*issock = 0;
+	
+	if (!strcasecmp(res, "stdin")) {
+		return fdopen(STDIN_FILENO, mode);
+	} else if (!strcasecmp(res, "stdout")) {
+		return fdopen(STDOUT_FILENO, mode);
+	} else if (!strcasecmp(res, "stderr")) {
+		return fdopen(STDERR_FILENO, mode);
+	}
+	
+	return NULL;
+}
+
+static FILE *php_fopen_url_wrapper(const char *path, char *mode, int options, int *issock, int *socketd, char **opened_path)
+{
+	FILE *fp = NULL;
+	const char *p;
+	const char *protocol=NULL;
+	int n=0;
+
+	for(p=path;isalnum(*p);p++) 
+		n++;
+	if((*p==':')&&(n>1)) {
+		protocol=path;
+	} 
+		
+	if(protocol) {
+		php_fopen_url_wrapper_t *wrapper=NULL;
+		char *protocopy = emalloc(n+1);
+
+		if(protocopy) {
+			strncpy(protocopy,protocol,n);
+			protocopy[n]='\0';
+			if(FAILURE==zend_hash_find(&fopen_url_wrappers_hash, protocopy, n+1,(void **)&wrapper)) {
+				wrapper=NULL;
+			}		
+			efree(protocopy);
+		}
+		if(wrapper)
+			return (*wrapper)(path, mode, options, issock, socketd, opened_path);	
+	} 
+
+	if( !protocol || !strncasecmp(protocol, "file",n)){
 		PLS_FETCH();
 
+		*issock = 0;
+		
+		if(protocol) {
+			if(path[n+1]=='/') {
+				if(path[n+2]=='/') { 
+					php_error(E_WARNING, "remote host file access not supported, %s", path);
+					return NULL;
+				}
+			}
+			path+= n+1; 			
+		}		
+
 		if (options & USE_PATH) {
 			fp = php_fopen_with_path((char *) path, mode, PG(include_path), opened_path);
 		} else {
@@ -921,14 +1040,11 @@
 			}
 		}
 
-		*issock = 0;
 
 		return (fp);
 	}
 
-	/* NOTREACHED */
-	SOCK_FCLOSE(*socketd);
-	*socketd = 0;
+	php_error(E_WARNING, "Invalid URL specified, %s", path);
 	return NULL;
 }
 
Index: fopen-wrappers.h
===================================================================
RCS file: /repository/php4/fopen-wrappers.h,v
retrieving revision 1.18
diff -u -b -w -B -r1.18 fopen-wrappers.h
--- fopen-wrappers.h	2000/05/18 15:34:21	1.18
+++ fopen-wrappers.h	2000/06/07 07:08:45
@@ -78,6 +78,11 @@
 
 PHPAPI char *expand_filepath(char *filepath);
 
+int php_init_fopen_wrappers(void); 
+int php_shutdown_fopen_wrappers(void); 
+PHPAPI int php_register_url_wrapper(char *protocol, FILE * (*wrapper)(const char *path, char *mode, int options, int *issock, int *socketd, char **opened_path));
+PHPAPI int php_unregister_url_wrapper(char *protocol);
+
 #endif
 /*
  * Local variables:
Index: main.c
===================================================================
RCS file: /repository/php4/main.c,v
retrieving revision 1.263
diff -u -b -w -B -r1.263 main.c
--- main.c	2000/06/06 19:16:57	1.263
+++ main.c	2000/06/07 07:08:46
@@ -714,12 +714,17 @@
 		php_printf("PHP:  Unable to parse configuration file.\n");
 		return FAILURE;
 	}
+	if (php_init_fopen_wrappers() == FAILURE) {
+		php_printf("PHP:  Unable to initialize fopen url wrappers.\n");
+		return FAILURE;
+	}
 	return SUCCESS;
 }
 
 static void php_config_ini_shutdown(void)
 {
 	php_shutdown_config();
+	php_shutdown_fopen_wrappers();
 }