Beispiel #1
0
void zephir_concat_vvvs(zval **result, zval *op1, zval *op2, zval *op3, const char *op4, zend_uint op4_len, int self_var TSRMLS_DC) {

    zval result_copy, op1_copy, op2_copy, op3_copy;
    int use_copy = 0, use_copy1 = 0, use_copy2 = 0, use_copy3 = 0;
    uint offset = 0, length;

    if (Z_TYPE_P(op1) != IS_STRING) {
        zend_make_printable_zval(op1, &op1_copy, &use_copy1);
        if (use_copy1) {
            op1 = &op1_copy;
        }
    }

    if (Z_TYPE_P(op2) != IS_STRING) {
        zend_make_printable_zval(op2, &op2_copy, &use_copy2);
        if (use_copy2) {
            op2 = &op2_copy;
        }
    }

    if (Z_TYPE_P(op3) != IS_STRING) {
        zend_make_printable_zval(op3, &op3_copy, &use_copy3);
        if (use_copy3) {
            op3 = &op3_copy;
        }
    }

    length = Z_STRLEN_P(op1) + Z_STRLEN_P(op2) + Z_STRLEN_P(op3) + op4_len;
    if (self_var) {

        if (Z_TYPE_PP(result) != IS_STRING) {
            zend_make_printable_zval(*result, &result_copy, &use_copy);
            if (use_copy) {
                ZEPHIR_CPY_WRT_CTOR(*result, (&result_copy));
            }
        }

        offset = Z_STRLEN_PP(result);
        length += offset;
        Z_STRVAL_PP(result) = (char *) str_erealloc(Z_STRVAL_PP(result), length + 1);

    } else {
        Z_STRVAL_PP(result) = (char *) emalloc(length + 1);
    }

    memcpy(Z_STRVAL_PP(result) + offset, Z_STRVAL_P(op1), Z_STRLEN_P(op1));
    memcpy(Z_STRVAL_PP(result) + offset + Z_STRLEN_P(op1), Z_STRVAL_P(op2), Z_STRLEN_P(op2));
    memcpy(Z_STRVAL_PP(result) + offset + Z_STRLEN_P(op1) + Z_STRLEN_P(op2), Z_STRVAL_P(op3), Z_STRLEN_P(op3));
    memcpy(Z_STRVAL_PP(result) + offset + Z_STRLEN_P(op1) + Z_STRLEN_P(op2) + Z_STRLEN_P(op3), op4, op4_len);
    Z_STRVAL_PP(result)[length] = 0;
    Z_TYPE_PP(result) = IS_STRING;
    Z_STRLEN_PP(result) = length;

    if (use_copy1) {
        zval_dtor(op1);
    }

    if (use_copy2) {
        zval_dtor(op2);
    }

    if (use_copy3) {
        zval_dtor(op3);
    }

    if (use_copy) {
        zval_dtor(&result_copy);
    }

}
Beispiel #2
0
static zend_always_inline int process_nested_data(UNSERIALIZE_PARAMETER, HashTable *ht, zend_long elements, int objprops)
{
	while (elements-- > 0) {
		zval key, *data, d, *old_data;
		zend_ulong idx;

		ZVAL_UNDEF(&key);

		if (!php_var_unserialize_ex(&key, p, max, NULL, classes)) {
			zval_dtor(&key);
			return 0;
		}

		data = NULL;
		ZVAL_UNDEF(&d);

		if (!objprops) {
			if (Z_TYPE(key) == IS_LONG) {
				idx = Z_LVAL(key);
numeric_key:
				if (UNEXPECTED((old_data = zend_hash_index_find(ht, idx)) != NULL)) {
					//??? update hash
					var_push_dtor(var_hash, old_data);
					data = zend_hash_index_update(ht, idx, &d);
				} else {
					data = zend_hash_index_add_new(ht, idx, &d);
				}
			} else if (Z_TYPE(key) == IS_STRING) {
				if (UNEXPECTED(ZEND_HANDLE_NUMERIC(Z_STR(key), idx))) {
					goto numeric_key;
				}
				if (UNEXPECTED((old_data = zend_hash_find(ht, Z_STR(key))) != NULL)) {
					//??? update hash
					var_push_dtor(var_hash, old_data);
					data = zend_hash_update(ht, Z_STR(key), &d);
				} else {
					data = zend_hash_add_new(ht, Z_STR(key), &d);
				}
			} else {
				zval_dtor(&key);
				return 0;
			}
		} else {
			if (EXPECTED(Z_TYPE(key) == IS_STRING)) {
string_key:
				if ((old_data = zend_hash_find(ht, Z_STR(key))) != NULL) {
					if (Z_TYPE_P(old_data) == IS_INDIRECT) {
						old_data = Z_INDIRECT_P(old_data);
					}
					var_push_dtor(var_hash, old_data);
					data = zend_hash_update_ind(ht, Z_STR(key), &d);
				} else {
					data = zend_hash_add_new(ht, Z_STR(key), &d);
				}
			} else if (Z_TYPE(key) == IS_LONG) {
				/* object properties should include no integers */
				convert_to_string(&key);
				goto string_key;
			} else {
				zval_dtor(&key);
				return 0;
			}
		}

		zval_dtor(&key);

		if (!php_var_unserialize_ex(data, p, max, var_hash, classes)) {
			return 0;
		}

		if (elements && *(*p-1) != ';' && *(*p-1) != '}') {
			(*p)--;
			return 0;
		}
	}

	return 1;
}
Beispiel #3
0
static void tokenize(zval *return_value)
{
	zval token;
	zval keyword;
	int token_type;
	zend_bool destroy;
	int token_line = 1;
	int need_tokens = -1; // for __halt_compiler lexing. -1 = disabled

	array_init(return_value);

	ZVAL_NULL(&token);
	while ((token_type = lex_scan(&token))) {
		destroy = 1;
		switch (token_type) {
			case T_CLOSE_TAG:
				if (zendtext[zendleng - 1] != '>') {
					CG(zend_lineno)++;
				}
			case T_OPEN_TAG:
			case T_OPEN_TAG_WITH_ECHO:
			case T_WHITESPACE:
			case T_COMMENT:
			case T_DOC_COMMENT:
				destroy = 0;
				break;
		}

		if (token_type >= 256) {
			array_init(&keyword);
			add_next_index_long(&keyword, token_type);
			if (token_type == T_END_HEREDOC) {
				if (CG(increment_lineno)) {
					token_line = ++CG(zend_lineno);
					CG(increment_lineno) = 0;
				}
			}
			add_next_index_stringl(&keyword, (char *)zendtext, zendleng);
			add_next_index_long(&keyword, token_line);
			add_next_index_zval(return_value, &keyword);
		} else {
			add_next_index_stringl(return_value, (char *)zendtext, zendleng);
		}
		if (destroy && Z_TYPE(token) != IS_NULL) {
			zval_dtor(&token);
		}
		ZVAL_NULL(&token);

		// after T_HALT_COMPILER collect the next three non-dropped tokens
		if (need_tokens != -1) {
			if (token_type != T_WHITESPACE && token_type != T_OPEN_TAG
			    && token_type != T_COMMENT && token_type != T_DOC_COMMENT
			    && --need_tokens == 0
			) {
				// fetch the rest into a T_INLINE_HTML
				if (zendcursor != zendlimit) {
					array_init(&keyword);
					add_next_index_long(&keyword, T_INLINE_HTML);
					add_next_index_stringl(&keyword, (char *)zendcursor, zendlimit - zendcursor);
					add_next_index_long(&keyword, token_line);
					add_next_index_zval(return_value, &keyword);
				}
				break;
			}
		} else if (token_type == T_HALT_COMPILER) {
			need_tokens = 3;
		}

		token_line = CG(zend_lineno);
	}
}
php_stream *php_stream_url_wrap_http_ex(php_stream_wrapper *wrapper, char *path, 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;

	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, ENFORCE_SAFE_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);

	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);
		efree(protocol_version);
		protocol_version = NULL;
	} 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;

			if (!header_init) { /* Remove post headers for redirects */
				int l = strlen(tmp);
				char *s2, *tmp_c = estrdup(tmp);
				
				php_strtolower(tmp_c, l);
				if ((s = strstr(tmp_c, "content-length:"))) {
					if ((s2 = memchr(s, '\n', tmp_c + l - s))) {
						int b = tmp_c + l - 1 - s2;
						memmove(tmp, tmp + (s2 + 1 - tmp_c), b);
						memmove(tmp_c, s2 + 1, b);
						
					} else {
						tmp[s - tmp_c] = *s = '\0';
					}
					l = strlen(tmp_c);
				}
				if ((s = strstr(tmp_c, "content-type:"))) {
					if ((s2 = memchr(s, '\n', tmp_c + l - s))) {
						memmove(tmp, tmp + (s2 + 1 - tmp_c), tmp_c + l - 1 - s2);
					} else {
						tmp[s - tmp_c] = '\0';
					}
				}

				efree(tmp_c);
				tmp_c = php_trim(tmp, strlen(tmp), NULL, 0, NULL, 3 TSRMLS_CC);
				efree(tmp);
				tmp = tmp_c;
			}

			user_headers = estrdup(tmp);

			/* Make lowercase for easy comparison against 'standard' headers */
			php_strtolower(tmp, strlen(tmp));
			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;
			}
			/* 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 */
	{
		char *from_address = php_ini_string("from", sizeof("from"), 0);
		if (((have_header & HTTP_HEADER_FROM) == 0) && from_address && from_address[0] != '\0') {
			if (snprintf(scratch, scratch_len, "From: %s\r\n", 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));
			}
		}
	}

	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;
			int response_code;

			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);
			}
			/* 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);
				}
				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 {
Beispiel #5
0
/* php_formatted_print() {{{
 * New sprintf implementation for PHP.
 *
 * Modifiers:
 *
 *  " "   pad integers with spaces
 *  "-"   left adjusted field
 *   n    field size
 *  "."n  precision (floats only)
 *  "+"   Always place a sign (+ or -) in front of a number
 *
 * Type specifiers:
 *
 *  "%"   literal "%", modifiers are ignored.
 *  "b"   integer argument is printed as binary
 *  "c"   integer argument is printed as a single character
 *  "d"   argument is an integer
 *  "f"   the argument is a float
 *  "o"   integer argument is printed as octal
 *  "s"   argument is a string
 *  "x"   integer argument is printed as lowercase hexadecimal
 *  "X"   integer argument is printed as uppercase hexadecimal
 *
 */
