0x000000ff php,beast.c · liexusong/php-beast - Gitee.com

/*

+----------------------------------------------------------------------+

| PHP Version 5 |

+----------------------------------------------------------------------+

| Copyright (c) 1997-2007 The PHP Group |

+----------------------------------------------------------------------+

| This source file is subject to version 3.01 of the PHP license, |

| that is bundled with this package in the file LICENSE, and is |

| available through the world-wide-web at the following url: |

| http://www.php.net/license/3_01.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: Liexusong |

| maben |

+----------------------------------------------------------------------+

*/

/* $Id: header,v 1.16.2.1.2.1 2007/01/01 19:32:09 iliaa Exp $ */

#ifdef HAVE_CONFIG_H

#include "config.h"

#endif

#include

#include

#include

#include

#include

typedef struct yy_buffer_state *YY_BUFFER_STATE;

#include "zend.h"

#include "zend_operators.h"

#include "zend_globals.h"

#include "zend_language_scanner.h"

#include "zend_API.h"

#include "zend_compile.h"

#include "php.h"

#include "php_main.h"

#include "php_globals.h"

#include "php_ini.h"

#include "main/SAPI.h"

#include "ext/standard/info.h"

#include "ext/date/php_date.h"

#include "php_streams.h"

#include "php_beast.h"

#include "beast_mm.h"

#include "cache.h"

#include "beast_log.h"

#include "beast_module.h"

#include "file_handler.h"

#ifdef PHP_WIN32

#include

#include

#pragma comment(lib, PHP_LIB)

#pragma comment(lib, "Iphlpapi.lib")

#else

#include

#include

#include

#endif

#if ZEND_MODULE_API_NO >= 20151012

# define BEAST_RETURN_STRING(str, dup) RETURN_STRING(str)

#else

# define BEAST_RETURN_STRING(str, dup) RETURN_STRING(str, dup)

#endif

#define BEAST_VERSION "2.7"

#define DEFAULT_CACHE_SIZE 10485760 /* 10MB */

#define HEADER_MAX_SIZE 256

#define INT_SIZE (sizeof(int))

extern struct beast_ops *ops_handler_list[];

/*

* Global vaiables for extension

*/

char *beast_log_file = NULL;

char *beast_log_user = NULL;

int log_level = beast_log_notice;

int beast_ncpu = 1;

int beast_is_root = 0;

int beast_pid = -1;

/* True global resources - no need for thread safety here */

static zend_op_array* (*old_compile_file)(zend_file_handle*, int TSRMLS_DC);

static int le_beast;

static int max_cache_size = DEFAULT_CACHE_SIZE;

static int beast_enable = 1;

static int beast_max_filesize = 0;

static char *local_networkcard = NULL;

static int beast_now_time = 0;

static int log_normal_file = 0;

static char *beast_debug_path = NULL;

static int beast_debug_mode = 0;

/* {{{ beast_functions[]

*

* Every user visible function must have an entry in beast_functions[].

*/

zend_function_entry beast_functions[] = {

PHP_FE(beast_encode_file, NULL)

PHP_FE(beast_avail_cache, NULL)

PHP_FE(beast_support_filesize, NULL)

PHP_FE(beast_file_expire, NULL)

PHP_FE(beast_clean_cache, NULL)

{NULL, NULL, NULL} /* Must be the last line in beast_functions[] */

};

/* }}} */

/* {{{ beast_module_entry

*/

zend_module_entry beast_module_entry = {

#if ZEND_MODULE_API_NO >= 20010901

STANDARD_MODULE_HEADER,

#endif

"beast",

beast_functions,

PHP_MINIT(beast),

PHP_MSHUTDOWN(beast),

PHP_RINIT(beast),

PHP_RSHUTDOWN(beast),

PHP_MINFO(beast),

#if ZEND_MODULE_API_NO >= 20010901

BEAST_VERSION, /* Replace with version number for your extension */

#endif

STANDARD_MODULE_PROPERTIES

};

/* }}} */

#ifdef COMPILE_DL_BEAST

ZEND_GET_MODULE(beast)

#endif

extern struct file_handler tmpfile_handler;

extern struct file_handler pipe_handler;

static struct file_handler *default_file_handler = NULL;

static struct file_handler *file_handlers[] = {

&tmpfile_handler,

#ifndef PHP_WIN32

&pipe_handler,

#endif

NULL

};

extern char encrypt_file_header_sign[];

extern int encrypt_file_header_length;

extern char *file_handler_switch;

#define swab32(x) \

((x & 0x000000FF) << 24 | (x & 0x0000FF00) << 8 | \

(x & 0x00FF0000) >> 8 | (x & 0xFF000000) >> 24)

#define little_endian() (!big_endian())

static int big_endian()

{

unsigned short num = 0x1122;

if(*((unsigned char *)&num) == 0x11) {

return 1;

}

return 0;

}

int filter_code_comments(char *filename, zval *retval TSRMLS_DC)

