<commit_before>/**
 * Appcelerator Kroll - licensed under the Apache Public License 2
 * see LICENSE in the root folder for details on the license.
 * Copyright (c) 2009 Appcelerator, Inc. All Rights Reserved.
 */

#include "php_module.h"
 
namespace kroll
{	
	PHPEvaluator::PHPEvaluator()
		: StaticBoundObject("PHPEvaluator")
	{
		/**
		 * @tiapi(method=True,name=PHP.evaluate,since=0.7) Evaluates a string as PHP code
		 * @tiarg(for=PHP.evaluate,name=mimeType,type=String) Code mime type (normally "text/php")
		 * @tiarg(for=PHP.evaluate,name=code,type=String) PHP script code
		 * @tiarg(for=PHP.evaluate,name=scope,type=Object) global variable scope
		 * @tiresult(for=PHP.evaluate,type=any) result of the evaluation
		 */
		SetMethod("evaluate", &PHPEvaluator::Evaluate);
		
		/**
		 * @tiapi(method=True,name=PHP.preprocess,since=0.7) Runs a string+URL through preprocessing
		 * @tiarg(for=PHP.preprocess,name=url,type=String) URL used to load this resource
		 * @tiarg(for=PHP.preprocess,name=code,type=String) PHP script code
		 * @tiresult(for=PHP.preprocess,type=String) result of the evaluation
		 */
		SetMethod("preprocess", &PHPEvaluator::Preprocess);
	}
	
	void PHPEvaluator::Evaluate(const ValueList& args, SharedValue result)
	{
		TSRMLS_FETCH();
		
		if (args.size() != 3
			|| !args.at(1)->IsString()
			|| !args.at(2)->IsObject())
		{
			return;
		}

		const char* code = args[1]->ToString();
		SharedKObject windowGlobal = args.at(2)->ToObject();
		const char* name = "<embedded PHP>";
		SharedValue kv = Value::Undefined;

		std::string contextName = CreateContextName();
		std::ostringstream codeString, callString;
		codeString << "function " << contextName << "() {\n";
		codeString << " global $Titanium, $window, $document;\n";
		codeString << code;
		codeString << " foreach (get_defined_vars() as $var=>$val) {\n";
		codeString << "  if ($var != 'Titanium' && $var != 'window' && $var != 'document') {\n";
		codeString << "    $window->$var = $val;\n";
		codeString << "  }\n";
		codeString << " }\n ";
		codeString << " $__fns = get_defined_functions();\n";
		codeString << " if (array_key_exists(\"user\", $__fns)) {\n";
		codeString << "  foreach($__fns[\"user\"] as $fname) {\n";
		codeString << "   if ($fname != \"" << contextName << "\" && !$window->$fname) {";
		codeString << "     krollAddFunction($window, $fname);\n";
		codeString << "   }\n";
		codeString << "  }\n";
		codeString << " }\n";
		
		//kroll_populate_context($window);\n";
		codeString << "};\n";
		codeString << contextName << "();";
		zend_first_try {
			/* This seems to be needed to make PHP actually give us errors at parse/compile time
			 * See: main/main.c line 969 */
			PG(during_request_startup) = 0;
			
			zval *windowValue = PHPUtils::ToPHPValue(args.at(2));
			ZEND_SET_SYMBOL(&EG(symbol_table), "window", windowValue);
			SharedValue document = windowGlobal->Get("document");
			zval *documentValue = PHPUtils::ToPHPValue(document);
			ZEND_SET_SYMBOL(&EG(symbol_table), "document", documentValue);
			
			zend_eval_string((char *) codeString.str().c_str(), NULL, (char *) name TSRMLS_CC);
		} zend_catch {
		} zend_end_try();

		result->SetValue(kv);
	}
	
	void PHPEvaluator::FillServerVars(Poco::URI& uri, SharedKObject headers, std::string& httpMethod TSRMLS_DC)
	{
		// Fill $_SERVER with HTTP headers
		zval *SERVER;
		array_init(SERVER);
		
		//if (zend_hash_find(&EG(symbol_table), "_SERVER", sizeof("_SERVER"), (void**)&SERVER) == SUCCESS)
		//{
			SharedStringList headerNames = headers->GetPropertyNames();
			for (size_t i = 0; i < headerNames->size(); i++)
			{
				//zval *headerValue;
				const char *headerName = headerNames->at(i)->c_str();
				const char *headerValue = headers->GetString(headerName).c_str();
				
				//ALLOC_INIT_ZVAL(headerValue);
				//ZVAL_STRING(headerValue, (char*)headers->GetString(headerName).c_str(), 1);
				
				add_assoc_stringl(SERVER, (char *) headerName, (char *) headerValue, strlen(headerValue), 1);
				//zend_hash_add(Z_ARRVAL_P(SERVER), (char*)headerName, strlen(headerName)+1, &headerValue, sizeof(zval*), NULL);
				//ZEND_SET_SYMBOL(Z_ARRVAL_P(SERVER), (char*)headerName, headerValue);
			}
			ZEND_SET_SYMBOL(&EG(symbol_table), (char *)"_SERVER", SERVER);
		//}
		
		// Fill $_GET with query string parameters
		zval *GET;
		if (zend_hash_find(&EG(symbol_table), "_GET", sizeof("_GET"), (void**)&GET) == SUCCESS)
		{
			std::string queryString = uri.getQuery();
			Poco::StringTokenizer tokens(uri.getQuery(), "&=");
			for (Poco::StringTokenizer::Iterator iter = tokens.begin();
				iter != tokens.end(); iter++)
			{
				std::string key = *iter;
				std::string value = *(++iter);
				
				zval *val;
				ALLOC_INIT_ZVAL(val);
				ZVAL_STRING(val, (char*)value.c_str(), 1);
				zend_hash_add(Z_ARRVAL_P(GET), (char*)key.c_str(), key.size()+1, &val, sizeof(zval*), NULL);
			}
		}
		
		// TODO: Fill $_POST, $_REQUEST
	}
	
