This source file includes following definitions.
- ZEND_BEGIN_MODULE_GLOBALS
- mlfi_connect
- mlfi_helo
- mlfi_envfrom
- mlfi_envrcpt
- mlfi_header
- mlfi_eoh
- mlfi_body
- mlfi_eom
- mlfi_abort
- mlfi_close
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_MINIT_FUNCTION
- PHP_MINFO_FUNCTION
- sapi_milter_ub_write
- sapi_milter_flush
- sapi_milter_register_variables
- sapi_milter_post_read
- sapi_milter_read_cookies
- sapi_milter_send_headers
- php_milter_startup
- php_milter_usage
- define_command_line_ini_entry
- main
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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
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
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
108
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
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
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
149 INIT_ZVAL(function_name);
150
151 ZVAL_STRING(&function_name, "milter_init", 0);
152
153
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
172
173
174
175
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
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
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
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
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
240
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
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
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
275
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
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
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
315
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
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
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
356
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
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
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
396
397
398 static sfsistat mlfi_eoh(SMFICTX *ctx)
399 {
400 zval function_name, retval;
401 int status;
402 TSRMLS_FETCH();
403
404
405 INIT_ZVAL(function_name);
406 ZVAL_STRING(&function_name, "milter_eoh", 0);
407
408
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
425
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
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);
441
442
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
461
462
463 static sfsistat mlfi_eom(SMFICTX *ctx)
464 {
465 zval function_name, retval;
466 int status;
467 TSRMLS_FETCH();
468
469
470 INIT_ZVAL(function_name);
471 ZVAL_STRING(&function_name, "milter_eom", 0);
472
473
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
490
491
492 static sfsistat mlfi_abort(SMFICTX *ctx)
493 {
494 zval function_name, retval;
495 int status;
496 TSRMLS_FETCH();
497
498
499 INIT_ZVAL(function_name);
500 ZVAL_STRING(&function_name, "milter_abort", 0);
501
502
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
519
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 if (!SG(sapi_started) && SUCCESS != php_request_startup(TSRMLS_C)) {
529 return ret;
530 }
531
532
533 INIT_ZVAL(function_name);
534 ZVAL_STRING(&function_name, "milter_close", 0);
535
536
537 MG(ctx) = ctx;
538 MG(state) = MLFI_CLOSE;
539
540 status = call_user_function(CG(function_table), NULL, &function_name, &retval, 0, NULL TSRMLS_CC);
541
542 MG(state) = MLFI_NONE;
543
544 if (status == SUCCESS && Z_TYPE(retval) == IS_LONG) {
545 ret = Z_LVAL(retval);
546 }
547
548 php_request_shutdown((void *) 0);
549
550 return ret;
551 }
552
553
554
555
556
557 static struct smfiDesc smfilter = {
558 "php-milter",
559 SMFI_VERSION,
560 0,
561 mlfi_connect,
562 mlfi_helo,
563 mlfi_envfrom,
564 mlfi_envrcpt,
565 mlfi_header,
566 mlfi_eoh,
567 mlfi_body,
568 mlfi_eom,
569 mlfi_abort,
570 mlfi_close,
571 };
572
573
574
575
576
577
578
579 PHP_FUNCTION(smfi_setflags)
580 {
581 long flags;
582
583
584 if (MG(state) != MLFI_INIT) {
585 php_error(E_WARNING, NOT_INIT, get_active_function_name(TSRMLS_C));
586 } else if (zend_parse_parameters(1 TSRMLS_CC, "l", &flags) == SUCCESS) {
587 flags = flags & (SMFIF_ADDHDRS|SMFIF_CHGHDRS|SMFIF_CHGBODY|SMFIF_ADDRCPT|SMFIF_DELRCPT);
588 smfilter.xxfi_flags = flags;
589 }
590 }
591
592
593
594
595 PHP_FUNCTION(smfi_settimeout)
596 {
597 long timeout;
598
599
600 if (MG(state) != MLFI_INIT) {
601 php_error(E_WARNING, NOT_INIT, get_active_function_name(TSRMLS_C));
602 } else if (zend_parse_parameters(1 TSRMLS_CC, "l", &timeout) == SUCCESS) {
603 smfi_settimeout(timeout);
604 }
605 }
606
607
608
609
610 PHP_FUNCTION(smfi_getsymval)
611 {
612 char *symname, *ret;
613 int len;
614
615
616 if (MG(state) == MLFI_NONE) {
617 php_error(E_WARNING, IS_NONE, get_active_function_name(TSRMLS_C));
618 } else if (zend_parse_parameters(1 TSRMLS_CC, "s", &symname, &len) == SUCCESS) {
619 if ((ret = smfi_getsymval(MG(ctx), symname)) != NULL) {
620 RETURN_STRING(ret, 1);
621 }
622 }
623
624 RETURN_NULL();
625 }
626
627
628
629
630
631 PHP_FUNCTION(smfi_setreply)
632 {
633 char *rcode, *xcode, *message;
634 int len;
635
636
637 if (MG(state) == MLFI_NONE) {
638 php_error(E_WARNING, IS_NONE, get_active_function_name(TSRMLS_C));
639 } else if (zend_parse_parameters(3 TSRMLS_CC, "sss", &rcode, &len, &xcode, &len, &message, &len) == SUCCESS) {
640 if (smfi_setreply(MG(ctx), rcode, xcode, message) == MI_SUCCESS) {
641 RETURN_TRUE;
642 }
643 }
644
645 RETURN_FALSE;
646 }
647
648
649
650
651 PHP_FUNCTION(smfi_addheader)
652 {
653 char *f, *v;
654 int len;
655
656
657 if (MG(state) != MLFI_EOM) {
658 php_error(E_WARNING, NOT_EOM, get_active_function_name(TSRMLS_C));
659 } else if (zend_parse_parameters(2 TSRMLS_CC, "ss", &f, &len, &v, &len) == SUCCESS) {
660 if (smfi_addheader(MG(ctx), f, v) == MI_SUCCESS) {
661 RETURN_TRUE;
662 }
663 }
664
665 RETURN_FALSE;
666 }
667
668
669
670
671 PHP_FUNCTION(smfi_chgheader)
672 {
673 char *f, *v;
674 long idx;
675 int len;
676
677
678 if (MG(state) != MLFI_EOM) {
679 php_error(E_WARNING, NOT_EOM, get_active_function_name(TSRMLS_C));
680 } else if (zend_parse_parameters(3 TSRMLS_CC, "sls", &f, &len, &idx, &v, &len) == SUCCESS) {
681 if (smfi_chgheader(MG(ctx), f, idx, v) == MI_SUCCESS) {
682 RETURN_TRUE;
683 }
684 }
685
686 RETURN_FALSE;
687 }
688
689
690
691
692 PHP_FUNCTION(smfi_addrcpt)
693 {
694 char *rcpt;
695 int len;
696
697
698 if (MG(state) != MLFI_EOM) {
699 php_error(E_WARNING, NOT_EOM, get_active_function_name(TSRMLS_C));
700 } else if (zend_parse_parameters(1 TSRMLS_CC, "s", &rcpt, &len) == SUCCESS) {
701 if (smfi_addrcpt(MG(ctx), rcpt) == MI_SUCCESS) {
702 RETURN_TRUE;
703 }
704 }
705
706 RETURN_FALSE;
707 }
708
709
710
711
712 PHP_FUNCTION(smfi_delrcpt)
713 {
714 char *rcpt;
715 int len;
716
717
718 if (MG(state) != MLFI_EOM) {
719 php_error(E_WARNING, NOT_EOM, get_active_function_name(TSRMLS_C));
720 } else if (zend_parse_parameters(1 TSRMLS_CC, "s", &rcpt, &len) == SUCCESS) {
721 if (smfi_delrcpt(MG(ctx), rcpt) == MI_SUCCESS) {
722 RETURN_TRUE;
723 }
724 }
725
726 RETURN_FALSE;
727 }
728
729
730
731
732
733 PHP_FUNCTION(smfi_replacebody)
734 {
735 char *body;
736 int len;
737
738
739 if (MG(state) != MLFI_EOM) {
740 php_error(E_WARNING, NOT_EOM, get_active_function_name(TSRMLS_C));
741 } else if (zend_parse_parameters(1 TSRMLS_CC, "s", &body, &len) == SUCCESS) {
742 if (smfi_replacebody(MG(ctx), (u_char*)body, len) == MI_SUCCESS) {
743 RETURN_TRUE;
744 }
745 }
746
747 RETURN_FALSE;
748 }
749
750
751
752
753 PHP_MINIT_FUNCTION(milter)
754 {
755 REGISTER_LONG_CONSTANT("SMFIS_CONTINUE", SMFIS_CONTINUE, CONST_CS | CONST_PERSISTENT);
756 REGISTER_LONG_CONSTANT("SMFIS_REJECT", SMFIS_REJECT, CONST_CS | CONST_PERSISTENT);
757 REGISTER_LONG_CONSTANT("SMFIS_DISCARD", SMFIS_DISCARD, CONST_CS | CONST_PERSISTENT);
758 REGISTER_LONG_CONSTANT("SMFIS_ACCEPT", SMFIS_ACCEPT, CONST_CS | CONST_PERSISTENT);
759 REGISTER_LONG_CONSTANT("SMFIS_TEMPFAIL", SMFIS_TEMPFAIL, CONST_CS | CONST_PERSISTENT);
760
761 REGISTER_LONG_CONSTANT("SMFIF_ADDHDRS", SMFIF_ADDHDRS, CONST_CS | CONST_PERSISTENT);
762 REGISTER_LONG_CONSTANT("SMFIF_CHGHDRS", SMFIF_CHGHDRS, CONST_CS | CONST_PERSISTENT);
763 REGISTER_LONG_CONSTANT("SMFIF_CHGBODY", SMFIF_CHGBODY, CONST_CS | CONST_PERSISTENT);
764 REGISTER_LONG_CONSTANT("SMFIF_ADDRCPT", SMFIF_ADDRCPT, CONST_CS | CONST_PERSISTENT);
765 REGISTER_LONG_CONSTANT("SMFIF_DELRCPT", SMFIF_DELRCPT, CONST_CS | CONST_PERSISTENT);
766
767 ZEND_INIT_MODULE_GLOBALS(milter, NULL, NULL);
768
769 MG(state) = MLFI_NONE;
770 MG(initialized) = 0;
771 return SUCCESS;
772 }
773
774
775
776
777 PHP_MINFO_FUNCTION(milter)
778 {
779 php_info_print_table_start();
780 php_info_print_table_header(2, "Milter support", "enabled");
781 php_info_print_table_end();
782 }
783
784
785
786
787 ZEND_BEGIN_ARG_INFO_EX(arginfo_smfi_setflags, 0, 0, 1)
788 ZEND_ARG_INFO(0, flags)
789 ZEND_END_ARG_INFO()
790
791 ZEND_BEGIN_ARG_INFO_EX(arginfo_smfi_settimeout, 0, 0, 1)
792 ZEND_ARG_INFO(0, timeout)
793 ZEND_END_ARG_INFO()
794
795 ZEND_BEGIN_ARG_INFO_EX(arginfo_smfi_getsymval, 0, 0, 1)
796 ZEND_ARG_INFO(0, macro)
797 ZEND_END_ARG_INFO()
798
799 ZEND_BEGIN_ARG_INFO_EX(arginfo_smfi_setreply, 0, 0, 3)
800 ZEND_ARG_INFO(0, rcode)
801 ZEND_ARG_INFO(0, xcode)
802 ZEND_ARG_INFO(0, message)
803 ZEND_END_ARG_INFO()
804
805 ZEND_BEGIN_ARG_INFO_EX(arginfo_smfi_addheader, 0, 0, 2)
806 ZEND_ARG_INFO(0, headerf)
807 ZEND_ARG_INFO(0, headerv)
808 ZEND_END_ARG_INFO()
809
810 ZEND_BEGIN_ARG_INFO_EX(arginfo_smfi_chgheader, 0, 0, 2)
811 ZEND_ARG_INFO(0, headerf)
812 ZEND_ARG_INFO(0, headerv)
813 ZEND_END_ARG_INFO()
814
815 ZEND_BEGIN_ARG_INFO_EX(arginfo_smfi_addrcpt, 0, 0, 1)
816 ZEND_ARG_INFO(0, rcpt)
817 ZEND_END_ARG_INFO()
818
819 ZEND_BEGIN_ARG_INFO_EX(arginfo_smfi_delrcpt, 0, 0, 1)
820 ZEND_ARG_INFO(0, rcpt)
821 ZEND_END_ARG_INFO()
822
823 ZEND_BEGIN_ARG_INFO_EX(arginfo_smfi_replacebody, 0, 0, 1)
824 ZEND_ARG_INFO(0, body)
825 ZEND_END_ARG_INFO()
826
827
828
829
830 const static zend_function_entry milter_functions[] = {
831 PHP_FE(smfi_setflags, arginfo_smfi_setflags)
832 PHP_FE(smfi_settimeout, arginfo_smfi_settimeout)
833 PHP_FE(smfi_getsymval, arginfo_smfi_getsymval)
834 PHP_FE(smfi_setreply, arginfo_smfi_setreply)
835 PHP_FE(smfi_addheader, arginfo_smfi_addheader)
836 PHP_FE(smfi_chgheader, arginfo_smfi_chgheader)
837 PHP_FE(smfi_addrcpt, arginfo_smfi_addrcpt)
838 PHP_FE(smfi_delrcpt, arginfo_smfi_delrcpt)
839 PHP_FE(smfi_replacebody, arginfo_smfi_replacebody)
840 PHP_FE_END
841 };
842
843
844
845
846 static zend_module_entry php_milter_module = {
847 STANDARD_MODULE_HEADER,
848 "Milter",
849 milter_functions,
850 PHP_MINIT(milter),
851 NULL,
852 NULL,
853 NULL,
854 PHP_MINFO(milter),
855 "0.1.0",
856 STANDARD_MODULE_PROPERTIES
857 };
858
859
860
861
862 static int sapi_milter_ub_write(const char *str, uint str_length TSRMLS_DC)
863 {
864 return str_length;
865 }
866
867 static void sapi_milter_flush(void *server_context)
868 {
869 }
870
871 static void sapi_milter_register_variables(zval *track_vars_array TSRMLS_DC)
872 {
873 php_register_variable ("SERVER_SOFTWARE", "Sendmail Milter", track_vars_array TSRMLS_CC);
874 }
875
876 static int sapi_milter_post_read(char *buf, uint count_bytes TSRMLS_DC)
877 {
878 return 0;
879 }
880
881 static char* sapi_milter_read_cookies(TSRMLS_D)
882 {
883 return NULL;
884 }
885
886 static int sapi_milter_send_headers(sapi_headers_struct *sapi_headers TSRMLS_DC)
887 {
888 return SAPI_HEADER_SENT_SUCCESSFULLY;
889 }
890
891 static int php_milter_startup(sapi_module_struct *sapi_module)
892 {
893 if (php_module_startup(sapi_module, &php_milter_module, 1) == FAILURE) {
894 return FAILURE;
895 }
896 return SUCCESS;
897 }
898
899
900
901
902 static sapi_module_struct milter_sapi_module = {
903 "milter",
904 "Sendmail Milter SAPI",
905
906 php_milter_startup,
907 php_module_shutdown_wrapper,
908
909 NULL,
910 NULL,
911
912 sapi_milter_ub_write,
913 sapi_milter_flush,
914 NULL,
915 NULL,
916
917 php_error,
918
919 NULL,
920 sapi_milter_send_headers,
921 NULL,
922
923 sapi_milter_post_read,
924 sapi_milter_read_cookies,
925
926 sapi_milter_register_variables,
927 NULL,
928 NULL,
929 NULL,
930
931 NULL,
932 NULL,
933
934 STANDARD_SAPI_MODULE_PROPERTIES
935 };
936
937
938
939
940
941
942
943
944 static void php_milter_usage(char *argv0)
945 {
946 char *prog;
947
948 prog = strrchr(argv0, '/');
949 if (prog) {
950 prog++;
951 } else {
952 prog = "php-milter";
953 }
954
955 printf( "Usage: %s [options] [-f] <file> [args...]\n"
956 " %s [options] [-- args...]\n"
957 " -a Run interactively\n"
958 " -c <path>|<file> Look for php.ini file in this directory\n"
959 " -n No php.ini file will be used\n"
960 " -d foo[=bar] Define INI entry foo with value 'bar'\n"
961 " -D run as daemon\n"
962 " -e Generate extended information for debugger/profiler\n"
963 " -f <file> Parse <file>.\n"
964 " -h This help\n"
965 " -p <socket> path to create socket\n"
966 " -v Version number\n"
967 " -V <n> set debug level to n (1 or 2).\n"
968 " -z <file> Load Zend extension <file>.\n"
969 " args... Arguments passed to script. Use -- args when first argument \n"
970 " starts with - or script is read from stdin\n"
971 , prog, prog);
972 }
973
974
975 static void define_command_line_ini_entry(char *arg)
976 {
977 char *name, *value;
978
979 name = arg;
980 value = strchr(arg, '=');
981 if (value) {
982 *value = 0;
983 value++;
984 } else {
985 value = "1";
986 }
987 zend_alter_ini_entry(name, strlen(name)+1, value, strlen(value), PHP_INI_SYSTEM, PHP_INI_STAGE_ACTIVATE);
988 }
989
990
991
992
993 int main(int argc, char *argv[])
994 {
995 char *sock = NULL;
996 int dofork = 0;
997
998 int exit_status = SUCCESS;
999 int c;
1000
1001 int orig_optind=ap_php_optind;
1002 char *orig_optarg=ap_php_optarg;
1003 int interactive=0;
1004 char *param_error=NULL;
1005
1006
1007 void ***tsrm_ls;
1008
1009 #ifdef HAVE_SIGNAL_H
1010 #if defined(SIGPIPE) && defined(SIG_IGN)
1011 signal(SIGPIPE, SIG_IGN);
1012
1013
1014
1015
1016
1017 #endif
1018 #endif
1019
1020
1021 tsrm_startup(1, 1, 0, NULL);
1022 tsrm_ls = ts_resource(0);
1023 sapi_startup(&milter_sapi_module);
1024
1025 while ((c=ap_php_getopt(argc, argv, OPTSTRING))!=-1) {
1026 switch (c) {
1027 case 'c':
1028 milter_sapi_module.php_ini_path_override = strdup(ap_php_optarg);
1029 break;
1030 case 'n':
1031 milter_sapi_module.php_ini_ignore = 1;
1032 break;
1033 }
1034 }
1035 ap_php_optind = orig_optind;
1036 ap_php_optarg = orig_optarg;
1037
1038 milter_sapi_module.executable_location = argv[0];
1039
1040
1041 sapi_module.startup(&milter_sapi_module);
1042
1043 zend_first_try {
1044 while ((c=ap_php_getopt(argc, argv, OPTSTRING))!=-1) {
1045 switch (c) {
1046 case '?':
1047 php_output_tearup();
1048 SG(headers_sent) = 1;
1049 php_milter_usage(argv[0]);
1050 php_output_teardown();
1051 exit(1);
1052 break;
1053 }
1054 }
1055 ap_php_optind = orig_optind;
1056 ap_php_optarg = orig_optarg;
1057
1058
1059 SG(options) |= SAPI_OPTION_NO_CHDIR;
1060 zend_alter_ini_entry("html_errors", 12, "0", 1, PHP_INI_SYSTEM, PHP_INI_STAGE_ACTIVATE);
1061 zend_alter_ini_entry("max_execution_time", 19, "0", 1, PHP_INI_SYSTEM, PHP_INI_STAGE_ACTIVATE);
1062
1063 zend_uv.html_errors = 0;
1064
1065 while ((c = ap_php_getopt(argc, argv, OPTSTRING)) != -1) {
1066 switch (c) {
1067
1068 case 'a':
1069 printf("Interactive mode enabled\n\n");
1070 interactive=1;
1071 break;
1072
1073 case 'C':
1074
1075 break;
1076 case 'd':
1077 define_command_line_ini_entry(ap_php_optarg);
1078 break;
1079
1080 case 'D':
1081 dofork = 1;
1082 break;
1083
1084 case 'e':
1085 CG(compiler_options) |= ZEND_COMPILE_EXTENDED_INFO;
1086 break;
1087
1088 case 'f':
1089 filename = ap_php_optarg;
1090 break;
1091
1092 case 'h':
1093 case '?':
1094 php_output_tearup();
1095 SG(headers_sent) = 1;
1096 php_milter_usage(argv[0]);
1097 php_output_teardown();
1098 exit(1);
1099 break;
1100
1101 case 'p':
1102 sock = strdup(ap_php_optarg);
1103 break;
1104
1105 case 'v':
1106 if (php_request_startup(TSRMLS_C)==FAILURE) {
1107 zend_ini_deactivate(TSRMLS_C);
1108 php_module_shutdown(TSRMLS_C);
1109 sapi_shutdown();
1110 tsrm_shutdown();
1111
1112 exit(1);
1113 }
1114 SG(headers_sent) = 1;
1115 SG(request_info).no_headers = 1;
1116 php_printf("PHP %s (%s) (built: %s %s)\nCopyright (c) 1997-2016 The PHP Group\n%s", PHP_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version());
1117 php_output_teardown();
1118 exit(1);
1119 break;
1120
1121 case 'V':
1122 flag_debug = atoi(ap_php_optarg);
1123 break;
1124
1125 case 'z':
1126 zend_load_extension(ap_php_optarg);
1127 break;
1128
1129 default:
1130 break;
1131 }
1132 }
1133
1134 if (param_error) {
1135 SG(headers_sent) = 1;
1136 SG(request_info).no_headers = 1;
1137 PUTS(param_error);
1138 exit(1);
1139 }
1140
1141 CG(interactive) = interactive;
1142
1143
1144 if (argc > ap_php_optind && !filename) {
1145 filename=argv[ap_php_optind];
1146 ap_php_optind++;
1147 }
1148
1149
1150
1151 if (dofork) {
1152 switch(fork()) {
1153 case -1:
1154 fprintf(stderr, "Uh-oh, couldn't fork!\n");
1155 exit(errno);
1156 break;
1157 case 0:
1158 break;
1159 default:
1160 exit(0);
1161 }
1162 }
1163
1164 if (sock) {
1165 struct stat junk;
1166 if (stat(sock,&junk) == 0) unlink(sock);
1167 }
1168
1169 openlog("php-milter", LOG_PID, LOG_MAIL);
1170
1171 if ((exit_status = mlfi_init())) {
1172 syslog(1, "mlfi_init failed.");
1173 closelog();
1174 goto err;
1175 }
1176
1177 smfi_setconn(sock);
1178 if (smfi_register(smfilter) == MI_FAILURE) {
1179 syslog(1, "smfi_register failed.");
1180 fprintf(stderr, "smfi_register failed\n");
1181 closelog();
1182 goto err;
1183 } else {
1184 exit_status = smfi_main();
1185 }
1186
1187 closelog();
1188
1189 if (milter_sapi_module.php_ini_path_override) {
1190 free(milter_sapi_module.php_ini_path_override);
1191 }
1192
1193 } zend_catch {
1194 exit_status = EG(exit_status);
1195 } zend_end_try();
1196
1197 err:
1198 php_module_shutdown(TSRMLS_C);
1199 sapi_shutdown();
1200 tsrm_shutdown();
1201
1202 exit(exit_status);
1203 }
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213