]> granicus.if.org Git - php/commitdiff
Add the Cyrus IMAP extension to PHP's CVS (Manual editing of the news file to occur).
authorSterling Hughes <sterling@php.net>
Sun, 5 Aug 2001 17:43:03 +0000 (17:43 +0000)
committerSterling Hughes <sterling@php.net>
Sun, 5 Aug 2001 17:43:03 +0000 (17:43 +0000)
ext/cyrus/CREDITS [new file with mode: 0644]
ext/cyrus/Makefile.in [new file with mode: 0644]
ext/cyrus/config.m4 [new file with mode: 0644]
ext/cyrus/cyrus.c [new file with mode: 0644]
ext/cyrus/php_cyrus.h [new file with mode: 0644]

diff --git a/ext/cyrus/CREDITS b/ext/cyrus/CREDITS
new file mode 100644 (file)
index 0000000..74371fa
--- /dev/null
@@ -0,0 +1,2 @@
+Cyrus
+Sterling Hughes
diff --git a/ext/cyrus/Makefile.in b/ext/cyrus/Makefile.in
new file mode 100644 (file)
index 0000000..8d09bef
--- /dev/null
@@ -0,0 +1,8 @@
+# $Id$
+
+LTLIBRARY_NAME        = libcyrus.la
+LTLIBRARY_SOURCES     = cyrus.c
+LTLIBRARY_SHARED_NAME = cyrus.la
+LTLIBRARY_SHARED_LIBADD  = $(CYRUS_SHARED_LIBADD)
+
+include $(top_srcdir)/build/dynlib.mk
diff --git a/ext/cyrus/config.m4 b/ext/cyrus/config.m4
new file mode 100644 (file)
index 0000000..3da4b01
--- /dev/null
@@ -0,0 +1,45 @@
+dnl config.m4 for extension cyrus
+
+PHP_ARG_WITH(cyrus, for cyrus imap support,
+[  --with-cyrus             Include cyrus imap support])
+
+if test "$PHP_CYRUS" != "no"; then
+       found_cyrus=no
+       found_sasl=no
+       found_openssl=no
+       for i in /usr /usr/local $PHP_CYRUS; do
+               if test -r $i/include/cyrus/imclient.h && test "$found_cyrus" = "no"; then
+                       PHP_ADD_INCLUDE($i/include)
+                       PHP_SUBST(CYRUS_SHARED_LIBADD)
+                       PHP_ADD_LIBRARY_WITH_PATH(cyrus, $i/lib, CYRUS_SHARED_LIBADD)
+                       found_cyrus=yes
+               fi
+               if test -r $i/include/sasl.h && test "$found_sasl" = "no"; then
+                       PHP_ADD_INCLUDE($i/include)
+                       PHP_SUBST(SASL_SHARED_LIBADD)
+                       PHP_ADD_LIBRARY_WITH_PATH(sasl, $i/lib, SASL_SHARED_LIBADD)
+                       found_sasl=yes
+               fi
+               if test -r $i/include/openssl/ssl.h && test "$found_openssl" = "no" && test "$PHP_OPENSSL" = "no"; then
+                       PHP_SUBST(OPENSSL_SHARED_LIBADD)
+                       PHP_SUBST(CRYPTO_SHARED_LIBADD)
+                       PHP_ADD_LIBRARY_WITH_PATH(ssl, $i/lib, OPENSSL_SHARED_LIBADD)
+                       PHP_ADD_LIBRARY_WITH_PATH(crypto, $i/lib, CRYPTO_SHARED_LIBADD)
+                       found_openssl=yes
+               fi
+       done
+
+       if test "$found_cyrus" = "no"; then
+               AC_MSG_RESULT(not found)
+               AC_MSG_ERROR(Please Re-install the cyrus distribution)
+       fi
+
+       if test "$found_sasl" = "no"; then
+               AC_MSG_RESULT(sasl not found)
+               AC_MSG_ERROR(Please Re-install the cyrus distribution)
+       fi
+
+       AC_DEFINE(HAVE_CYRUS,1,[ ])
+
+       PHP_EXTENSION(cyrus, $ext_shared)
+fi
diff --git a/ext/cyrus/cyrus.c b/ext/cyrus/cyrus.c
new file mode 100644 (file)
index 0000000..b06fe9f
--- /dev/null
@@ -0,0 +1,497 @@
+/*
+   +----------------------------------------------------------------------+
+   | PHP version 4.0                                                      |
+   +----------------------------------------------------------------------+
+   | Copyright (c) 1997-2001 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: Sterling Hughes <sterling@php.net>                          |
+   +----------------------------------------------------------------------+
+ */
+
+/* $Id$ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "php.h"
+#include "php_cyrus.h"
+
+#if HAVE_CYRUS
+
+#include <cyrus/imclient.h>
+
+#include <pwd.h>
+#include <sys/types.h>
+#include <stdlib.h>
+#include <string.h>
+
+static int le_cyrus;
+#define le_cyrus_name "Cyrus IMAP connection"
+
+function_entry cyrus_functions[] = {
+       PHP_FE(cyrus_connect,           NULL)
+       PHP_FE(cyrus_authenticate,      NULL)
+       PHP_FE(cyrus_bind,                      NULL)
+       PHP_FE(cyrus_unbind,            NULL)
+       PHP_FE(cyrus_query,                     NULL)
+       PHP_FE(cyrus_close,                     NULL)
+       {NULL, NULL, NULL}
+};
+
+zend_module_entry cyrus_module_entry = {
+       "cyrus",
+       cyrus_functions,
+       PHP_MINIT(cyrus),
+       NULL,
+       NULL,   
+       NULL,
+       PHP_MINFO(cyrus),
+       STANDARD_MODULE_PROPERTIES
+};
+
+#ifdef COMPILE_DL_CYRUS
+ZEND_GET_MODULE(cyrus)
+#endif
+
+static void cyrus_free(zend_rsrc_list_entry *rsrc)
+{
+       php_cyrus *conn = (php_cyrus *) rsrc->ptr;
+
+       if (conn->client)
+               imclient_close(conn->client);
+
+       if (conn->host) 
+               efree(conn->host);
+
+       if (conn->port)
+               efree(conn->port);
+
+       efree(conn);
+}
+       
+PHP_MINIT_FUNCTION(cyrus)
+{
+       le_cyrus = zend_register_list_destructors_ex(cyrus_free, NULL, 
+                                                    le_cyrus_name, module_number);
+
+       REGISTER_LONG_CONSTANT("CYRUS_CONN_NOSYNCLITERAL", 
+                              IMCLIENT_CONN_NOSYNCLITERAL,
+                              CONST_CS_ | CONST_PERSISTENT);
+       REGISTER_LONG_CONSTANT("CYRUS_CONN_INITIALRESPONSE", 
+                              IMCLIENT_CONN_INITIALRESPONSE,
+                              CONST_CS | CONST_PERSISTENT);
+       REGISTER_LONG_CONSTANT("CYRUS_CALLBACK_NUMBERED", CALLBACK_NUMBERED,
+                              CONST_CS | CONST_PERSISTENT);
+       REGISTER_LONG_CONSTANT("CYRUS_CALLBACK_NOLITERAL", CALLBACK_NOLITERAL,
+                              CONST_CS | CONST_PERSISTENT);
+
+       return SUCCESS;
+}
+
+PHP_MINFO_FUNCTION(cyrus)
+{
+       php_info_print_table_start();
+       php_info_print_table_header(2, "Cyrus IMAP support", "enabled");
+       php_info_print_table_end();
+}
+
+extern void fatal(char *s, int exit)
+{
+       php_error(E_ERROR, s);
+}
+
+PHP_FUNCTION(cyrus_connect)
+{
+       zval            **z_host;
+       zval            **z_port;
+       zval            **z_flags;
+       php_cyrus        *conn;
+       struct imclient  *client;
+       char             *host;
+       char             *port = NULL;
+       int               flags = 0;
+       int               error;
+       int               argc = ZEND_NUM_ARGS();
+       
+       if (argc < 0 || argc > 3 ||
+           zend_get_parameters_ex(argc, &z_host, &z_port, &z_flags) == FAILURE) {
+               WRONG_PARAM_COUNT;
+       }
+
+       if (argc > 0) {
+               convert_to_string_ex(z_host);
+               host = estrndup(Z_STRVAL_PP(z_host), Z_STRLEN_PP(z_host));
+       }
+       else {
+               host = estrndup("localhost", sizeof("localhost") - 1);
+       }
+
+       if (argc > 1) {
+               convert_to_string_ex(z_port);
+               port = estrndup(Z_STRVAL_PP(z_port), Z_STRLEN_PP(z_port));
+       }
+
+       if (argc > 2) {
+               convert_to_long_ex(z_flags);
+               flags = Z_LVAL_PP(z_flags);
+       }
+
+       error = imclient_connect(&client, host, port, NULL);
+       switch (error) {
+       case 0:
+               if (client) {
+                       conn = ecalloc(1, sizeof *conn);
+                       conn->client = client;
+                       conn->host = host;
+                       conn->port = port;
+
+                       if (flags) {
+                               imclient_setflags(conn->client, flags);
+                               conn->flags = flags;
+                       }
+               }
+
+               break;
+
+       case -1:
+               php_error(E_WARNING, "Invalid hostname: %s", host);
+               RETURN_FALSE;
+       
+       case -2:
+               php_error(E_WARNING, "Invalid port: %d", port);
+               RETURN_FALSE;
+       }
+
+       ZEND_REGISTER_RESOURCE(return_value, conn, le_cyrus);
+       conn->id = Z_LVAL_P(return_value);
+}
+
+static void cyrus_capable_callback(struct imclient *client, void *rock, 
+                                   struct imclient_reply *reply)
+{
+       char *token = NULL;
+       char *token_buf;
+       char *mechanism = rock;
+
+       
+       /* We need to split the reply up by the whitespace */
+       token = php_strtok_r(reply->text, " ", &token_buf);
+       while (token != NULL) {
+               if (! strncmp(token, "AUTH=", 5)) {
+                       memcpy(mechanism, token + 5, strlen(token) - 5);
+                       break;
+               }
+
+               token = php_strtok_r(NULL, " ", &token_buf);
+       }
+}
+
+PHP_FUNCTION(cyrus_authenticate)
+{
+       zval        **z_conn;
+       zval        **z_mechlist;
+       zval        **z_service;
+       zval        **z_user;
+       zval        **z_minssf;
+       zval        **z_maxssf;
+       php_cyrus    *conn;
+       char         *mechlist;
+       char         *service;
+       char         *user;
+       int           minssf;
+       int           maxssf;
+       int           argc = ZEND_NUM_ARGS();
+
+       if (argc < 1 || argc > 6 ||
+           zend_get_parameters_ex(argc, &z_conn, &z_mechlist, &z_service, &z_user, &z_minssf, &z_maxssf) == FAILURE) {
+               WRONG_PARAM_COUNT;
+       }
+       ZEND_FETCH_RESOURCE(conn, php_cyrus *, z_conn, -1, le_cyrus_name, le_cyrus);
+
+       /* Determine support mechanisms */
+       if (argc > 1 && Z_TYPE_PP(z_mechlist) != IS_NULL) {
+               convert_to_string_ex(z_mechlist);
+
+               mechlist = estrndup(Z_STRVAL_PP(z_mechlist), Z_STRLEN_PP(z_mechlist));
+       }
+       else {
+               char tmp_mechlist[100];
+               int  pos = 0;
+               
+               /* NULL out the buffer, ensures it has a safe ending and allows us to
+                * test properly for the end of the buffer
+                */
+               memset(tmp_mechlist, 0, sizeof tmp_mechlist);
+
+               /* We'll be calling the "CAPABILITY" command, which will give us a list
+                * of the types of authorization the server is capable of 
+                */
+               imclient_addcallback(conn->client, "CAPABILITY", 0, 
+                                    cyrus_capable_callback, (void *) tmp_mechlist, 0);
+               imclient_send(conn->client, NULL, NULL, "CAPABILITY");
+
+               /* Grab the end of string position into pos */
+               while (tmp_mechlist[pos++] != 0) 
+                       ;
+
+               /* Tack on PLAIN to whatever the auth string is */
+               memcpy(tmp_mechlist + pos, " PLAIN", 6);
+               
+               /* Copy it onto the main buffer */
+               mechlist = estrndup(tmp_mechlist, pos + 6);
+       }
+
+       /* Determine the service type */
+       if (argc > 2 && Z_TYPE_PP(z_service) != IS_NULL) {
+               convert_to_string_ex(z_service);
+               service = estrndup(Z_STRVAL_PP(z_service), Z_STRLEN_PP(z_service));
+       }
+       else {
+               service = estrndup("imap", 4);
+       }
+
+       /* Determine the user */
+       if (argc > 3 && Z_TYPE_PP(z_user) != IS_NULL) {
+               convert_to_string_ex(z_user);
+               user = estrndup(Z_STRVAL_PP(z_user), Z_STRLEN_PP(z_user));
+       }
+       else {
+               /* XXX: UGLY, but works, determines the username to use */
+               user = sapi_getenv("USER", 4);
+               if (! user) {
+               user = getenv("USER");
+               if (! user) {
+                       user = sapi_getenv("LOGNAME", 7);
+                       if (! user) {
+                       user = getenv("LOGNAME");
+                       if (! user) {
+                               struct passwd *pwd = getpwuid(getuid());
+                               if (! pwd) {
+                               php_error(E_WARNING, "Couldn't determine user id");
+                               RETURN_FALSE;
+                               }
+                       
+                               user = estrdup(pwd->pw_name);
+                       }
+                       }
+               }
+               }
+       }
+
+       /* Determine the minssf */
+       if (argc > 4 && Z_TYPE_PP(z_minssf) != NULL) {
+               convert_to_long_ex(z_minssf);
+               minssf = Z_LVAL_PP(z_minssf);
+       }
+       else {
+               minssf = 0;
+       }
+
+       /* Determine the maxssf */
+       if (argc > 5 && Z_TYPE_PP(z_maxssf) != NULL) {
+               convert_to_long_ex(z_maxssf);
+               maxssf = Z_LVAL_PP(z_maxssf);
+       }
+       else {
+               maxssf = 1000;
+       }
+
+       imclient_authenticate(conn->client, mechlist, service, 
+                             user, minssf, maxssf);
+
+       efree(mechlist);
+       efree(service);
+       efree(user);
+}
+
+static void cyrus_generic_callback(struct imclient *client, 
+                                   void *rock, 
+                                   struct imclient_reply *reply)
+{
+       php_cyrus_callback *callback = rock;
+
+       if (client) {
+               zval **argv[4];
+               zval  *retval;
+               zval  *cyrus;
+               zval  *keyword;
+               zval  *text;
+               zval  *msgno;
+               TSRMLS_FETCH();
+
+               MAKE_STD_ZVAL(cyrus);
+               MAKE_STD_ZVAL(keyword);
+               MAKE_STD_ZVAL(text);
+               MAKE_STD_ZVAL(msgno);
+
+               ZVAL_RESOURCE(cyrus, callback->le);
+               zend_list_addref(callback->le);
+
+               ZVAL_STRING(keyword, reply->keyword, 1);
+               ZVAL_STRING(text, reply->text, 1);
+               ZVAL_LONG(msgno, reply->msgno);
+
+               argv[0] = &cyrus;
+               argv[1] = &keyword;
+               argv[2] = &text;
+               argv[3] = &msgno;
+
+               if (call_user_function_ex(EG(function_table), NULL, callback->function, 
+                                  &retval, 4, argv, 0, NULL) == FAILURE) {
+                       php_error(E_WARNING, "Couldn't call the %s handler", 
+                                 callback->trigger);
+               }
+
+               zval_ptr_dtor(argv[0]);
+               zval_ptr_dtor(argv[1]);
+               zval_ptr_dtor(argv[2]);
+               zval_ptr_dtor(argv[3]);
+
+               efree(argv);
+       }
+       else {
+               return;
+       }
+}
+
+       
+
+PHP_FUNCTION(cyrus_bind)
+{
+       zval                  **z_conn;
+       zval                  **z_callback;
+       zval                  **tmp;
+       HashTable              *hash;
+       php_cyrus             *conn;
+       php_cyrus_callback     callback;
+       char                  *string_key;
+       ulong                  num_key;
+
+       if (ZEND_NUM_ARGS() != 3 ||
+           zend_get_parameters_ex(3, &z_conn, &z_callback) == FAILURE) {
+               WRONG_PARAM_COUNT;
+       }
+
+       ZEND_FETCH_RESOURCE(conn, php_cyrus *, z_conn, -1, le_cyrus_name, le_cyrus);
+
+       hash = HASH_OF(*z_callback);
+       if (! hash) {
+               php_error(E_WARNING, 
+                         "Second argument to cyrus_bind() must be an array or object");
+               RETURN_FALSE;
+       }
+
+       for (zend_hash_internal_pointer_reset(hash);
+            zend_hash_get_current_data(hash, (void **) &tmp) == SUCCESS;
+                zend_hash_move_forward(hash)) {
+               SEPARATE_ZVAL(tmp);
+               zend_hash_get_current_key(hash, &string_key, &num_key, 0);
+               if (! string_key) 
+                       continue;
+               
+               if (! strcasecmp(string_key, "trigger")) {
+                       convert_to_string_ex(tmp);
+                       callback.trigger = estrndup(Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp));
+               }
+               else if (! strcasecmp(string_key, "function")) {
+                       callback.function = *tmp;
+                       zval_add_ref(&callback.function);
+               }
+               else if (! strcasecmp(string_key, "flags")) {
+                       convert_to_long_ex(tmp);
+                       callback.flags |= Z_LVAL_PP(tmp);
+               }
+       }
+
+       if (! callback.trigger) {
+               php_error(E_WARNING, "You must specify a trigger in your callback");
+               RETURN_FALSE;
+       }
+
+       if (! callback.function) {
+               php_error(E_WARNING, "You must specify a function in your callback");
+               RETURN_FALSE;
+       }
+
+       callback.le = conn->id;
+
+       imclient_addcallback(conn->client, callback.trigger, callback.flags, 
+                            cyrus_generic_callback, (void **) &callback, 0);
+
+       RETURN_TRUE;
+}
+
+PHP_FUNCTION(cyrus_unbind)
+{
+       zval        **z_conn;
+       zval        **trigger_name;
+       php_cyrus    *conn;
+
+       if (ZEND_NUM_ARGS() != 2 ||
+           zend_get_parameters_ex(2, &z_conn, &trigger_name) == FAILURE) {
+               WRONG_PARAM_COUNT;
+       }
+       ZEND_FETCH_RESOURCE(conn, php_cyrus *, z_conn, -1, le_cyrus_name, le_cyrus);
+       convert_to_string_ex(trigger_name);
+
+       imclient_addcallback(conn->client, Z_STRVAL_PP(trigger_name), 0, 
+                            NULL, NULL, 0);
+
+       RETURN_TRUE;
+}
+
+PHP_FUNCTION(cyrus_query)
+{
+       zval               **z_conn;
+       zval               **query;
+       php_cyrus           *conn;
+
+       if (ZEND_NUM_ARGS() != 2 ||
+           zend_get_parameters_ex(2, &z_conn, &query) == FAILURE) {
+               WRONG_PARAM_COUNT;
+       }
+       ZEND_FETCH_RESOURCE(conn, php_cyrus *, z_conn, -1, le_cyrus_name, le_cyrus);
+       convert_to_string_ex(query);
+
+       if (imclient_send(conn->client, NULL, NULL, Z_STRVAL_PP(query)) != 0) 
+               RETURN_FALSE;
+
+       RETURN_TRUE;
+}
+
+
+PHP_FUNCTION(cyrus_close)
+{
+       zval      **z_conn;
+       php_cyrus  *conn;
+
+       if (ZEND_NUM_ARGS() != 1 ||
+           zend_get_parameters_ex(1, &z_conn) == FAILURE) {
+               WRONG_PARAM_COUNT;
+       }
+       ZEND_FETCH_RESOURCE(conn, php_cyrus *, z_conn, -1, le_cyrus_name, le_cyrus);
+
+       zend_list_delete(Z_LVAL_PP(z_conn));
+
+       RETURN_TRUE;
+}
+
+#endif
+
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * indent-tabs-mode: t
+ * End:
+ */
diff --git a/ext/cyrus/php_cyrus.h b/ext/cyrus/php_cyrus.h
new file mode 100644 (file)
index 0000000..ca153d2
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+   +----------------------------------------------------------------------+
+   | PHP version 4.0                                                      |
+   +----------------------------------------------------------------------+
+   | Copyright (c) 1997-2001 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: Sterling Hughes <sterling@php.net>                          |
+   +----------------------------------------------------------------------+
+ */
+
+/* $Id$ */
+
+#ifndef PHP_CYRUS_H
+#define PHP_CYRUS_H
+
+#include "php.h"
+
+#if HAVE_CYRUS
+
+#include <cyrus/imclient.h>
+
+extern zend_module_entry cyrus_module_entry;
+#define phpext_cyrus_ptr &cyrus_module_entry
+
+#ifdef PHP_WIN32
+#define PHP_CYRUS_API __declspec(dllexport)
+#else
+#define PHP_CYRUS_API
+#endif
+
+PHP_MINIT_FUNCTION(cyrus);
+PHP_MINFO_FUNCTION(cyrus);
+
+PHP_FUNCTION(cyrus_connect);
+PHP_FUNCTION(cyrus_authenticate);
+PHP_FUNCTION(cyrus_bind);
+PHP_FUNCTION(cyrus_unbind);
+PHP_FUNCTION(cyrus_query);
+PHP_FUNCTION(cyrus_close);
+
+typedef struct {
+       struct imclient *client;
+       char            *host;
+       char            *port;
+       int              flags;
+       int              id;
+}
+php_cyrus;
+
+typedef struct {
+       zval *function;
+       char *trigger;
+       long  le;
+       int   flags;
+}
+php_cyrus_callback;
+
+#endif
+
+
+#endif
+
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * indent-tabs-mode: t
+ * End:
+ */