	void PHPEvaluator::Preprocess(const ValueList& args, SharedValue result)
	{
		args.VerifyException("s o s s", "preprocess");
		
		std::string url = args.GetString(0);
		Poco::URI uri(url);
		
		SharedKObject headers = args.GetObject(1);
		std::string httpMethod = args.GetString(2);
		std::string path = args.GetString(3);
		
		TSRMLS_FETCH();
		
		PHPModule::SetBuffering(true);
		zend_first_try {
			/* This seems to be needed to make PHP actually give us errors at parse/compile time
			 * See: main/main.c line 969 */
			PG(during_request_startup) = 0;
			
			FillServerVars(uri, headers, httpMethod TSRMLS_CC);
			
			zend_file_handle script;
			script.type = ZEND_HANDLE_FP;
			script.filename = (char*)path.c_str();
			script.opened_path = NULL;
			script.free_filename = 0;
			script.handle.fp = fopen(script.filename, "rb");
			php_execute_script(&script TSRMLS_CC);
			
			//zend_execute_scripts(ZEND_REQUIRE TSRMLS_CC, NULL, 3, prepend_file_p, primary_file, append_file_p);
			//zend_eval_string((char *) code.c_str(), NULL, (char *) url.c_str() TSRMLS_CC);
		} zend_catch {
		} zend_end_try();
		
		result->SetString(PHPModule::GetBuffer().str());<commit_msg>build fix for osx<commit_after>/**
 * Appcelerator Kroll - licensed under the Apache Public License 2
 * see LICENSE in the root folder for details on the license.
 * Copyright (c) 2009 Appcelerator, Inc. All Rights Reserved.
 */

#include "php_module.h"
 
namespace kroll
{	
	PHPEvaluator::PHPEvaluator()
		: StaticBoundObject("PHPEvaluator")
	{
		/**
		 * @tiapi(method=True,name=PHP.evaluate,since=0.7) Evaluates a string as PHP code
		 * @tiarg(for=PHP.evaluate,name=mimeType,type=String) Code mime type (normally "text/php")
		 * @tiarg(for=PHP.evaluate,name=code,type=String) PHP script code
		 * @tiarg(for=PHP.evaluate,name=scope,type=Object) global variable scope
		 * @tiresult(for=PHP.evaluate,type=any) result of the evaluation
		 */
		SetMethod("evaluate", &PHPEvaluator::Evaluate);
		
		/**
		 * @tiapi(method=True,name=PHP.preprocess,since=0.7) Runs a string+URL through preprocessing
		 * @tiarg(for=PHP.preprocess,name=url,type=String) URL used to load this resource
		 * @tiarg(for=PHP.preprocess,name=code,type=String) PHP script code
		 * @tiresult(for=PHP.preprocess,type=String) result of the evaluation
		 */
		SetMethod("preprocess", &PHPEvaluator::Preprocess);
	}
	
	void PHPEvaluator::Evaluate(const ValueList& args, SharedValue result)
	{
		TSRMLS_FETCH();
		
		if (args.size() != 3
			|| !args.at(1)->IsString()
			|| !args.at(2)->IsObject())
		{
			return;
		}

		const char* code = args[1]->ToString();
		SharedKObject windowGlobal = args.at(2)->ToObject();
		const char* name = "<embedded PHP>";
		SharedValue kv = Value::Undefined;

		std::string contextName = CreateContextName();
		std::ostringstream codeString, callString;
		codeString << "function " << contextName << "() {\n";
		codeString << " global $Titanium, $window, $document;\n";
		codeString << code;
		codeString << " foreach (get_defined_vars() as $var=>$val) {\n";
		codeString << "  if ($var != 'Titanium' && $var != 'window' && $var != 'document') {\n";
		codeString << "    $window->$var = $val;\n";
		codeString << "  }\n";
		codeString << " }\n ";
		codeString << " $__fns = get_defined_functions();\n";
		codeString << " if (array_key_exists(\"user\", $__fns)) {\n";
		codeString << "  foreach($__fns[\"user\"] as $fname) {\n";
		codeString << "   if ($fname != \"" << contextName << "\" && !$window->$fname) {";
		codeString << "     krollAddFunction($window, $fname);\n";
		codeString << "   }\n";
		codeString << "  }\n";
		codeString << " }\n";
		
		//kroll_populate_context($window);\n";
		codeString << "};\n";
		codeString << contextName << "();";
		zend_first_try {
			/* This seems to be needed to make PHP actually give us errors at parse/compile time
			 * See: main/main.c line 969 */
			PG(during_request_startup) = 0;
			
			zval *windowValue = PHPUtils::ToPHPValue(args.at(2));
			ZEND_SET_SYMBOL(&EG(symbol_table), "window", windowValue);
			SharedValue document = windowGlobal->Get("document");
			zval *documentValue = PHPUtils::ToPHPValue(document);
			ZEND_SET_SYMBOL(&EG(symbol_table), "document", documentValue);
			
			zend_eval_string((char *) codeString.str().c_str(), NULL, (char *) name TSRMLS_CC);
		} zend_catch {
		} zend_end_try();

		result->SetValue(kv);
	}
	
	void PHPEvaluator::FillServerVars(Poco::URI& uri, SharedKObject headers, std::string& httpMethod TSRMLS_DC)
	{
		// Fill $_SERVER with HTTP headers
		zval *SERVER;
		array_init(SERVER);
		
		//if (zend_hash_find(&EG(symbol_table), "_SERVER", sizeof("_SERVER"), (void**)&SERVER) == SUCCESS)
		//{
			SharedStringList headerNames = headers->GetPropertyNames();
			for (size_t i = 0; i < headerNames->size(); i++)
			{
				//zval *headerValue;
				const char *headerName = headerNames->at(i)->c_str();
				const char *headerValue = headers->GetString(headerName).c_str();
				
				//ALLOC_INIT_ZVAL(headerValue);
				//ZVAL_STRING(headerValue, (char*)headers->GetString(headerName).c_str(), 1);
				
				add_assoc_stringl(SERVER, (char *) headerName, (char *) headerValue, strlen(headerValue), 1);
				//zend_hash_add(Z_ARRVAL_P(SERVER), (char*)headerName, strlen(headerName)+1, &headerValue, sizeof(zval*), NULL);
				//ZEND_SET_SYMBOL(Z_ARRVAL_P(SERVER), (char*)headerName, headerValue);
			}
			ZEND_SET_SYMBOL(&EG(symbol_table), (char *)"_SERVER", SERVER);
		//}
		
		// Fill $_GET with query string parameters
		zval *GET;
		if (zend_hash_find(&EG(symbol_table), "_GET", sizeof("_GET"), (void**)&GET) == SUCCESS)
		{
			std::string queryString = uri.getQuery();
			Poco::StringTokenizer tokens(uri.getQuery(), "&=");
			for (Poco::StringTokenizer::Iterator iter = tokens.begin();
				iter != tokens.end(); iter++)
			{
				std::string key = *iter;
				std::string value = *(++iter);
				
				zval *val;
				ALLOC_INIT_ZVAL(val);
				ZVAL_STRING(val, (char*)value.c_str(), 1);
				zend_hash_add(Z_ARRVAL_P(GET), (char*)key.c_str(), key.size()+1, &val, sizeof(zval*), NULL);
			}
		}
		
		// TODO: Fill $_POST, $_REQUEST
	}
	
	void PHPEvaluator::Preprocess(const ValueList& args, SharedValue result)
	{
		args.VerifyException("s o s s", "preprocess");
		
		std::string url = args.GetString(0);
		Poco::URI uri(url);
		
		SharedKObject headers = args.GetObject(1);
		std::string httpMethod = args.GetString(2);
		std::string path = args.GetString(3);
		
		TSRMLS_FETCH();
		
		PHPModule::SetBuffering(true);
		zend_first_try {
			/* This seems to be needed to make PHP actually give us errors at parse/compile time
			 * See: main/main.c line 969 */
			PG(during_request_startup) = 0;
			
			FillServerVars(uri, headers, httpMethod TSRMLS_CC);
			
			zend_file_handle script;
			script.type = ZEND_HANDLE_FP;
			script.filename = (char*)path.c_str();
			script.opened_path = NULL;
			script.free_filename = 0;
			script.handle.fp = fopen(script.filename, "rb");
			php_execute_script(&script TSRMLS_CC);
			
			//zend_execute_scripts(ZEND_REQUIRE TSRMLS_CC, NULL, 3, prepend_file_p, primary_file, append_file_p);
			//zend_eval_string((char *) code.c_str(), NULL, (char *) url.c_str() TSRMLS_CC);
		} zend_catch {
		} zend_end_try();
		
		result->SetString(PHPModule::GetBuffer().str().c_str());
{'fraction_non_alphanumeric': 0.16830951207491376, 'fraction_numerical': 0.005749958928864794, 'mean_word_length': 4.318916557448667, 'pattern_counts': {'":': 0, '<': 99, '<?xml version=': 0, '>': 37, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7531591', 'n_tokens_mistral': 4841, 'n_tokens_neox': 4230, 'n_words': 862}