cvs: php4 /ext/ircg .cvsignore Makefile.in config.m4 ircg.c ircg.php php_ircg.h

From: Date: Mon, 13 Nov 2000 14:51:09 +0000
Subject: cvs: php4 /ext/ircg .cvsignore Makefile.in config.m4 ircg.c ircg.php php_ircg.h
Groups: php.cvs 
Request: Send a blank email to php-cvs+get-2575@lists.php.net to get a copy of this message
sas Mon Nov 13 06:51:09 2000 EDT Added files: /php4/ext/ircg .cvsignore Makefile.in config.m4 ircg.c ircg.php php_ircg.h Log: V0.1 of a duplex HTTP/IRC Gateway. You can join arbitrary channels, send messages to arbitrary targets, and quit by hitting the stop button. The cool part of this extension is that it does not tie up a complete thread/process for one user. Instead, it keeps a connection open after finishing the PHP script. Since connections are only an entry in some table in thttpd, it allows us to handle arbitrary numbers of connections. TODO: - Allow sending of arbitrary IRC commands. - Allow customization of message output. A complete web-chat employing PHP 4 Sessions and IRCG is about 70 lines long. =)

Index: php4/ext/ircg/.cvsignore +++ php4/ext/ircg/.cvsignore deps Makefile *.o *.lo *.la libs libs.mk Index: php4/ext/ircg/Makefile.in +++ php4/ext/ircg/Makefile.in # $Id: Makefile.in,v 1.1 2000/11/13 14:51:09 sas Exp $ LTLIBRARY_NAME = libircg.la LTLIBRARY_SOURCES = ircg.c LTLIBRARY_SHARED_NAME = ircg.la LTLIBRARY_SHARED_LIBADD = $(IRCG_SHARED_LIBADD) include $(top_srcdir)/build/dynlib.mk Index: php4/ext/ircg/config.m4 +++ php4/ext/ircg/config.m4 PHP_ARG_WITH(ircg, for ircg support, [ --with-ircg Include ircg support]) if test "$PHP_IRCG" != "no"; then AC_ADD_LIBRARY(st) AC_ADD_LIBRARY_WITH_PATH(ircg, $PHP_IRCG/lib) AC_ADD_INCLUDE($PHP_IRCG/include) AC_DEFINE(HAVE_IRCG, 1, [ ]) PHP_EXTENSION(ircg, $ext_shared) fi Index: php4/ext/ircg/ircg.c +++ php4/ext/ircg/ircg.c /* +----------------------------------------------------------------------+ | PHP version 4.0 | +----------------------------------------------------------------------+ | Copyright (c) 1997, 1998, 1999, 2000 The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to version 2.02 of the PHP license, | | that is bundled with this package in the file LICENSE, and is | | available at through the world-wide-web at | | http://www.php.net/license/2_02.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. | +----------------------------------------------------------------------+ | Authors: Sascha Schumann <sascha@schumann.cx> | +----------------------------------------------------------------------+ */ #include "php.h" #include "php_ini.h" #include "php_ircg.h" #include "ext/standard/info.h" /* If you declare any globals in php_ircg.h uncomment this: ZEND_DECLARE_MODULE_GLOBALS(ircg) */ static HashTable h_fd2irconn; static HashTable h_irconn; static int irconn_id; /* Every user visible function must have an entry in ircg_functions[]. */ function_entry ircg_functions[] = { PHP_FE(ircg_pconnect, NULL) PHP_FE(ircg_set_current, NULL) PHP_FE(ircg_join, NULL) PHP_FE(ircg_part, NULL) PHP_FE(ircg_msg, NULL) PHP_FE(ircg_disconnect, NULL) {NULL, NULL, NULL} /* Must be the last line in ircg_functions[] */ }; #include "if_irc.h" typedef struct { irconn_t conn; const char *username; const char *channel; zend_llist buffer; int fd; } php_irconn_t; php_irconn_t *lookup_irconn(int id) { php_irconn_t **ret = NULL; if (zend_hash_index_find(&h_irconn, id, (void **) &ret) == FAILURE) return NULL; return *ret; } static void irconn_dtor(void *dummy) { php_irconn_t **conn = dummy; irc_disconnect(&(*conn)->conn, "Browser connection closed"); free((char *) (*conn)->username); } static void buffer_dtor(void *dummy) { free(dummy); } static void quit_handler(irconn_t *c, void *dummy) { php_irconn_t *conn = dummy; zend_llist_destroy(&conn->buffer); free(conn); } #include "SAPI.h" #define ADD_HEADER(a) sapi_add_header(a, strlen(a), 1) static void msg_http_start(php_irconn_t *conn) { ADD_HEADER("Pragma: no-cache"); sapi_flush(); } static void msg_send(php_irconn_t *conn, const char *msg) { /* zend_llist_add_element(&conn->buffer, strdup(msg)); */ if (conn->fd != -1) { send(conn->fd, msg, strlen(msg), 0); } } static void msg_handler(irconn_t *ircc, const char *chan, const char *from, smart_str *msg, void *conn_data, void *chan_data) { php_irconn_t *conn = conn_data; char buf[2048]; if (chan) snprintf(buf, sizeof(buf), "%s@%s: %s<br>", from, chan, msg->c); else snprintf(buf, sizeof(buf), "%s: %s<br>", from, msg->c); msg_send(conn, buf); } static void user_add(irconn_t *ircc, const char *channel, smart_str *users, int nr, void *dummy) { php_irconn_t *conn = dummy; int i; char buf[2048]; for (i = 0; i < nr; i++) { snprintf(buf, sizeof(buf), "%s joins %s<br>", users[i].c, channel); msg_send(conn, buf); } } static void user_leave(irconn_t *ircc, const char *channel, smart_str *user, void *dummy) { php_irconn_t *conn = dummy; char buf[2048]; snprintf(buf, sizeof(buf), "%s leaves %s<br>", user->c, channel); msg_send(conn, buf); } static void http_closed_connection(int fd) { int *id; if (zend_hash_index_find(&h_fd2irconn, fd, (void **) &id) == FAILURE) return; zend_hash_index_del(&h_fd2irconn, fd); zend_hash_index_del(&h_irconn, *id); } PHP_FUNCTION(ircg_set_current) { zval **p1; php_irconn_t *conn; if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &p1) == FAILURE) WRONG_PARAM_COUNT; convert_to_long_ex(p1); conn = lookup_irconn(Z_LVAL_PP(p1)); if (!conn) RETURN_FALSE; thttpd_register_on_close(http_closed_connection); thttpd_set_dont_close(); conn->fd = thttpd_get_fd(); zend_hash_index_update(&h_fd2irconn, conn->fd, &Z_LVAL_PP(p1), sizeof(int), NULL); msg_http_start(conn); RETURN_TRUE; } PHP_FUNCTION(ircg_new_window) { zval **p1; if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &p1) == FAILURE) WRONG_PARAM_COUNT; convert_to_string_ex(p1); RETVAL_STRING(Z_STRVAL_PP(p1), 1); } PHP_FUNCTION(ircg_join) { zval **p1, **p2; php_irconn_t *conn; if (ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &p1, &p2) == FAILURE) WRONG_PARAM_COUNT; convert_to_long_ex(p1); convert_to_string_ex(p2); conn = lookup_irconn(Z_LVAL_PP(p1)); if (!conn) RETURN_FALSE; irc_join(&conn->conn, Z_STRVAL_PP(p2), NULL, NULL, user_add, user_leave, conn); RETVAL_TRUE; } PHP_FUNCTION(ircg_part) { zval **p1, **p2; php_irconn_t *conn; if (ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &p1, &p2) == FAILURE) WRONG_PARAM_COUNT; convert_to_long_ex(p1); convert_to_string_ex(p2); conn = lookup_irconn(Z_LVAL_PP(p1)); if (!conn) RETURN_FALSE; irc_part(&conn->conn, Z_STRVAL_PP(p2)); RETVAL_TRUE; } PHP_FUNCTION(ircg_pconnect) { zval **p1, **p2, **p3; const char *username; const char *server = "0"; int port = 6667; php_irconn_t *conn; if (ZEND_NUM_ARGS() < 1 || ZEND_NUM_ARGS() > 3 || zend_get_parameters_ex(ZEND_NUM_ARGS(), &p1, &p2, &p3) == FAILURE) WRONG_PARAM_COUNT; switch (ZEND_NUM_ARGS()) { case 3: convert_to_long_ex(p3); port = Z_LVAL_PP(p3); case 2: convert_to_string_ex(p2); server = Z_STRVAL_PP(p2); case 1: convert_to_string_ex(p1); username = Z_STRVAL_PP(p1); } conn = malloc(sizeof(*conn)); conn->username = strdup(username); conn->channel = NULL, conn->fd = -1; irconn_id++; zend_hash_index_update(&h_irconn, irconn_id, &conn, sizeof(conn), NULL); zend_llist_init(&conn->buffer, 0, buffer_dtor, 1); irc_connect(username, NULL, msg_handler, quit_handler, conn, server, port, &conn->conn); st_sleep(0); RETVAL_LONG(irconn_id); } PHP_FUNCTION(ircg_disconnect) { zval **id, **reason; if (ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &id, &reason) == FAILURE) WRONG_PARAM_COUNT; convert_to_long_ex(id); convert_to_string_ex(reason); zend_hash_index_del(&h_irconn, Z_LVAL_PP(id)); RETURN_TRUE; } PHP_FUNCTION(ircg_msg) { zval **id, **recipient, **msg; php_irconn_t *conn; smart_str l = {0}; if (ZEND_NUM_ARGS() != 3 || zend_get_parameters_ex(3, &id, &recipient, &msg) == FAILURE) WRONG_PARAM_COUNT; convert_to_long_ex(id); convert_to_string_ex(recipient); convert_to_string_ex(msg); conn = lookup_irconn(Z_LVAL_PP(id)); if (!conn) RETURN_FALSE; irc_msg(&conn->conn, Z_STRVAL_PP(recipient), Z_STRVAL_PP(msg)); smart_str_setl(&l, Z_STRVAL_PP(msg), Z_STRLEN_PP(msg)); msg_handler(&conn->conn, Z_STRVAL_PP(recipient), conn->username, &l, conn, NULL); RETURN_TRUE; } zend_module_entry ircg_module_entry = { "ircg", ircg_functions, PHP_MINIT(ircg), PHP_MSHUTDOWN(ircg), PHP_RINIT(ircg), /* Replace with NULL if there's nothing to do at request start */ PHP_RSHUTDOWN(ircg), /* Replace with NULL if there's nothing to do at request end */ PHP_MINFO(ircg), STANDARD_MODULE_PROPERTIES }; #ifdef COMPILE_DL_IRCG ZEND_GET_MODULE(ircg) #endif PHP_MINIT_FUNCTION(ircg) { /* Remove comments if you have entries in php.ini REGISTER_INI_ENTRIES(); */ zend_hash_init(&h_fd2irconn, 0, NULL, NULL, 1); zend_hash_init(&h_irconn, 0, NULL, irconn_dtor, 1); return SUCCESS; } PHP_MSHUTDOWN_FUNCTION(ircg) { /* Remove comments if you have entries in php.ini UNREGISTER_INI_ENTRIES(); */ zend_hash_destroy(&h_irconn); zend_hash_destroy(&h_fd2irconn); return SUCCESS; } /* Remove if there's nothing to do at request start */ PHP_RINIT_FUNCTION(ircg) { return SUCCESS; } /* Remove if there's nothing to do at request end */ PHP_RSHUTDOWN_FUNCTION(ircg) { return SUCCESS; } PHP_MINFO_FUNCTION(ircg) { php_info_print_table_start(); php_info_print_table_header(2, "ircg support", "enabled"); php_info_print_table_end(); } /* Remove the following function when you have succesfully modified config.m4 so that your module can be compiled into PHP, it exists only for testing purposes. */ /* Every user-visible function in PHP should document itself in the source */ /* {{{ proto string confirm_ircg_compiled(string arg) Return a string to confirm that the module is compiled in */ PHP_FUNCTION(confirm_ircg_compiled) { zval **arg; int len; char string[256]; if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &arg) == FAILURE) { WRONG_PARAM_COUNT; } convert_to_string_ex(arg); len = sprintf(string, "Congratulations, you have successfully modified ext/ircg/config.m4, module %s is compiled into PHP", Z_STRVAL_PP(arg)); RETURN_STRINGL(string, len, 1); } /* }}} */ /* The previous line is meant for emacs, so it can correctly fold and unfold functions in source code. See the corresponding marks just before function definition, where the functions purpose is also documented. Please follow this convention for the convenience of others editing your code. */ /* * Local variables: * tab-width: 4 * c-basic-offset: 4 * End: */ Index: php4/ext/ircg/ircg.php +++ php4/ext/ircg/ircg.php <? $module = 'ircg'; $function = 'confirm_' . $module . '_compiled'; if (extension_loaded($module)) { $str = $function($module); } else { $str = "Module $module is not compiled into PHP"; } echo "$str\n"; ?> Index: php4/ext/ircg/php_ircg.h +++ php4/ext/ircg/php_ircg.h /* +----------------------------------------------------------------------+ | PHP version 4.0 | +----------------------------------------------------------------------+ | Copyright (c) 1997, 1998, 1999, 2000 The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to version 2.02 of the PHP license, | | that is bundled with this package in the file LICENSE, and is | | available at through the world-wide-web at | | http://www.php.net/license/2_02.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. | +----------------------------------------------------------------------+ | Authors: | | | +----------------------------------------------------------------------+ */ #ifndef PHP_IRCG_H #define PHP_IRCG_H extern zend_module_entry ircg_module_entry; #define phpext_ircg_ptr &ircg_module_entry #ifdef PHP_WIN32 #define PHP_IRCG_API __declspec(dllexport) #else #define PHP_IRCG_API #endif PHP_FUNCTION(ircg_pconnect); PHP_FUNCTION(ircg_join); PHP_FUNCTION(ircg_set_current); PHP_FUNCTION(ircg_part); PHP_FUNCTION(ircg_register_current_conn); PHP_FUNCTION(ircg_msg); PHP_FUNCTION(ircg_disconnect); PHP_MINIT_FUNCTION(ircg); PHP_MSHUTDOWN_FUNCTION(ircg); PHP_RINIT_FUNCTION(ircg); PHP_RSHUTDOWN_FUNCTION(ircg); PHP_MINFO_FUNCTION(ircg); PHP_FUNCTION(confirm_ircg_compiled); /* For testing, remove later. */ /* Declare any global variables you may need between the BEGIN and END macros here: ZEND_BEGIN_MODULE_GLOBALS(ircg) int global_variable; ZEND_END_MODULE_GLOBALS(ircg) */ /* In every function that needs to use variables in php_ircg_globals, do call IRCGLS_FETCH(); after declaring other variables used by that function, and always refer to them as IRCGG(variable). You are encouraged to rename these macros something shorter, see examples in any other php module directory. */ #ifdef ZTS #define IRCGG(v) (ircg_globals->v) #define IRCGLS_FETCH() php_ircg_globals *ircg_globals = ts_resource(ircg_globals_id) #else #define IRCGG(v) (ircg_globals.v) #define IRCGLS_FETCH() #endif #endif /* PHP_IRCG_H */ /* * Local variables: * tab-width: 4 * c-basic-offset: 4 * End: */
« previous php.cvs (#2575) next »