static char *
php_formatted_print(int ht, int *len, int use_array, int format_offset TSRMLS_DC)
{
	zval ***args, **z_format;
	int argc, size = 240, inpos = 0, outpos = 0, temppos;
	int alignment, currarg, adjusting, argnum, width, precision;
	char *format, *result, padding;
	int always_sign;

	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "+", &args, &argc) == FAILURE) {
		return NULL;
	}

	/* verify the number of args */
	if ((use_array && argc != (2 + format_offset)) 
			|| (!use_array && argc < (1 + format_offset))) {
		efree(args);
		WRONG_PARAM_COUNT_WITH_RETVAL(NULL);
	}
	
	if (use_array) {
		int i = 1;
		zval ***newargs;
		zval **array;

		z_format = args[format_offset];
		array = args[1 + format_offset];
		
		SEPARATE_ZVAL(array);
		convert_to_array_ex(array);
		
		argc = 1 + zend_hash_num_elements(Z_ARRVAL_PP(array));
		newargs = (zval ***)safe_emalloc(argc, sizeof(zval *), 0);
		newargs[0] = z_format;
		
		for (zend_hash_internal_pointer_reset(Z_ARRVAL_PP(array));
			 zend_hash_get_current_data(Z_ARRVAL_PP(array), (void **)&newargs[i++]) == SUCCESS;
			 zend_hash_move_forward(Z_ARRVAL_PP(array)));

		efree(args);
		args = newargs;
		format_offset = 0;
	}
	
	convert_to_string_ex(args[format_offset]);
	format = Z_STRVAL_PP(args[format_offset]);
	result = emalloc(size);

	currarg = 1;

	while (inpos<Z_STRLEN_PP(args[format_offset])) {
		int expprec = 0, multiuse = 0;
		zval *tmp;

		PRINTF_DEBUG(("sprintf: format[%d]='%c'\n", inpos, format[inpos]));
		PRINTF_DEBUG(("sprintf: outpos=%d\n", outpos));
		if (format[inpos] != '%') {
			php_sprintf_appendchar(&result, &outpos, &size, format[inpos++] TSRMLS_CC);
		} else if (format[inpos + 1] == '%') {
			php_sprintf_appendchar(&result, &outpos, &size, '%' TSRMLS_CC);
			inpos += 2;
		} else {
			/* starting a new format specifier, reset variables */
			alignment = ALIGN_RIGHT;
			adjusting = 0;
			padding = ' ';
			always_sign = 0;
			inpos++;			/* skip the '%' */

			PRINTF_DEBUG(("sprintf: first looking at '%c', inpos=%d\n",
						  format[inpos], inpos));
			if (isascii((int)format[inpos]) && !isalpha((int)format[inpos])) {
				/* first look for argnum */
				temppos = inpos;
				while (isdigit((int)format[temppos])) temppos++;
				if (format[temppos] == '$') {
					argnum = php_sprintf_getnumber(format, &inpos);

					if (argnum <= 0) {
						efree(result);
						efree(args);
						php_error_docref(NULL TSRMLS_CC, E_WARNING, "Argument number must be greater than zero");
						return NULL;
					}

					multiuse = 1;
					inpos++;  /* skip the '$' */
				} else {
					argnum = currarg++;
				}

				argnum += format_offset;

				/* after argnum comes modifiers */
				PRINTF_DEBUG(("sprintf: looking for modifiers\n"
							  "sprintf: now looking at '%c', inpos=%d\n",
							  format[inpos], inpos));
				for (;; inpos++) {
					if (format[inpos] == ' ' || format[inpos] == '0') {
						padding = format[inpos];
					} else if (format[inpos] == '-') {
						alignment = ALIGN_LEFT;
						/* space padding, the default */
					} else if (format[inpos] == '+') {
						always_sign = 1;
					} else if (format[inpos] == '\'') {
						padding = format[++inpos];
					} else {
						PRINTF_DEBUG(("sprintf: end of modifiers\n"));
						break;
					}
				}
				PRINTF_DEBUG(("sprintf: padding='%c'\n", padding));
				PRINTF_DEBUG(("sprintf: alignment=%s\n",
							  (alignment == ALIGN_LEFT) ? "left" : "right"));


				/* after modifiers comes width */
				if (isdigit((int)format[inpos])) {
					PRINTF_DEBUG(("sprintf: getting width\n"));
					if ((width = php_sprintf_getnumber(format, &inpos)) < 0) {
						efree(result);
						efree(args);
						php_error_docref(NULL TSRMLS_CC, E_WARNING, "Width must be greater than zero and less than %d", INT_MAX);
						return NULL;
					}
					adjusting |= ADJ_WIDTH;
				} else {
					width = 0;
				}
				PRINTF_DEBUG(("sprintf: width=%d\n", width));

				/* after width and argnum comes precision */
				if (format[inpos] == '.') {
					inpos++;
					PRINTF_DEBUG(("sprintf: getting precision\n"));
					if (isdigit((int)format[inpos])) {
						if ((precision = php_sprintf_getnumber(format, &inpos)) < 0) {
							efree(result);
							efree(args);
							php_error_docref(NULL TSRMLS_CC, E_WARNING, "Precision must be greater than zero and less than %d", INT_MAX);
							return NULL;
						}
						adjusting |= ADJ_PRECISION;
						expprec = 1;
					} else {
						precision = 0;
					}
				} else {
					precision = 0;
				}
				PRINTF_DEBUG(("sprintf: precision=%d\n", precision));
			} else {
				width = precision = 0;
				argnum = currarg++ + format_offset;
			}

			if (argnum >= argc) {
				efree(result);
				efree(args);
				php_error_docref(NULL TSRMLS_CC, E_WARNING, "Too few arguments");
				return NULL;
			}

			if (format[inpos] == 'l') {
				inpos++;
			}
			PRINTF_DEBUG(("sprintf: format character='%c'\n", format[inpos]));
			/* now we expect to find a type specifier */
			if (multiuse) {
				MAKE_STD_ZVAL(tmp);
				*tmp = **(args[argnum]);
				INIT_PZVAL(tmp);
				zval_copy_ctor(tmp);
			} else {
				SEPARATE_ZVAL(args[argnum]);
				tmp = *(args[argnum]);
			}

			switch (format[inpos]) {
				case 's': {
					zval *var, var_copy;
					int use_copy;

					zend_make_printable_zval(tmp, &var_copy, &use_copy);
					if (use_copy) {
						var = &var_copy;
					} else {
						var = tmp;
					}
					php_sprintf_appendstring(&result, &outpos, &size,
											 Z_STRVAL_P(var),
											 width, precision, padding,
											 alignment,
											 Z_STRLEN_P(var),
											 0, expprec, 0);
					if (use_copy) {
						zval_dtor(&var_copy);
					}
					break;
				}

				case 'd':
					convert_to_long(tmp);
					php_sprintf_appendint(&result, &outpos, &size,
										  Z_LVAL_P(tmp),
										  width, padding, alignment,
										  always_sign);
					break;

				case 'u':
					convert_to_long(tmp);
					php_sprintf_appenduint(&result, &outpos, &size,
										  Z_LVAL_P(tmp),
										  width, padding, alignment);
					break;

				case 'g':
				case 'G':
				case 'e':
				case 'E':
				case 'f':
				case 'F':
					convert_to_double(tmp);
					php_sprintf_appenddouble(&result, &outpos, &size,
											 Z_DVAL_P(tmp),
											 width, padding, alignment,
											 precision, adjusting,
											 format[inpos], always_sign
											 TSRMLS_CC);
					break;
					
				case 'c':
					convert_to_long(tmp);
					php_sprintf_appendchar(&result, &outpos, &size,
										(char) Z_LVAL_P(tmp) TSRMLS_CC);
					break;

				case 'o':
					convert_to_long(tmp);
					php_sprintf_append2n(&result, &outpos, &size,
										 Z_LVAL_P(tmp),
										 width, padding, alignment, 3,
										 hexchars, expprec);
					break;

				case 'x':
					convert_to_long(tmp);
					php_sprintf_append2n(&result, &outpos, &size,
										 Z_LVAL_P(tmp),
										 width, padding, alignment, 4,
										 hexchars, expprec);
					break;

				case 'X':
					convert_to_long(tmp);
					php_sprintf_append2n(&result, &outpos, &size,
										 Z_LVAL_P(tmp),
										 width, padding, alignment, 4,
										 HEXCHARS, expprec);
					break;

				case 'b':
					convert_to_long(tmp);
					php_sprintf_append2n(&result, &outpos, &size,
										 Z_LVAL_P(tmp),
										 width, padding, alignment, 1,
										 hexchars, expprec);
					break;

				case '%':
					php_sprintf_appendchar(&result, &outpos, &size, '%' TSRMLS_CC);

					break;
				default:
					break;
			}
			if (multiuse) {
				zval_ptr_dtor(&tmp);
			}
			inpos++;
		}
	}
	
	efree(args);
	
	/* possibly, we have to make sure we have room for the terminating null? */
	result[outpos]=0;
	*len = outpos;	
	return result;
}
Beispiel #6
0
PHPAPI void php_register_variable_ex(char *var_name, zval *val, zval *track_vars_array)
{
	char *p = NULL;
	char *ip = NULL;		/* index pointer */
	char *index;
	char *var, *var_orig;
	size_t var_len, index_len;
	zval gpc_element, *gpc_element_p;
	zend_bool is_array = 0;
	HashTable *symtable1 = NULL;
	ALLOCA_FLAG(use_heap)

	assert(var_name != NULL);

	if (track_vars_array && Z_TYPE_P(track_vars_array) == IS_ARRAY) {
		symtable1 = Z_ARRVAL_P(track_vars_array);
	}

	if (!symtable1) {
		/* Nothing to do */
		zval_dtor(val);
		return;
	}


	/* ignore leading spaces in the variable name */
	while (*var_name && *var_name==' ') {
		var_name++;
	}

	/*
	 * Prepare variable name
	 */
	var_len = strlen(var_name);
	var = var_orig = do_alloca(var_len + 1, use_heap);
	memcpy(var_orig, var_name, var_len + 1);

	/* ensure that we don't have spaces or dots in the variable name (not binary safe) */
	for (p = var; *p; p++) {
		if (*p == ' ' || *p == '.') {
			*p='_';
		} else if (*p == '[') {
			is_array = 1;
			ip = p;
			*p = 0;
			break;
		}
	}
	var_len = p - var;

	if (var_len==0) { /* empty variable name, or variable name with a space in it */
		zval_dtor(val);
		free_alloca(var_orig, use_heap);
		return;
	}

	/* GLOBALS hijack attempt, reject parameter */
	if (symtable1 == &EG(symbol_table) &&
		var_len == sizeof("GLOBALS")-1 &&
		!memcmp(var, "GLOBALS", sizeof("GLOBALS")-1)) {
		zval_dtor(val);
		free_alloca(var_orig, use_heap);
		return;
	}

	index = var;
	index_len = var_len;

	if (is_array) {
		int nest_level = 0;
		while (1) {
			char *index_s;
			size_t new_idx_len = 0;

			if(++nest_level > PG(max_input_nesting_level)) {
				HashTable *ht;
				/* too many levels of nesting */

				if (track_vars_array) {
					ht = Z_ARRVAL_P(track_vars_array);
					zend_symtable_str_del(ht, var, var_len);
				}

				zval_dtor(val);

				/* do not output the error message to the screen,
				 this helps us to to avoid "information disclosure" */
				if (!PG(display_errors)) {
					php_error_docref(NULL, E_WARNING, "Input variable nesting level exceeded " ZEND_LONG_FMT ". To increase the limit change max_input_nesting_level in php.ini.", PG(max_input_nesting_level));
				}
				free_alloca(var_orig, use_heap);
				return;
			}

			ip++;
			index_s = ip;
			if (isspace(*ip)) {
				ip++;
			}
			if (*ip==']') {
				index_s = NULL;
			} else {
				ip = strchr(ip, ']');
				if (!ip) {
					/* PHP variables cannot contain '[' in their names, so we replace the character with a '_' */
					*(index_s - 1) = '_';

					index_len = 0;
					if (index) {
						index_len = strlen(index);
					}
					goto plain_var;
					return;
				}
				*ip = 0;
				new_idx_len = strlen(index_s);
			}

			if (!index) {
				array_init(&gpc_element);
				if ((gpc_element_p = zend_hash_next_index_insert(symtable1, &gpc_element)) == NULL) {
					zval_ptr_dtor(&gpc_element);
					zval_dtor(val);
					free_alloca(var_orig, use_heap);
					return;
				}
			} else {
				gpc_element_p = zend_symtable_str_find(symtable1, index, index_len);
				if (!gpc_element_p) {
					zval tmp;
					array_init(&tmp);
					gpc_element_p = zend_symtable_str_update_ind(symtable1, index, index_len, &tmp);
				} else {
					if (Z_TYPE_P(gpc_element_p) == IS_INDIRECT) {
						gpc_element_p = Z_INDIRECT_P(gpc_element_p);
					}
					if (Z_TYPE_P(gpc_element_p) != IS_ARRAY) {
						zval_ptr_dtor(gpc_element_p);
						array_init(gpc_element_p);
					}
				}
			}
			symtable1 = Z_ARRVAL_P(gpc_element_p);
			/* ip pointed to the '[' character, now obtain the key */
			index = index_s;
			index_len = new_idx_len;

			ip++;
			if (*ip == '[') {
				is_array = 1;
				*ip = 0;
			} else {
				goto plain_var;
			}
		}
	} else {
plain_var:
		ZVAL_COPY_VALUE(&gpc_element, val);
		if (!index) {
			if ((gpc_element_p = zend_hash_next_index_insert(symtable1, &gpc_element)) == NULL) {
				zval_ptr_dtor(&gpc_element);
			}
		} else {
			/*
			 * According to rfc2965, more specific paths are listed above the less specific ones.
			 * If we encounter a duplicate cookie name, we should skip it, since it is not possible
			 * to have the same (plain text) cookie name for the same path and we should not overwrite
			 * more specific cookies with the less specific ones.
			 */
			if (Z_TYPE(PG(http_globals)[TRACK_VARS_COOKIE]) != IS_UNDEF &&
				symtable1 == Z_ARRVAL(PG(http_globals)[TRACK_VARS_COOKIE]) &&
				zend_symtable_str_exists(symtable1, index, index_len)) {
				zval_ptr_dtor(&gpc_element);
			} else {
				gpc_element_p = zend_symtable_str_update_ind(symtable1, index, index_len, &gpc_element);
			}
		}
	}
	free_alloca(var_orig, use_heap);
}
Beispiel #7
0
int zend_optimizer_replace_by_const(zend_op_array *op_array,
                                    zend_op       *opline,
                                    zend_uchar     type,
                                    uint32_t       var,
                                    zval          *val)
{
	zend_op *end = op_array->opcodes + op_array->last;

	while (opline < end) {
		if (ZEND_OP1_TYPE(opline) == type &&
			ZEND_OP1(opline).var == var) {
			switch (opline->opcode) {
				case ZEND_FETCH_DIM_W:
				case ZEND_FETCH_DIM_RW:
				case ZEND_FETCH_DIM_FUNC_ARG:
				case ZEND_FETCH_DIM_UNSET:
				case ZEND_ASSIGN_DIM:
				case ZEND_SEPARATE:
					return 0;
				case ZEND_SEND_VAR:
					opline->extended_value = 0;
					opline->opcode = ZEND_SEND_VAL;
					break;
				case ZEND_SEND_VAR_EX:
					opline->extended_value = 0;
					opline->opcode = ZEND_SEND_VAL_EX;
					break;
				case ZEND_SEND_VAR_NO_REF:
					if (opline->extended_value & ZEND_ARG_COMPILE_TIME_BOUND) {
						if (opline->extended_value & ZEND_ARG_SEND_BY_REF) {
							return 0;
						}
						opline->extended_value = 0;
						opline->opcode = ZEND_SEND_VAL_EX;
					} else {
						opline->extended_value = 0;
						opline->opcode = ZEND_SEND_VAL;
					}
					break;
				/* In most cases IS_TMP_VAR operand may be used only once.
				 * The operands are usually destroyed by the opcode handler.
				 * ZEND_CASE is an exception, that keeps operand unchanged,
				 * and allows its reuse. The number of ZEND_CASE instructions
				 * usually terminated by ZEND_FREE that finally kills the value.
				 */
				case ZEND_CASE: {
					zval old_val;
					ZVAL_COPY_VALUE(&old_val, val);
					zval_copy_ctor(val);
					zend_optimizer_update_op1_const(op_array, opline, val);
					ZVAL_COPY_VALUE(val, &old_val);
					opline++;
					continue;
				}
				case ZEND_FREE:
					MAKE_NOP(opline);
					zval_dtor(val);
					return 1;
				default:
					break;
			}
			zend_optimizer_update_op1_const(op_array, opline, val);
			break;
		}

		if (ZEND_OP2_TYPE(opline) == type &&
			ZEND_OP2(opline).var == var) {
			switch (opline->opcode) {
				case ZEND_ASSIGN_REF:
					return 0;
				default:
					break;
			}
			zend_optimizer_update_op2_const(op_array, opline, val);
			break;
		}
		opline++;
	}

	return 1;
}
Beispiel #8
0
/* {{{ _php_mb_regex_ereg_replace_exec */
static void _php_mb_regex_ereg_replace_exec(INTERNAL_FUNCTION_PARAMETERS, OnigOptionType options, int is_callable)
{
	zval *arg_pattern_zval;

	char *arg_pattern;
	size_t arg_pattern_len;

	char *replace;
	size_t replace_len;

	zend_fcall_info arg_replace_fci;
	zend_fcall_info_cache arg_replace_fci_cache;

	char *string;
	size_t string_len;

	char *p;
	php_mb_regex_t *re;
	OnigSyntaxType *syntax;
	OnigRegion *regs = NULL;
	smart_str out_buf = {0};
	smart_str eval_buf = {0};
	smart_str *pbuf;
	int i, err, eval, n;
	OnigUChar *pos;
	OnigUChar *string_lim;
	char *description = NULL;
	char pat_buf[2];

	const mbfl_encoding *enc;

	{
		const char *current_enc_name;
		current_enc_name = _php_mb_regex_mbctype2name(MBREX(current_mbctype));
		if (current_enc_name == NULL ||
			(enc = mbfl_name2encoding(current_enc_name)) == NULL) {
			php_error_docref(NULL, E_WARNING, "Unknown error");
			RETURN_FALSE;
		}
	}
	eval = 0;
	{
		char *option_str = NULL;
		size_t option_str_len = 0;

		if (!is_callable) {
			if (zend_parse_parameters(ZEND_NUM_ARGS(), "zss|s",
						&arg_pattern_zval,
						&replace, &replace_len,
						&string, &string_len,
						&option_str, &option_str_len) == FAILURE) {
				RETURN_FALSE;
			}
		} else {
			if (zend_parse_parameters(ZEND_NUM_ARGS(), "zfs|s",
						&arg_pattern_zval,
						&arg_replace_fci, &arg_replace_fci_cache,
						&string, &string_len,
						&option_str, &option_str_len) == FAILURE) {
				RETURN_FALSE;
			}
		}

		if (option_str != NULL) {
			_php_mb_regex_init_options(option_str, option_str_len, &options, &syntax, &eval);
		} else {
			options |= MBREX(regex_default_options);
			syntax = MBREX(regex_default_syntax);
		}
	}
	if (Z_TYPE_P(arg_pattern_zval) == IS_STRING) {
		arg_pattern = Z_STRVAL_P(arg_pattern_zval);
		arg_pattern_len = Z_STRLEN_P(arg_pattern_zval);
	} else {
		/* FIXME: this code is not multibyte aware! */
		convert_to_long_ex(arg_pattern_zval);
		pat_buf[0] = (char)Z_LVAL_P(arg_pattern_zval);	
		pat_buf[1] = '\0';

		arg_pattern = pat_buf;
		arg_pattern_len = 1;	
	}
	/* create regex pattern buffer */
	re = php_mbregex_compile_pattern(arg_pattern, arg_pattern_len, options, MBREX(current_mbctype), syntax);
	if (re == NULL) {
		RETURN_FALSE;
	}

	if (eval || is_callable) {
		pbuf = &eval_buf;
		description = zend_make_compiled_string_description("mbregex replace");
	} else {
		pbuf = &out_buf;
		description = NULL;
	}

	if (is_callable) {
		if (eval) {
			php_error_docref(NULL, E_WARNING, "Option 'e' cannot be used with replacement callback");
			RETURN_FALSE;
		}
	}

	/* do the actual work */
	err = 0;
	pos = (OnigUChar *)string;
	string_lim = (OnigUChar*)(string + string_len);
	regs = onig_region_new();
	while (err >= 0) {
		err = onig_search(re, (OnigUChar *)string, (OnigUChar *)string_lim, pos, (OnigUChar *)string_lim, regs, 0);
		if (err <= -2) {
			OnigUChar err_str[ONIG_MAX_ERROR_MESSAGE_LEN];
			onig_error_code_to_str(err_str, err);
			php_error_docref(NULL, E_WARNING, "mbregex search failure in php_mbereg_replace_exec(): %s", err_str);
			break;
		}
		if (err >= 0) {
#if moriyoshi_0
			if (regs->beg[0] == regs->end[0]) {
				php_error_docref(NULL, E_WARNING, "Empty regular expression");
				break;
			}
#endif
			/* copy the part of the string before the match */
			smart_str_appendl(&out_buf, pos, (size_t)((OnigUChar *)(string + regs->beg[0]) - pos));

			if (!is_callable) {
				/* copy replacement and backrefs */
				i = 0;
				p = replace;
				while (i < replace_len) {
					int fwd = (int) php_mb_mbchar_bytes_ex(p, enc);
					n = -1;
					if ((replace_len - i) >= 2 && fwd == 1 &&
					p[0] == '\\' && p[1] >= '0' && p[1] <= '9') {
						n = p[1] - '0';
					}
					if (n >= 0 && n < regs->num_regs) {
						if (regs->beg[n] >= 0 && regs->beg[n] < regs->end[n] && regs->end[n] <= string_len) {
							smart_str_appendl(pbuf, string + regs->beg[n], regs->end[n] - regs->beg[n]);
						}
						p += 2;
						i += 2;
					} else {
						smart_str_appendl(pbuf, p, fwd);
						p += fwd;
						i += fwd;
					}
				}
			}
				
			if (eval) {
				zval v;
				/* null terminate buffer */
				smart_str_0(&eval_buf);
				/* do eval */
				if (zend_eval_stringl(eval_buf.s->val, eval_buf.s->len, &v, description) == FAILURE) {
					efree(description);
					php_error_docref(NULL,E_ERROR, "Failed evaluating code: %s%s", PHP_EOL, eval_buf.s->val);
					/* zend_error() does not return in this case */
				}

				/* result of eval */
				convert_to_string(&v);
				smart_str_appendl(&out_buf, Z_STRVAL(v), Z_STRLEN(v));
				/* Clean up */
				eval_buf.s->len = 0;
				zval_dtor(&v);
			} else if (is_callable) {
				zval args[1];
				zval subpats, retval;
				int i;
				
				array_init(&subpats);
				for (i = 0; i < regs->num_regs; i++) {
					add_next_index_stringl(&subpats, string + regs->beg[i], regs->end[i] - regs->beg[i]);
				}				
				
				ZVAL_COPY_VALUE(&args[0], &subpats);
				/* null terminate buffer */
				smart_str_0(&eval_buf);
				
				arg_replace_fci.param_count = 1;
				arg_replace_fci.params = args;
				arg_replace_fci.retval = &retval;
				if (zend_call_function(&arg_replace_fci, &arg_replace_fci_cache) == SUCCESS &&
						!Z_ISUNDEF(retval)) {
					convert_to_string_ex(&retval);
					smart_str_appendl(&out_buf, Z_STRVAL(retval), Z_STRLEN(retval));
					if (eval_buf.s) {
						eval_buf.s->len = 0;
					}
					zval_ptr_dtor(&retval);
				} else {
					efree(description);
					if (!EG(exception)) {
						php_error_docref(NULL, E_WARNING, "Unable to call custom replacement function");
					}
				}
				zval_ptr_dtor(&subpats);
			}

			n = regs->end[0];
			if ((pos - (OnigUChar *)string) < n) {
				pos = (OnigUChar *)string + n;
			} else {
				if (pos < string_lim) {
					smart_str_appendl(&out_buf, pos, 1); 
				}
				pos++;
			}
		} else { /* nomatch */
			/* stick that last bit of string on our output */
			if (string_lim - pos > 0) {
				smart_str_appendl(&out_buf, pos, string_lim - pos);
			}
		}
		onig_region_free(regs, 0);
	}

	if (description) {
		efree(description);
	}
	if (regs != NULL) {
		onig_region_free(regs, 1);
	}
	smart_str_free(&eval_buf);

	if (err <= -2) {
		smart_str_free(&out_buf);	
		RETVAL_FALSE;
	} else if (out_buf.s) {
		smart_str_0(&out_buf);
		RETVAL_STR(out_buf.s);
	} else {
		RETVAL_EMPTY_STRING();
	}
}
static int create_transliterator( char *str_id, size_t str_id_len, zend_long direction, zval *object )
{
	Transliterator_object *to;
	UChar	              *ustr_id    = NULL;
	int32_t               ustr_id_len = 0;
	UTransliterator       *utrans;
	UParseError           parse_error   = {0, -1};

	intl_error_reset( NULL );

	if( ( direction != TRANSLITERATOR_FORWARD ) && (direction != TRANSLITERATOR_REVERSE ) )
	{
		intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR,
			"transliterator_create: invalid direction", 0 );
		return FAILURE;
	}

	object_init_ex( object, Transliterator_ce_ptr );
	TRANSLITERATOR_METHOD_FETCH_OBJECT_NO_CHECK; /* fetch zend object from zval "object" into "to" */

	/* Convert transliterator id to UTF-16 */
	intl_convert_utf8_to_utf16( &ustr_id, &ustr_id_len, str_id, str_id_len, TRANSLITERATOR_ERROR_CODE_P( to ) );
	if( U_FAILURE( TRANSLITERATOR_ERROR_CODE( to ) ) )
	{
		intl_error_set_code( NULL, TRANSLITERATOR_ERROR_CODE( to ) );
		intl_error_set_custom_msg( NULL, "String conversion of id to UTF-16 failed", 0 );
		zval_dtor( object );
		return FAILURE;
	}

	/* Open ICU Transliterator. */
	utrans = utrans_openU( ustr_id, ustr_id_len, (UTransDirection ) direction,
		NULL, -1, &parse_error, TRANSLITERATOR_ERROR_CODE_P( to ) );
	if (ustr_id) {
		efree( ustr_id );
	}

	if( U_FAILURE( TRANSLITERATOR_ERROR_CODE( to ) ) )
	{
		char *buf = NULL;
		intl_error_set_code( NULL, TRANSLITERATOR_ERROR_CODE( to ) );
		spprintf( &buf, 0, "transliterator_create: unable to open ICU transliterator"
			" with id \"%s\"", str_id );
		if( buf == NULL ) {
			intl_error_set_custom_msg( NULL,
				"transliterator_create: unable to open ICU transliterator", 0 );
		}
		else
		{
			intl_error_set_custom_msg( NULL, buf, /* copy message */ 1 );
			efree( buf );
		}
		zval_dtor( object );
		return FAILURE;
	}

	transliterator_object_construct( object, utrans, TRANSLITERATOR_ERROR_CODE_P( to ) );
	/* no need to close the transliterator manually on construction error */
	if( U_FAILURE( TRANSLITERATOR_ERROR_CODE( to ) ) )
	{
		intl_error_set_code( NULL, TRANSLITERATOR_ERROR_CODE( to ) );
		intl_error_set_custom_msg( NULL,
			"transliterator_create: internal constructor call failed", 0 );
		zval_dtor( object );
		return FAILURE;
	}

	return SUCCESS;
}
Beispiel #10
0
 ~PHPTransport() {
     efree(buffer);
     zval_dtor(&t);
 }