{

zend_lex_state original_lex_state;

zend_file_handle file_handle = {0};

#if PHP_API_VERSION > 20090626

php_output_start_default(TSRMLS_C);

file_handle.type = ZEND_HANDLE_FILENAME;

file_handle.filename = filename;

file_handle.free_filename = 0;

file_handle.opened_path = NULL;

zend_save_lexical_state(&original_lex_state TSRMLS_CC);

if (open_file_for_scanning(&file_handle TSRMLS_CC) == FAILURE) {

zend_restore_lexical_state(&original_lex_state TSRMLS_CC);

php_output_end(TSRMLS_C);

return -1;

}

zend_strip(TSRMLS_C);

zend_destroy_file_handle(&file_handle TSRMLS_CC);

zend_restore_lexical_state(&original_lex_state TSRMLS_CC);

php_output_get_contents(retval TSRMLS_CC);

php_output_discard(TSRMLS_C);

#else

file_handle.type = ZEND_HANDLE_FILENAME;

file_handle.filename = filename;

file_handle.free_filename = 0;

file_handle.opened_path = NULL;

zend_save_lexical_state(&original_lex_state TSRMLS_CC);

if (open_file_for_scanning(&file_handle TSRMLS_CC) == FAILURE) {

zend_restore_lexical_state(&original_lex_state TSRMLS_CC);

return -1;

}

php_start_ob_buffer(NULL, 0, 1 TSRMLS_CC);

zend_strip(TSRMLS_C);

zend_destroy_file_handle(&file_handle TSRMLS_CC);

zend_restore_lexical_state(&original_lex_state TSRMLS_CC);

php_ob_get_buffer(retval TSRMLS_CC);

php_end_ob_buffer(0, 0 TSRMLS_CC);

#endif

return 0;

}

struct beast_ops *beast_get_encrypt_algo(int type)

{

int index = type - 1;

if (index < 0 || index >= BEAST_ENCRYPT_TYPE_ERROR) {

return ops_handler_list[0];

}

return ops_handler_list[index];

}

/*****************************************************************************

* *

* Encrypt a plain text file and output a cipher file *

* *

*****************************************************************************/

int encrypt_file(const char *inputfile,

const char *outputfile, int expire,

int encrypt_type TSRMLS_DC)

{

php_stream *output_stream = NULL;

zval codes;

int need_free_code = 0;

char *inbuf, *outbuf;

int inlen, outlen, dumplen, expireval, dumptype;

struct beast_ops *encrypt_ops = beast_get_encrypt_algo(encrypt_type);

/* Get php codes from script file */

if (filter_code_comments((char *)inputfile, &codes TSRMLS_CC) == -1) {

php_error_docref(NULL TSRMLS_CC, E_ERROR,

"Unable get codes from php file `%s'", inputfile);

return -1;

}

need_free_code = 1;

#if ZEND_MODULE_API_NO >= 20151012

inlen = Z_STRLEN(codes);

inbuf = Z_STRVAL(codes);

#else

inlen = codes.value.str.len;

inbuf = codes.value.str.val;

#endif

/* PHP file size can not large than beast_max_filesize */

if (beast_max_filesize > 0 && inlen > beast_max_filesize) {

return -1;

}

/* Open output file */

#if ZEND_MODULE_API_NO >= 20151012

output_stream = php_stream_open_wrapper((char *)outputfile, "w+",

IGNORE_URL_WIN|REPORT_ERRORS, NULL);

#else

output_stream = php_stream_open_wrapper((char *)outputfile, "w+",

ENFORCE_SAFE_MODE|REPORT_ERRORS, NULL);

#endif

if (!output_stream) {

php_error_docref(NULL TSRMLS_CC, E_ERROR,

"Unable to open file `%s'", outputfile);

goto failed;

}

/* if computer is little endian, change file size to big endian */

if (little_endian()) {

dumplen = swab32(inlen);

expireval = swab32(expire);

dumptype = swab32(encrypt_type);

} else {

dumplen = inlen;

expireval = expire;

dumptype = encrypt_type;

}

php_stream_write(output_stream,

encrypt_file_header_sign, encrypt_file_header_length);

php_stream_write(output_stream, (const char *)&dumplen, INT_SIZE);

php_stream_write(output_stream, (const char *)&expireval, INT_SIZE);

php_stream_write(output_stream, (const char *)&dumptype, INT_SIZE);

if (encrypt_ops->encrypt(inbuf, inlen, &outbuf, &outlen) == -1) {

php_error_docref(NULL TSRMLS_CC, E_ERROR,

"Unable to encrypt file `%s'", outputfile);

goto failed;

}

php_stream_write(output_stream, outbuf, outlen);

php_stream_close(output_stream);

zval_dtor(&codes);

if (encrypt_ops->free) {

encrypt_ops->free(outbuf);

}

return 0;

failed:

if (output_stream)

php_stream_close(output_stream);

if (need_free_code)

zval_dtor(&codes);

return -1;

}

