/* cast as a socketd */
#define PHP_STREAM_AS_SOCKETD 2
-/* try really, really hard to make sure the cast happens (socketpair) */
+/* try really, really hard to make sure the cast happens (avoid using this flag if possible) */
#define PHP_STREAM_CAST_TRY_HARD 0x80000000
#define PHP_STREAM_CAST_RELEASE 0x40000000 /* stream becomes invalid on success */
#define PHP_STREAM_CAST_INTERNAL 0x20000000 /* stream cast for internal use */
#define PHP_STREAM_CRITICAL 3 /* an error occurred; origstream is in an unknown state; you should close origstream */
#define PHP_STREAM_NO_PREFERENCE 0
#define PHP_STREAM_PREFER_STDIO 1
+#define PHP_STREAM_FORCE_CONVERSION 2
/* DO NOT call this on streams that are referenced by resources! */
PHPAPI int _php_stream_make_seekable(php_stream *origstream, php_stream **newstream, int flags STREAMS_DC TSRMLS_DC);
#define php_stream_make_seekable(origstream, newstream, flags) _php_stream_make_seekable((origstream), (newstream), (flags) STREAMS_CC TSRMLS_CC)
#define STREAM_WRAPPER_PLAIN_FILES ((php_stream_wrapper*)-1)
+#undef HAVE_FOPENCOOKIE
+
/* {{{ some macros to help track leaks */
#if ZEND_DEBUG
#define emalloc_rel_orig(size) \
}
- if (stream->filterhead) {
+ if (stream->filterhead && (flags & PHP_STREAM_CAST_TRY_HARD) == 0) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "cannot cast a filtered stream on this system");
return FAILURE;
+ } else if (!stream->filterhead) {
+ if (stream->ops->cast && stream->ops->cast(stream, castas, ret TSRMLS_CC) == SUCCESS) {
+ goto exit_success;
+ }
}
-
- if (stream->ops->cast && stream->ops->cast(stream, castas, ret TSRMLS_CC) == SUCCESS)
- goto exit_success;
+ if ((flags & PHP_STREAM_CAST_TRY_HARD) && castas == PHP_STREAM_AS_STDIO) {
+ php_stream *newstream;
+
+ newstream = php_stream_fopen_tmpfile();
+ if (newstream) {
+ size_t copied = php_stream_copy_to_stream(stream, newstream, PHP_STREAM_COPY_ALL);
+
+ if (copied == 0) {
+ php_stream_close(newstream);
+ } else {
+ int retcode = php_stream_cast(newstream, castas | flags, ret, show_err TSRMLS_CC);
+
+ if (retcode == SUCCESS)
+ rewind((FILE*)*ret);
+
+ /* do some specialized cleanup */
+ if (flags & PHP_STREAM_CAST_RELEASE) {
+ php_stream_free(stream, PHP_STREAM_FREE_PRESERVE_HANDLE | PHP_STREAM_FREE_CLOSE);
+ }
+
+ return retcode;
+ }
+ }
+ }
+
if (show_err) {
/* these names depend on the values of the PHP_STREAM_AS_XXX defines in php_streams.h */
static const char *cast_names[3] = {
*newstream = NULL;
- if (origstream->ops->seek != NULL) {
+ if ((flags & PHP_STREAM_FORCE_CONVERSION == 0) && origstream->ops->seek != NULL) {
*newstream = origstream;
return PHP_STREAM_UNCHANGED;
}