Exemple #1
0
/* {{{ flatfile_store
 */
int flatfile_store(flatfile *dba, datum key_datum, datum value_datum, int mode TSRMLS_DC) {
	if (mode == FLATFILE_INSERT) {
		if (flatfile_findkey(dba, key_datum TSRMLS_CC)) {
			return 1;
		}
		php_stream_seek(dba->fp, 0L, SEEK_END);
		php_stream_printf(dba->fp TSRMLS_CC, "%zu\n", key_datum.dsize);
		php_stream_flush(dba->fp);
		if (php_stream_write(dba->fp, key_datum.dptr, key_datum.dsize) < key_datum.dsize) {
			return -1;
		}
		php_stream_printf(dba->fp TSRMLS_CC, "%zu\n", value_datum.dsize);
		php_stream_flush(dba->fp);
		if (php_stream_write(dba->fp, value_datum.dptr, value_datum.dsize) < value_datum.dsize) {
			return -1;
		}
	} else { /* FLATFILE_REPLACE */
		flatfile_delete(dba, key_datum TSRMLS_CC);
		php_stream_printf(dba->fp TSRMLS_CC, "%zu\n", key_datum.dsize);
		php_stream_flush(dba->fp);
		if (php_stream_write(dba->fp, key_datum.dptr, key_datum.dsize) < key_datum.dsize) {
			return -1;
		}
		php_stream_printf(dba->fp TSRMLS_CC, "%zu\n", value_datum.dsize);
		if (php_stream_write(dba->fp, value_datum.dptr, value_datum.dsize) < value_datum.dsize) {
			return -1;
		}
	}

	php_stream_flush(dba->fp);
	return 0;
}
Exemple #2
0
/* {{{ inifile_find_group
 * if found pos_grp_start points to "[group_name]"
 */
static int inifile_find_group(inifile *dba, const key_type *key, size_t *pos_grp_start)
{
	int ret = FAILURE;

	php_stream_flush(dba->fp);
	php_stream_seek(dba->fp, 0, SEEK_SET);
	inifile_line_free(&dba->curr);
	inifile_line_free(&dba->next);

	if (key->group && strlen(key->group)) {
		int res;
		line_type ln = {{NULL,NULL},{NULL}};

		res = 1;
		while(inifile_read(dba, &ln)) {
			if ((res=inifile_key_cmp(&ln.key, key)) < 2) {
				ret = SUCCESS;
				break;
			}
			*pos_grp_start = php_stream_tell(dba->fp);
		}
		inifile_line_free(&ln);
	} else {
		*pos_grp_start = 0;
		ret = SUCCESS;
	}
	if (ret == FAILURE) {
		*pos_grp_start = php_stream_tell(dba->fp);
	}
	return ret;
}
Exemple #3
0
static HRESULT STDMETHODCALLTYPE stm_commit(IStream *This, DWORD grfCommitFlags)
{
	FETCH_STM();

	php_stream_flush(stm->stream);

	return S_OK;
}
Exemple #4
0
/* {{{ flatfile_delete
 */