/*****************************************************************************

* *

* Decrypt a cipher text file and output plain buffer *

* *

*****************************************************************************/

int decrypt_file(const char *filename, int stream,

char **retbuf, int *retlen, int *free_buffer,

struct beast_ops **ret_encrypt TSRMLS_DC)

{

struct stat stat_ssb;

cache_key_t findkey;

cache_item_t *cache;

int reallen, bodylen, expire;

char header[HEADER_MAX_SIZE];

int headerlen;

char *buffer = NULL, *decbuf;

int declen;

int entype;

struct beast_ops *encrypt_ops;

int retval = -1;

int n = 0;

int filesize = 0;

#ifdef PHP_WIN32

ULARGE_INTEGER ull;

BY_HANDLE_FILE_INFORMATION fileinfo;

HANDLE hFile = (HANDLE)_get_osfhandle(stream);

if (!GetFileInformationByHandle(hFile, &fileinfo)) {

beast_write_log(beast_log_error,

"Failed to get file information from file `%s'", filename);

retval = -1;

goto failed;

}

findkey.device = fileinfo.dwVolumeSerialNumber;

findkey.inode = fileinfo.nFileIndexHigh * (MAXDWORD + 1) + fileinfo.nFileIndexLow;

ull.LowPart = fileinfo.ftLastWriteTime.dwLowDateTime;

ull.HighPart = fileinfo.ftLastWriteTime.dwHighDateTime;

findkey.mtime = ull.QuadPart / 10000000ULL - 11644473600ULL;

filesize = fileinfo.nFileSizeHigh * (MAXDWORD + 1) + fileinfo.nFileSizeLow;

#else

if (fstat(stream, &stat_ssb) == -1) {

beast_write_log(beast_log_error,

"Failed to readed state buffer from file `%s'", filename);

retval = -1;

goto failed;

}

findkey.device = stat_ssb.st_dev;

findkey.inode = stat_ssb.st_ino;

findkey.mtime = stat_ssb.st_mtime;

filesize = stat_ssb.st_size;

#endif

/**

* 1) 1 int is dump length,

* 2) 1 int is expire time.

* 3) 1 int is encrypt type.

*/

headerlen = encrypt_file_header_length + INT_SIZE * 3;

if (filesize < headerlen) { /* This file is not a encrypt file */

retval = -1;

goto failed;

}

cache = beast_cache_find(&findkey);

if (cache != NULL) { /* Found cache */

*retbuf = beast_cache_data(cache);

*retlen = beast_cache_size(cache);

return 0;

}

*free_buffer = 0; /* Set free buffer flag to false */

/* Not found cache and decrypt file */

if ((n = read(stream, header, headerlen)) != headerlen) {

beast_write_log(beast_log_error,

"Failed to readed header from file `%s', headerlen:%d, readlen:%d",

filename, headerlen, n);

retval = -1;

goto failed;

}

/* Not a encrypted file */

if (memcmp(header,

encrypt_file_header_sign,

encrypt_file_header_length))

{

if (log_normal_file) {

beast_write_log(beast_log_error,

"File `%s' isn't a encrypted file", filename);

}

retval = -1;

goto failed;

}

/* Real php script file's size */

reallen = *((int *)&header[encrypt_file_header_length]);

expire = *((int *)&header[encrypt_file_header_length + INT_SIZE]);

entype = *((int *)&header[encrypt_file_header_length + 2 * INT_SIZE]);

if (little_endian()) {

reallen = swab32(reallen);

expire = swab32(expire);

entype = swab32(entype);

}

/* Check file size is vaild */

if (beast_max_filesize > 0 && reallen > beast_max_filesize) {

beast_write_log(beast_log_error,

"File size `%d' out of max size `%d'",

reallen, beast_max_filesize);

retval = -1;

goto failed;

}

/* Check file is not expired */

if (expire > 0 && expire < beast_now_time) {

beast_write_log(beast_log_error, "File `%s' was expired", filename);

retval = -2;

goto failed;

}

*ret_encrypt = encrypt_ops = beast_get_encrypt_algo(entype);

/**

* How many bytes would be read from encrypt file,

* subtract encrypt file's header size,

* because we had read the header yet.

*/

bodylen = filesize - headerlen;

/* 1) Alloc memory for decrypt file */

if (!(buffer = malloc(bodylen))) {

beast_write_log(beast_log_error,

"Failed to alloc memory to file `%s' size `%d'",

filename, bodylen);

retval = -1;

goto failed;

}

/* 2) Read file stream */

if (read(stream, buffer, bodylen) != bodylen) {

beast_write_log(beast_log_error,

"Failed to readed stream from file `%s'", filename);

retval = -1;

goto failed;

}

/* 3) Decrypt file stream */

if (encrypt_ops->decrypt(buffer, bodylen, &decbuf, &declen) == -1) {

beast_write_log(beast_log_error,

"Failed to decrypted file `%s', using `%s' handler",

filename, encrypt_ops->name);

retval = -1;

goto failed;

}

free(buffer); /* Buffer don't need right now and free it */

findkey.fsize = reallen; /* How many size would we alloc from cache */

/* Try to add decrypt result to cache */

if ((cache = beast_cache_create(&findkey))) {

memcpy(beast_cache_data(cache), decbuf, reallen);

cache = beast_cache_push(cache); /* Push cache into hash table */

*retbuf = beast_cache_data(cache);

*retlen = beast_cache_size(cache);

if (encrypt_ops->free) {

encrypt_ops->free(decbuf);

}

} else { /* Return raw buffer and we need free after PHP finished */

*retbuf = decbuf;

*retlen = reallen;

*free_buffer = 1;

}

return 0;

failed:

if (buffer) {

free(buffer);

}

return retval;

}

