#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "php.h"
#include "php_pfpro.h"
#if HAVE_PFPRO
#include "php_ini.h"
#include "ext/standard/info.h"
#include "ext/standard/php_string.h"
#include <pfpro.h>
ZEND_DECLARE_MODULE_GLOBALS(pfpro)
function_entry pfpro_functions[] = {
PHP_FE(pfpro_version, NULL)
PHP_FE(pfpro_init, NULL)
PHP_FE(pfpro_cleanup, NULL)
PHP_FE(pfpro_process_raw, NULL)
PHP_FE(pfpro_process, NULL)
{NULL, NULL, NULL}
};
zend_module_entry pfpro_module_entry = {
STANDARD_MODULE_HEADER,
"pfpro",
pfpro_functions,
PHP_MINIT(pfpro),
PHP_MSHUTDOWN(pfpro),
PHP_RINIT(pfpro),
PHP_RSHUTDOWN(pfpro),
PHP_MINFO(pfpro),
NO_VERSION_YET,
STANDARD_MODULE_PROPERTIES
};
#ifdef COMPILE_DL_PFPRO
ZEND_GET_MODULE(pfpro)
#endif
PHP_INI_BEGIN()
STD_PHP_INI_ENTRY("pfpro.defaulthost", "test-payflow.verisign.com", PHP_INI_ALL, OnUpdateString, defaulthost, zend_pfpro_globals, pfpro_globals)
STD_PHP_INI_ENTRY("pfpro.defaultport", "443", PHP_INI_ALL, OnUpdateInt, defaultport, zend_pfpro_globals, pfpro_globals)
STD_PHP_INI_ENTRY("pfpro.defaulttimeout", "30", PHP_INI_ALL, OnUpdateInt, defaulttimeout, zend_pfpro_globals, pfpro_globals)
STD_PHP_INI_ENTRY("pfpro.proxyaddress", "", PHP_INI_ALL, OnUpdateString, proxyaddress, zend_pfpro_globals, pfpro_globals)
STD_PHP_INI_ENTRY("pfpro.proxyport", "", PHP_INI_ALL, OnUpdateInt, proxyport, zend_pfpro_globals, pfpro_globals)
STD_PHP_INI_ENTRY("pfpro.proxylogon", "", PHP_INI_ALL, OnUpdateString, proxylogon, zend_pfpro_globals, pfpro_globals)
STD_PHP_INI_ENTRY("pfpro.proxypassword", "", PHP_INI_ALL, OnUpdateString, proxypassword, zend_pfpro_globals, pfpro_globals)
PHP_INI_END()
static void php_pfpro_init_globals(zend_pfpro_globals *pfpro_globals)
{
pfpro_globals->initialized = 0;
pfpro_globals->defaulthost = NULL;
pfpro_globals->defaultport = 0;
pfpro_globals->defaulttimeout = 0;
pfpro_globals->proxyaddress = NULL;
pfpro_globals->proxyport = 0;
pfpro_globals->proxylogon = NULL;
pfpro_globals->proxypassword = NULL;
}
PHP_MINIT_FUNCTION(pfpro)
{
ZEND_INIT_MODULE_GLOBALS(pfpro, php_pfpro_init_globals, NULL);
REGISTER_INI_ENTRIES();
return SUCCESS;
}
PHP_MSHUTDOWN_FUNCTION(pfpro)
{
UNREGISTER_INI_ENTRIES();
return SUCCESS;
}
PHP_RINIT_FUNCTION(pfpro)
{
PFPROG(initialized) = 0;
return SUCCESS;
}
PHP_RSHUTDOWN_FUNCTION(pfpro)
{
if (PFPROG(initialized) == 1) {
pfproCleanup();
}
return SUCCESS;
}
PHP_MINFO_FUNCTION(pfpro)
{
php_info_print_table_start();
php_info_print_table_row(2, "Verisign Payflow Pro support", "enabled");
php_info_print_table_row(2, "libpfpro version", pfproVersion());
php_info_print_table_end();
DISPLAY_INI_ENTRIES();
}
PHP_FUNCTION(pfpro_version)
{
if (ZEND_NUM_ARGS() != 0) {
WRONG_PARAM_COUNT;
}
RETURN_STRING((char *)pfproVersion(), 1);
}
PHP_FUNCTION(pfpro_init)
{
if (ZEND_NUM_ARGS() != 0) {
WRONG_PARAM_COUNT;
}
pfproInit();
PFPROG(initialized) = 1;
RETURN_TRUE;
}
PHP_FUNCTION(pfpro_cleanup)
{
if (ZEND_NUM_ARGS() != 0) {
WRONG_PARAM_COUNT;
}
pfproCleanup();
PFPROG(initialized) = 0;
RETURN_TRUE;
}
PHP_FUNCTION(pfpro_process_raw)
{
zval ***args;
char *parmlist = NULL;
char *address = NULL;
int port = PFPROG(defaultport);
int timeout = PFPROG(defaulttimeout);
char *proxyAddress = PFPROG(proxyaddress);
int proxyPort = PFPROG(proxyport);
char *proxyLogon = PFPROG(proxylogon);
char *proxyPassword = PFPROG(proxypassword);
int freeaddress = 0;
#if PFPRO_VERSION < 3
char response[512] = "";
#else
int context;
char *response;
#endif
if (ZEND_NUM_ARGS() < 1 || ZEND_NUM_ARGS() > 8) {
WRONG_PARAM_COUNT;
}
args = (zval ***) emalloc(sizeof(zval **) * ZEND_NUM_ARGS());
if (zend_get_parameters_array_ex(ZEND_NUM_ARGS(), args) == FAILURE) {
php_error(E_WARNING, "Unable to read parameters in pfpro_process_raw()");
efree(args);
RETURN_FALSE;
}
switch (ZEND_NUM_ARGS()) {
case 8:
convert_to_string_ex(args[7]);
proxyPassword = Z_STRVAL_PP(args[7]);
case 7:
convert_to_string_ex(args[6]);
proxyLogon = Z_STRVAL_PP(args[6]);
case 6:
convert_to_long_ex(args[5]);
proxyPort = Z_LVAL_PP(args[5]);
case 5:
convert_to_string_ex(args[4]);
proxyAddress = Z_STRVAL_PP(args[4]);
case 4:
convert_to_long_ex(args[3]);
timeout = Z_LVAL_PP(args[3]);
case 3:
convert_to_long_ex(args[2]);
port = Z_LVAL_PP(args[2]);
case 2:
convert_to_string_ex(args[1]);
address = Z_STRVAL_PP(args[1]);
}
convert_to_string_ex(args[0]);
parmlist = Z_STRVAL_PP(args[0]);
efree(args);
if (address == NULL) {
address = estrdup(PFPROG(defaulthost));
freeaddress = 1;
}
#if PFPRO_VERSION < 3
memset(response, 0, sizeof(response));
#endif
if (PFPROG(initialized) == 0) {
pfproInit();
PFPROG(initialized) = 1;
}
#if PFPRO_VERSION < 3
ProcessPNTransaction(address, port, proxyAddress, proxyPort, proxyLogon, proxyPassword, parmlist, strlen(parmlist), timeout, response);
#else
pfproCreateContext(&context, address, port, timeout, proxyAddress, proxyPort, proxyLogon, proxyPassword);
pfproSubmitTransaction(context, parmlist, strlen(parmlist), &response);
pfproDestroyContext(context);
#endif
if (freeaddress) {
efree(address);
}
RETURN_STRING(response, 1);
}
PHP_FUNCTION(pfpro_process)
{
zval ***args;
HashTable *target_hash;
ulong num_key;
char *string_key;
zval **entry;
int pass;
char *parmlist = NULL;
char *address = NULL;
int port = PFPROG(defaultport);
int timeout = PFPROG(defaulttimeout);
char *proxyAddress = PFPROG(proxyaddress);
int proxyPort = PFPROG(proxyport);
char *proxyLogon = PFPROG(proxylogon);
char *proxyPassword = PFPROG(proxypassword);
int parmlength = 0;
int freeaddress = 0;
#if PFPRO_VERSION < 3
char response[512] = "";
#else
int context;
char *response;
#endif
char tmpbuf[128];
char *var,*val,*strtok_buf=NULL;
if (ZEND_NUM_ARGS() < 1 || ZEND_NUM_ARGS() > 8) {
WRONG_PARAM_COUNT;
}
args = (zval ***) emalloc(sizeof(zval **) * ZEND_NUM_ARGS());
if (zend_get_parameters_array_ex(ZEND_NUM_ARGS(), args) == FAILURE) {
efree(args);
php_error(E_ERROR, "Unable to read parameters in pfpro_process()");
RETURN_FALSE;
}
if (Z_TYPE_PP(args[0]) != IS_ARRAY) {
efree(args);
php_error(E_ERROR, "First parameter to pfpro_process() must be an array");
RETURN_FALSE;
}
switch (ZEND_NUM_ARGS()) {
case 8:
convert_to_string_ex(args[7]);
proxyPassword = Z_STRVAL_PP(args[7]);
case 7:
convert_to_string_ex(args[6]);
proxyLogon = Z_STRVAL_PP(args[6]);
case 6:
convert_to_long_ex(args[5]);
proxyPort = Z_LVAL_PP(args[5]);
case 5:
convert_to_string_ex(args[4]);
proxyAddress = Z_STRVAL_PP(args[4]);
case 4:
convert_to_long_ex(args[3]);
timeout = Z_LVAL_PP(args[3]);
case 3:
convert_to_long_ex(args[2]);
port = Z_LVAL_PP(args[2]);
case 2:
convert_to_string_ex(args[1]);
address = Z_STRVAL_PP(args[1]);
}
target_hash = HASH_OF(*args[0]);
for (pass = 0; pass <= 1; pass ++) {
parmlength = 0;
zend_hash_internal_pointer_reset(target_hash);
while (zend_hash_get_current_data(target_hash, (void **)&entry) == SUCCESS) {
if (parmlength > 0) {
if (pass == 1)
strcpy(parmlist + parmlength, "&");
parmlength += 1;
}
switch (zend_hash_get_current_key(target_hash, &string_key, &num_key, 0)) {
case HASH_KEY_IS_STRING:
if (pass == 1)
strcpy(parmlist + parmlength, string_key);
parmlength += strlen(string_key);
break;
case HASH_KEY_IS_LONG:
sprintf(tmpbuf, "%ld", num_key);
if (pass == 1)
strcpy(parmlist + parmlength, tmpbuf);
parmlength += strlen(tmpbuf);
break;
default:
if (parmlist) {
efree(parmlist);
}
efree(args);
php_error(E_ERROR, "pfpro_process() array keys must be strings or integers");
RETURN_FALSE;
}
switch (Z_TYPE_PP(entry)) {
case IS_STRING:
if (strchr(Z_STRVAL_PP(entry), '&')
|| strchr(Z_STRVAL_PP(entry), '=')) {
sprintf(tmpbuf, "[%d]=", Z_STRLEN_PP(entry));
if (pass == 1)
strcpy(parmlist + parmlength, tmpbuf);
parmlength += strlen(tmpbuf);
} else {
if (pass == 1)
strcpy(parmlist + parmlength, "=");
parmlength += 1;
}
if (pass == 1)
strcpy(parmlist + parmlength, Z_STRVAL_PP(entry));
parmlength += Z_STRLEN_PP(entry);
break;
case IS_LONG:
sprintf(tmpbuf, "=%ld", Z_LVAL_PP(entry));
if (pass == 1)
strcpy(parmlist + parmlength, tmpbuf);
parmlength += strlen(tmpbuf);
break;
case IS_DOUBLE:
sprintf(tmpbuf, "=%.2f", Z_DVAL_PP(entry));
if (pass == 1)
strcpy(parmlist + parmlength, tmpbuf);
parmlength += strlen(tmpbuf);
break;
default:
if (parmlist) {
efree(parmlist);
}
efree(args);
php_error(E_ERROR, "pfpro_process() array values must be strings, ints or floats");
RETURN_FALSE;
}
zend_hash_move_forward(target_hash);
}
if (pass == 0) {
parmlist = emalloc(parmlength + 1);
}
}
efree(args);
if (address == NULL) {
address = estrdup(PFPROG(defaulthost));
freeaddress = 1;
}
array_init(return_value);
#if PFPRO_VERSION < 3
memset(response, 0, sizeof(response));
#endif
if (PFPROG(initialized) == 0) {
pfproInit();
PFPROG(initialized) = 1;
}
#if PFPRO_VERSION < 3
ProcessPNTransaction(address, port, proxyAddress, proxyPort, proxyLogon, proxyPassword, parmlist, strlen(parmlist), timeout, response);
#else
pfproCreateContext(&context, address, port, timeout, proxyAddress, proxyPort, proxyLogon, proxyPassword);
pfproSubmitTransaction(context, parmlist, strlen(parmlist), &response);
pfproDestroyContext(context);
#endif
if (freeaddress) {
efree(address);
}
if (parmlist) {
efree(parmlist);
}
var = php_strtok_r(response, "&", &strtok_buf);
while (var) {
val = strchr(var, '=');
if (val) {
*val++ = '\0';
add_assoc_string(return_value, var, val, 1);
}
var = php_strtok_r(NULL, "&", &strtok_buf);
}
}
#endif