diff options
Diffstat (limited to 'main/fopen_wrappers.c')
-rw-r--r-- | main/fopen_wrappers.c | 1000 |
1 files changed, 1000 insertions, 0 deletions
diff --git a/main/fopen_wrappers.c b/main/fopen_wrappers.c new file mode 100644 index 0000000000..02f97208b8 --- /dev/null +++ b/main/fopen_wrappers.c @@ -0,0 +1,1000 @@ +/* + +----------------------------------------------------------------------+ + | PHP HTML Embedded Scripting Language Version 3.0 | + +----------------------------------------------------------------------+ + | Copyright (c) 1997,1998 PHP Development Team (See Credits file) | + +----------------------------------------------------------------------+ + | This program is free software; you can redistribute it and/or modify | + | it under the terms of one of the following licenses: | + | | + | A) the GNU General Public License as published by the Free Software | + | Foundation; either version 2 of the License, or (at your option) | + | any later version. | + | | + | B) the PHP License as published by the PHP Development Team and | + | included in the distribution in the file: LICENSE | + | | + | This program is distributed in the hope that it will be useful, | + | but WITHOUT ANY WARRANTY; without even the implied warranty of | + | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | + | GNU General Public License for more details. | + | | + | You should have received a copy of both licenses referred to here. | + | If you did not, or have any questions about PHP licensing, please | + | contact core@php.net. | + +----------------------------------------------------------------------+ + | Authors: Rasmus Lerdorf <rasmus@lerdorf.on.ca> | + | Jim Winstead <jimw@php.net> | + +----------------------------------------------------------------------+ + */ +/* $Id$ */ + +#ifdef THREAD_SAFE +#include "tls.h" +#endif + +#include "php.h" + +#include <stdio.h> +#include <stdlib.h> +#include <errno.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> + +#if MSVC5 +#include <windows.h> +#include <winsock.h> +#define O_RDONLY _O_RDONLY +#include "win32/param.h" +#else +#include <sys/param.h> +#endif + +#include "safe_mode.h" +#include "php3_realpath.h" +#include "functions/head.h" +#include "functions/url.h" +#include "functions/base64.h" +#include "functions/fsock.h" +#include "functions/php3_string.h" +#include "zend_compile.h" + +#if HAVE_PWD_H +#if MSVC5 +#include "win32/pwd.h" +#else +#include <pwd.h> +#endif +#endif + +#include <sys/types.h> +#if HAVE_SYS_SOCKET_H +#include <sys/socket.h> +#endif + +#ifndef S_ISREG +#define S_ISREG(mode) (((mode)&S_IFMT) == S_IFREG) +#endif + +#if MSVC5 +#include <winsock.h> +#else +#include <netinet/in.h> +#include <netdb.h> +#include <arpa/inet.h> +#endif + +#if MSVC5 +#undef AF_UNIX +#endif + +#if defined(AF_UNIX) +#include <sys/un.h> +#endif + +static FILE *php3_fopen_url_wrapper(const char *path, char *mode, int options, int *issock, int *socketd); + +int _php3_getftpresult(int socketd); + +/* + 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 + + When open_basedir is NULL, always return 0 +*/ +PHPAPI int _php3_check_open_basedir(char *path) +{ + char resolved_name[MAXPATHLEN]; + char local_open_basedir[MAXPATHLEN]; + int local_open_basedir_pos; + + /* Only check when open_basedir is available */ + if (php3_ini.open_basedir && *php3_ini.open_basedir) { + + /* Special case basedir==".": Use script-directory */ + if ((strcmp(php3_ini.open_basedir, ".") == 0) && + GLOBAL(request_info).filename && + *GLOBAL(request_info).filename + ) { + strcpy(local_open_basedir, GLOBAL(request_info).filename); + local_open_basedir_pos = strlen(local_open_basedir) - 1; + + /* Strip filename */ + while (( +#if WIN32|WINNT + (local_open_basedir[local_open_basedir_pos] != '\\') || +#endif + (local_open_basedir[local_open_basedir_pos] != '/') + ) && + (local_open_basedir_pos >= 0) + ) { + local_open_basedir[local_open_basedir_pos--] = 0; + } + + /* Strip double (back)slashes */ + if (local_open_basedir_pos > 0) { + while (( +#if WIN32|WINNT + (local_open_basedir[local_open_basedir_pos-1] == '\\') || +#endif + (local_open_basedir[local_open_basedir_pos-1] == '/') + ) && + (local_open_basedir_pos > 0) + ) { + local_open_basedir[local_open_basedir_pos--] = 0; + } + } + + } else { + /* Else use the unmodified path */ + strcpy(local_open_basedir, php3_ini.open_basedir); + } + + /* Resolve the real path into resolved_name */ + if (_php3_realpath(path, resolved_name) != NULL) { + /* Check the path */ +#if WIN32|WINNT + if (strncasecmp(local_open_basedir, resolved_name, strlen(local_open_basedir)) == 0) { +#else + if (strncmp(local_open_basedir, resolved_name, strlen(local_open_basedir)) == 0) { +#endif + /* File is in the right directory */ + return 0; + } else { + php3_error(E_WARNING, "open_basedir restriction in effect. File is in wrong directory."); + return -1; + } + } else { + /* Unable to resolve the real path, return -1 */ + php3_error(E_WARNING, "open_basedir restriction in effect. Unable to verify location of file."); + return -1; + } + } else { + /* open_basedir is not available, return 0 */ + return 0; + } +} + +PHPAPI FILE *php3_fopen_wrapper(char *path, char *mode, int options, int *issock, int *socketd) +{ + int cm=2; /* checkuid mode: 2 = if file does not exist, check directory */ +#if PHP3_URL_FOPEN + if (!(options & IGNORE_URL)) { + return php3_fopen_url_wrapper(path, mode, options, issock, socketd); + } +#endif + + if (options & USE_PATH && php3_ini.include_path != NULL) { + return php3_fopen_with_path(path, mode, php3_ini.include_path, NULL); + } else { + if(!strcmp(mode,"r") || !strcmp(mode,"r+")) cm=0; + if (options & ENFORCE_SAFE_MODE && php3_ini.safe_mode && (!_php3_checkuid(path, cm))) { + return NULL; + } + if (_php3_check_open_basedir(path)) return NULL; + return fopen(path, mode); + } +} + +#if CGI_BINARY || FHTTPD || USE_SAPI + +FILE *php3_fopen_for_parser(void) +{ + FILE *fp; + struct stat st; + char *temp, *path_info, *fn; + int l; + TLS_VARS; + + + fn = GLOBAL(request_info).filename; + path_info = GLOBAL(request_info).path_info; +#if HAVE_PWD_H + if (php3_ini.user_dir && *php3_ini.user_dir + && path_info && '/' == path_info[0] && '~' == path_info[1]) { + + char user[32]; + struct passwd *pw; + char *s = strchr(path_info + 2, '/'); + + fn = NULL; /* discard the original filename, it must not be used */ + if (s) { /* if there is no path name after the file, do not bother + to try open the directory */ + l = s - (path_info + 2); + if (l > sizeof(user) - 1) + l = sizeof(user) - 1; + memcpy(user, path_info + 2, l); + user[l] = '\0'; + + pw = getpwnam(user); + if (pw && pw->pw_dir) { + fn = emalloc(strlen(php3_ini.user_dir) + strlen(path_info) + strlen(pw->pw_dir) + 4); + if (fn) { + strcpy(fn, pw->pw_dir); /* safe */ + strcat(fn, "/"); /* safe */ + strcat(fn, php3_ini.user_dir); /* safe */ + strcat(fn, "/"); /* safe */ + strcat(fn, s + 1); /* safe (shorter than path_info) */ + STR_FREE(GLOBAL(request_info).filename); + GLOBAL(request_info).filename = fn; + } + } + } + } else +#endif +#if WIN32 + if (php3_ini.doc_root && path_info && ('/' == *php3_ini.doc_root || + '\\' == *php3_ini.doc_root || strstr(php3_ini.doc_root,":\\") || + strstr(php3_ini.doc_root,":/"))) { +#else + if (php3_ini.doc_root && '/' == *php3_ini.doc_root && path_info) { +#endif + l = strlen(php3_ini.doc_root); + fn = emalloc(l + strlen(path_info) + 2); + if (fn) { + memcpy(fn, php3_ini.doc_root, l); + if ('/' != fn[l - 1] || '\\' != fn[l - 1]) /* l is never 0 */ + fn[l++] = '/'; + if ('/' == path_info[0]) + l--; + strcpy(fn + l, path_info); + STR_FREE(GLOBAL(request_info).filename); + GLOBAL(request_info).filename = fn; + } + } /* if doc_root && path_info */ + if (!fn) { + /* we have to free request_info.filename here because + php3_destroy_request_info assumes that it will get + freed when the include_names hash is emptied, but + we're not adding it in this case */ + STR_FREE(GLOBAL(request_info).filename); + GLOBAL(request_info).filename = NULL; + return NULL; + } + fp = fopen(fn, "r"); + + /* refuse to open anything that is not a regular file */ + if (fp && (0 > fstat(fileno(fp), &st) || !S_ISREG(st.st_mode))) { + fclose(fp); + fp = NULL; + } + if (!fp) { + php3_error(E_CORE_ERROR, "Unable to open %s", fn); + STR_FREE(GLOBAL(request_info).filename); /* for same reason as above */ + return NULL; + } + + temp = estrdup(fn); + _php3_dirname(temp, strlen(temp)); + if (*temp) { + chdir(temp); + } + efree(temp); + + return fp; +} + +#endif /* CGI_BINARY || USE_SAPI */ + +/* + * Tries to open a file with a PATH-style list of directories. + * If the filename starts with "." or "/", the path is ignored. + */ +PHPAPI FILE *php3_fopen_with_path(char *filename, char *mode, char *path, char **opened_path) +{ + char *pathbuf, *ptr, *end; + char trypath[MAXPATHLEN + 1]; + struct stat sb; + FILE *fp; + int cm=2; + TLS_VARS; + + if(!strcmp(mode,"r") || !strcmp(mode,"r+")) cm=0; + if (opened_path) { + *opened_path = NULL; + } + /* Relative path open */ + if (*filename == '.') { + if (php3_ini.safe_mode && (!_php3_checkuid(filename, cm))) { + return NULL; + } + if (_php3_check_open_basedir(filename)) return NULL; + fp = fopen(filename, mode); + if (fp && opened_path) { + *opened_path = expand_filepath(filename); + } + return fp; + } + /* Absolute path open - prepend document_root in safe mode */ +#if WIN32|WINNT + if ((*filename == '\\') || (*filename == '/') || (filename[1] == ':')) { +#else + if (*filename == '/') { +#endif + if (php3_ini.safe_mode) { + if(php3_ini.doc_root) { + snprintf(trypath, MAXPATHLEN, "%s%s", php3_ini.doc_root, filename); + } else { + strncpy(trypath,filename,MAXPATHLEN); + } + if (!_php3_checkuid(trypath, cm)) { + return NULL; + } + if (_php3_check_open_basedir(trypath)) return NULL; + fp = fopen(trypath, mode); + if (fp && opened_path) { + *opened_path = expand_filepath(trypath); + } + return fp; + } else { + if (_php3_check_open_basedir(filename)) return NULL; + return fopen(filename, mode); + } + } + if (!path || (path && !*path)) { + if (php3_ini.safe_mode && (!_php3_checkuid(filename, cm))) { + return NULL; + } + if (_php3_check_open_basedir(filename)) return NULL; + fp = fopen(filename, mode); + if (fp && opened_path) { + *opened_path = strdup(filename); + } + return fp; + } + pathbuf = estrdup(path); + + ptr = pathbuf; + + while (ptr && *ptr) { +#if WIN32|WINNT + end = strchr(ptr, ';'); +#else + end = strchr(ptr, ':'); +#endif + if (end != NULL) { + *end = '\0'; + end++; + } + snprintf(trypath, MAXPATHLEN, "%s/%s", ptr, filename); + if (php3_ini.safe_mode) { + if (stat(trypath, &sb) == 0 && (!_php3_checkuid(trypath, cm))) { + efree(pathbuf); + return NULL; + } + } + if ((fp = fopen(trypath, mode)) != NULL) { + if (_php3_check_open_basedir(trypath)) { + fclose(fp); + efree(pathbuf); + return NULL; + } + if (opened_path) { + *opened_path = expand_filepath(trypath); + } + efree(pathbuf); + return fp; + } + ptr = end; + } + efree(pathbuf); + return NULL; +} + +/* + * If the specified path starts with "http://" (insensitive to case), + * a socket is opened to the specified web server and a file pointer is + * position at the start of the body of the response (past any headers). + * This makes a HTTP/1.0 request, and knows how to pass on the username + * and password for basic authentication. + * + * If the specified path starts with "ftp://" (insensitive to case), + * a pair of sockets are used to request the specified file and a file + * pointer to the requested file is returned. Passive mode ftp is used, + * so if the server doesn't suppor this, it will fail! + * + * Otherwise, fopen is called as usual and the file pointer is returned. + */ + +static FILE *php3_fopen_url_wrapper(const char *path, char *mode, int options, int *issock, int *socketd) +{ + url *resource; + int result; + char *scratch; + unsigned char *tmp; + + char tmp_line[256]; + char location[256]; + int chptr = 0; + char *tpath, *ttpath; + int body = 0; + int reqok = 0; + int lineone = 1; + int i; + char buf[2]; + + char oldch1 = 0; + char oldch2 = 0; + char oldch3 = 0; + char oldch4 = 0; + char oldch5 = 0; + + FILE *fp = NULL; + struct sockaddr_in server; + unsigned short portno; + char winfeof; + + if (!strncasecmp(path, "http://", 7)) { + resource = url_parse((char *) path); + if (resource == NULL) { + php3_error(E_WARNING, "Invalid URL specified, %s", path); + *issock = BAD_URL; + return NULL; + } + /* use port 80 if one wasn't specified */ + if (resource->port == 0) + resource->port = 80; + + *socketd = socket(AF_INET, SOCK_STREAM, 0); + if (*socketd == SOCK_ERR) { + SOCK_FCLOSE(*socketd); + *socketd = 0; + free_url(resource); + return NULL; + } + server.sin_addr.s_addr = lookup_hostname(resource->host); + server.sin_family = AF_INET; + + if (server.sin_addr.s_addr == -1) { + SOCK_FCLOSE(*socketd); + *socketd = 0; + free_url(resource); + return NULL; + } + server.sin_port = htons(resource->port); + + if (connect(*socketd, (struct sockaddr *) &server, sizeof(server)) == SOCK_CONN_ERR) { + SOCK_FCLOSE(*socketd); + *socketd = 0; + free_url(resource); + return NULL; + } +#if 0 + if ((fp = fdopen(*socketd, "r+")) == NULL) { + free_url(resource); + return NULL; + } +#ifdef HAVE_SETVBUF + if ((setvbuf(fp, NULL, _IONBF, 0)) != 0) { + free_url(resource); + return NULL; + } +#endif +#endif /*win32 */ + + /* tell remote http which file to get */ + SOCK_WRITE("GET ", *socketd); + if (resource->path != NULL) { + SOCK_WRITE(resource->path, *socketd); + } else { + SOCK_WRITE("/", *socketd); + } + + /* append the query string, if any */ + if (resource->query != NULL) { + SOCK_WRITE("?", *socketd); + SOCK_WRITE(resource->query, *socketd); + } + SOCK_WRITE(" HTTP/1.0\n", *socketd); + + /* send authorization header if we have user/pass */ + if (resource->user != NULL && resource->pass != NULL) { + scratch = (char *) emalloc(strlen(resource->user) + strlen(resource->pass) + 2); + if (!scratch) { + free_url(resource); + return NULL; + } + strcpy(scratch, resource->user); + strcat(scratch, ":"); + strcat(scratch, resource->pass); + tmp = _php3_base64_encode((unsigned char *)scratch, strlen(scratch), NULL); + + SOCK_WRITE("Authorization: Basic ", *socketd); + /* output "user:pass" as base64-encoded string */ + SOCK_WRITE((char *)tmp, *socketd); + SOCK_WRITE("\n", *socketd); + efree(scratch); + efree(tmp); + } + /* if the user has configured who they are, send a From: line */ + if (cfg_get_string("from", &scratch) == SUCCESS) { + SOCK_WRITE("From: ", *socketd); + SOCK_WRITE(scratch, *socketd); + SOCK_WRITE("\n", *socketd); + } + /* send a Host: header so name-based virtual hosts work */ + SOCK_WRITE("Host: ", *socketd); + SOCK_WRITE(resource->host, *socketd); + if(resource->port!=80) { + sprintf(tmp_line,"%i",resource->port); + SOCK_WRITE(":", *socketd); + SOCK_WRITE(tmp_line, *socketd); + } + SOCK_WRITE("\n", *socketd); + + /* identify ourselves */ + SOCK_WRITE("User-Agent: PHP/", *socketd); + SOCK_WRITE(PHP_VERSION, *socketd); + SOCK_WRITE("\n", *socketd); + + /* end the headers */ + SOCK_WRITE("\n", *socketd); + + /* Read past http header */ + body = 0; + location[0] = '\0'; + while (!body && recv(*socketd, (char *) &winfeof, 1, MSG_PEEK)) { + if (SOCK_FGETC(buf, *socketd) == SOCK_RECV_ERR) { + SOCK_FCLOSE(*socketd); + *socketd = 0; + free_url(resource); + return NULL; + } + oldch5 = oldch4; + oldch4 = oldch3; + oldch3 = oldch2; + oldch2 = oldch1; + oldch1 = *buf; + + tmp_line[chptr++] = *buf; + if (*buf == 10 || *buf == 13) { + tmp_line[chptr] = '\0'; + chptr = 0; + if (!strncasecmp(tmp_line, "Location: ", 10)) { + tpath = tmp_line + 10; + strcpy(location, tpath); + } + } + if (lineone && (*buf == 10 || *buf == 13)) { + lineone = 0; + } + if (lineone && oldch5 == ' ' && oldch4 == '2' && oldch3 == '0' && + oldch2 == '0' && oldch1 == ' ') { + reqok = 1; + } + if (oldch4 == 13 && oldch3 == 10 && oldch2 == 13 && oldch1 == 10) { + body = 1; + } + if (oldch2 == 10 && oldch1 == 10) { + body = 1; + } + if (oldch2 == 13 && oldch1 == 13) { + body = 1; + } + } + if (!reqok) { + SOCK_FCLOSE(*socketd); + *socketd = 0; + free_url(resource); + if (location[0] != '\0') { + return php3_fopen_url_wrapper(location, mode, options, issock, socketd); + } else { + return NULL; + } + } + free_url(resource); + *issock = 1; + return (fp); + } else if (!strncasecmp(path, "ftp://", 6)) { + resource = url_parse((char *) path); + if (resource == NULL) { + php3_error(E_WARNING, "Invalid URL specified, %s", path); + *issock = BAD_URL; + return NULL; + } else if (resource->path == NULL) { + php3_error(E_WARNING, "No file-path specified"); + free_url(resource); + *issock = BAD_URL; + return NULL; + } + /* use port 21 if one wasn't specified */ + if (resource->port == 0) + resource->port = 21; + + *socketd = socket(AF_INET, SOCK_STREAM, 0); + if (*socketd == SOCK_ERR) { + SOCK_FCLOSE(*socketd); + *socketd = 0; + free_url(resource); + return NULL; + } + server.sin_addr.s_addr = lookup_hostname(resource->host); + server.sin_family = AF_INET; + + if (server.sin_addr.s_addr == -1) { + SOCK_FCLOSE(*socketd); + *socketd = 0; + free_url(resource); + return NULL; + } + server.sin_port = htons(resource->port); + + if (connect(*socketd, (struct sockaddr *) &server, sizeof(server)) == SOCK_CONN_ERR) { + SOCK_FCLOSE(*socketd); + *socketd = 0; + free_url(resource); + return NULL; + } +#if 0 + if ((fpc = fdopen(*socketd, "r+")) == NULL) { + free_url(resource); + return NULL; + } +#ifdef HAVE_SETVBUF + if ((setvbuf(fpc, NULL, _IONBF, 0)) != 0) { + free_url(resource); + fclose(fpc); + return NULL; + } +#endif +#endif + + /* Start talking to ftp server */ + result = _php3_getftpresult(*socketd); + if (result > 299 || result < 200) { + free_url(resource); + SOCK_FCLOSE(*socketd); + *socketd = 0; + return NULL; + } + /* send the user name */ + SOCK_WRITE("USER ", *socketd); + if (resource->user != NULL) { + _php3_rawurldecode(resource->user, strlen(resource->user)); + SOCK_WRITE(resource->user, *socketd); + } else { + SOCK_WRITE("anonymous", *socketd); + } + SOCK_WRITE("\n", *socketd); + + /* get the response */ + result = _php3_getftpresult(*socketd); + + /* if a password is required, send it */ + if (result >= 300 && result <= 399) { + SOCK_WRITE("PASS ", *socketd); + if (resource->pass != NULL) { + _php3_rawurldecode(resource->pass, strlen(resource->pass)); + SOCK_WRITE(resource->pass, *socketd); + } else { + /* if the user has configured who they are, + send that as the password */ + if (cfg_get_string("from", &scratch) == SUCCESS) { + SOCK_WRITE(scratch, *socketd); + } else { + SOCK_WRITE("anonymous", *socketd); + } + } + SOCK_WRITE("\n", *socketd); + + /* read the response */ + result = _php3_getftpresult(*socketd); + if (result > 299 || result < 200) { + free_url(resource); + SOCK_FCLOSE(*socketd); + *socketd = 0; + return NULL; + } + } else if (result > 299 || result < 200) { + free_url(resource); + SOCK_FCLOSE(*socketd); + *socketd = 0; + return NULL; + } + + /* find out the size of the file (verifying it exists) */ + SOCK_WRITE("SIZE ", *socketd); + SOCK_WRITE(resource->path, *socketd); + SOCK_WRITE("\n", *socketd); + + /* read the response */ + result = _php3_getftpresult(*socketd); + if (mode[0] == 'r') { + /* when reading file, it must exist */ + if (result > 299 || result < 200) { + php3_error(E_WARNING, "File not found"); + free_url(resource); + SOCK_FCLOSE(*socketd); + *socketd = 0; + errno = ENOENT; + return NULL; + } + } else { + /* when writing file, it must NOT exist */ + if (result <= 299 && result >= 200) { + php3_error(E_WARNING, "File already exists"); + free_url(resource); + SOCK_FCLOSE(*socketd); + *socketd = 0; + errno = EEXIST; + return NULL; + } + } + + /* set the connection to be binary */ + SOCK_WRITE("TYPE I\n", *socketd); + result = _php3_getftpresult(*socketd); + if (result > 299 || result < 200) { + free_url(resource); + SOCK_FCLOSE(*socketd); + *socketd = 0; + return NULL; + } + /* set up the passive connection */ + SOCK_WRITE("PASV\n", *socketd); + while (SOCK_FGETS(tmp_line, 256, *socketd) && + !(isdigit((int) tmp_line[0]) && isdigit((int) tmp_line[1]) && + isdigit((int) tmp_line[2]) && tmp_line[3] == ' ')); + + /* make sure we got a 227 response */ + if (strncmp(tmp_line, "227", 3)) { + free_url(resource); + SOCK_FCLOSE(*socketd); + *socketd = 0; + return NULL; + } + /* parse pasv command (129,80,95,25,13,221) */ + tpath = tmp_line; + + /* skip over the "227 Some message " part */ + for (tpath += 4; *tpath && !isdigit((int) *tpath); tpath++); + if (!*tpath) { + free_url(resource); + SOCK_FCLOSE(*socketd); + *socketd = 0; + return NULL; + } + /* skip over the host ip, we just assume it's the same */ + for (i = 0; i < 4; i++) { + for (; isdigit((int) *tpath); tpath++); + if (*tpath == ',') { + tpath++; + } else { + SOCK_FCLOSE(*socketd); + *socketd = 0; + return NULL; + } + } + + /* pull out the MSB of the port */ + portno = (unsigned short) strtol(tpath, &ttpath, 10) * 256; + if (ttpath == NULL) { + /* didn't get correct response from PASV */ + free_url(resource); + SOCK_FCLOSE(*socketd); + *socketd = 0; + return NULL; + } + tpath = ttpath; + if (*tpath == ',') { + tpath++; + } else { + free_url(resource); + SOCK_FCLOSE(*socketd); + *socketd = 0; + return NULL; + } + + /* pull out the LSB of the port */ + portno += (unsigned short) strtol(tpath, &ttpath, 10); + + if (ttpath == NULL) { + /* didn't get correct response from PASV */ + free_url(resource); + SOCK_FCLOSE(*socketd); + *socketd = 0; + return NULL; + } + + if (mode[0] == 'r') { + /* retrieve file */ + SOCK_WRITE("RETR ", *socketd); + } else { + /* store file */ + SOCK_WRITE("STOR ", *socketd); + } + if (resource->path != NULL) { + SOCK_WRITE(resource->path, *socketd); + } else { + SOCK_WRITE("/", *socketd); + } + + /* close control connection */ + SOCK_WRITE("\nQUIT\n", *socketd); + SOCK_FCLOSE(*socketd); + + /* open the data channel */ + *socketd = socket(AF_INET, SOCK_STREAM, 0); + if (*socketd == SOCK_ERR) { + SOCK_FCLOSE(*socketd); + *socketd = 0; + free_url(resource); + return NULL; + } + server.sin_addr.s_addr = lookup_hostname(resource->host); + server.sin_family = AF_INET; + + if (server.sin_addr.s_addr == -1) { + free_url(resource); + SOCK_FCLOSE(*socketd); + *socketd = 0; + return NULL; + } + server.sin_port = htons(portno); + + if (connect(*socketd, (struct sockaddr *) &server, sizeof(server)) == SOCK_CONN_ERR) { + free_url(resource); + SOCK_FCLOSE(*socketd); + *socketd = 0; + return NULL; + } +#if 0 + if (mode[0] == 'r') { + if ((fp = fdopen(*socketd, "r+")) == NULL) { + free_url(resource); + return NULL; + } + } else { + if ((fp = fdopen(*socketd, "w+")) == NULL) { + free_url(resource); + return NULL; + } + } +#ifdef HAVE_SETVBUF + if ((setvbuf(fp, NULL, _IONBF, 0)) != 0) { + free_url(resource); + fclose(fp); + return NULL; + } +#endif +#endif + free_url(resource); + *issock = 1; + return (fp); + + } else { + if (options & USE_PATH) { + fp = php3_fopen_with_path((char *) path, mode, php3_ini.include_path, NULL); + } else { + int cm=2; + if(!strcmp(mode,"r") || !strcmp(mode,"r+")) cm=0; + if (options & ENFORCE_SAFE_MODE && php3_ini.safe_mode && (!_php3_checkuid(path, cm))) { + fp = NULL; + } else { + if (_php3_check_open_basedir((char *) path)) { + fp = NULL; + } else { + fp = fopen(path, mode); + } + } + } + + *issock = 0; + + return (fp); + } + + /* NOTREACHED */ + SOCK_FCLOSE(*socketd); + *socketd = 0; + return NULL; +} + +int _php3_getftpresult(int socketd) +{ + char tmp_line[256]; + + while (SOCK_FGETS(tmp_line, 256, socketd) && + !(isdigit((int) tmp_line[0]) && isdigit((int) tmp_line[1]) && + isdigit((int) tmp_line[2]) && tmp_line[3] == ' ')); + + return strtol(tmp_line, NULL, 10); +} + +PHPAPI int php3_isurl(char *path) +{ + return (!strncasecmp(path, "http://", 7) || !strncasecmp(path, "ftp://", 6)); +} + + +PHPAPI char *php3_strip_url_passwd(char *url) +{ + register char *p = url, *url_start; + + while (*p) { + if (*p==':' && *(p+1)=='/' && *(p+2)=='/') { + /* found protocol */ + url_start = p = p+3; + + while (*p) { + if (*p=='@') { + int i; + + for (i=0; i<3 && url_start<p; i++, url_start++) { + *url_start = '.'; + } + for (; *p; p++) { + *url_start++ = *p; + } + *url_start=0; + break; + } + p++; + } + return url; + } + p++; + } + return url; +} + + +PHPAPI char *expand_filepath(char *filepath) +{ + char *retval = NULL; + + if (filepath[0] == '.') { + char *cwd = malloc(MAXPATHLEN + 1); + + if (getcwd(cwd, MAXPATHLEN)) { + char *cwd_end = cwd + strlen(cwd); + + if (filepath[1] == '.') { /* parent directory - .. */ + /* erase the last directory name from the path */ + while (*cwd_end != '/') { + *cwd_end-- = 0; + } + filepath++; /* make filepath appear as a current directory path */ + } + if (cwd_end > cwd && *cwd_end == '/') { /* remove trailing slashes */ + *cwd_end-- = 0; + } + retval = (char *) malloc(strlen(cwd) + strlen(filepath) - 1 + 1); + strcpy(retval, cwd); + strcat(retval, filepath + 1); + free(cwd); + } + } + if (!retval) { + retval = strdup(filepath); + } + return retval; +} + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * End: + */ |