int beast_super_mkdir(char *path)

{

char *head, *last;

char temp[1024];

for (head = last = path; *last; last++) {

if (*last == '/') {

if (last > head) {

memset(temp, 0, 1024);

memcpy(temp, path, last - path);

if (access(temp, F_OK) == -1) {

if (mkdir(temp, 0777) != 0) {

beast_write_log(beast_log_error,

"Failed to make new directory `%s'",

temp);

return -1;

}

}

}

head = last + 1;

}

}

return 0;

}

/*

* CGI compile file

*/

zend_op_array *

cgi_compile_file(zend_file_handle *h, int type TSRMLS_DC)

{

#if ZEND_MODULE_API_NO >= 20151012

zend_string *opened_path;

#else

char *opened_path;

#endif

char *buf;

int fd;

FILE *fp = NULL;

int size, free_buffer = 0;

int retval;

struct beast_ops *ops = NULL;

int destroy_file_handler = 0;

#if 0

fp = zend_fopen(h->filename, &opened_path TSRMLS_CC);

#else

fp = fopen(h->filename, "rb");

#endif

if (fp != NULL) {

fd = fileno(fp);

} else {

goto final;

}

retval = decrypt_file(h->filename, fd, &buf, &size,

&free_buffer, &ops TSRMLS_CC);

if (retval == -2) {

php_error_docref(NULL TSRMLS_CC, E_ERROR,

"This program was expired, please contact administrator");

return NULL;

}

if (retval == -1) {

#if BEAST_EXECUTE_NORMAL_SCRIPT

goto final;

#else

php_error_docref(NULL TSRMLS_CC, E_ERROR,

"Not allow execute normal PHP script");

return NULL;

#endif

}

#if BEAST_DEBUG_MODE

if (beast_debug_mode && beast_debug_path) {

if (access(beast_debug_path, F_OK) == 0) {

char realpath[1024];

sprintf(realpath, "%s/%s", beast_debug_path, h->filename);

if (beast_super_mkdir(realpath) == 0) {

FILE *debug_fp = fopen(realpath, "w+");

if (debug_fp) {

fwrite(buf, size, 1, debug_fp);

fclose(debug_fp);

}

}

}

}

#endif

if (default_file_handler->open(default_file_handler) == -1 ||

default_file_handler->write(default_file_handler, buf, size) == -1 ||

default_file_handler->rewind(default_file_handler) == -1)

{

destroy_file_handler = 1;

goto final;

}

if (h->type == ZEND_HANDLE_FP) fclose(h->handle.fp);

if (h->type == ZEND_HANDLE_FD) close(h->handle.fd);

/*

* Get file handler and free context

*/

switch (default_file_handler->type) {

case BEAST_FILE_HANDLER_FP:

h->type = ZEND_HANDLE_FP;

h->handle.fp = default_file_handler->get_fp(default_file_handler);

break;

case BEAST_FILE_HANDLER_FD:

h->type = ZEND_HANDLE_FD;

h->handle.fd = default_file_handler->get_fd(default_file_handler);

break;

}

final:

if (free_buffer && ops) {

if (ops->free) {

ops->free(buf);

}

}

if (fp) fclose(fp);

if (destroy_file_handler) {

default_file_handler->destroy(default_file_handler);

}

return old_compile_file(h, type TSRMLS_CC);

}

/* Configure entries */

void beast_atoi(const char *str, int *ret, int *len)

{

const char *ptr = str;

char ch;

int absolute = 1;

int rlen, result;

ch = *ptr;

if (ch == '-') {

absolute = -1;

++ptr;

} else if (ch == '+') {

absolute = 1;

++ptr;

}

for (rlen = 0, result = 0; *ptr != '\0'; ptr++) {

ch = *ptr;

if (ch >= '0' && ch <= '9') {

result = result * 10 + (ch - '0');

rlen++;

} else {

break;

}

}

if (ret) *ret = absolute * result;

if (len) *len = rlen;

}

ZEND_INI_MH(php_beast_cache_size)