Beispiel #11
0
/* {{{ _php_mb_regex_ereg_exec */
static void _php_mb_regex_ereg_exec(INTERNAL_FUNCTION_PARAMETERS, int icase)
{
	zval *arg_pattern, *array;
	char *string;
	size_t string_len;
	php_mb_regex_t *re;
	OnigRegion *regs = NULL;
	int i, match_len, beg, end;
	OnigOptionType options;
	char *str;

	array = NULL;

	if (zend_parse_parameters(ZEND_NUM_ARGS(), "zs|z/", &arg_pattern, &string, &string_len, &array) == FAILURE) {
		RETURN_FALSE;
	}

	options = MBREX(regex_default_options);
	if (icase) {
		options |= ONIG_OPTION_IGNORECASE;
	}

	/* compile the regular expression from the supplied regex */
	if (Z_TYPE_P(arg_pattern) != IS_STRING) {
		/* we convert numbers to integers and treat them as a string */
		if (Z_TYPE_P(arg_pattern) == IS_DOUBLE) {
			convert_to_long_ex(arg_pattern);	/* get rid of decimal places */
		}
		convert_to_string_ex(arg_pattern);
		/* don't bother doing an extended regex with just a number */
	}

	if (Z_STRLEN_P(arg_pattern) == 0) {
		php_error_docref(NULL, E_WARNING, "empty pattern");
		RETVAL_FALSE;
		goto out;
	}

	re = php_mbregex_compile_pattern(Z_STRVAL_P(arg_pattern), Z_STRLEN_P(arg_pattern), options, MBREX(current_mbctype), MBREX(regex_default_syntax));
	if (re == NULL) {
		RETVAL_FALSE;
		goto out;
	}

	regs = onig_region_new();

	/* actually execute the regular expression */
	if (onig_search(re, (OnigUChar *)string, (OnigUChar *)(string + string_len), (OnigUChar *)string, (OnigUChar *)(string + string_len), regs, 0) < 0) {
		RETVAL_FALSE;
		goto out;
	}

	match_len = 1;
	str = string;
	if (array != NULL) {
		zval_dtor(array);
		array_init(array);

		match_len = regs->end[0] - regs->beg[0];
		for (i = 0; i < regs->num_regs; i++) {
			beg = regs->beg[i];
			end = regs->end[i];
			if (beg >= 0 && beg < end && end <= string_len) {
				add_index_stringl(array, i, (char *)&str[beg], end - beg);
			} else {
				add_index_bool(array, i, 0);
			}
		}
	}

	if (match_len == 0) {
		match_len = 1;
	}
	RETVAL_LONG(match_len);
out:
	if (regs != NULL) {
		onig_region_free(regs, 1);
	}
}
Beispiel #12
0
 ~PHPExceptionWrapper() throw() {
     zval_dtor(&ex);
 }
Beispiel #13
0
static int _php_tidy_set_tidy_opt(TidyDoc doc, char *optname, zval *value)
{
	TidyOption opt = tidyGetOptionByName(doc, optname);
	zval conv;

	ZVAL_COPY_VALUE(&conv, value);

	if (!opt) {
		php_error_docref(NULL, E_NOTICE, "Unknown Tidy Configuration Option '%s'", optname);
		return FAILURE;
	}

	if (tidyOptIsReadOnly(opt)) {
		php_error_docref(NULL, E_NOTICE, "Attempting to set read-only option '%s'", optname);
		return FAILURE;
	}

	switch(tidyOptGetType(opt)) {
		case TidyString:
			if (Z_TYPE(conv) != IS_STRING) {
				zval_copy_ctor(&conv);
				convert_to_string(&conv);
			}
			if (tidyOptSetValue(doc, tidyOptGetId(opt), Z_STRVAL(conv))) {
				if (Z_TYPE(conv) != Z_TYPE_P(value)) {
					zval_dtor(&conv);
				}
				return SUCCESS;
			}
			if (Z_TYPE(conv) != Z_TYPE_P(value)) {
				zval_dtor(&conv);
			}
			break;

		case TidyInteger:
			if (Z_TYPE(conv) != IS_LONG) {
				zval_copy_ctor(&conv);
				convert_to_long(&conv);
			}
			if (tidyOptSetInt(doc, tidyOptGetId(opt), Z_LVAL(conv))) {
				return SUCCESS;
			}
			break;

		case TidyBoolean:
			if (Z_TYPE(conv) != IS_LONG) {
				zval_copy_ctor(&conv);
				convert_to_long(&conv);
			}
			if (tidyOptSetBool(doc, tidyOptGetId(opt), Z_LVAL(conv))) {
				return SUCCESS;
			}
			break;

		default:
			php_error_docref(NULL, E_WARNING, "Unable to determine type of configuration option");
			break;
	}

	return FAILURE;
}
Beispiel #14
0
 ~value() {
     zval_dtor(static_cast<zval*>(this));
 }
