mirror of
https://github.com/php/php-src.git
synced 2024-12-01 13:54:10 +08:00
030b707296
Enable thread-safety memory debugging in ISAPI when in debug mode
429 lines
11 KiB
C
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);
|
|
}
|
|
|