{

#if ZEND_MODULE_API_NO >= 20151012

char *value = ZSTR_VAL(new_value);

int length = ZSTR_LEN(new_value);

int retlen;

if (length == 0) {

return FAILURE;

}

beast_atoi(value, &max_cache_size, &retlen);

if (retlen > 0 && retlen < length) {

switch (value[retlen]) {

case 'k':

case 'K':

max_cache_size *= 1024;

break;

case 'm':

case 'M':

max_cache_size *= 1024 * 1024;

break;

case 'g':

case 'G':

max_cache_size *= 1024 * 1024 * 1024;

break;

default:

return FAILURE;

}

} else if (retlen == 0) {

return FAILURE;

}

return SUCCESS;

#else

int len;

if (new_value_length == 0) {

return FAILURE;

}

beast_atoi(new_value, &max_cache_size, &len);

if (len > 0 && len < new_value_length) {

switch (new_value[len]) {

case 'k':

case 'K':

max_cache_size *= 1024;

break;

case 'm':

case 'M':

max_cache_size *= 1024 * 1024;

break;

case 'g':

case 'G':

max_cache_size *= 1024 * 1024 * 1024;

break;

default:

return FAILURE;

}

} else if (len == 0) {

return FAILURE;

}

return SUCCESS;

#endif

}

ZEND_INI_MH(php_beast_log_file)

{

#if ZEND_MODULE_API_NO >= 20151012

if (ZSTR_LEN(new_value) == 0) {

return SUCCESS;

}

beast_log_file = estrdup(ZSTR_VAL(new_value));

if (beast_log_file == NULL) {

return FAILURE;

}

return SUCCESS;

#else

if (new_value_length == 0) {

return SUCCESS;

}

beast_log_file = strdup(new_value);

if (beast_log_file == NULL) {

return FAILURE;

}

return SUCCESS;

#endif

}

ZEND_INI_MH(php_beast_log_user)

{

#if ZEND_MODULE_API_NO >= 20151012

if (ZSTR_LEN(new_value) == 0) {

return SUCCESS;

}

beast_log_user = estrdup(ZSTR_VAL(new_value));

if (beast_log_user == NULL) {

return FAILURE;

}

return SUCCESS;

#else

if (new_value_length == 0) {

return SUCCESS;

}

beast_log_user = strdup(new_value);

if (beast_log_user == NULL) {

return FAILURE;

}

return SUCCESS;

#endif

}

ZEND_INI_MH(php_beast_log_level)

{

char *level = NULL;

#if ZEND_MODULE_API_NO >= 20151012

if (ZSTR_LEN(new_value) == 0) {

return SUCCESS;

}

level = ZSTR_VAL(new_value);

#else

if (new_value_length == 0) {

return SUCCESS;

}

level = new_value;

#endif

if (level == NULL) {

return FAILURE;

}

if (strcasecmp(level, "debug") == 0) {

log_level = beast_log_debug;

} else if (strcasecmp(level, "notice") == 0) {

log_level = beast_log_notice;

} else if (strcasecmp(level, "error") == 0) {

log_level = beast_log_error;

} else {

return FAILURE;

}

return SUCCESS;

}

ZEND_INI_MH(php_beast_enable)

{

#if ZEND_MODULE_API_NO >= 20151012

if (ZSTR_LEN(new_value) == 0) {

return FAILURE;

}

if (!strcasecmp(ZSTR_VAL(new_value), "on")

|| !strcmp(ZSTR_VAL(new_value), "1"))

{

beast_enable = 1;

} else {

beast_enable = 0;

}

return SUCCESS;

#else

if (new_value_length == 0) {

return FAILURE;

}

if (!strcasecmp(new_value, "on")

|| !strcmp(new_value, "1"))

{

beast_enable = 1;

} else {

beast_enable = 0;

}

return SUCCESS;

#endif

}

ZEND_INI_MH(php_beast_set_networkcard)

{

#if ZEND_MODULE_API_NO >= 20151012

if (ZSTR_LEN(new_value) == 0) {

return FAILURE;

}

local_networkcard = estrdup(ZSTR_VAL(new_value));

if (local_networkcard == NULL) {

return FAILURE;

}

return SUCCESS;

#else

if (new_value_length == 0) {

return FAILURE;

}

local_networkcard = strdup(new_value);

if (local_networkcard == NULL) {

return FAILURE;

}

return SUCCESS;

#endif

}

ZEND_INI_MH(php_beast_set_log_normal_file)

{

#if ZEND_MODULE_API_NO >= 20151012

if (ZSTR_LEN(new_value) == 0) {

return FAILURE;

}

if (!strcasecmp(ZSTR_VAL(new_value), "on")

|| !strcmp(ZSTR_VAL(new_value), "1"))

{

log_normal_file = 1;

} else {

log_normal_file = 0;

}

return SUCCESS;

#else

if (new_value_length == 0) {

return FAILURE;

}

if (!strcasecmp(new_value, "on")

|| !strcmp(new_value, "1"))

{

log_normal_file = 1;

} else {

log_normal_file = 0;

}

return SUCCESS;

#endif

}

