Tuesday, June 21, 2005

Extending PHP

Sometimes we need a new funcionality on PHP that we don't have because it is an OS specific call which needs a deep degree of abstraction inherent in the language or due to another reason.

Today we will learn how to develop an extension to send faxes with only a line of code. You need efax installed and configured (just edit /usr/bin/fax).

Add this lines to /etc/printcap file:
 fax:
 :lp=/dev/null:
 :sd=/var/spool/fax:
 :if=/usr/bin/faxlpr:
Now we can write the module:

efax.c

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include "php.h"
#include "efax.h"

ZEND_FUNCTION(send_fax); 
PHP_MINFO_FUNCTION(efaxmod);

static function_entry efax_functions[] = {
    PHP_FE(send_fax, NULL)
    {NULL, NULL, NULL}
};

zend_module_entry efax_module_entry = {
#if ZEND_MODULE_API_NO >= 20010901
    STANDARD_MODULE_HEADER,
#endif
    PHP_EFAX_EXTNAME,
    efax_functions,
    NULL,
    NULL,
    NULL,
    NULL,
    NULL,
#if ZEND_MODULE_API_NO >= 20010901
    PHP_EFAX_VERSION,
#endif
    STANDARD_MODULE_PROPERTIES
};

#ifdef COMPILE_DL_EFAX
ZEND_GET_MODULE(efax)
#endif


PHP_MINFO_FUNCTION(efaxmod) { 
 php_info_print_table_start(); 
 php_info_print_table_row(2, "Efax Extension", "Hazent Systems"); 
 php_info_print_table_end(); 
}

 
PHP_FUNCTION(send_fax)
{

 char *name, *number;
 //int name_len, number_len;
        int ret;
    
 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sl", &name, &number) == FAILURE)
             return;
    
 
        char *cmd[] = { "lpr", "-Pfax" , "-J", number, name,(char *)0 };
        // FIXME: getenv
        char *env[] = { "HOME=/var/www", "LOGNAME=www-data", (char *)0 };
        ret = execve ("/usr/bin/lpr", cmd, env);
        return ret;

}

efax.h

#ifndef PHP_EFAX_H
#define PHP_EFAX_H 1

#define PHP_EFAX_VERSION "1.0"
#define PHP_EFAX_EXTNAME "eFax"

PHP_FUNCTION(send_fax);

extern zend_module_entry efax_module_entry;
#define phpext_hello_ptr &efax_module_entry

#endif

config.m4

PHP_ARG_ENABLE(efax, whether to enable eFax support,
[ --enable-efax   Enable eFax support])

if test "$PHP_EFAX" = "yes"; then
  AC_DEFINE(HAVE_EFAX, 1, [Whether you have eFax])
  PHP_NEW_EXTENSION(efax, efax.c, $ext_shared)
fi
To compile it type:
bash$ phpice && ./configure && make
If you want to install it type:
bash$ make install
or, just load it from php during the execution:
dl("efax.so");
send_fax("666666666","fichero.txt");
send_fax("667777666","fichero.pdf");
send_fax("688888866","fichero.ps");
...
You can get the source from: http://people.hazent.com/~jrp/soft/php4-efax.tgz