int flatfile_delete(flatfile *dba, datum key_datum TSRMLS_DC) {
	char *key = key_datum.dptr;
	size_t size = key_datum.dsize;
	size_t buf_size = FLATFILE_BLOCK_SIZE;
	char *buf = emalloc(buf_size);
	size_t num;
	size_t pos;

	php_stream_rewind(dba->fp);
	while(!php_stream_eof(dba->fp)) {
		/* read in the length of the key name */
		if (!php_stream_gets(dba->fp, buf, 15)) {
			break;
		}
		num = atoi(buf);
		if (num >= buf_size) {
			buf_size = num + FLATFILE_BLOCK_SIZE;
			buf = erealloc(buf, buf_size);
		}
		pos = php_stream_tell(dba->fp);

		/* read in the key name */
		num = php_stream_read(dba->fp, buf, num);
		if (num < 0)  {
			break;
		}

		if (size == num && !memcmp(buf, key, size)) {
			php_stream_seek(dba->fp, pos, SEEK_SET);
			php_stream_putc(dba->fp, 0);
			php_stream_flush(dba->fp);
			php_stream_seek(dba->fp, 0L, SEEK_END);
			efree(buf);
			return SUCCESS;
		}	

		/* read in the length of the value */
		if (!php_stream_gets(dba->fp, buf, 15)) {
			break;
		}
		num = atoi(buf);
		if (num >= buf_size) {
			buf_size = num + FLATFILE_BLOCK_SIZE;
			buf = erealloc(buf, buf_size);
		}
		/* read in the value */
		num = php_stream_read(dba->fp, buf, num);
		if (num < 0) {
			break;
		}
	}
	efree(buf);
	return FAILURE;
}	
Exemple #5
0
/* {{{ php_stream_cast */
PHPAPI int _php_stream_cast(php_stream *stream, int castas, void **ret, int show_err)
{
	int flags = castas & PHP_STREAM_CAST_MASK;
	castas &= ~PHP_STREAM_CAST_MASK;

	/* synchronize our buffer (if possible) */
	if (ret && castas != PHP_STREAM_AS_FD_FOR_SELECT) {
		php_stream_flush(stream);
		if (stream->ops->seek && (stream->flags & PHP_STREAM_FLAG_NO_SEEK) == 0) {
			zend_off_t dummy;

			stream->ops->seek(stream, stream->position, SEEK_SET, &dummy);
			stream->readpos = stream->writepos = 0;
		}
	}

	/* filtered streams can only be cast as stdio, and only when fopencookie is present */

	if (castas == PHP_STREAM_AS_STDIO) {
		if (stream->stdiocast) {
			if (ret) {
				*(FILE**)ret = stream->stdiocast;
			}
			goto exit_success;
		}

		/* if the stream is a stdio stream let's give it a chance to respond
		 * first, to avoid doubling up the layers of stdio with an fopencookie */
		if (php_stream_is(stream, PHP_STREAM_IS_STDIO) &&
			stream->ops->cast &&
			!php_stream_is_filtered(stream) &&
			stream->ops->cast(stream, castas, ret) == SUCCESS
		) {
			goto exit_success;
		}

#if HAVE_FOPENCOOKIE
		/* if just checking, say yes we can be a FILE*, but don't actually create it yet */
		if (ret == NULL) {
			goto exit_success;
		}

		{
			char fixed_mode[5];
			php_stream_mode_sanitize_fdopen_fopencookie(stream, fixed_mode);
			*(FILE**)ret = fopencookie(stream, fixed_mode, PHP_STREAM_COOKIE_FUNCTIONS);
		}

		if (*ret != NULL) {
			zend_off_t pos;

			stream->fclose_stdiocast = PHP_STREAM_FCLOSE_FOPENCOOKIE;

			/* If the stream position is not at the start, we need to force
			 * the stdio layer to believe it's real location. */
			pos = php_stream_tell(stream);
			if (pos > 0) {
				zend_fseek(*ret, pos, SEEK_SET);
			}

			goto exit_success;
		}

		/* must be either:
			a) programmer error
			b) no memory
			-> lets bail
		*/
		php_error_docref(NULL, E_ERROR, "fopencookie failed");
		return FAILURE;
#endif

		if (!php_stream_is_filtered(stream) && stream->ops->cast && stream->ops->cast(stream, castas, NULL) == SUCCESS) {
			if (FAILURE == stream->ops->cast(stream, castas, ret)) {
				return FAILURE;
			}
			goto exit_success;
		} else if (flags & PHP_STREAM_CAST_TRY_HARD) {
			php_stream *newstream;

			newstream = php_stream_fopen_tmpfile();
			if (newstream) {
				int retcopy = php_stream_copy_to_stream_ex(stream, newstream, PHP_STREAM_COPY_ALL, NULL);

				if (retcopy != SUCCESS) {
					php_stream_close(newstream);
				} else {
					int retcast = php_stream_cast(newstream, castas | flags, (void **)ret, show_err);

					if (retcast == SUCCESS) {
						rewind(*(FILE**)ret);
					}

					/* do some specialized cleanup */
					if ((flags & PHP_STREAM_CAST_RELEASE)) {
						php_stream_free(stream, PHP_STREAM_FREE_CLOSE_CASTED);
					}

					/* TODO: we probably should be setting .stdiocast and .fclose_stdiocast or
					 * we may be leaking the FILE*. Needs investigation, though. */
					return retcast;
				}
			}
		}
	}

	if (php_stream_is_filtered(stream)) {
		php_error_docref(NULL, E_WARNING, "cannot cast a filtered stream on this system");
		return FAILURE;
	} else if (stream->ops->cast && stream->ops->cast(stream, castas, ret) == SUCCESS) {
		goto exit_success;
	}

	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[4] = {
			"STDIO FILE*",
			"File Descriptor",
			"Socket Descriptor",
			"select()able descriptor"
		};

		php_error_docref(NULL, E_WARNING, "cannot represent a stream of type %s as a %s", stream->ops->label, cast_names[castas]);
	}

	return FAILURE;

