#include "php_wrenchboard_api.h" #include "php_wrenchboard_api_ns.h" #include "wrenchboard.h" #include "cfg.h" #include "clog.h" #include "vars.h" #include "safestring.h" #include #include #include zend_object_handlers wrenchboard_object_handlers; typedef struct _wrenchboard_object { WrenchBoard *wrenchboard; zend_object std; } wrenchboard_object; static inline wrenchboard_object *php_wrenchboard_obj_from_obj(zend_object *obj) { return (wrenchboard_object*)((char*)(obj) - XtOffsetOf(wrenchboard_object, std)); } #define Z_TSTOBJ_P(zv) php_wrenchboard_obj_from_obj(Z_OBJ_P((zv))) zend_class_entry *wrenchboard_ce; #define SET_ENV( env ) \ if (NULL != (token = zend_hash_str_find(_SERVER, env, sizeof(env)-1))) {\ setenv( env, Z_STRVAL_P(token), 1 ); \ logfmt( logINFO, env " = %s", Z_STRVAL_P(token) ); \ } else {\ unsetenv( env );\ } // ------------------------------------------------------------------ // ------------------------------------------------------------------ PHP_METHOD(WrenchBoard, __construct) { HashTable *_SERVER; zval *token; zval *id = getThis(); wrenchboard_object *intern; intern = Z_TSTOBJ_P(id); if(intern != NULL) { intern->wrenchboard = new WrenchBoard(); // Load some _SERVER data into environment zend_string *_server = zend_string_init("_SERVER", strlen("_SERVER"), 0); zend_is_auto_global(_server); if (Z_TYPE(PG(http_globals)[TRACK_VARS_SERVER]) == IS_UNDEF) { logfmt( logINFO, "_SERVER not found" ); } else { logfmt( logINFO, "_SERVER found" ); _SERVER = Z_ARRVAL(PG(http_globals)[TRACK_VARS_SERVER]); SET_ENV( "REMOTE_ADDR" ); SET_ENV( "SERVER_NAME" ); SET_ENV( "HTTP_COOKIE" ); SET_ENV( "QUERY_STRING" ); SET_ENV( "HTTP_X_FORWARDED_FOR" ); } zend_string_release(_server); intern->wrenchboard->logMessage("Constructor finished"); } } // ------------------------------------------------------------------ // ------------------------------------------------------------------ PHP_METHOD(WrenchBoard, wrenchboard_api) { zval *param, *param_out; zval *id = getThis(); wrenchboard_object *intern; CVars input, output; /* if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz", ¶m, ¶m_out) == FAILURE) { // Bad parameters RETURN_NULL(); } */ // https://wiki.php.net/rfc/fast_zpp ZEND_PARSE_PARAMETERS_START(2, 2) Z_PARAM_ARRAY_EX(param, 0, 1) Z_PARAM_ARRAY_EX(param_out, 0, 1) ZEND_PARSE_PARAMETERS_END(); intern = Z_TSTOBJ_P(id); if(intern != NULL) { // Convert input HashTable *hash; zend_string *key, val; ulong num_key; uint key_len; zval *value; convert_to_array_ex( param ); hash = HASH_OF( param ); zend_hash_internal_pointer_reset( hash ); ZEND_HASH_FOREACH_KEY_VAL(hash, num_key, key, value) { if (key) { //HASH_KEY_IS_STRING if (Z_TYPE_P(value) == IS_STRING) { input[ ZSTR_VAL(key) ] = Z_STRVAL_P(value); /* } else if (Z_TYPE_P(value) == IS_LONG) { input[ ZSTR_VAL(key) ] = Z_LVAL_P(value); } else if (Z_TYPE_P(value) == IS_DOUBLE) { input[ ZSTR_VAL(key) ] = Z_DVAL_P(value); } else if (Z_TYPE_P(value) == _IS_BOOL) { input[ ZSTR_VAL(key) ] = Z_BVAL(value) ? 1L : 0L; } else if (Z_TYPE_P(value) == IS_NULL) { input[ ZSTR_VAL(key) ] = ""; */ } else { //logfmt( logINFO, "Item %s has unsupported value type", ZSTR_VAL(key) ); convert_to_string(value); input[ ZSTR_VAL(key) ] = Z_STRVAL_P(value); } } } ZEND_HASH_FOREACH_END(); long retval = intern->wrenchboard->wrenchboard_api(input, output); // Convert output convert_to_array_ex( param_out ); CVars::iterator i; const int out_size = output.size(); // 200 const int out_value_size = 200; char out_key[out_value_size], out_value[out_value_size]; if (!output.empty()) { // array_init(param_out); // deferences variable & nothing comes out :( // for ( i=output.begin(); i != output.end() && jfirst.c_str(), i->second.c_str() ); strsafecpy( out_key, i->first.c_str(), out_value_size ); strsafecpy( out_value, i->second.c_str(), out_value_size ); if (strlen(out_key)>0) { /* char *str; str = estrdup(i->second.c_str()); add_assoc_string( param_out, out_key, str, 0); */ //add_assoc_string( param_out, out_key, out_value); add_assoc_string_ex( param_out, out_key, strlen(out_key), out_value); } //SAFE_STRING //efree(out_value); output.erase(output.begin()); } //RETURN_ZVAL(param_out, 0, 0); // Possible workaround to return array } logfmt( logDEBUG, "About to return %ld", retval ); RETURN_LONG(retval); } RETURN_NULL(); } // ------------------------------------------------------------------ // ------------------------------------------------------------------ PHP_METHOD(WrenchBoard, cfgReadChar) { char *parameter = NULL; size_t parameter_len = 0; zval *id = getThis(); wrenchboard_object *intern; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", ¶meter, ¶meter_len) == FAILURE) { RETURN_NULL(); } intern = Z_TSTOBJ_P(id); if(intern != NULL) { std::stringstream msg; msg << "PHP_METHOD(WrenchBoard, cfgReadChar):"; msg << (char*)parameter; intern->wrenchboard->logMessage(msg.str().c_str()); std::string s = intern->wrenchboard->cfgReadChar((char*)parameter); msg << " = " << s; intern->wrenchboard->logMessage(msg.str().c_str()); RETURN_STRING(s.c_str()); } RETURN_NULL(); } // DEBUG: // gdb --args php -f i.php // sysctl -w kernel.core_pattern=/opt/mainsite/wrenchboard/www/core.%e.%p.%h.%t // ------------------------------------------------------------------ // ------------------------------------------------------------------ PHP_METHOD(WrenchBoard, cfgReadLong) { char *parameter = NULL; size_t parameter_len = 0; zval *id = getThis(); wrenchboard_object *intern; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", ¶meter, ¶meter_len) == FAILURE) { RETURN_NULL(); } intern = Z_TSTOBJ_P(id); if(intern != NULL) { intern->wrenchboard->logMessage("PHP_METHOD(WrenchBoard, cfgReadLong)"); long l = intern->wrenchboard->cfgReadLong((char*)parameter); RETURN_LONG(l); } RETURN_NULL(); } // ------------------------------------------------------------------ // ------------------------------------------------------------------ PHP_METHOD(WrenchBoard, logMessage) { char *message = NULL; size_t message_len = 0; zval *id = getThis(); wrenchboard_object *intern; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &message, &message_len) == FAILURE) { RETURN_FALSE; } intern = Z_TSTOBJ_P(id); if(intern != NULL) { intern->wrenchboard->logMessage((char*)message); RETURN_TRUE; } RETURN_FALSE; } // ------------------------------------------------------------------ // ------------------------------------------------------------------ // https://www.phpinternalsbook.com/php7/extensions_design/php_functions.html // https://github.com/php/php-src/blob/master/Zend/zend_builtin_functions_arginfo.h // ZEND_BEGIN_ARG_INFO_EX(name, _unused, return_reference, required_num_args) // ZEND_ARG_INFO(pass_by_ref, name) // ZEND_ARG_OBJ_INFO(pass_by_ref, name, classname, allow_null) // ZEND_ARG_ARRAY_INFO(pass_by_ref, name, allow_null) // ZEND_ARG_CALLABLE_INFO(pass_by_ref, name, allow_null) // ZEND_ARG_TYPE_INFO(pass_by_ref, name, type_hint, allow_null) // ZEND_ARG_VARIADIC_INFO(pass_by_ref, name) // ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_void, 0, 0, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_string, 0, 0, 1) ZEND_ARG_TYPE_INFO(0, str, IS_STRING, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_api, 0, 0, 2) //ZEND_ARG_TYPE_INFO(1, in, IS_ARRAY, 0) //ZEND_ARG_TYPE_INFO(1, out, IS_ARRAY, 0) ZEND_ARG_ARRAY_INFO(1, in, 0) ZEND_ARG_ARRAY_INFO(1, out, 0) ZEND_END_ARG_INFO() // ------------------------------------------------------------------ // ------------------------------------------------------------------ const zend_function_entry wrenchboard_methods[] = { PHP_ME(WrenchBoard, __construct, arginfo_void, ZEND_ACC_PUBLIC | ZEND_ACC_CTOR) PHP_ME(WrenchBoard, wrenchboard_api, arginfo_api, ZEND_ACC_PUBLIC) PHP_ME(WrenchBoard, cfgReadChar, arginfo_string, ZEND_ACC_PUBLIC) PHP_ME(WrenchBoard, cfgReadLong, arginfo_string, ZEND_ACC_PUBLIC) PHP_ME(WrenchBoard, logMessage, arginfo_string, ZEND_ACC_PUBLIC) PHP_FE_END }; // ------------------------------------------------------------------ // ------------------------------------------------------------------ zend_object *wrenchboard_object_new(zend_class_entry *ce TSRMLS_DC) { wrenchboard_object *intern = (wrenchboard_object*)ecalloc(1, sizeof(wrenchboard_object) + zend_object_properties_size(ce)); zend_object_std_init(&intern->std, ce TSRMLS_CC); object_properties_init(&intern->std, ce); intern->std.handlers = &wrenchboard_object_handlers; return &intern->std; } // ------------------------------------------------------------------ // ------------------------------------------------------------------ static void wrenchboard_object_destroy(zend_object *object) { wrenchboard_object *my_obj; my_obj = (wrenchboard_object*)((char *) object - XtOffsetOf(wrenchboard_object, std)); // Call __destruct() from user-land. zend_objects_destroy_object(object); } static void wrenchboard_object_free(zend_object *object) { wrenchboard_object *my_obj; my_obj = (wrenchboard_object *)((char *) object - XtOffsetOf(wrenchboard_object, std)); delete my_obj->wrenchboard; // Free the object using Zend macro. zend_object_std_dtor(object); } // ------------------------------------------------------------------ // ------------------------------------------------------------------ PHP_MINIT_FUNCTION(twrenchboardapit) { zend_class_entry ce; INIT_NS_CLASS_ENTRY(ce, WRENCHBOARD_API_NS, "WrenchBoard", wrenchboard_methods); wrenchboard_ce = zend_register_internal_class(&ce TSRMLS_CC); wrenchboard_ce->create_object = wrenchboard_object_new; memcpy(&wrenchboard_object_handlers, zend_get_std_object_handlers(), sizeof(wrenchboard_object_handlers)); // Handler for free'ing the object. wrenchboard_object_handlers.free_obj = wrenchboard_object_free; // Handler for the destructor. wrenchboard_object_handlers.dtor_obj = wrenchboard_object_destroy; // Offset into the engine. wrenchboard_object_handlers.offset = XtOffsetOf(wrenchboard_object, std); return SUCCESS; } // ------------------------------------------------------------------ // ------------------------------------------------------------------ PHP_MINFO_FUNCTION(twrenchboardapit) { php_info_print_table_start(); php_info_print_table_row(2, "WRENCHBOARD API support", "enabled"); php_info_print_table_row(2, "Log File", WRENCHBOARD_LOG); php_info_print_table_row(2, "Config File", WRENCHBOARD_CONFIG"wrenchboard_api.conf"); php_info_print_table_row(2, "Build Date", __DATE__); php_info_print_table_row(2, "Build Time", __TIME__); php_info_print_table_row(2, "Namespace", WRENCHBOARD_API_NS); php_info_print_table_row(2, "Version", PHP_WRENCHBOARD_API_EXTVER); php_info_print_table_end(); } // ------------------------------------------------------------------ // ------------------------------------------------------------------ zend_module_entry twrenchboardapit_module_entry = { #if ZEND_MODULE_API_NO >= 20010901 STANDARD_MODULE_HEADER, #endif PHP_WRENCHBOARD_API_EXTNAME, NULL, /* Functions */ PHP_MINIT(twrenchboardapit), NULL, /* MSHUTDOWN */ NULL, /* RINIT */ NULL, /* RSHUTDOWN */ PHP_MINFO(twrenchboardapit), /* MINFO */ #if ZEND_MODULE_API_NO >= 20010901 PHP_WRENCHBOARD_API_EXTVER, #endif STANDARD_MODULE_PROPERTIES }; //#ifdef COMPILE_DL_WRENCHBOARD_API extern "C" { ZEND_GET_MODULE(twrenchboardapit) } //#endif