/* +----------------------------------------------------------------------+ | PHP version 4.0 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2001 The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to version 2.02 of the PHP license, | | that is bundled with this package in the file LICENSE, and is | | available at through the world-wide-web at | | http://www.php.net/license/2_02.txt. | | If you did not receive a copy of the PHP license and are unable to | | obtain it through the world-wide-web, please send a note to | | license@php.net so we can mail you a copy immediately. | +----------------------------------------------------------------------+ | Author: Sam Ruby (rubys@us.ibm.com) | +----------------------------------------------------------------------+ */ #include #include "php.h" #include "php_globals.h" #include "SAPI.h" #include #include "php.h" #ifdef PHP_WIN32 #include "win32/time.h" #include "win32/signal.h" #include #else #include "build-defs.h" #endif #if HAVE_SYS_TIME_H #include #endif #if HAVE_UNISTD_H #include #endif #if HAVE_SIGNAL_H #include #endif #if HAVE_SETLOCALE #include #endif #include "zend.h" #include "php_ini.h" #include "php_globals.h" #include "php_main.h" #include "fopen_wrappers.h" #include "ext/standard/php_standard.h" #include "ext/standard/php_dir.h" #ifdef PHP_WIN32 #include #include #include "win32/php_registry.h" #endif #include "zend_compile.h" #include "zend_execute.h" #include "zend_highlight.h" #include "zend_indent.h" JNIEXPORT void JNICALL Java_net_php_reflect_setEnv (JNIEnv *newJenv, jclass self); typedef struct { JNIEnv *jenv; jobject servlet; char *cookies; } servlet_request; extern zend_module_entry java_module_entry; static zend_module_entry *additional_php_extensions[] = { &java_module_entry }; #define EXTCOUNT (sizeof(additional_php_extensions)/sizeof(zend_module_entry *)) /***************************************************************************/ /* * JNI convenience utilities */ #define SETSTRING(target, source) \ { const char *UTFString; \ if (source) { \ UTFString = (*jenv)->GetStringUTFChars(jenv, source, 0); \ target = estrdup(UTFString); \ (*jenv)->ReleaseStringUTFChars(jenv, source, UTFString); \ } else { \ target = 0; \ } } #define FREESTRING(target) \ { if (target) { efree(target); target=0; } } void ThrowIOException (JNIEnv *jenv, char *msg) { jclass iox = (*jenv)->FindClass (jenv, "java/io/IOException"); (*jenv)->ThrowNew (jenv, iox, (msg?msg:"null") ); } void ThrowServletException (JNIEnv *jenv, char *msg) { jclass sx = (*jenv)->FindClass (jenv, "javax/servlet/ServletException"); (*jenv)->ThrowNew (jenv, sx, msg); } /***************************************************************************/ /* * sapi callbacks */ static int sapi_servlet_ub_write(const char *str, uint str_length) { TSRMLS_FETCH(); if (!SG(server_context)) { fprintf(stderr, str); return 0; } { JNIEnv *jenv = ((servlet_request*)SG(server_context))->jenv; jobject servlet = ((servlet_request*)SG(server_context))->servlet; jclass servletClass = (*jenv)->GetObjectClass(jenv, servlet); jmethodID write = (*jenv)->GetMethodID(jenv, servletClass, "write", "(Ljava/lang/String;)V"); char *copy = malloc(str_length+1); jstring arg; memcpy(copy, str, str_length); copy[str_length] = 0; arg=(*jenv)->NewStringUTF(jenv, copy); free(copy); (*jenv)->CallVoidMethod(jenv, servlet, write, arg); (*jenv)->DeleteLocalRef(jenv, arg); return str_length; } } static void sapi_servlet_send_header(sapi_header_struct *sapi_header, void *server_context) { TSRMLS_FETCH(); if (!sapi_header) return; if (!SG(server_context)) return; { JNIEnv *jenv = ((servlet_request*)SG(server_context))->jenv; jobject servlet = ((servlet_request*)SG(server_context))->servlet; jclass servletClass = (*jenv)->GetObjectClass(jenv, servlet); jmethodID header = (*jenv)->GetMethodID(jenv, servletClass, "header", "(Ljava/lang/String;)V"); jstring arg=(*jenv)->NewStringUTF(jenv, sapi_header->header); (*jenv)->CallVoidMethod(jenv, servlet, header, arg); (*jenv)->DeleteLocalRef(jenv, arg); } } static int sapi_servlet_read_post(char *buffer, uint count_bytes TSRMLS_DC) { if (count_bytes == 0) { return 0; } else { JNIEnv *jenv = ((servlet_request*)SG(server_context))->jenv; jobject servlet = ((servlet_request*)SG(server_context))->servlet; jclass servletClass = (*jenv)->GetObjectClass(jenv, servlet); jmethodID readPost = (*jenv)->GetMethodID(jenv, servletClass, "readPost", "(I)Ljava/lang/String;"); jstring post = (*jenv)->CallObjectMethod(jenv, servlet, readPost, count_bytes); const char *postAsUTF = (*jenv)->GetStringUTFChars(jenv, post, 0); uint read_bytes=(*jenv)->GetStringLength(jenv, post); if (read_bytes>count_bytes) read_bytes=count_bytes; memcpy(buffer, postAsUTF, read_bytes); if (read_bytesReleaseStringUTFChars(jenv, post, postAsUTF); return read_bytes; } } static char *sapi_servlet_read_cookies(TSRMLS_D) { JNIEnv *jenv = ((servlet_request*)SG(server_context))->jenv; jobject servlet = ((servlet_request*)SG(server_context))->servlet; jclass servletClass = (*jenv)->GetObjectClass(jenv, servlet); jmethodID readCookies = (*jenv)->GetMethodID(jenv, servletClass, "readCookies", "()Ljava/lang/String;"); jstring cookies = (*jenv)->CallObjectMethod(jenv, servlet, readCookies); SETSTRING( ((servlet_request*)SG(server_context))->cookies, cookies); return ((servlet_request*)SG(server_context))->cookies; } /***************************************************************************/ /* * sapi maintenance */ static sapi_module_struct servlet_sapi_module = { "java_servlet", /* name */ "Java Servlet", /* pretty name */ php_module_startup, /* startup */ php_module_shutdown_wrapper, /* shutdown */ NULL, /* activate */ NULL, /* deactivate */ sapi_servlet_ub_write, /* unbuffered write */ NULL, /* flush */ NULL, /* get uid */ NULL, /* getenv */ php_error, /* error handler */ NULL, /* header handler */ NULL, /* send headers handler */ sapi_servlet_send_header, /* send header handler */ sapi_servlet_read_post, /* read POST data */ sapi_servlet_read_cookies, /* read Cookies */ NULL, /* register server variables */ NULL, /* Log message */ NULL, /* Block interruptions */ NULL, /* Unblock interruptions */ STANDARD_SAPI_MODULE_PROPERTIES }; JNIEXPORT void JNICALL Java_net_php_servlet_startup (JNIEnv *jenv, jobject self) { #ifdef ZTS tsrm_startup(1, 1, 0, NULL); #endif sapi_startup(&servlet_sapi_module); if (php_module_startup(&servlet_sapi_module)==FAILURE) { ThrowServletException(jenv,"module startup failure"); return; } if (php_startup_extensions(additional_php_extensions, EXTCOUNT)==FAILURE) { ThrowServletException(jenv,"extension startup failure"); return; } } JNIEXPORT void JNICALL Java_net_php_servlet_shutdown (JNIEnv *jenv, jobject self) { php_module_shutdown(); #ifdef ZTS tsrm_shutdown(); #endif return; } /***************************************************************************/ /* * define a Java object to PHP */ JNIEXPORT jlong JNICALL Java_net_php_servlet_define (JNIEnv *jenv, jobject self, jstring name) { pval *pzval; jlong addr = 0; const char *nameAsUTF = (*jenv)->GetStringUTFChars(jenv, name, 0); TSRMLS_FETCH(); MAKE_STD_ZVAL(pzval); addr = (jlong)(long) pzval; zend_hash_add(&EG(symbol_table), (char*)nameAsUTF, strlen(nameAsUTF)+1, &pzval, sizeof(pval *), NULL); (*jenv)->ReleaseStringUTFChars(jenv, name, nameAsUTF); return addr; } /* * execute a script */ JNIEXPORT void JNICALL Java_net_php_servlet_send (JNIEnv *jenv, jobject self, jstring requestMethod, jstring queryString, jstring requestURI, jstring pathTranslated, jstring contentType, jint contentLength, jstring authUser, jboolean display_source_mode) { zend_file_handle file_handle; int retval; #ifndef VIRTUAL_DIR char cwd[MAXPATHLEN]; #endif TSRMLS_FETCH(); TSRMLS_FETCH(); TSRMLS_FETCH(); zend_try { SG(server_context) = emalloc(sizeof(servlet_request)); ((servlet_request*)SG(server_context))->jenv=jenv; ((servlet_request*)SG(server_context))->servlet=self; ((servlet_request*)SG(server_context))->cookies=0; CG(extended_info) = 0; /* * Initialize the request */ SETSTRING( SG(request_info).auth_user, authUser ); SETSTRING( SG(request_info).request_method, requestMethod ); SETSTRING( SG(request_info).query_string, queryString ); SETSTRING( SG(request_info).request_uri, requestURI ); SETSTRING( SG(request_info).content_type, contentType ); SG(sapi_headers).http_response_code = 200; SG(request_info).content_length = contentLength; SG(request_info).auth_password = NULL; if (php_request_startup(TSRMLS_C)==FAILURE) { ThrowServletException(jenv,"request startup failure"); return; } /* * Parse the file */ SETSTRING( SG(request_info).path_translated, pathTranslated ); #ifdef VIRTUAL_DIR retval = php_fopen_primary_script(&file_handle); #else /* * The java runtime doesn't like the working directory to be * changed, so save it and change it back as quickly as possible * in the hopes that Java doesn't notice. */ getcwd(cwd,MAXPATHLEN); retval = php_fopen_primary_script(&file_handle); chdir(cwd); #endif if (retval == FAILURE) { php_request_shutdown((void *) 0); php_module_shutdown(); ThrowIOException(jenv,file_handle.filename); return; } /* * Execute the request */ Java_net_php_reflect_setEnv(jenv, 0); if (display_source_mode) { zend_syntax_highlighter_ini syntax_highlighter_ini; if (open_file_for_scanning(&file_handle TSRMLS_CC)==SUCCESS) { php_get_highlight_struct(&syntax_highlighter_ini); sapi_send_headers(); zend_highlight(&syntax_highlighter_ini); } } else { php_execute_script(&file_handle TSRMLS_CC); php_header(); /* Make sure headers have been sent */ } /* * Clean up */ FREESTRING(SG(request_info).request_method); FREESTRING(SG(request_info).query_string); FREESTRING(SG(request_info).request_uri); FREESTRING(SG(request_info).path_translated); FREESTRING(SG(request_info).content_type); FREESTRING(((servlet_request*)SG(server_context))->cookies); efree(SG(server_context)); SG(server_context)=0; if (!display_source_mode) php_request_shutdown((void *) 0); } zend_catch { ThrowServletException(jenv,"bailout"); } zend_end_try(); }