Beispiel #15
0
/* event must be initialized with MAKE_STD_ZVAL or similar and array_init before sending here */
void php_aware_capture_error_ex(zval *event, int type, const char *error_filename, const uint error_lineno, zend_bool free_event, const char *format, va_list args TSRMLS_DC)
{
	zval **ppzval;
	va_list args_cp;
	int len;
	char *buffer;
	char uuid_str[PHP_AWARE_UUID_LEN + 1];
	
	TSRMLS_FETCH();
	
	/* Generate unique identifier */
	if (!php_aware_generate_uuid(uuid_str)) {
		php_aware_original_error_cb(E_WARNING TSRMLS_CC, "Failed to generate uuid");
		return;
	}

	/* Capture superglobals */
	if (AWARE_G(log_get)) {
		_add_assoc_zval_helper(event, "_GET", sizeof("_GET") TSRMLS_CC);
	}
	
	if (AWARE_G(log_post)) {
		_add_assoc_zval_helper(event, "_POST", sizeof("_POST") TSRMLS_CC);
	}
	
	if (AWARE_G(log_cookie)) {
		_add_assoc_zval_helper(event, "_COOKIE", sizeof("_COOKIE") TSRMLS_CC);
	}
	
	if (AWARE_G(log_session)) {
		_add_assoc_zval_helper(event, "_SESSION", sizeof("_SESSION") TSRMLS_CC);
	}
	
	if (AWARE_G(log_server)) {
		_add_assoc_zval_helper(event, "_SERVER", sizeof("_SERVER") TSRMLS_CC);
	}
	
	if (AWARE_G(log_env)) {
		_add_assoc_zval_helper(event, "_ENV", sizeof("_ENV") TSRMLS_CC);
	}
	
	if (AWARE_G(log_files)) {
		_add_assoc_zval_helper(event, "_FILES", sizeof("_FILES") TSRMLS_CC);
	}
	
	/* Capture backtrace */
	if (AWARE_G(log_backtrace)) {
		zval *btrace;
		ALLOC_INIT_ZVAL(btrace);
		zend_fetch_debug_backtrace(btrace, 0, 0 TSRMLS_CC);
		add_assoc_zval(event, "backtrace", btrace);
	}
	
	va_copy(args_cp, args);
	len = vspprintf(&buffer, PG(log_errors_max_len), format, args_cp);
	va_end(args_cp);

	add_assoc_string(event,	"error_message", buffer, 0);
	add_assoc_string(event,	"filename",	(char *)error_filename, 1);
	
	add_assoc_long(event, "line_number", error_lineno);
	add_assoc_long(event, "error_type", type);
	
	/*
		Set the last logged uuid into _SERVER
	*/
	add_assoc_string(event, "aware_event_uuid", uuid_str, 1);
	add_assoc_long(event, "aware_event_time", time(NULL));

	/*
		Set the last logged uuid into _SERVER
	*/
	if (zend_hash_find(&EG(symbol_table), "_SERVER", sizeof("_SERVER"), (void **) &ppzval) == SUCCESS) {
		add_assoc_string(*ppzval, "aware_last_uuid", uuid_str, 1);
	}

	/* Send to backend */
	php_aware_storage_store_all(uuid_str, event, type, error_filename, error_lineno TSRMLS_CC);
	
	if (free_event) {
		zval_dtor(event);
		FREE_ZVAL(event);
	}
}
Beispiel #16
0
static void php_fsockopen_stream(INTERNAL_FUNCTION_PARAMETERS, int persistent)
{
	char *host;
	int host_len;
	long port = -1;
	zval *zerrno = NULL, *zerrstr = NULL, *zcontext = NULL;
	double timeout = FG(default_socket_timeout);
	unsigned long conv;
	struct timeval tv;
	char *hashkey = NULL;
	php_stream *stream = NULL;
	php_stream_context *context = NULL;
	int err;

	RETVAL_FALSE;
	
	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|lzzdr", &host, &host_len, &port, &zerrno, &zerrstr, &timeout, &zcontext) == FAILURE) {
		RETURN_FALSE;
	}
	if (zcontext) {
		ZEND_FETCH_RESOURCE(context, php_stream_context*, &zcontext, -1, "stream-context", php_le_stream_context());
	}

	if (persistent) {
		spprintf(&hashkey, 0, "pfsockopen__%s:%ld", host, port);

		switch(php_stream_from_persistent_id(hashkey, &stream TSRMLS_CC)) {
			case PHP_STREAM_PERSISTENT_SUCCESS:
				if (_php_network_is_stream_alive(stream TSRMLS_CC)) {
					php_stream_to_zval(stream, return_value);
				} else {
					/* it died; we need to replace it */
					php_stream_pclose(stream);
					break;
				}
				
				/* fall through */
			case PHP_STREAM_PERSISTENT_FAILURE:
				efree(hashkey);
				return;
		}
	}

	/* prepare the timeout value for use */
	conv = (unsigned long) (timeout * 1000000.0);
	tv.tv_sec = conv / 1000000;
	tv.tv_usec = conv % 1000000;

	if (zerrno)	{
		zval_dtor(zerrno);
		ZVAL_LONG(zerrno, 0);
	}
	if (zerrstr) {
		zval_dtor(zerrstr);
		ZVAL_STRING(zerrstr, "", 1);
	}

	if (port > 0)	{ /* connect to a host */
		enum php_sslflags_t { php_ssl_none, php_ssl_v23, php_ssl_tls };
		enum php_sslflags_t ssl_flags = php_ssl_none;
		struct {
			char *proto;
			int protolen;
			int socktype;
			enum php_sslflags_t ssl_flags;
			/* more flags to be added here */
		} sockmodes[] = {
			{ "udp://", 6, SOCK_DGRAM,	php_ssl_none },
			{ "tcp://", 6, SOCK_STREAM,	php_ssl_none },
			{ "ssl://", 6, SOCK_STREAM, php_ssl_v23 },
			{ "tls://", 6, SOCK_STREAM, php_ssl_tls },
			/* more modes to be added here */
			{ NULL, 0, 0 }
		};
		int socktype = SOCK_STREAM;
		int i;

		for (i = 0; sockmodes[i].proto != NULL; i++) {
			if (strncmp(host, sockmodes[i].proto, sockmodes[i].protolen) == 0) {
				ssl_flags = sockmodes[i].ssl_flags;		
				socktype = sockmodes[i].socktype;
				host += sockmodes[i].protolen;
				break;
			}
		}
#ifndef HAVE_OPENSSL_EXT
		if (ssl_flags != php_ssl_none) {
			php_error_docref(NULL TSRMLS_CC, E_WARNING, "no SSL support in this build");
		}
		else
#endif
		stream = php_stream_sock_open_host(host, (unsigned short)port, socktype, &tv, hashkey);

		/* Preserve error */
		err = php_socket_errno();

		if (stream == NULL) {
			php_error_docref(NULL TSRMLS_CC, E_WARNING, "unable to connect to %s:%ld", host, port);
		} else if (context) {
			php_stream_context_set(stream, context);
		}
		
#ifdef HAVE_OPENSSL_EXT
		if (stream && ssl_flags != php_ssl_none) {
			int ssl_ret = FAILURE;
			switch(ssl_flags)	{
				case php_ssl_v23:
					ssl_ret = php_stream_sock_ssl_activate_with_method(stream, 1, SSLv23_client_method(), NULL TSRMLS_CC);
					break;
				case php_ssl_tls:
					ssl_ret = php_stream_sock_ssl_activate_with_method(stream, 1, TLSv1_client_method(), NULL TSRMLS_CC);
					break;
				default:
					/* unknown ?? */
					break;
			}
			if (ssl_ret == FAILURE) {
				php_error_docref(NULL TSRMLS_CC, E_WARNING, "failed to activate SSL mode %d", ssl_flags);
				php_stream_close(stream);
				stream = NULL;
			}
		}
#endif
		
	} else {
		/* FIXME: Win32 - this probably does not return sensible errno and errstr */
		stream = php_stream_sock_open_unix(host, host_len, hashkey, &tv);
		err = php_socket_errno();
	}

	if (hashkey)
		efree(hashkey);
	
	if (stream == NULL)	{
		if (zerrno) {
			zval_dtor(zerrno);
			ZVAL_LONG(zerrno, err);
		}
		if (zerrstr) {
			char *buf = php_socket_strerror(err, NULL, 0);

			/* no need to dup; we would only need to efree buf anyway */
			zval_dtor(zerrstr);
			ZVAL_STRING(zerrstr, buf, 0);
		}
		RETURN_FALSE;
	}
	
	if (zcontext) {
		zend_list_addref(Z_RESVAL_P(zcontext));
	}
	php_stream_to_zval(stream, return_value);
}
Beispiel #17
0
PHP_METHOD(air_view, render){
	AIR_INIT_THIS;

	char *tpl_str;
	int tpl_len = 0;
	zend_bool ret_res = 0;
	if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|b", &tpl_str, &tpl_len, &ret_res) == FAILURE)
	{
		RETURN_FALSE;
	}

	smart_str ss_path = {0};
	if(tpl_str[0] != '/'){
		zval root_path;
		if(zend_get_constant(ZEND_STRL("ROOT_PATH"), &root_path) == FAILURE){
			php_error_docref(NULL TSRMLS_CC, E_ERROR,  "ROOT_PATH not defined");
		}
		smart_str_appendl(&ss_path, Z_STRVAL(root_path), Z_STRLEN(root_path));
		smart_str_appendc(&ss_path, '/');
		zval_dtor(&root_path);

		zval *tmp = NULL;
		zval **tmp_pp;
		zval *config = zend_read_property(air_view_ce, getThis(), ZEND_STRL("_config"), 0 TSRMLS_CC);
		if(config != NULL && Z_TYPE_P(config) == IS_ARRAY
				&& zend_hash_find(Z_ARRVAL_P(config), ZEND_STRL("path"), (void **)&tmp_pp) == SUCCESS){
			smart_str_appendl(&ss_path, Z_STRVAL_PP(tmp_pp), Z_STRLEN_PP(tmp_pp));
		}else{
			zval *app_conf;
			zval *view_conf;
			if(air_config_get(NULL, ZEND_STRS("app"), &app_conf TSRMLS_CC) == FAILURE){
			}
			if(air_config_get(NULL, ZEND_STRS("app"), &app_conf TSRMLS_CC) == FAILURE){
				AIR_NEW_EXCEPTION(1, "@error config: app");
			}
			zval *app_path = NULL;
			if(air_config_get(app_conf, ZEND_STRS("path"), &app_path) == FAILURE){
				AIR_NEW_EXCEPTION(1, "@error config: app.path");
			}
			zval *view_path = NULL;
			if(air_config_path_get(app_conf, ZEND_STRS("view.path"), &view_path) == FAILURE){
				AIR_NEW_EXCEPTION(1, "@view config not found");
			}
			smart_str_appendl(&ss_path, Z_STRVAL_P(app_path), Z_STRLEN_P(app_path));
			smart_str_appendc(&ss_path, '/');
			smart_str_appendl(&ss_path, Z_STRVAL_P(view_path), Z_STRLEN_P(view_path));
		}
		smart_str_appendc(&ss_path, '/');
	}
	smart_str_appendl(&ss_path, tpl_str, tpl_len);
	smart_str_0(&ss_path);

	//构造运行时所需基本变量
	HashTable *origin_symbol_table = NULL;
	zval *output_handler = NULL;
	long chunk_size = 0;
	long flags = PHP_OUTPUT_HANDLER_STDFLAGS;
	zval *view_ret = NULL;

	//尝试缓存当前符号表
	if(EG(active_symbol_table)){
		origin_symbol_table = EG(active_symbol_table);
	}

	if (ret_res) {
		MAKE_STD_ZVAL(view_ret);
		if(php_output_start_user(output_handler, chunk_size, flags TSRMLS_CC) == FAILURE)
		{
			php_error_docref("ref.outcontrol" TSRMLS_CC, E_NOTICE, "failed to create buffer");
			RETURN_FALSE;
		}
	}
	ALLOC_HASHTABLE(EG(active_symbol_table));
	zval *data = zend_read_property(air_view_ce, getThis(), ZEND_STRL("_data"), 0 TSRMLS_CC);
	zend_hash_init(EG(active_symbol_table), 0, NULL, ZVAL_PTR_DTOR, 0);
	//将当前的模板变量放到符号表去
	ZEND_SET_SYMBOL_WITH_LENGTH(EG(active_symbol_table), "var", 4, data, Z_REFCOUNT_P(data) + 1, PZVAL_IS_REF(data));
	if(air_loader_include_file(ss_path.c TSRMLS_CC) == FAILURE){
		air_throw_exception_ex(1, "tpl %s render failed!\n", ss_path.c);
		return ;
	}

	if(ret_res){
		php_output_get_contents(view_ret TSRMLS_CC);
		php_output_discard(TSRMLS_C);
		RETVAL_ZVAL(view_ret, 1, 0);
		zval_ptr_dtor(&view_ret);
	}

	zend_hash_destroy(EG(active_symbol_table));
	FREE_HASHTABLE(EG(active_symbol_table));
	EG(active_symbol_table) = origin_symbol_table;

	smart_str_free(&ss_path);
}
PHP_COUCHBASE_LOCAL
void php_couchbase_get_impl(INTERNAL_FUNCTION_PARAMETERS,
							int multi,
							int oo,
							int lock,
							int touch)
{
	char *key, **keys;
	long *klens, klen = 0;
	int	 nkey = 0;
	long flag = 0;
	lcb_time_t exp = {0};
	long expiry = 0;
	zval *res, *cas_token = NULL;
	int argflags;
	lcb_error_t retval;
	php_couchbase_res *couchbase_res;
	php_couchbase_ctx *ctx;

	argflags = oo ? PHP_COUCHBASE_ARG_F_OO : PHP_COUCHBASE_ARG_F_FUNCTIONAL;

	if (multi) {
		zval *akeys;
		zval **ppzval;
		zend_bool preserve_order;
		int i;

		if (lock) {
			PHP_COUCHBASE_GET_PARAMS_WITH_ZV(res, couchbase_res, argflags,
											 "az|ll",
											 &akeys, &cas_token,
											 &flag, &expiry);
		} else if (touch) {
			PHP_COUCHBASE_GET_PARAMS_WITH_ZV(res, couchbase_res, argflags,
											 "al|z",
											 &akeys, &expiry, &cas_token);
		} else {
			PHP_COUCHBASE_GET_PARAMS_WITH_ZV(res, couchbase_res, argflags,
											 "a|zl",
											 &akeys, &cas_token, &flag);
		}

		nkey = zend_hash_num_elements(Z_ARRVAL_P(akeys));
		keys = ecalloc(nkey, sizeof(char *));
		klens = ecalloc(nkey, sizeof(long));
		preserve_order = (flag & COUCHBASE_GET_PRESERVE_ORDER);

		array_init(return_value);

		for (i = 0, zend_hash_internal_pointer_reset(Z_ARRVAL_P(akeys));
				zend_hash_has_more_elements(Z_ARRVAL_P(akeys)) == SUCCESS;
				zend_hash_move_forward(Z_ARRVAL_P(akeys)), i++) {
			if (zend_hash_get_current_data(Z_ARRVAL_P(akeys), (void **)&ppzval) == FAILURE) {
				nkey--;
				continue;
			}

			if (IS_ARRAY != Z_TYPE_PP(ppzval)) {
				convert_to_string_ex(ppzval);
			}

			if (!Z_STRLEN_PP(ppzval)) {
				nkey--;
				continue;
			}

			if (couchbase_res->prefix_key_len) {
				klens[i] = spprintf(&(keys[i]), 0, "%s_%s", couchbase_res->prefix_key, Z_STRVAL_PP(ppzval));
			} else {
				keys[i] = Z_STRVAL_PP(ppzval);
				klens[i] = Z_STRLEN_PP(ppzval);
			}

			if (preserve_order) {
				add_assoc_null_ex(return_value, keys[i], klens[i] + 1);
			}
		}

		if (!nkey) {
			efree(keys);
			efree(klens);
			return;
		}

		if (cas_token && IS_ARRAY != Z_TYPE_P(cas_token)) {
			zval_dtor(cas_token);
			array_init(cas_token);
		}
	} else {
		if (lock) {
			PHP_COUCHBASE_GET_PARAMS_WITH_ZV(res, couchbase_res, argflags,
											 "sz|l", &key, &klen,
											 &cas_token, &expiry);
		} else if (touch) {
			PHP_COUCHBASE_GET_PARAMS_WITH_ZV(res, couchbase_res, argflags,
											 "sl|z", &key, &klen, &expiry,
											 &cas_token);
		} else {
			PHP_COUCHBASE_GET_PARAMS_WITH_ZV(res, couchbase_res, argflags,
											 "s|z", &key, &klen,
											 &cas_token);
		}

		if (!klen) {
			return;
		}

		nkey = 1;
		if (couchbase_res->prefix_key_len) {
			klen = spprintf(&key, 0, "%s_%s", couchbase_res->prefix_key, key);
		}
		keys = &key;
		klens = &klen;

		if (cas_token) {
			zval_dtor(cas_token);
			ZVAL_NULL(cas_token);
		}
	}
	{
		lcb_get_cmd_t **commands = ecalloc(nkey, sizeof(lcb_get_cmd_t *));
		int ii;

		if (expiry) {
			exp = pcbc_check_expiry(expiry);
		}

		for (ii = 0; ii < nkey; ++ii) {
			lcb_get_cmd_t *cmd = ecalloc(1, sizeof(lcb_get_cmd_t));
			commands[ii] = cmd;
			cmd->v.v0.key = keys[ii];
			cmd->v.v0.nkey = klens[ii];
			cmd->v.v0.lock = (int)lock;
			cmd->v.v0.exptime = exp; /* NB: this assumes sizeof(lcb_time_t) == sizeof(long) */
		}

		ctx = ecalloc(1, sizeof(php_couchbase_ctx));
		ctx->res = couchbase_res;
		ctx->rv	 = return_value;
		ctx->cas = cas_token;

		retval = lcb_get(couchbase_res->handle, ctx,
						 nkey, (const lcb_get_cmd_t * const *)commands);
		for (ii = 0; ii < nkey; ++ii) {
			efree(commands[ii]);
		}
		efree(commands);

		if (LCB_SUCCESS != retval) {
			if (couchbase_res->prefix_key_len) {
				int i;
				for (i = 0; i < nkey; i++) {
					efree(keys[i]);
				}
			}
			if (multi) {
				efree(keys);
				efree(klens);
				zval_dtor(return_value);
			}
			efree(ctx);

			couchbase_report_error(INTERNAL_FUNCTION_PARAM_PASSTHRU, oo,
								   cb_lcb_exception,
								   "Failed to schedule get request: %s",
								   lcb_strerror(couchbase_res->handle, retval));
			return;
		}

		couchbase_res->seqno += nkey;
		pcbc_start_loop(couchbase_res);
		if (LCB_SUCCESS != ctx->res->rc) {
			if (LCB_KEY_ENOENT != ctx->res->rc) {
				couchbase_report_error(INTERNAL_FUNCTION_PARAM_PASSTHRU, oo,
									   cb_lcb_exception,
									   "Failed to get a value from server: %s",
									   lcb_strerror(couchbase_res->handle,
													ctx->res->rc));
			}
		}
		efree(ctx);
		if (couchbase_res->prefix_key_len) {
			int i;
			for (i = 0; i < nkey; i++) {
				efree(keys[i]);
			}
		}
		if (multi) {
			efree(keys);
			efree(klens);
		}
	}
}
Beispiel #19
0
void zend_optimizer_update_op2_const(zend_op_array *op_array,
                                     zend_op       *opline,
                                     zval          *val)
{
	ZEND_OP2_TYPE(opline) = IS_CONST;
	if (opline->opcode == ZEND_INIT_FCALL) {
		zend_str_tolower(Z_STRVAL_P(val), Z_STRLEN_P(val));
		opline->op2.constant = zend_optimizer_add_literal(op_array, val);
		zend_string_hash_val(Z_STR(ZEND_OP2_LITERAL(opline)));
		Z_CACHE_SLOT(op_array->literals[opline->op2.constant]) = op_array->last_cache_slot++;
		return;
	}
	opline->op2.constant = zend_optimizer_add_literal(op_array, val);
	if (Z_TYPE_P(val) == IS_STRING) {
		zend_string_hash_val(Z_STR(ZEND_OP2_LITERAL(opline)));
		switch (opline->opcode) {
			case ZEND_FETCH_R:
			case ZEND_FETCH_W:
			case ZEND_FETCH_RW:
			case ZEND_FETCH_IS:
			case ZEND_FETCH_UNSET:
			case ZEND_FETCH_FUNC_ARG:
			case ZEND_FETCH_CLASS:
			case ZEND_INIT_FCALL_BY_NAME:
			/*case ZEND_INIT_NS_FCALL_BY_NAME:*/
			case ZEND_UNSET_VAR:
			case ZEND_ISSET_ISEMPTY_VAR:
			case ZEND_ADD_INTERFACE:
			case ZEND_ADD_TRAIT:
			case ZEND_INSTANCEOF:
				Z_CACHE_SLOT(op_array->literals[opline->op2.constant]) = op_array->last_cache_slot++;
				zend_str_tolower(Z_STRVAL_P(val), Z_STRLEN_P(val));
				zend_optimizer_add_literal(op_array, val);
				zend_string_hash_val(Z_STR(op_array->literals[opline->op2.constant+1]));
				break;
			case ZEND_INIT_METHOD_CALL:
			case ZEND_INIT_STATIC_METHOD_CALL:
				zend_str_tolower(Z_STRVAL_P(val), Z_STRLEN_P(val));
				zend_optimizer_add_literal(op_array, val);
				zend_string_hash_val(Z_STR(op_array->literals[opline->op2.constant+1]));
				/* break missing intentionally */
			/*case ZEND_FETCH_CONSTANT:*/
			case ZEND_ASSIGN_OBJ:
			case ZEND_FETCH_OBJ_R:
			case ZEND_FETCH_OBJ_W:
			case ZEND_FETCH_OBJ_RW:
			case ZEND_FETCH_OBJ_IS:
			case ZEND_FETCH_OBJ_UNSET:
			case ZEND_FETCH_OBJ_FUNC_ARG:
			case ZEND_UNSET_OBJ:
			case ZEND_PRE_INC_OBJ:
			case ZEND_PRE_DEC_OBJ:
			case ZEND_POST_INC_OBJ:
			case ZEND_POST_DEC_OBJ:
			case ZEND_ISSET_ISEMPTY_PROP_OBJ:
				Z_CACHE_SLOT(op_array->literals[opline->op2.constant]) = op_array->last_cache_slot;
				op_array->last_cache_slot += 2;
				break;
			case ZEND_ASSIGN_ADD:
			case ZEND_ASSIGN_SUB:
			case ZEND_ASSIGN_MUL:
			case ZEND_ASSIGN_DIV:
			case ZEND_ASSIGN_MOD:
			case ZEND_ASSIGN_SL:
			case ZEND_ASSIGN_SR:
			case ZEND_ASSIGN_CONCAT:
			case ZEND_ASSIGN_BW_OR:
			case ZEND_ASSIGN_BW_AND:
			case ZEND_ASSIGN_BW_XOR:
				if (opline->extended_value == ZEND_ASSIGN_OBJ) {
					Z_CACHE_SLOT(op_array->literals[opline->op2.constant]) = op_array->last_cache_slot;
					op_array->last_cache_slot += 2;
				}
				break;
			case ZEND_OP_DATA:
				if ((opline-1)->opcode == ZEND_ASSIGN_DIM ||
				    ((opline-1)->extended_value == ZEND_ASSIGN_DIM &&
				     ((opline-1)->opcode == ZEND_ASSIGN_ADD ||
				     (opline-1)->opcode == ZEND_ASSIGN_SUB ||
				     (opline-1)->opcode == ZEND_ASSIGN_MUL ||
				     (opline-1)->opcode == ZEND_ASSIGN_DIV ||
				     (opline-1)->opcode == ZEND_ASSIGN_MOD ||
				     (opline-1)->opcode == ZEND_ASSIGN_SL ||
				     (opline-1)->opcode == ZEND_ASSIGN_SR ||
				     (opline-1)->opcode == ZEND_ASSIGN_CONCAT ||
				     (opline-1)->opcode == ZEND_ASSIGN_BW_OR ||
				     (opline-1)->opcode == ZEND_ASSIGN_BW_AND ||
				     (opline-1)->opcode == ZEND_ASSIGN_BW_XOR))) {
					goto check_numeric;
				}
				break;
			case ZEND_ISSET_ISEMPTY_DIM_OBJ:
			case ZEND_ADD_ARRAY_ELEMENT:
			case ZEND_INIT_ARRAY:
			case ZEND_UNSET_DIM:
			case ZEND_FETCH_DIM_R:
			case ZEND_FETCH_DIM_W:
			case ZEND_FETCH_DIM_RW:
			case ZEND_FETCH_DIM_IS:
			case ZEND_FETCH_DIM_FUNC_ARG:
			case ZEND_FETCH_DIM_UNSET:
			case ZEND_FETCH_LIST:
check_numeric:
				{
					zend_ulong index;

					if (ZEND_HANDLE_NUMERIC(Z_STR_P(val), index)) {
						zval_dtor(val);
						ZVAL_LONG(val, index);
						op_array->literals[opline->op2.constant] = *val;
		        	}
				}
				break;
			default:
				break;
		}
	}
}
PHP_COUCHBASE_LOCAL
void php_couchbase_fetch_impl(INTERNAL_FUNCTION_PARAMETERS, int multi, int oo) /* {{{ */
{
	php_couchbase_res *couchbase_res;
	int argflags;

	if (oo) {
		argflags = PHP_COUCHBASE_ARG_F_OO;
	} else {
		argflags = PHP_COUCHBASE_ARG_F_FUNCTIONAL;
	}

	argflags |= PHP_COUCHBASE_ARG_F_ASYNC;

	PHP_COUCHBASE_GET_PARAMS(couchbase_res, argflags, "");

	{
		php_couchbase_ctx *ctx;

		if (!couchbase_res->async) {
			RETURN_FALSE;
		}

		ctx = couchbase_res->async_ctx;

		if (couchbase_res->async == 2) {
fetch_one: {
				char *key;
				uint key_len;
				ulong index = 0;
				zval **ppzval;
				zval *stash = (zval *)ctx->extended_value;
				if (zend_hash_num_elements(Z_ARRVAL_P(stash)) == 0) {
					couchbase_res->async = 0;
					zval_ptr_dtor(&stash);
					efree(ctx);
					couchbase_res->async_ctx = NULL;
					RETURN_NULL();
				}
				zend_hash_internal_pointer_reset(Z_ARRVAL_P(stash));
				zend_hash_get_current_data(Z_ARRVAL_P(stash), (void **)&ppzval);
				RETVAL_ZVAL(*ppzval, 1, 0);
				zend_hash_get_current_key_ex(Z_ARRVAL_P(stash), &key, &key_len, &index, 0, NULL);
				zend_hash_index_del(Z_ARRVAL_P(stash), index);
				return;
			}
		}

		array_init(return_value);
		ctx->rv = return_value;
		pcbc_start_loop(couchbase_res);
		if (!multi) {
			zval *stash;
			MAKE_STD_ZVAL(stash);
			ZVAL_ZVAL(stash, return_value, 1, 0);
			ctx->extended_value = (void *)stash;
			zval_dtor(return_value);
			couchbase_res->async = 2;
			goto fetch_one;
		} else {
			efree(ctx);
			couchbase_res->async = 0;
			couchbase_res->async_ctx = NULL;
		}
	}
}
Beispiel #21
0
static void zend_optimizer_zval_dtor_wrapper(zval *zvalue)
{
	zval_dtor(zvalue);
}
Beispiel #22
0
static void regexp_ctor(INTERNAL_FUNCTION_PARAMETERS)
{
    zval *object;
    Regexp_object *ro;
    char *pattern;
    int32_t pattern_len;
    UChar *upattern = NULL;
    int32_t upattern_len = 0;
    zval *zflags = NULL;
    uint32_t flags = 0;
    UParseError pe = { -1, -1, {0}, {0} };

    intl_error_reset(NULL TSRMLS_CC);
    object = return_value;
    if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|z", &pattern, &pattern_len, &zflags)) {
        intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, "bad arguments", 0 TSRMLS_CC);
        zval_dtor(object);
        RETURN_NULL();
    }
    if (NULL != zflags) {
        switch (Z_TYPE_P(zflags)) {
            case IS_LONG:
                flags = (uint32_t) Z_LVAL_P(zflags);
                if (0 != (flags & ~(UREGEX_CASE_INSENSITIVE|UREGEX_MULTILINE|UREGEX_DOTALL|UREGEX_COMMENTS|UREGEX_UWORD))) {
                    intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, "invalid flag", 0 TSRMLS_CC);
                    zval_dtor(object);
                    RETURN_NULL();
                }
                break;
            case IS_STRING:
            {
                const char *p;

                for (p = Z_STRVAL_P(zflags); '\0' != *p; p++) {
                    switch (*p) {
                        case 'i': flags |= UREGEX_CASE_INSENSITIVE; break;
                        case 'm': flags |= UREGEX_MULTILINE;        break;
                        case 's': flags |= UREGEX_DOTALL;           break;
                        case 'x': flags |= UREGEX_COMMENTS;         break;
                        case 'w': flags |= UREGEX_UWORD;            break;
                        default:
                            intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, "invalid modifier", 0 TSRMLS_CC);
                            zval_dtor(object);
                            RETURN_NULL();
                    }
                }
                break;
            }
            default:
                intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, "bad arguments", 0 TSRMLS_CC);
                zval_dtor(object);
                RETURN_NULL();
        }
    }
    ro = (Regexp_object *) zend_object_store_get_object(object TSRMLS_CC);
    intl_convert_utf8_to_utf16(&upattern, &upattern_len, pattern, pattern_len, REGEXP_ERROR_CODE_P(ro));
    INTL_CTOR_CHECK_STATUS(ro, "string conversion of pattern to UTF-16 failed");
    ro->uregex = uregex_open(upattern, upattern_len, flags, &pe, REGEXP_ERROR_CODE_P(ro));
    efree(upattern);
    if (U_FAILURE(REGEXP_ERROR_CODE(ro))) {
        intl_error_set_code(NULL, REGEXP_ERROR_CODE(ro) TSRMLS_CC);
        if (-1 != pe.line) {
            smart_str parse_error_str;

            parse_error_str = transliterator_parse_error_to_string(&pe);
            intl_errors_setf_custom_msg(NULL, TSRMLS_CC "unable to compile ICU regular expression, %s", parse_error_str.c);
            smart_str_free(&parse_error_str);
        } else {
            intl_error_set_custom_msg(NULL, "unable to compile ICU regular expression", 0 TSRMLS_CC);
        }
        zval_dtor(object);
        RETURN_NULL();
    }
}
Beispiel #23
0
/**
 * Generates a SELECT tag
 *
 * @param array $parameters
 * @param array $data
 */
