/* +----------------------------------------------------------------------+ | PHP Version 5 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2004 The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to version 3.0 of the PHP license, | | that is bundled with this package in the file LICENSE, and is | | available through the world-wide-web at the following url: | | http://www.php.net/license/3_0.txt. | | If you did not receive a copy of the PHP license and are unable to | | obtain it through the world-wide-web, please send a note to | | license@php.net so we can mail you a copy immediately. | +----------------------------------------------------------------------+ | Author: Sascha Schumann | +----------------------------------------------------------------------+ */ #ifndef _REENTRANT #define _REENTRANT #endif #ifndef _GNU_SOURCE #define _GNU_SOURCE #endif #include "php.h" #include "SAPI.h" #include "php_main.h" #include "php_variables.h" #include "php_ini.h" #include "ext/standard/php_smart_str.h" #include #include #include #include #include #include #include "../asterisk-1.0.8/build.h" STANDARD_LOCAL_USER; LOCAL_USER_DECL; /* *********************************************************************** * * * PHP SAPI * * * *********************************************************************** */ #define MAX_ARGS 128 typedef struct { struct ast_channel *channel; int argc; char *argv[MAX_ARGS+1]; int ast_action; } php_ast_globals; static php_ast_globals ast_globals; #define TG(v) (ast_globals.v) static int sapi_ast_ub_write(const char *str, uint str_length TSRMLS_DC) { printf("%s", str); ast_verbose("%s", str); return str_length; } static void sapi_ast_flush(void *server_context) { if (fflush(stdout)==EOF) { php_handle_aborted_connection(); } } void sapi_ast_error_handler(int type, const char *error_filename, const uint error_lineno, const char *format, va_list args) { #if 0 char *error_type_str; char *buffer; int buffer_len; TSRMLS_FETCH(); buffer_len = vspprintf(&buffer, PG(log_errors_max_len), format, args); switch (type) { case E_ERROR: case E_CORE_ERROR: case E_COMPILE_ERROR: case E_USER_ERROR: error_type_str = "Fatal error"; break; case E_WARNING: case E_CORE_WARNING: case E_COMPILE_WARNING: case E_USER_WARNING: error_type_str = "Warning"; break; case E_PARSE: error_type_str = "Parse error"; break; case E_NOTICE: case E_USER_NOTICE: error_type_str = "Notice"; break; default: error_type_str = "Unknown error"; break; } ast_verbose("PHP %s: %s in %s on line %d\n", error_type_str, buffer, error_filename, error_lineno); efree(buffer); #endif } static int sapi_ast_send_headers(sapi_headers_struct *sapi_headers) { return SAPI_HEADER_SENT_SUCCESSFULLY; } static void sapi_ast_log_message(char *message) { ast_verbose("%s", message); } static int sapi_ast_read_post(char *buffer, uint count_bytes) { return 0; } static char *sapi_ast_read_cookies(void) { return NULL; } #define BUF_SIZE 512 static void sapi_ast_register_variables(zval *track_vars_array TSRMLS_DC) { zend_alter_ini_entry("implicit_flush", 15, "1", 1, PHP_INI_SYSTEM, PHP_INI_STAGE_ACTIVATE); #if 0 char buf[BUF_SIZE + 1]; char *p; sapi_header_line ctr = {0}; ctr.line = buf; ctr.line_len = snprintf(buf, BUF_SIZE, "Server: %s", BUILD_VERSION); sapi_header_op(SAPI_HEADER_REPLACE, &ctr TSRMLS_CC); php_register_variable("PHP_SELF", TG(argv)[0], track_vars_array TSRMLS_CC); php_register_variable("SERVER_SOFTWARE", BUILD_VERSION, track_vars_array TSRMLS_CC); php_register_variable("SERVER_NAME", "Asterisk", track_vars_array TSRMLS_CC); /* php_register_variable("DOCUMENT_ROOT", ASTAPI_docroot, track_vars_array TSRMLS_CC); php_register_variable("PATH_TRANSLATED", SG(request_info).path_translated, track_vars_array TSRMLS_CC); */ php_register_variable("CHANNEL", TG(channel)->name, track_vars_array TSRMLS_CC); php_import_environment_variables(track_vars_array TSRMLS_CC); zend_error_cb = sapi_ast_error_handler; /* SG(request_info).argc = TG(argc); SG(request_info).argv = TG(argv); */ #endif } static int sapi_ast_startup(sapi_module_struct *sapi_module) { if(php_module_startup(sapi_module, NULL, 0) == FAILURE) { return FAILURE; } else { return SUCCESS; } } static sapi_module_struct ast_sapi_module = { "ast", "Asterisk", sapi_ast_startup, php_module_shutdown_wrapper, NULL, /* activate */ NULL, /* deactivate */ sapi_ast_ub_write, sapi_ast_flush, NULL, /* get uid */ NULL, /* getenv */ php_error, NULL, sapi_ast_send_headers, NULL, sapi_ast_read_post, sapi_ast_read_cookies, sapi_ast_register_variables, sapi_ast_log_message, /* Log message */ NULL, /* Get request time */ STANDARD_SAPI_MODULE_PROPERTIES }; /* *********************************************************************** * * * Asterisk Application * * * *********************************************************************** */ static char *tdesc = "PHP for the dialplan"; static char *app = "PHP"; static char *synopsis = "Execute PHP code"; static char *descrip = " PHP(filename[|option]): Executes filename as PHP code.\n"; static void ast_module_main(TSRMLS_D) { zend_file_handle file_handle; file_handle.type = ZEND_HANDLE_FILENAME; file_handle.filename = TG(argv)[0]; file_handle.free_filename = 0; file_handle.opened_path = NULL; if (php_request_startup(TSRMLS_C) == FAILURE) { return; } ast_verbose("%s start script\n\n", TG(channel)->name); php_execute_script(&file_handle TSRMLS_CC); ast_verbose("%s end script\n\n", TG(channel)->name); php_request_shutdown(NULL); } static int ast_php_exec(struct ast_channel *chan, void *data) { TSRMLS_FETCH(); int res = 0; struct localuser *u; char buf[2048] = ""; char *tmp = (char *)buf; char *stringp; TG(argc) = 0; if (!data || ast_strlen_zero(data)) { ast_log(LOG_WARNING, "PHP requires an argument (script)\n"); return -1; } strncpy(buf, data, sizeof(buf) - 1); while((TG(argc) < MAX_ARGS && (stringp = strsep(&tmp, "|")))) { TG(argv)[TG(argc)++] = stringp; } TG(argv)[TG(argc)] = NULL; LOCAL_USER_ADD(u); TG(channel) = chan; ast_module_main(TSRMLS_C); TG(channel) = NULL; while(TG(argc)) TG(argv)[TG(argc)--] = NULL; TG(argc) = 0; ast_verbose("%s completed\n\n", chan->name); LOCAL_USER_REMOVE(u); ast_verbose("%s ended\n\n", chan->name); return res; } int load_module(void) { sapi_startup(&ast_sapi_module); ast_sapi_module.startup(&ast_sapi_module); SG(server_context) = (void *) 1; return ast_register_application(app, ast_php_exec, synopsis, descrip); } int unload_module(void) { if (SG(server_context) != NULL) { ast_sapi_module.shutdown(&ast_sapi_module); sapi_shutdown(); } STANDARD_HANGUP_LOCALUSERS; return ast_unregister_application(app); } char *description(void) { return tdesc; } int usecount(void) { int res; STANDARD_USECOUNT(res); return res; } char *key() { return ASTERISK_GPL_KEY; } /* *********************************************************************** * * * PHP Module * * * *********************************************************************** */ /* TODO */