php-src/sapi/servlet/servlet.c
Zeev Suraski 030b707296 Update SAPI modules to interface with the new TSRM.
Enable thread-safety memory debugging in ISAPI when in debug mode
2000-11-18 02:44:04 +00:00

429 lines
11 KiB
C

/*
+----------------------------------------------------------------------+
| PHP version 4.0 |
+----------------------------------------------------------------------+
| Copyright (c) 1997, 1998, 1999, 2000 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 <jni.h>
#include "php.h"
#include "php_globals.h"
#include "SAPI.h"
#include <stdio.h>
#include "php.h"
#ifdef PHP_WIN32
#include "win32/time.h"
#include "win32/signal.h"
#include <process.h>
#else
#include "build-defs.h"
#endif
#if HAVE_SYS_TIME_H
#include <sys/time.h>
#endif
#if HAVE_UNISTD_H
#include <unistd.h>
#endif
#if HAVE_SIGNAL_H
#include <signal.h>
#endif
#if HAVE_SETLOCALE
#include <locale.h>
#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 <io.h>
#include <fcntl.h>
#include "win32/syslog.h"
#include "win32/php_registry.h"
#else
#include <syslog.h>
#endif
#include "zend_compile.h"
#include "zend_execute.h"
#include "zend_highlight.h"
#include "zend_indent.h"
PHPAPI extern char *php_ini_path;
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)
{
SLS_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)
{
SLS_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 SLS_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_bytes<count_bytes) buffer[read_bytes]=0;
(*jenv)->ReleaseStringUTFChars(jenv, post, postAsUTF);
return read_bytes;
}
}
static char *sapi_servlet_read_cookies(SLS_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 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);
#else
if (setjmp(EG(bailout))!=0) {
ThrowServletException(jenv,"bailout");
return;
}
#endif
sapi_startup(&sapi_module);
if (php_module_startup(&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();
php_global_shutdown_extensions(additional_php_extensions, EXTCOUNT);
#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);
ELS_FETCH();
MAKE_STD_ZVAL(pzval);
(pval*)(long)addr = 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;
#ifndef VIRTUAL_DIR
char cwd[MAXPATHLEN+1];
#endif
SLS_FETCH();
PLS_FETCH();
CLS_FETCH();
ELS_FETCH();
#ifdef ZTS
if (setjmp(EG(bailout))!=0) {
ThrowServletException(jenv,"bailout");
return;
}
#endif
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(CLS_C ELS_CC PLS_CC SLS_CC)==FAILURE) {
ThrowServletException(jenv,"request startup failure");
return;
}
/*
* Parse the file
*/
SETSTRING( SG(request_info).path_translated, pathTranslated );
#ifdef VIRTUAL_DIR
file_handle.handle.fp = php_fopen_primary_script();
#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);
file_handle.handle.fp = php_fopen_primary_script();
chdir(cwd);
#endif
file_handle.filename = SG(request_info).path_translated;
file_handle.opened_path = NULL;
file_handle.free_filename = 0;
file_handle.type = ZEND_HANDLE_FP;
if (!file_handle.handle.fp) {
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 CLS_CC)==SUCCESS) {
php_get_highlight_struct(&syntax_highlighter_ini);
sapi_send_headers();
zend_highlight(&syntax_highlighter_ini);
}
} else {
php_execute_script(&file_handle CLS_CC ELS_CC PLS_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);
}