Esempio n. 1
0
void PHPQt5::zif_emit(INTERNAL_FUNCTION_PARAMETERS)
{
#ifdef PQDEBUG
    PQDBG_LVL_START(__FUNCTION__);
#endif

    QString className = "";

    void *TSRMLS_CACHE = tsrm_get_ls_cache();

    zend_object *zo = zend_get_this_object(EG(current_execute_data));

    if(zo && zo->ce) {
        zval zobject;
        ZVAL_OBJ(&zobject, zo);

        if(pq_test_ce(&zobject PQDBG_LVL_CC)) {
            className = QString(Z_OBJCE_NAME(zobject));

            char *signal_signature;
            int signal_signature_len;
            zval *args;

            if(zend_parse_parameters(ZEND_NUM_ARGS(), "sa", &signal_signature, &signal_signature_len, &args) == FAILURE) {
                PQDBG_LVL_DONE();
                return;
            }

            QObject *qo = Q_NULLPTR;//objectFactory()->getQObject(&zobject);

            if(qo != nullptr) {
                bool haveSignalConnection = false;
                bool haveSignal = false;
                QByteArray signalSignature(signal_signature);

                signalSignature.replace(",string",",QString")
                        .replace("string,","QString,")
                        .replace("(string)","(QString)");

                if(!QMetaObject::invokeMethod(qo,
                                          "haveSignal",
                                          Qt::DirectConnection,
                                          Q_RETURN_ARG(bool, haveSignal),
                                          Q_ARG(QByteArray, signalSignature))) {
                    php_error(E_WARNING,
                              QString("ERROR %1::invokeMethod( haveSignal )")
                              .arg(className)
                              .toUtf8().constData());
                }

                if(!haveSignal) {
                    php_error(E_WARNING,
                              QString("Undefined signal %1::%2")
                              .arg(className)
                              .arg(signal_signature).toUtf8().constData());

                    RETURN_NULL();
                }

                if(QMetaObject::invokeMethod(qo,
                                             "haveSignalConnection",
                                             Qt::DirectConnection,
                                             Q_RETURN_ARG(bool, haveSignalConnection),
                                             Q_ARG(QByteArray, signalSignature))) {
                    if(haveSignalConnection) {
                        #if defined(PQDEBUG) && defined(PQDETAILEDDEBUG)
                        PQDBGLPUP(QString("emit: %1").arg(signal_signature));
                        #endif
                        pq_emit(qo, signalSignature, args);
                    }
                    #if defined(PQDEBUG) && defined(PQDETAILEDDEBUG)
                    else {
                        #if defined(PQDEBUG) && defined(PQDETAILEDDEBUG)
                        PQDBGLPUP(QString("no have connections for %1").arg(signal_signature));
                        #endif
                    }
                    #endif
                }
                #if defined(PQDEBUG) && defined(PQDETAILEDDEBUG)
                else {
Esempio n. 2
0
void PHPQt5ConnectionWorker::process()
{
#ifdef PQDEBUG
    PQDBG_LVL_START(__FUNCTION__);
#endif

    if(this->ctx == nullptr) {
        PQDBGLPUP("tsrm_get_ls_cache");
        this->ctx = tsrm_get_ls_cache();

        if(!this->ctx) {

            PQDBGLPUP("tsrm_new_interpreter_context");
            this->ctx = tsrm_new_interpreter_context();

            PQDBGLPUP("php_request_startup");
            php_request_startup();

            /*
            PQDBGLPUP("get interpreter context from thread");
            void *TSRMLS_CACHE;
            bool php_started;

            QMetaObject::invokeMethod(this->thread(), "get_ls_cache",
                                      Qt::DirectConnection,
                                      Q_RETURN_ARG(void*, TSRMLS_CACHE));

            if(!TSRMLS_CACHE) {
                php_error(E_ERROR, "Failed getting interpreter context from thread");
            }

            QMetaObject::invokeMethod(this->thread(), "php_started",
                                      Qt::DirectConnection,
                                      Q_RETURN_ARG(bool, php_started));

            PQDBGLPUP(QString("tsrm_set_interpreter_context %1")
                      .arg(reinterpret_cast<quint64>(TSRMLS_CACHE)));

            this->ctx = TSRMLS_CACHE;
            tsrm_set_interpreter_context(TSRMLS_CACHE);

            if(!php_started) {
                PQDBGLPUP("php_request_startup");
                php_request_startup();

                QMetaObject::invokeMethod(this->thread(), "set_php_started",
                                          Qt::DirectConnection);
            }

            //PQDBGLPUP("php_request_startup");
            //php_request_startup();
            */
        }
    }

    argc++; // the first argument for PHP-slots it is a PHP-object sender

    zval function_name, retval, z_receiver;
    zval *params = new zval[argc];

    ZVAL_STRING(&function_name, slotName.constData());
    ZVAL_OBJ(&z_receiver, zo_receiver);

    ZVAL_OBJ(&params[0], zo_sender);

    for(int i = 1; i < argc; i++) {
        QVariant arg = args.at(i-1);
        params[i] = PHPQt5::pq_cast_to_zval(arg, true PQDBG_LVL_CC);
    }

#ifdef PQDEBUG
    PQDBGLPUP(QString("call function (%1)").arg(reinterpret_cast<quint64>(&z_receiver)));
#endif
    //zend_call_method(&z_receiver, Z_OBJCE(z_receiver), NULL, ZEND_STRL("run"), &retval, 0, NULL, NULL);
    if(call_user_function(nullptr, &z_receiver, &function_name, &retval, argc, params) == FAILURE) {
        QString s = QString("PHPQt5 could not call method: %1 of class: %2")
                .arg(Z_STRVAL(function_name))
                .arg(Z_OBJCE(z_receiver)->name->val);

        php_error(E_ERROR, s.toUtf8().constData());
    }

#ifdef PQDEBUG
    PQDBGLPUP("dtor params");
#endif
    for(int i = 1; i < argc; i++) { // do not remove sender!
        zval_dtor(&params[i]);
    }

#ifdef PQDEBUG
    PQDBGLPUP("dtor temps");
#endif

    delete params;
    params = nullptr;

    zval_dtor(&retval);
    zval_dtor(&function_name);

    /*
    if(createNewCtx) {
        #ifdef PQDEBUG
                PQDBGLPUP("php_request_shutdown");
        #endif
        php_request_shutdown(nullptr);

        #ifdef PQDEBUG
                PQDBGLPUP("tsrm_free_interpreter_context");
        #endif
        tsrm_free_interpreter_context(ctx);
    }
    */

    PQDBG_LVL_DONE();
}
Esempio n. 3
0
int32_t ScriptEngine::executeWebRequest(const std::string& path, BaseLib::HTTP& request, std::shared_ptr<BaseLib::Rpc::ServerInfo::Info>& serverInfo, std::shared_ptr<BaseLib::SocketOperations>& socket)
{
	if(_disposing) return 1;
	if(!GD::bl->io.fileExists(path))
	{
		GD::out.printError("Error: PHP script \"" + path + "\" does not exist.");
		return -1;
	}
	ts_resource_ex(0, NULL); //Replaces TSRMLS_FETCH()
	try
	{
		zend_file_handle script;

		script.type = ZEND_HANDLE_FILENAME;
		script.filename = path.c_str();
		script.opened_path = NULL;
		script.free_filename = 0;

		zend_homegear_globals* globals = php_homegear_get_globals();
		if(!globals)
		{
			ts_free_thread();
			return -1;
		}
		globals->socket = socket.get();
		globals->http = &request;

		if(!tsrm_get_ls_cache())
		{
			GD::out.printCritical("Critical: Error in PHP: No thread safe resource exists (1).");
			ts_free_thread();
			return -1;
		}
		if(!((sapi_globals_struct *) (*((void ***) tsrm_get_ls_cache()))[((sapi_globals_id)-1)]))
		{
			GD::out.printCritical("Critical: Error in PHP: No thread safe resource exists (2).");
			ts_free_thread();
			return -1;
		}
		SG(server_context) = (void*)serverInfo.get(); //Must be defined! Otherwise POST data is not processed.
		SG(sapi_headers).http_response_code = 200;
		SG(default_mimetype) = nullptr;
		SG(default_charset) = nullptr;
		SG(request_info).content_length = request.getHeader()->contentLength;
		if(!request.getHeader()->contentType.empty()) SG(request_info).content_type = request.getHeader()->contentType.c_str();
		SG(request_info).request_method = request.getHeader()->method.c_str();
		SG(request_info).proto_num = request.getHeader()->protocol == BaseLib::HTTP::Protocol::http10 ? 1000 : 1001;
		std::string uri = request.getHeader()->path + request.getHeader()->pathInfo;
		if(!request.getHeader()->args.empty()) uri.append('?' + request.getHeader()->args);
		if(!request.getHeader()->args.empty()) SG(request_info).query_string = estrndup(&request.getHeader()->args.at(0), request.getHeader()->args.size());
		if(!uri.empty()) SG(request_info).request_uri = estrndup(&uri.at(0), uri.size());
		std::string pathTranslated = serverInfo->contentPath.substr(0, serverInfo->contentPath.size() - 1) + request.getHeader()->pathInfo;
		SG(request_info).path_translated = estrndup(&pathTranslated.at(0), pathTranslated.size());

		if (php_request_startup() == FAILURE) {
			GD::bl->out.printError("Error calling php_request_startup...");
			ts_free_thread();
			return 1;
		}

		php_execute_script(&script);

		int32_t exitCode = EG(exit_status);

		if(SG(request_info).query_string)
		{
			efree(SG(request_info).query_string);
			SG(request_info).query_string = nullptr;
		}
		if(SG(request_info).request_uri)
		{
			efree(SG(request_info).request_uri);
			SG(request_info).request_uri = nullptr;
		}
		if(SG(request_info).path_translated)
		{
			efree(SG(request_info).path_translated);
			SG(request_info).path_translated = nullptr;
		}

		php_request_shutdown(NULL);

		ts_free_thread();
		return exitCode;
	}
	catch(const std::exception& ex)
	{
		GD::bl->out.printEx(__FILE__, __LINE__, __PRETTY_FUNCTION__, ex.what());
	}
	catch(BaseLib::Exception& ex)
	{
		GD::bl->out.printEx(__FILE__, __LINE__, __PRETTY_FUNCTION__, ex.what());
	}
	catch(...)
	{
		GD::bl->out.printEx(__FILE__, __LINE__, __PRETTY_FUNCTION__);
	}
	std::string error("Error executing script. Check Homegear log for more details.");
	if(socket) php_homegear_write_socket(socket.get(), error.c_str(), error.length());
	if(SG(request_info).query_string)
	{
		efree(SG(request_info).query_string);
		SG(request_info).query_string = nullptr;
	}
	if(SG(request_info).request_uri)
	{
		efree(SG(request_info).request_uri);
		SG(request_info).request_uri = nullptr;
	}
	if(SG(request_info).path_translated)
	{
		efree(SG(request_info).path_translated);
		SG(request_info).path_translated = nullptr;
	}
	ts_free_thread();
	return 1;
}
Esempio n. 4
0
bool ScriptEngine::checkSessionId(const std::string& sessionId)
{
	if(_disposing) return false;
	std::unique_ptr<BaseLib::HTTP> request(new BaseLib::HTTP());
	ts_resource_ex(0, NULL); //Replaces TSRMLS_FETCH()
	try
	{
		zend_homegear_globals* globals = php_homegear_get_globals();
		if(!globals)
		{
			ts_free_thread();
			return false;
		}
		globals->http = request.get();

		if(!tsrm_get_ls_cache() || !((sapi_globals_struct *) (*((void ***) tsrm_get_ls_cache()))[((sapi_globals_id)-1)]))
		{
			GD::out.printCritical("Critical: Error in PHP: No thread safe resource exists.");
			ts_free_thread();
			return false;
		}
		SG(server_context) = (void*)request.get(); //Must be defined! Otherwise POST data is not processed.
		SG(sapi_headers).http_response_code = 200;
		SG(default_mimetype) = nullptr;
		SG(default_charset) = nullptr;
		SG(request_info).content_length = 0;
		SG(request_info).request_method = "GET";
		SG(request_info).proto_num = 1001;
		request->getHeader()->cookie = "PHPSESSID=" + sessionId;

		if (php_request_startup(TSRMLS_C) == FAILURE) {
			GD::bl->out.printError("Error calling php_request_startup...");
			ts_free_thread();
			return false;
		}

		zval returnValue;
		zval function;

		ZVAL_STRING(&function, "session_start");
		call_user_function(EG(function_table), NULL, &function, &returnValue, 0, nullptr);

		bool result = false;
		zval* reference = zend_hash_str_find(&EG(symbol_table), "_SESSION", sizeof("_SESSION") - 1);
		if(reference != NULL)
		{
			if(Z_ISREF_P(reference) && Z_RES_P(reference)->ptr && Z_TYPE_P(Z_REFVAL_P(reference)) == IS_ARRAY)
			{
				zval* token = zend_hash_str_find(Z_ARRVAL_P(Z_REFVAL_P(reference)), "authorized", sizeof("authorized") - 1);
				if(token != NULL)
				{
					result = (Z_TYPE_P(token) == IS_TRUE);
				}
			}
        }

		php_request_shutdown(NULL);

		ts_free_thread();
		return result;
	}
	catch(const std::exception& ex)
	{
		GD::bl->out.printEx(__FILE__, __LINE__, __PRETTY_FUNCTION__, ex.what());
	}
	catch(BaseLib::Exception& ex)
	{
		GD::bl->out.printEx(__FILE__, __LINE__, __PRETTY_FUNCTION__, ex.what());
	}
	catch(...)
	{
		GD::bl->out.printEx(__FILE__, __LINE__, __PRETTY_FUNCTION__);
	}
	std::string error("Error executing script. Check Homegear log for more details.");
	ts_free_thread();
	return false;
}
Esempio n. 5
0
void ScriptEngine::execute(const std::string path, const std::string arguments, std::shared_ptr<std::vector<char>> output, int32_t* exitCode, bool wait, int32_t threadId)
{
	try
	{
		if(_disposing)
		{
			setThreadNotRunning(threadId);
			return;
		}
		if(path.empty())
		{
			//No thread yet
			return;
		}
		if(!output) output.reset(new std::vector<char>());
		if(!wait)
		{
			collectGarbage();
			if(!scriptThreadMaxReached())
			{
				_scriptThreadMutex.lock();
				try
				{
					int32_t threadId = _currentScriptThreadID++;
					if(threadId == -1) threadId = _currentScriptThreadID++;
					_scriptThreads.insert(std::pair<int32_t, std::pair<std::thread, bool>>(threadId, std::pair<std::thread, bool>(std::thread(&ScriptEngine::execute, this, path, arguments, output, nullptr, true, threadId), true)));
				}
				catch(const std::exception& ex)
				{
					GD::out.printEx(__FILE__, __LINE__, __PRETTY_FUNCTION__, ex.what());
				}
				catch(...)
				{
					GD::out.printEx(__FILE__, __LINE__, __PRETTY_FUNCTION__);
				}
				_scriptThreadMutex.unlock();
			}
			if(exitCode) *exitCode = 0;
			//No thread yet
			return;
		}
	}
	catch(const std::exception& ex)
	{
		GD::bl->out.printEx(__FILE__, __LINE__, __PRETTY_FUNCTION__, ex.what());
		setThreadNotRunning(threadId);
		return;
	}
	catch(BaseLib::Exception& ex)
	{
		GD::bl->out.printEx(__FILE__, __LINE__, __PRETTY_FUNCTION__, ex.what());
		setThreadNotRunning(threadId);
		return;
	}
	catch(...)
	{
		GD::bl->out.printEx(__FILE__, __LINE__, __PRETTY_FUNCTION__);
		setThreadNotRunning(threadId);
		return;
	}
	if(exitCode) *exitCode = -1;
	if(!GD::bl->io.fileExists(path))
	{
		GD::out.printError("Error: PHP script \"" + path + "\" does not exist.");
		setThreadNotRunning(threadId);
		return;
	}
	ts_resource_ex(0, NULL); //Replaces TSRMLS_FETCH()
	try
	{
		zend_file_handle script;

		/* Set up a File Handle structure */
		script.type = ZEND_HANDLE_FILENAME;
		script.filename = path.c_str();
		script.opened_path = NULL;
		script.free_filename = 0;

		zend_homegear_globals* globals = php_homegear_get_globals();
		if(!globals)
		{
			ts_free_thread();
			setThreadNotRunning(threadId);
			return;
		}
		globals->output = output.get();
		globals->commandLine = true;
		globals->cookiesParsed = true;

		if(!tsrm_get_ls_cache() || !((sapi_globals_struct *) (*((void ***) tsrm_get_ls_cache()))[((sapi_globals_id)-1)]) || !((php_core_globals *) (*((void ***) tsrm_get_ls_cache()))[((core_globals_id)-1)]))
		{
			GD::out.printCritical("Critical: Error in PHP: No thread safe resource exists.");
			ts_free_thread();
			setThreadNotRunning(threadId);
			return;
		}
		PG(register_argc_argv) = 1;
		SG(server_context) = (void*)output.get(); //Must be defined! Otherwise php_homegear_activate is not called.
		SG(options) |= SAPI_OPTION_NO_CHDIR;
		SG(headers_sent) = 1;
		SG(request_info).no_headers = 1;
		SG(default_mimetype) = nullptr;
		SG(default_charset) = nullptr;
		SG(request_info).path_translated = estrndup(path.c_str(), path.size());

		if (php_request_startup(TSRMLS_C) == FAILURE) {
			GD::bl->out.printError("Error calling php_request_startup...");
			ts_free_thread();
			setThreadNotRunning(threadId);
			return;
		}

		std::vector<std::string> argv = getArgs(path, arguments);
		php_homegear_build_argv(argv);
		SG(request_info).argc = argv.size();
		SG(request_info).argv = (char**)malloc((argv.size() + 1) * sizeof(char*));
		for(uint32_t i = 0; i < argv.size(); ++i)
		{
			SG(request_info).argv[i] = (char*)argv[i].c_str(); //Value is not modified.
		}
		SG(request_info).argv[argv.size()] = nullptr;

		php_execute_script(&script);
		if(exitCode) *exitCode = EG(exit_status);

		php_request_shutdown(NULL);
		if(output->size() > 0)
		{
			std::string outputString(&output->at(0), output->size());
			if(BaseLib::HelperFunctions::trim(outputString).size() > 0) GD::out.printMessage("Script output:\n" + outputString);
		}
	}
	catch(const std::exception& ex)
	{
		GD::bl->out.printEx(__FILE__, __LINE__, __PRETTY_FUNCTION__, ex.what());
	}
	catch(BaseLib::Exception& ex)
	{
		GD::bl->out.printEx(__FILE__, __LINE__, __PRETTY_FUNCTION__, ex.what());
	}
	catch(...)
	{
		GD::bl->out.printEx(__FILE__, __LINE__, __PRETTY_FUNCTION__);
	}
	if(SG(request_info).path_translated)
	{
		efree(SG(request_info).query_string);
		SG(request_info).query_string = nullptr;
	}
	if(SG(request_info).argv)
	{
		free(SG(request_info).argv);
		SG(request_info).argv = nullptr;
	}
	SG(request_info).argc = 0;
	ts_free_thread();
	setThreadNotRunning(threadId);
}