ZEND_INI_MH(php_beast_debug_path)

{

#if ZEND_MODULE_API_NO >= 20151012

if (ZSTR_LEN(new_value) == 0) {

return SUCCESS;

}

beast_debug_path = estrdup(ZSTR_VAL(new_value));

if (beast_debug_path == NULL) {

return FAILURE;

}

return SUCCESS;

#else

if (new_value_length == 0) {

return SUCCESS;

}

beast_debug_path = strdup(new_value);

if (beast_debug_path == NULL) {

return FAILURE;

}

return SUCCESS;

#endif

}

ZEND_INI_MH(php_beast_debug_mode)

{

#if ZEND_MODULE_API_NO >= 20151012

if (ZSTR_LEN(new_value) == 0) {

return FAILURE;

}

if (!strcasecmp(ZSTR_VAL(new_value), "on")

|| !strcmp(ZSTR_VAL(new_value), "1"))

{

beast_debug_mode = 1;

} else {

beast_debug_mode = 0;

}

return SUCCESS;

#else

if (new_value_length == 0) {

return FAILURE;

}

if (!strcasecmp(new_value, "on")

|| !strcmp(new_value, "1"))

{

beast_debug_mode = 1;

} else {

beast_debug_mode = 0;

}

return SUCCESS;

#endif

}

PHP_INI_BEGIN()

PHP_INI_ENTRY("beast.cache_size", "10485760", PHP_INI_ALL,

php_beast_cache_size)

PHP_INI_ENTRY("beast.log_file", "./php-beast.log", PHP_INI_ALL,

php_beast_log_file)

PHP_INI_ENTRY("beast.log_user", "root", PHP_INI_ALL,

php_beast_log_user)

PHP_INI_ENTRY("beast.log_level", "notice", PHP_INI_ALL,

php_beast_log_level)

PHP_INI_ENTRY("beast.enable", "1", PHP_INI_ALL,

php_beast_enable)

PHP_INI_ENTRY("beast.networkcard", "eth0", PHP_INI_ALL,

php_beast_set_networkcard)

PHP_INI_ENTRY("beast.log_normal_file", "0", PHP_INI_ALL,

php_beast_set_log_normal_file)

#if BEAST_DEBUG_MODE

PHP_INI_ENTRY("beast.debug_path", "/tmp", PHP_INI_ALL,

php_beast_debug_path)

PHP_INI_ENTRY("beast.debug_mode", "0", PHP_INI_ALL,

php_beast_debug_mode)

#endif

PHP_INI_END()

/* }}} */

void segmentfault_deadlock_fix(int sig)

{

#ifdef PHP_WIN32 // windows not support backtrace

beast_write_log(beast_log_error, "Segmentation fault and fix deadlock");

#else

void *array[10] = {0};

size_t size;

char **info = NULL;

int i;

size = backtrace(array, 10);

info = backtrace_symbols(array, (int)size);

beast_write_log(beast_log_error, "Segmentation fault and fix deadlock");

if (info) {

for (i = 0; i < size; i++) {

beast_write_log(beast_log_error, info[i]);

}

free(info);

}

#endif

beast_mm_unlock(); /* Maybe lock mm so free here */

beast_cache_unlock(); /* Maybe lock cache so free here */

exit(sig);

}

static char *get_mac_address(char *networkcard)

{

#ifdef PHP_WIN32

// For windows

ULONG size = sizeof(IP_ADAPTER_INFO);

int ret, i;

char *address = NULL;

char buf[128] = { 0 }, *pos;

PIP_ADAPTER_INFO pCurrentAdapter = NULL;

PIP_ADAPTER_INFO pIpAdapterInfo = (PIP_ADAPTER_INFO)malloc(sizeof(*pIpAdapterInfo));

if (!pIpAdapterInfo) {

beast_write_log(beast_log_error, "Failed to allocate memory for IP_ADAPTER_INFO");

return NULL;

}

ret = GetAdaptersInfo(pIpAdapterInfo, &size);

if (ERROR_BUFFER_OVERFLOW == ret) {

// see ERROR_BUFFER_OVERFLOW https://msdn.microsoft.com/en-us/library/aa365917(VS.85).aspx

free(pIpAdapterInfo);

pIpAdapterInfo = (PIP_ADAPTER_INFO)malloc(size);

ret = GetAdaptersInfo(pIpAdapterInfo, &size);

}

if (ERROR_SUCCESS != ret) {

beast_write_log(beast_log_error, "Failed to get network adapter information");

free(pIpAdapterInfo);

return NULL;

}

pCurrentAdapter = pIpAdapterInfo;

do {

if (strcmp(pCurrentAdapter->AdapterName, networkcard) == 0) {

for (i = 0, pos = buf; i < pCurrentAdapter->AddressLength; i++, pos += 3) {

sprintf(pos, "%.2X-", (int)pCurrentAdapter->Address[i]);

}

*(--pos) = '\0'; // remove last -

address = strdup(buf);

break;

}

pCurrentAdapter = pCurrentAdapter->Next;

} while (pCurrentAdapter);

free(pIpAdapterInfo);

return address;

#else

// For linux / unix

char netfile[128] = { 0 }, cmd[128] = { 0 }, buf[128] = { 0 };

FILE *fp;

char *retbuf, *curr, *last;

snprintf(netfile, 128, "/sys/class/net/%s/address", networkcard);

if (access((const char *)netfile, R_OK) != 0) { /* File not exists */

snprintf(cmd, 128, "ifconfig %s|awk '/ether/ {print $2}'", networkcard);

} else {

snprintf(cmd, 128, "cat %s", netfile);

}

fp = popen(cmd, "r");

if (!fp) {

return NULL;

}

retbuf = fgets(buf, 128, fp);

for (curr = buf, last = NULL; *curr; curr++) {

if (*curr != '\n') {

last = curr;

}

}

if (!last) {

return NULL;

}

for (last += 1; *last; last++) {

*last = '\0';

}

pclose(fp);

return strdup(buf);

#endif

}

