1/*
2   +----------------------------------------------------------------------+
3   | PHP Version 5                                                        |
4   +----------------------------------------------------------------------+
5   | Copyright (c) 1997-2014 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 at 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: George Wang <gwang@litespeedtech.com>                        |
16   +----------------------------------------------------------------------+
17*/
18
19/* $Id$ */
20
21#include "php.h"
22#include "SAPI.h"
23#include "php_main.h"
24#include "php_ini.h"
25#include "php_variables.h"
26#include "zend_highlight.h"
27#include "zend.h"
28
29#include "lsapilib.h"
30
31#include <stdio.h>
32
33#if HAVE_STDLIB_H
34#include <stdlib.h>
35#endif
36
37#if HAVE_UNISTD_H
38#include <unistd.h>
39#endif
40
41#ifdef PHP_WIN32
42
43#include <io.h>
44#include <fcntl.h>
45#include "win32/php_registry.h"
46
47#else
48
49#include <sys/wait.h>
50
51#endif
52
53#include <sys/stat.h>
54
55#if HAVE_SYS_TYPES_H
56
57#include <sys/types.h>
58
59#endif
60
61#if HAVE_SIGNAL_H
62
63#include <signal.h>
64
65#endif
66
67#include <sys/socket.h>
68#include <arpa/inet.h>
69#include <netinet/in.h>
70
71
72#define SAPI_LSAPI_MAX_HEADER_LENGTH 2048
73
74static int  lsapi_mode       = 1;
75static char *php_self        = "";
76static char *script_filename = "";
77static int  source_highlight = 0;
78
79#ifdef ZTS
80zend_compiler_globals    *compiler_globals;
81zend_executor_globals    *executor_globals;
82php_core_globals         *core_globals;
83sapi_globals_struct      *sapi_globals;
84void ***tsrm_ls;
85#endif
86
87zend_module_entry litespeed_module_entry;
88
89/* {{{ php_lsapi_startup
90 */
91static int php_lsapi_startup(sapi_module_struct *sapi_module)
92{
93    if (php_module_startup(sapi_module, NULL, 0)==FAILURE) {
94        return FAILURE;
95    }
96    return SUCCESS;
97}
98/* }}} */
99
100
101
102/* {{{ sapi_lsapi_ub_write
103 */
104static int sapi_lsapi_ub_write(const char *str, uint str_length TSRMLS_DC)
105{
106    int ret;
107    int remain;
108    if ( lsapi_mode ) {
109        ret  = LSAPI_Write( str, str_length );
110        if ( ret < str_length ) {
111            php_handle_aborted_connection();
112            return str_length - ret;
113        }
114    } else {
115        remain = str_length;
116        while( remain > 0 ) {
117            ret = write( 1, str, remain );
118            if ( ret <= 0 ) {
119                php_handle_aborted_connection();
120                return str_length - remain;
121            }
122            str += ret;
123            remain -= ret;
124        }
125    }
126    return str_length;
127}
128/* }}} */
129
130
131/* {{{ sapi_lsapi_flush
132 */
133static void sapi_lsapi_flush( void * server_context )
134{
135    if ( lsapi_mode ) {
136        if ( LSAPI_Flush() == -1) {
137            php_handle_aborted_connection();
138        }
139    }
140}
141/* }}} */
142
143
144/* {{{ sapi_lsapi_deactivate
145 */
146static int sapi_lsapi_deactivate(TSRMLS_D)
147{
148    LSAPI_Finish();
149    return SUCCESS;
150}
151/* }}} */
152
153
154
155
156/* {{{ sapi_lsapi_getenv
157 */
158static char *sapi_lsapi_getenv( char * name, size_t name_len TSRMLS_DC )
159{
160    if ( lsapi_mode ) {
161        return LSAPI_GetEnv( name );
162    } else {
163        return getenv( name );
164    }
165}
166/* }}} */
167
168
169
170static int add_variable( const char * pKey, int keyLen, const char * pValue, int valLen,
171                         void * arg )
172{
173    php_register_variable_safe((char *)pKey, (char *)pValue, valLen, (zval *)arg TSRMLS_CC);
174    return 1;
175}
176
177
178
179/* {{{ sapi_lsapi_register_variables
180 */
181static void sapi_lsapi_register_variables(zval *track_vars_array TSRMLS_DC)
182{
183
184    if ( lsapi_mode ) {
185        LSAPI_ForeachHeader( add_variable, track_vars_array );
186        LSAPI_ForeachEnv( add_variable, track_vars_array );
187        php_import_environment_variables(track_vars_array TSRMLS_CC);
188
189        php_register_variable("PHP_SELF", (SG(request_info).request_uri ? SG(request_info).request_uri:""), track_vars_array TSRMLS_CC);
190    } else {
191        php_import_environment_variables(track_vars_array TSRMLS_CC);
192
193        php_register_variable("PHP_SELF", php_self, track_vars_array TSRMLS_CC);
194        php_register_variable("SCRIPT_NAME", php_self, track_vars_array TSRMLS_CC);
195        php_register_variable("SCRIPT_FILENAME", script_filename, track_vars_array TSRMLS_CC);
196        php_register_variable("PATH_TRANSLATED", script_filename, track_vars_array TSRMLS_CC);
197        php_register_variable("DOCUMENT_ROOT", "", track_vars_array TSRMLS_CC);
198
199    }
200}
201/* }}} */
202
203
204/* {{{ sapi_lsapi_read_post
205 */
206static int sapi_lsapi_read_post(char *buffer, uint count_bytes TSRMLS_DC)
207{
208    if ( lsapi_mode ) {
209        return LSAPI_ReadReqBody( buffer, count_bytes );
210    } else {
211        return 0;
212    }
213}
214/* }}} */
215
216
217
218
219/* {{{ sapi_lsapi_read_cookies
220 */
221static char *sapi_lsapi_read_cookies(TSRMLS_D)
222{
223    if ( lsapi_mode ) {
224        return LSAPI_GetHeader( H_COOKIE );
225    } else {
226        return NULL;
227    }
228}
229/* }}} */
230
231
232/* {{{ sapi_lsapi_send_headers
233 */
234static int sapi_lsapi_send_headers(sapi_headers_struct *sapi_headers TSRMLS_DC)
235{
236    sapi_header_struct  *h;
237    zend_llist_position pos;
238    if ( lsapi_mode ) {
239        LSAPI_SetRespStatus( SG(sapi_headers).http_response_code );
240
241        h = zend_llist_get_first_ex(&sapi_headers->headers, &pos);
242        while (h) {
243            if ( h->header_len > 0 ) {
244                LSAPI_AppendRespHeader(h->header, h->header_len);
245            }
246            h = zend_llist_get_next_ex(&sapi_headers->headers, &pos);
247        }
248        if (SG(sapi_headers).send_default_content_type) {
249            char    *hd;
250            int  len;
251            char    headerBuf[SAPI_LSAPI_MAX_HEADER_LENGTH];
252
253            hd = sapi_get_default_content_type(TSRMLS_C);
254            len = snprintf( headerBuf, SAPI_LSAPI_MAX_HEADER_LENGTH - 1,
255                            "Content-type: %s", hd );
256            efree(hd);
257
258            LSAPI_AppendRespHeader( headerBuf, len );
259        }
260    }
261    LSAPI_FinalizeRespHeaders();
262    return SAPI_HEADER_SENT_SUCCESSFULLY;
263
264
265}
266/* }}} */
267
268
269/* {{{ sapi_lsapi_send_headers
270 */
271static void sapi_lsapi_log_message(char *message TSRMLS_DC)
272{
273    int len = strlen( message );
274    LSAPI_Write_Stderr( message, len);
275}
276/* }}} */
277
278
279/* {{{ sapi_module_struct cgi_sapi_module
280 */
281static sapi_module_struct lsapi_sapi_module =
282{
283    "litespeed",
284    "LiteSpeed",
285
286    php_lsapi_startup,              /* startup */
287    php_module_shutdown_wrapper,    /* shutdown */
288
289    NULL,                           /* activate */
290    sapi_lsapi_deactivate,          /* deactivate */
291
292    sapi_lsapi_ub_write,            /* unbuffered write */
293    sapi_lsapi_flush,               /* flush */
294    NULL,                           /* get uid */
295    sapi_lsapi_getenv,              /* getenv */
296
297    php_error,                      /* error handler */
298
299    NULL,                           /* header handler */
300    sapi_lsapi_send_headers,        /* send headers handler */
301    NULL,                           /* send header handler */
302
303    sapi_lsapi_read_post,           /* read POST data */
304    sapi_lsapi_read_cookies,        /* read Cookies */
305
306    sapi_lsapi_register_variables,  /* register server variables */
307    sapi_lsapi_log_message,         /* Log message */
308
309    NULL,                           /* php.ini path override */
310    NULL,                           /* block interruptions */
311    NULL,                           /* unblock interruptions */
312    NULL,                           /* default post reader */
313    NULL,                           /* treat data */
314    NULL,                           /* executable location */
315
316    0,                              /* php.ini ignore */
317
318    STANDARD_SAPI_MODULE_PROPERTIES
319
320};
321/* }}} */
322
323static int init_request_info( TSRMLS_D )
324{
325    char * pContentType = LSAPI_GetHeader( H_CONTENT_TYPE );
326    char * pAuth;
327
328    SG(request_info).content_type = pContentType ? pContentType : "";
329    SG(request_info).request_method = LSAPI_GetRequestMethod();
330    SG(request_info).query_string = LSAPI_GetQueryString();
331    SG(request_info).request_uri = LSAPI_GetScriptName();
332    SG(request_info).content_length = LSAPI_GetReqBodyLen();
333    SG(request_info).path_translated = LSAPI_GetScriptFileName();
334
335    /* It is not reset by zend engine, set it to 0. */
336    SG(sapi_headers).http_response_code = 0;
337
338    pAuth = LSAPI_GetHeader( H_AUTHORIZATION );
339    php_handle_auth_data(pAuth TSRMLS_CC);
340}
341
342static int lsapi_module_main(int show_source TSRMLS_DC)
343{
344    zend_file_handle file_handle = {0};
345
346    if (php_request_startup(TSRMLS_C) == FAILURE ) {
347        return -1;
348    }
349    if (show_source) {
350        zend_syntax_highlighter_ini syntax_highlighter_ini;
351
352        php_get_highlight_struct(&syntax_highlighter_ini);
353        highlight_file(SG(request_info).path_translated, &syntax_highlighter_ini TSRMLS_CC);
354    } else {
355        file_handle.type = ZEND_HANDLE_FILENAME;
356        file_handle.handle.fd = 0;
357        file_handle.filename = SG(request_info).path_translated;
358        file_handle.free_filename = 0;
359        file_handle.opened_path = NULL;
360
361        php_execute_script(&file_handle TSRMLS_CC);
362    }
363    zend_try {
364        php_request_shutdown(NULL);
365    } zend_end_try();
366    return 0;
367}
368
369
370static int alter_ini( const char * pKey, int keyLen, const char * pValue, int valLen,
371                void * arg )
372{
373    int type = ZEND_INI_PERDIR;
374    if ( '\001' == *pKey ) {
375        ++pKey;
376        if ( *pKey == 4 ) {
377            type = ZEND_INI_SYSTEM;
378        }
379        ++pKey;
380        --keyLen;
381        zend_alter_ini_entry((char *)pKey, keyLen,
382                             (char *)pValue, valLen,
383                             type, PHP_INI_STAGE_ACTIVATE);
384    }
385    return 1;
386}
387
388
389static void override_ini()
390{
391
392    LSAPI_ForeachSpecialEnv( alter_ini, NULL );
393
394}
395
396static int processReq( TSRMLS_D )
397{
398    int ret = 0;
399    zend_first_try {
400        /* avoid server_context==NULL checks */
401        SG(server_context) = (void *) 1;
402
403        init_request_info( TSRMLS_C );
404
405        override_ini();
406
407        if ( lsapi_module_main( source_highlight TSRMLS_CC ) == -1 ) {
408            ret = -1;
409        }
410    } zend_end_try();
411    return ret;
412}
413
414static void cli_usage( TSRMLS_D )
415{
416    static const char * usage =
417        "Usage: php\n"
418        "      php -[b|c|h|i|q|s|v|?] [<file>] [args...]\n"
419        "  Run in LSAPI mode, only '-b', '-s' and '-c' are effective\n"
420        "  Run in Command Line Interpreter mode when parameters are specified\n"
421        "\n"
422        "  -b <address:port>|<port> Bind Path for external LSAPI Server mode\n"
423        "  -c <path>|<file> Look for php.ini file in this directory\n"
424        "  -h    This help\n"
425        "  -i    PHP information\n"
426        "  -q    Quiet-mode.  Suppress HTTP Header output.\n"
427        "  -s    Display colour syntax highlighted source.\n"
428        "  -v    Version number\n"
429        "  -?    This help\n"
430        "\n"
431        "  args...  Arguments passed to script.\n";
432    php_output_startup();
433    php_output_activate(TSRMLS_C);
434    php_printf( "%s", usage );
435#ifdef PHP_OUTPUT_NEWAPI
436    php_output_end_all(TSRMLS_C);
437#else
438    php_end_ob_buffers(1 TSRMLS_CC);
439#endif
440}
441
442static int parse_opt( int argc, char * argv[], int *climode,
443                        char **php_ini_path, char ** php_bind )
444{
445    char ** p = &argv[1];
446    char ** argend= &argv[argc];
447    int c;
448    while (( p < argend )&&(**p == '-' )) {
449        c = *((*p)+1);
450        ++p;
451        switch( c ) {
452        case 'b':
453            if ( p >= argend ) {
454                fprintf( stderr, "TCP or socket address must be specified following '-b' option.\n");
455                return -1;
456            }
457            *php_bind = *p++;
458            break;
459
460        case 'c':
461            if ( p >= argend ) {
462                fprintf( stderr, "<path> or <file> must be specified following '-c' option.\n");
463
464                return -1;
465            }
466            *php_ini_path = *p++;
467            break;
468        case 's':
469            source_highlight = 1;
470            break;
471        case 'h':
472        case 'i':
473        case 'q':
474        case 'v':
475        case '?':
476        default:
477            *climode = 1;
478            break;
479        }
480    }
481    if ( p - argv < argc ) {
482        *climode = 1;
483    }
484    return 0;
485}
486
487static int cli_main( int argc, char * argv[] )
488{
489
490    static const char * ini_defaults[] = {
491        "report_zend_debug",    "0",
492        "display_errors",       "1",
493        "register_argc_argv",   "1",
494        "html_errors",          "0",
495        "implicit_flush",       "1",
496        "output_buffering",     "0",
497        "max_execution_time",   "0",
498        "max_input_time",       "-1",
499        NULL
500    };
501
502    const char ** ini;
503    char ** p = &argv[1];
504    char ** argend= &argv[argc];
505    int ret = 0;
506    int c;
507    lsapi_mode = 0;        /* enter CLI mode */
508
509#ifdef PHP_WIN32
510    _fmode = _O_BINARY;         /*sets default for file streams to binary */
511    setmode(_fileno(stdin), O_BINARY);    /* make the stdio mode be binary */
512    setmode(_fileno(stdout), O_BINARY);   /* make the stdio mode be binary */
513    setmode(_fileno(stderr), O_BINARY);   /* make the stdio mode be binary */
514#endif
515
516    zend_first_try  {
517        SG(server_context) = (void *) 1;
518
519        zend_uv.html_errors = 0; /* tell the engine we're in non-html mode */
520        CG(in_compilation) = 0; /* not initialized but needed for several options */
521        EG(uninitialized_zval_ptr) = NULL;
522
523        for( ini = ini_defaults; *ini; ini+=2 ) {
524            zend_alter_ini_entry( (char *)*ini, strlen( *ini )+1,
525                                (char *)*(ini+1), strlen( *(ini+1) ),
526                                PHP_INI_SYSTEM, PHP_INI_STAGE_ACTIVATE);
527        }
528
529        while (( p < argend )&&(**p == '-' )) {
530            c = *((*p)+1);
531            ++p;
532            switch( c ) {
533            case 'q':
534                break;
535            case 'i':
536                if (php_request_startup(TSRMLS_C) != FAILURE) {
537                    php_print_info(0xFFFFFFFF TSRMLS_CC);
538#ifdef PHP_OUTPUT_NEWAPI
539                    php_output_end_all(TSRMLS_C);
540#else
541                    php_end_ob_buffers(1 TSRMLS_CC);
542#endif
543                    php_request_shutdown( NULL );
544                }
545                ret = 1;
546                break;
547            case 'v':
548                if (php_request_startup(TSRMLS_C) != FAILURE) {
549#if ZEND_DEBUG
550                    php_printf("PHP %s (%s) (built: %s %s) (DEBUG)\nCopyright (c) 1997-2014 The PHP Group\n%s", PHP_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version());
551#else
552                    php_printf("PHP %s (%s) (built: %s %s)\nCopyright (c) 1997-2014 The PHP Group\n%s", PHP_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version());
553#endif
554#ifdef PHP_OUTPUT_NEWAPI
555                    php_output_end_all(TSRMLS_C);
556#else
557                    php_end_ob_buffers(1 TSRMLS_CC);
558#endif
559                    php_request_shutdown( NULL );
560                }
561                ret = 1;
562                break;
563            case 'c':
564                ++p;
565            /* fall through */
566            case 's':
567                break;
568
569            case 'h':
570            case '?':
571            default:
572                cli_usage(TSRMLS_C);
573                ret = 1;
574                break;
575
576            }
577        }
578        if ( !ret ) {
579            if ( *p ) {
580                zend_file_handle file_handle = {0};
581
582                file_handle.type = ZEND_HANDLE_FP;
583                file_handle.handle.fp = VCWD_FOPEN(*p, "rb");
584
585                if ( file_handle.handle.fp ) {
586                    script_filename = *p;
587                    php_self = *p;
588
589                    SG(request_info).path_translated = *p;
590                    SG(request_info).argc = argc - (p - argv);
591                    SG(request_info).argv = p;
592
593                    if (php_request_startup(TSRMLS_C) == FAILURE ) {
594                        fclose( file_handle.handle.fp );
595                        ret = 2;
596                    } else {
597                        if (source_highlight) {
598                            zend_syntax_highlighter_ini syntax_highlighter_ini;
599
600                            php_get_highlight_struct(&syntax_highlighter_ini);
601                            highlight_file(SG(request_info).path_translated, &syntax_highlighter_ini TSRMLS_CC);
602                        } else {
603                            file_handle.filename = *p;
604                            file_handle.free_filename = 0;
605                            file_handle.opened_path = NULL;
606
607                            php_execute_script(&file_handle TSRMLS_CC);
608                        }
609
610                        php_request_shutdown( NULL );
611                    }
612                } else {
613                    php_printf("Could not open input file: %s.\n", *p);
614                }
615            } else {
616                cli_usage(TSRMLS_C);
617            }
618        }
619
620    }zend_end_try();
621
622    php_module_shutdown(TSRMLS_C);
623
624#ifdef ZTS
625    tsrm_shutdown();
626#endif
627    return ret;
628}
629
630static int s_stop;
631void litespeed_cleanup(int signal)
632{
633    s_stop = signal;
634}
635
636
637void start_children( int children )
638{
639    struct sigaction act, old_term, old_quit, old_int, old_usr1;
640    int running = 0;
641    int status;
642    pid_t pid;
643
644    /* Create a process group */
645    setsid();
646
647    /* Set up handler to kill children upon exit */
648    act.sa_flags = 0;
649    act.sa_handler = litespeed_cleanup;
650    if( sigaction( SIGTERM, &act, &old_term ) ||
651        sigaction( SIGINT,  &act, &old_int  ) ||
652        sigaction( SIGUSR1, &act, &old_usr1 ) ||
653        sigaction( SIGQUIT, &act, &old_quit )) {
654        perror( "Can't set signals" );
655        exit( 1 );
656    }
657    s_stop = 0;
658    while( 1 ) {
659        while((!s_stop )&&( running < children )) {
660            pid = fork();
661            switch( pid ) {
662            case 0: /* children process */
663
664                /* don't catch our signals */
665                sigaction( SIGTERM, &old_term, 0 );
666                sigaction( SIGQUIT, &old_quit, 0 );
667                sigaction( SIGINT,  &old_int,  0 );
668                sigaction( SIGUSR1, &old_usr1, 0 );
669                return ;
670            case -1:
671                perror( "php (pre-forking)" );
672                exit( 1 );
673                break;
674            default: /* parent process */
675                running++;
676                break;
677            }
678        }
679        if ( s_stop ) {
680            break;
681        }
682        pid = wait( &status );
683        running--;
684    }
685    kill( -getpgrp(), SIGUSR1 );
686    exit( 0 );
687}
688
689
690
691#include <fcntl.h>
692int main( int argc, char * argv[] )
693{
694    int ret;
695    int bindFd;
696
697    char * php_ini_path = NULL;
698    char * php_bind  = NULL;
699    char * p;
700    int n;
701    int climode = 0;
702
703#ifdef HAVE_SIGNAL_H
704#if defined(SIGPIPE) && defined(SIG_IGN)
705    signal(SIGPIPE, SIG_IGN);
706#endif
707#endif
708
709#ifdef ZTS
710    tsrm_startup(1, 1, 0, NULL);
711#endif
712
713    if (argc > 1 ) {
714        if ( parse_opt( argc, argv, &climode,
715                &php_ini_path, &php_bind ) == -1 ) {
716            return 1;
717        }
718    }
719    if ( climode ) {
720        lsapi_sapi_module.phpinfo_as_text = 1;
721    }
722    sapi_startup(&lsapi_sapi_module);
723
724#ifdef ZTS
725    compiler_globals = ts_resource(compiler_globals_id);
726    executor_globals = ts_resource(executor_globals_id);
727    core_globals = ts_resource(core_globals_id);
728    sapi_globals = ts_resource(sapi_globals_id);
729    tsrm_ls = ts_resource(0);
730
731    SG(request_info).path_translated = NULL;
732#endif
733
734    lsapi_sapi_module.executable_location = argv[0];
735
736    if ( php_ini_path ) {
737        lsapi_sapi_module.php_ini_path_override = php_ini_path;
738    }
739
740    if (php_module_startup(&lsapi_sapi_module, &litespeed_module_entry, 1) == FAILURE) {
741#ifdef ZTS
742        tsrm_shutdown();
743#endif
744        return FAILURE;
745    }
746
747    if ( climode ) {
748        return cli_main(argc, argv);
749    }
750
751
752    if ( php_bind ) {
753        bindFd = LSAPI_CreateListenSock( php_bind, 10 );
754        if ( bindFd == -1 ) {
755            fprintf( stderr,
756                     "Failed to bind socket [%s]: %s\n", php_bind, strerror( errno ) );
757            exit( 2 );
758        }
759        if ( bindFd != 0 ) {
760            dup2( bindFd, 0 );
761            close( bindFd );
762        }
763    }
764
765    LSAPI_Init();
766
767    LSAPI_Init_Env_Parameters( NULL );
768
769    if ( php_bind ) {
770        LSAPI_No_Check_ppid();
771    }
772
773    while( LSAPI_Prefork_Accept_r( &g_req ) >= 0 ) {
774        ret = processReq(TSRMLS_C);
775        LSAPI_Finish();
776        if ( ret ) {
777            break;
778        }
779    }
780    php_module_shutdown(TSRMLS_C);
781
782#ifdef ZTS
783    tsrm_shutdown();
784#endif
785    return ret;
786}
787
788
789/*   LiteSpeed PHP module starts here */
790
791/* {{{ arginfo */
792ZEND_BEGIN_ARG_INFO(arginfo_litespeed__void, 0)
793ZEND_END_ARG_INFO()
794/* }}} */
795
796PHP_FUNCTION(litespeed_request_headers);
797PHP_FUNCTION(litespeed_response_headers);
798
799PHP_MINFO_FUNCTION(litespeed);
800
801zend_function_entry litespeed_functions[] = {
802    PHP_FE(litespeed_request_headers,   arginfo_litespeed__void)
803    PHP_FE(litespeed_response_headers,  arginfo_litespeed__void)
804    PHP_FALIAS(getallheaders,           litespeed_request_headers,  arginfo_litespeed__void)
805    PHP_FALIAS(apache_request_headers,  litespeed_request_headers,  arginfo_litespeed__void)
806    PHP_FALIAS(apache_response_headers, litespeed_response_headers, arginfo_litespeed__void)
807    {NULL, NULL, NULL}
808};
809
810static PHP_MINIT_FUNCTION(litespeed)
811{
812    /* REGISTER_INI_ENTRIES(); */
813    return SUCCESS;
814}
815
816
817static PHP_MSHUTDOWN_FUNCTION(litespeed)
818{
819    /* UNREGISTER_INI_ENTRIES(); */
820    return SUCCESS;
821}
822
823zend_module_entry litespeed_module_entry = {
824    STANDARD_MODULE_HEADER,
825    "litespeed",
826    litespeed_functions,
827    PHP_MINIT(litespeed),
828    PHP_MSHUTDOWN(litespeed),
829    NULL,
830    NULL,
831    NULL,
832    NO_VERSION_YET,
833    STANDARD_MODULE_PROPERTIES
834};
835
836static int add_associate_array( const char * pKey, int keyLen, const char * pValue, int valLen,
837                         void * arg )
838{
839    add_assoc_string_ex( (zval *)arg, (char *)pKey, keyLen+1, (char *)pValue, 1 );
840    return 1;
841}
842
843
844/* {{{ proto array litespeed_request_headers(void)
845   Fetch all HTTP request headers */
846PHP_FUNCTION(litespeed_request_headers)
847{
848    /* TODO: */
849    if (ZEND_NUM_ARGS() > 0) {
850        WRONG_PARAM_COUNT;
851    }
852    array_init(return_value);
853
854    LSAPI_ForeachOrgHeader( add_associate_array, return_value );
855
856}
857/* }}} */
858
859
860
861/* {{{ proto array litespeed_response_headers(void)
862   Fetch all HTTP response headers */
863PHP_FUNCTION(litespeed_response_headers)
864{
865    sapi_header_struct  *h;
866    zend_llist_position pos;
867    char *     p;
868    int       len;
869    char         headerBuf[SAPI_LSAPI_MAX_HEADER_LENGTH];
870
871    if (ZEND_NUM_ARGS() > 0) {
872        WRONG_PARAM_COUNT;
873    }
874
875    if (!&SG(sapi_headers).headers) {
876        RETURN_FALSE;
877    }
878    array_init(return_value);
879
880    h = zend_llist_get_first_ex(&SG(sapi_headers).headers, &pos);
881    while (h) {
882        if ( h->header_len > 0 ) {
883            p = strchr( h->header, ':' );
884            len = p - h->header;
885            if (( p )&&( len > 0 )) {
886                memmove( headerBuf, h->header, len );
887                while( len > 0 && (isspace( headerBuf[len-1])) ) {
888                    --len;
889                }
890                headerBuf[len] = 0;
891                if ( len ) {
892                    while( isspace(*++p));
893                    add_assoc_string_ex(return_value, headerBuf, len+1, p, 1 );
894                }
895            }
896        }
897        h = zend_llist_get_next_ex(&SG(sapi_headers).headers, &pos);
898    }
899}
900
901/* }}} */
902
903
904/*
905 * Local variables:
906 * tab-width: 4
907 * c-basic-offset: 4
908 * End:
909 * vim600: sw=4 ts=4 fdm=marker
910 * vim<600: sw=4 ts=4
911 */
912
913
914