diff options
-rw-r--r-- | ext/standard/basic_functions.c | 7 | ||||
-rw-r--r-- | ext/standard/file.c | 625 | ||||
-rw-r--r-- | ext/standard/file.h | 4 | ||||
-rw-r--r-- | ext/standard/fsock.c | 168 | ||||
-rw-r--r-- | ext/standard/fsock.h | 4 | ||||
-rw-r--r-- | ext/standard/info.c | 5 |
6 files changed, 542 insertions, 271 deletions
diff --git a/ext/standard/basic_functions.c b/ext/standard/basic_functions.c index 83e8a60fbb..3e538ba5f8 100644 --- a/ext/standard/basic_functions.c +++ b/ext/standard/basic_functions.c @@ -430,6 +430,9 @@ function_entry basic_functions[] = { use socket_set_blocking() instead */ PHP_FE(set_socket_blocking, NULL) PHP_FE(socket_set_blocking, NULL) +#if HAVE_PHP_STREAM + PHP_FE(fopenstream, NULL) +#endif #if HAVE_SYS_TIME_H PHP_FE(socket_set_timeout, NULL) #else @@ -2491,11 +2494,11 @@ PHP_FUNCTION(move_uploaded_file) if (!zend_hash_exists(SG(rfc1867_uploaded_files), Z_STRVAL_PP(path), Z_STRLEN_PP(path)+1)) { RETURN_FALSE; } - + if (PG(safe_mode) &&(!php_checkuid(Z_STRVAL_PP(new_path), NULL, CHECKUID_CHECK_FILE_AND_DIR))) { RETURN_FALSE; } - + V_UNLINK(Z_STRVAL_PP(new_path)); if (rename(Z_STRVAL_PP(path), Z_STRVAL_PP(new_path))==0) { successful=1; diff --git a/ext/standard/file.c b/ext/standard/file.c index 98928c45d8..8513feb895 100644 --- a/ext/standard/file.c +++ b/ext/standard/file.c @@ -101,7 +101,10 @@ php_file_globals file_globals; /* {{{ ZTS-stuff / Globals / Prototypes */ /* sharing globals is *evil* */ -static int le_fopen, le_popen, le_socket; +static int le_fopen, le_popen, le_socket; +/* sorry folks; including this even if you haven't enabled streams + saves a zillion ifdefs */ +static int le_stream = FAILURE; /* }}} */ @@ -116,7 +119,7 @@ static void _file_popen_dtor(zend_rsrc_list_entry *rsrc) } -static void _file_socket_dtor(zend_rsrc_list_entry *rsrc) +static void _file_socket_dtor(zend_rsrc_list_entry *rsrc) { int *sock = (int *)rsrc->ptr; SOCK_FCLOSE(*sock); @@ -126,8 +129,15 @@ static void _file_socket_dtor(zend_rsrc_list_entry *rsrc) efree(sock); } +#if HAVE_PHP_STREAM +static void _file_stream_dtor(zend_rsrc_list_entry * rsrc) +{ + php_stream * stream = (php_stream*)rsrc->ptr; + php_stream_close(stream); +} +#endif -static void _file_fopen_dtor(zend_rsrc_list_entry *rsrc) +static void _file_fopen_dtor(zend_rsrc_list_entry *rsrc) { FILE *fp = (FILE *)rsrc->ptr; fclose(fp); @@ -176,6 +186,10 @@ PHP_MINIT_FUNCTION(file) le_popen = zend_register_list_destructors_ex(_file_popen_dtor, NULL, "pipe", module_number); le_socket = zend_register_list_destructors_ex(_file_socket_dtor, NULL, "socket", module_number); +#if HAVE_PHP_STREAM + le_stream = zend_register_list_destructors_ex(_file_stream_dtor, NULL, "stream", module_number); +#endif + #ifdef ZTS file_globals_id = ts_allocate_id(sizeof(php_file_globals), (ts_allocate_ctor) file_globals_ctor, (ts_allocate_dtor) file_globals_dtor); #else @@ -217,20 +231,27 @@ PHP_FUNCTION(flock) pval **arg1, **arg2, **arg3; int type, fd, act, ret, arg_count = ARG_COUNT(ht); void *what; - + if (arg_count > 3 || zend_get_parameters_ex(arg_count, &arg1, &arg2, &arg3) == FAILURE) { WRONG_PARAM_COUNT; } - - what = zend_fetch_resource(arg1,-1,"File-Handle",&type,3,le_fopen,le_popen,le_socket); + + what = zend_fetch_resource(arg1, -1, "File-Handle", &type, 4, le_fopen, le_popen, le_socket, le_stream); ZEND_VERIFY_RESOURCE(what); - + +#if HAVE_PHP_STREAM + if (type == le_stream) { + if (php_stream_cast((php_stream*)what, PHP_STREAM_AS_FD, (void*)&fd, 1) == FAILURE) { + RETURN_FALSE; + } + } else +#endif if (type == le_socket) { fd = *(int *) what; } else { fd = fileno((FILE*) what); } - + convert_to_long_ex(arg2); act = (*arg2)->value.lval & 3; @@ -271,7 +292,7 @@ PHP_FUNCTION(get_meta_tags) char *token_data=NULL, *name=NULL, *value=NULL, *temp=NULL; php_meta_tags_token tok, tok_last; PLS_FETCH(); - + /* check args */ switch (ARG_COUNT(ht)) { case 1: @@ -290,7 +311,7 @@ PHP_FUNCTION(get_meta_tags) WRONG_PARAM_COUNT; } convert_to_string_ex(filename); - + fp = php_fopen_wrapper((*filename)->value.str.val,"rb", use_include_path|ENFORCE_SAFE_MODE, &issock, &socketd, NULL); if (!fp && !socketd) { if (issock != BAD_URL) { @@ -301,7 +322,7 @@ PHP_FUNCTION(get_meta_tags) } RETURN_FALSE; } - + if (array_init(return_value)==FAILURE) { if (issock) { SOCK_FCLOSE(socketd); @@ -426,7 +447,7 @@ PHP_FUNCTION(file) int target_len, len; zend_bool reached_eof=0; PLS_FETCH(); - + /* check args */ switch (ARG_COUNT(ht)) { case 1: @@ -445,7 +466,7 @@ PHP_FUNCTION(file) WRONG_PARAM_COUNT; } convert_to_string_ex(filename); - + fp = php_fopen_wrapper((*filename)->value.str.val,"rb", use_include_path|ENFORCE_SAFE_MODE, &issock, &socketd, NULL); if (!fp && !socketd) { if (issock != BAD_URL) { @@ -460,8 +481,8 @@ PHP_FUNCTION(file) /* Initialize return array */ if (array_init(return_value) == FAILURE) { RETURN_FALSE; - } - + } + /* Now loop through the file and do the magic quotes thing if needed */ target_len = 0; target_buf = NULL; @@ -519,7 +540,7 @@ PHP_FUNCTION(tempnam) char *opened_path; char p[64]; FILE *fp; - + if (ARG_COUNT(ht) != 2 || zend_get_parameters_ex(2, &arg1, &arg2) == FAILURE) { WRONG_PARAM_COUNT; } @@ -555,6 +576,31 @@ PHP_NAMED_FUNCTION(php_if_tmpfile) } /* }}} */ +PHP_FUNCTION(fopenstream) +{ +#if HAVE_PHP_STREAM + zval ** zfilename, ** zmode; + php_stream * stream; + + if (ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &zfilename, &zmode) == FAILURE) { + WRONG_PARAM_COUNT; + } + convert_to_string_ex(zfilename); + convert_to_string_ex(zmode); + + stream = php_stream_fopen(Z_STRVAL_PP(zfilename), Z_STRVAL_PP(zmode)); + + if (stream == NULL) { + zend_error(E_WARNING, "%s(): unable to open %s: %s", get_active_function_name(), Z_STRVAL_PP(zfilename), strerror(errno)); + RETURN_FALSE; + } + ZEND_REGISTER_RESOURCE(return_value, stream, le_stream); +#else + zend_error(E_ERROR, "%s(): no stream support in this PHP build", get_active_function_name()); + RETURN_FALSE; +#endif +} + /* {{{ proto int fopen(string filename, string mode [, int use_include_path]) Open a file or a URL and return a file pointer */ @@ -567,7 +613,7 @@ PHP_NAMED_FUNCTION(php_if_fopen) int use_include_path = 0; int issock=0, socketd=0; FLS_FETCH(); - + switch(ARG_COUNT(ht)) { case 2: if (zend_get_parameters_ex(2,&arg1,&arg2) == FAILURE) { @@ -616,7 +662,7 @@ PHP_NAMED_FUNCTION(php_if_fopen) } } -/* }}} */ +/* }}} */ /* {{{ proto int fclose(int fp) Close an open file pointer */ @@ -625,14 +671,14 @@ PHP_FUNCTION(fclose) pval **arg1; int type; void *what; - + if (ARG_COUNT(ht) != 1 || zend_get_parameters_ex(1, &arg1) == FAILURE) { WRONG_PARAM_COUNT; } - what = zend_fetch_resource(arg1,-1,"File-Handle",&type,2,le_fopen,le_socket); + what = zend_fetch_resource(arg1, -1, "File-Handle", &type, 3, le_fopen, le_socket, le_stream); ZEND_VERIFY_RESOURCE(what); - + zend_list_delete((*arg1)->value.lval); RETURN_TRUE; } @@ -648,7 +694,7 @@ PHP_FUNCTION(popen) char *p,*tmp = NULL; char *b, buf[1024]; PLS_FETCH(); - + if (ARG_COUNT(ht) != 2 || zend_get_parameters_ex(2, &arg1, &arg2) == FAILURE) { WRONG_PARAM_COUNT; } @@ -705,14 +751,14 @@ PHP_FUNCTION(pclose) pval **arg1; void *what; FLS_FETCH(); - + if (ARG_COUNT(ht) != 1 || zend_get_parameters_ex(1, &arg1) == FAILURE) { WRONG_PARAM_COUNT; } what = zend_fetch_resource(arg1,-1,"File-Handle",NULL,1,le_popen); ZEND_VERIFY_RESOURCE(what); - + zend_list_delete((*arg1)->value.lval); RETURN_LONG(FG(pclose_ret)); } @@ -728,23 +774,35 @@ PHP_FUNCTION(feof) int issock=0; int socketd=0; void *what; - + if (ARG_COUNT(ht) != 1 || zend_get_parameters_ex(1, &arg1) == FAILURE) { WRONG_PARAM_COUNT; } - what = zend_fetch_resource(arg1,-1,"File-Handle",&type,3,le_fopen,le_popen,le_socket); + what = zend_fetch_resource(arg1, -1, "File-Handle", &type, 4, le_fopen, le_popen, le_socket, le_stream); ZEND_VERIFY_RESOURCE(what); if (type == le_socket) { issock=1; socketd=*(int *) what; - } + } - if (FP_FEOF(socketd, (FILE*)what, issock)) { - RETURN_TRUE; - } else { +#if HAVE_PHP_STREAM + if (type == le_stream) { + if (php_stream_eof((php_stream*)what)) + { + RETURN_TRUE; + } RETURN_FALSE; } + else +#endif + { + if (FP_FEOF(socketd, (FILE*)what, issock)) { + RETURN_TRUE; + } else { + RETURN_FALSE; + } + } } /* }}} */ @@ -756,7 +814,7 @@ PHPAPI int php_set_sock_blocking(int socketd, int block) int ret = SUCCESS; int flags; int myflag = 0; - + #ifdef PHP_WIN32 /* with ioctlsocket, a non-zero sets nonblocking, a zero sets blocking */ flags = !block; @@ -784,27 +842,35 @@ PHPAPI int php_set_sock_blocking(int socketd, int block) PHP_FUNCTION(socket_set_blocking) { pval **arg1, **arg2; - int block; + int block, type; int socketd = 0; void *what; - + if (ARG_COUNT(ht) != 2 || zend_get_parameters_ex(2, &arg1, &arg2) == FAILURE) { WRONG_PARAM_COUNT; } - what = zend_fetch_resource(arg1,-1,"File-Handle",NULL,1,le_socket); + what = zend_fetch_resource(arg1, -1, "File-Handle", &type, 2, le_socket, le_stream); ZEND_VERIFY_RESOURCE(what); convert_to_long_ex(arg2); block = (*arg2)->value.lval; - - socketd = *(int*)what; + if (type == le_socket) { + socketd = *(int*)what; + } +#if HAVE_PHP_STREAM + else if (type == le_stream) { + if (php_stream_cast((php_stream*)what, PHP_STREAM_AS_SOCKETD, (void*)&socketd, 1) == FAILURE) { + RETURN_FALSE; + } + } +#endif if (php_set_sock_blocking(socketd, block) == FAILURE) RETURN_FALSE; php_sockset_blocking(socketd, block == 0 ? 0 : 1); - + RETURN_TRUE; } @@ -831,11 +897,11 @@ PHP_FUNCTION(socket_set_timeout) zend_get_parameters_ex(ZEND_NUM_ARGS(), &socket, &seconds, µseconds)==FAILURE) { WRONG_PARAM_COUNT; } - + /* XXX: add stream support --Wez. */ what = zend_fetch_resource(socket, -1, "File-Handle", &type, 1, le_socket); ZEND_VERIFY_RESOURCE(what); socketd = *(int *)what; - + convert_to_long_ex(seconds); t.tv_sec = (*seconds)->value.lval; @@ -868,6 +934,7 @@ PHP_FUNCTION(socket_get_status) if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(ZEND_NUM_ARGS(), &socket) == FAILURE) { WRONG_PARAM_COUNT; } + /* XXX: add stream support --Wez. */ what = zend_fetch_resource(socket, -1, "File-Handle", &type, 1, le_socket); ZEND_VERIFY_RESOURCE(what); @@ -896,12 +963,12 @@ PHP_FUNCTION(fgets) int socketd=0; void *what; PLS_FETCH(); - + if (ARG_COUNT(ht) != 2 || zend_get_parameters_ex(2, &arg1, &arg2) == FAILURE) { WRONG_PARAM_COUNT; } - what = zend_fetch_resource(arg1,-1,"File-Handle",&type,3,le_fopen,le_popen,le_socket); + what = zend_fetch_resource(arg1, -1, "File-Handle", &type, 4, le_fopen, le_popen, le_socket, le_stream); ZEND_VERIFY_RESOURCE(what); convert_to_long_ex(arg2); @@ -920,27 +987,44 @@ PHP_FUNCTION(fgets) buf = emalloc(sizeof(char) * (len + 1)); /* needed because recv doesnt put a null at the end*/ memset(buf,0,len+1); -#ifdef HAVE_FLUSHIO - if (type == le_fopen) { - fseek((FILE*)what, 0, SEEK_CUR); + +#if HAVE_PHP_STREAM + if (type == le_stream) { + if (php_stream_gets((php_stream*)what, buf, len) == NULL) + goto exit_failed; } + else #endif - if (FP_FGETS(buf, len, socketd, (FILE*)what, issock) == NULL) { - efree(buf); - RETVAL_FALSE; + { + if (type == le_socket) { + issock=1; + socketd=*(int*)what; + } +#ifdef HAVE_FLUSHIO + if (type == le_fopen) { + fseek((FILE*)what, 0, SEEK_CUR); + } +#endif + if (FP_FGETS(buf, len, socketd, (FILE*)what, issock) == NULL) + goto exit_failed; + } + + if (PG(magic_quotes_runtime)) { + return_value->value.str.val = php_addslashes(buf,0,&return_value->value.str.len,1); } else { - if (PG(magic_quotes_runtime)) { - return_value->value.str.val = php_addslashes(buf,0,&return_value->value.str.len,1); - } else { - return_value->value.str.val = buf; - return_value->value.str.len = strlen(return_value->value.str.val); - /* resize buffer if it's much larger than the result */ - if(return_value->value.str.len < len/2) { - return_value->value.str.val = erealloc(buf,return_value->value.str.len+1); - } + return_value->value.str.val = buf; + return_value->value.str.len = strlen(return_value->value.str.val); + /* resize buffer if it's much larger than the result */ + if(return_value->value.str.len < len/2) { + return_value->value.str.val = erealloc(buf,return_value->value.str.len+1); } - return_value->type = IS_STRING; } + return_value->type = IS_STRING; + return; + +exit_failed: + RETVAL_FALSE; + efree(buf); } /* }}} */ @@ -955,12 +1039,12 @@ PHP_FUNCTION(fgetc) { int socketd=0; void *what; int result; - + if (ARG_COUNT(ht) != 1 || zend_get_parameters_ex(1, &arg1) == FAILURE) { WRONG_PARAM_COUNT; } - what = zend_fetch_resource(arg1,-1,"File-Handle",&type,3,le_fopen,le_popen,le_socket); + what = zend_fetch_resource(arg1, -1, "File-Handle", &type, 4, le_fopen, le_popen, le_socket, le_stream); ZEND_VERIFY_RESOURCE(what); if (type == le_socket) { @@ -974,14 +1058,24 @@ PHP_FUNCTION(fgetc) { } #endif buf = emalloc(sizeof(int)); - if ((result = FP_FGETC(socketd, (FILE*)what, issock)) == EOF) { + +#if HAVE_PHP_STREAM + if (type == le_stream) { + result = php_stream_getc((php_stream*)what); + } + else +#endif + result = FP_FGETC(socketd, (FILE*)what, issock); + + + if (result == EOF) { efree(buf); RETVAL_FALSE; } else { buf[0]=result; buf[1]='\0'; - return_value->value.str.val = buf; - return_value->value.str.len = 1; + return_value->value.str.val = buf; + return_value->value.str.len = 1; return_value->type = IS_STRING; } } @@ -1023,7 +1117,7 @@ PHP_FUNCTION(fgetss) break; } - what = zend_fetch_resource(fd,-1,"File-Handle",&type,3,le_fopen,le_popen,le_socket); + what = zend_fetch_resource(fd, -1, "File-Handle", &type, 4, le_fopen, le_popen, le_socket, le_stream); ZEND_VERIFY_RESOURCE(what); if (type == le_socket) { @@ -1041,6 +1135,16 @@ PHP_FUNCTION(fgetss) buf = emalloc(sizeof(char) * (len + 1)); /*needed because recv doesnt set null char at end*/ memset(buf, 0, len + 1); + +#if HAVE_PHP_STREAM + if (type == le_stream) { + if (php_stream_gets((php_stream*)what, buf, len) == NULL) { + efree(buf); + RETURN_FALSE; + } + } + else +#endif if (FP_FGETS(buf, len, socketd, (FILE*)what, issock) == NULL) { efree(buf); RETURN_FALSE; @@ -1057,64 +1161,75 @@ PHP_FUNCTION(fgetss) Implements a mostly ANSI compatible fscanf() */ PHP_FUNCTION(fscanf) { - int result; - pval **file_handle, **format_string; - int len, type; - char *buf; - int issock=0; - int socketd=0; - void *what; - - zval ***args; - int argCount; - - argCount = ZEND_NUM_ARGS(); - if (argCount < 2) { - WRONG_PARAM_COUNT; - } - args = (zval ***)emalloc(argCount * sizeof(zval **)); - if (!args || (zend_get_parameters_array_ex(argCount,args) == FAILURE)) { - efree( args ); - WRONG_PARAM_COUNT; - } - - file_handle = args[0]; - format_string = args[1]; - - what = zend_fetch_resource(file_handle,-1,"File-Handle",&type,3,le_fopen,le_popen,le_socket); - - /* - * we can't do a ZEND_VERIFY_RESOURCE(what), otherwise we end up - * with a leak if we have an invalid filehandle. This needs changing - * if the code behind ZEND_VERIFY_RESOURCE changed. - cc - */ - if (!what) { - efree(args); - RETURN_FALSE; - } + int result; + pval **file_handle, **format_string; + int len, type; + char *buf; + int issock=0; + int socketd=0; + void *what; - len = SCAN_MAX_FSCANF_BUFSIZE; + zval ***args; + int argCount; - if (type == le_socket) { - issock=1; - socketd=*(int*)what; - } - buf = emalloc(sizeof(char) * (len + 1)); - /* needed because recv doesnt put a null at the end*/ - memset(buf,0,len+1); - if (FP_FGETS(buf, len, socketd, (FILE*)what, issock) == NULL) { - efree(buf); - RETVAL_FALSE; - } else { - convert_to_string_ex( format_string ); - result = php_sscanf_internal( buf,(*format_string)->value.str.val, - argCount,args, 2,&return_value); - efree(args); - efree(buf); - if (SCAN_ERROR_WRONG_PARAM_COUNT == result) { - WRONG_PARAM_COUNT - } - } + argCount = ZEND_NUM_ARGS(); + if (argCount < 2) { + WRONG_PARAM_COUNT; + } + args = (zval ***)emalloc(argCount * sizeof(zval **)); + if (!args || (zend_get_parameters_array_ex(argCount,args) == FAILURE)) { + efree( args ); + WRONG_PARAM_COUNT; + } + + file_handle = args[0]; + format_string = args[1]; + + what = zend_fetch_resource(file_handle, -1, "File-Handle", &type, 4, le_fopen, le_popen, le_socket, le_stream); + + /* + * we can't do a ZEND_VERIFY_RESOURCE(what), otherwise we end up + * with a leak if we have an invalid filehandle. This needs changing + * if the code behind ZEND_VERIFY_RESOURCE changed. - cc + */ + if (!what) { + efree(args); + RETURN_FALSE; + } + + len = SCAN_MAX_FSCANF_BUFSIZE; + + if (type == le_socket) { + issock=1; + socketd=*(int*)what; + } + buf = emalloc(sizeof(char) * (len + 1)); + /* needed because recv doesnt put a null at the end*/ + memset(buf,0,len+1); + +#if HAVE_PHP_STREAM + if (type == le_stream) { + if (php_stream_gets((php_stream*)what, buf, len) == NULL) { + efree(buf); + RETURN_FALSE; + } + } + else +#endif + + if (FP_FGETS(buf, len, socketd, (FILE*)what, issock) == NULL) { + efree(buf); + RETURN_FALSE; + } + + convert_to_string_ex( format_string ); + result = php_sscanf_internal( buf,(*format_string)->value.str.val, + argCount,args, 2,&return_value); + efree(args); + efree(buf); + if (SCAN_ERROR_WRONG_PARAM_COUNT == result) { + WRONG_PARAM_COUNT + } } @@ -1153,9 +1268,10 @@ PHP_FUNCTION(fwrite) WRONG_PARAM_COUNT; /* NOTREACHED */ break; - } + } - what = zend_fetch_resource(arg1,-1,"File-Handle",&type,3,le_fopen,le_popen,le_socket); + what = zend_fetch_resource(arg1, -1, "File-Handle", &type, 4, le_fopen, + le_popen, le_socket, le_stream); ZEND_VERIFY_RESOURCE(what); if (type == le_socket) { @@ -1168,6 +1284,13 @@ PHP_FUNCTION(fwrite) php_stripslashes((*arg2)->value.str.val,&num_bytes); } +#if HAVE_PHP_STREAM + if (type == le_stream) { + ret = php_stream_write((php_stream*)what, Z_STRVAL_PP(arg2), num_bytes); + } + else +#endif + if (issock){ ret = SOCK_WRITEL((*arg2)->value.str.val,num_bytes,socketd); } else { @@ -1181,7 +1304,7 @@ PHP_FUNCTION(fwrite) RETURN_LONG(ret); } -/* }}} */ +/* }}} */ /* {{{ proto int fflush(int fp) Flushes output */ @@ -1197,9 +1320,19 @@ PHP_FUNCTION(fflush) WRONG_PARAM_COUNT; } - what = zend_fetch_resource(arg1,-1,"File-Handle",&type,3,le_fopen,le_popen,le_socket); + what = zend_fetch_resource(arg1,-1,"File-Handle",&type,4,le_fopen,le_popen,le_socket, le_stream); ZEND_VERIFY_RESOURCE(what); +#if HAVE_PHP_STREAM + if (type == le_stream) { + ret = php_stream_flush((php_stream*)what); + if (ret) { + RETURN_FALSE; + } + RETURN_TRUE; + } +#endif + if (type == le_socket) { issock=1; socketd=*(int*)what; @@ -1218,7 +1351,7 @@ PHP_FUNCTION(fflush) } } -/* }}} */ +/* }}} */ /* {{{ proto int set_file_buffer(int fp, int buffer) Set file write buffer */ @@ -1227,24 +1360,26 @@ PHP_FUNCTION(set_file_buffer) pval **arg1, **arg2; int ret,type,buff; void *what; - + switch (ARG_COUNT(ht)) { case 2: if (zend_get_parameters_ex(2, &arg1, &arg2)==FAILURE) { RETURN_FALSE; - } + } break; default: WRONG_PARAM_COUNT; /* NOTREACHED */ break; - } + } + + /* XXX: add stream support --Wez. */ what = zend_fetch_resource(arg1,-1,"File-Handle",&type,2,le_fopen,le_popen); ZEND_VERIFY_RESOURCE(what); convert_to_long_ex(arg2); - buff = (*arg2)->value.lval; + buff = (*arg2)->value.lval; /* if buff is 0 then set to non-buffered */ if (buff == 0){ @@ -1256,7 +1391,7 @@ PHP_FUNCTION(set_file_buffer) RETURN_LONG(ret); } -/* }}} */ +/* }}} */ /* {{{ proto int rewind(int fp) Rewind the position of a file pointer */ @@ -1264,14 +1399,15 @@ PHP_FUNCTION(rewind) { pval **arg1; void *what; - + if (ARG_COUNT(ht) != 1 || zend_get_parameters_ex(1, &arg1) == FAILURE) { WRONG_PARAM_COUNT; } - + /* XXX: add stream support --Wez. */ + what = zend_fetch_resource(arg1,-1,"File-Handle",NULL,2,le_fopen,le_popen); ZEND_VERIFY_RESOURCE(what); - + rewind((FILE*) what); RETURN_TRUE; } @@ -1285,19 +1421,20 @@ PHP_FUNCTION(ftell) pval **arg1; void *what; long ret; - + if (ARG_COUNT(ht) != 1 || zend_get_parameters_ex(1, &arg1) == FAILURE) { WRONG_PARAM_COUNT; } - + /* XXX: add stream support --Wez. */ + what = zend_fetch_resource(arg1,-1,"File-Handle",NULL,2,le_fopen,le_popen); ZEND_VERIFY_RESOURCE(what); ret = ftell((FILE*) what); if(ret == -1) { RETURN_FALSE; - } - + } + RETURN_LONG(ret); } @@ -1310,12 +1447,13 @@ PHP_FUNCTION(fseek) zval **arg1, **arg2, **arg3; int argcount = ARG_COUNT(ht), whence = SEEK_SET; void *what; - + if (argcount < 2 || argcount > 3 || zend_get_parameters_ex(argcount, &arg1, &arg2, &arg3) == FAILURE) { WRONG_PARAM_COUNT; } - + /* XXX: add stream support --Wez. */ + what = zend_fetch_resource(arg1,-1,"File-Handle",NULL,2,le_fopen,le_popen); ZEND_VERIFY_RESOURCE(what); @@ -1324,7 +1462,7 @@ PHP_FUNCTION(fseek) convert_to_long_ex(arg3); whence = (*arg3)->value.lval; } - + RETURN_LONG(fseek((FILE*)what, (*arg2)->value.lval, whence)); } @@ -1338,7 +1476,7 @@ PHP_FUNCTION(mkdir) int ret; mode_t mode; PLS_FETCH(); - + if (ARG_COUNT(ht) != 2 || zend_get_parameters_ex(2, &arg1, &arg2) == FAILURE) { WRONG_PARAM_COUNT; } @@ -1356,7 +1494,7 @@ PHP_FUNCTION(mkdir) RETURN_TRUE; } -/* }}} */ +/* }}} */ /* {{{ proto int rmdir(string dirname) Remove a directory */ @@ -1365,7 +1503,7 @@ PHP_FUNCTION(rmdir) pval **arg1; int ret; PLS_FETCH(); - + if (ARG_COUNT(ht) != 1 || zend_get_parameters_ex(1, &arg1) == FAILURE) { WRONG_PARAM_COUNT; } @@ -1381,7 +1519,7 @@ PHP_FUNCTION(rmdir) RETURN_TRUE; } -/* }}} */ +/* }}} */ /* {{{ php_passthru_fd */ static size_t php_passthru_fd(int socketd, FILE *fp, int issock) @@ -1389,8 +1527,9 @@ static size_t php_passthru_fd(int socketd, FILE *fp, int issock) size_t bcount = 0; int ready = 0; char buf[8192]; - -#ifdef HAVE_MMAP + /* XXX: add stream support --Wez. */ + +#ifdef HAVE_MMAP if(!issock) { int fd; struct stat sbuf; @@ -1400,7 +1539,7 @@ static size_t php_passthru_fd(int socketd, FILE *fp, int issock) fd = fileno(fp); fstat(fd, &sbuf); - + if (sbuf.st_size > sizeof(buf)) { off = ftell(fp); len = sbuf.st_size - off; @@ -1423,7 +1562,7 @@ static size_t php_passthru_fd(int socketd, FILE *fp, int issock) bcount += b; } } - + return bcount; } @@ -1439,7 +1578,7 @@ PHP_FUNCTION(readfile) int use_include_path=0; int issock=0, socketd=0; int rsrc_id; - + /* check args */ switch (ARG_COUNT(ht)) { case 1: @@ -1498,7 +1637,7 @@ PHP_FUNCTION(umask) pval **arg1; int oldumask; int arg_count = ARG_COUNT(ht); - + oldumask = umask(077); if (arg_count == 0) { @@ -1527,11 +1666,12 @@ PHP_FUNCTION(fpassthru) int issock=0; int socketd=0; void *what; - + if (ARG_COUNT(ht) != 1 || zend_get_parameters_ex(1, &arg1) == FAILURE) { WRONG_PARAM_COUNT; } + /* XXX: add stream support --Wez. */ what = zend_fetch_resource(arg1,-1,"File-Handle",&type,3,le_fopen,le_popen,le_socket); ZEND_VERIFY_RESOURCE(what); @@ -1556,7 +1696,7 @@ PHP_FUNCTION(rename) char *old_name, *new_name; int ret; PLS_FETCH(); - + if (ARG_COUNT(ht) != 2 || zend_get_parameters_ex(2, &old_arg, &new_arg) == FAILURE) { WRONG_PARAM_COUNT; } @@ -1589,7 +1729,7 @@ PHP_FUNCTION(unlink) pval **filename; int ret; PLS_FETCH(); - + if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &filename) == FAILURE) { WRONG_PARAM_COUNT; } @@ -1623,7 +1763,8 @@ PHP_NAMED_FUNCTION(php_if_ftruncate) if (ARG_COUNT(ht) != 2 || zend_get_parameters_ex(2, &fp, &size) == FAILURE) { WRONG_PARAM_COUNT; } - + /* XXX: add stream support --Wez. */ + what = zend_fetch_resource(fp,-1,"File-Handle",&type,3,le_fopen,le_popen,le_socket); ZEND_VERIFY_RESOURCE(what); @@ -1652,6 +1793,7 @@ PHP_NAMED_FUNCTION(php_if_fstat) if (ARG_COUNT(ht) != 1 || zend_get_parameters_ex(1, &fp) == FAILURE) { WRONG_PARAM_COUNT; } + /* XXX: add stream support --Wez. */ what = zend_fetch_resource(fp,-1,"File-Handle",&type,3,le_fopen,le_popen,le_socket); ZEND_VERIFY_RESOURCE(what); @@ -1675,7 +1817,7 @@ PHP_NAMED_FUNCTION(php_if_fstat) #ifdef HAVE_ST_BLKSIZE add_assoc_long ( return_value , "blksize" , stat_sb.st_blksize ); #endif - + add_assoc_long ( return_value , "size" , stat_sb.st_size ); add_assoc_long ( return_value , "atime" , stat_sb.st_atime ); add_assoc_long ( return_value , "mtime" , stat_sb.st_mtime ); @@ -1770,12 +1912,12 @@ PHPAPI int php_copy_file(char *src, char *dest) } } ret = SUCCESS; - + cleanup: close(fd_s); close(fd_t); return ret; -} +} @@ -1791,10 +1933,11 @@ PHP_FUNCTION(fread) int socketd=0; void *what; PLS_FETCH(); - + if (ARG_COUNT(ht) != 2 || zend_get_parameters_ex(2, &arg1, &arg2) == FAILURE) { WRONG_PARAM_COUNT; } + /* XXX: add stream support --Wez. */ what = zend_fetch_resource(arg1,-1,"File-Handle",&type,3,le_fopen,le_popen,le_socket); ZEND_VERIFY_RESOURCE(what); @@ -1813,7 +1956,7 @@ PHP_FUNCTION(fread) return_value->value.str.val = emalloc(sizeof(char) * (len + 1)); /* needed because recv doesnt put a null at the end*/ - + if (!issock) { #ifdef HAVE_FLUSHIO if (type == le_fopen) { @@ -1834,7 +1977,7 @@ PHP_FUNCTION(fread) /* }}} */ /* {{{ proto array fgetcsv(int fp, int length [, string delimiter]) Get line from file pointer and parse for CSV fields */ - + PHP_FUNCTION(fgetcsv) { char *temp, *tptr, *bptr, *lineEnd; char delimiter = ','; /* allow this to be set as parameter */ @@ -1847,14 +1990,14 @@ PHP_FUNCTION(fgetcsv) { int issock=0; int socketd=0; void *what; - + switch(ARG_COUNT(ht)) { case 2: if (zend_get_parameters_ex(2, &fd, &bytes) == FAILURE) { WRONG_PARAM_COUNT; } break; - + case 3: if (zend_get_parameters_ex(3, &fd, &bytes, &p_delim) == FAILURE) { WRONG_PARAM_COUNT; @@ -1867,12 +2010,13 @@ PHP_FUNCTION(fgetcsv) { /* use first character from string */ delimiter = (*p_delim)->value.str.val[0]; break; - + default: WRONG_PARAM_COUNT; /* NOTREACHED */ break; } + /* XXX: add stream support --Wez. */ what = zend_fetch_resource(fd,-1,"File-Handle",&type,3,le_fopen,le_popen,le_socket); ZEND_VERIFY_RESOURCE(what); @@ -1884,10 +2028,10 @@ PHP_FUNCTION(fgetcsv) { convert_to_long_ex(bytes); len = (*bytes)->value.lval; - if (len < 0) { + if (len < 0) { php_error(E_WARNING, "length parameter to fgetcsv() may not be negative"); RETURN_FALSE; - } + } buf = emalloc(sizeof(char) * (len + 1)); /*needed because recv doesnt set null char at end*/ @@ -1902,11 +2046,11 @@ PHP_FUNCTION(fgetcsv) { /* Strip trailing space from buf, saving end of line in case required for quoted field */ lineEnd = emalloc(sizeof(char) * (len + 1)); - bptr = buf; - tptr = buf + strlen(buf) -1; - while ( isspace((int)*tptr) && (*tptr!=delimiter) && (tptr > bptr) ) tptr--; - tptr++; - strcpy(lineEnd, tptr); + bptr = buf; + tptr = buf + strlen(buf) -1; + while ( isspace((int)*tptr) && (*tptr!=delimiter) && (tptr > bptr) ) tptr--; + tptr++; + strcpy(lineEnd, tptr); /* add single space - makes it easier to parse trailing null field */ *tptr++ = ' '; @@ -1929,8 +2073,8 @@ PHP_FUNCTION(fgetcsv) { /* NB this routine will return a single null entry for a blank line */ do { - /* 1. Strip any leading space */ - while(isspace((int)*bptr) && (*bptr!=delimiter)) bptr++; + /* 1. Strip any leading space */ + while(isspace((int)*bptr) && (*bptr!=delimiter)) bptr++; /* 2. Read field, leaving bptr pointing at start of next field */ if (*bptr == '"') { /* 2A. handle quote delimited field */ @@ -1952,26 +2096,26 @@ PHP_FUNCTION(fgetcsv) { /* normal character */ *tptr++ = *bptr++; - if (*bptr == 0) { /* embedded line end? */ - *(tptr-1)=0; /* remove space character added on reading line */ - strcat(temp,lineEnd); /* add the embedded line end to the field */ + if (*bptr == 0) { /* embedded line end? */ + *(tptr-1)=0; /* remove space character added on reading line */ + strcat(temp,lineEnd); /* add the embedded line end to the field */ - /* read a new line from input, as at start of routine */ - memset(buf,0,len+1); + /* read a new line from input, as at start of routine */ + memset(buf,0,len+1); if (FP_FGETS(buf, len, socketd, (FILE*)what, issock) == NULL) { - efree(lineEnd); efree(temp); efree(buf); - zval_dtor(return_value); - RETURN_FALSE; - } - bptr = buf; - tptr = buf + strlen(buf) -1; - while ( isspace((int)*tptr) && (*tptr!=delimiter) && (tptr > bptr) ) tptr--; - tptr++; strcpy(lineEnd, tptr); - *tptr++ = ' '; *tptr = 0; - - tptr=temp; /* reset temp pointer to end of field as read so far */ - while (*tptr) tptr++; - } + efree(lineEnd); efree(temp); efree(buf); + zval_dtor(return_value); + RETURN_FALSE; + } + bptr = buf; + tptr = buf + strlen(buf) -1; + while ( isspace((int)*tptr) && (*tptr!=delimiter) && (tptr > bptr) ) tptr--; + tptr++; strcpy(lineEnd, tptr); + *tptr++ = ' '; *tptr = 0; + + tptr=temp; /* reset temp pointer to end of field as read so far */ + while (*tptr) tptr++; + } } } } else { @@ -1988,7 +2132,7 @@ PHP_FUNCTION(fgetcsv) { add_next_index_string(return_value, temp, 1); tptr=temp; } while (*bptr); - + efree(lineEnd); efree(temp); efree(buf); @@ -2010,7 +2154,7 @@ PHP_FUNCTION(realpath) } convert_to_string_ex(path); - + if (V_REALPATH((*path)->value.str.val, resolved_path_buff)) { RETURN_STRING(resolved_path_buff, 1); } else { @@ -2028,50 +2172,52 @@ static int max_fd; PHP_FUNCTION(fd_set) { - pval **arg; - void *what; - int type, fd; - - if(ARG_COUNT(ht) <= 0) { - php_error(E_WARNING, "fd_set: Must be passed at least one value" ); - var_uninit(return_value); - return; - } - else if(ARG_COUNT(ht) == 1) { - if(zend_get_parameters_ex(1, &arg) == FAILURE) { - WRONG_PARAM_COUNT; - } - what = zend_fetch_resource(arg,-1,"select",&type,3,le_fopen,le_socket,le_popen); - ZEND_VERIFY_RESOURCE(what); - if(type == le_socket) { - fd = *(int *)what; - } else { - fd = fileno((FILE *)what); - } - max_fd = fd; - FD_ZERO(&readfd); - FD_SET(max_fd, &readfd); - } - else { - pval ***args = (pval ***) emalloc(sizeof(pval **) * ARG_COUNT(ht)); - int i; - if(zend_get_parameters_array_ex(ARG_COUNT(ht), args) == FAILURE) { - efree(args); - WRONG_PARAM_COUNT; - } - FD_ZERO(&readfd); - for(i = 0; i < ARG_COUNT(ht); i++) { - what = zend_fetch_resource(*args,-1,"select",&type,3,le_fopen,le_socket,le_popen); - ZEND_VERIFY_RESOURCE(what); - if(type == le_socket) { - fd = *(int *)what; - } else { - fd = fileno((FILE *)what); - } - FD_SET(fd, &readfd); - if(fd > max_fd) max_fd = fd; + pval **arg; + void *what; + int type, fd; + + if(ARG_COUNT(ht) <= 0) { + php_error(E_WARNING, "fd_set: Must be passed at least one value" ); + var_uninit(return_value); + return; + } + else if(ARG_COUNT(ht) == 1) { + if(zend_get_parameters_ex(1, &arg) == FAILURE) { + WRONG_PARAM_COUNT; } - efree(args); + /* XXX: add stream support --Wez. */ + what = zend_fetch_resource(arg,-1,"select",&type,3,le_fopen,le_socket,le_popen); + ZEND_VERIFY_RESOURCE(what); + if(type == le_socket) { + fd = *(int *)what; + } else { + fd = fileno((FILE *)what); + } + max_fd = fd; + FD_ZERO(&readfd); + FD_SET(max_fd, &readfd); + } + else { + pval ***args = (pval ***) emalloc(sizeof(pval **) * ARG_COUNT(ht)); + int i; + if(zend_get_parameters_array_ex(ARG_COUNT(ht), args) == FAILURE) { + efree(args); + WRONG_PARAM_COUNT; + } + FD_ZERO(&readfd); + for(i = 0; i < ARG_COUNT(ht); i++) { + /* XXX: add stream support --Wez. */ + what = zend_fetch_resource(*args,-1,"select",&type,3,le_fopen,le_socket,le_popen); + ZEND_VERIFY_RESOURCE(what); + if(type == le_socket) { + fd = *(int *)what; + } else { + fd = fileno((FILE *)what); + } + FD_SET(fd, &readfd); + if(fd > max_fd) max_fd = fd; + } + efree(args); } RETURN_LONG(1); } @@ -2089,6 +2235,7 @@ PHP_FUNCTION(select) tv.tv_sec = (*timeout)->value.lval / 1000000; tv.tv_usec = (*timeout)->value.lval % 1000000; + /* XXX: add stream support --Wez. */ RETURN_LONG(select(max_fd + 1,&readfd,NULL,NULL,((*timeout)->value.lval <= 0) ? NULL : &tv)); } @@ -2102,6 +2249,7 @@ PHP_FUNCTION(fd_isset) if(ARG_COUNT(ht) != 1 || zend_get_parameters_ex(1, &fdarg) == FAILURE) { WRONG_PARAM_COUNT; } + /* XXX: add stream support --Wez. */ what = zend_fetch_resource(fdarg,-1,"select",&type,3,le_fopen,le_socket,le_popen); ZEND_VERIFY_RESOURCE(what); @@ -2114,9 +2262,9 @@ PHP_FUNCTION(fd_isset) if(FD_ISSET(fd,&readfd)) { RETURN_TRUE; - } + } RETURN_FALSE; -} +} #endif @@ -2127,9 +2275,10 @@ size_t php_fread_all(char **buf, int socket, FILE *fp, int issock) { size_t len = 0, max_len; int step = PHP_FSOCK_CHUNK_SIZE; int min_room = PHP_FSOCK_CHUNK_SIZE/4; - + ptr = *buf = emalloc(step); max_len = step; + /* XXX: add stream support --Wez. */ while((ret = FP_FREAD(ptr, max_len - len, socket, fp, issock))) { len += ret; @@ -2193,7 +2342,7 @@ php_meta_tags_token php_next_meta_token(FILE *fp, int socketd, int issock, int * if (*datalen == META_DEF_BUFSIZE) break; } - + *data = (char *) emalloc( *datalen + 1 ); memcpy(*data,buff,*datalen+1); diff --git a/ext/standard/file.h b/ext/standard/file.h index 8af3bc79cd..2c54abf04b 100644 --- a/ext/standard/file.h +++ b/ext/standard/file.h @@ -67,6 +67,10 @@ PHP_FUNCTION(realpath); PHP_NAMED_FUNCTION(php_if_ftruncate); PHP_NAMED_FUNCTION(php_if_fstat); +/* temporary function for testing streams */ +PHP_FUNCTION(fopenstream); + + PHPAPI int php_set_sock_blocking(int socketd, int block); PHPAPI int php_file_le_fopen(void); PHPAPI int php_file_le_popen(void); diff --git a/ext/standard/fsock.c b/ext/standard/fsock.c index 00ecbc0003..a3a8bf4ee1 100644 --- a/ext/standard/fsock.c +++ b/ext/standard/fsock.c @@ -204,7 +204,7 @@ PHPAPI int connect_nonb(int sockfd, /* }}} */ /* {{{ php_fsockopen() */ -/* +/* This function takes an optional third argument which should be passed by reference. The error code from the connect call is written to this variable. @@ -221,7 +221,7 @@ static void php_fsockopen(INTERNAL_FUNCTION_PARAMETERS, int persistent) { unsigned long conv; char *key = NULL; FLS_FETCH(); - + if (arg_count > 5 || arg_count < 2 || zend_get_parameters_array_ex(arg_count,args)==FAILURE) { CLOSE_SOCK(1); WRONG_PARAM_COUNT; @@ -256,7 +256,7 @@ static void php_fsockopen(INTERNAL_FUNCTION_PARAMETERS, int persistent) { ZEND_REGISTER_RESOURCE(return_value,sock,php_file_le_socket()); return; } - + if (portno) { struct sockaddr_in server; @@ -264,23 +264,23 @@ static void php_fsockopen(INTERNAL_FUNCTION_PARAMETERS, int persistent) { if(Z_STRLEN_PP(args[0]) >= 6 && !memcmp(Z_STRVAL_PP(args[0]), "udp://", sizeof("udp://")-1)) { udp = 1; } - + socketd = socket(AF_INET,udp ? SOCK_DGRAM : SOCK_STREAM,0); if (socketd == SOCK_ERR) { CLOSE_SOCK(1); RETURN_FALSE; } - + server.sin_family = AF_INET; - + if(php_lookup_hostname(udp ? &(*args[0])->value.str.val[6] : (*args[0])->value.str.val,&server.sin_addr)) { CLOSE_SOCK(1); RETURN_FALSE; } - + server.sin_port = htons(portno); - + if (connect_nonb(socketd, (struct sockaddr *)&server, sizeof(server), &timeout) == SOCK_CONN_ERR) { CLOSE_SOCK(1); @@ -303,7 +303,7 @@ static void php_fsockopen(INTERNAL_FUNCTION_PARAMETERS, int persistent) { CLOSE_SOCK(1); RETURN_FALSE; } - + memset(&unix_addr, (char)0, sizeof(unix_addr)); unix_addr.sun_family = AF_UNIX; strlcpy(unix_addr.sun_path, (*args[0])->value.str.val, sizeof(unix_addr.sun_path)); @@ -328,7 +328,7 @@ static void php_fsockopen(INTERNAL_FUNCTION_PARAMETERS, int persistent) { RETURN_LONG(-6); /* FIXME */ } -#ifdef HAVE_SETVBUF +#ifdef HAVE_SETVBUF if ((setvbuf(fp, NULL, _IONBF, 0)) != 0){ RETURN_LONG(-7); /* FIXME */ } @@ -337,7 +337,7 @@ static void php_fsockopen(INTERNAL_FUNCTION_PARAMETERS, int persistent) { *sock=socketd; if (persistent) { - zend_hash_update(&FG(ht_fsock_keys), key, strlen(key) + 1, + zend_hash_update(&FG(ht_fsock_keys), key, strlen(key) + 1, sock, sizeof(*sock), NULL); zend_hash_update(&FG(ht_fsock_socks), (char *) sock, sizeof(*sock), key, strlen(key) + 1, NULL); @@ -350,14 +350,14 @@ static void php_fsockopen(INTERNAL_FUNCTION_PARAMETERS, int persistent) { /* {{{ proto int fsockopen(string hostname, int port [, int errno [, string errstr [, double timeout]]]) Open Internet or Unix domain socket connection */ -PHP_FUNCTION(fsockopen) +PHP_FUNCTION(fsockopen) { php_fsockopen(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0); } /* }}} */ /* {{{ proto int pfsockopen(string hostname, int port [, int errno [, string errstr [, double timeout]]]) Open persistent Internet or Unix domain socket connection */ -PHP_FUNCTION(pfsockopen) +PHP_FUNCTION(pfsockopen) { php_fsockopen(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1); } @@ -396,7 +396,7 @@ static php_sockbuf *php_sockfind(int socket FLS_DC) { php_sockbuf *buf = NULL, *tmp; - for(tmp = FG(phpsockbuf); tmp; tmp = tmp->next) + for(tmp = FG(phpsockbuf); tmp; tmp = tmp->next) if(tmp->socket == socket) { buf = tmp; break; @@ -412,7 +412,7 @@ static php_sockbuf *php_sockcreate(int socket FLS_DC) sock = pecalloc(sizeof(*sock), 1, persistent); sock->socket = socket; - if((sock->next = FG(phpsockbuf))) + if((sock->next = FG(phpsockbuf))) FG(phpsockbuf)->prev = sock; sock->persistent = persistent; sock->is_blocked = 1; @@ -436,7 +436,7 @@ PHPAPI size_t php_sock_set_def_chunk_size(size_t size) old = FG(def_chunk_size); - if(size <= PHP_FSOCK_CHUNK_SIZE || size > 0) + if(size <= PHP_FSOCK_CHUNK_SIZE || size > 0) FG(def_chunk_size) = size; return old; @@ -500,7 +500,7 @@ static void php_sockwait_for_data(php_sockbuf *sock) FD_SET(sock->socket, &fdr); sock->timeout_event = 0; - if (sock->timeout.tv_sec == -1) + if (sock->timeout.tv_sec == -1) ptimeout = NULL; else ptimeout = &timeout; @@ -510,7 +510,7 @@ static void php_sockwait_for_data(php_sockbuf *sock) timeout = sock->timeout; retval = select(sock->socket + 1, &tfdr, NULL, NULL, ptimeout); - + if (retval == 0) sock->timeout_event = 1; @@ -524,15 +524,15 @@ static size_t php_sockread_internal(php_sockbuf *sock) char buf[PHP_FSOCK_CHUNK_SIZE]; int nr_bytes; size_t nr_read = 0; - + /* For blocking sockets, we wait until there is some data to read (real data or EOF) - + Otherwise, recv() may time out and return 0 and therefore sock->eof would be set errornously. */ - + if(sock->is_blocked) { php_sockwait_for_data(sock); if (sock->timeout_event) @@ -569,7 +569,7 @@ static size_t php_sockread(php_sockbuf *sock) size_t nr_bytes; size_t nr_read = 0; int i; - + for(i = 0; !sock->eof && i < MAX_CHUNKS_PER_READ; i++) { nr_bytes = php_sockread_internal(sock); if(nr_bytes == 0) break; @@ -585,9 +585,9 @@ PHPAPI int php_sockset_blocking(int socket, int mode) SOCK_FIND(sock, socket); old = sock->is_blocked; - + sock->is_blocked = mode; - + return old; } @@ -632,13 +632,13 @@ PHPAPI char *php_sock_fgets(char *buf, size_t maxlen, int socket) } } - + if(p) { amount = (ptrdiff_t) p - (ptrdiff_t) READPTR(sock) + 1; } else { amount = TOREAD(sock); } - + amount = MIN(amount, maxlen); if(amount > 0) { @@ -646,8 +646,8 @@ PHPAPI char *php_sock_fgets(char *buf, size_t maxlen, int socket) sock->readpos += amount; } buf[amount] = '\0'; - - /* signal error only, if we don't return data from this call and + + /* signal error only, if we don't return data from this call and if there is no data to read and if the eof flag is set */ if(amount || TOREAD(sock) || !sock->eof) { ret = buf; @@ -685,8 +685,8 @@ PHPAPI int php_sock_feof(int socket) if(!sock->is_blocked) php_sockread(sock); - - if(!TOREAD(sock) && sock->eof) + + if(!TOREAD(sock) && sock->eof) ret = 1; return ret; @@ -699,7 +699,7 @@ PHPAPI size_t php_sock_fread(char *ptr, size_t size, int socket) size_t ret = 0; SOCK_FIND_AND_READ_MAX(size); - if(size < 0) + if(size < 0) return ret; ret = MIN(TOREAD(sock), size); @@ -722,6 +722,112 @@ PHPAPI void php_msock_destroy(int *data) /* }}} */ +/* {{{ stream abstraction */ +#if HAVE_PHP_STREAM +static size_t php_sockop_write(php_stream * stream, const char * buf, size_t count) +{ + int socket = (int)stream->abstract; + return send(socket, buf, count, 0); +} + +static void php_stream_sockwait_for_data(php_stream * stream) +{ + fd_set fdr, tfdr; + int retval, socket; + struct timeval timeout, *ptimeout; + + socket = (int)stream->abstract; + + FD_ZERO(&fdr); + FD_SET(socket, &fdr); + stream->timeout_event = 0; + + if (stream->timeout.tv_sec == -1) + ptimeout = NULL; + else + ptimeout = &timeout; + + while(1) { + tfdr = fdr; + timeout = stream->timeout; + + retval = select(socket + 1, &tfdr, NULL, NULL, ptimeout); + + if (retval == 0) + stream->timeout_event = 1; + + if (retval >= 0) + break; + } +} + +static size_t php_sockop_read(php_stream * stream, char * buf, size_t count) +{ + int socket = (int)stream->abstract; + + /* For blocking sockets, we wait until there is some + data to read (real data or EOF) + + Otherwise, recv() may time out and return 0 and + therefore sock->eof would be set errornously. + */ + + if (stream->is_blocked) { + php_stream_sockwait_for_data(stream); + if (stream->timeout_event) + return 0; + } + return recv(socket, buf, count, 0); +} + +static int php_sockop_close(php_stream * stream) +{ + int socket = (int)stream->abstract; + SOCK_CLOSE(socket); + return 0; +} + +static int php_sockop_flush(php_stream * stream) +{ + int socket = (int)stream->abstract; + return fsync(socket); +} + +static int php_sockop_cast(php_stream * stream, int castas, void ** ret) +{ + int socket = (int)stream->abstract; + + switch(castas) { + case PHP_STREAM_AS_STDIO: + if (ret) { + /* DANGER!: data buffered in stream->readbuf will be forgotten! */ + *ret = fdopen(socket, stream->mode); + if (*ret) + return SUCCESS; + return FAILURE; + } + return SUCCESS; + case PHP_STREAM_AS_FD: + case PHP_STREAM_AS_SOCKETD: + if (ret) + *ret = (void*)socket; + return SUCCESS; + default: + return FAILURE; + } +} + +php_stream_ops php_stream_socket_ops = { + php_sockop_write, php_sockop_read, + php_sockop_close, php_sockop_flush, + NULL, NULL, + php_sockop_cast, + "socket" +}; +#endif + +/* }}} */ + PHP_RSHUTDOWN_FUNCTION(fsock) { FLS_FETCH(); diff --git a/ext/standard/fsock.h b/ext/standard/fsock.h index 1418eb0908..f285306836 100644 --- a/ext/standard/fsock.h +++ b/ext/standard/fsock.h @@ -49,6 +49,10 @@ #define PHP_FSOCK_CHUNK_SIZE 8192 +#if HAVE_PHP_STREAM +extern php_stream_ops php_stream_socket_ops; +#endif + struct php_sockbuf { int socket; unsigned char *readbuf; diff --git a/ext/standard/info.c b/ext/standard/info.c index 055ff9aedb..e0233012c8 100644 --- a/ext/standard/info.c +++ b/ext/standard/info.c @@ -203,6 +203,11 @@ PHPAPI void php_print_info(int flag) #else php_info_print_table_row(2, "Thread Safety", "disabled" ); #endif + +#if HAVE_PHP_STREAM + php_info_print_table_row(2, "Experimental PHP Streams", "enabled"); +#endif + php_info_print_table_end(); /* Zend Engine */ |