static int validate_networkcard()

{

extern char *allow_networkcards[];

char **ptr;

char *networkcard_start, *networkcard_end;

int endof_networkcard = 0;

int active = 0;

char *address;

for (ptr = allow_networkcards; *ptr; ptr++, active++);

if (!active) {

return 0;

}

networkcard_start = networkcard_end = local_networkcard;

while (1) {

while (*networkcard_end && *networkcard_end != ',') {

networkcard_end++;

}

if (networkcard_start == networkcard_end) { /* empty string */

break;

}

if (*networkcard_end == ',') {

*networkcard_end = '\0';

}

else {

endof_networkcard = 1;

}

address = get_mac_address(networkcard_start);

if (address) {

for (ptr = allow_networkcards; *ptr; ptr++) {

if (!strcasecmp(address, *ptr)) {

free(address); /* release buffer */

return 0;

}

}

free(address);

}

if (endof_networkcard) {

break;

}

networkcard_start = networkcard_end + 1;

}

return -1;

}

/* {{{ PHP_MINIT_FUNCTION

*/

PHP_MINIT_FUNCTION(beast)

{

int i;

#ifdef PHP_WIN32

SYSTEM_INFO info;

#endif

/* If you have INI entries, uncomment these lines */

REGISTER_INI_ENTRIES();

if (!beast_enable) {

return SUCCESS;

}

if (validate_networkcard() == -1) {

php_error_docref(NULL TSRMLS_CC, E_ERROR,

"Not allow run at this computer");

return FAILURE;

}

if ((encrypt_file_header_length + INT_SIZE * 2) > HEADER_MAX_SIZE) {

php_error_docref(NULL TSRMLS_CC, E_ERROR,

"Header size overflow max size `%d'", HEADER_MAX_SIZE);

return FAILURE;

}

/* Check module support the max file size */

for (i = 0; ; i++) {

default_file_handler = file_handlers[i];

if (!default_file_handler ||

!strcasecmp(file_handler_switch, default_file_handler->name))

{

break;

}

}

if (!default_file_handler) {

return FAILURE;

}

beast_max_filesize = default_file_handler->check();

if (beast_max_filesize == -1) {

return FAILURE;

}

if (beast_cache_init(max_cache_size) == -1) {

php_error_docref(NULL TSRMLS_CC,

E_ERROR, "Unable initialize cache for beast");

return FAILURE;

}

if (beast_log_init(beast_log_file, log_level) == -1) {

php_error_docref(NULL TSRMLS_CC,

E_ERROR, "Unable open log file for beast");

return FAILURE;

}

#ifndef PHP_WIN32

if (getuid() == 0 && beast_log_user) { /* Change log file owner user */

struct passwd *pwd;

pwd = getpwnam((const char *)beast_log_user);

if (!pwd) {

php_error_docref(NULL TSRMLS_CC,

E_ERROR, "Unable get user passwd information");

return FAILURE;

}

if (beast_log_chown(pwd->pw_uid, pwd->pw_gid) != 0) {

php_error_docref(NULL TSRMLS_CC,

E_ERROR, "Unable change log file owner");

return FAILURE;

}

}

#endif

old_compile_file = zend_compile_file;

zend_compile_file = cgi_compile_file;

#ifdef PHP_WIN32

GetSystemInfo(&info);

beast_ncpu = info.dwNumberOfProcessors;

#else

beast_ncpu = sysconf(_SC_NPROCESSORS_ONLN); /* Get CPU nums */

#endif

if (beast_ncpu <= 0) {

beast_ncpu = 1;

}

signal(SIGSEGV, segmentfault_deadlock_fix);

REGISTER_LONG_CONSTANT("BEAST_ENCRYPT_TYPE_DES",

BEAST_ENCRYPT_TYPE_DES, CONST_CS|CONST_PERSISTENT);

REGISTER_LONG_CONSTANT("BEAST_ENCRYPT_TYPE_AES",

BEAST_ENCRYPT_TYPE_AES, CONST_CS|CONST_PERSISTENT);

REGISTER_LONG_CONSTANT("BEAST_ENCRYPT_TYPE_BASE64",

BEAST_ENCRYPT_TYPE_BASE64, CONST_CS|CONST_PERSISTENT);

beast_write_log(beast_log_debug, "Beast module was initialized");

return SUCCESS;

}

