Пример #1
0
static php_stream_filter_status_t php_zlib_inflate_filter(
	php_stream *stream,
	php_stream_filter *thisfilter,
	php_stream_bucket_brigade *buckets_in,
	php_stream_bucket_brigade *buckets_out,
	size_t *bytes_consumed,
	int flags
	TSRMLS_DC)
{
	php_zlib_filter_data *data;
	php_stream_bucket *bucket;
	size_t consumed = 0, original_out, original_in;
	int status;
	php_stream_filter_status_t exit_status = PSFS_FEED_ME;
	z_stream *streamp;

	if (!thisfilter || !thisfilter->abstract) {
		/* Should never happen */
		return PSFS_ERR_FATAL;
	}

	data = (php_zlib_filter_data *)(thisfilter->abstract);
	streamp = &(data->strm);
	original_in = data->strm.total_in;
	original_out = data->strm.total_out;

	while (buckets_in->head) {
		size_t bin = 0, desired;

		bucket = buckets_in->head;

		bucket = php_stream_bucket_make_writeable(buckets_in->head TSRMLS_CC);

		while (bin < (unsigned int) bucket->buflen) {

			if (data->finished) {
				consumed += bucket->buflen;
				break;
			}

			desired = bucket->buflen - bin;
			if (desired > data->inbuf_len) {
				desired = data->inbuf_len;
			}
			memcpy(data->strm.next_in, bucket->buf + bin, desired);
			data->strm.avail_in = desired;

			status = inflate(&(data->strm), flags & PSFS_FLAG_FLUSH_CLOSE ? Z_FINISH : Z_SYNC_FLUSH);
			if (status == Z_STREAM_END) {
				inflateEnd(&(data->strm));
				data->finished = '\1';
			} else if (status != Z_OK) {
				/* Something bad happened */
				php_stream_bucket_delref(bucket TSRMLS_CC);
				/* reset these because despite the error the filter may be used again */
				data->strm.next_in = data->inbuf;
				data->strm.avail_in = 0;
				return PSFS_ERR_FATAL;
			}
			desired -= data->strm.avail_in; /* desired becomes what we consumed this round through */
			data->strm.next_in = data->inbuf;
			data->strm.avail_in = 0;
			bin += desired;

			if (data->strm.avail_out < data->outbuf_len) {
				php_stream_bucket *out_bucket;
				size_t bucketlen = data->outbuf_len - data->strm.avail_out;
				out_bucket = php_stream_bucket_new(stream, estrndup(data->outbuf, bucketlen), bucketlen, 1, 0 TSRMLS_CC);
				php_stream_bucket_append(buckets_out, out_bucket TSRMLS_CC);
				data->strm.avail_out = data->outbuf_len;
				data->strm.next_out = data->outbuf;
				exit_status = PSFS_PASS_ON;
			} else if (status == Z_STREAM_END && data->strm.avail_out >= data->outbuf_len) {
				/* no more data to decompress, and nothing was spat out */
				php_stream_bucket_delref(bucket TSRMLS_CC);
				return PSFS_PASS_ON;
			}

		}
		consumed += bucket->buflen;
		php_stream_bucket_delref(bucket TSRMLS_CC);
	}

	if (!data->finished && flags & PSFS_FLAG_FLUSH_CLOSE) {
		/* Spit it out! */
		status = Z_OK;
		while (status == Z_OK) {
			status = inflate(&(data->strm), Z_FINISH);
			if (data->strm.avail_out < data->outbuf_len) {
				size_t bucketlen = data->outbuf_len - data->strm.avail_out;

				bucket = php_stream_bucket_new(stream, estrndup(data->outbuf, bucketlen), bucketlen, 1, 0 TSRMLS_CC);
				php_stream_bucket_append(buckets_out, bucket TSRMLS_CC);
				data->strm.avail_out = data->outbuf_len;
				data->strm.next_out = data->outbuf;
				exit_status = PSFS_PASS_ON;
			}
		}
	}

	if (bytes_consumed) {
		*bytes_consumed = consumed;
	}

	return exit_status;
}
Пример #2
0
zval *phalcon_replace_marker(int named, zval *paths, zval *replacements, unsigned long *position, char *cursor, char *marker){

	zval **zv, **tmp;
	int result = FAILURE;
	unsigned int length, variable_length, ch;
	char *item = NULL, *cursor_var, *variable = NULL;
	int not_valid = 0, j;

	if (named) {
		length = cursor - marker - 1;
		item = estrndup(marker + 1, length);
		cursor_var = item;
		marker = item;
		for (j = 0; j < length; j++) {
			ch = *cursor_var;
			if (ch == '\0') {
				not_valid = 1;
				break;
			}
			if (j == 0 && !((ch >= 'a' && ch <='z') || (ch >= 'A' && ch <= 'Z'))){
				not_valid = 1;
				break;
			}
			if ((ch >= 'a' && ch <='z') || (ch >= 'A' && ch <= 'Z') || (ch >= '0' && ch <= '9') || ch == '-' || ch == '_' || ch ==  ':') {
				if (ch == ':') {
					variable_length = cursor_var - marker;
					variable = estrndup(marker, variable_length);
					break;
				}
			} else {
				not_valid = 1;
				break;
			}
			cursor_var++;
		}
	}

	if (!not_valid) {

		if (zend_hash_index_exists(Z_ARRVAL_P(paths), *position)) {
			if (named) {
				if (variable) {
					efree(item);
					item = variable;
					length = variable_length;
				}
				if (zend_hash_exists(Z_ARRVAL_P(replacements), item, length + 1)) {
					if ((result = zend_hash_find(Z_ARRVAL_P(replacements), item, length + 1, (void**) &zv)) == SUCCESS) {
						efree(item);
						(*position)++;
						return *zv;
					}
				}
			} else {
				if ((result = zend_hash_index_find(Z_ARRVAL_P(paths), *position, (void**) &zv)) == SUCCESS) {
					if (Z_TYPE_PP(zv) == IS_STRING) {
						if (zend_hash_exists(Z_ARRVAL_P(replacements), Z_STRVAL_PP(zv), Z_STRLEN_PP(zv) + 1)) {
							if ((result = zend_hash_find(Z_ARRVAL_P(replacements), Z_STRVAL_PP(zv), Z_STRLEN_PP(zv) + 1, (void**) &tmp)) == SUCCESS) {
								(*position)++;
								return *tmp;
							}
						}
					}
				}
			}
		}

		(*position)++;
	}

	if (item) {
		efree(item);
	}

	return NULL;
}
Пример #3
0
static int odbc_stmt_get_col(pdo_stmt_t *stmt, int colno, char **ptr, zend_ulong *len, int *caller_frees)
{
	pdo_odbc_stmt *S = (pdo_odbc_stmt*)stmt->driver_data;
	pdo_odbc_column *C = &S->cols[colno];
	zend_ulong ulen;

	/* if it is a column containing "long" data, perform late binding now */
	if (C->is_long) {
		zend_ulong used = 0;
		char *buf;
		RETCODE rc;

		/* fetch it into C->data, which is allocated with a length
		 * of 256 bytes; if there is more to be had, we then allocate
		 * bigger buffer for the caller to free */

		rc = SQLGetData(S->stmt, colno+1, C->is_unicode ? SQL_C_BINARY : SQL_C_CHAR, C->data,
 			256, &C->fetched_len);

		if (rc == SQL_SUCCESS) {
			/* all the data fit into our little buffer;
			 * jump down to the generic bound data case */
			goto in_data;
		}

		if (rc == SQL_SUCCESS_WITH_INFO) {
			/* this is a 'long column'
			
			 read the column in 255 byte blocks until the end of the column is reached, reassembling those blocks
			 in order into the output buffer
			
			 this loop has to work whether or not SQLGetData() provides the total column length.
			 calling SQLDescribeCol() or other, specifically to get the column length, then doing a single read
			 for that size would be slower except maybe for extremely long columns.*/
			char *buf2;

			buf2 = emalloc(256);
			buf = estrndup(C->data, 256);
			used = 255; /* not 256; the driver NUL terminated the buffer */
			
			do {
				C->fetched_len = 0;
				/* read block. 256 bytes => 255 bytes are actually read, the last 1 is NULL */
				rc = SQLGetData(S->stmt, colno+1, SQL_C_CHAR, buf2, 256, &C->fetched_len);
				
				/* resize output buffer and reassemble block */
				if (rc==SQL_SUCCESS_WITH_INFO) {
					/* point 5, in section "Retrieving Data with SQLGetData" in http://msdn.microsoft.com/en-us/library/windows/desktop/ms715441(v=vs.85).aspx
					 states that if SQL_SUCCESS_WITH_INFO, fetched_len will be > 255 (greater than buf2's size)
					 (if a driver fails to follow that and wrote less than 255 bytes to buf2, this will AV or read garbage into buf) */
					buf = erealloc(buf, used + 255+1);
					memcpy(buf + used, buf2, 255);
					used = used + 255;
				} else if (rc==SQL_SUCCESS) {
					buf = erealloc(buf, used + C->fetched_len+1);
					memcpy(buf + used, buf2, C->fetched_len);
					used = used + C->fetched_len;
				} else {
					/* includes SQL_NO_DATA */
					break;
				}
				
			} while (1);
			
			efree(buf2);
			
			/* NULL terminate the buffer once, when finished, for use with the rest of PHP */
			buf[used] = '\0';

			*ptr = buf;
			*caller_frees = 1;
			*len = used;
			if (C->is_unicode) {
				goto unicode_conv;
			}
			return 1;
		}

		/* something went caca */
		*ptr = NULL;
		*len = 0;
		return 1;
	}

in_data:
	/* check the indicator to ensure that the data is intact */
	if (C->fetched_len == SQL_NULL_DATA) {
		/* A NULL value */
		*ptr = NULL;
		*len = 0;
		return 1;
	} else if (C->fetched_len >= 0) {
		/* it was stored perfectly */
		*ptr = C->data;
		*len = C->fetched_len;
		if (C->is_unicode) {
			goto unicode_conv;
		}
		return 1;
	} else {
		/* no data? */
		*ptr = NULL;
		*len = 0;
		return 1;
	}

	unicode_conv:
	switch (pdo_odbc_ucs22utf8(stmt, C->is_unicode, *ptr, *len, &ulen)) {
		case PDO_ODBC_CONV_FAIL:
			/* oh well.  They can have the binary version of it */
		case PDO_ODBC_CONV_NOT_REQUIRED:
			/* shouldn't happen... */
			return 1;

		case PDO_ODBC_CONV_OK:
			if (*caller_frees) {
				efree(*ptr);
			}
			*ptr = emalloc(ulen + 1);
			*len = ulen;
			memcpy(*ptr, S->convbuf, ulen+1);
			*caller_frees = 1;
			return 1;
	}
	return 1;
}
Пример #4
0
/*
** The following code executes when a syntax error first occurs.
*/
static void jj_syntax_error(
  jjParser *jjpParser,           /* The parser */
  int jjmajor,                   /* The major type of the error token */
  JJMINORTYPE jjminor            /* The minor type of the error token */
){
  phannot_ARG_FETCH;
#define JTOKEN (jjminor.jj0)
// 159 "parser.lemon"

	if (status->scanner_state->start_length) {
		{

			char *token_name = NULL;
			const phannot_token_names *tokens = phannot_tokens;
			int token_found = 0;
			int active_token = status->scanner_state->active_token;
			int near_length = status->scanner_state->start_length;

			if (active_token) {
				do {
					if (tokens->code == active_token) {
						token_found = 1;
						token_name = tokens->name;
						break;
					}
					++tokens;
				} while (tokens[0].code != 0);
			}

			if (!token_name) {
				token_found = 0;
				token_name = estrndup("UNKNOWN", strlen("UNKNOWN"));
			}

			status->syntax_error_len = 128 + strlen(token_name) + Z_STRLEN_P(status->scanner_state->active_file);
			status->syntax_error = emalloc(sizeof(char) * status->syntax_error_len);

			if (near_length > 0) {
				if (status->token->value) {
					snprintf(status->syntax_error, status->syntax_error_len, "Syntax error, unexpected token %s(%s), near to '%s' in %s on line %d", token_name, status->token->value, status->scanner_state->start, Z_STRVAL_P(status->scanner_state->active_file), status->scanner_state->active_line);
				} else {
					snprintf(status->syntax_error, status->syntax_error_len, "Syntax error, unexpected token %s, near to '%s' in %s on line %d", token_name, status->scanner_state->start, Z_STRVAL_P(status->scanner_state->active_file), status->scanner_state->active_line);
				}
			} else {
				if (active_token != PHANNOT_T_IGNORE) {
					if (status->token->value) {
						snprintf(status->syntax_error, status->syntax_error_len, "Syntax error, unexpected token %s(%s), at the end of docblock in %s on line %d", token_name, status->token->value, Z_STRVAL_P(status->scanner_state->active_file), status->scanner_state->active_line);
					} else {
						snprintf(status->syntax_error, status->syntax_error_len, "Syntax error, unexpected token %s, at the end of docblock in %s on line %d", token_name, Z_STRVAL_P(status->scanner_state->active_file), status->scanner_state->active_line);
					}
				} else {
					snprintf(status->syntax_error, status->syntax_error_len, "Syntax error, unexpected EOF, at the end of docblock in %s on line %d", Z_STRVAL_P(status->scanner_state->active_file), status->scanner_state->active_line);
				}
				status->syntax_error[status->syntax_error_len-1] = '\0';
			}

			if (!token_found) {
				if (token_name) {
					efree(token_name);
				}
			}
		}
	} else {
		status->syntax_error_len = 48 + Z_STRLEN_P(status->scanner_state->active_file);
		status->syntax_error = emalloc(sizeof(char) * status->syntax_error_len);
		sprintf(status->syntax_error, "Syntax error, unexpected EOF in %s", Z_STRVAL_P(status->scanner_state->active_file));
	}

	status->status = PHANNOT_PARSING_FAILED;

// 1019 "parser.c"
  phannot_ARG_STORE; /* Suppress warning about unused %extra_argument variable */
}
Пример #5
0
PHP_SUHOSIN_API void suhosin_log(int loglevel, char *fmt, ...)
{
	int s, r, i=0, fd;
	long written, towrite;
	int getcaller=0;
	char *wbuf;
	struct timeval tv;
	time_t now;
	struct tm tm;
#if defined(AF_UNIX)
	struct sockaddr_un saun;
#endif
#ifdef PHP_WIN32
	LPTSTR strs[2];
	unsigned short etype;
	DWORD evid;
#endif
	char buf[5000];
	char error[5000];
	char *ip_address;
	char *fname;
	char *alertstring;
	int lineno;
	va_list ap;
	TSRMLS_FETCH();

#if PHP_VERSION_ID >= 50500
	getcaller = (loglevel & S_GETCALLER) == S_GETCALLER;
#endif
	/* remove the S_GETCALLER flag */
	loglevel = loglevel & ~S_GETCALLER;

	SDEBUG("(suhosin_log) loglevel: %d log_syslog: %u - log_sapi: %u - log_script: %u", loglevel, SUHOSIN_G(log_syslog), SUHOSIN_G(log_sapi), SUHOSIN_G(log_script));

	/* dump core if wanted */
	if (SUHOSIN_G(coredump) && loglevel == S_MEMORY) {
		volatile unsigned int *x = 0;
		volatile int y = *x;
	}
	
	if (SUHOSIN_G(log_use_x_forwarded_for)) {
		ip_address = suhosin_getenv("HTTP_X_FORWARDED_FOR", 20 TSRMLS_CC);
		if (ip_address == NULL) {
			ip_address = "X-FORWARDED-FOR not set";
		}
	} else {
		ip_address = suhosin_getenv("REMOTE_ADDR", 11 TSRMLS_CC);
		if (ip_address == NULL) {
			ip_address = "REMOTE_ADDR not set";
		}
	}
	
	
	va_start(ap, fmt);
	ap_php_vsnprintf(error, sizeof(error), fmt, ap);
	va_end(ap);
	while (error[i]) {
		if (error[i] < 32) error[i] = '.';
		i++;
	}
	
	if (SUHOSIN_G(simulation)) {
		alertstring = "ALERT-SIMULATION";
	} else {
		alertstring = "ALERT";
	}
	
	if (zend_is_executing(TSRMLS_C)) {
		zend_execute_data *exdata = EG(current_execute_data);
		if (exdata) {
			if (getcaller && exdata->prev_execute_data) {
				lineno = exdata->prev_execute_data->opline->lineno;
				fname = (char *)exdata->prev_execute_data->op_array->filename;									
			} else {
				lineno = exdata->opline->lineno;
				fname = (char *)exdata->op_array->filename;				
			}
		} else {
			lineno = zend_get_executed_lineno(TSRMLS_C);
			fname = (char *)zend_get_executed_filename(TSRMLS_C);
		}
		ap_php_snprintf(buf, sizeof(buf), "%s - %s (attacker '%s', file '%s', line %u)", alertstring, error, ip_address, fname, lineno);
	} else {
		fname = suhosin_getenv("SCRIPT_FILENAME", 15 TSRMLS_CC);
		if (fname==NULL) {
			fname = "unknown";
		}
		ap_php_snprintf(buf, sizeof(buf), "%s - %s (attacker '%s', file '%s')", alertstring, error, ip_address, fname);
	}
			
	/* Syslog-Logging disabled? */
	if (((SUHOSIN_G(log_syslog)|S_INTERNAL) & loglevel)==0) {
		goto log_file;
	}	
	
#if defined(AF_UNIX)
	ap_php_snprintf(error, sizeof(error), "<%u>suhosin[%u]: %s\n", (unsigned int)(SUHOSIN_G(log_syslog_facility)|SUHOSIN_G(log_syslog_priority)),getpid(),buf);

	s = socket(AF_UNIX, SOCK_DGRAM, 0);
	if (s == -1) {
		goto log_file;
	}
	
	memset(&saun, 0, sizeof(saun));
	saun.sun_family = AF_UNIX;
	strcpy(saun.sun_path, SYSLOG_PATH);
	/*saun.sun_len = sizeof(saun);*/
	
	r = connect(s, (struct sockaddr *)&saun, sizeof(saun));
	if (r) {
		close(s);
    		s = socket(AF_UNIX, SOCK_STREAM, 0);
		if (s == -1) {
			goto log_file;
		}
	
		memset(&saun, 0, sizeof(saun));
		saun.sun_family = AF_UNIX;
		strcpy(saun.sun_path, SYSLOG_PATH);
		/*saun.sun_len = sizeof(saun);*/

		r = connect(s, (struct sockaddr *)&saun, sizeof(saun));
		if (r) { 
			close(s);
			goto log_file;
		}
	}
	send(s, error, strlen(error), 0);
	
	close(s);
#endif
#ifdef PHP_WIN32
	ap_php_snprintf(error, sizeof(error), "suhosin[%u]: %s", getpid(),buf);

	switch (SUHOSIN_G(log_syslog_priority)) {			/* translate UNIX type into NT type */
		case 1: /*LOG_ALERT:*/
			etype = EVENTLOG_ERROR_TYPE;
			break;
		case 6: /*LOG_INFO:*/
			etype = EVENTLOG_INFORMATION_TYPE;
			break;
		default:
			etype = EVENTLOG_WARNING_TYPE;
	}
	evid = loglevel;
	strs[0] = error;
	/* report the event */
	if (log_source == NULL) {
		log_source = RegisterEventSource(NULL, "Suhosin-" SUHOSIN_EXT_VERSION);
	}
	ReportEvent(log_source, etype, (unsigned short) SUHOSIN_G(log_syslog_priority), evid, NULL, 1, 0, strs, NULL);
	
#endif
log_file:
	/* File-Logging disabled? */
	if ((SUHOSIN_G(log_file) & loglevel)==0) {
		goto log_sapi;
	}
	
	if (!SUHOSIN_G(log_filename) || !SUHOSIN_G(log_filename)[0]) {
		goto log_sapi;
	}
	fd = open(SUHOSIN_G(log_filename), O_CREAT|O_APPEND|O_WRONLY, 0640);
	if (fd == -1) {
	    suhosin_log(S_INTERNAL, "Unable to open logfile: %s", SUHOSIN_G(log_filename));
	    return;
	}

	gettimeofday(&tv, NULL);
	now = tv.tv_sec;
	php_gmtime_r(&now, &tm);
	ap_php_snprintf(error, sizeof(error), "%s %2d %02d:%02d:%02d [%u] %s\n", month_names[tm.tm_mon], tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec, getpid(),buf);
	towrite = strlen(error);
	wbuf = error;
	php_flock(fd, LOCK_EX);
	while (towrite > 0) {
		written = write(fd, wbuf, towrite);
		if (written < 0) {
			break;
		}
		towrite -= written;
		wbuf += written;
	}
	php_flock(fd, LOCK_UN);
	close(fd);

log_sapi:
	/* SAPI Logging activated? */
	SDEBUG("(suhosin_log) log_syslog: %u - log_sapi: %u - log_script: %u - log_phpscript: %u", SUHOSIN_G(log_syslog), SUHOSIN_G(log_sapi), SUHOSIN_G(log_script), SUHOSIN_G(log_phpscript));
	if (((SUHOSIN_G(log_sapi)|S_INTERNAL) & loglevel)!=0) {
#if PHP_VERSION_ID < 50400
		sapi_module.log_message(buf);
#else
		sapi_module.log_message(buf TSRMLS_CC);
#endif
	}
	if ((SUHOSIN_G(log_stdout) & loglevel)!=0) {
		printf("%s\n", buf);
	}

/*log_script:*/
	/* script logging activaed? */
	if (((SUHOSIN_G(log_script) & loglevel)!=0) && SUHOSIN_G(log_scriptname)!=NULL) {
		char cmd[8192], *cmdpos, *bufpos;
		FILE *in;
		int space;
		struct stat st;
		
		char *sname = SUHOSIN_G(log_scriptname);
		while (isspace(*sname)) ++sname;
		if (*sname == 0) goto log_phpscript;
		
		if (VCWD_STAT(sname, &st) < 0) {
			suhosin_log(S_INTERNAL, "unable to find logging shell script %s - file dropped", sname);
			goto log_phpscript;
		}
		if (access(sname, X_OK|R_OK) < 0) {
			suhosin_log(S_INTERNAL, "logging shell script %s is not executable - file dropped", sname);
			goto log_phpscript;					
		}
		
		/* TODO: clean up this code to calculate size of output dynamically */
		ap_php_snprintf(cmd, sizeof(cmd) - 20, "%s %s \'", sname, loglevel2string(loglevel));
		space = sizeof(cmd) - strlen(cmd) - 20;
		cmdpos = cmd + strlen(cmd);
		bufpos = buf;
		if (space <= 1) return;
		while (space > 2 && *bufpos) {
			if (*bufpos == '\'') {
				if (space<=5) break;
				*cmdpos++ = '\'';
				*cmdpos++ = '\\';
				*cmdpos++ = '\'';
				*cmdpos++ = '\'';
				bufpos++;
				space-=4;
			} else {
				*cmdpos++ = *bufpos++;
				space--;
			}
		}
		*cmdpos++ = '\'';
		*cmdpos++ = ' ';
		*cmdpos++ = '2';
		*cmdpos++ = '>';
		*cmdpos++ = '&';
		*cmdpos++ = '1';
		*cmdpos = 0;
		
		if ((in=VCWD_POPEN(cmd, "r"))==NULL) {
			suhosin_log(S_INTERNAL, "Unable to execute logging shell script: %s", sname);
			goto log_phpscript;
		}
		/* read and forget the result */
		while (1) {
			int readbytes = fread(cmd, 1, sizeof(cmd), in);
			if (readbytes<=0) {
				break;
			}
			if (strncmp(cmd, "sh: ", 4) == 0) {
				/* assume this is an error */
				suhosin_log(S_INTERNAL, "Error while executing logging shell script: %s", sname);
				pclose(in);
				goto log_phpscript;
			}
		}
		pclose(in);
	}
log_phpscript:
	if ((SUHOSIN_G(log_phpscript) & loglevel)!=0 && EG(in_execution) && SUHOSIN_G(log_phpscriptname) && SUHOSIN_G(log_phpscriptname)[0]) {
		zend_file_handle file_handle;
		zend_op_array *new_op_array;
		zval *result = NULL;
		
		long orig_execution_depth = SUHOSIN_G(execution_depth);
#if PHP_VERSION_ID < 50400
		zend_bool orig_safe_mode = PG(safe_mode);
#endif
		char *orig_basedir = PG(open_basedir);
		
		char *phpscript = SUHOSIN_G(log_phpscriptname);
SDEBUG("scriptname %s", SUHOSIN_G(log_phpscriptname));				
#ifdef ZEND_ENGINE_2
		if (zend_stream_open(phpscript, &file_handle TSRMLS_CC) == SUCCESS) {
#else
		if (zend_open(phpscript, &file_handle) == SUCCESS && ZEND_IS_VALID_FILE_HANDLE(&file_handle)) {
			file_handle.filename = phpscript;
			file_handle.free_filename = 0;
#endif		
			if (!file_handle.opened_path) {
				file_handle.opened_path = estrndup(phpscript, strlen(phpscript));
			}
			new_op_array = zend_compile_file(&file_handle, ZEND_REQUIRE TSRMLS_CC);
			zend_destroy_file_handle(&file_handle TSRMLS_CC);
			if (new_op_array) {
				HashTable *active_symbol_table = EG(active_symbol_table);
				zval *zerror, *zerror_class;
				
				if (active_symbol_table == NULL) {
					active_symbol_table = &EG(symbol_table);
				}
				EG(return_value_ptr_ptr) = &result;
				EG(active_op_array) = new_op_array;
				
				MAKE_STD_ZVAL(zerror);
				MAKE_STD_ZVAL(zerror_class);
				ZVAL_STRING(zerror, buf, 1);
				ZVAL_LONG(zerror_class, loglevel);

				zend_hash_update(active_symbol_table, "SUHOSIN_ERROR", sizeof("SUHOSIN_ERROR"), (void **)&zerror, sizeof(zval *), NULL);
				zend_hash_update(active_symbol_table, "SUHOSIN_ERRORCLASS", sizeof("SUHOSIN_ERRORCLASS"), (void **)&zerror_class, sizeof(zval *), NULL);
				
				SUHOSIN_G(execution_depth) = 0;
				if (SUHOSIN_G(log_phpscript_is_safe)) {
#if PHP_VERSION_ID < 50400
					PG(safe_mode) = 0;
#endif
					PG(open_basedir) = NULL;
				}
				
				zend_execute(new_op_array TSRMLS_CC);
				
				SUHOSIN_G(execution_depth) = orig_execution_depth;
#if PHP_VERSION_ID < 50400				
				PG(safe_mode) = orig_safe_mode;
#endif
				PG(open_basedir) = orig_basedir;
				
#ifdef ZEND_ENGINE_2
				destroy_op_array(new_op_array TSRMLS_CC);
#else
				destroy_op_array(new_op_array);
#endif
				efree(new_op_array);
#ifdef ZEND_ENGINE_2
				if (!EG(exception))
#endif			
				{
					if (EG(return_value_ptr_ptr)) {
						zval_ptr_dtor(EG(return_value_ptr_ptr));
						EG(return_value_ptr_ptr) = NULL;
					}
				}
			} else {
				suhosin_log(S_INTERNAL, "Unable to execute logging PHP script: %s", SUHOSIN_G(log_phpscriptname));
				return;
			}
		} else {
			suhosin_log(S_INTERNAL, "Unable to execute logging PHP script: %s", SUHOSIN_G(log_phpscriptname));
			return;
		}
	}

}
Пример #6
0
php_stream *php_stream_url_wrap_http_ex(php_stream_wrapper *wrapper, 
		const char *path, const char *mode, int options, char **opened_path, 
		php_stream_context *context, int redirect_max, int flags STREAMS_DC TSRMLS_DC) /* {{{ */
{
	php_stream *stream = NULL;
	php_url *resource = NULL;
	int use_ssl;
	int use_proxy = 0;
	char *scratch = NULL;
	char *tmp = NULL;
	char *ua_str = NULL;
	zval **ua_zval = NULL, **tmpzval = NULL;
	int scratch_len = 0;
	int body = 0;
	char location[HTTP_HEADER_BLOCK_SIZE];
	zval *response_header = NULL;
	int reqok = 0;
	char *http_header_line = NULL;
	char tmp_line[128];
	size_t chunk_size = 0, file_size = 0;
	int eol_detect = 0;
	char *transport_string, *errstr = NULL;
	int transport_len, have_header = 0, request_fulluri = 0, ignore_errors = 0;
	char *protocol_version = NULL;
	int protocol_version_len = 3; /* Default: "1.0" */
	struct timeval timeout;
	char *user_headers = NULL;
	int header_init = ((flags & HTTP_WRAPPER_HEADER_INIT) != 0);
	int redirected = ((flags & HTTP_WRAPPER_REDIRECTED) != 0);
	int follow_location = 1;
	php_stream_filter *transfer_encoding = NULL;
	int response_code;

	tmp_line[0] = '\0';

	if (redirect_max < 1) {
		php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "Redirection limit reached, aborting");
		return NULL;
	}

	resource = php_url_parse(path);
	if (resource == NULL) {
		return NULL;
	}

	if (strncasecmp(resource->scheme, "http", sizeof("http")) && strncasecmp(resource->scheme, "https", sizeof("https"))) {
		if (!context || 
			php_stream_context_get_option(context, wrapper->wops->label, "proxy", &tmpzval) == FAILURE ||
			Z_TYPE_PP(tmpzval) != IS_STRING ||
			Z_STRLEN_PP(tmpzval) <= 0) {
			php_url_free(resource);
			return php_stream_open_wrapper_ex(path, mode, REPORT_ERRORS, NULL, context);
		}
		/* Called from a non-http wrapper with http proxying requested (i.e. ftp) */
		request_fulluri = 1;
		use_ssl = 0;
		use_proxy = 1;

		transport_len = Z_STRLEN_PP(tmpzval);
		transport_string = estrndup(Z_STRVAL_PP(tmpzval), Z_STRLEN_PP(tmpzval));
	} else {
		/* Normal http request (possibly with proxy) */
	
		if (strpbrk(mode, "awx+")) {
			php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "HTTP wrapper does not support writeable connections");
			php_url_free(resource);
			return NULL;
		}

		use_ssl = resource->scheme && (strlen(resource->scheme) > 4) && resource->scheme[4] == 's';
		/* choose default ports */
		if (use_ssl && resource->port == 0)
			resource->port = 443;
		else if (resource->port == 0)
			resource->port = 80;

		if (context &&
			php_stream_context_get_option(context, wrapper->wops->label, "proxy", &tmpzval) == SUCCESS &&
			Z_TYPE_PP(tmpzval) == IS_STRING &&
			Z_STRLEN_PP(tmpzval) > 0) {
			use_proxy = 1;
			transport_len = Z_STRLEN_PP(tmpzval);
			transport_string = estrndup(Z_STRVAL_PP(tmpzval), Z_STRLEN_PP(tmpzval));
		} else {
			transport_len = spprintf(&transport_string, 0, "%s://%s:%d", use_ssl ? "ssl" : "tcp", resource->host, resource->port);
		}
	}

	if (context && php_stream_context_get_option(context, wrapper->wops->label, "timeout", &tmpzval) == SUCCESS) {
		SEPARATE_ZVAL(tmpzval);
		convert_to_double_ex(tmpzval);
		timeout.tv_sec = (time_t) Z_DVAL_PP(tmpzval);
		timeout.tv_usec = (size_t) ((Z_DVAL_PP(tmpzval) - timeout.tv_sec) * 1000000);
	} else {
		timeout.tv_sec = FG(default_socket_timeout);
		timeout.tv_usec = 0;
	}

	stream = php_stream_xport_create(transport_string, transport_len, options,
			STREAM_XPORT_CLIENT | STREAM_XPORT_CONNECT,
			NULL, &timeout, context, &errstr, NULL);
    
	if (stream) {
		php_stream_set_option(stream, PHP_STREAM_OPTION_READ_TIMEOUT, 0, &timeout);
	}
			
	if (errstr) {
		php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "%s", errstr);
		efree(errstr);
		errstr = NULL;
	}

	efree(transport_string);

	if (stream && use_proxy && use_ssl) {
		smart_str header = {0};

		smart_str_appendl(&header, "CONNECT ", sizeof("CONNECT ")-1);
		smart_str_appends(&header, resource->host);
		smart_str_appendc(&header, ':');
		smart_str_append_unsigned(&header, resource->port);
		smart_str_appendl(&header, " HTTP/1.0\r\n", sizeof(" HTTP/1.0\r\n")-1);

	    /* check if we have Proxy-Authorization header */
		if (context && php_stream_context_get_option(context, "http", "header", &tmpzval) == SUCCESS) {
			char *s, *p;

			if (Z_TYPE_PP(tmpzval) == IS_ARRAY) {
				HashPosition pos;
				zval **tmpheader = NULL;

				for (zend_hash_internal_pointer_reset_ex(Z_ARRVAL_PP(tmpzval), &pos);
					SUCCESS == zend_hash_get_current_data_ex(Z_ARRVAL_PP(tmpzval), (void *)&tmpheader, &pos);
					zend_hash_move_forward_ex(Z_ARRVAL_PP(tmpzval), &pos)) {
					if (Z_TYPE_PP(tmpheader) == IS_STRING) {
						s = Z_STRVAL_PP(tmpheader);
						do {
							while (*s == ' ' || *s == '\t') s++;
							p = s;
							while (*p != 0 && *p != ':' && *p != '\r' && *p !='\n') p++;
							if (*p == ':') {
								p++;
								if (p - s == sizeof("Proxy-Authorization:") - 1 &&
								    zend_binary_strcasecmp(s, sizeof("Proxy-Authorization:") - 1,
								        "Proxy-Authorization:", sizeof("Proxy-Authorization:") - 1) == 0) {
									while (*p != 0 && *p != '\r' && *p !='\n') p++;
									smart_str_appendl(&header, s, p - s);
									smart_str_appendl(&header, "\r\n", sizeof("\r\n")-1);
									goto finish;
								} else {
									while (*p != 0 && *p != '\r' && *p !='\n') p++;
								}
							}
							s = p;
							while (*s == '\r' || *s == '\n') s++;
						} while (*s != 0);
					}
				}
			} else if (Z_TYPE_PP(tmpzval) == IS_STRING && Z_STRLEN_PP(tmpzval)) {
				s = Z_STRVAL_PP(tmpzval);
				do {
					while (*s == ' ' || *s == '\t') s++;
					p = s;
					while (*p != 0 && *p != ':' && *p != '\r' && *p !='\n') p++;
					if (*p == ':') {
						p++;
						if (p - s == sizeof("Proxy-Authorization:") - 1 &&
						    zend_binary_strcasecmp(s, sizeof("Proxy-Authorization:") - 1,
						        "Proxy-Authorization:", sizeof("Proxy-Authorization:") - 1) == 0) {
							while (*p != 0 && *p != '\r' && *p !='\n') p++;
							smart_str_appendl(&header, s, p - s);
							smart_str_appendl(&header, "\r\n", sizeof("\r\n")-1);
							goto finish;
						} else {
							while (*p != 0 && *p != '\r' && *p !='\n') p++;
						}
					}
					s = p;
					while (*s == '\r' || *s == '\n') s++;
				} while (*s != 0);
			}
		}
finish:
		smart_str_appendl(&header, "\r\n", sizeof("\r\n")-1);

		if (php_stream_write(stream, header.c, header.len) != header.len) {
			php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "Cannot connect to HTTPS server through proxy");
			php_stream_close(stream);
			stream = NULL;
		}
 	 	smart_str_free(&header);

 	 	if (stream) {
 	 		char header_line[HTTP_HEADER_BLOCK_SIZE];

			/* get response header */
			while (php_stream_gets(stream, header_line, HTTP_HEADER_BLOCK_SIZE-1) != NULL) {
				if (header_line[0] == '\n' ||
				    header_line[0] == '\r' ||
				    header_line[0] == '\0') {
				  break;
				}
			}
		}

		/* enable SSL transport layer */
		if (stream) {
			if (php_stream_xport_crypto_setup(stream, STREAM_CRYPTO_METHOD_SSLv23_CLIENT, NULL TSRMLS_CC) < 0 ||
			    php_stream_xport_crypto_enable(stream, 1 TSRMLS_CC) < 0) {
				php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "Cannot connect to HTTPS server through proxy");
				php_stream_close(stream);
				stream = NULL;
			}
		}
	}

	if (stream == NULL)
		goto out;

	/* avoid buffering issues while reading header */
	if (options & STREAM_WILL_CAST)
		chunk_size = php_stream_set_chunk_size(stream, 1);
	
	/* avoid problems with auto-detecting when reading the headers -> the headers
	 * are always in canonical \r\n format */
	eol_detect = stream->flags & (PHP_STREAM_FLAG_DETECT_EOL | PHP_STREAM_FLAG_EOL_MAC);
	stream->flags &= ~(PHP_STREAM_FLAG_DETECT_EOL | PHP_STREAM_FLAG_EOL_MAC);

	php_stream_context_set(stream, context TSRMLS_CC);

	php_stream_notify_info(context, PHP_STREAM_NOTIFY_CONNECT, NULL, 0);

	if (header_init && context && php_stream_context_get_option(context, "http", "max_redirects", &tmpzval) == SUCCESS) {
		SEPARATE_ZVAL(tmpzval);
		convert_to_long_ex(tmpzval);
		redirect_max = Z_LVAL_PP(tmpzval);
	}

	if (context && php_stream_context_get_option(context, "http", "method", &tmpzval) == SUCCESS) {
		if (Z_TYPE_PP(tmpzval) == IS_STRING && Z_STRLEN_PP(tmpzval) > 0) {
			/* As per the RFC, automatically redirected requests MUST NOT use other methods than
			 * GET and HEAD unless it can be confirmed by the user */
			if (!redirected
				|| (Z_STRLEN_PP(tmpzval) == 3 && memcmp("GET", Z_STRVAL_PP(tmpzval), 3) == 0)
				|| (Z_STRLEN_PP(tmpzval) == 4 && memcmp("HEAD",Z_STRVAL_PP(tmpzval), 4) == 0)
			) {
				scratch_len = strlen(path) + 29 + Z_STRLEN_PP(tmpzval);
				scratch = emalloc(scratch_len);
				strlcpy(scratch, Z_STRVAL_PP(tmpzval), Z_STRLEN_PP(tmpzval) + 1);
				strncat(scratch, " ", 1);
			}
		}
	}
 
	if (context && php_stream_context_get_option(context, "http", "protocol_version", &tmpzval) == SUCCESS) {
		SEPARATE_ZVAL(tmpzval);
		convert_to_double_ex(tmpzval);
		protocol_version_len = spprintf(&protocol_version, 0, "%.1F", Z_DVAL_PP(tmpzval));
	}

	if (!scratch) {
		scratch_len = strlen(path) + 29 + protocol_version_len;
		scratch = emalloc(scratch_len);
		strncpy(scratch, "GET ", scratch_len);
	}

	/* Should we send the entire path in the request line, default to no. */
	if (!request_fulluri &&
		context &&
		php_stream_context_get_option(context, "http", "request_fulluri", &tmpzval) == SUCCESS) {
		zval ztmp = **tmpzval;

		zval_copy_ctor(&ztmp);
		convert_to_boolean(&ztmp);
		request_fulluri = Z_BVAL(ztmp) ? 1 : 0;
		zval_dtor(&ztmp);
	}

	if (request_fulluri) {
		/* Ask for everything */
		strcat(scratch, path);
	} else {
		/* Send the traditional /path/to/file?query_string */

		/* file */
		if (resource->path && *resource->path) {
			strlcat(scratch, resource->path, scratch_len);
		} else {
			strlcat(scratch, "/", scratch_len);
		}

		/* query string */
		if (resource->query) {
			strlcat(scratch, "?", scratch_len);
			strlcat(scratch, resource->query, scratch_len);
		}
	}

	/* protocol version we are speaking */
	if (protocol_version) {
		strlcat(scratch, " HTTP/", scratch_len);
		strlcat(scratch, protocol_version, scratch_len);
		strlcat(scratch, "\r\n", scratch_len);
	} else {
		strlcat(scratch, " HTTP/1.0\r\n", scratch_len);
	}

	/* send it */
	php_stream_write(stream, scratch, strlen(scratch));

	if (context && php_stream_context_get_option(context, "http", "header", &tmpzval) == SUCCESS) {
		tmp = NULL;
		
		if (Z_TYPE_PP(tmpzval) == IS_ARRAY) {
			HashPosition pos;
			zval **tmpheader = NULL;
			smart_str tmpstr = {0};

			for (zend_hash_internal_pointer_reset_ex(Z_ARRVAL_PP(tmpzval), &pos);
				SUCCESS == zend_hash_get_current_data_ex(Z_ARRVAL_PP(tmpzval), (void *)&tmpheader, &pos);
				zend_hash_move_forward_ex(Z_ARRVAL_PP(tmpzval), &pos)
			) {
				if (Z_TYPE_PP(tmpheader) == IS_STRING) {
					smart_str_appendl(&tmpstr, Z_STRVAL_PP(tmpheader), Z_STRLEN_PP(tmpheader));
					smart_str_appendl(&tmpstr, "\r\n", sizeof("\r\n") - 1);
				}
			}
			smart_str_0(&tmpstr);
			/* Remove newlines and spaces from start and end. there's at least one extra \r\n at the end that needs to go. */
			if (tmpstr.c) {
				tmp = php_trim(tmpstr.c, strlen(tmpstr.c), NULL, 0, NULL, 3 TSRMLS_CC);
				smart_str_free(&tmpstr);
			}
		}
		if (Z_TYPE_PP(tmpzval) == IS_STRING && Z_STRLEN_PP(tmpzval)) {
			/* Remove newlines and spaces from start and end php_trim will estrndup() */
			tmp = php_trim(Z_STRVAL_PP(tmpzval), Z_STRLEN_PP(tmpzval), NULL, 0, NULL, 3 TSRMLS_CC);
		}
		if (tmp && strlen(tmp) > 0) {
			char *s;

			user_headers = estrdup(tmp);

			/* Make lowercase for easy comparison against 'standard' headers */
			php_strtolower(tmp, strlen(tmp));

			if (!header_init) {
				/* strip POST headers on redirect */
				strip_header(user_headers, tmp, "content-length:");
				strip_header(user_headers, tmp, "content-type:");
			}

			if ((s = strstr(tmp, "user-agent:")) && 
			    (s == tmp || *(s-1) == '\r' || *(s-1) == '\n' || 
			                 *(s-1) == '\t' || *(s-1) == ' ')) {
				 have_header |= HTTP_HEADER_USER_AGENT;
			}
			if ((s = strstr(tmp, "host:")) &&
			    (s == tmp || *(s-1) == '\r' || *(s-1) == '\n' || 
			                 *(s-1) == '\t' || *(s-1) == ' ')) {
				 have_header |= HTTP_HEADER_HOST;
			}
			if ((s = strstr(tmp, "from:")) &&
			    (s == tmp || *(s-1) == '\r' || *(s-1) == '\n' || 
			                 *(s-1) == '\t' || *(s-1) == ' ')) {
				 have_header |= HTTP_HEADER_FROM;
				}
			if ((s = strstr(tmp, "authorization:")) &&
			    (s == tmp || *(s-1) == '\r' || *(s-1) == '\n' || 
			                 *(s-1) == '\t' || *(s-1) == ' ')) {
				 have_header |= HTTP_HEADER_AUTH;
			}
			if ((s = strstr(tmp, "content-length:")) &&
			    (s == tmp || *(s-1) == '\r' || *(s-1) == '\n' || 
			                 *(s-1) == '\t' || *(s-1) == ' ')) {
				 have_header |= HTTP_HEADER_CONTENT_LENGTH;
			}
			if ((s = strstr(tmp, "content-type:")) &&
			    (s == tmp || *(s-1) == '\r' || *(s-1) == '\n' || 
			                 *(s-1) == '\t' || *(s-1) == ' ')) {
				 have_header |= HTTP_HEADER_TYPE;
			}
			if ((s = strstr(tmp, "connection:")) &&
			    (s == tmp || *(s-1) == '\r' || *(s-1) == '\n' || 
			                 *(s-1) == '\t' || *(s-1) == ' ')) {
				 have_header |= HTTP_HEADER_CONNECTION;
			}
			/* remove Proxy-Authorization header */
			if (use_proxy && use_ssl && (s = strstr(tmp, "proxy-authorization:")) &&
			    (s == tmp || *(s-1) == '\r' || *(s-1) == '\n' || 
			                 *(s-1) == '\t' || *(s-1) == ' ')) {
				char *p = s + sizeof("proxy-authorization:") - 1;
				
				while (s > tmp && (*(s-1) == ' ' || *(s-1) == '\t')) s--;
				while (*p != 0 && *p != '\r' && *p != '\n') p++;
				while (*p == '\r' || *p == '\n') p++;
				if (*p == 0) {
					if (s == tmp) {
						efree(user_headers);
						user_headers = NULL;
					} else {
						while (s > tmp && (*(s-1) == '\r' || *(s-1) == '\n')) s--;
						user_headers[s - tmp] = 0;
					}
				} else {
					memmove(user_headers + (s - tmp), user_headers + (p - tmp), strlen(p) + 1);
				}
			}

		}
		if (tmp) {
			efree(tmp);
		}
	}

	/* auth header if it was specified */
	if (((have_header & HTTP_HEADER_AUTH) == 0) && resource->user) {
		/* decode the strings first */
		php_url_decode(resource->user, strlen(resource->user));

		/* scratch is large enough, since it was made large enough for the whole URL */
		strcpy(scratch, resource->user);
		strcat(scratch, ":");

		/* Note: password is optional! */
		if (resource->pass) {
			php_url_decode(resource->pass, strlen(resource->pass));
			strcat(scratch, resource->pass);
		}

		tmp = (char*)php_base64_encode((unsigned char*)scratch, strlen(scratch), NULL);
		
		if (snprintf(scratch, scratch_len, "Authorization: Basic %s\r\n", tmp) > 0) {
			php_stream_write(stream, scratch, strlen(scratch));
			php_stream_notify_info(context, PHP_STREAM_NOTIFY_AUTH_REQUIRED, NULL, 0);
		}

		efree(tmp);
		tmp = NULL;
	}

	/* if the user has configured who they are, send a From: line */
	if (((have_header & HTTP_HEADER_FROM) == 0) && FG(from_address)) {
		if (snprintf(scratch, scratch_len, "From: %s\r\n", FG(from_address)) > 0)
			php_stream_write(stream, scratch, strlen(scratch));
	}

	/* Send Host: header so name-based virtual hosts work */
	if ((have_header & HTTP_HEADER_HOST) == 0) {
		if ((use_ssl && resource->port != 443 && resource->port != 0) || 
			(!use_ssl && resource->port != 80 && resource->port != 0)) {
			if (snprintf(scratch, scratch_len, "Host: %s:%i\r\n", resource->host, resource->port) > 0)
				php_stream_write(stream, scratch, strlen(scratch));
		} else {
			if (snprintf(scratch, scratch_len, "Host: %s\r\n", resource->host) > 0) {
				php_stream_write(stream, scratch, strlen(scratch));
			}
		}
	}

	/* Send a Connection: close header when using HTTP 1.1 or later to avoid
	 * hanging when the server interprets the RFC literally and establishes a
	 * keep-alive connection, unless the user specifically requests something
	 * else by specifying a Connection header in the context options. */
	if (protocol_version &&
	    ((have_header & HTTP_HEADER_CONNECTION) == 0) &&
	    (strncmp(protocol_version, "1.0", MIN(protocol_version_len, 3)) > 0)) {
		php_stream_write_string(stream, "Connection: close\r\n");
	}

	if (context && 
	    php_stream_context_get_option(context, "http", "user_agent", &ua_zval) == SUCCESS &&
		Z_TYPE_PP(ua_zval) == IS_STRING) {
		ua_str = Z_STRVAL_PP(ua_zval);
	} else if (FG(user_agent)) {
		ua_str = FG(user_agent);
	}

	if (((have_header & HTTP_HEADER_USER_AGENT) == 0) && ua_str) {
#define _UA_HEADER "User-Agent: %s\r\n"
		char *ua;
		size_t ua_len;
		
		ua_len = sizeof(_UA_HEADER) + strlen(ua_str);
		
		/* ensure the header is only sent if user_agent is not blank */
		if (ua_len > sizeof(_UA_HEADER)) {
			ua = emalloc(ua_len + 1);
			if ((ua_len = slprintf(ua, ua_len, _UA_HEADER, ua_str)) > 0) {
				ua[ua_len] = 0;
				php_stream_write(stream, ua, ua_len);
			} else {
				php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot construct User-agent header");
			}

			if (ua) {
				efree(ua);
			}
		}	
	}

	if (user_headers) {
		/* A bit weird, but some servers require that Content-Length be sent prior to Content-Type for POST
		 * see bug #44603 for details. Since Content-Type maybe part of user's headers we need to do this check first.
		 */
		if (
				header_init &&
				context &&
				!(have_header & HTTP_HEADER_CONTENT_LENGTH) &&
				php_stream_context_get_option(context, "http", "content", &tmpzval) == SUCCESS &&
				Z_TYPE_PP(tmpzval) == IS_STRING && Z_STRLEN_PP(tmpzval) > 0
		) {
			scratch_len = slprintf(scratch, scratch_len, "Content-Length: %d\r\n", Z_STRLEN_PP(tmpzval));
			php_stream_write(stream, scratch, scratch_len);
			have_header |= HTTP_HEADER_CONTENT_LENGTH;
		}

		php_stream_write(stream, user_headers, strlen(user_headers));
		php_stream_write(stream, "\r\n", sizeof("\r\n")-1);
		efree(user_headers);
	}

	/* Request content, such as for POST requests */
	if (header_init && context &&
		php_stream_context_get_option(context, "http", "content", &tmpzval) == SUCCESS &&
		Z_TYPE_PP(tmpzval) == IS_STRING && Z_STRLEN_PP(tmpzval) > 0) {
		if (!(have_header & HTTP_HEADER_CONTENT_LENGTH)) {
			scratch_len = slprintf(scratch, scratch_len, "Content-Length: %d\r\n", Z_STRLEN_PP(tmpzval));
			php_stream_write(stream, scratch, scratch_len);
		}
		if (!(have_header & HTTP_HEADER_TYPE)) {
			php_stream_write(stream, "Content-Type: application/x-www-form-urlencoded\r\n",
				sizeof("Content-Type: application/x-www-form-urlencoded\r\n") - 1);
			php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Content-type not specified assuming application/x-www-form-urlencoded");
		}
		php_stream_write(stream, "\r\n", sizeof("\r\n")-1);
		php_stream_write(stream, Z_STRVAL_PP(tmpzval), Z_STRLEN_PP(tmpzval));
	} else {
		php_stream_write(stream, "\r\n", sizeof("\r\n")-1);
	}

	location[0] = '\0';

	if (!EG(active_symbol_table)) {
		zend_rebuild_symbol_table(TSRMLS_C);
	}

	if (header_init) {
		zval *ztmp;
		MAKE_STD_ZVAL(ztmp);
		array_init(ztmp);
		ZEND_SET_SYMBOL(EG(active_symbol_table), "http_response_header", ztmp);
	}

	{
		zval **rh;
		zend_hash_find(EG(active_symbol_table), "http_response_header", sizeof("http_response_header"), (void **) &rh);
		response_header = *rh;
	}

	if (!php_stream_eof(stream)) {
		size_t tmp_line_len;
		/* get response header */

		if (php_stream_get_line(stream, tmp_line, sizeof(tmp_line) - 1, &tmp_line_len) != NULL) {
			zval *http_response;

			if (tmp_line_len > 9) {
				response_code = atoi(tmp_line + 9);
			} else {
				response_code = 0;
			}
			if (context && SUCCESS==php_stream_context_get_option(context, "http", "ignore_errors", &tmpzval)) {
				ignore_errors = zend_is_true(*tmpzval TSRMLS_CC);
			}
			/* when we request only the header, don't fail even on error codes */
			if ((options & STREAM_ONLY_GET_HEADERS) || ignore_errors) {
				reqok = 1;
			}
			/* all status codes in the 2xx range are defined by the specification as successful;
			 * all status codes in the 3xx range are for redirection, and so also should never
			 * fail */
			if (response_code >= 200 && response_code < 400) {
				reqok = 1;
			} else {
				switch(response_code) {
					case 403:
						php_stream_notify_error(context, PHP_STREAM_NOTIFY_AUTH_RESULT,
								tmp_line, response_code);
						break;
					default:
						/* safety net in the event tmp_line == NULL */
						if (!tmp_line_len) {
							tmp_line[0] = '\0';
						}
						php_stream_notify_error(context, PHP_STREAM_NOTIFY_FAILURE,
								tmp_line, response_code);
				}
			}
			if (tmp_line[tmp_line_len - 1] == '\n') {
				--tmp_line_len;
				if (tmp_line[tmp_line_len - 1] == '\r') {
					--tmp_line_len;
				}
			}
			MAKE_STD_ZVAL(http_response);
			ZVAL_STRINGL(http_response, tmp_line, tmp_line_len, 1);
			zend_hash_next_index_insert(Z_ARRVAL_P(response_header), &http_response, sizeof(zval *), NULL);
		}
	} else {
		php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "HTTP request failed, unexpected end of socket!");
		goto out;
	}
	
	/* read past HTTP headers */
	
	http_header_line = emalloc(HTTP_HEADER_BLOCK_SIZE);

	while (!body && !php_stream_eof(stream)) {
		size_t http_header_line_length;
		if (php_stream_get_line(stream, http_header_line, HTTP_HEADER_BLOCK_SIZE, &http_header_line_length) && *http_header_line != '\n' && *http_header_line != '\r') {
			char *e = http_header_line + http_header_line_length - 1;
			if (*e != '\n') {
				do { /* partial header */
					if (php_stream_get_line(stream, http_header_line, HTTP_HEADER_BLOCK_SIZE, &http_header_line_length) == NULL) {
						php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "Failed to read HTTP headers");
						goto out;
					}
					e = http_header_line + http_header_line_length - 1;
				} while (*e != '\n');
				continue;
			}
			while (*e == '\n' || *e == '\r') {
				e--;
			}
			http_header_line_length = e - http_header_line + 1;
			http_header_line[http_header_line_length] = '\0';

			if (!strncasecmp(http_header_line, "Location: ", 10)) {
				if (context && php_stream_context_get_option(context, "http", "follow_location", &tmpzval) == SUCCESS) {
					SEPARATE_ZVAL(tmpzval);
					convert_to_long_ex(tmpzval);
					follow_location = Z_LVAL_PP(tmpzval);
				} else if (!(response_code >= 300 && response_code < 304 || 307 == response_code || 308 == response_code)) {
					/* we shouldn't redirect automatically
					if follow_location isn't set and response_code not in (300, 301, 302, 303 and 307) 
					see http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.3.1
					RFC 7238 defines 308: http://tools.ietf.org/html/rfc7238 */
					follow_location = 0;
				}
				strlcpy(location, http_header_line + 10, sizeof(location));
			} else if (!strncasecmp(http_header_line, "Content-Type: ", 14)) {
				php_stream_notify_info(context, PHP_STREAM_NOTIFY_MIME_TYPE_IS, http_header_line + 14, 0);
			} else if (!strncasecmp(http_header_line, "Content-Length: ", 16)) {
				file_size = atoi(http_header_line + 16);
				php_stream_notify_file_size(context, file_size, http_header_line, 0);
			} else if (!strncasecmp(http_header_line, "Transfer-Encoding: chunked", sizeof("Transfer-Encoding: chunked"))) {

				/* create filter to decode response body */
				if (!(options & STREAM_ONLY_GET_HEADERS)) {
					long decode = 1;

					if (context && php_stream_context_get_option(context, "http", "auto_decode", &tmpzval) == SUCCESS) {
						SEPARATE_ZVAL(tmpzval);
						convert_to_boolean(*tmpzval);
						decode = Z_LVAL_PP(tmpzval);
					}
					if (decode) {
						transfer_encoding = php_stream_filter_create("dechunk", NULL, php_stream_is_persistent(stream) TSRMLS_CC);
						if (transfer_encoding) {
							/* don't store transfer-encodeing header */
							continue;
						}
					}
				}
			}

			if (http_header_line[0] == '\0') {
				body = 1;
			} else {
				zval *http_header;

				MAKE_STD_ZVAL(http_header);

				ZVAL_STRINGL(http_header, http_header_line, http_header_line_length, 1);
				
				zend_hash_next_index_insert(Z_ARRVAL_P(response_header), &http_header, sizeof(zval *), NULL);
			}
		} else {
			break;
		}
	}

	if (!reqok || (location[0] != '\0' && follow_location)) {
		if (!follow_location || (((options & STREAM_ONLY_GET_HEADERS) || ignore_errors) && redirect_max <= 1)) {
			goto out;
		}

		if (location[0] != '\0')
			php_stream_notify_info(context, PHP_STREAM_NOTIFY_REDIRECTED, location, 0);

		php_stream_close(stream);
		stream = NULL;

		if (location[0] != '\0') {

			char new_path[HTTP_HEADER_BLOCK_SIZE];
			char loc_path[HTTP_HEADER_BLOCK_SIZE];

			*new_path='\0';
			if (strlen(location)<8 || (strncasecmp(location, "http://", sizeof("http://")-1) && 
							strncasecmp(location, "https://", sizeof("https://")-1) && 
							strncasecmp(location, "ftp://", sizeof("ftp://")-1) && 
							strncasecmp(location, "ftps://", sizeof("ftps://")-1))) 
			{
				if (*location != '/') {
					if (*(location+1) != '\0' && resource->path) {
						char *s = strrchr(resource->path, '/');
						if (!s) {
							s = resource->path;
							if (!s[0]) {
								efree(s);
								s = resource->path = estrdup("/");
							} else {
								*s = '/';
							}
						}
						s[1] = '\0'; 
						if (resource->path && *(resource->path) == '/' && *(resource->path + 1) == '\0') {
							snprintf(loc_path, sizeof(loc_path) - 1, "%s%s", resource->path, location);
						} else {
							snprintf(loc_path, sizeof(loc_path) - 1, "%s/%s", resource->path, location);
						}
					} else {
						snprintf(loc_path, sizeof(loc_path) - 1, "/%s", location);
					}
				} else {
					strlcpy(loc_path, location, sizeof(loc_path));
				}
				if ((use_ssl && resource->port != 443) || (!use_ssl && resource->port != 80)) {
					snprintf(new_path, sizeof(new_path) - 1, "%s://%s:%d%s", resource->scheme, resource->host, resource->port, loc_path);
				} else {
					snprintf(new_path, sizeof(new_path) - 1, "%s://%s%s", resource->scheme, resource->host, loc_path);
				}
			} else {
				strlcpy(new_path, location, sizeof(new_path));
			}

			php_url_free(resource);
			/* check for invalid redirection URLs */
			if ((resource = php_url_parse(new_path)) == NULL) {
				php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "Invalid redirect URL! %s", new_path);
				goto out;
			}

#define CHECK_FOR_CNTRL_CHARS(val) { \
	if (val) { \
		unsigned char *s, *e; \
		int l; \
		l = php_url_decode(val, strlen(val)); \
		s = (unsigned char*)val; e = s + l; \
		while (s < e) { \
			if (iscntrl(*s)) { \
				php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "Invalid redirect URL! %s", new_path); \
				goto out; \
			} \
			s++; \
		} \
	} \
}
			/* check for control characters in login, password & path */
			if (strncasecmp(new_path, "http://", sizeof("http://") - 1) || strncasecmp(new_path, "https://", sizeof("https://") - 1)) {
				CHECK_FOR_CNTRL_CHARS(resource->user)
				CHECK_FOR_CNTRL_CHARS(resource->pass)
				CHECK_FOR_CNTRL_CHARS(resource->path)
			}
			stream = php_stream_url_wrap_http_ex(wrapper, new_path, mode, options, opened_path, context, --redirect_max, HTTP_WRAPPER_REDIRECTED STREAMS_CC TSRMLS_CC);
		} else {
Пример #7
0
SAPI_API SAPI_TREAT_DATA_FUNC(php_default_treat_data)
{
	char *res = NULL, *var, *val, *separator = NULL;
	const char *c_var;
	zval array;
	int free_buffer = 0;
	char *strtok_buf = NULL;
	zend_long count = 0;

	ZVAL_UNDEF(&array);
	switch (arg) {
		case PARSE_POST:
		case PARSE_GET:
		case PARSE_COOKIE:
			array_init(&array);
			switch (arg) {
				case PARSE_POST:
					zval_ptr_dtor(&PG(http_globals)[TRACK_VARS_POST]);
					ZVAL_COPY_VALUE(&PG(http_globals)[TRACK_VARS_POST], &array);
					break;
				case PARSE_GET:
					zval_ptr_dtor(&PG(http_globals)[TRACK_VARS_GET]);
					ZVAL_COPY_VALUE(&PG(http_globals)[TRACK_VARS_GET], &array);
					break;
				case PARSE_COOKIE:
					zval_ptr_dtor(&PG(http_globals)[TRACK_VARS_COOKIE]);
					ZVAL_COPY_VALUE(&PG(http_globals)[TRACK_VARS_COOKIE], &array);
					break;
			}
			break;
		default:
			ZVAL_COPY_VALUE(&array, destArray);
			break;
	}

	if (arg == PARSE_POST) {
		sapi_handle_post(&array);
		return;
	}

	if (arg == PARSE_GET) {		/* GET data */
		c_var = SG(request_info).query_string;
		if (c_var && *c_var) {
			res = (char *) estrdup(c_var);
			free_buffer = 1;
		} else {
			free_buffer = 0;
		}
	} else if (arg == PARSE_COOKIE) {		/* Cookie data */
		c_var = SG(request_info).cookie_data;
		if (c_var && *c_var) {
			res = (char *) estrdup(c_var);
			free_buffer = 1;
		} else {
			free_buffer = 0;
		}
	} else if (arg == PARSE_STRING) {		/* String data */
		res = str;
		free_buffer = 1;
	}

	if (!res) {
		return;
	}

	switch (arg) {
		case PARSE_GET:
		case PARSE_STRING:
			separator = (char *) estrdup(PG(arg_separator).input);
			break;
		case PARSE_COOKIE:
			separator = ";\0";
			break;
	}

	var = php_strtok_r(res, separator, &strtok_buf);

	while (var) {
		val = strchr(var, '=');

		if (arg == PARSE_COOKIE) {
			/* Remove leading spaces from cookie names, needed for multi-cookie header where ; can be followed by a space */
			while (isspace(*var)) {
				var++;
			}
			if (var == val || *var == '\0') {
				goto next_cookie;
			}
		}

		if (++count > PG(max_input_vars)) {
			php_error_docref(NULL, E_WARNING, "Input variables exceeded " ZEND_LONG_FMT ". To increase the limit change max_input_vars in php.ini.", PG(max_input_vars));
			break;
		}

		if (val) { /* have a value */
			size_t val_len;
			size_t new_val_len;

			*val++ = '\0';
			php_url_decode(var, strlen(var));
			val_len = php_url_decode(val, strlen(val));
			val = estrndup(val, val_len);
			if (sapi_module.input_filter(arg, var, &val, val_len, &new_val_len)) {
				php_register_variable_safe(var, val, new_val_len, &array);
			}
			efree(val);
		} else {
			size_t val_len;
			size_t new_val_len;

			php_url_decode(var, strlen(var));
			val_len = 0;
			val = estrndup("", val_len);
			if (sapi_module.input_filter(arg, var, &val, val_len, &new_val_len)) {
				php_register_variable_safe(var, val, new_val_len, &array);
			}
			efree(val);
		}
next_cookie:
		var = php_strtok_r(NULL, separator, &strtok_buf);
	}

	if (arg != PARSE_COOKIE) {
		efree(separator);
	}

	if (free_buffer) {
		efree(res);
	}
}
Пример #8
0
PDO_API int php_pdo_parse_data_source(const char *data_source,
		unsigned long data_source_len, struct pdo_data_src_parser *parsed,
		int nparams)
{
	int i, j;
	int valstart = -1;
	int semi = -1;
	int optstart = 0;
	int nlen;
	int n_matches = 0;
	int n_semicolumns = 0;

	i = 0;
	while (i < data_source_len) {
		/* looking for NAME= */

		if (data_source[i] == '\0') {
			break;
		}

		if (data_source[i] != '=') {
			++i;
			continue;
		}

		valstart = ++i;

		/* now we're looking for VALUE; or just VALUE<NUL> */
		semi = -1;
		n_semicolumns = 0;
		while (i < data_source_len) {
			if (data_source[i] == '\0') {
				semi = i++;
				break;
			}
			if (data_source[i] == ';') {
				if ((i + 1 >= data_source_len) || data_source[i+1] != ';') {
					semi = i++;
					break;
				} else {
					n_semicolumns++; 
					i += 2;
					continue;
				}
			}
			++i;
		}

		if (semi == -1) {
			semi = i;
		}

		/* find the entry in the array */
		nlen = valstart - optstart - 1;
		for (j = 0; j < nparams; j++) {
			if (0 == strncmp(data_source + optstart, parsed[j].optname, nlen) && parsed[j].optname[nlen] == '\0') {
				/* got a match */
				if (parsed[j].freeme) {
					efree(parsed[j].optval);
				}

				if (n_semicolumns == 0) {
					parsed[j].optval = estrndup(data_source + valstart, semi - valstart - n_semicolumns);
				} else {
					int vlen = semi - valstart;
					const char *orig_val = data_source + valstart;
					char *new_val  = (char *) emalloc(vlen - n_semicolumns + 1);
				
					parsed[j].optval = new_val;

					while (vlen && *orig_val) {
						*new_val = *orig_val;
						new_val++;

						if (*orig_val == ';') {
							orig_val+=2; 
							vlen-=2;
						} else {
							orig_val++;
							vlen--;
						}
					}
					*new_val = '\0';
				}

				parsed[j].freeme = 1;
				++n_matches;
				break;
			}
		}

		while (i < data_source_len && isspace(data_source[i])) {
			i++;
		}

		optstart = i;
	}

	return n_matches;
}
Пример #9
0
/* {{{ fix the scope of methods such that self:: and parent:: work everywhere */
static int pthreads_apply_property_scope(zend_property_info *info, PTHREAD thread TSRMLS_DC); /* }}} */

/* {{{ prepared resource destructor */
static void pthreads_prepared_resource_dtor(zend_rsrc_list_entry *entry); /* }}} */

static zend_class_entry* pthreads_copy_entry(PTHREAD thread, zend_class_entry *candidate TSRMLS_DC) {
    zval *tz;
	zend_function *tf;
	zend_property_info *ti;
    zend_class_entry *prepared = NULL;
    
	/* create a new user class for this context */
	prepared = (zend_class_entry*) emalloc(sizeof(zend_class_entry));
	prepared->name = estrndup(candidate->name, candidate->name_length);
	prepared->name_length = candidate->name_length;
	prepared->type = candidate->type;
	
	/* initialize class data */
	zend_initialize_class_data(prepared, 1 TSRMLS_CC);
	
	/* set ce flags (reset by initialize) */
	prepared->ce_flags = candidate->ce_flags;
	
	/* set parent */
	if (candidate->parent)
	    prepared->parent = pthreads_prepared_entry(thread, candidate->parent TSRMLS_CC);
	
	/* declare interfaces */
	if (candidate->num_interfaces) {
Пример #10
0
/** {{{ int yaf_route_map_route(yaf_route_t *route, yaf_request_t *request)
*/
int yaf_route_map_route(yaf_route_t *route, yaf_request_t *request) {
	zval *ctl_prefer, *delimer, *zuri, *base_uri, params;
	char *req_uri, *tmp, *rest, *ptrptr, *seg;
	char *query_str = NULL;
	uint seg_len = 0;

	smart_str route_result = {0};

	zuri = zend_read_property(yaf_request_ce, request, ZEND_STRL(YAF_REQUEST_PROPERTY_NAME_URI), 1, NULL);
	base_uri = zend_read_property(yaf_request_ce, request, ZEND_STRL(YAF_REQUEST_PROPERTY_NAME_BASE), 1, NULL);

	ctl_prefer = zend_read_property(yaf_route_map_ce, route, ZEND_STRL(YAF_ROUTE_MAP_VAR_NAME_CTL_PREFER), 1, NULL);
	delimer	   = zend_read_property(yaf_route_map_ce, route, ZEND_STRL(YAF_ROUTE_MAP_VAR_NAME_DELIMETER), 1, NULL);

	if (base_uri && IS_STRING == Z_TYPE_P(base_uri)
			&& !strncasecmp(Z_STRVAL_P(zuri), Z_STRVAL_P(base_uri), Z_STRLEN_P(base_uri))) {
		req_uri  = estrdup(Z_STRVAL_P(zuri) + Z_STRLEN_P(base_uri));
	} else {
		req_uri  = estrdup(Z_STRVAL_P(zuri));
	}

	if (Z_TYPE_P(delimer) == IS_STRING
			&& Z_STRLEN_P(delimer)) {
		if ((query_str = strstr(req_uri, Z_STRVAL_P(delimer))) != NULL
			&& *(query_str - 1) == '/') {
			tmp  = req_uri;
			rest = query_str + Z_STRLEN_P(delimer);
			if (*rest == '\0') {
				req_uri 	= estrndup(req_uri, query_str - req_uri);
				query_str 	= NULL;
				efree(tmp);
			} else if (*rest == '/') {
				req_uri 	= estrndup(req_uri, query_str - req_uri);
				query_str   = estrdup(rest);
				efree(tmp);
			} else {
				query_str = NULL;
			}
		} else {
			query_str = NULL;
		}
	}

	seg = php_strtok_r(req_uri, YAF_ROUTER_URL_DELIMIETER, &ptrptr);
	while (seg) {
		seg_len = strlen(seg);
		if (seg_len) {
			smart_str_appendl(&route_result, seg, seg_len);
		}
		smart_str_appendc(&route_result, '_');
		seg = php_strtok_r(NULL, YAF_ROUTER_URL_DELIMIETER, &ptrptr);
	}

	if (route_result.s) {
		ZSTR_LEN(route_result.s)--;
		ZSTR_VAL(route_result.s)[ZSTR_LEN(route_result.s)] = '\0';
		if (Z_TYPE_P(ctl_prefer) == IS_TRUE) {
			zend_update_property_str(yaf_request_ce,
					request, ZEND_STRL(YAF_REQUEST_PROPERTY_NAME_CONTROLLER), route_result.s);
		} else {
			zend_update_property_str(yaf_request_ce,
					request, ZEND_STRL(YAF_REQUEST_PROPERTY_NAME_ACTION), route_result.s);
		}
		smart_str_free(&route_result);
	}

	if (query_str) {
		(void)yaf_router_parse_parameters(query_str, &params);
		(void)yaf_request_set_params_multi(request, &params);
		zval_ptr_dtor(&params);
		efree(query_str);
	}

	efree(req_uri);

	return 1;
}
Пример #11
0
    zend_object_std_dtor(&obj->std TSRMLS_CC);
    efree(obj);
}


zend_object_value splclassloader_create_object(zend_class_entry* class_type TSRMLS_DC)
{
    zend_object_value retval;

    splclassloader_object* obj = (splclassloader_object*)emalloc(sizeof(splclassloader_object));
    memset(obj, 0, sizeof(splclassloader_object));

    zend_object_std_init(&obj->std, class_type TSRMLS_CC);
    zend_hash_copy(obj->std.properties, &class_type->default_properties, (copy_ctor_func_t) zval_add_ref, (void*)0, sizeof(zval*));

    obj->file_ext = estrndup(".php", sizeof(".php")-1);
    obj->file_ext_len = sizeof(".php")-1;
    
    retval.handle = zend_objects_store_put(obj, (zend_objects_store_dtor_t)zend_objects_destroy_object, (void*)splclassloader_object_dtor, NULL TSRMLS_CC);
    retval.handlers = &splclassloader_object_handlers;

    return retval;
}


/* {{{ proto void SplClassLoader::__construct([string $namespace [, string $include_path]])
       Constructor */
PHP_METHOD(SplClassLoader, __construct)
{    
    char* ns = NULL;
    int   ns_len = 0;
Пример #12
0
/** {{{ zend_string * yaf_route_map_assemble(zval *info, zval *query)
 */
zend_string * yaf_route_map_assemble(yaf_route_t *this_ptr, zval *info, zval *query) {
	char *seg, *ptrptr, *pname;
	smart_str uri = {0};
	size_t seg_len;
	zend_bool has_delim = 0;
	zval *delim, *ctl_prefer, *zv;

	ctl_prefer = zend_read_property(yaf_route_map_ce, this_ptr, ZEND_STRL(YAF_ROUTE_MAP_VAR_NAME_CTL_PREFER), 1, NULL);
	delim = zend_read_property(yaf_route_map_ce, this_ptr, ZEND_STRL(YAF_ROUTE_MAP_VAR_NAME_DELIMETER), 1, NULL);

	if (IS_STRING == Z_TYPE_P(delim) && Z_STRLEN_P(delim)) {
		has_delim = 1;
	}

	do {
		if (Z_TYPE_P(ctl_prefer) == IS_TRUE) {
			if ((zv = zend_hash_str_find(Z_ARRVAL_P(info),
					ZEND_STRL(YAF_ROUTE_ASSEMBLE_ACTION_FORMAT))) != NULL && Z_TYPE_P(zv) == IS_STRING) {
				pname = estrndup(Z_STRVAL_P(zv), Z_STRLEN_P(zv));
			} else {
				yaf_trigger_error(YAF_ERR_TYPE_ERROR, "%s",
						"Undefined the 'action' parameter for the 1st parameter");
				break;
			}
		} else {
			if ((zv = zend_hash_str_find(Z_ARRVAL_P(info),
					ZEND_STRL(YAF_ROUTE_ASSEMBLE_CONTROLLER_FORMAT))) != NULL && Z_TYPE_P(zv) == IS_STRING) {
				pname = estrndup(Z_STRVAL_P(zv), Z_STRLEN_P(zv));
			} else {
				yaf_trigger_error(YAF_ERR_TYPE_ERROR, "%s",
						"Undefined the 'controller' parameter for the 1st parameter");
				break;
			}
		}

		seg = php_strtok_r(pname, "_", &ptrptr);	
		while (seg) {
			seg_len = strlen(seg);
			if (seg_len) {
				smart_str_appendc(&uri, '/');
				smart_str_appendl(&uri, seg, seg_len);
			}
			seg = php_strtok_r(NULL, "_", &ptrptr);
		}
		efree(pname);

		if (query && IS_ARRAY == Z_TYPE_P(query)) {
			zend_bool start = 1;
			zend_string *key, *val;

			if (has_delim) {
				smart_str_appendc(&uri, '/');
				smart_str_appendl(&uri, Z_STRVAL_P(delim), Z_STRLEN_P(delim));
			}

            ZEND_HASH_FOREACH_STR_KEY_VAL(Z_ARRVAL_P(query), key, zv) {
				if (key) {
					val = zval_get_string(zv);
					if (has_delim) {
						smart_str_appendc(&uri, '/');
						smart_str_appendl(&uri, ZSTR_VAL(key), ZSTR_LEN(key));
						smart_str_appendc(&uri, '/');
						smart_str_appendl(&uri, ZSTR_VAL(val), ZSTR_LEN(val));
					} else {
						if (start) {
							smart_str_appendc(&uri, '?');
							smart_str_appendl(&uri, ZSTR_VAL(key), ZSTR_LEN(key));
							smart_str_appendc(&uri, '=');
							smart_str_appendl(&uri, ZSTR_VAL(val), ZSTR_LEN(val));
							start = 0;
						} else {
							smart_str_appendc(&uri, '&');
							smart_str_appendl(&uri, ZSTR_VAL(key), ZSTR_LEN(key));
							smart_str_appendc(&uri, '=');
							smart_str_appendl(&uri, ZSTR_VAL(val), ZSTR_LEN(val));
						}
					}
					zend_string_release(val);
				}
			} ZEND_HASH_FOREACH_END();
		}

		smart_str_0(&uri);
		return uri.s;
	} while (0);
Пример #13
0
int phql_get_token(phql_scanner_state *s, phql_scanner_token *token) {

	char *q = YYCURSOR;
	int status = PHQL_SCANNER_RETCODE_IMPOSSIBLE;

	while(PHQL_SCANNER_RETCODE_IMPOSSIBLE == status) {

		
#line 45 "scanner.c"
		{
			YYCTYPE yych;

			yych = *YYCURSOR;
			switch (yych) {
			case 0x00:	goto yy53;
			case '\t':
			case '\n':
			case '\r':
			case ' ':	goto yy51;
			case '!':	goto yy43;
			case '"':	goto yy26;
			case '\'':	goto yy27;
			case '(':	goto yy39;
			case ')':	goto yy41;
			case '*':	goto yy33;
			case '+':	goto yy29;
			case ',':	goto yy37;
			case '-':	goto yy31;
			case '.':	goto yy4;
			case '/':	goto yy35;
			case '0':
			case '1':
			case '2':
			case '3':
			case '4':
			case '5':
			case '6':
			case '7':
			case '8':
			case '9':	goto yy2;
			case ':':	goto yy8;
			case '<':	goto yy45;
			case '=':	goto yy49;
			case '>':	goto yy47;
			case '?':	goto yy6;
			case 'A':
			case 'a':	goto yy14;
			case 'B':
			case 'b':	goto yy19;
			case 'C':
			case 'E':
			case 'K':
			case 'M':
			case 'P':
			case 'Q':
			case 'T':
			case 'X':
			case 'Y':
			case 'Z':
			case 'c':
			case 'e':
			case 'k':
			case 'm':
			case 'p':
			case 'q':
			case 't':
			case 'x':
			case 'y':
			case 'z':	goto yy28;
			case 'D':
			case 'd':	goto yy12;
			case 'F':
			case 'f':	goto yy13;
			case 'G':
			case 'g':	goto yy20;
			case 'H':
			case 'h':	goto yy21;
			case 'I':
			case 'i':	goto yy15;
			case 'J':
			case 'j':	goto yy24;
			case 'L':
			case 'l':	goto yy22;
			case 'N':
			case 'n':	goto yy23;
			case 'O':
			case 'o':	goto yy18;
			case 'R':
			case 'r':	goto yy25;
			case 'S':
			case 's':	goto yy11;
			case 'U':
			case 'u':	goto yy9;
			case 'V':
			case 'v':	goto yy16;
			case 'W':
			case 'w':	goto yy17;
			default:	goto yy55;
			}
yy2:
			++YYCURSOR;
			switch ((yych = *YYCURSOR)) {
			case '.':	goto yy192;
			case '0':
			case '1':
			case '2':
			case '3':
			case '4':
			case '5':
			case '6':
			case '7':
			case '8':
			case '9':	goto yy194;
			default:	goto yy3;
			}
yy3:
#line 46 "scanner.re"
			{
			token->opcode = PHQL_T_INTEGER;
			token->value = estrndup(q, YYCURSOR - q);
			token->len = YYCURSOR - q;
			q = YYCURSOR;
			return 0;
		}
#line 161 "scanner.c"
yy4:
			++YYCURSOR;
			switch ((yych = *YYCURSOR)) {
			case '0':
			case '1':
			case '2':
			case '3':
			case '4':
			case '5':
			case '6':
			case '7':
			case '8':
			case '9':	goto yy189;
			default:	goto yy5;
			}
yy5:
#line 254 "scanner.re"
			{
			token->opcode = PHQL_T_DOT;
			return 0;
		}
#line 183 "scanner.c"
yy6:
			++YYCURSOR;
			switch ((yych = *YYCURSOR)) {
			case '0':
			case '1':
			case '2':
			case '3':
			case '4':
			case '5':
			case '6':
			case '7':
			case '8':
			case '9':	goto yy186;
			default:	goto yy7;
			}
yy7:
#line 324 "scanner.re"
			{
			status = PHQL_SCANNER_RETCODE_ERR;
			break;
		}
#line 205 "scanner.c"
yy8:
			yych = *(YYMARKER = ++YYCURSOR);
			switch (yych) {
			case '0':
			case '1':
			case '2':
			case '3':
			case '4':
			case '5':
			case '6':
			case '7':
			case '8':
			case '9':
			case 'A':
			case 'B':
			case 'C':
			case 'D':
			case 'E':
			case 'F':
			case 'G':
			case 'H':
			case 'I':
			case 'J':
			case 'K':
			case 'L':
			case 'M':
			case 'N':
			case 'O':
			case 'P':
			case 'Q':
			case 'R':
			case 'S':
			case 'T':
			case 'U':
			case 'V':
			case 'W':
			case 'X':
			case 'Y':
			case 'Z':
			case '_':
			case 'a':
			case 'b':
			case 'c':
			case 'd':
			case 'e':
			case 'f':
			case 'g':
			case 'h':
			case 'i':
			case 'j':
			case 'k':
			case 'l':
			case 'm':
			case 'n':
			case 'o':
			case 'p':
			case 'q':
			case 'r':
			case 's':
			case 't':
			case 'u':
			case 'v':
			case 'w':
			case 'x':
			case 'y':
			case 'z':	goto yy182;
			default:	goto yy7;
			}
yy9:
			++YYCURSOR;
			switch ((yych = *YYCURSOR)) {
			case 'P':
			case 'p':	goto yy176;
			default:	goto yy67;
			}
yy10:
#line 226 "scanner.re"
			{
			token->opcode = PHQL_T_IDENTIFIER;
			token->value = estrndup(q, YYCURSOR - q);
			token->len = YYCURSOR - q;
			q = YYCURSOR;
			return 0;
		}
#line 290 "scanner.c"
yy11:
			yych = *++YYCURSOR;
			switch (yych) {
			case 'E':
			case 'e':	goto yy168;
			default:	goto yy67;
			}
yy12:
			yych = *++YYCURSOR;
			switch (yych) {
			case 'E':
			case 'e':	goto yy162;
			default:	goto yy67;
			}
yy13:
			yych = *++YYCURSOR;
			switch (yych) {
			case 'R':
			case 'r':	goto yy158;
			default:	goto yy67;
			}
yy14:
			yych = *++YYCURSOR;
			switch (yych) {
			case 'N':
			case 'n':	goto yy153;
			case 'S':
			case 's':	goto yy154;
			default:	goto yy67;
			}
yy15:
			yych = *++YYCURSOR;
			switch (yych) {
			case 'N':
			case 'n':	goto yy137;
			case 'S':
			case 's':	goto yy139;
			default:	goto yy67;
			}
yy16:
			yych = *++YYCURSOR;
			switch (yych) {
			case 'A':
			case 'a':	goto yy131;
			default:	goto yy67;
			}
yy17:
			yych = *++YYCURSOR;
			switch (yych) {
			case 'H':
			case 'h':	goto yy126;
			default:	goto yy67;
			}
yy18:
			yych = *++YYCURSOR;
			switch (yych) {
			case 'N':
			case 'n':	goto yy118;
			case 'R':
			case 'r':	goto yy120;
			default:	goto yy67;
			}
yy19:
			yych = *++YYCURSOR;
			switch (yych) {
			case 'Y':
			case 'y':	goto yy116;
			default:	goto yy67;
			}
yy20:
			yych = *++YYCURSOR;
			switch (yych) {
			case 'R':
			case 'r':	goto yy111;
			default:	goto yy67;
			}
yy21:
			yych = *++YYCURSOR;
			switch (yych) {
			case 'A':
			case 'a':	goto yy105;
			default:	goto yy67;
			}
yy22:
			yych = *++YYCURSOR;
			switch (yych) {
			case 'E':
			case 'e':	goto yy93;
			case 'I':
			case 'i':	goto yy94;
			default:	goto yy67;
			}
yy23:
			yych = *++YYCURSOR;
			switch (yych) {
			case 'O':
			case 'o':	goto yy86;
			case 'U':
			case 'u':	goto yy87;
			default:	goto yy67;
			}
yy24:
			yych = *++YYCURSOR;
			switch (yych) {
			case 'O':
			case 'o':	goto yy82;
			default:	goto yy67;
			}
yy25:
			yych = *++YYCURSOR;
			switch (yych) {
			case 'I':
			case 'i':	goto yy77;
			default:	goto yy67;
			}
yy26:
			yych = *(YYMARKER = ++YYCURSOR);
			if (yych <= 0x00) goto yy7;
			goto yy75;
yy27:
			yych = *(YYMARKER = ++YYCURSOR);
			if (yych <= 0x00) goto yy7;
			goto yy69;
yy28:
			yych = *++YYCURSOR;
			goto yy67;
yy29:
			++YYCURSOR;
#line 234 "scanner.re"
			{
			token->opcode = PHQL_T_ADD;
			return 0;
		}
#line 424 "scanner.c"
yy31:
			++YYCURSOR;
#line 239 "scanner.re"
			{
			token->opcode = PHQL_T_SUB;
			return 0;
		}
#line 432 "scanner.c"
yy33:
			++YYCURSOR;
#line 244 "scanner.re"
			{
			token->opcode = PHQL_T_MUL;
			return 0;
		}
#line 440 "scanner.c"
yy35:
			++YYCURSOR;
#line 249 "scanner.re"
			{
			token->opcode = PHQL_T_DIV;
			return 0;
		}
#line 448 "scanner.c"
yy37:
			++YYCURSOR;
#line 259 "scanner.re"
			{
			token->opcode = PHQL_T_COMMA;
			return 0;
		}
#line 456 "scanner.c"
yy39:
			++YYCURSOR;
#line 264 "scanner.re"
			{
			token->opcode = PHQL_T_BRACKET_OPEN;
			return 0;
		}
#line 464 "scanner.c"
yy41:
			++YYCURSOR;
#line 269 "scanner.re"
			{
			token->opcode = PHQL_T_BRACKET_CLOSE;
			return 0;
		}
#line 472 "scanner.c"
yy43:
			++YYCURSOR;
			switch ((yych = *YYCURSOR)) {
			case '=':	goto yy64;
			default:	goto yy44;
			}
yy44:
#line 299 "scanner.re"
			{
			token->opcode = PHQL_T_NOT;
			return 0;
		}
#line 485 "scanner.c"
yy45:
			++YYCURSOR;
			switch ((yych = *YYCURSOR)) {
			case '=':	goto yy60;
			case '>':	goto yy62;
			default:	goto yy46;
			}
yy46:
#line 304 "scanner.re"
			{
			token->opcode = PHQL_T_LESS;
			return 0;
		}
#line 499 "scanner.c"
yy47:
			++YYCURSOR;
			switch ((yych = *YYCURSOR)) {
			case '=':	goto yy58;
			default:	goto yy48;
			}
yy48:
#line 309 "scanner.re"
			{
			token->opcode = PHQL_T_GREATER;
			return 0;
		}
#line 512 "scanner.c"
yy49:
			++YYCURSOR;
#line 294 "scanner.re"
			{
			token->opcode = PHQL_T_EQUALS;
			return 0;
		}
#line 520 "scanner.c"
yy51:
			++YYCURSOR;
			yych = *YYCURSOR;
			goto yy57;
yy52:
#line 314 "scanner.re"
			{
			token->opcode = PHQL_T_IGNORE;
			return 0;
		}
#line 531 "scanner.c"
yy53:
			++YYCURSOR;
#line 319 "scanner.re"
			{
			status = PHQL_SCANNER_RETCODE_EOF;
			break;
		}
#line 539 "scanner.c"
yy55:
			yych = *++YYCURSOR;
			goto yy7;
yy56:
			++YYCURSOR;
			yych = *YYCURSOR;
yy57:
			switch (yych) {
			case '\t':
			case '\n':
			case '\r':
			case ' ':	goto yy56;
			default:	goto yy52;
			}
yy58:
			++YYCURSOR;
#line 289 "scanner.re"
			{
			token->opcode = PHQL_T_GREATEREQUAL;
			return 0;
		}
#line 561 "scanner.c"
yy60:
			++YYCURSOR;
#line 284 "scanner.re"
			{
			token->opcode = PHQL_T_LESSEQUAL;
			return 0;
		}
#line 569 "scanner.c"
yy62:
			++YYCURSOR;
#line 279 "scanner.re"
			{
			token->opcode = PHQL_T_NOTEQUALS;
			return 0;
		}
#line 577 "scanner.c"
yy64:
			++YYCURSOR;
#line 274 "scanner.re"
			{
			token->opcode = PHQL_T_NOTEQUALS;
			return 0;
		}
#line 585 "scanner.c"
yy66:
			++YYCURSOR;
			yych = *YYCURSOR;
yy67:
			switch (yych) {
			case '0':
			case '1':
			case '2':
			case '3':
			case '4':
			case '5':
			case '6':
			case '7':
			case '8':
			case '9':
			case 'A':
			case 'B':
			case 'C':
			case 'D':
			case 'E':
			case 'F':
			case 'G':
			case 'H':
			case 'I':
			case 'J':
			case 'K':
			case 'L':
			case 'M':
			case 'N':
			case 'O':
			case 'P':
			case 'Q':
			case 'R':
			case 'S':
			case 'T':
			case 'U':
			case 'V':
			case 'W':
			case 'X':
			case 'Y':
			case 'Z':
			case '_':
			case 'a':
			case 'b':
			case 'c':
			case 'd':
			case 'e':
			case 'f':
			case 'g':
			case 'h':
			case 'i':
			case 'j':
			case 'k':
			case 'l':
			case 'm':
			case 'n':
			case 'o':
			case 'p':
			case 'q':
			case 'r':
			case 's':
			case 't':
			case 'u':
			case 'v':
			case 'w':
			case 'x':
			case 'y':
			case 'z':	goto yy66;
			default:	goto yy10;
			}
yy68:
			++YYCURSOR;
			yych = *YYCURSOR;
yy69:
			switch (yych) {
			case 0x00:	goto yy70;
			case '\'':	goto yy72;
			case '\\':	goto yy71;
			default:	goto yy68;
			}
yy70:
			YYCURSOR = YYMARKER;
			goto yy7;
yy71:
			++YYCURSOR;
			yych = *YYCURSOR;
			switch (yych) {
			case '\n':	goto yy70;
			default:	goto yy68;
			}
yy72:
			++YYCURSOR;
#line 217 "scanner.re"
			{
			token->opcode = PHQL_T_STRING;
			token->value = estrndup(q, YYCURSOR - q - 1);
			token->len = YYCURSOR - q - 1;
			q = YYCURSOR;
			return 0;
		}
#line 686 "scanner.c"
yy74:
			++YYCURSOR;
			yych = *YYCURSOR;
yy75:
			switch (yych) {
			case 0x00:	goto yy70;
			case '"':	goto yy72;
			case '\\':	goto yy76;
			default:	goto yy74;
			}
yy76:
			++YYCURSOR;
			yych = *YYCURSOR;
			switch (yych) {
			case '\n':	goto yy70;
			default:	goto yy74;
			}
yy77:
			yych = *++YYCURSOR;
			switch (yych) {
			case 'G':
			case 'g':	goto yy78;
			default:	goto yy67;
			}
yy78:
			yych = *++YYCURSOR;
			switch (yych) {
			case 'H':
			case 'h':	goto yy79;
			default:	goto yy67;
			}
yy79:
			yych = *++YYCURSOR;
			switch (yych) {
			case 'T':
			case 't':	goto yy80;
			default:	goto yy67;
			}
yy80:
			++YYCURSOR;
			switch ((yych = *YYCURSOR)) {
			case '0':
			case '1':
			case '2':
			case '3':
			case '4':
			case '5':
			case '6':
			case '7':
			case '8':
			case '9':
			case 'A':
			case 'B':
			case 'C':
			case 'D':
			case 'E':
			case 'F':
			case 'G':
			case 'H':
			case 'I':
			case 'J':
			case 'K':
			case 'L':
			case 'M':
			case 'N':
			case 'O':
			case 'P':
			case 'Q':
			case 'R':
			case 'S':
			case 'T':
			case 'U':
			case 'V':
			case 'W':
			case 'X':
			case 'Y':
			case 'Z':
			case '_':
			case 'a':
			case 'b':
			case 'c':
			case 'd':
			case 'e':
			case 'f':
			case 'g':
			case 'h':
			case 'i':
			case 'j':
			case 'k':
			case 'l':
			case 'm':
			case 'n':
			case 'o':
			case 'p':
			case 'q':
			case 'r':
			case 's':
			case 't':
			case 'u':
			case 'v':
			case 'w':
			case 'x':
			case 'y':
			case 'z':	goto yy66;
			default:	goto yy81;
			}
yy81:
#line 201 "scanner.re"
			{
			token->opcode = PHQL_T_RIGHT;
			return 0;
		}
#line 799 "scanner.c"
yy82:
			yych = *++YYCURSOR;
			switch (yych) {
			case 'I':
			case 'i':	goto yy83;
			default:	goto yy67;
			}
yy83:
			yych = *++YYCURSOR;
			switch (yych) {
			case 'N':
			case 'n':	goto yy84;
			default:	goto yy67;
			}
yy84:
			++YYCURSOR;
			switch ((yych = *YYCURSOR)) {
			case '0':
			case '1':
			case '2':
			case '3':
			case '4':
			case '5':
			case '6':
			case '7':
			case '8':
			case '9':
			case 'A':
			case 'B':
			case 'C':
			case 'D':
			case 'E':
			case 'F':
			case 'G':
			case 'H':
			case 'I':
			case 'J':
			case 'K':
			case 'L':
			case 'M':
			case 'N':
			case 'O':
			case 'P':
			case 'Q':
			case 'R':
			case 'S':
			case 'T':
			case 'U':
			case 'V':
			case 'W':
			case 'X':
			case 'Y':
			case 'Z':
			case '_':
			case 'a':
			case 'b':
			case 'c':
			case 'd':
			case 'e':
			case 'f':
			case 'g':
			case 'h':
			case 'i':
			case 'j':
			case 'k':
			case 'l':
			case 'm':
			case 'n':
			case 'o':
			case 'p':
			case 'q':
			case 'r':
			case 's':
			case 't':
			case 'u':
			case 'v':
			case 'w':
			case 'x':
			case 'y':
			case 'z':	goto yy66;
			default:	goto yy85;
			}
yy85:
#line 186 "scanner.re"
			{
			token->opcode = PHQL_T_JOIN;
			return 0;
		}
#line 888 "scanner.c"
yy86:
			yych = *++YYCURSOR;
			switch (yych) {
			case 'T':
			case 't':	goto yy91;
			default:	goto yy67;
			}
yy87:
			yych = *++YYCURSOR;
			switch (yych) {
			case 'L':
			case 'l':	goto yy88;
			default:	goto yy67;
			}
yy88:
			yych = *++YYCURSOR;
			switch (yych) {
			case 'L':
			case 'l':	goto yy89;
			default:	goto yy67;
			}
yy89:
			++YYCURSOR;
			switch ((yych = *YYCURSOR)) {
			case '0':
			case '1':
			case '2':
			case '3':
			case '4':
			case '5':
			case '6':
			case '7':
			case '8':
			case '9':
			case 'A':
			case 'B':
			case 'C':
			case 'D':
			case 'E':
			case 'F':
			case 'G':
			case 'H':
			case 'I':
			case 'J':
			case 'K':
			case 'L':
			case 'M':
			case 'N':
			case 'O':
			case 'P':
			case 'Q':
			case 'R':
			case 'S':
			case 'T':
			case 'U':
			case 'V':
			case 'W':
			case 'X':
			case 'Y':
			case 'Z':
			case '_':
			case 'a':
			case 'b':
			case 'c':
			case 'd':
			case 'e':
			case 'f':
			case 'g':
			case 'h':
			case 'i':
			case 'j':
			case 'k':
			case 'l':
			case 'm':
			case 'n':
			case 'o':
			case 'p':
			case 'q':
			case 'r':
			case 's':
			case 't':
			case 'u':
			case 'v':
			case 'w':
			case 'x':
			case 'y':
			case 'z':	goto yy66;
			default:	goto yy90;
			}
yy90:
#line 211 "scanner.re"
			{
			token->opcode = PHQL_T_NULL;
			return 0;
		}
#line 984 "scanner.c"
yy91:
			++YYCURSOR;
			switch ((yych = *YYCURSOR)) {
			case '0':
			case '1':
			case '2':
			case '3':
			case '4':
			case '5':
			case '6':
			case '7':
			case '8':
			case '9':
			case 'A':
			case 'B':
			case 'C':
			case 'D':
			case 'E':
			case 'F':
			case 'G':
			case 'H':
			case 'I':
			case 'J':
			case 'K':
			case 'L':
			case 'M':
			case 'N':
			case 'O':
			case 'P':
			case 'Q':
			case 'R':
			case 'S':
			case 'T':
			case 'U':
			case 'V':
			case 'W':
			case 'X':
			case 'Y':
			case 'Z':
			case '_':
			case 'a':
			case 'b':
			case 'c':
			case 'd':
			case 'e':
			case 'f':
			case 'g':
			case 'h':
			case 'i':
			case 'j':
			case 'k':
			case 'l':
			case 'm':
			case 'n':
			case 'o':
			case 'p':
			case 'q':
			case 'r':
			case 's':
			case 't':
			case 'u':
			case 'v':
			case 'w':
			case 'x':
			case 'y':
			case 'z':	goto yy66;
			default:	goto yy92;
			}
yy92:
#line 156 "scanner.re"
			{
			token->opcode = PHQL_T_NOT;
			return 0;
		}
#line 1059 "scanner.c"
yy93:
			yych = *++YYCURSOR;
			switch (yych) {
			case 'F':
			case 'f':	goto yy102;
			default:	goto yy67;
			}
yy94:
			yych = *++YYCURSOR;
			switch (yych) {
			case 'K':
			case 'k':	goto yy96;
			case 'M':
			case 'm':	goto yy95;
			default:	goto yy67;
			}
yy95:
			yych = *++YYCURSOR;
			switch (yych) {
			case 'I':
			case 'i':	goto yy99;
			default:	goto yy67;
			}
yy96:
			yych = *++YYCURSOR;
			switch (yych) {
			case 'E':
			case 'e':	goto yy97;
			default:	goto yy67;
			}
yy97:
			++YYCURSOR;
			switch ((yych = *YYCURSOR)) {
			case '0':
			case '1':
			case '2':
			case '3':
			case '4':
			case '5':
			case '6':
			case '7':
			case '8':
			case '9':
			case 'A':
			case 'B':
			case 'C':
			case 'D':
			case 'E':
			case 'F':
			case 'G':
			case 'H':
			case 'I':
			case 'J':
			case 'K':
			case 'L':
			case 'M':
			case 'N':
			case 'O':
			case 'P':
			case 'Q':
			case 'R':
			case 'S':
			case 'T':
			case 'U':
			case 'V':
			case 'W':
			case 'X':
			case 'Y':
			case 'Z':
			case '_':
			case 'a':
			case 'b':
			case 'c':
			case 'd':
			case 'e':
			case 'f':
			case 'g':
			case 'h':
			case 'i':
			case 'j':
			case 'k':
			case 'l':
			case 'm':
			case 'n':
			case 'o':
			case 'p':
			case 'q':
			case 'r':
			case 's':
			case 't':
			case 'u':
			case 'v':
			case 'w':
			case 'x':
			case 'y':
			case 'z':	goto yy66;
			default:	goto yy98;
			}
yy98:
#line 171 "scanner.re"
			{
			token->opcode = PHQL_T_LIKE;
			return 0;
		}
#line 1164 "scanner.c"
yy99:
			yych = *++YYCURSOR;
			switch (yych) {
			case 'T':
			case 't':	goto yy100;
			default:	goto yy67;
			}
yy100:
			++YYCURSOR;
			switch ((yych = *YYCURSOR)) {
			case '0':
			case '1':
			case '2':
			case '3':
			case '4':
			case '5':
			case '6':
			case '7':
			case '8':
			case '9':
			case 'A':
			case 'B':
			case 'C':
			case 'D':
			case 'E':
			case 'F':
			case 'G':
			case 'H':
			case 'I':
			case 'J':
			case 'K':
			case 'L':
			case 'M':
			case 'N':
			case 'O':
			case 'P':
			case 'Q':
			case 'R':
			case 'S':
			case 'T':
			case 'U':
			case 'V':
			case 'W':
			case 'X':
			case 'Y':
			case 'Z':
			case '_':
			case 'a':
			case 'b':
			case 'c':
			case 'd':
			case 'e':
			case 'f':
			case 'g':
			case 'h':
			case 'i':
			case 'j':
			case 'k':
			case 'l':
			case 'm':
			case 'n':
			case 'o':
			case 'p':
			case 'q':
			case 'r':
			case 's':
			case 't':
			case 'u':
			case 'v':
			case 'w':
			case 'x':
			case 'y':
			case 'z':	goto yy66;
			default:	goto yy101;
			}
yy101:
#line 151 "scanner.re"
			{
			token->opcode = PHQL_T_LIMIT;
			return 0;
		}
#line 1246 "scanner.c"
yy102:
			yych = *++YYCURSOR;
			switch (yych) {
			case 'T':
			case 't':	goto yy103;
			default:	goto yy67;
			}
yy103:
			++YYCURSOR;
			switch ((yych = *YYCURSOR)) {
			case '0':
			case '1':
			case '2':
			case '3':
			case '4':
			case '5':
			case '6':
			case '7':
			case '8':
			case '9':
			case 'A':
			case 'B':
			case 'C':
			case 'D':
			case 'E':
			case 'F':
			case 'G':
			case 'H':
			case 'I':
			case 'J':
			case 'K':
			case 'L':
			case 'M':
			case 'N':
			case 'O':
			case 'P':
			case 'Q':
			case 'R':
			case 'S':
			case 'T':
			case 'U':
			case 'V':
			case 'W':
			case 'X':
			case 'Y':
			case 'Z':
			case '_':
			case 'a':
			case 'b':
			case 'c':
			case 'd':
			case 'e':
			case 'f':
			case 'g':
			case 'h':
			case 'i':
			case 'j':
			case 'k':
			case 'l':
			case 'm':
			case 'n':
			case 'o':
			case 'p':
			case 'q':
			case 'r':
			case 's':
			case 't':
			case 'u':
			case 'v':
			case 'w':
			case 'x':
			case 'y':
			case 'z':	goto yy66;
			default:	goto yy104;
			}
yy104:
#line 196 "scanner.re"
			{
			token->opcode = PHQL_T_LEFT;
			return 0;
		}
#line 1328 "scanner.c"
yy105:
			yych = *++YYCURSOR;
			switch (yych) {
			case 'V':
			case 'v':	goto yy106;
			default:	goto yy67;
			}
yy106:
			yych = *++YYCURSOR;
			switch (yych) {
			case 'I':
			case 'i':	goto yy107;
			default:	goto yy67;
			}
yy107:
			yych = *++YYCURSOR;
			switch (yych) {
			case 'N':
			case 'n':	goto yy108;
			default:	goto yy67;
			}
yy108:
			yych = *++YYCURSOR;
			switch (yych) {
			case 'G':
			case 'g':	goto yy109;
			default:	goto yy67;
			}
yy109:
			++YYCURSOR;
			switch ((yych = *YYCURSOR)) {
			case '0':
			case '1':
			case '2':
			case '3':
			case '4':
			case '5':
			case '6':
			case '7':
			case '8':
			case '9':
			case 'A':
			case 'B':
			case 'C':
			case 'D':
			case 'E':
			case 'F':
			case 'G':
			case 'H':
			case 'I':
			case 'J':
			case 'K':
			case 'L':
			case 'M':
			case 'N':
			case 'O':
			case 'P':
			case 'Q':
			case 'R':
			case 'S':
			case 'T':
			case 'U':
			case 'V':
			case 'W':
			case 'X':
			case 'Y':
			case 'Z':
			case '_':
			case 'a':
			case 'b':
			case 'c':
			case 'd':
			case 'e':
			case 'f':
			case 'g':
			case 'h':
			case 'i':
			case 'j':
			case 'k':
			case 'l':
			case 'm':
			case 'n':
			case 'o':
			case 'p':
			case 'q':
			case 'r':
			case 's':
			case 't':
			case 'u':
			case 'v':
			case 'w':
			case 'x':
			case 'y':
			case 'z':	goto yy66;
			default:	goto yy110;
			}
yy110:
#line 146 "scanner.re"
			{
			token->opcode = PHQL_T_HAVING;
			return 0;
		}
#line 1431 "scanner.c"
yy111:
			yych = *++YYCURSOR;
			switch (yych) {
			case 'O':
			case 'o':	goto yy112;
			default:	goto yy67;
			}
yy112:
			yych = *++YYCURSOR;
			switch (yych) {
			case 'U':
			case 'u':	goto yy113;
			default:	goto yy67;
			}
yy113:
			yych = *++YYCURSOR;
			switch (yych) {
			case 'P':
			case 'p':	goto yy114;
			default:	goto yy67;
			}
yy114:
			++YYCURSOR;
			switch ((yych = *YYCURSOR)) {
			case '0':
			case '1':
			case '2':
			case '3':
			case '4':
			case '5':
			case '6':
			case '7':
			case '8':
			case '9':
			case 'A':
			case 'B':
			case 'C':
			case 'D':
			case 'E':
			case 'F':
			case 'G':
			case 'H':
			case 'I':
			case 'J':
			case 'K':
			case 'L':
			case 'M':
			case 'N':
			case 'O':
			case 'P':
			case 'Q':
			case 'R':
			case 'S':
			case 'T':
			case 'U':
			case 'V':
			case 'W':
			case 'X':
			case 'Y':
			case 'Z':
			case '_':
			case 'a':
			case 'b':
			case 'c':
			case 'd':
			case 'e':
			case 'f':
			case 'g':
			case 'h':
			case 'i':
			case 'j':
			case 'k':
			case 'l':
			case 'm':
			case 'n':
			case 'o':
			case 'p':
			case 'q':
			case 'r':
			case 's':
			case 't':
			case 'u':
			case 'v':
			case 'w':
			case 'x':
			case 'y':
			case 'z':	goto yy66;
			default:	goto yy115;
			}
yy115:
#line 141 "scanner.re"
			{
			token->opcode = PHQL_T_GROUP;
			return 0;
		}
#line 1527 "scanner.c"
yy116:
			++YYCURSOR;
			switch ((yych = *YYCURSOR)) {
			case '0':
			case '1':
			case '2':
			case '3':
			case '4':
			case '5':
			case '6':
			case '7':
			case '8':
			case '9':
			case 'A':
			case 'B':
			case 'C':
			case 'D':
			case 'E':
			case 'F':
			case 'G':
			case 'H':
			case 'I':
			case 'J':
			case 'K':
			case 'L':
			case 'M':
			case 'N':
			case 'O':
			case 'P':
			case 'Q':
			case 'R':
			case 'S':
			case 'T':
			case 'U':
			case 'V':
			case 'W':
			case 'X':
			case 'Y':
			case 'Z':
			case '_':
			case 'a':
			case 'b':
			case 'c':
			case 'd':
			case 'e':
			case 'f':
			case 'g':
			case 'h':
			case 'i':
			case 'j':
			case 'k':
			case 'l':
			case 'm':
			case 'n':
			case 'o':
			case 'p':
			case 'q':
			case 'r':
			case 's':
			case 't':
			case 'u':
			case 'v':
			case 'w':
			case 'x':
			case 'y':
			case 'z':	goto yy66;
			default:	goto yy117;
			}
yy117:
#line 136 "scanner.re"
			{
			token->opcode = PHQL_T_BY;
			return 0;
		}
#line 1602 "scanner.c"
yy118:
			++YYCURSOR;
			switch ((yych = *YYCURSOR)) {
			case '0':
			case '1':
			case '2':
			case '3':
			case '4':
			case '5':
			case '6':
			case '7':
			case '8':
			case '9':
			case 'A':
			case 'B':
			case 'C':
			case 'D':
			case 'E':
			case 'F':
			case 'G':
			case 'H':
			case 'I':
			case 'J':
			case 'K':
			case 'L':
			case 'M':
			case 'N':
			case 'O':
			case 'P':
			case 'Q':
			case 'R':
			case 'S':
			case 'T':
			case 'U':
			case 'V':
			case 'W':
			case 'X':
			case 'Y':
			case 'Z':
			case '_':
			case 'a':
			case 'b':
			case 'c':
			case 'd':
			case 'e':
			case 'f':
			case 'g':
			case 'h':
			case 'i':
			case 'j':
			case 'k':
			case 'l':
			case 'm':
			case 'n':
			case 'o':
			case 'p':
			case 'q':
			case 'r':
			case 's':
			case 't':
			case 'u':
			case 'v':
			case 'w':
			case 'x':
			case 'y':
			case 'z':	goto yy66;
			default:	goto yy119;
			}
yy119:
#line 181 "scanner.re"
			{
			token->opcode = PHQL_T_ON;
			return 0;
		}
#line 1677 "scanner.c"
yy120:
			++YYCURSOR;
			switch ((yych = *YYCURSOR)) {
			case '0':
			case '1':
			case '2':
			case '3':
			case '4':
			case '5':
			case '6':
			case '7':
			case '8':
			case '9':
			case 'A':
			case 'B':
			case 'C':
			case 'E':
			case 'F':
			case 'G':
			case 'H':
			case 'I':
			case 'J':
			case 'K':
			case 'L':
			case 'M':
			case 'N':
			case 'O':
			case 'P':
			case 'Q':
			case 'R':
			case 'S':
			case 'T':
			case 'U':
			case 'V':
			case 'W':
			case 'X':
			case 'Y':
			case 'Z':
			case '_':
			case 'a':
			case 'b':
			case 'c':
			case 'e':
			case 'f':
			case 'g':
			case 'h':
			case 'i':
			case 'j':
			case 'k':
			case 'l':
			case 'm':
			case 'n':
			case 'o':
			case 'p':
			case 'q':
			case 'r':
			case 's':
			case 't':
			case 'u':
			case 'v':
			case 'w':
			case 'x':
			case 'y':
			case 'z':	goto yy66;
			case 'D':
			case 'd':	goto yy122;
			default:	goto yy121;
			}
yy121:
#line 166 "scanner.re"
			{
			token->opcode = PHQL_T_OR;
			return 0;
		}
#line 1752 "scanner.c"
yy122:
			yych = *++YYCURSOR;
			switch (yych) {
			case 'E':
			case 'e':	goto yy123;
			default:	goto yy67;
			}
yy123:
			yych = *++YYCURSOR;
			switch (yych) {
			case 'R':
			case 'r':	goto yy124;
			default:	goto yy67;
			}
yy124:
			++YYCURSOR;
			switch ((yych = *YYCURSOR)) {
			case '0':
			case '1':
			case '2':
			case '3':
			case '4':
			case '5':
			case '6':
			case '7':
			case '8':
			case '9':
			case 'A':
			case 'B':
			case 'C':
			case 'D':
			case 'E':
			case 'F':
			case 'G':
			case 'H':
			case 'I':
			case 'J':
			case 'K':
			case 'L':
			case 'M':
			case 'N':
			case 'O':
			case 'P':
			case 'Q':
			case 'R':
			case 'S':
			case 'T':
			case 'U':
			case 'V':
			case 'W':
			case 'X':
			case 'Y':
			case 'Z':
			case '_':
			case 'a':
			case 'b':
			case 'c':
			case 'd':
			case 'e':
			case 'f':
			case 'g':
			case 'h':
			case 'i':
			case 'j':
			case 'k':
			case 'l':
			case 'm':
			case 'n':
			case 'o':
			case 'p':
			case 'q':
			case 'r':
			case 's':
			case 't':
			case 'u':
			case 'v':
			case 'w':
			case 'x':
			case 'y':
			case 'z':	goto yy66;
			default:	goto yy125;
			}
yy125:
#line 131 "scanner.re"
			{
			token->opcode = PHQL_T_ORDER;
			return 0;
		}
#line 1841 "scanner.c"
yy126:
			yych = *++YYCURSOR;
			switch (yych) {
			case 'E':
			case 'e':	goto yy127;
			default:	goto yy67;
			}
yy127:
			yych = *++YYCURSOR;
			switch (yych) {
			case 'R':
			case 'r':	goto yy128;
			default:	goto yy67;
			}
yy128:
			yych = *++YYCURSOR;
			switch (yych) {
			case 'E':
			case 'e':	goto yy129;
			default:	goto yy67;
			}
yy129:
			++YYCURSOR;
			switch ((yych = *YYCURSOR)) {
			case '0':
			case '1':
			case '2':
			case '3':
			case '4':
			case '5':
			case '6':
			case '7':
			case '8':
			case '9':
			case 'A':
			case 'B':
			case 'C':
			case 'D':
			case 'E':
			case 'F':
			case 'G':
			case 'H':
			case 'I':
			case 'J':
			case 'K':
			case 'L':
			case 'M':
			case 'N':
			case 'O':
			case 'P':
			case 'Q':
			case 'R':
			case 'S':
			case 'T':
			case 'U':
			case 'V':
			case 'W':
			case 'X':
			case 'Y':
			case 'Z':
			case '_':
			case 'a':
			case 'b':
			case 'c':
			case 'd':
			case 'e':
			case 'f':
			case 'g':
			case 'h':
			case 'i':
			case 'j':
			case 'k':
			case 'l':
			case 'm':
			case 'n':
			case 'o':
			case 'p':
			case 'q':
			case 'r':
			case 's':
			case 't':
			case 'u':
			case 'v':
			case 'w':
			case 'x':
			case 'y':
			case 'z':	goto yy66;
			default:	goto yy130;
			}
yy130:
#line 121 "scanner.re"
			{
			token->opcode = PHQL_T_WHERE;
			return 0;
		}
#line 1937 "scanner.c"
yy131:
			yych = *++YYCURSOR;
			switch (yych) {
			case 'L':
			case 'l':	goto yy132;
			default:	goto yy67;
			}
yy132:
			yych = *++YYCURSOR;
			switch (yych) {
			case 'U':
			case 'u':	goto yy133;
			default:	goto yy67;
			}
yy133:
			yych = *++YYCURSOR;
			switch (yych) {
			case 'E':
			case 'e':	goto yy134;
			default:	goto yy67;
			}
yy134:
			yych = *++YYCURSOR;
			switch (yych) {
			case 'S':
			case 's':	goto yy135;
			default:	goto yy67;
			}
yy135:
			++YYCURSOR;
			switch ((yych = *YYCURSOR)) {
			case '0':
			case '1':
			case '2':
			case '3':
			case '4':
			case '5':
			case '6':
			case '7':
			case '8':
			case '9':
			case 'A':
			case 'B':
			case 'C':
			case 'D':
			case 'E':
			case 'F':
			case 'G':
			case 'H':
			case 'I':
			case 'J':
			case 'K':
			case 'L':
			case 'M':
			case 'N':
			case 'O':
			case 'P':
			case 'Q':
			case 'R':
			case 'S':
			case 'T':
			case 'U':
			case 'V':
			case 'W':
			case 'X':
			case 'Y':
			case 'Z':
			case '_':
			case 'a':
			case 'b':
			case 'c':
			case 'd':
			case 'e':
			case 'f':
			case 'g':
			case 'h':
			case 'i':
			case 'j':
			case 'k':
			case 'l':
			case 'm':
			case 'n':
			case 'o':
			case 'p':
			case 'q':
			case 'r':
			case 's':
			case 't':
			case 'u':
			case 'v':
			case 'w':
			case 'x':
			case 'y':
			case 'z':	goto yy66;
			default:	goto yy136;
			}
yy136:
#line 116 "scanner.re"
			{
			token->opcode = PHQL_T_VALUES;
			return 0;
		}
#line 2040 "scanner.c"
yy137:
			++YYCURSOR;
			switch ((yych = *YYCURSOR)) {
			case '0':
			case '1':
			case '2':
			case '3':
			case '4':
			case '5':
			case '6':
			case '7':
			case '8':
			case '9':
			case 'A':
			case 'B':
			case 'C':
			case 'D':
			case 'E':
			case 'F':
			case 'G':
			case 'H':
			case 'I':
			case 'J':
			case 'K':
			case 'L':
			case 'M':
			case 'O':
			case 'P':
			case 'Q':
			case 'R':
			case 'U':
			case 'V':
			case 'W':
			case 'X':
			case 'Y':
			case 'Z':
			case '_':
			case 'a':
			case 'b':
			case 'c':
			case 'd':
			case 'e':
			case 'f':
			case 'g':
			case 'h':
			case 'i':
			case 'j':
			case 'k':
			case 'l':
			case 'm':
			case 'o':
			case 'p':
			case 'q':
			case 'r':
			case 'u':
			case 'v':
			case 'w':
			case 'x':
			case 'y':
			case 'z':	goto yy66;
			case 'N':
			case 'n':	goto yy143;
			case 'S':
			case 's':	goto yy141;
			case 'T':
			case 't':	goto yy142;
			default:	goto yy138;
			}
yy138:
#line 176 "scanner.re"
			{
			token->opcode = PHQL_T_IN;
			return 0;
		}
#line 2115 "scanner.c"
yy139:
			++YYCURSOR;
			switch ((yych = *YYCURSOR)) {
			case '0':
			case '1':
			case '2':
			case '3':
			case '4':
			case '5':
			case '6':
			case '7':
			case '8':
			case '9':
			case 'A':
			case 'B':
			case 'C':
			case 'D':
			case 'E':
			case 'F':
			case 'G':
			case 'H':
			case 'I':
			case 'J':
			case 'K':
			case 'L':
			case 'M':
			case 'N':
			case 'O':
			case 'P':
			case 'Q':
			case 'R':
			case 'S':
			case 'T':
			case 'U':
			case 'V':
			case 'W':
			case 'X':
			case 'Y':
			case 'Z':
			case '_':
			case 'a':
			case 'b':
			case 'c':
			case 'd':
			case 'e':
			case 'f':
			case 'g':
			case 'h':
			case 'i':
			case 'j':
			case 'k':
			case 'l':
			case 'm':
			case 'n':
			case 'o':
			case 'p':
			case 'q':
			case 'r':
			case 's':
			case 't':
			case 'u':
			case 'v':
			case 'w':
			case 'x':
			case 'y':
			case 'z':	goto yy66;
			default:	goto yy140;
			}
yy140:
#line 206 "scanner.re"
			{
			token->opcode = PHQL_T_IS;
			return 0;
		}
#line 2190 "scanner.c"
yy141:
			yych = *++YYCURSOR;
			switch (yych) {
			case 'E':
			case 'e':	goto yy149;
			default:	goto yy67;
			}
yy142:
			yych = *++YYCURSOR;
			switch (yych) {
			case 'O':
			case 'o':	goto yy147;
			default:	goto yy67;
			}
yy143:
			yych = *++YYCURSOR;
			switch (yych) {
			case 'E':
			case 'e':	goto yy144;
			default:	goto yy67;
			}
yy144:
			yych = *++YYCURSOR;
			switch (yych) {
			case 'R':
			case 'r':	goto yy145;
			default:	goto yy67;
			}
yy145:
			++YYCURSOR;
			switch ((yych = *YYCURSOR)) {
			case '0':
			case '1':
			case '2':
			case '3':
			case '4':
			case '5':
			case '6':
			case '7':
			case '8':
			case '9':
			case 'A':
			case 'B':
			case 'C':
			case 'D':
			case 'E':
			case 'F':
			case 'G':
			case 'H':
			case 'I':
			case 'J':
			case 'K':
			case 'L':
			case 'M':
			case 'N':
			case 'O':
			case 'P':
			case 'Q':
			case 'R':
			case 'S':
			case 'T':
			case 'U':
			case 'V':
			case 'W':
			case 'X':
			case 'Y':
			case 'Z':
			case '_':
			case 'a':
			case 'b':
			case 'c':
			case 'd':
			case 'e':
			case 'f':
			case 'g':
			case 'h':
			case 'i':
			case 'j':
			case 'k':
			case 'l':
			case 'm':
			case 'n':
			case 'o':
			case 'p':
			case 'q':
			case 'r':
			case 's':
			case 't':
			case 'u':
			case 'v':
			case 'w':
			case 'x':
			case 'y':
			case 'z':	goto yy66;
			default:	goto yy146;
			}
yy146:
#line 191 "scanner.re"
			{
			token->opcode = PHQL_T_INNER;
			return 0;
		}
#line 2293 "scanner.c"
yy147:
			++YYCURSOR;
			switch ((yych = *YYCURSOR)) {
			case '0':
			case '1':
			case '2':
			case '3':
			case '4':
			case '5':
			case '6':
			case '7':
			case '8':
			case '9':
			case 'A':
			case 'B':
			case 'C':
			case 'D':
			case 'E':
			case 'F':
			case 'G':
			case 'H':
			case 'I':
			case 'J':
			case 'K':
			case 'L':
			case 'M':
			case 'N':
			case 'O':
			case 'P':
			case 'Q':
			case 'R':
			case 'S':
			case 'T':
			case 'U':
			case 'V':
			case 'W':
			case 'X':
			case 'Y':
			case 'Z':
			case '_':
			case 'a':
			case 'b':
			case 'c':
			case 'd':
			case 'e':
			case 'f':
			case 'g':
			case 'h':
			case 'i':
			case 'j':
			case 'k':
			case 'l':
			case 'm':
			case 'n':
			case 'o':
			case 'p':
			case 'q':
			case 'r':
			case 's':
			case 't':
			case 'u':
			case 'v':
			case 'w':
			case 'x':
			case 'y':
			case 'z':	goto yy66;
			default:	goto yy148;
			}
yy148:
#line 111 "scanner.re"
			{
			token->opcode = PHQL_T_INTO;
			return 0;
		}
#line 2368 "scanner.c"
yy149:
			yych = *++YYCURSOR;
			switch (yych) {
			case 'R':
			case 'r':	goto yy150;
			default:	goto yy67;
			}
yy150:
			yych = *++YYCURSOR;
			switch (yych) {
			case 'T':
			case 't':	goto yy151;
			default:	goto yy67;
			}
yy151:
			++YYCURSOR;
			switch ((yych = *YYCURSOR)) {
			case '0':
			case '1':
			case '2':
			case '3':
			case '4':
			case '5':
			case '6':
			case '7':
			case '8':
			case '9':
			case 'A':
			case 'B':
			case 'C':
			case 'D':
			case 'E':
			case 'F':
			case 'G':
			case 'H':
			case 'I':
			case 'J':
			case 'K':
			case 'L':
			case 'M':
			case 'N':
			case 'O':
			case 'P':
			case 'Q':
			case 'R':
			case 'S':
			case 'T':
			case 'U':
			case 'V':
			case 'W':
			case 'X':
			case 'Y':
			case 'Z':
			case '_':
			case 'a':
			case 'b':
			case 'c':
			case 'd':
			case 'e':
			case 'f':
			case 'g':
			case 'h':
			case 'i':
			case 'j':
			case 'k':
			case 'l':
			case 'm':
			case 'n':
			case 'o':
			case 'p':
			case 'q':
			case 'r':
			case 's':
			case 't':
			case 'u':
			case 'v':
			case 'w':
			case 'x':
			case 'y':
			case 'z':	goto yy66;
			default:	goto yy152;
			}
yy152:
#line 106 "scanner.re"
			{
			token->opcode = PHQL_T_INSERT;
			return 0;
		}
#line 2457 "scanner.c"
yy153:
			yych = *++YYCURSOR;
			switch (yych) {
			case 'D':
			case 'd':	goto yy156;
			default:	goto yy67;
			}
yy154:
			++YYCURSOR;
			switch ((yych = *YYCURSOR)) {
			case '0':
			case '1':
			case '2':
			case '3':
			case '4':
			case '5':
			case '6':
			case '7':
			case '8':
			case '9':
			case 'A':
			case 'B':
			case 'C':
			case 'D':
			case 'E':
			case 'F':
			case 'G':
			case 'H':
			case 'I':
			case 'J':
			case 'K':
			case 'L':
			case 'M':
			case 'N':
			case 'O':
			case 'P':
			case 'Q':
			case 'R':
			case 'S':
			case 'T':
			case 'U':
			case 'V':
			case 'W':
			case 'X':
			case 'Y':
			case 'Z':
			case '_':
			case 'a':
			case 'b':
			case 'c':
			case 'd':
			case 'e':
			case 'f':
			case 'g':
			case 'h':
			case 'i':
			case 'j':
			case 'k':
			case 'l':
			case 'm':
			case 'n':
			case 'o':
			case 'p':
			case 'q':
			case 'r':
			case 's':
			case 't':
			case 'u':
			case 'v':
			case 'w':
			case 'x':
			case 'y':
			case 'z':	goto yy66;
			default:	goto yy155;
			}
yy155:
#line 101 "scanner.re"
			{
			token->opcode = PHQL_T_AS;
			return 0;
		}
#line 2539 "scanner.c"
yy156:
			++YYCURSOR;
			switch ((yych = *YYCURSOR)) {
			case '0':
			case '1':
			case '2':
			case '3':
			case '4':
			case '5':
			case '6':
			case '7':
			case '8':
			case '9':
			case 'A':
			case 'B':
			case 'C':
			case 'D':
			case 'E':
			case 'F':
			case 'G':
			case 'H':
			case 'I':
			case 'J':
			case 'K':
			case 'L':
			case 'M':
			case 'N':
			case 'O':
			case 'P':
			case 'Q':
			case 'R':
			case 'S':
			case 'T':
			case 'U':
			case 'V':
			case 'W':
			case 'X':
			case 'Y':
			case 'Z':
			case '_':
			case 'a':
			case 'b':
			case 'c':
			case 'd':
			case 'e':
			case 'f':
			case 'g':
			case 'h':
			case 'i':
			case 'j':
			case 'k':
			case 'l':
			case 'm':
			case 'n':
			case 'o':
			case 'p':
			case 'q':
			case 'r':
			case 's':
			case 't':
			case 'u':
			case 'v':
			case 'w':
			case 'x':
			case 'y':
			case 'z':	goto yy66;
			default:	goto yy157;
			}
yy157:
#line 161 "scanner.re"
			{
			token->opcode = PHQL_T_AND;
			return 0;
		}
#line 2614 "scanner.c"
yy158:
			yych = *++YYCURSOR;
			switch (yych) {
			case 'O':
			case 'o':	goto yy159;
			default:	goto yy67;
			}
yy159:
			yych = *++YYCURSOR;
			switch (yych) {
			case 'M':
			case 'm':	goto yy160;
			default:	goto yy67;
			}
yy160:
			++YYCURSOR;
			switch ((yych = *YYCURSOR)) {
			case '0':
			case '1':
			case '2':
			case '3':
			case '4':
			case '5':
			case '6':
			case '7':
			case '8':
			case '9':
			case 'A':
			case 'B':
			case 'C':
			case 'D':
			case 'E':
			case 'F':
			case 'G':
			case 'H':
			case 'I':
			case 'J':
			case 'K':
			case 'L':
			case 'M':
			case 'N':
			case 'O':
			case 'P':
			case 'Q':
			case 'R':
			case 'S':
			case 'T':
			case 'U':
			case 'V':
			case 'W':
			case 'X':
			case 'Y':
			case 'Z':
			case '_':
			case 'a':
			case 'b':
			case 'c':
			case 'd':
			case 'e':
			case 'f':
			case 'g':
			case 'h':
			case 'i':
			case 'j':
			case 'k':
			case 'l':
			case 'm':
			case 'n':
			case 'o':
			case 'p':
			case 'q':
			case 'r':
			case 's':
			case 't':
			case 'u':
			case 'v':
			case 'w':
			case 'x':
			case 'y':
			case 'z':	goto yy66;
			default:	goto yy161;
			}
yy161:
#line 96 "scanner.re"
			{
			token->opcode = PHQL_T_FROM;
			return 0;
		}
#line 2703 "scanner.c"
yy162:
			yych = *++YYCURSOR;
			switch (yych) {
			case 'L':
			case 'l':	goto yy163;
			default:	goto yy67;
			}
yy163:
			yych = *++YYCURSOR;
			switch (yych) {
			case 'E':
			case 'e':	goto yy164;
			default:	goto yy67;
			}
yy164:
			yych = *++YYCURSOR;
			switch (yych) {
			case 'T':
			case 't':	goto yy165;
			default:	goto yy67;
			}
yy165:
			yych = *++YYCURSOR;
			switch (yych) {
			case 'E':
			case 'e':	goto yy166;
			default:	goto yy67;
			}
yy166:
			++YYCURSOR;
			switch ((yych = *YYCURSOR)) {
			case '0':
			case '1':
			case '2':
			case '3':
			case '4':
			case '5':
			case '6':
			case '7':
			case '8':
			case '9':
			case 'A':
			case 'B':
			case 'C':
			case 'D':
			case 'E':
			case 'F':
			case 'G':
			case 'H':
			case 'I':
			case 'J':
			case 'K':
			case 'L':
			case 'M':
			case 'N':
			case 'O':
			case 'P':
			case 'Q':
			case 'R':
			case 'S':
			case 'T':
			case 'U':
			case 'V':
			case 'W':
			case 'X':
			case 'Y':
			case 'Z':
			case '_':
			case 'a':
			case 'b':
			case 'c':
			case 'd':
			case 'e':
			case 'f':
			case 'g':
			case 'h':
			case 'i':
			case 'j':
			case 'k':
			case 'l':
			case 'm':
			case 'n':
			case 'o':
			case 'p':
			case 'q':
			case 'r':
			case 's':
			case 't':
			case 'u':
			case 'v':
			case 'w':
			case 'x':
			case 'y':
			case 'z':	goto yy66;
			default:	goto yy167;
			}
yy167:
#line 91 "scanner.re"
			{
			token->opcode = PHQL_T_DELETE;
			return 0;
		}
#line 2806 "scanner.c"
yy168:
			yych = *++YYCURSOR;
			switch (yych) {
			case 'L':
			case 'l':	goto yy171;
			case 'T':
			case 't':	goto yy169;
			default:	goto yy67;
			}
yy169:
			++YYCURSOR;
			switch ((yych = *YYCURSOR)) {
			case '0':
			case '1':
			case '2':
			case '3':
			case '4':
			case '5':
			case '6':
			case '7':
			case '8':
			case '9':
			case 'A':
			case 'B':
			case 'C':
			case 'D':
			case 'E':
			case 'F':
			case 'G':
			case 'H':
			case 'I':
			case 'J':
			case 'K':
			case 'L':
			case 'M':
			case 'N':
			case 'O':
			case 'P':
			case 'Q':
			case 'R':
			case 'S':
			case 'T':
			case 'U':
			case 'V':
			case 'W':
			case 'X':
			case 'Y':
			case 'Z':
			case '_':
			case 'a':
			case 'b':
			case 'c':
			case 'd':
			case 'e':
			case 'f':
			case 'g':
			case 'h':
			case 'i':
			case 'j':
			case 'k':
			case 'l':
			case 'm':
			case 'n':
			case 'o':
			case 'p':
			case 'q':
			case 'r':
			case 's':
			case 't':
			case 'u':
			case 'v':
			case 'w':
			case 'x':
			case 'y':
			case 'z':	goto yy66;
			default:	goto yy170;
			}
yy170:
#line 86 "scanner.re"
			{
			token->opcode = PHQL_T_SET;
			return 0;
		}
#line 2890 "scanner.c"
yy171:
			yych = *++YYCURSOR;
			switch (yych) {
			case 'E':
			case 'e':	goto yy172;
			default:	goto yy67;
			}
yy172:
			yych = *++YYCURSOR;
			switch (yych) {
			case 'C':
			case 'c':	goto yy173;
			default:	goto yy67;
			}
yy173:
			yych = *++YYCURSOR;
			switch (yych) {
			case 'T':
			case 't':	goto yy174;
			default:	goto yy67;
			}
yy174:
			++YYCURSOR;
			switch ((yych = *YYCURSOR)) {
			case '0':
			case '1':
			case '2':
			case '3':
			case '4':
			case '5':
			case '6':
			case '7':
			case '8':
			case '9':
			case 'A':
			case 'B':
			case 'C':
			case 'D':
			case 'E':
			case 'F':
			case 'G':
			case 'H':
			case 'I':
			case 'J':
			case 'K':
			case 'L':
			case 'M':
			case 'N':
			case 'O':
			case 'P':
			case 'Q':
			case 'R':
			case 'S':
			case 'T':
			case 'U':
			case 'V':
			case 'W':
			case 'X':
			case 'Y':
			case 'Z':
			case '_':
			case 'a':
			case 'b':
			case 'c':
			case 'd':
			case 'e':
			case 'f':
			case 'g':
			case 'h':
			case 'i':
			case 'j':
			case 'k':
			case 'l':
			case 'm':
			case 'n':
			case 'o':
			case 'p':
			case 'q':
			case 'r':
			case 's':
			case 't':
			case 'u':
			case 'v':
			case 'w':
			case 'x':
			case 'y':
			case 'z':	goto yy66;
			default:	goto yy175;
			}
yy175:
#line 126 "scanner.re"
			{
			token->opcode = PHQL_T_SELECT;
			return 0;
		}
#line 2986 "scanner.c"
yy176:
			yych = *++YYCURSOR;
			switch (yych) {
			case 'D':
			case 'd':	goto yy177;
			default:	goto yy67;
			}
yy177:
			yych = *++YYCURSOR;
			switch (yych) {
			case 'A':
			case 'a':	goto yy178;
			default:	goto yy67;
			}
yy178:
			yych = *++YYCURSOR;
			switch (yych) {
			case 'T':
			case 't':	goto yy179;
			default:	goto yy67;
			}
yy179:
			yych = *++YYCURSOR;
			switch (yych) {
			case 'E':
			case 'e':	goto yy180;
			default:	goto yy67;
			}
yy180:
			++YYCURSOR;
			switch ((yych = *YYCURSOR)) {
			case '0':
			case '1':
			case '2':
			case '3':
			case '4':
			case '5':
			case '6':
			case '7':
			case '8':
			case '9':
			case 'A':
			case 'B':
			case 'C':
			case 'D':
			case 'E':
			case 'F':
			case 'G':
			case 'H':
			case 'I':
			case 'J':
			case 'K':
			case 'L':
			case 'M':
			case 'N':
			case 'O':
			case 'P':
			case 'Q':
			case 'R':
			case 'S':
			case 'T':
			case 'U':
			case 'V':
			case 'W':
			case 'X':
			case 'Y':
			case 'Z':
			case '_':
			case 'a':
			case 'b':
			case 'c':
			case 'd':
			case 'e':
			case 'f':
			case 'g':
			case 'h':
			case 'i':
			case 'j':
			case 'k':
			case 'l':
			case 'm':
			case 'n':
			case 'o':
			case 'p':
			case 'q':
			case 'r':
			case 's':
			case 't':
			case 'u':
			case 'v':
			case 'w':
			case 'x':
			case 'y':
			case 'z':	goto yy66;
			default:	goto yy181;
			}
yy181:
#line 81 "scanner.re"
			{
			token->opcode = PHQL_T_UPDATE;
			return 0;
		}
#line 3089 "scanner.c"
yy182:
			++YYCURSOR;
			yych = *YYCURSOR;
			switch (yych) {
			case '0':
			case '1':
			case '2':
			case '3':
			case '4':
			case '5':
			case '6':
			case '7':
			case '8':
			case '9':
			case 'A':
			case 'B':
			case 'C':
			case 'D':
			case 'E':
			case 'F':
			case 'G':
			case 'H':
			case 'I':
			case 'J':
			case 'K':
			case 'L':
			case 'M':
			case 'N':
			case 'O':
			case 'P':
			case 'Q':
			case 'R':
			case 'S':
			case 'T':
			case 'U':
			case 'V':
			case 'W':
			case 'X':
			case 'Y':
			case 'Z':
			case '_':
			case 'a':
			case 'b':
			case 'c':
			case 'd':
			case 'e':
			case 'f':
			case 'g':
			case 'h':
			case 'i':
			case 'j':
			case 'k':
			case 'l':
			case 'm':
			case 'n':
			case 'o':
			case 'p':
			case 'q':
			case 'r':
			case 's':
			case 't':
			case 'u':
			case 'v':
			case 'w':
			case 'x':
			case 'y':
			case 'z':	goto yy182;
			case ':':	goto yy184;
			default:	goto yy70;
			}
yy184:
			++YYCURSOR;
#line 73 "scanner.re"
			{
			token->opcode = PHQL_T_SPLACEHOLDER;
			token->value = estrndup(q, YYCURSOR - q - 1);
			token->len = YYCURSOR - q - 1;
			q = YYCURSOR;
			return 0;
		}
#line 3170 "scanner.c"
yy186:
			++YYCURSOR;
			yych = *YYCURSOR;
			switch (yych) {
			case '0':
			case '1':
			case '2':
			case '3':
			case '4':
			case '5':
			case '6':
			case '7':
			case '8':
			case '9':	goto yy186;
			default:	goto yy188;
			}
yy188:
#line 64 "scanner.re"
			{
			token->opcode = PHQL_T_NPLACEHOLDER;
			token->value = estrndup(q, YYCURSOR - q);
			token->len = YYCURSOR - q;
			q = YYCURSOR;
			return 0;
		}
#line 3196 "scanner.c"
yy189:
			++YYCURSOR;
			yych = *YYCURSOR;
			switch (yych) {
			case '0':
			case '1':
			case '2':
			case '3':
			case '4':
			case '5':
			case '6':
			case '7':
			case '8':
			case '9':	goto yy189;
			default:	goto yy191;
			}
yy191:
#line 55 "scanner.re"
			{
			token->opcode = PHQL_T_DOUBLE;
			token->value = estrndup(q, YYCURSOR - q);
			token->len = YYCURSOR - q;
			q = YYCURSOR;
			return 0;
		}
#line 3222 "scanner.c"
yy192:
			++YYCURSOR;
			yych = *YYCURSOR;
			switch (yych) {
			case '0':
			case '1':
			case '2':
			case '3':
			case '4':
			case '5':
			case '6':
			case '7':
			case '8':
			case '9':	goto yy192;
			default:	goto yy191;
			}
yy194:
			++YYCURSOR;
			yych = *YYCURSOR;
			switch (yych) {
			case '.':	goto yy192;
			case '0':
			case '1':
			case '2':
			case '3':
			case '4':
			case '5':
			case '6':
			case '7':
			case '8':
			case '9':	goto yy194;
			default:	goto yy3;
			}
		}
#line 329 "scanner.re"

	}

	return status;
}
Пример #14
0
php_stream *php_stream_url_wrap_http_ex(php_stream_wrapper *wrapper,
		const char *path, const char *mode, int options, zend_string **opened_path,
		php_stream_context *context, int redirect_max, int flags STREAMS_DC) /* {{{ */
{
	php_stream *stream = NULL;
	php_url *resource = NULL;
	int use_ssl;
	int use_proxy = 0;
	char *scratch = NULL;
	zend_string *tmp = NULL;
	char *ua_str = NULL;
	zval *ua_zval = NULL, *tmpzval = NULL, ssl_proxy_peer_name;
	size_t scratch_len = 0;
	int body = 0;
	char location[HTTP_HEADER_BLOCK_SIZE];
	zval response_header;
	int reqok = 0;
	char *http_header_line = NULL;
	char tmp_line[128];
	size_t chunk_size = 0, file_size = 0;
	int eol_detect = 0;
	char *transport_string;
	zend_string *errstr = NULL;
	size_t transport_len;
	int have_header = 0;
	zend_bool request_fulluri = 0, ignore_errors = 0;
	char *protocol_version = NULL;
	int protocol_version_len = 3; /* Default: "1.0" */
	struct timeval timeout;
	char *user_headers = NULL;
	int header_init = ((flags & HTTP_WRAPPER_HEADER_INIT) != 0);
	int redirected = ((flags & HTTP_WRAPPER_REDIRECTED) != 0);
	zend_bool follow_location = 1;
	php_stream_filter *transfer_encoding = NULL;
	int response_code;
	zend_array *symbol_table;
	smart_str req_buf = {0};

	ZVAL_UNDEF(&response_header);
	tmp_line[0] = '\0';

	if (redirect_max < 1) {
		php_stream_wrapper_log_error(wrapper, options, "Redirection limit reached, aborting");
		return NULL;
	}

	resource = php_url_parse(path);
	if (resource == NULL) {
		return NULL;
	}

	if (strncasecmp(resource->scheme, "http", sizeof("http")) && strncasecmp(resource->scheme, "https", sizeof("https"))) {
		if (!context ||
			(tmpzval = php_stream_context_get_option(context, wrapper->wops->label, "proxy")) == NULL ||
			Z_TYPE_P(tmpzval) != IS_STRING ||
			Z_STRLEN_P(tmpzval) <= 0) {
			php_url_free(resource);
			return php_stream_open_wrapper_ex(path, mode, REPORT_ERRORS, NULL, context);
		}
		/* Called from a non-http wrapper with http proxying requested (i.e. ftp) */
		request_fulluri = 1;
		use_ssl = 0;
		use_proxy = 1;

		transport_len = Z_STRLEN_P(tmpzval);
		transport_string = estrndup(Z_STRVAL_P(tmpzval), Z_STRLEN_P(tmpzval));
	} else {
		/* Normal http request (possibly with proxy) */

		if (strpbrk(mode, "awx+")) {
			php_stream_wrapper_log_error(wrapper, options, "HTTP wrapper does not support writeable connections");
			php_url_free(resource);
			return NULL;
		}

		use_ssl = resource->scheme && (strlen(resource->scheme) > 4) && resource->scheme[4] == 's';
		/* choose default ports */
		if (use_ssl && resource->port == 0)
			resource->port = 443;
		else if (resource->port == 0)
			resource->port = 80;

		if (context &&
			(tmpzval = php_stream_context_get_option(context, wrapper->wops->label, "proxy")) != NULL &&
			Z_TYPE_P(tmpzval) == IS_STRING &&
			Z_STRLEN_P(tmpzval) > 0) {
			use_proxy = 1;
			transport_len = Z_STRLEN_P(tmpzval);
			transport_string = estrndup(Z_STRVAL_P(tmpzval), Z_STRLEN_P(tmpzval));
		} else {
			transport_len = spprintf(&transport_string, 0, "%s://%s:%d", use_ssl ? "ssl" : "tcp", resource->host, resource->port);
		}
	}

	if (context && (tmpzval = php_stream_context_get_option(context, wrapper->wops->label, "timeout")) != NULL) {
		double d = zval_get_double(tmpzval);
#ifndef PHP_WIN32
		timeout.tv_sec = (time_t) d;
		timeout.tv_usec = (size_t) ((d - timeout.tv_sec) * 1000000);
#else
		timeout.tv_sec = (long) d;
		timeout.tv_usec = (long) ((d - timeout.tv_sec) * 1000000);
#endif
	} else {
#ifndef PHP_WIN32
		timeout.tv_sec = FG(default_socket_timeout);
#else
		timeout.tv_sec = (long)FG(default_socket_timeout);
#endif
		timeout.tv_usec = 0;
	}

	stream = php_stream_xport_create(transport_string, transport_len, options,
			STREAM_XPORT_CLIENT | STREAM_XPORT_CONNECT,
			NULL, &timeout, context, &errstr, NULL);

	if (stream) {
		php_stream_set_option(stream, PHP_STREAM_OPTION_READ_TIMEOUT, 0, &timeout);
	}

	if (errstr) {
		php_stream_wrapper_log_error(wrapper, options, "%s", ZSTR_VAL(errstr));
		zend_string_release(errstr);
		errstr = NULL;
	}

	efree(transport_string);

	if (stream && use_proxy && use_ssl) {
		smart_str header = {0};

		/* Set peer_name or name verification will try to use the proxy server name */
		if (!context || (tmpzval = php_stream_context_get_option(context, "ssl", "peer_name")) == NULL) {
			ZVAL_STRING(&ssl_proxy_peer_name, resource->host);
			php_stream_context_set_option(PHP_STREAM_CONTEXT(stream), "ssl", "peer_name", &ssl_proxy_peer_name);
			zval_ptr_dtor(&ssl_proxy_peer_name);
		}

		smart_str_appendl(&header, "CONNECT ", sizeof("CONNECT ")-1);
		smart_str_appends(&header, resource->host);
		smart_str_appendc(&header, ':');
		smart_str_append_unsigned(&header, resource->port);
		smart_str_appendl(&header, " HTTP/1.0\r\n", sizeof(" HTTP/1.0\r\n")-1);

	    /* check if we have Proxy-Authorization header */
		if (context && (tmpzval = php_stream_context_get_option(context, "http", "header")) != NULL) {
			char *s, *p;

			if (Z_TYPE_P(tmpzval) == IS_ARRAY) {
				zval *tmpheader = NULL;

				ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(tmpzval), tmpheader) {
					if (Z_TYPE_P(tmpheader) == IS_STRING) {
						s = Z_STRVAL_P(tmpheader);
						do {
							while (*s == ' ' || *s == '\t') s++;
							p = s;
							while (*p != 0 && *p != ':' && *p != '\r' && *p !='\n') p++;
							if (*p == ':') {
								p++;
								if (p - s == sizeof("Proxy-Authorization:") - 1 &&
								    zend_binary_strcasecmp(s, sizeof("Proxy-Authorization:") - 1,
								        "Proxy-Authorization:", sizeof("Proxy-Authorization:") - 1) == 0) {
									while (*p != 0 && *p != '\r' && *p !='\n') p++;
									smart_str_appendl(&header, s, p - s);
									smart_str_appendl(&header, "\r\n", sizeof("\r\n")-1);
									goto finish;
								} else {
									while (*p != 0 && *p != '\r' && *p !='\n') p++;
								}
							}
							s = p;
							while (*s == '\r' || *s == '\n') s++;
						} while (*s != 0);
					}
				} ZEND_HASH_FOREACH_END();
			} else if (Z_TYPE_P(tmpzval) == IS_STRING && Z_STRLEN_P(tmpzval)) {
Пример #15
0
SAPI_API int sapi_header_op(sapi_header_op_enum op, void *arg)
{
	sapi_header_struct sapi_header;
	char *colon_offset;
	char *header_line;
	size_t header_line_len;
	int http_response_code;

	if (SG(headers_sent) && !SG(request_info).no_headers) {
		const char *output_start_filename = php_output_get_start_filename();
		int output_start_lineno = php_output_get_start_lineno();

		if (output_start_filename) {
			sapi_module.sapi_error(E_WARNING, "Cannot modify header information - headers already sent by (output started at %s:%d)",
				output_start_filename, output_start_lineno);
		} else {
			sapi_module.sapi_error(E_WARNING, "Cannot modify header information - headers already sent");
		}
		return FAILURE;
	}

	switch (op) {
		case SAPI_HEADER_SET_STATUS:
			sapi_update_response_code((int)(zend_intptr_t) arg);
			return SUCCESS;

		case SAPI_HEADER_ADD:
		case SAPI_HEADER_REPLACE:
		case SAPI_HEADER_DELETE: {
				sapi_header_line *p = arg;

				if (!p->line || !p->line_len) {
					return FAILURE;
				}
				header_line = p->line;
				header_line_len = p->line_len;
				http_response_code = p->response_code;
				break;
			}

		case SAPI_HEADER_DELETE_ALL:
			if (sapi_module.header_handler) {
				sapi_module.header_handler(&sapi_header, op, &SG(sapi_headers));
			}
			zend_llist_clean(&SG(sapi_headers).headers);
			return SUCCESS;

		default:
			return FAILURE;
	}

	header_line = estrndup(header_line, header_line_len);

	/* cut off trailing spaces, linefeeds and carriage-returns */
	if (header_line_len && isspace(header_line[header_line_len-1])) {
		do {
			header_line_len--;
		} while(header_line_len && isspace(header_line[header_line_len-1]));
		header_line[header_line_len]='\0';
	}

	if (op == SAPI_HEADER_DELETE) {
		if (strchr(header_line, ':')) {
			efree(header_line);
			sapi_module.sapi_error(E_WARNING, "Header to delete may not contain colon.");
			return FAILURE;
		}
		if (sapi_module.header_handler) {
			sapi_header.header = header_line;
			sapi_header.header_len = header_line_len;
			sapi_module.header_handler(&sapi_header, op, &SG(sapi_headers));
		}
		sapi_remove_header(&SG(sapi_headers).headers, header_line, header_line_len);
		efree(header_line);
		return SUCCESS;
	} else {
		/* new line/NUL character safety check */
		uint i;
		for (i = 0; i < header_line_len; i++) {
			/* RFC 7230 ch. 3.2.4 deprecates folding support */
			if (header_line[i] == '\n' || header_line[i] == '\r') {
				efree(header_line);
				sapi_module.sapi_error(E_WARNING, "Header may not contain "
						"more than a single header, new line detected");
				return FAILURE;
			}
			if (header_line[i] == '\0') {
				efree(header_line);
				sapi_module.sapi_error(E_WARNING, "Header may not contain NUL bytes");
				return FAILURE;
			}
		}
	}

	sapi_header.header = header_line;
	sapi_header.header_len = header_line_len;

	/* Check the header for a few cases that we have special support for in SAPI */
	if (header_line_len>=5
		&& !strncasecmp(header_line, "HTTP/", 5)) {
		/* filter out the response code */
		sapi_update_response_code(sapi_extract_response_code(header_line));
		/* sapi_update_response_code doesn't free the status line if the code didn't change */
		if (SG(sapi_headers).http_status_line) {
			efree(SG(sapi_headers).http_status_line);
		}
		SG(sapi_headers).http_status_line = header_line;
		return SUCCESS;
	} else {
		colon_offset = strchr(header_line, ':');
		if (colon_offset) {
			*colon_offset = 0;
			if (!strcasecmp(header_line, "Content-Type")) {
				char *ptr = colon_offset+1, *mimetype = NULL, *newheader;
				size_t len = header_line_len - (ptr - header_line), newlen;
				while (*ptr == ' ') {
					ptr++;
					len--;
				}

				/* Disable possible output compression for images */
				if (!strncmp(ptr, "image/", sizeof("image/")-1)) {
					zend_string *key = zend_string_init("zlib.output_compression", sizeof("zlib.output_compression")-1, 0);
					zend_alter_ini_entry_chars(key, "0", sizeof("0") - 1, PHP_INI_USER, PHP_INI_STAGE_RUNTIME);
					zend_string_release(key);
				}

				mimetype = estrdup(ptr);
				newlen = sapi_apply_default_charset(&mimetype, len);
				if (!SG(sapi_headers).mimetype){
					SG(sapi_headers).mimetype = estrdup(mimetype);
				}

				if (newlen != 0) {
					newlen += sizeof("Content-type: ");
					newheader = emalloc(newlen);
					PHP_STRLCPY(newheader, "Content-type: ", newlen, sizeof("Content-type: ")-1);
					strlcat(newheader, mimetype, newlen);
					sapi_header.header = newheader;
					sapi_header.header_len = (uint)(newlen - 1);
					efree(header_line);
				}
				efree(mimetype);
				SG(sapi_headers).send_default_content_type = 0;
			} else if (!strcasecmp(header_line, "Content-Length")) {
				/* Script is setting Content-length. The script cannot reasonably
				 * know the size of the message body after compression, so it's best
				 * do disable compression altogether. This contributes to making scripts
				 * portable between setups that have and don't have zlib compression
				 * enabled globally. See req #44164 */
				zend_string *key = zend_string_init("zlib.output_compression", sizeof("zlib.output_compression")-1, 0);
				zend_alter_ini_entry_chars(key,
					"0", sizeof("0") - 1, PHP_INI_USER, PHP_INI_STAGE_RUNTIME);
				zend_string_release(key);
			} else if (!strcasecmp(header_line, "Location")) {
				if ((SG(sapi_headers).http_response_code < 300 ||
					SG(sapi_headers).http_response_code > 399) &&
					SG(sapi_headers).http_response_code != 201) {
					/* Return a Found Redirect if one is not already specified */
					if (http_response_code) { /* user specified redirect code */
						sapi_update_response_code(http_response_code);
					} else if (SG(request_info).proto_num > 1000 &&
					   SG(request_info).request_method &&
					   strcmp(SG(request_info).request_method, "HEAD") &&
					   strcmp(SG(request_info).request_method, "GET")) {
						sapi_update_response_code(303);
					} else {
						sapi_update_response_code(302);
					}
				}
			} else if (!strcasecmp(header_line, "WWW-Authenticate")) { /* HTTP Authentication */
				sapi_update_response_code(401); /* authentication-required */
			}
			if (sapi_header.header==header_line) {
				*colon_offset = ':';
			}
		}
	}
	if (http_response_code) {
		sapi_update_response_code(http_response_code);
	}
	sapi_header_add_op(op, &sapi_header);
	return SUCCESS;
}
Пример #16
0
SAPI_API SAPI_POST_HANDLER_FUNC(rfc1867_post_handler) /* {{{ */
{
	char *boundary, *s = NULL, *boundary_end = NULL, *start_arr = NULL, *array_index = NULL;
	char *lbuf = NULL, *abuf = NULL;
	zend_string *temp_filename = NULL;
	int boundary_len = 0, cancel_upload = 0, is_arr_upload = 0, array_len = 0;
	int64_t total_bytes = 0, max_file_size = 0;
	int skip_upload = 0, anonindex = 0, is_anonymous;
	HashTable *uploaded_files = NULL;
	multipart_buffer *mbuff;
	zval *array_ptr = (zval *) arg;
	int fd = -1;
	zend_llist header;
	void *event_extra_data = NULL;
	unsigned int llen = 0;
	int upload_cnt = INI_INT("max_file_uploads");
	const zend_encoding *internal_encoding = zend_multibyte_get_internal_encoding();
	php_rfc1867_getword_t getword;
	php_rfc1867_getword_conf_t getword_conf;
	php_rfc1867_basename_t _basename;
	zend_long count = 0;

	if (php_rfc1867_encoding_translation() && internal_encoding) {
		getword = php_rfc1867_getword;
		getword_conf = php_rfc1867_getword_conf;
		_basename = php_rfc1867_basename;
	} else {
		getword = php_ap_getword;
		getword_conf = php_ap_getword_conf;
		_basename = php_ap_basename;
	}

	if (SG(post_max_size) > 0 && SG(request_info).content_length > SG(post_max_size)) {
		sapi_module.sapi_error(E_WARNING, "POST Content-Length of " ZEND_LONG_FMT " bytes exceeds the limit of " ZEND_LONG_FMT " bytes", SG(request_info).content_length, SG(post_max_size));
		return;
	}

	/* Get the boundary */
	boundary = strstr(content_type_dup, "boundary");
	if (!boundary) {
		int content_type_len = (int)strlen(content_type_dup);
		char *content_type_lcase = estrndup(content_type_dup, content_type_len);

		php_strtolower(content_type_lcase, content_type_len);
		boundary = strstr(content_type_lcase, "boundary");
		if (boundary) {
			boundary = content_type_dup + (boundary - content_type_lcase);
		}
		efree(content_type_lcase);
	}

	if (!boundary || !(boundary = strchr(boundary, '='))) {
		sapi_module.sapi_error(E_WARNING, "Missing boundary in multipart/form-data POST data");
		return;
	}

	boundary++;
	boundary_len = (int)strlen(boundary);

	if (boundary[0] == '"') {
		boundary++;
		boundary_end = strchr(boundary, '"');
		if (!boundary_end) {
			sapi_module.sapi_error(E_WARNING, "Invalid boundary in multipart/form-data POST data");
			return;
		}
	} else {
		/* search for the end of the boundary */
		boundary_end = strpbrk(boundary, ",;");
	}
	if (boundary_end) {
		boundary_end[0] = '\0';
		boundary_len = boundary_end-boundary;
	}

	/* Initialize the buffer */
	if (!(mbuff = multipart_buffer_new(boundary, boundary_len))) {
		sapi_module.sapi_error(E_WARNING, "Unable to initialize the input buffer");
		return;
	}

	/* Initialize $_FILES[] */
	zend_hash_init(&PG(rfc1867_protected_variables), 8, NULL, NULL, 0);

	ALLOC_HASHTABLE(uploaded_files);
	zend_hash_init(uploaded_files, 8, NULL, free_filename, 0);
	SG(rfc1867_uploaded_files) = uploaded_files;

	if (Z_TYPE(PG(http_globals)[TRACK_VARS_FILES]) != IS_ARRAY) {
		/* php_auto_globals_create_files() might have already done that */
		array_init(&PG(http_globals)[TRACK_VARS_FILES]);
	}

	zend_llist_init(&header, sizeof(mime_header_entry), (llist_dtor_func_t) php_free_hdr_entry, 0);

	if (php_rfc1867_callback != NULL) {
		multipart_event_start event_start;

		event_start.content_length = SG(request_info).content_length;
		if (php_rfc1867_callback(MULTIPART_EVENT_START, &event_start, &event_extra_data) == FAILURE) {
			goto fileupload_done;
		}
	}

	while (!multipart_buffer_eof(mbuff))
	{
		char buff[FILLUNIT];
		char *cd = NULL, *param = NULL, *filename = NULL, *tmp = NULL;
		size_t blen = 0, wlen = 0;
		zend_off_t offset;

		zend_llist_clean(&header);

		if (!multipart_buffer_headers(mbuff, &header)) {
			goto fileupload_done;
		}

		if ((cd = php_mime_get_hdr_value(header, "Content-Disposition"))) {
			char *pair = NULL;
			int end = 0;

			while (isspace(*cd)) {
				++cd;
			}

			while (*cd && (pair = getword(mbuff->input_encoding, &cd, ';')))
			{
				char *key = NULL, *word = pair;

				while (isspace(*cd)) {
					++cd;
				}

				if (strchr(pair, '=')) {
					key = getword(mbuff->input_encoding, &pair, '=');

					if (!strcasecmp(key, "name")) {
						if (param) {
							efree(param);
						}
						param = getword_conf(mbuff->input_encoding, pair);
						if (mbuff->input_encoding && internal_encoding) {
							unsigned char *new_param;
							size_t new_param_len;
							if ((size_t)-1 != zend_multibyte_encoding_converter(&new_param, &new_param_len, (unsigned char *)param, strlen(param), internal_encoding, mbuff->input_encoding)) {
								efree(param);
								param = (char *)new_param;
							}
						}
					} else if (!strcasecmp(key, "filename")) {
						if (filename) {
							efree(filename);
						}
						filename = getword_conf(mbuff->input_encoding, pair);
						if (mbuff->input_encoding && internal_encoding) {
							unsigned char *new_filename;
							size_t new_filename_len;
							if ((size_t)-1 != zend_multibyte_encoding_converter(&new_filename, &new_filename_len, (unsigned char *)filename, strlen(filename), internal_encoding, mbuff->input_encoding)) {
								efree(filename);
								filename = (char *)new_filename;
							}
						}
					}
				}
				if (key) {
					efree(key);
				}
				efree(word);
			}

			/* Normal form variable, safe to read all data into memory */
			if (!filename && param) {
				size_t value_len;
				char *value = multipart_buffer_read_body(mbuff, &value_len);
				size_t new_val_len; /* Dummy variable */

				if (!value) {
					value = estrdup("");
					value_len = 0;
				}

				if (mbuff->input_encoding && internal_encoding) {
					unsigned char *new_value;
					size_t new_value_len;
					if ((size_t)-1 != zend_multibyte_encoding_converter(&new_value, &new_value_len, (unsigned char *)value, value_len, internal_encoding, mbuff->input_encoding)) {
						efree(value);
						value = (char *)new_value;
						value_len = new_value_len;
					}
				}

				if (++count <= PG(max_input_vars) && sapi_module.input_filter(PARSE_POST, param, &value, value_len, &new_val_len)) {
					if (php_rfc1867_callback != NULL) {
						multipart_event_formdata event_formdata;
						size_t newlength = new_val_len;

						event_formdata.post_bytes_processed = SG(read_post_bytes);
						event_formdata.name = param;
						event_formdata.value = &value;
						event_formdata.length = new_val_len;
						event_formdata.newlength = &newlength;
						if (php_rfc1867_callback(MULTIPART_EVENT_FORMDATA, &event_formdata, &event_extra_data) == FAILURE) {
							efree(param);
							efree(value);
							continue;
						}
						new_val_len = newlength;
					}
					safe_php_register_variable(param, value, new_val_len, array_ptr, 0);
				} else {
					if (count == PG(max_input_vars) + 1) {
						php_error_docref(NULL, E_WARNING, "Input variables exceeded " ZEND_LONG_FMT ". To increase the limit change max_input_vars in php.ini.", PG(max_input_vars));
					}

					if (php_rfc1867_callback != NULL) {
						multipart_event_formdata event_formdata;

						event_formdata.post_bytes_processed = SG(read_post_bytes);
						event_formdata.name = param;
						event_formdata.value = &value;
						event_formdata.length = value_len;
						event_formdata.newlength = NULL;
						php_rfc1867_callback(MULTIPART_EVENT_FORMDATA, &event_formdata, &event_extra_data);
					}
				}

				if (!strcasecmp(param, "MAX_FILE_SIZE")) {
#ifdef HAVE_ATOLL
					max_file_size = atoll(value);
#else
					max_file_size = strtoll(value, NULL, 10);
#endif
				}

				efree(param);
				efree(value);
				continue;
			}

			/* If file_uploads=off, skip the file part */
			if (!PG(file_uploads)) {
				skip_upload = 1;
			} else if (upload_cnt <= 0) {
				skip_upload = 1;
				sapi_module.sapi_error(E_WARNING, "Maximum number of allowable file uploads has been exceeded");
			}

			/* Return with an error if the posted data is garbled */
			if (!param && !filename) {
				sapi_module.sapi_error(E_WARNING, "File Upload Mime headers garbled");
				goto fileupload_done;
			}

			if (!param) {
				is_anonymous = 1;
				param = emalloc(MAX_SIZE_ANONNAME);
				snprintf(param, MAX_SIZE_ANONNAME, "%u", anonindex++);
			} else {
				is_anonymous = 0;
			}

			/* New Rule: never repair potential malicious user input */
			if (!skip_upload) {
				long c = 0;
				tmp = param;

				while (*tmp) {
					if (*tmp == '[') {
						c++;
					} else if (*tmp == ']') {
						c--;
						if (tmp[1] && tmp[1] != '[') {
							skip_upload = 1;
							break;
						}
					}
					if (c < 0) {
						skip_upload = 1;
						break;
					}
					tmp++;
				}
				/* Brackets should always be closed */
				if(c != 0) {
					skip_upload = 1;
				}
			}

			total_bytes = cancel_upload = 0;
			temp_filename = NULL;
			fd = -1;

			if (!skip_upload && php_rfc1867_callback != NULL) {
				multipart_event_file_start event_file_start;

				event_file_start.post_bytes_processed = SG(read_post_bytes);
				event_file_start.name = param;
				event_file_start.filename = &filename;
				if (php_rfc1867_callback(MULTIPART_EVENT_FILE_START, &event_file_start, &event_extra_data) == FAILURE) {
					temp_filename = NULL;
					efree(param);
					efree(filename);
					continue;
				}
			}

			if (skip_upload) {
				efree(param);
				efree(filename);
				continue;
			}

			if (filename[0] == '\0') {
#if DEBUG_FILE_UPLOAD
				sapi_module.sapi_error(E_NOTICE, "No file uploaded");
#endif
				cancel_upload = UPLOAD_ERROR_D;
			}

			offset = 0;
			end = 0;

			if (!cancel_upload) {
				/* only bother to open temp file if we have data */
				blen = multipart_buffer_read(mbuff, buff, sizeof(buff), &end);
#if DEBUG_FILE_UPLOAD
				if (blen > 0) {
#else
				/* in non-debug mode we have no problem with 0-length files */
				{
#endif
					fd = php_open_temporary_fd_ex(PG(upload_tmp_dir), "php", &temp_filename, 1);
					upload_cnt--;
					if (fd == -1) {
						sapi_module.sapi_error(E_WARNING, "File upload error - unable to create a temporary file");
						cancel_upload = UPLOAD_ERROR_E;
					}
				}
			}

			while (!cancel_upload && (blen > 0))
			{
				if (php_rfc1867_callback != NULL) {
					multipart_event_file_data event_file_data;

					event_file_data.post_bytes_processed = SG(read_post_bytes);
					event_file_data.offset = offset;
					event_file_data.data = buff;
					event_file_data.length = blen;
					event_file_data.newlength = &blen;
					if (php_rfc1867_callback(MULTIPART_EVENT_FILE_DATA, &event_file_data, &event_extra_data) == FAILURE) {
						cancel_upload = UPLOAD_ERROR_X;
						continue;
					}
				}

				if (PG(upload_max_filesize) > 0 && (zend_long)(total_bytes+blen) > PG(upload_max_filesize)) {
#if DEBUG_FILE_UPLOAD
					sapi_module.sapi_error(E_NOTICE, "upload_max_filesize of " ZEND_LONG_FMT " bytes exceeded - file [%s=%s] not saved", PG(upload_max_filesize), param, filename);
#endif
					cancel_upload = UPLOAD_ERROR_A;
				} else if (max_file_size && ((zend_long)(total_bytes+blen) > max_file_size)) {
#if DEBUG_FILE_UPLOAD
					sapi_module.sapi_error(E_NOTICE, "MAX_FILE_SIZE of %" PRId64 " bytes exceeded - file [%s=%s] not saved", max_file_size, param, filename);
#endif
					cancel_upload = UPLOAD_ERROR_B;
				} else if (blen > 0) {
#ifdef PHP_WIN32
					wlen = write(fd, buff, (unsigned int)blen);
#else
					wlen = write(fd, buff, blen);
#endif

					if (wlen == (size_t)-1) {
						/* write failed */
#if DEBUG_FILE_UPLOAD
						sapi_module.sapi_error(E_NOTICE, "write() failed - %s", strerror(errno));
#endif
						cancel_upload = UPLOAD_ERROR_F;
					} else if (wlen < blen) {
#if DEBUG_FILE_UPLOAD
						sapi_module.sapi_error(E_NOTICE, "Only %zd bytes were written, expected to write %zd", wlen, blen);
#endif
						cancel_upload = UPLOAD_ERROR_F;
					} else {
						total_bytes += wlen;
					}
					offset += wlen;
				}

				/* read data for next iteration */
				blen = multipart_buffer_read(mbuff, buff, sizeof(buff), &end);
			}

			if (fd != -1) { /* may not be initialized if file could not be created */
				close(fd);
			}

			if (!cancel_upload && !end) {
#if DEBUG_FILE_UPLOAD
				sapi_module.sapi_error(E_NOTICE, "Missing mime boundary at the end of the data for file %s", filename[0] != '\0' ? filename : "");
#endif
				cancel_upload = UPLOAD_ERROR_C;
			}
#if DEBUG_FILE_UPLOAD
			if (filename[0] != '\0' && total_bytes == 0 && !cancel_upload) {
				sapi_module.sapi_error(E_WARNING, "Uploaded file size 0 - file [%s=%s] not saved", param, filename);
				cancel_upload = 5;
			}
#endif
			if (php_rfc1867_callback != NULL) {
				multipart_event_file_end event_file_end;

				event_file_end.post_bytes_processed = SG(read_post_bytes);
				event_file_end.temp_filename = temp_filename ? ZSTR_VAL(temp_filename) : NULL;
				event_file_end.cancel_upload = cancel_upload;
				if (php_rfc1867_callback(MULTIPART_EVENT_FILE_END, &event_file_end, &event_extra_data) == FAILURE) {
					cancel_upload = UPLOAD_ERROR_X;
				}
			}

			if (cancel_upload) {
				if (temp_filename) {
					if (cancel_upload != UPLOAD_ERROR_E) { /* file creation failed */
						unlink(ZSTR_VAL(temp_filename));
					}
					zend_string_release_ex(temp_filename, 0);
				}
				temp_filename = NULL;
			} else {
				zend_hash_add_ptr(SG(rfc1867_uploaded_files), temp_filename, temp_filename);
			}

			/* is_arr_upload is true when name of file upload field
			 * ends in [.*]
			 * start_arr is set to point to 1st [ */
			is_arr_upload =	(start_arr = strchr(param,'[')) && (param[strlen(param)-1] == ']');

			if (is_arr_upload) {
				array_len = (int)strlen(start_arr);
				if (array_index) {
					efree(array_index);
				}
				array_index = estrndup(start_arr + 1, array_len - 2);
			}

			/* Add $foo_name */
			if (llen < strlen(param) + MAX_SIZE_OF_INDEX + 1) {
				llen = (int)strlen(param);
				lbuf = (char *) safe_erealloc(lbuf, llen, 1, MAX_SIZE_OF_INDEX + 1);
				llen += MAX_SIZE_OF_INDEX + 1;
			}

			if (is_arr_upload) {
				if (abuf) efree(abuf);
				abuf = estrndup(param, strlen(param)-array_len);
				snprintf(lbuf, llen, "%s_name[%s]", abuf, array_index);
			} else {
				snprintf(lbuf, llen, "%s_name", param);
			}

			/* The \ check should technically be needed for win32 systems only where
			 * it is a valid path separator. However, IE in all it's wisdom always sends
			 * the full path of the file on the user's filesystem, which means that unless
			 * the user does basename() they get a bogus file name. Until IE's user base drops
			 * to nill or problem is fixed this code must remain enabled for all systems. */
			s = _basename(internal_encoding, filename);
			if (!s) {
				s = filename;
			}

			if (!is_anonymous) {
				safe_php_register_variable(lbuf, s, strlen(s), NULL, 0);
			}

			/* Add $foo[name] */
			if (is_arr_upload) {
				snprintf(lbuf, llen, "%s[name][%s]", abuf, array_index);
			} else {
				snprintf(lbuf, llen, "%s[name]", param);
			}
			register_http_post_files_variable(lbuf, s, &PG(http_globals)[TRACK_VARS_FILES], 0);
			efree(filename);
			s = NULL;

			/* Possible Content-Type: */
			if (cancel_upload || !(cd = php_mime_get_hdr_value(header, "Content-Type"))) {
				cd = "";
			} else {
				/* fix for Opera 6.01 */
				s = strchr(cd, ';');
				if (s != NULL) {
					*s = '\0';
				}
			}

			/* Add $foo_type */
			if (is_arr_upload) {
				snprintf(lbuf, llen, "%s_type[%s]", abuf, array_index);
			} else {
				snprintf(lbuf, llen, "%s_type", param);
			}
			if (!is_anonymous) {
				safe_php_register_variable(lbuf, cd, strlen(cd), NULL, 0);
			}

			/* Add $foo[type] */
			if (is_arr_upload) {
				snprintf(lbuf, llen, "%s[type][%s]", abuf, array_index);
			} else {
				snprintf(lbuf, llen, "%s[type]", param);
			}
			register_http_post_files_variable(lbuf, cd, &PG(http_globals)[TRACK_VARS_FILES], 0);

			/* Restore Content-Type Header */
			if (s != NULL) {
				*s = ';';
			}
			s = "";

			{
				/* store temp_filename as-is (in case upload_tmp_dir
				 * contains escapeable characters. escape only the variable name.) */
				zval zfilename;

				/* Initialize variables */
				add_protected_variable(param);

				/* if param is of form xxx[.*] this will cut it to xxx */
				if (!is_anonymous) {
					if (temp_filename) {
						ZVAL_STR_COPY(&zfilename, temp_filename);
					} else {
						ZVAL_EMPTY_STRING(&zfilename);
					}
					safe_php_register_variable_ex(param, &zfilename, NULL, 1);
				}

				/* Add $foo[tmp_name] */
				if (is_arr_upload) {
					snprintf(lbuf, llen, "%s[tmp_name][%s]", abuf, array_index);
				} else {
					snprintf(lbuf, llen, "%s[tmp_name]", param);
				}
				add_protected_variable(lbuf);
				if (temp_filename) {
					ZVAL_STR_COPY(&zfilename, temp_filename);
				} else {
					ZVAL_EMPTY_STRING(&zfilename);
				}
				register_http_post_files_variable_ex(lbuf, &zfilename, &PG(http_globals)[TRACK_VARS_FILES], 1);
			}

			{
				zval file_size, error_type;
				int size_overflow = 0;
				char file_size_buf[65];

				ZVAL_LONG(&error_type, cancel_upload);

				/* Add $foo[error] */
				if (cancel_upload) {
					ZVAL_LONG(&file_size, 0);
				} else {
					if (total_bytes > ZEND_LONG_MAX) {
#ifdef PHP_WIN32
						if (_i64toa_s(total_bytes, file_size_buf, 65, 10)) {
							file_size_buf[0] = '0';
							file_size_buf[1] = '\0';
						}
#else
						{
							int __len = snprintf(file_size_buf, 65, "%" PRId64, total_bytes);
							file_size_buf[__len] = '\0';
						}
#endif
						size_overflow = 1;

					} else {
						ZVAL_LONG(&file_size, total_bytes);
					}
				}

				if (is_arr_upload) {
					snprintf(lbuf, llen, "%s[error][%s]", abuf, array_index);
				} else {
					snprintf(lbuf, llen, "%s[error]", param);
				}
				register_http_post_files_variable_ex(lbuf, &error_type, &PG(http_globals)[TRACK_VARS_FILES], 0);

				/* Add $foo_size */
				if (is_arr_upload) {
					snprintf(lbuf, llen, "%s_size[%s]", abuf, array_index);
				} else {
					snprintf(lbuf, llen, "%s_size", param);
				}
				if (!is_anonymous) {
					if (size_overflow) {
						ZVAL_STRING(&file_size, file_size_buf);
					}
					safe_php_register_variable_ex(lbuf, &file_size, NULL, size_overflow);
				}

				/* Add $foo[size] */
				if (is_arr_upload) {
					snprintf(lbuf, llen, "%s[size][%s]", abuf, array_index);
				} else {
					snprintf(lbuf, llen, "%s[size]", param);
				}
				if (size_overflow) {
					ZVAL_STRING(&file_size, file_size_buf);
				}
				register_http_post_files_variable_ex(lbuf, &file_size, &PG(http_globals)[TRACK_VARS_FILES], size_overflow);
			}
			efree(param);
		}
	}

fileupload_done:
	if (php_rfc1867_callback != NULL) {
		multipart_event_end event_end;

		event_end.post_bytes_processed = SG(read_post_bytes);
		php_rfc1867_callback(MULTIPART_EVENT_END, &event_end, &event_extra_data);
	}

	if (lbuf) efree(lbuf);
	if (abuf) efree(abuf);
	if (array_index) efree(array_index);
	zend_hash_destroy(&PG(rfc1867_protected_variables));
	zend_llist_destroy(&header);
	if (mbuff->boundary_next) efree(mbuff->boundary_next);
	if (mbuff->boundary) efree(mbuff->boundary);
	if (mbuff->buffer) efree(mbuff->buffer);
	if (mbuff) efree(mbuff);
}
/* }}} */

SAPI_API void php_rfc1867_set_multibyte_callbacks(
					php_rfc1867_encoding_translation_t encoding_translation,
					php_rfc1867_get_detect_order_t get_detect_order,
					php_rfc1867_set_input_encoding_t set_input_encoding,
					php_rfc1867_getword_t getword,
					php_rfc1867_getword_conf_t getword_conf,
					php_rfc1867_basename_t basename) /* {{{ */
{
	php_rfc1867_encoding_translation = encoding_translation;
	php_rfc1867_get_detect_order = get_detect_order;
	php_rfc1867_set_input_encoding = set_input_encoding;
	php_rfc1867_getword = getword;
	php_rfc1867_getword_conf = getword_conf;
	php_rfc1867_basename = basename;
}
Пример #17
0
/* {{{ php_url_parse
 */
PHPAPI php_url *php_url_parse_ex(char const *str, int length)
{
    char port_buf[6];
    php_url *ret = (php_url*) ecalloc(1, sizeof(php_url));
    char const *s, *e, *p, *pp, *ue;

    s = str;
    ue = s + length;

    /* parse scheme */
    if ((e = (const char*) memchr(s, ':', length)) && (e - s)) {
        /* validate scheme */
        p = s;
        while (p < e) {
            /* scheme = 1*[ lowalpha | digit | "+" | "-" | "." ] */
            if (!isalpha(*p) && !isdigit(*p) && *p != '+' && *p != '.' && *p != '-') {
                if (e + 1 < ue) {
                    goto parse_port;
                } else {
                    goto just_path;
                }
            }
            p++;
        }

        if (*(e + 1) == '\0') { /* only scheme is available */
            ret->scheme = estrndup(s, (e - s));
            php_replace_controlchars_ex(ret->scheme, (e - s));
            goto end;
        }

        /*
         * certain schemas like mailto: and zlib: may not have any / after them
         * this check ensures we support those.
         */
        if (*(e+1) != '/') {
            /* check if the data we get is a port this allows us to
             * correctly parse things like a.com:80
             */
            p = e + 1;
            while (isdigit(*p)) {
                p++;
            }

            if ((*p == '\0' || *p == '/') && (p - e) < 7) {
                goto parse_port;
            }

            ret->scheme = estrndup(s, (e-s));
            php_replace_controlchars_ex(ret->scheme, (e - s));

            length -= ++e - s;
            s = e;
            goto just_path;
        } else {
            ret->scheme = estrndup(s, (e-s));
            php_replace_controlchars_ex(ret->scheme, (e - s));

            if (*(e+2) == '/') {
                s = e + 3;
                if (!strncasecmp("file", ret->scheme, sizeof("file"))) {
                    if (*(e + 3) == '/') {
                        /* support windows drive letters as in:
                           file:///c:/somedir/file.txt
                        */
                        if (*(e + 5) == ':') {
                            s = e + 4;
                        }
                        goto nohost;
                    }
                }
            } else {
                if (!strncasecmp("file", ret->scheme, sizeof("file"))) {
                    s = e + 1;
                    goto nohost;
                } else {
                    length -= ++e - s;
                    s = e;
                    goto just_path;
                }
            }
        }
    } else if (e) { /* no scheme; starts with colon: look for port */
parse_port:
        p = e + 1;
        pp = p;

        while (pp-p < 6 && isdigit(*pp)) {
            pp++;
        }

        if (pp - p > 0 && pp - p < 6 && (*pp == '/' || *pp == '\0')) {
            long port;
            memcpy(port_buf, p, (pp - p));
            port_buf[pp - p] = '\0';
            port = strtol(port_buf, NULL, 10);
            if (port > 0 && port <= 65535) {
                ret->port = (unsigned short) port;
            } else {
                STR_FREE(ret->scheme);
                efree(ret);
                return NULL;
            }
        } else if (p == pp && *pp == '\0') {
            STR_FREE(ret->scheme);
            efree(ret);
            return NULL;
        } else if (*s == '/' && *(s+1) == '/') { /* relative-scheme URL */
            s += 2;
        } else {
            goto just_path;
        }
    } else if (*s == '/' && *(s+1) == '/') { /* relative-scheme URL */
        s += 2;
    } else {
just_path:
        ue = s + length;
        goto nohost;
    }

    e = ue;

    if (!(p = (const char*) memchr(s, '/', (ue - s)))) {
        char *query, *fragment;

        query = (char*) memchr(s, '?', (ue - s));
        fragment = (char*) memchr(s, '#', (ue - s));

        if (query && fragment) {
            if (query > fragment) {
                e = fragment;
            } else {
                e = query;
            }
        } else if (query) {
            e = query;
        } else if (fragment) {
            e = fragment;
        }
    } else {
        e = p;
    }

    /* check for login and password */
    if ((p = (const char*) zend_memrchr(s, '@', (e-s)))) {
        if ((pp = (const char*) memchr(s, ':', (p-s)))) {
            if ((pp-s) > 0) {
                ret->user = estrndup(s, (pp-s));
                php_replace_controlchars_ex(ret->user, (pp - s));
            }

            pp++;
            if (p-pp > 0) {
                ret->pass = estrndup(pp, (p-pp));
                php_replace_controlchars_ex(ret->pass, (p-pp));
            }
        } else {
            ret->user = estrndup(s, (p-s));
            php_replace_controlchars_ex(ret->user, (p-s));
        }

        s = p + 1;
    }

    /* check for port */
    if (*s == '[' && *(e-1) == ']') {
        /* Short circuit portscan,
           we're dealing with an
           IPv6 embedded address */
        p = s;
    } else {
        p = (const char*)zend_memrchr(s, ':', (e - s + 1));
    }

    if (p >= s && *p == ':') {
        if (!ret->port) {
            p++;
            if (e-p > 5) { /* port cannot be longer then 5 characters */
                STR_FREE(ret->scheme);
                STR_FREE(ret->user);
                STR_FREE(ret->pass);
                efree(ret);
                return NULL;
            } else if (e - p > 0) {
                long port;
                memcpy(port_buf, p, (e - p));
                port_buf[e - p] = '\0';
                port = strtol(port_buf, NULL, 10);
                if (port > 0 && port <= 65535) {
                    ret->port = (unsigned short)port;
                } else {
                    STR_FREE(ret->scheme);
                    STR_FREE(ret->user);
                    STR_FREE(ret->pass);
                    efree(ret);
                    return NULL;
                }
            }
            p--;
        }
    } else {
        p = e;
    }

    /* check if we have a valid host, if we don't reject the string as url */
    if ((p-s) < 1) {
        STR_FREE(ret->scheme);
        STR_FREE(ret->user);
        STR_FREE(ret->pass);
        efree(ret);
        return NULL;
    }

    ret->host = estrndup(s, (p-s));
    php_replace_controlchars_ex(ret->host, (p - s));

    if (e == ue) {
        return ret;
    }

    s = e;

nohost:

    if ((p = (const char*) memchr(s, '?', (ue - s)))) {
        pp = (const char*)memchr(s, '#', (ue - s));

        if (pp && pp < p) {
            if (pp - s) {
                ret->path = estrndup(s, (pp-s));
                php_replace_controlchars_ex(ret->path, (pp - s));
            }
            p = pp;
            goto label_parse;
        }

        if (p - s) {
            ret->path = estrndup(s, (p-s));
            php_replace_controlchars_ex(ret->path, (p - s));
        }

        if (pp) {
            if (pp - ++p) {
                ret->query = estrndup(p, (pp-p));
                php_replace_controlchars_ex(ret->query, (pp - p));
            }
            p = pp;
            goto label_parse;
        } else if (++p - ue) {
            ret->query = estrndup(p, (ue-p));
            php_replace_controlchars_ex(ret->query, (ue - p));
        }
    } else if ((p = (const char*) memchr(s, '#', (ue - s)))) {
        if (p - s) {
            ret->path = estrndup(s, (p-s));
            php_replace_controlchars_ex(ret->path, (p - s));
        }

label_parse:
        p++;

        if (ue - p) {
            ret->fragment = estrndup(p, (ue-p));
            php_replace_controlchars_ex(ret->fragment, (ue - p));
        }
    } else {
        ret->path = estrndup(s, (ue-s));
        php_replace_controlchars_ex(ret->path, (ue - s));
    }
end:
    return ret;
}
Пример #18
0
static PHP_METHOD(swoole_redis, __call)
{
    zval *params;
    char *command;
    zend_size_t command_len;

    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz", &command, &command_len, &params) == FAILURE)
    {
        return;
    }

    swRedisClient *redis = swoole_get_object(getThis());
    switch (redis->state)
    {
    case SWOOLE_REDIS_STATE_CONNECT:
        swoole_php_error(E_WARNING, "redis client is not connected.");
        RETURN_FALSE;
        break;
    case SWOOLE_REDIS_STATE_WAIT:
        swoole_php_error(E_WARNING, "redis client is waiting for response.");
        RETURN_FALSE;
        break;
    case SWOOLE_REDIS_STATE_CLOSED:
        swoole_php_error(E_WARNING, "redis client connection is closed.");
        RETURN_FALSE;
        break;
    default:
        break;
    }

#if PHP_MAJOR_VERSION < 7
    zval *callback;
    zval **cb_tmp;
    if (zend_hash_index_find(Z_ARRVAL_P(params), zend_hash_num_elements(Z_ARRVAL_P(params)) - 1, (void **) &cb_tmp) == FAILURE)
    {
        swoole_php_error(E_WARNING, "index out of array.");
        RETURN_FALSE;
    }
    callback = *cb_tmp;
    redis->result_callback = callback;
#else
    zval *callback = zend_hash_index_find(Z_ARRVAL_P(params), zend_hash_num_elements(Z_ARRVAL_P(params)) - 1);
    if (callback == NULL)
    {
        swoole_php_error(E_WARNING, "index out of array.");
        RETURN_FALSE;
    }
    redis->result_callback = &redis->_result_callback;
    memcpy(redis->result_callback, callback, sizeof(zval));
#endif

    sw_zval_add_ref(&redis->result_callback);

    redis->state = SWOOLE_REDIS_STATE_WAIT;

    int argc = zend_hash_num_elements(Z_ARRVAL_P(params));

    size_t stack_argvlen[SW_REDIS_COMMAND_BUFFER_SIZE];
    char *stack_argv[SW_REDIS_COMMAND_BUFFER_SIZE];

    size_t *argvlen;
    char **argv;
    zend_bool free_mm = 0;

    if (argc > SW_REDIS_COMMAND_BUFFER_SIZE)
    {
        argvlen = emalloc(sizeof(size_t) * argc);
        argv = emalloc(sizeof(char*) * argc);
        free_mm = 1;
    }
    else
    {
        argvlen = stack_argvlen;
        argv = stack_argv;
    }

    assert(command_len < SW_REDIS_COMMAND_KEY_SIZE - 1);

    char command_name[SW_REDIS_COMMAND_KEY_SIZE];
    memcpy(command_name, command, command_len);
    command_name[command_len] = '\0';

    argv[0] = command_name;
    argvlen[0] = command_len;

    zval *value;
    int i = 1;

    SW_HASHTABLE_FOREACH_START(Z_ARRVAL_P(params), value)
        convert_to_string(value);
        argvlen[i] = (size_t) Z_STRLEN_P(value);
        argv[i] = estrndup(Z_STRVAL_P(value), Z_STRLEN_P(value));
        if (i == argc - 1)
        {
            break;
        }
        i++;
    SW_HASHTABLE_FOREACH_END();

    if (redisAsyncCommandArgv(redis->context, swoole_redis_onResult, NULL, argc, (const char **) argv, (const size_t *) argvlen) < 0)
    {
        swoole_php_error(E_WARNING, "redisAsyncCommandArgv() failed.");
        RETURN_FALSE;
    }

    for (i = 1; i < argc; i++)
    {
        efree((void* )argv[i]);
    }

    if (free_mm)
    {
        efree(argvlen);
        efree(argv);
    }

    redis->state = SWOOLE_REDIS_STATE_WAIT;
    RETURN_TRUE;
}
Пример #19
0
static int hhvm_register_ini_entries_do_work(
  const zend_ini_entry *ini_entry,
  int module_number,
  int acceptable_mode_mask
  TSRMLS_DC)
{
  auto extension = HPHP::ZendExtension::GetByModuleNumber(module_number);
  assert(extension);

  for (const zend_ini_entry *constp = ini_entry; constp->name; constp++) {
    /*
     * Make a copy of the const version of zend_ini_entry.
     * This const version is static const in the compiled php extension.
     *
     * Copy the given (default) value into a freeable string,
     * so that assignments to the setting will consistently free the
     * previous string.
     *
     * This copy will have its ownership in the 1:1 corresponding
     * ZendUserIniData structure.
     */
    zend_ini_entry *p = new zend_ini_entry();
    *p = *constp;
    p->value = estrndup(p->value, p->value_length);

    /*
     * A factory to generate a unique instance of a UserIniData
     * which will eventually end up in either the per-request or system-wide
     * table that maps ini settings to their callbacks.
     */
    auto userDataCallback = [p]() -> HPHP::UserIniData * {
      return new HPHP::ZendUserIniData(p);
    };

    auto updateCallback = [p](const std::string& value) -> bool {
      TSRMLS_FETCH();
      char* data = estrndup(value.data(), value.size());
      int ret = FAILURE;
      /*
       * Store the data as the current value of this extension's ini setting.
       *
       * It should be safe to free the string we previously allocated,
       * since we have not got to the end of the request when the
       * MemoryManager will free these strings.
       */
      efree(p->value);
      p->value = data;
      p->value_length = value.size();
      if (p->on_modify) {
        ret = p->on_modify(
          p, p->value, p->value_length,
          p->mh_arg1, p->mh_arg2, p->mh_arg3, ZEND_INI_STAGE_STARTUP TSRMLS_CC
        );
      }
      return (ret == SUCCESS);
    };

    auto getCallback = [p]() {
      return std::string(p->value, p->value_length);
    };

    int mode_mask = 0;
    assert(HPHP::IniSetting::Mode::PHP_INI_NONE == 0);
    if (p->modifiable & ZEND_INI_USER & acceptable_mode_mask) {
      mode_mask |= HPHP::IniSetting::Mode::PHP_INI_USER;
    }
    if (p->modifiable & ZEND_INI_PERDIR & acceptable_mode_mask) {
      mode_mask |= HPHP::IniSetting::Mode::PHP_INI_PERDIR;
    }
    if (p->modifiable & ZEND_INI_SYSTEM & acceptable_mode_mask) {
      mode_mask |= HPHP::IniSetting::Mode::PHP_INI_SYSTEM;
    }
    if (mode_mask) {
      HPHP::IniSetting::Mode mode = (HPHP::IniSetting::Mode) mode_mask;
      /*
       * Calls HPHP::IniSetting::Bind<std::string> from/near
       *   hphp/runtime/base/ini-setting.h:205
       * The default value is p->value, which is assigned back
       * by an immediate call to the updateCallback
       *
       */
      HPHP::IniSetting::Bind(
        extension, mode,
        p->name, p->value,
        HPHP::IniSetting::SetAndGet<std::string>(
          updateCallback,
          getCallback,
          userDataCallback));
    }
  }
  return SUCCESS;
}
Пример #20
0
PHP_METHOD(MongoCursor, count) {
  zval *db_z, *coll, *query;
  mongo_cursor *cursor;
  mongo_collection *c;
  mongo_db *db;
  zend_bool all = 0;

  if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b", &all) == FAILURE) {
    return;
  }

  PHP_MONGO_GET_CURSOR(getThis());

  // fake a MongoDB object
  MAKE_STD_ZVAL(db_z);
  object_init_ex(db_z, mongo_ce_DB);
  db = (mongo_db*)zend_object_store_get_object(db_z TSRMLS_CC);
  db->link = cursor->resource;
  MAKE_STD_ZVAL(db->name);
  ZVAL_STRING(db->name, estrndup(cursor->ns, strchr(cursor->ns, '.') - cursor->ns), 0);

  // fake a MongoCollection object
  MAKE_STD_ZVAL(coll);
  object_init_ex(coll, mongo_ce_Collection);
  c = (mongo_collection*)zend_object_store_get_object(coll TSRMLS_CC);
  MAKE_STD_ZVAL(c->ns);
  ZVAL_STRING(c->ns, estrdup(cursor->ns), 0);
  MAKE_STD_ZVAL(c->name);
  ZVAL_STRING(c->name, estrdup(cursor->ns + (strchr(cursor->ns, '.') - cursor->ns) + 1), 0);
  c->parent = db_z;

  if (cursor->query) {
    zval **inner_query = 0;

    if (!cursor->special) {
      query = cursor->query;
      zval_add_ref(&query);
    }
    else if (zend_hash_find(HASH_P(cursor->query), "$query", strlen("$query")+1, (void**)&inner_query) == SUCCESS) {
      query = *inner_query;
      zval_add_ref(&query);
    }
  }
  else {
    MAKE_STD_ZVAL(query);
    array_init(query);
  }

  if (all) {
    zval *limit_z, *skip_z;

    MAKE_STD_ZVAL(limit_z);
    MAKE_STD_ZVAL(skip_z);

    ZVAL_LONG(limit_z, cursor->limit);
    ZVAL_LONG(skip_z, cursor->skip);

    MONGO_METHOD3(MongoCollection, count, return_value, coll, query, limit_z, skip_z);

    zval_ptr_dtor(&limit_z);
    zval_ptr_dtor(&skip_z);
  }
  else {
    MONGO_METHOD1(MongoCollection, count, return_value, coll, query);
  }

  zval_ptr_dtor(&query);

  c->parent = 0;
  zend_objects_store_del_ref(coll TSRMLS_CC);
  zval_ptr_dtor(&coll);

  db->link = 0;
  zend_objects_store_del_ref(db_z TSRMLS_CC);
  zval_ptr_dtor(&db_z);
}
Пример #21
0
/* {{{ mbfl_no_encoding _php_mb_encoding_handler_ex() */
const mbfl_encoding *_php_mb_encoding_handler_ex(const php_mb_encoding_handler_info_t *info, zval *arg, char *res)
{
	char *var, *val;
	const char *s1, *s2;
	char *strtok_buf = NULL, **val_list = NULL;
	zval *array_ptr = (zval *) arg;
	size_t n, num, *len_list = NULL;
	size_t val_len, new_val_len;
	mbfl_string string, resvar, resval;
	const mbfl_encoding *from_encoding = NULL;
	mbfl_encoding_detector *identd = NULL;
	mbfl_buffer_converter *convd = NULL;

	mbfl_string_init_set(&string, info->to_language, info->to_encoding);
	mbfl_string_init_set(&resvar, info->to_language, info->to_encoding);
	mbfl_string_init_set(&resval, info->to_language, info->to_encoding);

	if (!res || *res == '\0') {
		goto out;
	}

	/* count the variables(separators) contained in the "res".
	 * separator may contain multiple separator chars.
	 */
	num = 1;
	for (s1=res; *s1 != '\0'; s1++) {
		for (s2=info->separator; *s2 != '\0'; s2++) {
			if (*s1 == *s2) {
				num++;
			}
		}
	}
	num *= 2; /* need space for variable name and value */

	val_list = (char **)ecalloc(num, sizeof(char *));
	len_list = (size_t *)ecalloc(num, sizeof(size_t));

	/* split and decode the query */
	n = 0;
	strtok_buf = NULL;
	var = php_strtok_r(res, info->separator, &strtok_buf);
	while (var)  {
		val = strchr(var, '=');
		if (val) { /* have a value */
			len_list[n] = php_url_decode(var, val-var);
			val_list[n] = var;
			n++;

			*val++ = '\0';
			val_list[n] = val;
			len_list[n] = php_url_decode(val, strlen(val));
		} else {
			len_list[n] = php_url_decode(var, strlen(var));
			val_list[n] = var;
			n++;

			val_list[n] = "";
			len_list[n] = 0;
		}
		n++;
		var = php_strtok_r(NULL, info->separator, &strtok_buf);
	}

	if (ZEND_SIZE_T_GT_ZEND_LONG(n, (PG(max_input_vars) * 2))) {
		php_error_docref(NULL, E_WARNING, "Input variables exceeded " ZEND_LONG_FMT ". To increase the limit change max_input_vars in php.ini.", PG(max_input_vars));
		goto out;
	}

	num = n; /* make sure to process initialized vars only */

	/* initialize converter */
	if (info->num_from_encodings <= 0) {
		from_encoding = &mbfl_encoding_pass;
	} else if (info->num_from_encodings == 1) {
		from_encoding = info->from_encodings[0];
	} else {
		/* auto detect */
		from_encoding = NULL;
		identd = mbfl_encoding_detector_new(info->from_encodings, info->num_from_encodings, MBSTRG(strict_detection));
		if (identd != NULL) {
			n = 0;
			while (n < num) {
				string.val = (unsigned char *)val_list[n];
				string.len = len_list[n];
				if (mbfl_encoding_detector_feed(identd, &string)) {
					break;
				}
				n++;
			}
			from_encoding = mbfl_encoding_detector_judge(identd);
			mbfl_encoding_detector_delete(identd);
		}
		if (!from_encoding) {
			if (info->report_errors) {
				php_error_docref(NULL, E_WARNING, "Unable to detect encoding");
			}
			from_encoding = &mbfl_encoding_pass;
		}
	}

	convd = NULL;
	if (from_encoding != &mbfl_encoding_pass) {
		convd = mbfl_buffer_converter_new(from_encoding, info->to_encoding, 0);
		if (convd != NULL) {
			mbfl_buffer_converter_illegal_mode(convd, MBSTRG(current_filter_illegal_mode));
			mbfl_buffer_converter_illegal_substchar(convd, MBSTRG(current_filter_illegal_substchar));
		} else {
			if (info->report_errors) {
				php_error_docref(NULL, E_WARNING, "Unable to create converter");
			}
			goto out;
		}
	}

	/* convert encoding */
	string.encoding = from_encoding;

	n = 0;
	while (n < num) {
		string.val = (unsigned char *)val_list[n];
		string.len = len_list[n];
		if (convd != NULL && mbfl_buffer_converter_feed_result(convd, &string, &resvar) != NULL) {
			var = (char *)resvar.val;
		} else {
			var = val_list[n];
		}
		n++;
		string.val = (unsigned char *)val_list[n];
		string.len = len_list[n];
		if (convd != NULL && mbfl_buffer_converter_feed_result(convd, &string, &resval) != NULL) {
			val = (char *)resval.val;
			val_len = resval.len;
		} else {
			val = val_list[n];
			val_len = len_list[n];
		}
		n++;
		/* we need val to be emalloc()ed */
		val = estrndup(val, val_len);
		if (sapi_module.input_filter(info->data_type, var, &val, val_len, &new_val_len)) {
			/* add variable to symbol table */
			php_register_variable_safe(var, val, new_val_len, array_ptr);
		}
		efree(val);

		if (convd != NULL){
			mbfl_string_clear(&resvar);
			mbfl_string_clear(&resval);
		}
	}

out:
	if (convd != NULL) {
		MBSTRG(illegalchars) += mbfl_buffer_illegalchars(convd);
		mbfl_buffer_converter_delete(convd);
	}
	if (val_list != NULL) {
		efree((void *)val_list);
	}
	if (len_list != NULL) {
		efree((void *)len_list);
	}

	return from_encoding;
}
Пример #22
0
static zend_string *cli_get_prompt(char *block, char prompt) /* {{{ */
{
	smart_str retval = {0};
	char *prompt_spec = CLIR_G(prompt) ? CLIR_G(prompt) : DEFAULT_PROMPT;

	do {
		if (*prompt_spec == '\\') {
			switch (prompt_spec[1]) {
			case '\\':
				smart_str_appendc(&retval, '\\');
				prompt_spec++;
				break;
			case 'n':
				smart_str_appendc(&retval, '\n');
				prompt_spec++;
				break;
			case 't':
				smart_str_appendc(&retval, '\t');
				prompt_spec++;
				break;
			case 'e':
				smart_str_appendc(&retval, '\033');
				prompt_spec++;
				break;


			case 'v':
				smart_str_appends(&retval, PHP_VERSION);
				prompt_spec++;
				break;
			case 'b':
				smart_str_appends(&retval, block);
				prompt_spec++;
				break;
			case '>':
				smart_str_appendc(&retval, prompt);
				prompt_spec++;
				break;
			case '`':
				smart_str_appendc(&retval, '`');
				prompt_spec++;
				break;
			default:
				smart_str_appendc(&retval, '\\');
				break;
			}
		} else if (*prompt_spec == '`') {
			char *prompt_end = strstr(prompt_spec + 1, "`");
			char *code;

			if (prompt_end) {
				code = estrndup(prompt_spec + 1, prompt_end - prompt_spec - 1);

				CLIR_G(prompt_str) = &retval;
				zend_try {
					zend_eval_stringl(code, prompt_end - prompt_spec - 1, NULL, "php prompt code");
				} zend_end_try();
				CLIR_G(prompt_str) = NULL;
				efree(code);
				prompt_spec = prompt_end;
			}
		} else {
			smart_str_appendc(&retval, *prompt_spec);
		}
	} while (++prompt_spec && *prompt_spec);
Пример #23
0
static php_stream_filter_status_t php_bz2_decompress_filter(
	php_stream *stream,
	php_stream_filter *thisfilter,
	php_stream_bucket_brigade *buckets_in,
	php_stream_bucket_brigade *buckets_out,
	size_t *bytes_consumed,
	int flags
	TSRMLS_DC)
{
	php_bz2_filter_data *data;
	php_stream_bucket *bucket;
	size_t consumed = 0;
	int status;
	php_stream_filter_status_t exit_status = PSFS_FEED_ME;
	bz_stream *streamp;

	if (!Z_PTR(thisfilter->abstract)) {
		/* Should never happen */
		return PSFS_ERR_FATAL;
	}

	data = (php_bz2_filter_data *)Z_PTR(thisfilter->abstract);
	streamp = &(data->strm);

	while (buckets_in->head) {
		size_t bin = 0, desired;

		bucket = php_stream_bucket_make_writeable(buckets_in->head TSRMLS_CC);
		while (bin < bucket->buflen) {
			if (data->status == PHP_BZ2_UNITIALIZED) {
				status = BZ2_bzDecompressInit(streamp, 0, data->small_footprint);

				if (BZ_OK != status) {
					php_stream_bucket_delref(bucket TSRMLS_CC);
					return PSFS_ERR_FATAL;
				}

				data->status = PHP_BZ2_RUNNING;
			}

			if (data->status != PHP_BZ2_RUNNING) {
				consumed += bucket->buflen;
				break;
			}

			desired = bucket->buflen - bin;
			if (desired > data->inbuf_len) {
				desired = data->inbuf_len;
			}
			memcpy(data->strm.next_in, bucket->buf + bin, desired);
			data->strm.avail_in = desired;

			status = BZ2_bzDecompress(&(data->strm));

			if (status == BZ_STREAM_END) {
				BZ2_bzDecompressEnd(&(data->strm));
				if (data->expect_concatenated) {
					data->status = PHP_BZ2_UNITIALIZED;
				} else {
					data->status = PHP_BZ2_FINISHED;
				}
			} else if (status != BZ_OK) {
				/* Something bad happened */
				php_stream_bucket_delref(bucket TSRMLS_CC);
				return PSFS_ERR_FATAL;
			}
			desired -= data->strm.avail_in; /* desired becomes what we consumed this round through */
			data->strm.next_in = data->inbuf;
			data->strm.avail_in = 0;
			consumed += desired;
			bin += desired;

			if (data->strm.avail_out < data->outbuf_len) {
				php_stream_bucket *out_bucket;
				size_t bucketlen = data->outbuf_len - data->strm.avail_out;
				out_bucket = php_stream_bucket_new(stream, estrndup(data->outbuf, bucketlen), bucketlen, 1, 0 TSRMLS_CC);
				php_stream_bucket_append(buckets_out, out_bucket TSRMLS_CC);
				data->strm.avail_out = data->outbuf_len;
				data->strm.next_out = data->outbuf;
				exit_status = PSFS_PASS_ON;
			} else if (status == BZ_STREAM_END && data->strm.avail_out >= data->outbuf_len) {
				/* no more data to decompress, and nothing was spat out */
				php_stream_bucket_delref(bucket TSRMLS_CC);
				return PSFS_PASS_ON;
			}
		}

		php_stream_bucket_delref(bucket TSRMLS_CC);
	}

	if ((data->status == PHP_BZ2_RUNNING) && (flags & PSFS_FLAG_FLUSH_CLOSE)) {
		/* Spit it out! */
		status = BZ_OK;
		while (status == BZ_OK) {
			status = BZ2_bzDecompress(&(data->strm));
			if (data->strm.avail_out < data->outbuf_len) {
				size_t bucketlen = data->outbuf_len - data->strm.avail_out;

				bucket = php_stream_bucket_new(stream, estrndup(data->outbuf, bucketlen), bucketlen, 1, 0 TSRMLS_CC);
				php_stream_bucket_append(buckets_out, bucket TSRMLS_CC);
				data->strm.avail_out = data->outbuf_len;
				data->strm.next_out = data->outbuf;
				exit_status = PSFS_PASS_ON;
			} else if (status == BZ_OK) {
				break;
			}
		}
	}

	if (bytes_consumed) {
		*bytes_consumed = consumed;
	}

	return exit_status;
}
Пример #24
0
/* {{{ mysqlnd_res_meta::set_mode */
static void
MYSQLND_METHOD(mysqlnd_debug, set_mode)(MYSQLND_DEBUG * self, const char * const mode)
{
	unsigned int mode_len = strlen(mode), i;
	enum mysqlnd_debug_parser_state state = PARSER_WAIT_MODIFIER;

	self->flags = 0;
	self->nest_level_limit = 0;
	if (self->file_name && self->file_name != mysqlnd_debug_default_trace_file) {
		efree(self->file_name);
		self->file_name = NULL;
	}
	if (zend_hash_num_elements(&self->not_filtered_functions)) {
		zend_hash_destroy(&self->not_filtered_functions);
		zend_hash_init(&self->not_filtered_functions, 0, NULL, NULL, 0);
	}

	for (i = 0; i < mode_len; i++) {
		switch (mode[i]) {
			case 'O':
			case 'A':
				self->flags |= MYSQLND_DEBUG_FLUSH;
			case 'a':
			case 'o':
				if (mode[i] == 'a' || mode[i] == 'A') {
					self->flags |= MYSQLND_DEBUG_APPEND;
				}
				if (i + 1 < mode_len && mode[i+1] == ',') {
					unsigned int j = i + 2;
					while (j < mode_len) {
						if (mode[j] == ':') {
							break;
						}
						j++;
					}
					if (j > i + 2) {
						self->file_name = estrndup(mode + i + 2, j - i - 2);
					}
					i = j;
				} else {
					if (!self->file_name)
						self->file_name = (char *) mysqlnd_debug_default_trace_file;
				}
				state = PARSER_WAIT_COLON;
				break;
			case ':':
#if 0
				if (state != PARSER_WAIT_COLON) {
					php_error_docref(NULL TSRMLS_CC, E_WARNING, "Consecutive semicolons at position %u", i);
				}
#endif
				state = PARSER_WAIT_MODIFIER;
				break;
			case 'f': /* limit output to these functions */
				if (i + 1 < mode_len && mode[i+1] == ',') {
					unsigned int j = i + 2;
					i++;
					while (j < mode_len) {
						if (mode[j] == ':') {
							/* function names with :: */
							if ((j + 1 < mode_len) && mode[j+1] == ':') {
								j += 2;
								continue;
							}
						}
						if (mode[j] == ',' || mode[j] == ':') {
							if (j > i + 2) {
								char func_name[1024];
								unsigned int func_name_len = MIN(sizeof(func_name) - 1, j - i - 1);
								memcpy(func_name, mode + i + 1, func_name_len);
								func_name[func_name_len] = '\0'; 

								zend_hash_add_empty_element(&self->not_filtered_functions,
															func_name, func_name_len + 1);
								i = j;
							}
							if (mode[j] == ':') {
								break;
							}
						}
						j++;
					}
					i = j;
				} else {
#if 0
					php_error_docref(NULL TSRMLS_CC, E_WARNING,
									 "Expected list of functions for '%c' found none", mode[i]);				
#endif
				}
				state = PARSER_WAIT_COLON;
				break;
			case 'D':
			case 'd':
			case 'g':
			case 'p':
				/* unsupported */
				if ((i + 1) < mode_len && mode[i+1] == ',') {
					i+= 2;
					while (i < mode_len) {
						if (mode[i] == ':') {
							break;
						}
						i++;
					}
				}
				state = PARSER_WAIT_COLON;
				break;
			case 'F':
				self->flags |= MYSQLND_DEBUG_DUMP_FILE;
				state = PARSER_WAIT_COLON;
				break;
			case 'i':
				self->flags |= MYSQLND_DEBUG_DUMP_PID;
				state = PARSER_WAIT_COLON;
				break;
			case 'L':
				self->flags |= MYSQLND_DEBUG_DUMP_LINE;
				state = PARSER_WAIT_COLON;
				break;
			case 'n':
				self->flags |= MYSQLND_DEBUG_DUMP_LEVEL;
				state = PARSER_WAIT_COLON;
				break;
			case 't':
				if (mode[i+1] == ',') {
					unsigned int j = i + 2;
					while (j < mode_len) {
						if (mode[j] == ':') {
							break;
						}
						j++;
					}
					if (j > i + 2) {
						char *value_str = estrndup(mode + i + 2, j - i - 2);
						self->nest_level_limit = atoi(value_str);
						efree(value_str);
					}
					i = j;
				} else {
					self->nest_level_limit = 200; /* default value for FF DBUG */
				}
				self->flags |= MYSQLND_DEBUG_DUMP_TRACE;
				state = PARSER_WAIT_COLON;
				break;
			case 'T':
				self->flags |= MYSQLND_DEBUG_DUMP_TIME;
				state = PARSER_WAIT_COLON;
				break;
			case 'N':
			case 'P':
			case 'r':
			case 'S':
				state = PARSER_WAIT_COLON;
				break;
			case 'm': /* mysqlnd extension - trace memory functions */
				self->flags |= MYSQLND_DEBUG_TRACE_MEMORY_CALLS;
				state = PARSER_WAIT_COLON;
				break;
			default:
				if (state == PARSER_WAIT_MODIFIER) {
#if 0
					php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unrecognized format '%c'", mode[i]);
#endif
					if (i+1 < mode_len && mode[i+1] == ',') {
						i+= 2;
						while (i < mode_len) {
							if (mode[i] == ':') {
								break;
							}
							i++;
						}
					}
					state = PARSER_WAIT_COLON;
				} else if (state == PARSER_WAIT_COLON) {
#if 0
					php_error_docref(NULL TSRMLS_CC, E_WARNING, "Colon expected, '%c' found", mode[i]);				
#endif
				}
				break;
		}
	}
}
Пример #25
0
/* {{{ expand_filepath_use_realpath
 */
PHPAPI char *expand_filepath_with_mode(const char *filepath, char *real_path, const char *relative_to, size_t relative_to_len, int realpath_mode)
{
	cwd_state new_state;
	char cwd[MAXPATHLEN];
	int copy_len;
	int path_len;

	if (!filepath[0]) {
		return NULL;
	}

	path_len = (int)strlen(filepath);

	if (IS_ABSOLUTE_PATH(filepath, path_len)) {
		cwd[0] = '\0';
	} else {
		const char *iam = SG(request_info).path_translated;
		const char *result;
		if (relative_to) {
			if (relative_to_len > MAXPATHLEN-1U) {
				return NULL;
			}
			result = relative_to;
			memcpy(cwd, relative_to, relative_to_len+1U);
		} else {
			result = VCWD_GETCWD(cwd, MAXPATHLEN);
		}

		if (!result && (iam != filepath)) {
			int fdtest = -1;

			fdtest = VCWD_OPEN(filepath, O_RDONLY);
			if (fdtest != -1) {
				/* return a relative file path if for any reason
				 * we cannot cannot getcwd() and the requested,
				 * relatively referenced file is accessible */
				copy_len = path_len > MAXPATHLEN - 1 ? MAXPATHLEN - 1 : path_len;
				if (real_path) {
					memcpy(real_path, filepath, copy_len);
					real_path[copy_len] = '\0';
				} else {
					real_path = estrndup(filepath, copy_len);
				}
				close(fdtest);
				return real_path;
			} else {
				cwd[0] = '\0';
			}
		} else if (!result) {
			cwd[0] = '\0';
		}
	}

	new_state.cwd = estrdup(cwd);
	new_state.cwd_length = (int)strlen(cwd);

	if (virtual_file_ex(&new_state, filepath, NULL, realpath_mode)) {
		efree(new_state.cwd);
		return NULL;
	}

	if (real_path) {
		copy_len = new_state.cwd_length > MAXPATHLEN - 1 ? MAXPATHLEN - 1 : new_state.cwd_length;
		memcpy(real_path, new_state.cwd, copy_len);
		real_path[copy_len] = '\0';
	} else {
		real_path = estrndup(new_state.cwd, new_state.cwd_length);
	}
	efree(new_state.cwd);

	return real_path;
}
Пример #26
0
int php_var_unserialize2(UNSERIALIZE_PARAMETER)
{
	const unsigned char *cursor, *limit, *marker, *start;
	zval **rval_ref;

	limit = max;
	cursor = *p;
	
	if (YYCURSOR >= YYLIMIT) {
		return 0;
	}
	
	if (var_hash && cursor[0] != 'R') {
		var_push(var_hash, rval);
	}

	start = cursor;

	
	


{
	YYCTYPE yych;
	static const unsigned char yybm[] = {
		  0,   0,   0,   0,   0,   0,   0,   0, 
		  0,   0,   0,   0,   0,   0,   0,   0, 
		  0,   0,   0,   0,   0,   0,   0,   0, 
		  0,   0,   0,   0,   0,   0,   0,   0, 
		  0,   0,   0,   0,   0,   0,   0,   0, 
		  0,   0,   0,   0,   0,   0,   0,   0, 
		128, 128, 128, 128, 128, 128, 128, 128, 
		128, 128,   0,   0,   0,   0,   0,   0, 
		  0,   0,   0,   0,   0,   0,   0,   0, 
		  0,   0,   0,   0,   0,   0,   0,   0, 
		  0,   0,   0,   0,   0,   0,   0,   0, 
		  0,   0,   0,   0,   0,   0,   0,   0, 
		  0,   0,   0,   0,   0,   0,   0,   0, 
		  0,   0,   0,   0,   0,   0,   0,   0, 
		  0,   0,   0,   0,   0,   0,   0,   0, 
		  0,   0,   0,   0,   0,   0,   0,   0, 
		  0,   0,   0,   0,   0,   0,   0,   0, 
		  0,   0,   0,   0,   0,   0,   0,   0, 
		  0,   0,   0,   0,   0,   0,   0,   0, 
		  0,   0,   0,   0,   0,   0,   0,   0, 
		  0,   0,   0,   0,   0,   0,   0,   0, 
		  0,   0,   0,   0,   0,   0,   0,   0, 
		  0,   0,   0,   0,   0,   0,   0,   0, 
		  0,   0,   0,   0,   0,   0,   0,   0, 
		  0,   0,   0,   0,   0,   0,   0,   0, 
		  0,   0,   0,   0,   0,   0,   0,   0, 
		  0,   0,   0,   0,   0,   0,   0,   0, 
		  0,   0,   0,   0,   0,   0,   0,   0, 
		  0,   0,   0,   0,   0,   0,   0,   0, 
		  0,   0,   0,   0,   0,   0,   0,   0, 
		  0,   0,   0,   0,   0,   0,   0,   0, 
		  0,   0,   0,   0,   0,   0,   0,   0, 
	};

	if ((YYLIMIT - YYCURSOR) < 7) YYFILL(7);
	yych = *YYCURSOR;
	switch (yych) {
	case 'C':
	case 'O':	goto yy13;
	case 'N':	goto yy5;
	case 'R':	goto yy2;
	case 'S':	goto yy10;
	case 'a':	goto yy11;
	case 'b':	goto yy6;
	case 'd':	goto yy8;
	case 'i':	goto yy7;
	case 'o':	goto yy12;
	case 'r':	goto yy4;
	case 's':	goto yy9;
	case '}':	goto yy14;
	default:	goto yy16;
	}
yy2:
	yych = *(YYMARKER = ++YYCURSOR);
	if (yych == ':') goto yy95;
yy3:

	{ return 0; }

yy4:
	yych = *(YYMARKER = ++YYCURSOR);
	if (yych == ':') goto yy89;
	goto yy3;
yy5:
	yych = *++YYCURSOR;
	if (yych == ';') goto yy87;
	goto yy3;
yy6:
	yych = *(YYMARKER = ++YYCURSOR);
	if (yych == ':') goto yy83;
	goto yy3;
yy7:
	yych = *(YYMARKER = ++YYCURSOR);
	if (yych == ':') goto yy77;
	goto yy3;
yy8:
	yych = *(YYMARKER = ++YYCURSOR);
	if (yych == ':') goto yy53;
	goto yy3;
yy9:
	yych = *(YYMARKER = ++YYCURSOR);
	if (yych == ':') goto yy46;
	goto yy3;
yy10:
	yych = *(YYMARKER = ++YYCURSOR);
	if (yych == ':') goto yy39;
	goto yy3;
yy11:
	yych = *(YYMARKER = ++YYCURSOR);
	if (yych == ':') goto yy32;
	goto yy3;
yy12:
	yych = *(YYMARKER = ++YYCURSOR);
	if (yych == ':') goto yy25;
	goto yy3;
yy13:
	yych = *(YYMARKER = ++YYCURSOR);
	if (yych == ':') goto yy17;
	goto yy3;
yy14:
	++YYCURSOR;

	{
	/* this is the case where we have less data than planned */
	php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Unexpected end of serialized data");
	return 0; /* not sure if it should be 0 or 1 here? */
}

yy16:
	yych = *++YYCURSOR;
	goto yy3;
yy17:
	yych = *++YYCURSOR;
	if (yybm[0+yych] & 128) {
		goto yy20;
	}
	if (yych == '+') goto yy19;
yy18:
	YYCURSOR = YYMARKER;
	goto yy3;
yy19:
	yych = *++YYCURSOR;
	if (yybm[0+yych] & 128) {
		goto yy20;
	}
	goto yy18;
yy20:
	++YYCURSOR;
	if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
	yych = *YYCURSOR;
	if (yybm[0+yych] & 128) {
		goto yy20;
	}
	if (yych != ':') goto yy18;
	yych = *++YYCURSOR;
	if (yych != '"') goto yy18;
	++YYCURSOR;

	{
	size_t len, len2, len3, maxlen;
	long elements;
	char *class_name;
	zend_class_entry *ce;
	zend_class_entry **pce;
	int incomplete_class = 0;

	int custom_object = 0;

	zval *user_func;
	zval *retval_ptr;
	zval **args[1];
	zval *arg_func_name;

	if (*start == 'C') {
		custom_object = 1;
	}
	
	INIT_PZVAL(*rval);
	len2 = len = parse_uiv(start + 2);
	maxlen = max - YYCURSOR;
	if (maxlen < len || len == 0) {
		*p = start + 2;
		return 0;
	}

	class_name = (char*)YYCURSOR;

	YYCURSOR += len;

	if (*(YYCURSOR) != '"') {
		*p = YYCURSOR;
		return 0;
	}
	if (*(YYCURSOR+1) != ':') {
		*p = YYCURSOR+1;
		return 0;
	}

	len3 = strspn(class_name, "0123456789_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ\177\200\201\202\203\204\205\206\207\210\211\212\213\214\215\216\217\220\221\222\223\224\225\226\227\230\231\232\233\234\235\236\237\240\241\242\243\244\245\246\247\250\251\252\253\254\255\256\257\260\261\262\263\264\265\266\267\270\271\272\273\274\275\276\277\300\301\302\303\304\305\306\307\310\311\312\313\314\315\316\317\320\321\322\323\324\325\326\327\330\331\332\333\334\335\336\337\340\341\342\343\344\345\346\347\350\351\352\353\354\355\356\357\360\361\362\363\364\365\366\367\370\371\372\373\374\375\376\377\\");
	if (len3 != len)
	{
		*p = YYCURSOR + len3 - len;
		return 0;
	}

	class_name = estrndup(class_name, len);

	do {
		/* Try to find class directly */
		UNSERIALIZE2_G(serialize_lock)++;
		if (zend_lookup_class(class_name, len2, &pce TSRMLS_CC) == SUCCESS) {
			UNSERIALIZE2_G(serialize_lock)--;
			if (EG(exception)) {
				efree(class_name);
				return 0;
			}
			ce = *pce;
			break;
		}
		UNSERIALIZE2_G(serialize_lock)--;

		if (EG(exception)) {
			efree(class_name);
			return 0;
		}
		
		/* Check for unserialize callback */
		if ((PG(unserialize_callback_func) == NULL) || (PG(unserialize_callback_func)[0] == '\0')) {
			incomplete_class = 1;
			ce = PHP_IC_ENTRY;
			break;
		}
		
		/* Call unserialize callback */
		MAKE_STD_ZVAL(user_func);
		ZVAL_STRING(user_func, PG(unserialize_callback_func), 1);
		args[0] = &arg_func_name;
		MAKE_STD_ZVAL(arg_func_name);
		ZVAL_STRING(arg_func_name, class_name, 1);
		UNSERIALIZE2_G(serialize_lock)++;
		if (call_user_function_ex(CG(function_table), NULL, user_func, &retval_ptr, 1, args, 0, NULL TSRMLS_CC) != SUCCESS) {
			UNSERIALIZE2_G(serialize_lock)--;
			if (EG(exception)) {
				efree(class_name);
				zval_ptr_dtor(&user_func);
				zval_ptr_dtor(&arg_func_name);
				return 0;
			}
			php_error_docref(NULL TSRMLS_CC, E_WARNING, "defined (%s) but not found", user_func->value.str.val);
			incomplete_class = 1;
			ce = PHP_IC_ENTRY;
			zval_ptr_dtor(&user_func);
			zval_ptr_dtor(&arg_func_name);
			break;
		}
		UNSERIALIZE2_G(serialize_lock)--;
		if (retval_ptr) {
			zval_ptr_dtor(&retval_ptr);
		}
		if (EG(exception)) {
			efree(class_name);
			zval_ptr_dtor(&user_func);
			zval_ptr_dtor(&arg_func_name);
			return 0;
		}
		
		/* The callback function may have defined the class */
		if (zend_lookup_class(class_name, len2, &pce TSRMLS_CC) == SUCCESS) {
			ce = *pce;
		} else {
			php_error_docref(NULL TSRMLS_CC, E_WARNING, "Function %s() hasn't defined the class it was called for", user_func->value.str.val);
			incomplete_class = 1;
			ce = PHP_IC_ENTRY;
		}

		zval_ptr_dtor(&user_func);
		zval_ptr_dtor(&arg_func_name);
		break;
	} while (1);

	*p = YYCURSOR;

	if (custom_object) {
		int ret;

		ret = object_custom(UNSERIALIZE_PASSTHRU, ce);

		if (ret && incomplete_class) {
			php_store_class_name(*rval, class_name, len2);
		}
		efree(class_name);
		return ret;
	}
	
	elements = object_common1(UNSERIALIZE_PASSTHRU, ce);

	if (incomplete_class) {
		php_store_class_name(*rval, class_name, len2);
	}
	efree(class_name);

	return object_common2(UNSERIALIZE_PASSTHRU, elements);
}

yy25:
	yych = *++YYCURSOR;
	if (yych <= ',') {
		if (yych != '+') goto yy18;
	} else {
		if (yych <= '-') goto yy26;
		if (yych <= '/') goto yy18;
		if (yych <= '9') goto yy27;
		goto yy18;
	}
yy26:
	yych = *++YYCURSOR;
	if (yych <= '/') goto yy18;
	if (yych >= ':') goto yy18;
yy27:
	++YYCURSOR;
	if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
	yych = *YYCURSOR;
	if (yych <= '/') goto yy18;
	if (yych <= '9') goto yy27;
	if (yych >= ';') goto yy18;
	yych = *++YYCURSOR;
	if (yych != '"') goto yy18;
	++YYCURSOR;

	{

	INIT_PZVAL(*rval);
	
	return object_common2(UNSERIALIZE_PASSTHRU,
			object_common1(UNSERIALIZE_PASSTHRU, ZEND_STANDARD_CLASS_DEF_PTR));
}

yy32:
	yych = *++YYCURSOR;
	if (yych == '+') goto yy33;
	if (yych <= '/') goto yy18;
	if (yych <= '9') goto yy34;
	goto yy18;
yy33:
	yych = *++YYCURSOR;
	if (yych <= '/') goto yy18;
	if (yych >= ':') goto yy18;
yy34:
	++YYCURSOR;
	if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
	yych = *YYCURSOR;
	if (yych <= '/') goto yy18;
	if (yych <= '9') goto yy34;
	if (yych >= ';') goto yy18;
	yych = *++YYCURSOR;
	if (yych != '{') goto yy18;
	++YYCURSOR;

	{
	long elements = parse_iv(start + 2);
	/* use iv() not uiv() in order to check data range */
	*p = YYCURSOR;

	if (elements < 0) {
		return 0;
	}

	INIT_PZVAL(*rval);

	array_init_size(*rval, elements);

	if (!process_nested_data(UNSERIALIZE_PASSTHRU, Z_ARRVAL_PP(rval), elements, 0)) {
		return 0;
	}

	return finish_nested_data(UNSERIALIZE_PASSTHRU);
}

yy39:
	yych = *++YYCURSOR;
	if (yych == '+') goto yy40;
	if (yych <= '/') goto yy18;
	if (yych <= '9') goto yy41;
	goto yy18;
yy40:
	yych = *++YYCURSOR;
	if (yych <= '/') goto yy18;
	if (yych >= ':') goto yy18;
yy41:
	++YYCURSOR;
	if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
	yych = *YYCURSOR;
	if (yych <= '/') goto yy18;
	if (yych <= '9') goto yy41;
	if (yych >= ';') goto yy18;
	yych = *++YYCURSOR;
	if (yych != '"') goto yy18;
	++YYCURSOR;

	{
	size_t len, maxlen;
	char *str;

	len = parse_uiv(start + 2);
	maxlen = max - YYCURSOR;
	if (maxlen < len) {
		*p = start + 2;
		return 0;
	}

	if ((str = unserialize_str(&YYCURSOR, &len, maxlen)) == NULL) {
		return 0;
	}

	if (*(YYCURSOR) != '"') {
		efree(str);
		*p = YYCURSOR;
		return 0;
	}

	YYCURSOR += 2;
	*p = YYCURSOR;

	INIT_PZVAL(*rval);
	ZVAL_STRINGL(*rval, str, len, 0);
	return 1;
}

yy46:
	yych = *++YYCURSOR;
	if (yych == '+') goto yy47;
	if (yych <= '/') goto yy18;
	if (yych <= '9') goto yy48;
	goto yy18;
yy47:
	yych = *++YYCURSOR;
	if (yych <= '/') goto yy18;
	if (yych >= ':') goto yy18;
yy48:
	++YYCURSOR;
	if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
	yych = *YYCURSOR;
	if (yych <= '/') goto yy18;
	if (yych <= '9') goto yy48;
	if (yych >= ';') goto yy18;
	yych = *++YYCURSOR;
	if (yych != '"') goto yy18;
	++YYCURSOR;

	{
	size_t len, maxlen;
	char *str;

	len = parse_uiv(start + 2);
	maxlen = max - YYCURSOR;
	if (maxlen < len) {
		*p = start + 2;
		return 0;
	}

	str = (char*)YYCURSOR;

	YYCURSOR += len;

	if (*(YYCURSOR) != '"') {
		*p = YYCURSOR;
		return 0;
	}

	YYCURSOR += 2;
	*p = YYCURSOR;

	INIT_PZVAL(*rval);
	ZVAL_STRINGL(*rval, str, len, 1);
	return 1;
}

yy53:
	yych = *++YYCURSOR;
	if (yych <= '/') {
		if (yych <= ',') {
			if (yych == '+') goto yy57;
			goto yy18;
		} else {
			if (yych <= '-') goto yy55;
			if (yych <= '.') goto yy60;
			goto yy18;
		}
	} else {
		if (yych <= 'I') {
			if (yych <= '9') goto yy58;
			if (yych <= 'H') goto yy18;
			goto yy56;
		} else {
			if (yych != 'N') goto yy18;
		}
	}
	yych = *++YYCURSOR;
	if (yych == 'A') goto yy76;
	goto yy18;
yy55:
	yych = *++YYCURSOR;
	if (yych <= '/') {
		if (yych == '.') goto yy60;
		goto yy18;
	} else {
		if (yych <= '9') goto yy58;
		if (yych != 'I') goto yy18;
	}
yy56:
	yych = *++YYCURSOR;
	if (yych == 'N') goto yy72;
	goto yy18;
yy57:
	yych = *++YYCURSOR;
	if (yych == '.') goto yy60;
	if (yych <= '/') goto yy18;
	if (yych >= ':') goto yy18;
yy58:
	++YYCURSOR;
	if ((YYLIMIT - YYCURSOR) < 4) YYFILL(4);
	yych = *YYCURSOR;
	if (yych <= ':') {
		if (yych <= '.') {
			if (yych <= '-') goto yy18;
			goto yy70;
		} else {
			if (yych <= '/') goto yy18;
			if (yych <= '9') goto yy58;
			goto yy18;
		}
	} else {
		if (yych <= 'E') {
			if (yych <= ';') goto yy63;
			if (yych <= 'D') goto yy18;
			goto yy65;
		} else {
			if (yych == 'e') goto yy65;
			goto yy18;
		}
	}
yy60:
	yych = *++YYCURSOR;
	if (yych <= '/') goto yy18;
	if (yych >= ':') goto yy18;
yy61:
	++YYCURSOR;
	if ((YYLIMIT - YYCURSOR) < 4) YYFILL(4);
	yych = *YYCURSOR;
	if (yych <= ';') {
		if (yych <= '/') goto yy18;
		if (yych <= '9') goto yy61;
		if (yych <= ':') goto yy18;
	} else {
		if (yych <= 'E') {
			if (yych <= 'D') goto yy18;
			goto yy65;
		} else {
			if (yych == 'e') goto yy65;
			goto yy18;
		}
	}
yy63:
	++YYCURSOR;

	{
#if SIZEOF_LONG == 4
use_double:
#endif
	*p = YYCURSOR;
	INIT_PZVAL(*rval);
	ZVAL_DOUBLE(*rval, zend_strtod((const char *)start + 2, NULL));
	return 1;
}

yy65:
	yych = *++YYCURSOR;
	if (yych <= ',') {
		if (yych != '+') goto yy18;
	} else {
		if (yych <= '-') goto yy66;
		if (yych <= '/') goto yy18;
		if (yych <= '9') goto yy67;
		goto yy18;
	}
yy66:
	yych = *++YYCURSOR;
	if (yych <= ',') {
		if (yych == '+') goto yy69;
		goto yy18;
	} else {
		if (yych <= '-') goto yy69;
		if (yych <= '/') goto yy18;
		if (yych >= ':') goto yy18;
	}
yy67:
	++YYCURSOR;
	if (YYLIMIT <= YYCURSOR) YYFILL(1);
	yych = *YYCURSOR;
	if (yych <= '/') goto yy18;
	if (yych <= '9') goto yy67;
	if (yych == ';') goto yy63;
	goto yy18;
yy69:
	yych = *++YYCURSOR;
	if (yych <= '/') goto yy18;
	if (yych <= '9') goto yy67;
	goto yy18;
yy70:
	++YYCURSOR;
	if ((YYLIMIT - YYCURSOR) < 4) YYFILL(4);
	yych = *YYCURSOR;
	if (yych <= ';') {
		if (yych <= '/') goto yy18;
		if (yych <= '9') goto yy70;
		if (yych <= ':') goto yy18;
		goto yy63;
	} else {
		if (yych <= 'E') {
			if (yych <= 'D') goto yy18;
			goto yy65;
		} else {
			if (yych == 'e') goto yy65;
			goto yy18;
		}
	}
yy72:
	yych = *++YYCURSOR;
	if (yych != 'F') goto yy18;
yy73:
	yych = *++YYCURSOR;
	if (yych != ';') goto yy18;
	++YYCURSOR;

	{
	*p = YYCURSOR;
	INIT_PZVAL(*rval);

	if (!strncmp(start + 2, "NAN", 3)) {
		ZVAL_DOUBLE(*rval, php_get_nan());
	} else if (!strncmp(start + 2, "INF", 3)) {
		ZVAL_DOUBLE(*rval, php_get_inf());
	} else if (!strncmp(start + 2, "-INF", 4)) {
		ZVAL_DOUBLE(*rval, -php_get_inf());
	}

	return 1;
}

yy76:
	yych = *++YYCURSOR;
	if (yych == 'N') goto yy73;
	goto yy18;
yy77:
	yych = *++YYCURSOR;
	if (yych <= ',') {
		if (yych != '+') goto yy18;
	} else {
		if (yych <= '-') goto yy78;
		if (yych <= '/') goto yy18;
		if (yych <= '9') goto yy79;
		goto yy18;
	}
yy78:
	yych = *++YYCURSOR;
	if (yych <= '/') goto yy18;
	if (yych >= ':') goto yy18;
yy79:
	++YYCURSOR;
	if (YYLIMIT <= YYCURSOR) YYFILL(1);
	yych = *YYCURSOR;
	if (yych <= '/') goto yy18;
	if (yych <= '9') goto yy79;
	if (yych != ';') goto yy18;
	++YYCURSOR;

	{
#if SIZEOF_LONG == 4
	int digits = YYCURSOR - start - 3;

	if (start[2] == '-' || start[2] == '+') {
		digits--;
	}

	/* Use double for large long values that were serialized on a 64-bit system */
	if (digits >= MAX_LENGTH_OF_LONG - 1) {
		if (digits == MAX_LENGTH_OF_LONG - 1) {
			int cmp = strncmp(YYCURSOR - MAX_LENGTH_OF_LONG, long_min_digits, MAX_LENGTH_OF_LONG - 1);

			if (!(cmp < 0 || (cmp == 0 && start[2] == '-'))) {
				goto use_double;
			}
		} else {
			goto use_double;
		}
	}
#endif
	*p = YYCURSOR;
	INIT_PZVAL(*rval);
	ZVAL_LONG(*rval, parse_iv(start + 2));
	return 1;
}

yy83:
	yych = *++YYCURSOR;
	if (yych <= '/') goto yy18;
	if (yych >= '2') goto yy18;
	yych = *++YYCURSOR;
	if (yych != ';') goto yy18;
	++YYCURSOR;

	{
	*p = YYCURSOR;
	INIT_PZVAL(*rval);
	ZVAL_BOOL(*rval, parse_iv(start + 2));
	return 1;
}

yy87:
	++YYCURSOR;

	{
	*p = YYCURSOR;
	INIT_PZVAL(*rval);
	ZVAL_NULL(*rval);
	return 1;
}

yy89:
	yych = *++YYCURSOR;
	if (yych <= ',') {
		if (yych != '+') goto yy18;
	} else {
		if (yych <= '-') goto yy90;
		if (yych <= '/') goto yy18;
		if (yych <= '9') goto yy91;
		goto yy18;
	}
yy90:
	yych = *++YYCURSOR;
	if (yych <= '/') goto yy18;
	if (yych >= ':') goto yy18;
yy91:
	++YYCURSOR;
	if (YYLIMIT <= YYCURSOR) YYFILL(1);
	yych = *YYCURSOR;
	if (yych <= '/') goto yy18;
	if (yych <= '9') goto yy91;
	if (yych != ';') goto yy18;
	++YYCURSOR;

	{
	long id;

 	*p = YYCURSOR;
	if (!var_hash) return 0;

	id = parse_iv(start + 2) - 1;
	if (id == -1 || var_access(var_hash, id, &rval_ref) != SUCCESS) {
		return 0;
	}

	if (*rval == *rval_ref) return 0;

	if (*rval != NULL) {
		var_push_dtor_no_addref(var_hash, rval);
	}
	*rval = *rval_ref;
	Z_ADDREF_PP(rval);
	Z_UNSET_ISREF_PP(rval);
	
	return 1;
}

yy95:
	yych = *++YYCURSOR;
	if (yych <= ',') {
		if (yych != '+') goto yy18;
	} else {
		if (yych <= '-') goto yy96;
		if (yych <= '/') goto yy18;
		if (yych <= '9') goto yy97;
		goto yy18;
	}
yy96:
	yych = *++YYCURSOR;
	if (yych <= '/') goto yy18;
	if (yych >= ':') goto yy18;
yy97:
	++YYCURSOR;
	if (YYLIMIT <= YYCURSOR) YYFILL(1);
	yych = *YYCURSOR;
	if (yych <= '/') goto yy18;
	if (yych <= '9') goto yy97;
	if (yych != ';') goto yy18;
	++YYCURSOR;

	{
	long id;

 	*p = YYCURSOR;
	if (!var_hash) return 0;

	id = parse_iv(start + 2) - 1;
	if (id == -1 || var_access(var_hash, id, &rval_ref) != SUCCESS) {
		return 0;
	}

	if (*rval != NULL) {
		zval_ptr_dtor(rval);
	}
	*rval = *rval_ref;
	Z_ADDREF_PP(rval);
	Z_SET_ISREF_PP(rval);
	
	return 1;
}

}



	return 0;
}
Пример #27
0
/*
caution: the Hebrew format produces non unique result.
for example both: year '5' and year '5000' produce 'ה'.
use the numeric one for calculations. 
 */
static char *heb_number_to_chars(int n, int fl, char **ret)
{
	char *p, old[18], *endofalafim;

	p = endofalafim = old;
/* 
   prevents the option breaking the jewish beliefs, and some other 
   critical resources ;)
 */
	if (n > 9999 || n < 1) {
		*ret = NULL;
		return NULL;
	}	

/* alafim (thousands) case */
	if (n / 1000) {
		*p = alef_bet[n / 1000];
		p++;

		if (CAL_JEWISH_ADD_ALAFIM_GERESH & fl) {
			*p = '\'';
			p++;
		}
		if (CAL_JEWISH_ADD_ALAFIM & fl) {
			strcpy(p, " אלפים ");
			p += 7;
		}

		endofalafim = p;
		n = n % 1000;
	}

/* tav-tav (tav=400) case */
	while (n >= 400) {
		*p = alef_bet[22];
		p++;
		n -= 400;
	}

/* meot (hundreads) case */
	if (n >= 100) {
		*p = alef_bet[18 + n / 100];
		p++;
		n = n % 100;
	}

/* tet-vav & tet-zain case (special case for 15 and 16) */
	if (n == 15 || n == 16) {
		*p = alef_bet[9];
		p++;
		*p = alef_bet[n - 9];
		p++;
	} else {
/* asarot (tens) case */
		if (n >= 10) {
			*p = alef_bet[9 + n / 10];
			p++;
			n = n % 10;
		}

/* yehidot (ones) case */
		if (n > 0) {
			*p = alef_bet[n];
			p++;
		}
	}

	if (CAL_JEWISH_ADD_GERESHAYIM & fl) {
		switch (p - endofalafim) {
		case 0:
			break;
		case 1:
			*p = '\'';
			p++;
			break;
		default:
			*(p) = *(p - 1);
			*(p - 1) = '"';
			p++;
		}
	}

	*p = '\0';
	*ret = estrndup(old, (p - old) + 1);
	p = *ret;
	return p;
}
Пример #28
0
/**
 * @desc 将请求中的参数写入请求的环境变量中
 * @param req
 * @param p
 * @param end
 * @return 
 */
static int fcgi_get_params(fcgi_request *req, unsigned char *p, unsigned char *end)
{
	char buf[128];
	char *tmp = buf;
	size_t buf_size = sizeof(buf);     // 128
	int name_len = 0;
	int val_len = 0;
	uint eff_name_len = 0;
	char *s;
	int ret = 1;
	size_t bytes_consumed;

	while (p < end) {
                // 参数名的长度
		bytes_consumed = fcgi_get_params_len(&name_len, p, end);
		if (!bytes_consumed) {
			/* Malformated request */
			ret = 0;
			break;
		}
		p += bytes_consumed;
                
                // 参数值的长度
		bytes_consumed = fcgi_get_params_len(&val_len, p, end);
		if (!bytes_consumed) {
			/* Malformated request */
			ret = 0;
			break;
		}
		p += bytes_consumed;
		if (name_len > (INT_MAX - val_len) || /* would the addition overflow? */
		    name_len + val_len > end - p) {   /* would we exceed the buffer? */
			/* Malformated request */
			ret = 0;
			break;
		}

		/*
		 * get the effective length of the name in case it's not a valid string
		 * don't do this on the value because it can be binary data
                 * 考虑参数名中填充,这里取出参数名实际长度
		 */
		if (!fcgi_param_get_eff_len(p, p+name_len, &eff_name_len)){
			/* Malicious request */
			ret = 0;
			break;
		}
		if (eff_name_len >= buf_size-1) {  // 127 参数名长度是一个字节,否则是4个字节
			if (eff_name_len > ((uint)-1)-64) {  // 这里的64 估计是对齐用的 (尚未验证)
				ret = 0;
				break;
			}
			buf_size = eff_name_len + 64;
			tmp = (tmp == buf ? emalloc(buf_size): erealloc(tmp, buf_size));
			if (tmp == NULL) {
				ret = 0;
				break;
			}
		}
		memcpy(tmp, p, eff_name_len);                   // 参数名 
		tmp[eff_name_len] = 0;
		s = estrndup((char*)p + name_len, val_len);     // 参数值
		if (s == NULL) {
			ret = 0;
			break;
		}
		zend_hash_update(req->env, tmp, eff_name_len+1, &s, sizeof(char*), NULL);    // 写入环境标量中
		p += name_len + val_len;
	}
	if (tmp != buf && tmp != NULL) {
		efree(tmp);
	}
	return ret;
}
Пример #29
0
int yaf_route_pathinfo_route(yaf_request_t *request, char *req_uri, int req_uri_len TSRMLS_DC) /* {{{ */ {
	zval *params;
	char *module = NULL, *controller = NULL, *action = NULL, *rest = NULL;

	do {
#define strip_slashs(p) while (*p == ' ' || *p == '/') { ++p; }
		char *s, *p;
		char *uri;

		if (req_uri_len == 0
				|| (req_uri_len == 1 && *req_uri == '/')) {
			break;
		}

		uri = req_uri;
		s = p = uri;

		if (req_uri_len) {
			char *q = req_uri + req_uri_len - 1;
			while (q > req_uri && (*q == ' ' || *q == '/')) {
				*q-- = '\0';
			}
		}

		strip_slashs(p);

		if ((s = strstr(p, "/")) != NULL) {
			if (yaf_application_is_module_name(p, s-p TSRMLS_CC)) {
				module = estrndup(p, s - p);
				p  = s + 1;
		        strip_slashs(p);
				if ((s = strstr(p, "/")) != NULL) {
					controller = estrndup(p, s - p);
					p  = s + 1;
				}
			} else {
				controller = estrndup(p, s - p);
				p  = s + 1;
			}
		}

		strip_slashs(p);
		if ((s = strstr(p, "/")) != NULL) {
			action = estrndup(p, s - p);
			p  = s + 1;
		}

		strip_slashs(p);
		if (*p != '\0') {
			do {
				if (!module && !controller && !action) {
					if (yaf_application_is_module_name(p, strlen(p) TSRMLS_CC)) {
						module = estrdup(p);
						break;
					}
				}

				if (!controller) {
					controller = estrdup(p);
					break;
				}

				if (!action) {
					action = estrdup(p);
					break;
				}

				rest = estrdup(p);
			} while (0);
		}

		if (module && controller == NULL) {
			controller = module;
			module = NULL;
		} else if (module && action == NULL) {
			action = controller;
			controller = module;
			module = NULL;
	    } else if (controller && action == NULL ) {
			/* /controller */
			if (YAF_G(action_prefer)) {
				action = controller;
				controller = NULL;
			}
		}
	} while (0);

	if (module != NULL) {
		zend_update_property_string(yaf_request_ce, request, ZEND_STRL(YAF_REQUEST_PROPERTY_NAME_MODULE), module TSRMLS_CC);
		efree(module);
	}
	if (controller != NULL) {
		zend_update_property_string(yaf_request_ce, request, ZEND_STRL(YAF_REQUEST_PROPERTY_NAME_CONTROLLER), controller TSRMLS_CC);
		efree(controller);
	}

	if (action != NULL) {
		zend_update_property_string(yaf_request_ce, request, ZEND_STRL(YAF_REQUEST_PROPERTY_NAME_ACTION), action TSRMLS_CC);
		efree(action);
	}

	if (rest) {
		params = yaf_router_parse_parameters(rest TSRMLS_CC);
		(void)yaf_request_set_params_multi(request, params TSRMLS_CC);
		zval_ptr_dtor(&params);
		efree(rest);
	}

	return 1;
}
Пример #30
0
/* {{{ php_url_parse
 */
PHPAPI php_url *php_url_parse_ex(char const *str, int length)
{
	char port_buf[6];
	php_url *ret = ecalloc(1, sizeof(php_url));
	const char *s, *e, *p, *pp, *ue;
		
	s = str;
	ue = s + length;

	/* parse scheme */
	if ((e = memchr(s, ':', length)) && (e - s)) {
		/* validate scheme */
		p = s;
		while (p < e) {
			/* scheme = 1*[ lowalpha | digit | "+" | "-" | "." ] */
			if (!isalpha(*p) && !isdigit(*p) && *p != '+' && *p != '.' && *p != '-') {
				if (e + 1 < ue) {
					goto parse_port;
				} else {
					goto just_path;
				}
			}
			p++;
		}
	
		if (*(e + 1) == '\0') { /* only scheme is available */
			ret->scheme = estrndup(s, (e - s));
			php_replace_controlchars_ex(ret->scheme, (e - s));
			goto end;
		}

		/* 
		 * certain schemas like mailto: and zlib: may not have any / after them
		 * this check ensures we support those.
		 */
		if (*(e+1) != '/') {
			/* check if the data we get is a port this allows us to 
			 * correctly parse things like a.com:80
			 */
			p = e + 1;
			while (isdigit(*p)) {
				p++;
			}
			
			if ((*p == '\0' || *p == '/') && (p - e) < 7) {
				goto parse_port;
			}
			
			ret->scheme = estrndup(s, (e-s));
			php_replace_controlchars_ex(ret->scheme, (e - s));
			
			length -= ++e - s;
			s = e;
			goto just_path;
		} else {
			ret->scheme = estrndup(s, (e-s));
			php_replace_controlchars_ex(ret->scheme, (e - s));
		
			if (*(e+2) == '/') {
				s = e + 3;
				if (!strncasecmp("file", ret->scheme, sizeof("file"))) {
					if (*(e + 3) == '/') {
						goto nohost;
					}
				}
			} else {
				if (!strncasecmp("file", ret->scheme, sizeof("file"))) {
					s = e + 1;
					goto nohost;
				} else {
					length -= ++e - s;
					s = e;
					goto just_path;
				}	
			}
		}	
	} else if (e) { /* no scheme, look for port */
		parse_port:
		p = e + 1;
		pp = p;
		
		while (pp-p < 6 && isdigit(*pp)) {
			pp++;
		}
		
		if (pp-p < 6 && (*pp == '/' || *pp == '\0')) {
			memcpy(port_buf, p, (pp-p));
			port_buf[pp-p] = '\0';
			ret->port = atoi(port_buf);
		} else {
			goto just_path;
		}
	} else {
		just_path:
		ue = s + length;
		goto nohost;
	}
	
	e = ue;
	
	if (!(p = memchr(s, '/', (ue - s)))) {
		if ((p = memchr(s, '?', (ue - s)))) {
			e = p;
		} else if ((p = memchr(s, '#', (ue - s)))) {
			e = p;
		}
	} else {
		e = p;
	}	

	{
		const char *t = s;
		p = NULL;
		while (e > t && (t = memchr(t, '@', (e-t)))) {
			p = t++;
		}
	}
		
	/* check for login and password */
	if (p) {
		if ((pp = memchr(s, ':', (p-s)))) {
			if ((pp-s) > 0) {
				ret->user = estrndup(s, (pp-s));
				php_replace_controlchars_ex(ret->user, (pp - s));
			}	
		
			pp++;
			if (p-pp > 0) {
				ret->pass = estrndup(pp, (p-pp));
				php_replace_controlchars_ex(ret->pass, (p-pp));
			}	
		} else {
			ret->user = estrndup(s, (p-s));
			php_replace_controlchars_ex(ret->user, (p-s));
		}
		
		s = p + 1;
	}
	
	/* check for port */
	if (*s == '[' && *(e-1) == ']') {
		/* Short circuit portscan
		   we're dealing with an
		   IPv6 embedded address */
		p = s;
	} else {
		/* memchr is a GNU specific extension
		   Emulate for wide compatability */
		for(p = e; *p != ':' && p >= s; p--);
	}

	if (p >= s && *p == ':') {
		if (!ret->port) {
			p++;
			if (e-p > 5) { /* port cannot be longer then 5 characters */
				STR_FREE(ret->scheme);
				STR_FREE(ret->user);
				STR_FREE(ret->pass);
				efree(ret);
				return NULL;
			} else if (e - p > 0) {
				memcpy(port_buf, p, (e-p));
				port_buf[e-p] = '\0';
				ret->port = atoi(port_buf);
			}
			p--;
		}	
	} else {
		p = e;
	}

	/* check if we have a valid host, if we don't reject the string as url */
	if ((p-s) < 1) {
		STR_FREE(ret->scheme);
		STR_FREE(ret->user);
		STR_FREE(ret->pass);
		efree(ret);
		return NULL;
	}
	
	ret->host = estrndup(s, (p-s));
	php_replace_controlchars_ex(ret->host, (p - s));
	
	if (e == ue) {
		return ret;
	}
	
	s = e;
	
	nohost:
	
	if ((p = memchr(s, '?', (ue - s)))) {
		pp = strchr(s, '#');
		
		if (pp && pp < p) {
			p = pp;
			pp = strchr(pp+2, '#');
		}
	
		if (p - s) {
			ret->path = estrndup(s, (p-s));
			php_replace_controlchars_ex(ret->path, (p - s));
		}	
	
		if (pp) {
			if (pp - ++p) { 
				ret->query = estrndup(p, (pp-p));
				php_replace_controlchars_ex(ret->query, (pp - p));
			}
			p = pp;
			goto label_parse;
		} else if (++p - ue) {
			ret->query = estrndup(p, (ue-p));
			php_replace_controlchars_ex(ret->query, (ue - p));
		}
	} else if ((p = memchr(s, '#', (ue - s)))) {
		if (p - s) {
			ret->path = estrndup(s, (p-s));
			php_replace_controlchars_ex(ret->path, (p - s));
		}	
		
		label_parse:
		p++;
		
		if (ue - p) {
			ret->fragment = estrndup(p, (ue-p));
			php_replace_controlchars_ex(ret->fragment, (ue - p));
		}	
	} else {
		ret->path = estrndup(s, (ue-s));
		php_replace_controlchars_ex(ret->path, (ue - s));
	}
end:
	return ret;
}