PHP_METHOD(Phalcon_Tag_Select, selectField){

	zval *parameters, *data = NULL, *params = NULL, *eol, *id = NULL, *name, *value = NULL;
	zval *use_empty = NULL, *empty_value = NULL, *empty_text = NULL, *code;
	zval *avalue = NULL, *key = NULL, *close_option, *options = NULL, *using;
	zval *resultset_options, *array_options, *escaped;
	HashTable *ah0;
	HashPosition hp0;
	zval **hd;

	PHALCON_MM_GROW();

	phalcon_fetch_params(1, 1, 1, &parameters, &data);
	
	if (!data) {
		PHALCON_INIT_VAR(data);
	}
	
	if (Z_TYPE_P(parameters) != IS_ARRAY) { 
		PHALCON_INIT_VAR(params);
		array_init_size(params, 2);
		phalcon_array_append(&params, parameters, PH_SEPARATE);
		phalcon_array_append(&params, data, PH_SEPARATE);
	} else {
		PHALCON_CPY_WRT(params, parameters);
	}
	
	PHALCON_INIT_VAR(eol);
	ZVAL_STRING(eol, PHP_EOL, 1);
	if (!phalcon_array_isset_long(params, 0)) {
		PHALCON_OBS_VAR(id);
		phalcon_array_fetch_string(&id, params, SL("id"), PH_NOISY);
		phalcon_array_update_long(&params, 0, &id, PH_COPY | PH_SEPARATE);
	}
	
	PHALCON_OBS_NVAR(id);
	phalcon_array_fetch_long(&id, params, 0, PH_NOISY);
	if (!phalcon_array_isset_string(params, SS("name"))) {
		phalcon_array_update_string(&params, SL("name"), &id, PH_COPY | PH_SEPARATE);
	} else {
		PHALCON_OBS_VAR(name);
		phalcon_array_fetch_string(&name, params, SL("name"), PH_NOISY);
		if (!zend_is_true(name)) {
			phalcon_array_update_string(&params, SL("name"), &id, PH_COPY | PH_SEPARATE);
		}
	}
	
	/** 
	 * Automatically assign the id if the name is not an array
	 */
	if (!phalcon_memnstr_str(id, SL("["))) {
		if (!phalcon_array_isset_string(params, SS("id"))) {
			phalcon_array_update_string(&params, SL("id"), &id, PH_COPY | PH_SEPARATE);
		}
	}
	
	if (!phalcon_array_isset_string(params, SS("value"))) {
		PHALCON_INIT_VAR(value);
		PHALCON_CALL_STATIC_PARAMS_2(value, "phalcon\\tag", "getvalue", id, params);
	} else {
		PHALCON_OBS_NVAR(value);
		phalcon_array_fetch_string(&value, params, SL("value"), PH_NOISY);
		phalcon_array_unset_string(&params, SS("value"), PH_SEPARATE);
	}
	
	PHALCON_INIT_VAR(use_empty);
	ZVAL_BOOL(use_empty, 0);
	if (phalcon_array_isset_string(params, SS("useEmpty"))) {
		if (!phalcon_array_isset_string(params, SS("emptyValue"))) {
			PHALCON_INIT_VAR(empty_value);
			ZVAL_STRING(empty_value, "", 1);
		} else {
			PHALCON_OBS_NVAR(empty_value);
			phalcon_array_fetch_string(&empty_value, params, SL("emptyValue"), PH_NOISY);
			phalcon_array_unset_string(&params, SS("emptyValue"), PH_SEPARATE);
		}
		if (!phalcon_array_isset_string(params, SS("emptyText"))) {
			PHALCON_INIT_VAR(empty_text);
			ZVAL_STRING(empty_text, "Choose...", 1);
		} else {
			PHALCON_OBS_NVAR(empty_text);
			phalcon_array_fetch_string(&empty_text, params, SL("emptyText"), PH_NOISY);
			phalcon_array_unset_string(&params, SS("emptyText"), PH_SEPARATE);
		}
	
		PHALCON_OBS_NVAR(use_empty);
		phalcon_array_fetch_string(&use_empty, params, SL("useEmpty"), PH_NOISY);
		phalcon_array_unset_string(&params, SS("useEmpty"), PH_SEPARATE);
	}
	
	PHALCON_INIT_VAR(code);
	ZVAL_STRING(code, "<select", 1);
	if (Z_TYPE_P(params) == IS_ARRAY) { 
	
		phalcon_is_iterable(params, &ah0, &hp0, 0, 0);
	
		PHALCON_INIT_VAR(escaped);

		while (zend_hash_get_current_data_ex(ah0, (void**) &hd, &hp0) == SUCCESS) {
	
			PHALCON_GET_HKEY(key, ah0, hp0);
			PHALCON_GET_HVALUE(avalue);
	
			if (Z_TYPE_P(key) != IS_LONG) {
				if (Z_TYPE_P(avalue) != IS_ARRAY) { 
					phalcon_htmlspecialchars(escaped, avalue, NULL, NULL TSRMLS_CC);
					PHALCON_SCONCAT_SVSVS(code, " ", key, "=\"", escaped, "\"");
					zval_dtor(escaped);
					ZVAL_NULL(escaped);
				}
			}
	
			zend_hash_move_forward_ex(ah0, &hp0);
		}
	
	}
	
	PHALCON_SCONCAT_SV(code, ">", eol);
	
	PHALCON_INIT_VAR(close_option);
	PHALCON_CONCAT_SV(close_option, "</option>", eol);
	if (zend_is_true(use_empty)) {
		/** 
		 * Create an empty value
		 */
		PHALCON_SCONCAT_SVSVV(code, "\t<option value=\"", empty_value, "\">", empty_text, close_option);
		phalcon_array_unset_string(&params, SS("useEmpty"), PH_SEPARATE);
	}
	
	if (phalcon_array_isset_long(params, 1)) {
		PHALCON_OBS_VAR(options);
		phalcon_array_fetch_long(&options, params, 1, PH_NOISY);
	} else {
		PHALCON_CPY_WRT(options, data);
	}
	
	if (Z_TYPE_P(options) == IS_OBJECT) {
	
		/** 
		 * The options is a resultset
		 */
		if (!phalcon_array_isset_string(params, SS("using"))) {
			PHALCON_THROW_EXCEPTION_STR(phalcon_tag_exception_ce, "The 'using' parameter is required");
			return;
		} else {
			PHALCON_OBS_VAR(using);
			phalcon_array_fetch_string(&using, params, SL("using"), PH_NOISY);
			if (Z_TYPE_P(using) != IS_ARRAY) { 
				if (Z_TYPE_P(using) != IS_OBJECT) {
					PHALCON_THROW_EXCEPTION_STR(phalcon_tag_exception_ce, "The 'using' parameter should be an Array");
					return;
				}
			}
		}
	
		/** 
		 * Create the SELECT's option from a resultset
		 */
		PHALCON_INIT_VAR(resultset_options);
		PHALCON_CALL_SELF_PARAMS_4(resultset_options, this_ptr, "_optionsfromresultset", options, using, value, close_option);
		phalcon_concat_self(&code, resultset_options TSRMLS_CC);
	} else {
		if (Z_TYPE_P(options) == IS_ARRAY) { 
Beispiel #24
0
/**
 * Perform escaping of non-alphanumeric characters to different formats
 */
void phalcon_escape_multi(zval *return_value, zval *param, const char *escape_char, unsigned int escape_length, char escape_extra, int use_whitelist) {

	int i;
	zval copy;
	smart_str escaped_str = {0};
	char *hex;
	int big_endian_long_map[4];
	int use_copy = 0;
	int issigned = 0;
	long int value;

	if (Z_TYPE_P(param) != IS_STRING) {
		zend_make_printable_zval(param, &copy, &use_copy);
		if (use_copy) {
			param = &copy;
		}
	}

	if (Z_STRLEN_P(param) <= 0) {
		RETURN_FALSE;
	}

	/**
	 * This is how the big_ending_long_map is calculated as in 'pack'
	 */
#ifndef WORDS_BIGENDIAN
	big_endian_long_map[0] = 3;
	big_endian_long_map[1] = 2;
	big_endian_long_map[2] = 1;
	big_endian_long_map[3] = 0;
#else
	big_endian_long_map[0] = 0;
	big_endian_long_map[1] = 1;
	big_endian_long_map[2] = 2;
	big_endian_long_map[3] = 3;
#endif

	/**
	 * The input must be a valid UTF-32 string
	 */
	if ((Z_STRLEN_P(param) % 4) != 0) {
		RETURN_FALSE;
	}

	for (i = 0; i < Z_STRLEN_P(param); i += 4) {

		issigned = Z_STRVAL_P(param)[i] & 0x80;

		value = 0;
		if (sizeof(long) > 4 && issigned) {
			value = ~INT_MAX;
		}

		value |= phalcon_unpack(&Z_STRVAL_P(param)[i], 4, issigned, big_endian_long_map);
		if (sizeof(long) > 4) {
			value = (unsigned int) value;
		}

		/**
		 * CSS 2.1 section 4.1.3: "It is undefined in CSS 2.1 what happens if a
		 * style sheet does contain a character with Unicode codepoint zero."
		 */
		if (value == '\0') {
			RETURN_FALSE;
		}

		/**
		 * Alphanumeric characters are not escaped
		 */
		if (value > 32 && value < 127 && isalnum(value)) {
			smart_str_appendc(&escaped_str, (unsigned char) value);
			continue;
		}

		/**
		 * Chararters in the whitelist are left as they are
		 */
		if (use_whitelist) {
			switch (value) {
				case ' ':
				case '/':
				case '*':
				case '+':
				case '-':
				case '\t':
				case '\n':
				case '^':
				case '$':
				case '!':
				case '?':
				case '\\':
				case '#':
				case '}':
				case '{':
				case ')':
				case '(':
				case ']':
				case '[':
				case '.':
				case ',':
				case ':':
				case ';':
				case '_':
				case '|':
				case '~':
				case '`':
					smart_str_appendc(&escaped_str, (unsigned char) value);
					continue;
			}
		}

		/**
		 * Convert character to hexadecimal
		 */
		hex = phalcon_longtohex(value);

		/**
		 * Append the escaped character
		 */
		smart_str_appendl(&escaped_str, escape_char, escape_length);
		smart_str_appendl(&escaped_str, hex, strlen(hex));
		if (escape_extra != '\0') {
			smart_str_appendc(&escaped_str, escape_extra);
		}

		efree(hex);
	}

	if (use_copy) {
		zval_dtor(param);
	}

	smart_str_0(&escaped_str);

	if (escaped_str.c) {
		RETURN_STRINGL(escaped_str.c, escaped_str.len, 0);
	} else {
		RETURN_EMPTY_STRING();
	}

}
Beispiel #25
0
Datei: pcntl.c Projekt: 0/php-src
static void pcntl_sigwaitinfo(INTERNAL_FUNCTION_PARAMETERS, int timedwait) /* {{{ */
{
	zval            *user_set, **user_signo, *user_siginfo = NULL;
	long             tv_sec = 0, tv_nsec = 0;
	sigset_t         set;
	HashPosition     pos;
	int              signo;
	siginfo_t        siginfo;
	struct timespec  timeout;

	if (timedwait) {
		if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a|zll", &user_set, &user_siginfo, &tv_sec, &tv_nsec) == FAILURE) {
			return;
		}
	} else {
		if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a|z", &user_set, &user_siginfo) == FAILURE) {
			return;
		}
	}

	if (sigemptyset(&set) != 0) {
		PCNTL_G(last_error) = errno;
		php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", strerror(errno));
		RETURN_FALSE;
	}

	zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(user_set), &pos);
	while (zend_hash_get_current_data_ex(Z_ARRVAL_P(user_set), (void **)&user_signo, &pos) == SUCCESS)
	{
		if (Z_TYPE_PP(user_signo) != IS_LONG) {
			SEPARATE_ZVAL(user_signo);
			convert_to_long_ex(user_signo);
		}
		signo = Z_LVAL_PP(user_signo);
		if (sigaddset(&set, signo) != 0) {
			PCNTL_G(last_error) = errno;
			php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", strerror(errno));
			RETURN_FALSE;
		}
		zend_hash_move_forward_ex(Z_ARRVAL_P(user_set), &pos);
	}

	if (timedwait) {
		timeout.tv_sec  = (time_t) tv_sec;
		timeout.tv_nsec = tv_nsec;
		signo = sigtimedwait(&set, &siginfo, &timeout);
	} else {
		signo = sigwaitinfo(&set, &siginfo);
	}
	if (signo == -1 && errno != EAGAIN) {
		PCNTL_G(last_error) = errno;
		php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", strerror(errno));
	}

	/*
	 * sigtimedwait and sigwaitinfo can return 0 on success on some 
	 * platforms, e.g. NetBSD
	 */
	if (!signo && siginfo.si_signo) {
		signo = siginfo.si_signo;
	}

	if (signo > 0 && user_siginfo) {
		if (Z_TYPE_P(user_siginfo) != IS_ARRAY) {
			zval_dtor(user_siginfo);
			array_init(user_siginfo);
		} else {
			zend_hash_clean(Z_ARRVAL_P(user_siginfo));
		}
		add_assoc_long_ex(user_siginfo, "signo", sizeof("signo"), siginfo.si_signo);
		add_assoc_long_ex(user_siginfo, "errno", sizeof("errno"), siginfo.si_errno);
		add_assoc_long_ex(user_siginfo, "code",  sizeof("code"),  siginfo.si_code);
		switch(signo) {
#ifdef SIGCHLD
			case SIGCHLD:
				add_assoc_long_ex(user_siginfo,   "status", sizeof("status"), siginfo.si_status);
# ifdef si_utime
				add_assoc_double_ex(user_siginfo, "utime",  sizeof("utime"),  siginfo.si_utime);
# endif
# ifdef si_stime
				add_assoc_double_ex(user_siginfo, "stime",  sizeof("stime"),  siginfo.si_stime);
# endif
				add_assoc_long_ex(user_siginfo,   "pid",    sizeof("pid"),    siginfo.si_pid);
				add_assoc_long_ex(user_siginfo,   "uid",    sizeof("uid"),    siginfo.si_uid);
				break;
#endif
			case SIGILL:
			case SIGFPE:
			case SIGSEGV:
			case SIGBUS:
				add_assoc_double_ex(user_siginfo, "addr", sizeof("addr"), (long)siginfo.si_addr);
				break;
#ifdef SIGPOLL
			case SIGPOLL:
				add_assoc_long_ex(user_siginfo, "band", sizeof("band"), siginfo.si_band);
# ifdef si_fd
				add_assoc_long_ex(user_siginfo, "fd",   sizeof("fd"),   siginfo.si_fd);
# endif
				break;
#endif
			EMPTY_SWITCH_DEFAULT_CASE();
		}
	}
	
	RETURN_LONG(signo);
}
void zend_optimizer_compact_literals(zend_op_array *op_array, zend_optimizer_ctx *ctx)
{
    zend_op *opline, *end;
    int i, j, n, *map, cache_size;
    zval zv, *pos;
    literal_info *info;
    int l_null = -1;
    int l_false = -1;
    int l_true = -1;
    HashTable hash;
    zend_string *key = NULL;
    void *checkpoint = zend_arena_checkpoint(ctx->arena);

    if (op_array->last_literal) {
        cache_size = 0;
        info = (literal_info*)zend_arena_calloc(&ctx->arena, op_array->last_literal, sizeof(literal_info));

        /* Mark literals of specific types */
        opline = op_array->opcodes;
        end = opline + op_array->last;
        while (opline < end) {
            switch (opline->opcode) {
            case ZEND_INIT_FCALL:
                LITERAL_INFO(opline->op2.constant, LITERAL_FUNC, 1, 1, 1);
                break;
            case ZEND_INIT_FCALL_BY_NAME:
                LITERAL_INFO(opline->op2.constant, LITERAL_FUNC, 1, 1, 2);
                break;
            case ZEND_INIT_NS_FCALL_BY_NAME:
                LITERAL_INFO(opline->op2.constant, LITERAL_FUNC, 1, 1, 3);
                break;
            case ZEND_INIT_METHOD_CALL:
                if (ZEND_OP2_TYPE(opline) == IS_CONST) {
                    optimizer_literal_obj_info(
                        info,
                        opline->op1_type,
                        opline->op1,
                        opline->op2.constant,
                        LITERAL_METHOD, 2, 2,
                        op_array);
                }
                break;
            case ZEND_INIT_STATIC_METHOD_CALL:
                if (ZEND_OP1_TYPE(opline) == IS_CONST) {
                    LITERAL_INFO(opline->op1.constant, LITERAL_CLASS, 1, 1, 2);
                }
                if (ZEND_OP2_TYPE(opline) == IS_CONST) {
                    optimizer_literal_class_info(
                        info,
                        opline->op1_type,
                        opline->op1,
                        opline->op2.constant,
                        LITERAL_STATIC_METHOD, (ZEND_OP1_TYPE(opline) == IS_CONST) ? 1 : 2, 2,
                        op_array);
                }
                break;
            case ZEND_CATCH:
                LITERAL_INFO(opline->op1.constant, LITERAL_CLASS, 1, 1, 2);
                break;
            case ZEND_DEFINED:
                LITERAL_INFO(opline->op1.constant, LITERAL_CONST, 1, 1, 2);
                break;
            case ZEND_FETCH_CONSTANT:
                if (ZEND_OP1_TYPE(opline) == IS_UNUSED) {
                    if ((opline->extended_value & (IS_CONSTANT_IN_NAMESPACE|IS_CONSTANT_UNQUALIFIED)) == (IS_CONSTANT_IN_NAMESPACE|IS_CONSTANT_UNQUALIFIED)) {
                        LITERAL_INFO(opline->op2.constant, LITERAL_CONST, 1, 1, 5);
                    } else {
                        LITERAL_INFO(opline->op2.constant, LITERAL_CONST, 1, 1, 3);
                    }
                } else {
                    if (ZEND_OP1_TYPE(opline) == IS_CONST) {
                        LITERAL_INFO(opline->op1.constant, LITERAL_CLASS, 1, 1, 2);
                    }
                    optimizer_literal_class_info(
                        info,
                        opline->op1_type,
                        opline->op1,
                        opline->op2.constant,
                        LITERAL_CLASS_CONST, (ZEND_OP1_TYPE(opline) == IS_CONST) ? 1 : 2, 1,
                        op_array);
                }
                break;
            case ZEND_FETCH_R:
            case ZEND_FETCH_W:
            case ZEND_FETCH_RW:
            case ZEND_FETCH_IS:
            case ZEND_FETCH_UNSET:
            case ZEND_FETCH_FUNC_ARG:
            case ZEND_UNSET_VAR:
            case ZEND_ISSET_ISEMPTY_VAR:
                if (ZEND_OP2_TYPE(opline) == IS_UNUSED) {
                    if (ZEND_OP1_TYPE(opline) == IS_CONST) {
                        LITERAL_INFO(opline->op1.constant, LITERAL_VALUE, 1, 0, 1);
                    }
                } else {
                    if (ZEND_OP2_TYPE(opline) == IS_CONST) {
                        LITERAL_INFO(opline->op2.constant, LITERAL_CLASS, 1, 1, 2);
                    }
                    if (ZEND_OP1_TYPE(opline) == IS_CONST) {
                        optimizer_literal_class_info(
                            info,
                            opline->op2_type,
                            opline->op2,
                            opline->op1.constant,
                            LITERAL_STATIC_PROPERTY, 2, 1,
                            op_array);
                    }
                }
                break;
            case ZEND_FETCH_CLASS:
            case ZEND_ADD_INTERFACE:
            case ZEND_ADD_TRAIT:
            case ZEND_INSTANCEOF:
                if (ZEND_OP2_TYPE(opline) == IS_CONST) {
                    LITERAL_INFO(opline->op2.constant, LITERAL_CLASS, 1, 1, 2);
                }
                break;
            case ZEND_NEW:
                if (ZEND_OP1_TYPE(opline) == IS_CONST) {
                    LITERAL_INFO(opline->op1.constant, LITERAL_CLASS, 1, 1, 2);
                }
                break;
            case ZEND_ASSIGN_OBJ:
            case ZEND_FETCH_OBJ_R:
            case ZEND_FETCH_OBJ_W:
            case ZEND_FETCH_OBJ_RW:
            case ZEND_FETCH_OBJ_IS:
            case ZEND_FETCH_OBJ_UNSET:
            case ZEND_FETCH_OBJ_FUNC_ARG:
            case ZEND_UNSET_OBJ:
            case ZEND_PRE_INC_OBJ:
            case ZEND_PRE_DEC_OBJ:
            case ZEND_POST_INC_OBJ:
            case ZEND_POST_DEC_OBJ:
            case ZEND_ISSET_ISEMPTY_PROP_OBJ:
                if (ZEND_OP2_TYPE(opline) == IS_CONST) {
                    optimizer_literal_obj_info(
                        info,
                        opline->op1_type,
                        opline->op1,
                        opline->op2.constant,
                        LITERAL_PROPERTY, 2, 1,
                        op_array);
                }
                break;
            case ZEND_ASSIGN_ADD:
            case ZEND_ASSIGN_SUB:
            case ZEND_ASSIGN_MUL:
            case ZEND_ASSIGN_DIV:
            case ZEND_ASSIGN_MOD:
            case ZEND_ASSIGN_SL:
            case ZEND_ASSIGN_SR:
            case ZEND_ASSIGN_CONCAT:
            case ZEND_ASSIGN_BW_OR:
            case ZEND_ASSIGN_BW_AND:
            case ZEND_ASSIGN_BW_XOR:
                if (ZEND_OP2_TYPE(opline) == IS_CONST) {
                    if (opline->extended_value == ZEND_ASSIGN_OBJ) {
                        optimizer_literal_obj_info(
                            info,
                            opline->op1_type,
                            opline->op1,
                            opline->op2.constant,
                            LITERAL_PROPERTY, 2, 1,
                            op_array);
                    } else {
                        LITERAL_INFO(opline->op2.constant, LITERAL_VALUE, 1, 0, 1);
                    }
                }
                break;
            case ZEND_BIND_GLOBAL:
                LITERAL_INFO(opline->op2.constant, LITERAL_GLOBAL, 0, 1, 1);
                break;
            case ZEND_RECV_INIT:
                LITERAL_INFO(opline->op2.constant, LITERAL_VALUE, 0, 0, 1);
                if (Z_CACHE_SLOT(op_array->literals[opline->op2.constant]) != -1) {
                    Z_CACHE_SLOT(op_array->literals[opline->op2.constant]) = cache_size;
                    cache_size += sizeof(void *);
                }
                break;
            case ZEND_RECV:
            case ZEND_VERIFY_RETURN_TYPE:
                if (opline->op2.num != -1) {
                    opline->op2.num = cache_size;
                    cache_size += sizeof(void *);
                }
            default:
                if (ZEND_OP1_TYPE(opline) == IS_CONST) {
                    LITERAL_INFO(opline->op1.constant, LITERAL_VALUE, 1, 0, 1);
                }
                if (ZEND_OP2_TYPE(opline) == IS_CONST) {
                    LITERAL_INFO(opline->op2.constant, LITERAL_VALUE, 1, 0, 1);
                }
                break;
            }
            opline++;
        }

#if DEBUG_COMPACT_LITERALS
        {
            int i, use_copy;
            fprintf(stderr, "File %s func %s\n", op_array->filename->val,
                    op_array->function_name ? op_array->function_name->val : "main");
            fprintf(stderr, "Literlas table size %d\n", op_array->last_literal);

            for (i = 0; i < op_array->last_literal; i++) {
                zval zv;
                ZVAL_COPY_VALUE(&zv, op_array->literals + i);
                use_copy = zend_make_printable_zval(op_array->literals + i, &zv);
                fprintf(stderr, "Literal %d, val (%d):%s\n", i, Z_STRLEN(zv), Z_STRVAL(zv));
                if (use_copy) {
                    zval_dtor(&zv);
                }
            }
            fflush(stderr);
        }
#endif

        /* Merge equal constants */
        j = 0;
        zend_hash_init(&hash, op_array->last_literal, NULL, NULL, 0);
        map = (int*)zend_arena_alloc(&ctx->arena, op_array->last_literal * sizeof(int));
        memset(map, 0, op_array->last_literal * sizeof(int));
        for (i = 0; i < op_array->last_literal; i++) {
            if (!info[i].flags) {
                /* unsed literal */
                zval_dtor(&op_array->literals[i]);
                continue;
            }
            switch (Z_TYPE(op_array->literals[i])) {
            case IS_NULL:
                /* Only checking MAY_MERGE for IS_NULL here
                 * is because only IS_NULL can be default value for class type hinting(RECV_INIT). */
                if ((info[i].flags & LITERAL_MAY_MERGE)) {
                    if (l_null < 0) {
                        l_null = j;
                        if (i != j) {
                            op_array->literals[j] = op_array->literals[i];
                            info[j] = info[i];
                        }
                        j++;
                    }
                    map[i] = l_null;
                } else {
                    map[i] = j;
                    if (i != j) {
                        op_array->literals[j] = op_array->literals[i];
                        info[j] = info[i];
                    }
                    j++;
                }
                break;
            case IS_FALSE:
                if (l_false < 0) {
                    l_false = j;
                    if (i != j) {
                        op_array->literals[j] = op_array->literals[i];
                        info[j] = info[i];
                    }
                    j++;
                }
                map[i] = l_false;
                break;
            case IS_TRUE:
                if (l_true < 0) {
                    l_true = j;
                    if (i != j) {
                        op_array->literals[j] = op_array->literals[i];
                        info[j] = info[i];
                    }
                    j++;
                }
                map[i] = l_true;
                break;
            case IS_LONG:
                if ((pos = zend_hash_index_find(&hash, Z_LVAL(op_array->literals[i]))) != NULL) {
                    map[i] = Z_LVAL_P(pos);
                } else {
                    map[i] = j;
                    ZVAL_LONG(&zv, j);
                    zend_hash_index_add_new(&hash, Z_LVAL(op_array->literals[i]), &zv);
                    if (i != j) {
                        op_array->literals[j] = op_array->literals[i];
                        info[j] = info[i];
                    }
                    j++;
                }
                break;
            case IS_DOUBLE:
                if ((pos = zend_hash_str_find(&hash, (char*)&Z_DVAL(op_array->literals[i]), sizeof(double))) != NULL) {
                    map[i] = Z_LVAL_P(pos);
                } else {
                    map[i] = j;
                    ZVAL_LONG(&zv, j);
                    zend_hash_str_add(&hash, (char*)&Z_DVAL(op_array->literals[i]), sizeof(double), &zv);
                    if (i != j) {
                        op_array->literals[j] = op_array->literals[i];
                        info[j] = info[i];
                    }
                    j++;
                }
                break;
            case IS_STRING:
            case IS_CONSTANT:
                if (info[i].flags & LITERAL_MAY_MERGE) {
                    if (info[i].flags & LITERAL_EX_OBJ) {
                        int key_len = MAX_LENGTH_OF_LONG + sizeof("->") + Z_STRLEN(op_array->literals[i]);
                        key = zend_string_alloc(key_len, 0);
                        key->len = snprintf(key->val, key->len-1, "%d->%s", info[i].u.num, Z_STRVAL(op_array->literals[i]));
                    } else if (info[i].flags & LITERAL_EX_CLASS) {
                        int key_len;
                        zval *class_name = &op_array->literals[(info[i].u.num < i) ? map[info[i].u.num] : info[i].u.num];
                        key_len = Z_STRLEN_P(class_name) + sizeof("::") + Z_STRLEN(op_array->literals[i]);
                        key = zend_string_alloc(key_len, 0);
                        memcpy(key->val, Z_STRVAL_P(class_name), Z_STRLEN_P(class_name));
                        memcpy(key->val + Z_STRLEN_P(class_name), "::", sizeof("::") - 1);
                        memcpy(key->val + Z_STRLEN_P(class_name) + sizeof("::") - 1,
                               Z_STRVAL(op_array->literals[i]),
                               Z_STRLEN(op_array->literals[i]) + 1);
                    } else {
                        key = zend_string_init(Z_STRVAL(op_array->literals[i]), Z_STRLEN(op_array->literals[i]), 0);
                    }
                    key->h = zend_hash_func(key->val, key->len);
                    key->h += info[i].flags;
                }
                if ((info[i].flags & LITERAL_MAY_MERGE) &&
                        (pos = zend_hash_find(&hash, key)) != NULL &&
                        Z_TYPE(op_array->literals[i]) == Z_TYPE(op_array->literals[Z_LVAL_P(pos)]) &&
                        info[i].flags == info[Z_LVAL_P(pos)].flags) {

                    zend_string_release(key);
                    map[i] = Z_LVAL_P(pos);
                    zval_dtor(&op_array->literals[i]);
                    n = LITERAL_NUM_RELATED(info[i].flags);
                    while (n > 1) {
                        i++;
                        zval_dtor(&op_array->literals[i]);
                        n--;
                    }
                } else {
                    map[i] = j;
                    if (info[i].flags & LITERAL_MAY_MERGE) {
                        ZVAL_LONG(&zv, j);
                        zend_hash_add_new(&hash, key, &zv);
                        zend_string_release(key);
                    }
                    if (i != j) {
                        op_array->literals[j] = op_array->literals[i];
                        info[j] = info[i];
                    }
                    if (LITERAL_NUM_SLOTS(info[i].flags)) {
                        Z_CACHE_SLOT(op_array->literals[j]) = cache_size;
                        cache_size += LITERAL_NUM_SLOTS(info[i].flags) * sizeof(void*);
                    }
                    j++;
                    n = LITERAL_NUM_RELATED(info[i].flags);
                    while (n > 1) {
                        i++;
                        if (i != j) op_array->literals[j] = op_array->literals[i];
                        j++;
                        n--;
                    }
                }
                break;
            default:
                /* don't merge other types */
                map[i] = j;
                if (i != j) {
                    op_array->literals[j] = op_array->literals[i];
                    info[j] = info[i];
                }
                j++;
                break;
            }
        }
        zend_hash_destroy(&hash);
        op_array->last_literal = j;
        op_array->cache_size = cache_size;

        /* Update opcodes to use new literals table */
        opline = op_array->opcodes;
        end = opline + op_array->last;
        while (opline < end) {
            if (ZEND_OP1_TYPE(opline) == IS_CONST) {
                opline->op1.constant = map[opline->op1.constant];
            }
            if (ZEND_OP2_TYPE(opline) == IS_CONST) {
                opline->op2.constant = map[opline->op2.constant];
            }
            opline++;
        }
        zend_arena_release(&ctx->arena, checkpoint);

#if DEBUG_COMPACT_LITERALS
        {
            int i, use_copy;
            fprintf(stderr, "Optimized literlas table size %d\n", op_array->last_literal);

            for (i = 0; i < op_array->last_literal; i++) {
                zval zv;
                ZVAL_COPY_VALUE(&zv, op_array->literals + i);
                use_copy = zend_make_printable_zval(op_array->literals + i, &zv);
                fprintf(stderr, "Literal %d, val (%d):%s\n", i, Z_STRLEN(zv), Z_STRVAL(zv));
                if (use_copy) {
                    zval_dtor(&zv);
                }
            }
            fflush(stderr);
        }
#endif
    }
}
Beispiel #27
0
static void dom_xpath_ext_function_php(xmlXPathParserContextPtr ctxt, int nargs, int type) /* {{{ */
{
	zval retval;
	int result, i;
	int error = 0;
	zend_fcall_info fci;
	xmlXPathObjectPtr obj;
	char *str;
	zend_string *callable = NULL;
	dom_xpath_object *intern;
	

	if (! zend_is_executing()) {
		xmlGenericError(xmlGenericErrorContext,
		"xmlExtFunctionTest: Function called from outside of PHP\n");
		error = 1;
	} else {
		intern = (dom_xpath_object *) ctxt->context->userData;
		if (intern == NULL) {
			xmlGenericError(xmlGenericErrorContext,
			"xmlExtFunctionTest: failed to get the internal object\n");
			error = 1;
		}
		else if (intern->registerPhpFunctions == 0) {
			xmlGenericError(xmlGenericErrorContext,
			"xmlExtFunctionTest: PHP Object did not register PHP functions\n");
			error = 1;
		}
	}
	
	if (error == 1) {
		for (i = nargs - 1; i >= 0; i--) {
			obj = valuePop(ctxt);
			xmlXPathFreeObject(obj);
		}
		return;
	}
		
	fci.param_count = nargs - 1;
	if (fci.param_count > 0) {
		fci.params = safe_emalloc(fci.param_count, sizeof(zval), 0);
	}
	/* Reverse order to pop values off ctxt stack */
	for (i = nargs - 2; i >= 0; i--) {
		obj = valuePop(ctxt);
		switch (obj->type) {
			case XPATH_STRING:
				ZVAL_STRING(&fci.params[i],  (char *)obj->stringval);
				break;
			case XPATH_BOOLEAN:
				ZVAL_BOOL(&fci.params[i],  obj->boolval);
				break;
			case XPATH_NUMBER:
				ZVAL_DOUBLE(&fci.params[i], obj->floatval);
				break;
			case XPATH_NODESET:
				if (type == 1) {
					str = (char *)xmlXPathCastToString(obj);
					ZVAL_STRING(&fci.params[i], str);
					xmlFree(str);
				} else if (type == 2) {
					int j;
					array_init(&fci.params[i]);
					if (obj->nodesetval && obj->nodesetval->nodeNr > 0) {
						for (j = 0; j < obj->nodesetval->nodeNr; j++) {
							xmlNodePtr node = obj->nodesetval->nodeTab[j];
							zval child;
							/* not sure, if we need this... it's copied from xpath.c */
							if (node->type == XML_NAMESPACE_DECL) {
								xmlNsPtr curns;
								xmlNodePtr nsparent;
								
								nsparent = node->_private;
								curns = xmlNewNs(NULL, node->name, NULL);
								if (node->children) {
									curns->prefix = xmlStrdup((xmlChar *) node->children);
								}
								if (node->children) {
									node = xmlNewDocNode(node->doc, NULL, (xmlChar *) node->children, node->name);
								} else {
									node = xmlNewDocNode(node->doc, NULL, (xmlChar *) "xmlns", node->name);
								}
								node->type = XML_NAMESPACE_DECL;
								node->parent = nsparent;
								node->ns = curns;
							}
							php_dom_create_object(node, &child, &intern->dom);
							add_next_index_zval(&fci.params[i], &child);
						}
					}
				}
				break;
			default:
			ZVAL_STRING(&fci.params[i], (char *)xmlXPathCastToString(obj));
		}
		xmlXPathFreeObject(obj);
	}
	
	fci.size = sizeof(fci);
	fci.function_table = EG(function_table);
	
	obj = valuePop(ctxt);
	if (obj->stringval == NULL) {
		php_error_docref(NULL, E_WARNING, "Handler name must be a string");
		xmlXPathFreeObject(obj);
		if (fci.param_count > 0) {
			for (i = 0; i < nargs - 1; i++) {
				zval_ptr_dtor(&fci.params[i]);
			}
			efree(fci.params);
		}
		return; 
	}
	ZVAL_STRING(&fci.function_name, (char *) obj->stringval);
	xmlXPathFreeObject(obj);

	fci.symbol_table = NULL;
	fci.object = NULL;
	fci.retval = &retval;
	fci.no_separation = 0;

	if (!zend_make_callable(&fci.function_name, &callable)) {
		php_error_docref(NULL, E_WARNING, "Unable to call handler %s()", callable->val);
	} else if (intern->registerPhpFunctions == 2 && zend_hash_exists(intern->registered_phpfunctions, callable) == 0) { 
		php_error_docref(NULL, E_WARNING, "Not allowed to call handler '%s()'.", callable->val);
		/* Push an empty string, so that we at least have an xslt result... */
		valuePush(ctxt, xmlXPathNewString((xmlChar *)""));
	} else {
		result = zend_call_function(&fci, NULL);
		if (result == SUCCESS && Z_TYPE(retval) != IS_UNDEF) {
			if (Z_TYPE(retval) == IS_OBJECT && instanceof_function(Z_OBJCE(retval), dom_node_class_entry)) {
				xmlNode *nodep;
				dom_object *obj;
				if (intern->node_list == NULL) {
					ALLOC_HASHTABLE(intern->node_list);
					zend_hash_init(intern->node_list, 0, NULL, ZVAL_PTR_DTOR, 0);
				}
				GC_REFCOUNT(&retval)++;
				zend_hash_next_index_insert(intern->node_list, &retval);
				obj = Z_DOMOBJ_P(&retval);
				nodep = dom_object_get_node(obj);
				valuePush(ctxt, xmlXPathNewNodeSet(nodep));
			} else if (Z_TYPE(retval) == IS_FALSE || Z_TYPE(retval) == IS_TRUE) {
				valuePush(ctxt, xmlXPathNewBoolean(Z_TYPE(retval) == IS_TRUE));
			} else if (Z_TYPE(retval) == IS_OBJECT) {
				php_error_docref(NULL, E_WARNING, "A PHP Object cannot be converted to a XPath-string");
				valuePush(ctxt, xmlXPathNewString((xmlChar *)""));
			} else {
				zend_string *str = zval_get_string(&retval);
				valuePush(ctxt, xmlXPathNewString((xmlChar *) str->val));
				zend_string_release(str);
			}
			zval_ptr_dtor(&retval);
		}
	}
	zend_string_release(callable);
	zval_dtor(&fci.function_name);
	if (fci.param_count > 0) {
		for (i = 0; i < nargs - 1; i++) {
			zval_ptr_dtor(&fci.params[i]);
		}
		efree(fci.params);
	}
}
Beispiel #28
0
static void call_php(char *name, PARAMDSC *r, int argc, PARAMDSC **argv)
{
	do {
		zval callback, args[4], return_value;
		PARAMVARY *res = (PARAMVARY*)r->dsc_address;
		int i;

		ZVAL_STRING(&callback, name);

		LOCK();

		/* check if the requested function exists */
		if (!zend_is_callable(&callback, 0, NULL)) {
			break;
		}

		UNLOCK();

		/* create the argument array */
		for (i = 0; i < argc; ++i) {

			/* test arg for null */
			if (argv[i]->dsc_flags & DSC_null) {
				ZVAL_NULL(&args[i]);
				continue;
			}

			switch (argv[i]->dsc_dtype) {
				ISC_INT64 l;
				struct tm t;
				char const *fmt;
				char d[64];

				case dtype_cstring:
//???
					ZVAL_STRING(&args[i], (char*)argv[i]->dsc_address);
					break;

				case dtype_text:
//???
					ZVAL_STRINGL(&args[i], (char*)argv[i]->dsc_address, argv[i]->dsc_length);
					break;

				case dtype_varying:
//???
					ZVAL_STRINGL(&args[i], ((PARAMVARY*)argv[i]->dsc_address)->vary_string,
						((PARAMVARY*)argv[i]->dsc_address)->vary_length);
					break;

				case dtype_short:
					if (argv[i]->dsc_scale == 0) {
						ZVAL_LONG(&args[i], *(short*)argv[i]->dsc_address);
					} else {
						ZVAL_DOUBLE(&args[i],
							((double)*(short*)argv[i]->dsc_address)/scales[-argv[i]->dsc_scale]);
					}
					break;

				case dtype_long:
					if (argv[i]->dsc_scale == 0) {
						ZVAL_LONG(&args[i], *(ISC_LONG*)argv[i]->dsc_address);
					} else {
						ZVAL_DOUBLE(&args[i],
							((double)*(ISC_LONG*)argv[i]->dsc_address)/scales[-argv[i]->dsc_scale]);
					}
					break;

				case dtype_int64:
					l = *(ISC_INT64*)argv[i]->dsc_address;

					if (argv[i]->dsc_scale == 0 && l <= LONG_MAX && l >= LONG_MIN) {
						ZVAL_LONG(&args[i], (long)l);
					} else {
						ZVAL_DOUBLE(&args[i], ((double)l)/scales[-argv[i]->dsc_scale]);
					}
					break;

				case dtype_real:
					ZVAL_DOUBLE(&args[i], *(float*)argv[i]->dsc_address);
					break;

				case dtype_double:
					ZVAL_DOUBLE(&args[i], *(double*)argv[i]->dsc_address);
					break;

				case dtype_sql_date:
					isc_decode_sql_date((ISC_DATE*)argv[i]->dsc_address, &t);
					ZVAL_STRINGL(&args[i], d, strftime(d, sizeof(d), INI_STR("ibase.dateformat"), &t),1);
					break;

				case dtype_sql_time:
					isc_decode_sql_time((ISC_TIME*)argv[i]->dsc_address, &t);
					ZVAL_STRINGL(&args[i], d, strftime(d, sizeof(d), INI_STR("ibase.timeformat"), &t),1);
					break;

				case dtype_timestamp:
					isc_decode_timestamp((ISC_TIMESTAMP*)argv[i]->dsc_address, &t);
					ZVAL_STRINGL(&args[i], d, strftime(d, sizeof(d), INI_STR("ibase.timestampformat"), &t));
					break;
			}
		}

		LOCK();

		/* now call the function */
		if (FAILURE == call_user_function(EG(function_table), NULL,
				&callback, &return_value, argc, args)) {
			UNLOCK();
			break;
		}

		UNLOCK();

		for (i = 0; i < argc; ++i) {
			switch (argv[i]->dsc_dtype) {
				case dtype_sql_date:
				case dtype_sql_time:
				case dtype_timestamp:
					zval_dtor(&args[i]);
			}
		}

		zval_dtor(&callback);

		/* return whatever type we got back from the callback: let DB handle conversion */
		switch (Z_TYPE(return_value)) {

			case IS_LONG:
				r->dsc_dtype = dtype_long;
				*(long*)r->dsc_address = Z_LVAL(return_value);
				r->dsc_length = sizeof(long);
				break;

			case IS_DOUBLE:
				r->dsc_dtype = dtype_double;
				*(double*)r->dsc_address = Z_DVAL(return_value);
				r->dsc_length = sizeof(double);
				break;

			case IS_NULL:
				r->dsc_flags |= DSC_null;
				break;

			default:
				convert_to_string(&return_value);

			case IS_STRING:
				r->dsc_dtype = dtype_varying;
				memcpy(res->vary_string, Z_STRVAL(return_value),
					(res->vary_length = min(r->dsc_length-2,Z_STRLEN(return_value))));
				r->dsc_length = res->vary_length+2;
				break;
		}

		zval_dtor(&return_value);

		return;

	} while (0);

	/**
	* If we end up here, we should report an error back to the DB engine, but
	* that's not possible. We can however report it back to PHP.
	*/
	LOCK();
	php_error_docref(NULL, E_WARNING, "Error calling function '%s' from database", name);
	UNLOCK();
}
Beispiel #29
0
static void dom_xpath_ext_function_php(xmlXPathParserContextPtr ctxt, int nargs, int type) /* {{{ */
{
	zval **args;
	zval *retval;
	int result, i, ret;
	int error = 0;
	zend_fcall_info fci;
	zval handler;
	xmlXPathObjectPtr obj;
	char *str;
	char *callable = NULL;
	dom_xpath_object *intern;
	
	TSRMLS_FETCH();

	if (! zend_is_executing(TSRMLS_C)) {
		xmlGenericError(xmlGenericErrorContext,
		"xmlExtFunctionTest: Function called from outside of PHP\n");
		error = 1;
	} else {
		intern = (dom_xpath_object *) ctxt->context->userData;
		if (intern == NULL) {
			xmlGenericError(xmlGenericErrorContext,
			"xmlExtFunctionTest: failed to get the internal object\n");
			error = 1;
		}
		else if (intern->registerPhpFunctions == 0) {
			xmlGenericError(xmlGenericErrorContext,
			"xmlExtFunctionTest: PHP Object did not register PHP functions\n");
			error = 1;
		}
	}
	
	if (error == 1) {
		for (i = nargs - 1; i >= 0; i--) {
			obj = valuePop(ctxt);
			xmlXPathFreeObject(obj);
		}
		return;
	}
		
	fci.param_count = nargs - 1;
	if (fci.param_count > 0) {
		fci.params = safe_emalloc(fci.param_count, sizeof(zval**), 0);
		args = safe_emalloc(fci.param_count, sizeof(zval *), 0);
	}
	/* Reverse order to pop values off ctxt stack */
	for (i = nargs - 2; i >= 0; i--) {
		obj = valuePop(ctxt);
		MAKE_STD_ZVAL(args[i]);
		switch (obj->type) {
			case XPATH_STRING:
				ZVAL_STRING(args[i],  (char *)obj->stringval, 1);
				break;
			case XPATH_BOOLEAN:
				ZVAL_BOOL(args[i],  obj->boolval);
				break;
			case XPATH_NUMBER:
				ZVAL_DOUBLE(args[i], obj->floatval);
				break;
			case XPATH_NODESET:
				if (type == 1) {
					str = (char *)xmlXPathCastToString(obj);
					ZVAL_STRING(args[i], str, 1);
					xmlFree(str);
				} else if (type == 2) {
					int j;
					array_init(args[i]);
					if (obj->nodesetval && obj->nodesetval->nodeNr > 0) {
						for (j = 0; j < obj->nodesetval->nodeNr; j++) {
							xmlNodePtr node = obj->nodesetval->nodeTab[j];
							zval *child;
							MAKE_STD_ZVAL(child);
							/* not sure, if we need this... it's copied from xpath.c */
							if (node->type == XML_NAMESPACE_DECL) {
								xmlNsPtr curns;
								xmlNodePtr nsparent;
								
								nsparent = node->_private;
								curns = xmlNewNs(NULL, node->name, NULL);
								if (node->children) {
									curns->prefix = xmlStrdup((xmlChar *) node->children);
								}
								if (node->children) {
									node = xmlNewDocNode(node->doc, NULL, (xmlChar *) node->children, node->name);
								} else {
									node = xmlNewDocNode(node->doc, NULL, (xmlChar *) "xmlns", node->name);
								}
								node->type = XML_NAMESPACE_DECL;
								node->parent = nsparent;
								node->ns = curns;
							}
							child = php_dom_create_object(node, &ret, child, (dom_object *)intern TSRMLS_CC);
							add_next_index_zval(args[i], child);
						}
					}
				}
				break;
			default:
			ZVAL_STRING(args[i], (char *)xmlXPathCastToString(obj), 1);
		}
		xmlXPathFreeObject(obj);
		fci.params[i] = &args[i];
	}
	
	fci.size = sizeof(fci);
	fci.function_table = EG(function_table);
	
	obj = valuePop(ctxt);
	if (obj->stringval == NULL) {
		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Handler name must be a string");
		xmlXPathFreeObject(obj);
		if (fci.param_count > 0) {
			for (i = 0; i < nargs - 1; i++) {
				zval_ptr_dtor(&args[i]);
			}
			efree(args);
			efree(fci.params);
		}
		return; 
	}
	INIT_PZVAL(&handler);
	ZVAL_STRING(&handler, obj->stringval, 1);
	xmlXPathFreeObject(obj);

	fci.function_name = &handler;
	fci.symbol_table = NULL;
	fci.object_ptr = NULL;
	fci.retval_ptr_ptr = &retval;
	fci.no_separation = 0;

	if (!zend_make_callable(&handler, &callable TSRMLS_CC)) {
		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to call handler %s()", callable);
		
	} else if ( intern->registerPhpFunctions == 2 && zend_hash_exists(intern->registered_phpfunctions, callable, strlen(callable) + 1) == 0) { 
		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Not allowed to call handler '%s()'.", callable);
		/* Push an empty string, so that we at least have an xslt result... */
		valuePush(ctxt, xmlXPathNewString((xmlChar *)""));
	} else {
		result = zend_call_function(&fci, NULL TSRMLS_CC);
		if (result == FAILURE) {
			if (Z_TYPE(handler) == IS_STRING) {
				php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to call handler %s()", Z_STRVAL_P(&handler));
			}
		/* retval is == NULL, when an exception occurred, don't report anything, because PHP itself will handle that */
		} else if (retval == NULL) {
		} else {
			if (retval->type == IS_OBJECT && instanceof_function( Z_OBJCE_P(retval), dom_node_class_entry TSRMLS_CC)) {
				xmlNode *nodep;
				dom_object *obj;
				if (intern->node_list == NULL) {
					ALLOC_HASHTABLE(intern->node_list);
					zend_hash_init(intern->node_list, 0, NULL, ZVAL_PTR_DTOR, 0);
				}
				zval_add_ref(&retval);
				zend_hash_next_index_insert(intern->node_list, &retval, sizeof(zval *), NULL);
				obj = (dom_object *)zend_object_store_get_object(retval TSRMLS_CC);
				nodep = dom_object_get_node(obj);
				valuePush(ctxt, xmlXPathNewNodeSet(nodep));
			} else if (retval->type == IS_BOOL) {
				valuePush(ctxt, xmlXPathNewBoolean(retval->value.lval));
			} else if (retval->type == IS_OBJECT) {
				php_error_docref(NULL TSRMLS_CC, E_WARNING, "A PHP Object cannot be converted to a XPath-string");
				valuePush(ctxt, xmlXPathNewString((xmlChar *)""));
			} else {
				convert_to_string_ex(&retval);
				valuePush(ctxt, xmlXPathNewString( Z_STRVAL_P(retval)));
			}
			zval_ptr_dtor(&retval);
		}
	}
	efree(callable);
	zval_dtor(&handler);
	if (fci.param_count > 0) {
		for (i = 0; i < nargs - 1; i++) {
			zval_ptr_dtor(&args[i]);
		}
		efree(args);
		efree(fci.params);
	}
}
Beispiel #30
0
void qb_extract_pbj_info(qb_extractor_context *cxt, int output_type) {
	qb_pbj_translator_context *translator_cxt = cxt->translator_context;
	zval path = *cxt->input, *parameters;
	uint32_t i;

	zval_copy_ctor(&path);
	convert_to_string(&path);

	// load the code into memory
	qb_load_external_code(cxt->compiler_context, Z_STRVAL(path));

	// decode the pbj data
	qb_decode_pbj_binary(translator_cxt);

	if(output_type == QB_PBJ_DETAILS) {
		array_init(cxt->return_value);
		qb_add_string(cxt->return_value, "vendor", translator_cxt->vendor, -1);
		qb_add_string(cxt->return_value, "name", translator_cxt->name, translator_cxt->name_length);
		qb_add_string(cxt->return_value, "displayName", translator_cxt->display_name, -1);
		qb_add_string(cxt->return_value, "description", translator_cxt->description, -1);
		qb_add_int(cxt->return_value, "version", translator_cxt->version);
		parameters = qb_add_array(cxt->return_value, "parameters");
		for(i = 0; i < translator_cxt->parameter_count; i++) {
			qb_pbj_parameter *param = &translator_cxt->parameters[i];
			if(param != translator_cxt->out_coord && !param->input_size_name) {
				zval *param_info = qb_add_array(parameters, NULL);
				qb_add_string(param_info, "direction", (param->qualifier == PBJ_PARAMETER_OUT) ? "out" : "in", -1);
				qb_add_string(param_info, "name", param->name, -1);
				qb_add_string(param_info, "displayName", param->display_name, -1);
				qb_add_string(param_info, "type", pbj_type_names[param->type], -1);
				qb_add_string(param_info, "parameterType", param->parameter_type, -1);
				qb_add_string(param_info, "description", param->description, -1);
				if(param->qualifier == PBJ_PARAMETER_IN) {
					qb_add_pbj_value(param_info, "minValue", &param->min_value);
					qb_add_pbj_value(param_info, "maxValue", &param->max_value);
					qb_add_pbj_value(param_info, "defaultValue", &param->default_value);
				}
			}
		}
		for(i = 0; i < translator_cxt->texture_count; i++) {
			qb_pbj_texture *texture = &translator_cxt->textures[i];
			zval *param_info = qb_add_array(parameters, NULL);
			qb_add_string(param_info, "direction", "in", -1);
			qb_add_string(param_info, "name", texture->name, -1);
			qb_add_string(param_info, "displayName", NULL, 0);
			qb_add_string(param_info, "type", pbj_texture_type_names[texture->channel_count], -1);
			qb_add_string(param_info, "parameterType", NULL, 0);
			qb_add_string(param_info, "description", NULL, 0);
		}
	} else if(output_type == QB_PBJ_DECLARATION) {
		const char *pbj_path = Z_STRVAL_P(cxt->input);
		uint32_t param_count = 0;
		ZVAL_STRING(cxt->return_value, "/**\n", TRUE);
		qb_append_string(cxt->return_value, " * %.*s()\t", translator_cxt->name_length, translator_cxt->name);
		if(translator_cxt->description) {
			qb_append_string(cxt->return_value, "%s", translator_cxt->description);
		}
		if(translator_cxt->vendor) {
			qb_append_string(cxt->return_value, " (%s)", translator_cxt->vendor);
		}
		qb_append_string(cxt->return_value, "\n");
		
		qb_append_string(cxt->return_value, " *\n");
		qb_append_string(cxt->return_value, " * @engine\tqb\n");
		qb_append_string(cxt->return_value, " * @import\t%s\n", pbj_path);
		qb_append_string(cxt->return_value, " *\n");

		if(translator_cxt->out_pixel) {
			qb_pbj_parameter *param = translator_cxt->out_pixel;
			uint32_t channel_count;
			switch(param->type) {
				case PBJ_TYPE_FLOAT:  channel_count = 1; break;
				case PBJ_TYPE_FLOAT2: channel_count = 2; break;
				case PBJ_TYPE_FLOAT3: channel_count = 3; break;
				case PBJ_TYPE_FLOAT4: channel_count = 4; break;
			}
			qb_append_string(cxt->return_value, " * @param\t%s\t$%s\n", pbj_texture_qb_types[channel_count], param->name);
		}
		for(i = 0; i < translator_cxt->texture_count; i++) {
			qb_pbj_texture *texture = &translator_cxt->textures[i];
			qb_append_string(cxt->return_value, " * @param\t%s\t$%s\n", pbj_texture_qb_types[texture->channel_count], texture->name);
		}
		for(i = 0; i < translator_cxt->parameter_count; i++) {
			qb_pbj_parameter *param = &translator_cxt->parameters[i];
			if(param != translator_cxt->out_coord && param != translator_cxt->out_pixel && !param->input_size_name) {
				const char *type = pbj_param_qb_types[param->type];
				if(param->parameter_type) {
					if(param->type == PBJ_TYPE_FLOAT2) {
						if(strcmp(param->parameter_type, "position") == 0) {
							type = "float32[x,y]";
						}
					} else if(param->type == PBJ_TYPE_FLOAT3) {
						if(strcmp(param->parameter_type, "colorLAB") == 0) {
							type = "float32[L,a,b]";
						} else if(strcmp(param->parameter_type, "colorRGB") == 0) {
							type = "float32[r,g,b]";
						}
					} else if(param->type == PBJ_TYPE_FLOAT4) {
						if(strcmp(param->parameter_type, "colorCMYK") == 0) {
							type = "float32[c,m,y,k]";
						} else if(strcmp(param->parameter_type, "colorRGBA") == 0) {
							type = "float32[r,g,b,a]";
						}
					}
				}
				qb_append_string(cxt->return_value, " * @param\t%s\t$%s", type, param->name);
				if(param->description) {
					qb_append_string(cxt->return_value, "\t%s", param->description);
				}
				qb_append_string(cxt->return_value, "\n");
			}
		}

		qb_append_string(cxt->return_value, " *\n");
		qb_append_string(cxt->return_value, " * @return\tvoid\n");
		qb_append_string(cxt->return_value, " */\n");
		qb_append_string(cxt->return_value, "function %.*s(", translator_cxt->name_length, translator_cxt->name);
		if(translator_cxt->out_pixel) {
			qb_pbj_parameter *param = translator_cxt->out_pixel;
			qb_append_string(cxt->return_value, "&$%s", param->name);
			param_count++;
		}
		for(i = 0; i < translator_cxt->texture_count; i++) {
			qb_pbj_texture *texture = &translator_cxt->textures[i];
			if(param_count) {
				qb_append_string(cxt->return_value, ", ");
			}
			qb_append_string(cxt->return_value, "$%s", texture->name);
			param_count++;
		}
		for(i = 0; i < translator_cxt->parameter_count; i++) {
			qb_pbj_parameter *param = &translator_cxt->parameters[i];
			if(param != translator_cxt->out_coord && param != translator_cxt->out_pixel && !param->input_size_name) {
				if(param_count) {
					qb_append_string(cxt->return_value, ", ");
				}
				qb_append_string(cxt->return_value, "$%s", param->name);
			}
		}
		qb_append_string(cxt->return_value, ") {}\n");
	}
	zval_dtor(&path);
}