/* }}} */

/* {{{ PHP_MSHUTDOWN_FUNCTION

*/

PHP_MSHUTDOWN_FUNCTION(beast)

{

/* uncomment this line if you have INI entries */

UNREGISTER_INI_ENTRIES();

if (!beast_enable) {

return SUCCESS;

}

beast_cache_destroy();

beast_log_destroy();

zend_compile_file = old_compile_file;

return SUCCESS;

}

/* }}} */

/* {{{ PHP_RINIT_FUNCTION

*/

PHP_RINIT_FUNCTION(beast)

{

if (beast_pid == -1) {

beast_pid = getpid();

}

beast_now_time = time(NULL); /* Update now time */

return SUCCESS;

}

/* }}} */

/* {{{ PHP_RSHUTDOWN_FUNCTION

*/

PHP_RSHUTDOWN_FUNCTION(beast)

{

return SUCCESS;

}

/* }}} */

/* {{{ PHP_MINFO_FUNCTION

*/

PHP_MINFO_FUNCTION(beast)

{

php_info_print_table_start();

php_info_print_table_header(2,

"beast V" BEAST_VERSION " support", "enabled");

php_info_print_table_end();

DISPLAY_INI_ENTRIES();

}

/* }}} */

PHP_FUNCTION(beast_file_expire)

{

char *file;

int file_len;

char header[HEADER_MAX_SIZE] = {0};

int header_len;

signed long expire = 0;

int fd = -1;

char *string;

char *format = "Y-m-d H:i:s";

#if ZEND_MODULE_API_NO >= 20151012

zend_string *input_file;

if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "S",

&input_file TSRMLS_CC) == FAILURE)

{

RETURN_FALSE;

}

file = ZSTR_VAL(input_file);

file_len = ZSTR_LEN(input_file);

#else

if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s",

&file, &file_len TSRMLS_CC) == FAILURE)

{

RETURN_FALSE;

}

#endif

fd = open(file, O_RDONLY);

if (fd < 0) {

goto error;

}

header_len = encrypt_file_header_length + INT_SIZE * 2;

if (read(fd, header, header_len) != header_len

|| memcmp(header, encrypt_file_header_sign, encrypt_file_header_length))

{

goto error;

}

close(fd);

expire = *((int *)&header[encrypt_file_header_length + INT_SIZE]);

if (little_endian()) {

expire = swab32(expire);

}

if (expire > 0) {

string = (char *)php_format_date(format, strlen(format), expire, 1 TSRMLS_CC);

BEAST_RETURN_STRING(string, 0);

} else {

BEAST_RETURN_STRING("+Infinity", 1);

}

error:

if (fd >= 0) {

close(fd);

}

RETURN_FALSE;

}

PHP_FUNCTION(beast_encode_file)

{

char *input, *output;

int input_len, output_len;

long expire = 0;

long encrypt_type = BEAST_ENCRYPT_TYPE_DES;

int ret;

#if ZEND_MODULE_API_NO >= 20151012

zend_string *in, *out;

if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "SS|ll",

&in, &out, &expire, &encrypt_type) == FAILURE)

{

RETURN_FALSE;

}

input = ZSTR_VAL(in);

output = ZSTR_VAL(out);

input_len = ZSTR_LEN(in);

output_len = ZSTR_LEN(out);

#else

if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|ll",

&input, &input_len, &output, &output_len,

&expire, &encrypt_type TSRMLS_CC) == FAILURE)

{

RETURN_FALSE;

}

#endif

if (encrypt_type <= 0

|| encrypt_type >= BEAST_ENCRYPT_TYPE_ERROR)

{

RETURN_FALSE;

}

ret = encrypt_file(input, output,

(int)expire, (int)encrypt_type TSRMLS_CC);

if (ret == -1) {

RETURN_FALSE;

}

RETURN_TRUE;

}

PHP_FUNCTION(beast_avail_cache)

{

RETURN_LONG(beast_mm_availspace());

}

PHP_FUNCTION(beast_support_filesize)

{

RETURN_LONG(beast_max_filesize);

}

PHP_FUNCTION(beast_clean_cache)

{

beast_cache_flush();

}

/*

* Local variables:

* tab-width: 4

* c-basic-offset: 4

* End:

* vim600: noet sw=4 ts=4 fdm=marker expandtab

* vim<600: noet sw=4 ts=4

*/

一键复制

编辑

Web IDE

原始数据

按行查看

历史

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值