Annotation of embedaddon/php/sapi/milter/php_milter.c, revision 1.1
1.1 ! misho 1: /*
! 2: +----------------------------------------------------------------------+
! 3: | PHP Version 5 |
! 4: +----------------------------------------------------------------------+
! 5: | Copyright (c) 1997-2012 The PHP Group |
! 6: +----------------------------------------------------------------------+
! 7: | This source file is subject to version 3.01 of the PHP license, |
! 8: | that is bundled with this package in the file LICENSE, and is |
! 9: | available through the world-wide-web at the following url: |
! 10: | http://www.php.net/license/3_01.txt |
! 11: | If you did not receive a copy of the PHP license and are unable to |
! 12: | obtain it through the world-wide-web, please send a note to |
! 13: | license@php.net so we can mail you a copy immediately. |
! 14: +----------------------------------------------------------------------+
! 15: | Author: Harald Radi <phanto@php.net> |
! 16: | Parts based on CGI SAPI Module by |
! 17: | Rasmus Lerdorf, Stig Bakken and Zeev Suraski |
! 18: +----------------------------------------------------------------------+
! 19: */
! 20:
! 21: /* $Id: php_milter.c 321634 2012-01-01 13:15:04Z felipe $ */
! 22:
! 23: #include "php.h"
! 24: #include "php_globals.h"
! 25: #include "php_variables.h"
! 26: #include "zend_modules.h"
! 27:
! 28: #ifndef ZTS
! 29: #error SRM sapi module is only useable in thread-safe mode
! 30: #endif
! 31:
! 32: #include "SAPI.h"
! 33:
! 34: #include <stdio.h>
! 35: #include "php.h"
! 36: #if HAVE_SYS_TIME_H
! 37: #include <sys/time.h>
! 38: #endif
! 39: #if HAVE_UNISTD_H
! 40: #include <unistd.h>
! 41: #endif
! 42: #if HAVE_SIGNAL_H
! 43: #include <signal.h>
! 44: #endif
! 45: #if HAVE_SETLOCALE
! 46: #include <locale.h>
! 47: #endif
! 48: #include "zend.h"
! 49: #include "zend_extensions.h"
! 50: #include "php_ini.h"
! 51: #include "php_globals.h"
! 52: #include "php_main.h"
! 53: #include "fopen_wrappers.h"
! 54: #include "ext/standard/php_standard.h"
! 55:
! 56: #ifdef __riscos__
! 57: #include <unixlib/local.h>
! 58: #endif
! 59:
! 60: #include "zend_compile.h"
! 61: #include "zend_execute.h"
! 62: #include "zend_highlight.h"
! 63: #include "zend_indent.h"
! 64:
! 65: #include "libmilter/mfapi.h"
! 66:
! 67: #include "php_getopt.h"
! 68:
! 69: #define OPTSTRING "ac:d:Def:hnp:vVz:?"
! 70: #define MG(v) TSRMG(milter_globals_id, zend_milter_globals *, v)
! 71:
! 72: #define IS_NONE "%s(): This function must not be called outside of a milter callback function's scope"
! 73: #define NOT_EOM "%s(): This function can only be used inside the milter_eom callback's scope"
! 74: #define NOT_INIT "%s(): This function can only be used inside the milter_init callback's scope"
! 75:
! 76: #define MLFI_NONE 0
! 77: #define MLFI_CONNECT 1
! 78: #define MLFI_HELO 2
! 79: #define MLFI_ENVFROM 3
! 80: #define MLFI_ENVRCPT 4
! 81: #define MLFI_HEADER 5
! 82: #define MLFI_EOH 6
! 83: #define MLFI_BODY 7
! 84: #define MLFI_EOM 8
! 85: #define MLFI_ABORT 9
! 86: #define MLFI_CLOSE 10
! 87: #define MLFI_INIT 11
! 88:
! 89: /* {{{ globals
! 90: */
! 91: extern char *ap_php_optarg;
! 92: extern int ap_php_optind;
! 93:
! 94: static int flag_debug=0;
! 95: static char *filename = NULL;
! 96:
! 97: /* per thread */
! 98: ZEND_BEGIN_MODULE_GLOBALS(milter)
! 99: SMFICTX *ctx;
! 100: int state;
! 101: int initialized;
! 102: ZEND_END_MODULE_GLOBALS(milter)
! 103:
! 104: ZEND_DECLARE_MODULE_GLOBALS(milter)
! 105: /* }}} */
! 106:
! 107: /* this method is called only once when the milter starts */
! 108: /* {{{ Init Milter
! 109: */
! 110: static int mlfi_init()
! 111: {
! 112: int ret = 0;
! 113: zend_file_handle file_handle;
! 114: zval function_name, retval;
! 115: int status;
! 116: TSRMLS_FETCH();
! 117:
! 118: /* request startup */
! 119: if (php_request_startup(TSRMLS_C)==FAILURE) {
! 120: SG(headers_sent) = 1;
! 121: SG(request_info).no_headers = 1;
! 122: php_request_shutdown((void *) 0);
! 123:
! 124: return -1;
! 125: }
! 126:
! 127: /* disable headers */
! 128: SG(headers_sent) = 1;
! 129: SG(request_info).no_headers = 1;
! 130:
! 131: if (filename == NULL) {
! 132: php_printf("No input file specified");
! 133: return SMFIS_TEMPFAIL;
! 134: }
! 135:
! 136: if (!(file_handle.handle.fp = VCWD_FOPEN(filename, "rb"))) {
! 137: php_printf("Could not open input file: %s\n", filename);
! 138: return SMFIS_TEMPFAIL;
! 139: }
! 140:
! 141: file_handle.type = ZEND_HANDLE_FP;
! 142: file_handle.filename = filename;
! 143: file_handle.free_filename = 0;
! 144: file_handle.opened_path = NULL;
! 145:
! 146: php_execute_script(&file_handle TSRMLS_CC);
! 147:
! 148: /* call userland */
! 149: INIT_ZVAL(function_name);
! 150:
! 151: ZVAL_STRING(&function_name, "milter_init", 0);
! 152:
! 153: /* set the milter context for possible use in API functions */
! 154: MG(state) = MLFI_INIT;
! 155:
! 156: status = call_user_function(CG(function_table), NULL, &function_name, &retval, 0, NULL TSRMLS_CC);
! 157:
! 158: MG(state) = MLFI_NONE;
! 159: MG(initialized) = 1;
! 160:
! 161: if (status == SUCCESS && Z_TYPE(retval) == IS_LONG) {
! 162: ret = Z_LVAL(retval);
! 163: }
! 164:
! 165: php_request_shutdown((void *) 0);
! 166:
! 167: return ret;
! 168: }
! 169: /* }}} */
! 170:
! 171: /* {{{ Milter callback functions
! 172: */
! 173:
! 174: /* connection info filter, is called whenever sendmail connects to the milter */
! 175: /* {{{ mlfi_connect()
! 176: */
! 177: static sfsistat mlfi_connect(SMFICTX *ctx, char *hostname, _SOCK_ADDR *hostaddr)
! 178: {
! 179: zend_file_handle file_handle;
! 180: zval function_name, retval, *param[1];
! 181: int status;
! 182: TSRMLS_FETCH();
! 183:
! 184: /* request startup */
! 185: if (php_request_startup(TSRMLS_C)==FAILURE) {
! 186: SG(headers_sent) = 1;
! 187: SG(request_info).no_headers = 1;
! 188: php_request_shutdown((void *) 0);
! 189:
! 190: return SMFIS_TEMPFAIL;
! 191: }
! 192:
! 193: /* disable headers */
! 194: SG(headers_sent) = 1;
! 195: SG(request_info).no_headers = 1;
! 196:
! 197: if (filename == NULL) {
! 198: php_printf("No input file specified");
! 199: return SMFIS_TEMPFAIL;
! 200: }
! 201:
! 202: if (!(file_handle.handle.fp = VCWD_FOPEN(filename, "rb"))) {
! 203: php_printf("Could not open input file: %s\n", filename);
! 204: return SMFIS_TEMPFAIL;
! 205: }
! 206:
! 207: file_handle.type = ZEND_HANDLE_FP;
! 208: file_handle.filename = filename;
! 209: file_handle.free_filename = 0;
! 210: file_handle.opened_path = NULL;
! 211:
! 212: php_execute_script(&file_handle TSRMLS_CC);
! 213:
! 214: /* call userland */
! 215: INIT_ZVAL(function_name);
! 216:
! 217: ALLOC_ZVAL(param[0]);
! 218: INIT_PZVAL(param[0]);
! 219:
! 220: ZVAL_STRING(&function_name, "milter_connect", 0);
! 221: ZVAL_STRING(param[0], hostname, 1);
! 222:
! 223: /* set the milter context for possible use in API functions */
! 224: MG(ctx) = ctx;
! 225: MG(state) = MLFI_CONNECT;
! 226:
! 227: status = call_user_function(CG(function_table), NULL, &function_name, &retval, 1, param TSRMLS_CC);
! 228:
! 229: MG(state) = MLFI_NONE;
! 230: zval_ptr_dtor(param);
! 231: if (status == SUCCESS && Z_TYPE(retval) == IS_LONG) {
! 232: return Z_LVAL(retval);
! 233: }
! 234:
! 235: return SMFIS_CONTINUE;
! 236: }
! 237: /* }}} */
! 238:
! 239: /* SMTP HELO command filter */
! 240: /* {{{ mlfi_helo()
! 241: */
! 242: static sfsistat mlfi_helo(SMFICTX *ctx, char *helohost)
! 243: {
! 244: zval function_name, retval, *param[1];
! 245: int status;
! 246: TSRMLS_FETCH();
! 247:
! 248: /* call userland */
! 249: INIT_ZVAL(function_name);
! 250:
! 251: ALLOC_ZVAL(param[0]);
! 252: INIT_PZVAL(param[0]);
! 253:
! 254: ZVAL_STRING(&function_name, "milter_helo", 0);
! 255: ZVAL_STRING(param[0], helohost, 1);
! 256:
! 257: /* set the milter context for possible use in API functions */
! 258: MG(ctx) = ctx;
! 259: MG(state) = MLFI_HELO;
! 260:
! 261: status = call_user_function(CG(function_table), NULL, &function_name, &retval, 1, param TSRMLS_CC);
! 262:
! 263: MG(state) = MLFI_NONE;
! 264: zval_ptr_dtor(param);
! 265:
! 266: if (status == SUCCESS && Z_TYPE(retval) == IS_LONG) {
! 267: return Z_LVAL(retval);
! 268: }
! 269:
! 270: return SMFIS_CONTINUE;
! 271: }
! 272: /* }}} */
! 273:
! 274: /* envelope sender filter */
! 275: /* {{{ mlfi_envform()
! 276: */
! 277: static sfsistat mlfi_envfrom(SMFICTX *ctx, char **argv)
! 278: {
! 279: zval function_name, retval, *param[1];
! 280: int status;
! 281: TSRMLS_FETCH();
! 282:
! 283: /* call userland */
! 284: INIT_ZVAL(function_name);
! 285:
! 286: ALLOC_ZVAL(param[0]);
! 287: INIT_PZVAL(param[0]);
! 288:
! 289: ZVAL_STRING(&function_name, "milter_envfrom", 0);
! 290: array_init(param[0]);
! 291:
! 292: while (*argv) {
! 293: add_next_index_string(param[0], *argv, 1);
! 294: argv++;
! 295: }
! 296:
! 297: /* set the milter context for possible use in API functions */
! 298: MG(ctx) = ctx;
! 299: MG(state) = MLFI_ENVFROM;
! 300:
! 301: status = call_user_function(CG(function_table), NULL, &function_name, &retval, 1, param TSRMLS_CC);
! 302:
! 303: MG(state) = MLFI_NONE;
! 304: zval_ptr_dtor(param);
! 305:
! 306: if (status == SUCCESS && Z_TYPE(retval) == IS_LONG) {
! 307: return Z_LVAL(retval);
! 308: }
! 309:
! 310: return SMFIS_CONTINUE;
! 311: }
! 312: /* }}} */
! 313:
! 314: /* envelope recipient filter */
! 315: /* {{{ mlfi_envrcpt()
! 316: */
! 317: static sfsistat mlfi_envrcpt(SMFICTX *ctx, char **argv)
! 318: {
! 319: zval function_name, retval, *param[1];
! 320: int status;
! 321: TSRMLS_FETCH();
! 322:
! 323: /* call userland */
! 324: INIT_ZVAL(function_name);
! 325:
! 326: ALLOC_ZVAL(param[0]);
! 327: INIT_PZVAL(param[0]);
! 328:
! 329: ZVAL_STRING(&function_name, "milter_envrcpt", 0);
! 330: array_init(param[0]);
! 331:
! 332: while (*argv) {
! 333: add_next_index_string(param[0], *argv, 1);
! 334: argv++;
! 335: }
! 336:
! 337: /* set the milter context for possible use in API functions */
! 338: MG(ctx) = ctx;
! 339: MG(state) = MLFI_ENVRCPT;
! 340:
! 341: status = call_user_function(CG(function_table), NULL, &function_name, &retval, 1, param TSRMLS_CC);
! 342:
! 343: MG(state) = MLFI_NONE;
! 344:
! 345: zval_ptr_dtor(param);
! 346:
! 347: if (status == SUCCESS && Z_TYPE(retval) == IS_LONG) {
! 348: return Z_LVAL(retval);
! 349: }
! 350:
! 351: return SMFIS_CONTINUE;
! 352: }
! 353: /* }}} */
! 354:
! 355: /* header filter */
! 356: /* {{{ mlfi_header()
! 357: */
! 358: static sfsistat mlfi_header(SMFICTX *ctx, char *headerf, char *headerv)
! 359: {
! 360: zval function_name, retval, *param[2];
! 361: int status;
! 362: TSRMLS_FETCH();
! 363:
! 364: /* call userland */
! 365: INIT_ZVAL(function_name);
! 366:
! 367: ALLOC_ZVAL(param[0]);
! 368: ALLOC_ZVAL(param[1]);
! 369: INIT_PZVAL(param[0]);
! 370: INIT_PZVAL(param[1]);
! 371:
! 372: ZVAL_STRING(&function_name, "milter_header", 0);
! 373: ZVAL_STRING(param[0], headerf, 1);
! 374: ZVAL_STRING(param[1], headerv, 1);
! 375:
! 376: /* set the milter context for possible use in API functions */
! 377: MG(ctx) = ctx;
! 378: MG(state) = MLFI_HEADER;
! 379:
! 380: status = call_user_function(CG(function_table), NULL, &function_name, &retval, 2, param TSRMLS_CC);
! 381:
! 382: MG(state) = MLFI_NONE;
! 383:
! 384: zval_ptr_dtor(¶m[0]);
! 385: zval_ptr_dtor(¶m[1]);
! 386:
! 387: if (status == SUCCESS && Z_TYPE(retval) == IS_LONG) {
! 388: return Z_LVAL(retval);
! 389: }
! 390:
! 391: return SMFIS_CONTINUE;
! 392: }
! 393: /* }}} */
! 394:
! 395: /* end of header */
! 396: /* {{{ mlfi_eoh()
! 397: */
! 398: static sfsistat mlfi_eoh(SMFICTX *ctx)
! 399: {
! 400: zval function_name, retval;
! 401: int status;
! 402: TSRMLS_FETCH();
! 403:
! 404: /* call userland */
! 405: INIT_ZVAL(function_name);
! 406: ZVAL_STRING(&function_name, "milter_eoh", 0);
! 407:
! 408: /* set the milter context for possible use in API functions */
! 409: MG(ctx) = ctx;
! 410: MG(state) = MLFI_EOH;
! 411:
! 412: status = call_user_function(CG(function_table), NULL, &function_name, &retval, 0, NULL TSRMLS_CC);
! 413:
! 414: MG(state) = MLFI_NONE;
! 415:
! 416: if (status == SUCCESS && Z_TYPE(retval) == IS_LONG) {
! 417: return Z_LVAL(retval);
! 418: }
! 419:
! 420: return SMFIS_CONTINUE;
! 421: }
! 422: /* }}} */
! 423:
! 424: /* body block */
! 425: /* {{{ mlfi_body()
! 426: */
! 427: static sfsistat mlfi_body(SMFICTX *ctx, u_char *bodyp, size_t len)
! 428: {
! 429: zval function_name, retval, *param[1];
! 430: int status;
! 431: TSRMLS_FETCH();
! 432:
! 433: /* call userland */
! 434: INIT_ZVAL(function_name);
! 435:
! 436: ALLOC_ZVAL(param[0]);
! 437: INIT_PZVAL(param[0]);
! 438:
! 439: ZVAL_STRING(&function_name, "milter_body", 0);
! 440: ZVAL_STRINGL(param[0], (char*)bodyp, len, 1); /*alex*/
! 441:
! 442: /* set the milter context for possible use in API functions */
! 443: MG(ctx) = ctx;
! 444: MG(state) = MLFI_BODY;
! 445:
! 446: status = call_user_function(CG(function_table), NULL, &function_name, &retval, 1, param TSRMLS_CC);
! 447:
! 448: MG(state) = MLFI_NONE;
! 449:
! 450: zval_ptr_dtor(param);
! 451:
! 452: if (status == SUCCESS && Z_TYPE(retval) == IS_LONG) {
! 453: return Z_LVAL(retval);
! 454: }
! 455:
! 456: return SMFIS_CONTINUE;
! 457: }
! 458: /* }}} */
! 459:
! 460: /* end of message */
! 461: /* {{{ mlfi_eom()
! 462: */
! 463: static sfsistat mlfi_eom(SMFICTX *ctx)
! 464: {
! 465: zval function_name, retval;
! 466: int status;
! 467: TSRMLS_FETCH();
! 468:
! 469: /* call userland */
! 470: INIT_ZVAL(function_name);
! 471: ZVAL_STRING(&function_name, "milter_eom", 0);
! 472:
! 473: /* set the milter context for possible use in API functions */
! 474: MG(ctx) = ctx;
! 475: MG(state) = MLFI_EOM;
! 476:
! 477: status = call_user_function(CG(function_table), NULL, &function_name, &retval, 0, NULL TSRMLS_CC);
! 478:
! 479: MG(state) = MLFI_NONE;
! 480:
! 481: if (status == SUCCESS && Z_TYPE(retval) == IS_LONG) {
! 482: return Z_LVAL(retval);
! 483: }
! 484:
! 485: return SMFIS_CONTINUE;
! 486: }
! 487: /* }}} */
! 488:
! 489: /* message aborted */
! 490: /* {{{ mlfi_abort()
! 491: */
! 492: static sfsistat mlfi_abort(SMFICTX *ctx)
! 493: {
! 494: zval function_name, retval;
! 495: int status;
! 496: TSRMLS_FETCH();
! 497:
! 498: /* call userland */
! 499: INIT_ZVAL(function_name);
! 500: ZVAL_STRING(&function_name, "milter_abort", 0);
! 501:
! 502: /* set the milter context for possible use in API functions */
! 503: MG(ctx) = ctx;
! 504: MG(state) = MLFI_ABORT;
! 505:
! 506: status = call_user_function(CG(function_table), NULL, &function_name, &retval, 0, NULL TSRMLS_CC);
! 507:
! 508: MG(state) = MLFI_NONE;
! 509:
! 510: if (status == SUCCESS && Z_TYPE(retval) == IS_LONG) {
! 511: return Z_LVAL(retval);
! 512: }
! 513:
! 514: return SMFIS_CONTINUE;
! 515: }
! 516: /* }}} */
! 517:
! 518: /* connection cleanup */
! 519: /* {{{ mlfi_close()
! 520: */
! 521: static sfsistat mlfi_close(SMFICTX *ctx)
! 522: {
! 523: int ret = SMFIS_CONTINUE;
! 524: zval function_name, retval;
! 525: int status;
! 526: TSRMLS_FETCH();
! 527:
! 528: /* call userland */
! 529: INIT_ZVAL(function_name);
! 530: ZVAL_STRING(&function_name, "milter_close", 0);
! 531:
! 532: /* set the milter context for possible use in API functions */
! 533: MG(ctx) = ctx;
! 534: MG(state) = MLFI_CLOSE;
! 535:
! 536: status = call_user_function(CG(function_table), NULL, &function_name, &retval, 0, NULL TSRMLS_CC);
! 537:
! 538: MG(state) = MLFI_NONE;
! 539:
! 540: if (status == SUCCESS && Z_TYPE(retval) == IS_LONG) {
! 541: ret = Z_LVAL(retval);
! 542: }
! 543:
! 544: php_request_shutdown((void *) 0);
! 545:
! 546: return ret;
! 547: }
! 548: /* }}} */
! 549: /* }}} */
! 550:
! 551: /* {{{ Milter entry struct
! 552: */
! 553: struct smfiDesc smfilter = {
! 554: "php-milter", /* filter name */
! 555: SMFI_VERSION, /* version code -- leave untouched */
! 556: 0, /* flags */
! 557: mlfi_connect, /* info filter callback */
! 558: mlfi_helo, /* HELO filter callback */
! 559: mlfi_envfrom, /* envelope filter callback */
! 560: mlfi_envrcpt, /* envelope recipient filter callback */
! 561: mlfi_header, /* header filter callback */
! 562: mlfi_eoh, /* end of header callback */
! 563: mlfi_body, /* body filter callback */
! 564: mlfi_eom, /* end of message callback */
! 565: mlfi_abort, /* message aborted callback */
! 566: mlfi_close, /* connection cleanup callback */
! 567: };
! 568: /* }}} */
! 569:
! 570: /* {{{ PHP Milter API
! 571: */
! 572:
! 573: /* {{{ proto void smfi_setflags(long flags)
! 574: Sets the flags describing the actions the filter may take. */
! 575: PHP_FUNCTION(smfi_setflags)
! 576: {
! 577: long flags;
! 578:
! 579: /* valid only in the init callback */
! 580: if (MG(state) != MLFI_INIT) {
! 581: php_error(E_WARNING, NOT_INIT, get_active_function_name(TSRMLS_C));
! 582: } else if (zend_parse_parameters(1 TSRMLS_CC, "l", &flags) == SUCCESS) {
! 583: flags = flags & (SMFIF_ADDHDRS|SMFIF_CHGHDRS|SMFIF_CHGBODY|SMFIF_ADDRCPT|SMFIF_DELRCPT);
! 584: smfilter.xxfi_flags = flags;
! 585: }
! 586: }
! 587: /* }}} */
! 588:
! 589: /* {{{ proto void smfi_settimeout(long timeout)
! 590: Sets the number of seconds libmilter will wait for an MTA connection before timing out a socket. */
! 591: PHP_FUNCTION(smfi_settimeout)
! 592: {
! 593: long timeout;
! 594:
! 595: /* valid only in the init callback */
! 596: if (MG(state) != MLFI_INIT) {
! 597: php_error(E_WARNING, NOT_INIT, get_active_function_name(TSRMLS_C));
! 598: } else if (zend_parse_parameters(1 TSRMLS_CC, "l", &timeout) == SUCCESS) {
! 599: smfi_settimeout(timeout);
! 600: }
! 601: }
! 602: /* }}} */
! 603:
! 604: /* {{{ proto string smfi_getsymval(string macro)
! 605: Returns the value of the given macro or NULL if the macro is not defined. */
! 606: PHP_FUNCTION(smfi_getsymval)
! 607: {
! 608: char *symname, *ret;
! 609: int len;
! 610:
! 611: /* valid in any callback */
! 612: if (MG(state) == MLFI_NONE) {
! 613: php_error(E_WARNING, IS_NONE, get_active_function_name(TSRMLS_C));
! 614: } else if (zend_parse_parameters(1 TSRMLS_CC, "s", &symname, &len) == SUCCESS) {
! 615: if ((ret = smfi_getsymval(MG(ctx), symname)) != NULL) {
! 616: RETURN_STRING(ret, 1);
! 617: }
! 618: }
! 619:
! 620: RETURN_NULL();
! 621: }
! 622: /* }}} */
! 623:
! 624: /* {{{ proto bool smfi_setreply(string rcode, string xcode, string message)
! 625: Directly set the SMTP error reply code for this connection.
! 626: This code will be used on subsequent error replies resulting from actions taken by this filter. */
! 627: PHP_FUNCTION(smfi_setreply)
! 628: {
! 629: char *rcode, *xcode, *message;
! 630: int len;
! 631:
! 632: /* valid in any callback */
! 633: if (MG(state) == MLFI_NONE) {
! 634: php_error(E_WARNING, IS_NONE, get_active_function_name(TSRMLS_C));
! 635: } else if (zend_parse_parameters(3 TSRMLS_CC, "sss", &rcode, &len, &xcode, &len, &message, &len) == SUCCESS) {
! 636: if (smfi_setreply(MG(ctx), rcode, xcode, message) == MI_SUCCESS) {
! 637: RETURN_TRUE;
! 638: }
! 639: }
! 640:
! 641: RETURN_FALSE;
! 642: }
! 643: /* }}} */
! 644:
! 645: /* {{{ proto bool smfi_addheader(string headerf, string headerv)
! 646: Adds a header to the current message. */
! 647: PHP_FUNCTION(smfi_addheader)
! 648: {
! 649: char *f, *v;
! 650: int len;
! 651:
! 652: /* valid only in milter_eom */
! 653: if (MG(state) != MLFI_EOM) {
! 654: php_error(E_WARNING, NOT_EOM, get_active_function_name(TSRMLS_C));
! 655: } else if (zend_parse_parameters(2 TSRMLS_CC, "ss", &f, &len, &v, &len) == SUCCESS) {
! 656: if (smfi_addheader(MG(ctx), f, v) == MI_SUCCESS) {
! 657: RETURN_TRUE;
! 658: }
! 659: }
! 660:
! 661: RETURN_FALSE;
! 662: }
! 663: /* }}} */
! 664:
! 665: /* {{{ proto bool smfi_chgheader(string headerf, string headerv)
! 666: Changes a header's value for the current message. */
! 667: PHP_FUNCTION(smfi_chgheader)
! 668: {
! 669: char *f, *v;
! 670: long idx;
! 671: int len;
! 672:
! 673: /* valid only in milter_eom */
! 674: if (MG(state) != MLFI_EOM) {
! 675: php_error(E_WARNING, NOT_EOM, get_active_function_name(TSRMLS_C));
! 676: } else if (zend_parse_parameters(3 TSRMLS_CC, "sls", &f, &len, &idx, &v, &len) == SUCCESS) {
! 677: if (smfi_chgheader(MG(ctx), f, idx, v) == MI_SUCCESS) {
! 678: RETURN_TRUE;
! 679: }
! 680: }
! 681:
! 682: RETURN_FALSE;
! 683: }
! 684: /* }}} */
! 685:
! 686: /* {{{ proto bool smfi_addrcpt(string rcpt)
! 687: Add a recipient to the message envelope. */
! 688: PHP_FUNCTION(smfi_addrcpt)
! 689: {
! 690: char *rcpt;
! 691: int len;
! 692:
! 693: /* valid only in milter_eom */
! 694: if (MG(state) != MLFI_EOM) {
! 695: php_error(E_WARNING, NOT_EOM, get_active_function_name(TSRMLS_C));
! 696: } else if (zend_parse_parameters(1 TSRMLS_CC, "s", &rcpt, &len) == SUCCESS) {
! 697: if (smfi_addrcpt(MG(ctx), rcpt) == MI_SUCCESS) {
! 698: RETURN_TRUE;
! 699: }
! 700: }
! 701:
! 702: RETURN_FALSE;
! 703: }
! 704: /* }}} */
! 705:
! 706: /* {{{ proto bool smfi_delrcpt(string rcpt)
! 707: Removes the named recipient from the current message's envelope. */
! 708: PHP_FUNCTION(smfi_delrcpt)
! 709: {
! 710: char *rcpt;
! 711: int len;
! 712:
! 713: /* valid only in milter_eom */
! 714: if (MG(state) != MLFI_EOM) {
! 715: php_error(E_WARNING, NOT_EOM, get_active_function_name(TSRMLS_C));
! 716: } else if (zend_parse_parameters(1 TSRMLS_CC, "s", &rcpt, &len) == SUCCESS) {
! 717: if (smfi_delrcpt(MG(ctx), rcpt) == MI_SUCCESS) {
! 718: RETURN_TRUE;
! 719: }
! 720: }
! 721:
! 722: RETURN_FALSE;
! 723: }
! 724: /* }}} */
! 725:
! 726: /* {{{ proto bool smfi_replacebody(string body)
! 727: Replaces the body of the current message. If called more than once,
! 728: subsequent calls result in data being appended to the new body. */
! 729: PHP_FUNCTION(smfi_replacebody)
! 730: {
! 731: char *body;
! 732: int len;
! 733:
! 734: /* valid only in milter_eom */
! 735: if (MG(state) != MLFI_EOM) {
! 736: php_error(E_WARNING, NOT_EOM, get_active_function_name(TSRMLS_C));
! 737: } else if (zend_parse_parameters(1 TSRMLS_CC, "s", &body, &len) == SUCCESS) {
! 738: if (smfi_replacebody(MG(ctx), (u_char*)body, len) == MI_SUCCESS) {
! 739: RETURN_TRUE;
! 740: }
! 741: }
! 742:
! 743: RETURN_FALSE;
! 744: }
! 745: /* }}} */
! 746:
! 747: /* {{{ PHP_MINIT_FUNCTION
! 748: */
! 749: PHP_MINIT_FUNCTION(milter)
! 750: {
! 751: REGISTER_LONG_CONSTANT("SMFIS_CONTINUE", SMFIS_CONTINUE, CONST_CS | CONST_PERSISTENT);
! 752: REGISTER_LONG_CONSTANT("SMFIS_REJECT", SMFIS_REJECT, CONST_CS | CONST_PERSISTENT);
! 753: REGISTER_LONG_CONSTANT("SMFIS_DISCARD", SMFIS_DISCARD, CONST_CS | CONST_PERSISTENT);
! 754: REGISTER_LONG_CONSTANT("SMFIS_ACCEPT", SMFIS_ACCEPT, CONST_CS | CONST_PERSISTENT);
! 755: REGISTER_LONG_CONSTANT("SMFIS_TEMPFAIL", SMFIS_TEMPFAIL, CONST_CS | CONST_PERSISTENT);
! 756:
! 757: REGISTER_LONG_CONSTANT("SMFIF_ADDHDRS", SMFIF_ADDHDRS, CONST_CS | CONST_PERSISTENT);
! 758: REGISTER_LONG_CONSTANT("SMFIF_CHGHDRS", SMFIF_CHGHDRS, CONST_CS | CONST_PERSISTENT);
! 759: REGISTER_LONG_CONSTANT("SMFIF_CHGBODY", SMFIF_CHGBODY, CONST_CS | CONST_PERSISTENT);
! 760: REGISTER_LONG_CONSTANT("SMFIF_ADDRCPT", SMFIF_ADDRCPT, CONST_CS | CONST_PERSISTENT);
! 761: REGISTER_LONG_CONSTANT("SMFIF_DELRCPT", SMFIF_DELRCPT, CONST_CS | CONST_PERSISTENT);
! 762:
! 763: ZEND_INIT_MODULE_GLOBALS(milter, NULL, NULL);
! 764:
! 765: MG(state) = MLFI_NONE;
! 766: MG(initialized) = 0;
! 767: return SUCCESS;
! 768: }
! 769: /* }}} */
! 770:
! 771: /* {{{ PHP_MINFO_FUNCTION
! 772: */
! 773: PHP_MINFO_FUNCTION(milter)
! 774: {
! 775: php_info_print_table_start();
! 776: php_info_print_table_header(2, "Milter support", "enabled");
! 777: php_info_print_table_end();
! 778: }
! 779: /* }}} */
! 780: /* }}} */
! 781:
! 782: /* {{{ arginfo */
! 783: ZEND_BEGIN_ARG_INFO_EX(arginfo_smfi_setflags, 0, 0, 1)
! 784: ZEND_ARG_INFO(0, flags)
! 785: ZEND_END_ARG_INFO()
! 786:
! 787: ZEND_BEGIN_ARG_INFO_EX(arginfo_smfi_settimeout, 0, 0, 1)
! 788: ZEND_ARG_INFO(0, timeout)
! 789: ZEND_END_ARG_INFO()
! 790:
! 791: ZEND_BEGIN_ARG_INFO_EX(arginfo_smfi_getsymval, 0, 0, 1)
! 792: ZEND_ARG_INFO(0, macro)
! 793: ZEND_END_ARG_INFO()
! 794:
! 795: ZEND_BEGIN_ARG_INFO_EX(arginfo_smfi_setreply, 0, 0, 3)
! 796: ZEND_ARG_INFO(0, rcode)
! 797: ZEND_ARG_INFO(0, xcode)
! 798: ZEND_ARG_INFO(0, message)
! 799: ZEND_END_ARG_INFO()
! 800:
! 801: ZEND_BEGIN_ARG_INFO_EX(arginfo_smfi_addheader, 0, 0, 2)
! 802: ZEND_ARG_INFO(0, headerf)
! 803: ZEND_ARG_INFO(0, headerv)
! 804: ZEND_END_ARG_INFO()
! 805:
! 806: ZEND_BEGIN_ARG_INFO_EX(arginfo_smfi_chgheader, 0, 0, 2)
! 807: ZEND_ARG_INFO(0, headerf)
! 808: ZEND_ARG_INFO(0, headerv)
! 809: ZEND_END_ARG_INFO()
! 810:
! 811: ZEND_BEGIN_ARG_INFO_EX(arginfo_smfi_addrcpt, 0, 0, 1)
! 812: ZEND_ARG_INFO(0, rcpt)
! 813: ZEND_END_ARG_INFO()
! 814:
! 815: ZEND_BEGIN_ARG_INFO_EX(arginfo_smfi_delrcpt, 0, 0, 1)
! 816: ZEND_ARG_INFO(0, rcpt)
! 817: ZEND_END_ARG_INFO()
! 818:
! 819: ZEND_BEGIN_ARG_INFO_EX(arginfo_smfi_replacebody, 0, 0, 1)
! 820: ZEND_ARG_INFO(0, body)
! 821: ZEND_END_ARG_INFO()
! 822: /* }}} */
! 823:
! 824: /* {{{ milter_functions[]
! 825: */
! 826: const static zend_function_entry milter_functions[] = {
! 827: PHP_FE(smfi_setflags, arginfo_smfi_setflags)
! 828: PHP_FE(smfi_settimeout, arginfo_smfi_settimeout)
! 829: PHP_FE(smfi_getsymval, arginfo_smfi_getsymval)
! 830: PHP_FE(smfi_setreply, arginfo_smfi_setreply)
! 831: PHP_FE(smfi_addheader, arginfo_smfi_addheader)
! 832: PHP_FE(smfi_chgheader, arginfo_smfi_chgheader)
! 833: PHP_FE(smfi_addrcpt, arginfo_smfi_addrcpt)
! 834: PHP_FE(smfi_delrcpt, arginfo_smfi_delrcpt)
! 835: PHP_FE(smfi_replacebody, arginfo_smfi_replacebody)
! 836: PHP_FE_END
! 837: };
! 838: /* }}} */
! 839:
! 840: /* {{{ Zend module entry
! 841: */
! 842: static zend_module_entry php_milter_module = {
! 843: STANDARD_MODULE_HEADER,
! 844: "Milter",
! 845: milter_functions,
! 846: PHP_MINIT(milter),
! 847: NULL,
! 848: NULL,
! 849: NULL,
! 850: PHP_MINFO(milter),
! 851: "0.1.0",
! 852: STANDARD_MODULE_PROPERTIES
! 853: };
! 854: /* }}} */
! 855:
! 856: /* {{{ Milter SAPI
! 857: */
! 858: static int sapi_milter_ub_write(const char *str, uint str_length TSRMLS_DC)
! 859: {
! 860: return str_length;
! 861: }
! 862:
! 863: static void sapi_milter_flush(void *server_context)
! 864: {
! 865: }
! 866:
! 867: static void sapi_milter_register_variables(zval *track_vars_array TSRMLS_DC)
! 868: {
! 869: php_register_variable ("SERVER_SOFTWARE", "Sendmail Milter", track_vars_array TSRMLS_CC);
! 870: }
! 871:
! 872: static int sapi_milter_post_read(char *buf, uint count_bytes TSRMLS_DC)
! 873: {
! 874: return 0;
! 875: }
! 876:
! 877: static char* sapi_milter_read_cookies(TSRMLS_D)
! 878: {
! 879: return NULL;
! 880: }
! 881:
! 882: static int sapi_milter_send_headers(sapi_headers_struct *sapi_headers TSRMLS_DC)
! 883: {
! 884: return SAPI_HEADER_SENT_SUCCESSFULLY;
! 885: }
! 886:
! 887: static int php_milter_startup(sapi_module_struct *sapi_module)
! 888: {
! 889: if (php_module_startup(sapi_module, &php_milter_module, 1) == FAILURE) {
! 890: return FAILURE;
! 891: }
! 892: return SUCCESS;
! 893: }
! 894: /* }}} */
! 895:
! 896: /* {{{ sapi_module_struct milter_sapi_module
! 897: */
! 898: static sapi_module_struct milter_sapi_module = {
! 899: "milter", /* name */
! 900: "Sendmail Milter SAPI", /* pretty name */
! 901:
! 902: php_milter_startup, /* startup */
! 903: php_module_shutdown_wrapper, /* shutdown */
! 904:
! 905: NULL, /* activate */
! 906: NULL, /* deactivate */
! 907:
! 908: sapi_milter_ub_write, /* unbuffered write */
! 909: sapi_milter_flush, /* flush */
! 910: NULL, /* get uid */
! 911: NULL, /* getenv */
! 912:
! 913: php_error, /* error handler */
! 914:
! 915: NULL, /* header handler */
! 916: sapi_milter_send_headers, /* send headers handler */
! 917: NULL, /* send header handler */
! 918:
! 919: sapi_milter_post_read, /* read POST data */
! 920: sapi_milter_read_cookies, /* read Cookies */
! 921:
! 922: sapi_milter_register_variables, /* register server variables */
! 923: NULL, /* Log message */
! 924: NULL, /* Get request time */
! 925: NULL, /* Child terminate */
! 926:
! 927: NULL, /* Block interruptions */
! 928: NULL, /* Unblock interruptions */
! 929:
! 930: STANDARD_SAPI_MODULE_PROPERTIES
! 931: };
! 932: /* }}} */
! 933:
! 934: /****
! 935: * ripped from cli, has to be cleaned up !
! 936: */
! 937:
! 938: /* {{{ php_milter_usage
! 939: */
! 940: static void php_milter_usage(char *argv0)
! 941: {
! 942: char *prog;
! 943:
! 944: prog = strrchr(argv0, '/');
! 945: if (prog) {
! 946: prog++;
! 947: } else {
! 948: prog = "php-milter";
! 949: }
! 950:
! 951: printf( "Usage: %s [options] [-f] <file> [args...]\n"
! 952: " %s [options] [-- args...]\n"
! 953: " -a Run interactively\n"
! 954: " -c <path>|<file> Look for php.ini file in this directory\n"
! 955: " -n No php.ini file will be used\n"
! 956: " -d foo[=bar] Define INI entry foo with value 'bar'\n"
! 957: " -D run as daemon\n"
! 958: " -e Generate extended information for debugger/profiler\n"
! 959: " -f <file> Parse <file>.\n"
! 960: " -h This help\n"
! 961: " -p <socket> path to create socket\n"
! 962: " -v Version number\n"
! 963: " -V <n> set debug level to n (1 or 2).\n"
! 964: " -z <file> Load Zend extension <file>.\n"
! 965: " args... Arguments passed to script. Use -- args when first argument \n"
! 966: " starts with - or script is read from stdin\n"
! 967: , prog, prog);
! 968: }
! 969: /* }}} */
! 970:
! 971: static void define_command_line_ini_entry(char *arg) /* {{{ */
! 972: {
! 973: char *name, *value;
! 974:
! 975: name = arg;
! 976: value = strchr(arg, '=');
! 977: if (value) {
! 978: *value = 0;
! 979: value++;
! 980: } else {
! 981: value = "1";
! 982: }
! 983: zend_alter_ini_entry(name, strlen(name)+1, value, strlen(value), PHP_INI_SYSTEM, PHP_INI_STAGE_ACTIVATE);
! 984: }
! 985: /* }}} */
! 986:
! 987: /* {{{ main
! 988: */
! 989: int main(int argc, char *argv[])
! 990: {
! 991: char *sock = NULL;
! 992: int dofork = 0;
! 993:
! 994: int exit_status = SUCCESS;
! 995: int c;
! 996: /* temporary locals */
! 997: int orig_optind=ap_php_optind;
! 998: char *orig_optarg=ap_php_optarg;
! 999: int interactive=0;
! 1000: char *param_error=NULL;
! 1001: /* end of temporary locals */
! 1002:
! 1003: void ***tsrm_ls;
! 1004:
! 1005: #ifdef HAVE_SIGNAL_H
! 1006: #if defined(SIGPIPE) && defined(SIG_IGN)
! 1007: signal(SIGPIPE, SIG_IGN); /* ignore SIGPIPE in standalone mode so
! 1008: that sockets created via fsockopen()
! 1009: don't kill PHP if the remote site
! 1010: closes it. in apache|apxs mode apache
! 1011: does that for us! thies@thieso.net
! 1012: 20000419 */
! 1013: #endif
! 1014: #endif
! 1015:
! 1016:
! 1017: tsrm_startup(1, 1, 0, NULL);
! 1018: sapi_startup(&milter_sapi_module);
! 1019:
! 1020: while ((c=ap_php_getopt(argc, argv, OPTSTRING))!=-1) {
! 1021: switch (c) {
! 1022: case 'c':
! 1023: milter_sapi_module.php_ini_path_override = strdup(ap_php_optarg);
! 1024: break;
! 1025: case 'n':
! 1026: milter_sapi_module.php_ini_ignore = 1;
! 1027: break;
! 1028: }
! 1029: }
! 1030: ap_php_optind = orig_optind;
! 1031: ap_php_optarg = orig_optarg;
! 1032:
! 1033: milter_sapi_module.executable_location = argv[0];
! 1034:
! 1035: tsrm_ls = ts_resource(0);
! 1036:
! 1037: sapi_module.startup(&milter_sapi_module);
! 1038:
! 1039: zend_first_try {
! 1040: while ((c=ap_php_getopt(argc, argv, OPTSTRING))!=-1) {
! 1041: switch (c) {
! 1042: case '?':
! 1043: php_output_startup();
! 1044: php_output_activate(TSRMLS_C);
! 1045: SG(headers_sent) = 1;
! 1046: php_milter_usage(argv[0]);
! 1047: php_end_ob_buffers(1 TSRMLS_CC);
! 1048: exit(1);
! 1049: break;
! 1050: }
! 1051: }
! 1052: ap_php_optind = orig_optind;
! 1053: ap_php_optarg = orig_optarg;
! 1054:
! 1055: /* Set some CLI defaults */
! 1056: SG(options) |= SAPI_OPTION_NO_CHDIR;
! 1057: zend_alter_ini_entry("html_errors", 12, "0", 1, PHP_INI_SYSTEM, PHP_INI_STAGE_ACTIVATE);
! 1058: zend_alter_ini_entry("max_execution_time", 19, "0", 1, PHP_INI_SYSTEM, PHP_INI_STAGE_ACTIVATE);
! 1059:
! 1060: zend_uv.html_errors = 0; /* tell the engine we're in non-html mode */
! 1061:
! 1062: while ((c = ap_php_getopt(argc, argv, OPTSTRING)) != -1) {
! 1063: switch (c) {
! 1064:
! 1065: case 'a': /* interactive mode */
! 1066: printf("Interactive mode enabled\n\n");
! 1067: interactive=1;
! 1068: break;
! 1069:
! 1070: case 'C': /* don't chdir to the script directory */
! 1071: /* This is default so NOP */
! 1072: break;
! 1073: case 'd': /* define ini entries on command line */
! 1074: define_command_line_ini_entry(ap_php_optarg);
! 1075: break;
! 1076:
! 1077: case 'D': /* daemon */
! 1078: dofork = 1;
! 1079: break;
! 1080:
! 1081: case 'e': /* enable extended info output */
! 1082: CG(compiler_options) |= ZEND_COMPILE_EXTENDED_INFO;
! 1083: break;
! 1084:
! 1085: case 'f': /* parse file */
! 1086: filename = ap_php_optarg;
! 1087: break;
! 1088:
! 1089: case 'h': /* help & quit */
! 1090: case '?':
! 1091: php_output_startup();
! 1092: php_output_activate(TSRMLS_C);
! 1093: SG(headers_sent) = 1;
! 1094: php_milter_usage(argv[0]);
! 1095: php_end_ob_buffers(1 TSRMLS_CC);
! 1096: exit(1);
! 1097: break;
! 1098:
! 1099: case 'p': /* socket */
! 1100: sock = strdup(ap_php_optarg);
! 1101: break;
! 1102:
! 1103: case 'v': /* show php version & quit */
! 1104: if (php_request_startup(TSRMLS_C)==FAILURE) {
! 1105: zend_ini_deactivate(TSRMLS_C);
! 1106: php_module_shutdown(TSRMLS_C);
! 1107: sapi_shutdown();
! 1108: tsrm_shutdown();
! 1109:
! 1110: exit(1);
! 1111: }
! 1112: SG(headers_sent) = 1;
! 1113: SG(request_info).no_headers = 1;
! 1114: #if SUHOSIN_PATCH
! 1115: php_printf("PHP %s with Suhosin-Patch (%s) (built: %s %s)\nCopyright (c) 1997-2012 The PHP Group\n%s", PHP_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version());
! 1116: #else
! 1117: php_printf("PHP %s (%s) (built: %s %s)\nCopyright (c) 1997-2012 The PHP Group\n%s", PHP_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version());
! 1118: #endif
! 1119: php_end_ob_buffers(1 TSRMLS_CC);
! 1120: exit(1);
! 1121: break;
! 1122:
! 1123: case 'V': /* verbose */
! 1124: flag_debug = atoi(ap_php_optarg);
! 1125: break;
! 1126:
! 1127: case 'z': /* load extension file */
! 1128: zend_load_extension(ap_php_optarg);
! 1129: break;
! 1130:
! 1131: default:
! 1132: break;
! 1133: }
! 1134: }
! 1135:
! 1136: if (param_error) {
! 1137: SG(headers_sent) = 1;
! 1138: SG(request_info).no_headers = 1;
! 1139: PUTS(param_error);
! 1140: exit(1);
! 1141: }
! 1142:
! 1143: CG(interactive) = interactive;
! 1144:
! 1145: /* only set script_file if not set already and not in direct mode and not at end of parameter list */
! 1146: if (argc > ap_php_optind && !filename) {
! 1147: filename=argv[ap_php_optind];
! 1148: ap_php_optind++;
! 1149: }
! 1150:
! 1151: /* check if file exists, exit else */
! 1152:
! 1153: if (dofork) {
! 1154: switch(fork()) {
! 1155: case -1: /* Uh-oh, we have a problem forking. */
! 1156: fprintf(stderr, "Uh-oh, couldn't fork!\n");
! 1157: exit(errno);
! 1158: break;
! 1159: case 0: /* Child */
! 1160: break;
! 1161: default: /* Parent */
! 1162: exit(0);
! 1163: }
! 1164: }
! 1165:
! 1166: if (sock) {
! 1167: struct stat junk;
! 1168: if (stat(sock,&junk) == 0) unlink(sock);
! 1169: }
! 1170:
! 1171: openlog("php-milter", LOG_PID, LOG_MAIL);
! 1172:
! 1173: if ((exit_status = mlfi_init())) {
! 1174: syslog(1, "mlfi_init failed.");
! 1175: closelog();
! 1176: goto err;
! 1177: }
! 1178:
! 1179: smfi_setconn(sock);
! 1180: if (smfi_register(smfilter) == MI_FAILURE) {
! 1181: syslog(1, "smfi_register failed.");
! 1182: fprintf(stderr, "smfi_register failed\n");
! 1183: closelog();
! 1184: goto err;
! 1185: } else {
! 1186: exit_status = smfi_main();
! 1187: }
! 1188:
! 1189: closelog();
! 1190:
! 1191: if (milter_sapi_module.php_ini_path_override) {
! 1192: free(milter_sapi_module.php_ini_path_override);
! 1193: }
! 1194:
! 1195: } zend_catch {
! 1196: exit_status = EG(exit_status);
! 1197: } zend_end_try();
! 1198:
! 1199: err:
! 1200: php_module_shutdown(TSRMLS_C);
! 1201: sapi_shutdown();
! 1202: tsrm_shutdown();
! 1203:
! 1204: exit(exit_status);
! 1205: }
! 1206: /* }}} */
! 1207:
! 1208: /*
! 1209: * Local variables:
! 1210: * tab-width: 4
! 1211: * c-basic-offset: 4
! 1212: * End:
! 1213: * vim600: sw=4 ts=4 fdm=marker
! 1214: * vim<600: sw=4 ts=4
! 1215: */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>