exit_success:

	if ((stream->writepos - stream->readpos) > 0 &&
		stream->fclose_stdiocast != PHP_STREAM_FCLOSE_FOPENCOOKIE &&
		(flags & PHP_STREAM_CAST_INTERNAL) == 0
	) {
		/* the data we have buffered will be lost to the third party library that
		 * will be accessing the stream.  Emit a warning so that the end-user will
		 * know that they should try something else */

		php_error_docref(NULL, E_WARNING, ZEND_LONG_FMT " bytes of buffered data lost during stream conversion!", (zend_long)(stream->writepos - stream->readpos));
	}

	if (castas == PHP_STREAM_AS_STDIO && ret) {
		stream->stdiocast = *(FILE**)ret;
	}

	if (flags & PHP_STREAM_CAST_RELEASE) {
		php_stream_free(stream, PHP_STREAM_FREE_CLOSE_CASTED);
	}

	return SUCCESS;

}
Exemple #6
0
/* {{{ inifile_delete_replace_append
 */
static int inifile_delete_replace_append(inifile *dba, const key_type *key, const val_type *value, int append, zend_bool *found)
{
	size_t pos_grp_start=0, pos_grp_next;
	inifile *ini_tmp = NULL;
	php_stream *fp_tmp = NULL;
	int ret;

	/* 1) Search group start
	 * 2) Search next group
	 * 3) If not append: Copy group to ini_tmp
	 * 4) Open temp_stream and copy remainder
	 * 5) Truncate stream
	 * 6) If not append AND key.name given: Filtered copy back from ini_tmp
	 *    to stream. Otherwise the user wanted to delete the group.
	 * 7) Append value if given
	 * 8) Append temporary stream
	 */

	assert(!append || (key->name && value)); /* missuse */

	/* 1 - 3 */
	inifile_find_group(dba, key, &pos_grp_start);
	inifile_next_group(dba, key, &pos_grp_next);
	if (append) {
		ret = SUCCESS;
	} else {
		ret = inifile_copy_to(dba, pos_grp_start, pos_grp_next, &ini_tmp);
	}

	/* 4 */
	if (ret == SUCCESS) {
		fp_tmp = php_stream_temp_create(0, 64 * 1024);
		if (!fp_tmp) {
			php_error_docref(NULL, E_WARNING, "Could not create temporary stream");
			ret = FAILURE;
		} else {
			php_stream_seek(dba->fp, 0, SEEK_END);
			if (pos_grp_next != (size_t)php_stream_tell(dba->fp)) {
				php_stream_seek(dba->fp, pos_grp_next, SEEK_SET);
				if (SUCCESS != php_stream_copy_to_stream_ex(dba->fp, fp_tmp, PHP_STREAM_COPY_ALL, NULL)) {
					php_error_docref(NULL, E_WARNING, "Could not copy remainder to temporary stream");
					ret = FAILURE;
				}
			}
		}
	}

	/* 5 */
	if (ret == SUCCESS) {
		if (!value || (key->name && strlen(key->name))) {
			ret = inifile_truncate(dba, append ? pos_grp_next : pos_grp_start); /* writes error on fail */
		}
	}

	if (ret == SUCCESS) {
		if (key->name && strlen(key->name)) {
			/* 6 */
			if (!append && ini_tmp) {
				ret = inifile_filter(dba, ini_tmp, key, found);
			}

			/* 7 */
			/* important: do not query ret==SUCCESS again: inifile_filter might fail but
			 * however next operation must be done.
			 */
			if (value) {
				if (pos_grp_start == pos_grp_next && key->group && strlen(key->group)) {
					php_stream_printf(dba->fp, "[%s]\n", key->group);
				}
				php_stream_printf(dba->fp, "%s=%s\n", key->name, value->value ? value->value : "");
			}
		}

		/* 8 */
		/* important: do not query ret==SUCCESS again: inifile_filter might fail but
		 * however next operation must be done.
		 */
		if (fp_tmp && php_stream_tell(fp_tmp)) {
			php_stream_seek(fp_tmp, 0, SEEK_SET);
			php_stream_seek(dba->fp, 0, SEEK_END);
			if (SUCCESS != php_stream_copy_to_stream_ex(fp_tmp, dba->fp, PHP_STREAM_COPY_ALL, NULL)) {
				zend_throw_error(NULL, "Could not copy from temporary stream - ini file truncated");
				ret = FAILURE;
			}
		}
	}

	if (ini_tmp) {
		php_stream_close(ini_tmp->fp);
		inifile_free(ini_tmp, 0);
	}
	if (fp_tmp) {
		php_stream_close(fp_tmp);
	}
	php_stream_flush(dba->fp);
	php_stream_seek(dba->fp, 0, SEEK_SET);

	return ret;
}