Annotation of embedaddon/php/sapi/milter/php_milter.c, revision 1.1.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>