├── .github └── workflows │ └── integrate.yml ├── CREDITS ├── EXPERIMENTAL ├── README.md ├── aes_algo_handler.c ├── aes_algo_lib.c ├── base64_algo_handler.c ├── beast.c ├── beast_log.c ├── beast_log.h ├── beast_mm.c ├── beast_mm.h ├── beast_module.h ├── cache.c ├── cache.h ├── config.m4 ├── config.w32 ├── des_algo_handler.c ├── des_algo_lib.c ├── file_handler.h ├── file_handler_switch.c ├── global_algo_modules.c ├── header.c ├── images ├── beast1.png ├── beast2.png └── pay.jpg ├── networkcards.c ├── php_beast.h ├── pipe_file_handler.c ├── shm.c ├── shm.h ├── spinlock.c ├── spinlock.h ├── tests ├── 001.phpt └── encrypt.php ├── tmpfile_file_handler.c └── tools ├── configure.ini ├── encode_file.php └── encode_files.php /.github/workflows/integrate.yml: -------------------------------------------------------------------------------- 1 | name: integrate 2 | on: 3 | push: 4 | branches: [ master ] 5 | pull_request: 6 | branches: [ master ] 7 | 8 | jobs: 9 | matrix: 10 | name: "PHP" 11 | runs-on: ${{ matrix.OS }} 12 | strategy: 13 | matrix: 14 | PHP: ["7.0", "7.1", "7.2", "7.3"] 15 | OS: ["ubuntu-latest"] 16 | include: 17 | - PHP: "7.4" 18 | OS: "ubuntu-latest" 19 | ZTS: true 20 | env: 21 | GITHUB: "yes" 22 | enable_debug: "yes" 23 | enable_session: "yes" 24 | TEST_PHP_ARGS : "--show-diff" 25 | REPORT_EXIT_STATUS: "yes" 26 | NO_INTERACTION: "yes" 27 | steps: 28 | - name: Checkout 29 | uses: actions/checkout@v2 30 | with: 31 | submodules: true 32 | - name: Setup 33 | uses: shivammathur/setup-php@v2 34 | with: 35 | php-version: ${{ matrix.PHP }} 36 | - name: Install 37 | run: | 38 | sudo apt-get install -y re2c 39 | - name: Prepare 40 | run: | 41 | phpize 42 | - name: Build 43 | run: | 44 | ./configure 45 | - name: Make 46 | run: | 47 | make 48 | - name: Test 49 | run: | 50 | make test -------------------------------------------------------------------------------- /CREDITS: -------------------------------------------------------------------------------- 1 | beast -------------------------------------------------------------------------------- /EXPERIMENTAL: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liexusong/php-beast/4549b2a642a9b04408b4bfbb3af64131c7f1f2dd/EXPERIMENTAL -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |
  2 |         ____  __  ______     ____  _________   ___________
  3 |        / __ \/ / / / __ \   / __ )/ ____/   | / ___/_  __/
  4 |       / /_/ / /_/ / /_/ /  / __  / __/ / /| | \__ \ / /
  5 |      / ____/ __  / ____/  / /_/ / /___/ ___ |___/ // /
  6 |     /_/   /_/ /_/_/      /_____/_____/_/  |_/____//_/
  7 | 
  8 | 贡献者名字:
  9 | @imaben (windows版本提供者)  https://github.com/imaben
 10 | @pinguo-niulingyun (PHP7版本提供者) https://github.com/pinguo-niulingyun
 11 | 
 12 | QQ交流群:239243332
 13 | 
14 | 15 | Windows DLL:下载地址 16 | 17 | php-beast可以自定义加密模块,加密模块编写教程: 点击 18 | 19 |

编译安装如下:

20 |

 21 | $ wget https://github.com/liexusong/php-beast/archive/master.zip
 22 | $ unzip master.zip
 23 | $ cd php-beast-master
 24 | $ phpize
 25 | $ ./configure
 26 | $ sudo make && make install
 27 | 
 28 | 编译好之后修改php.ini配置文件, 加入配置项: extension=beast.so, 重启php-fpm
 29 | 
30 | 31 |
温馨提示: 可以设置较大的缓存提高效率
32 | 33 |

使用php-beast的性能:

34 |

35 | 36 |

不使用php-beast的性能:

37 |

38 | 39 | 配置项: 40 |

 41 |  beast.cache_size = size
 42 |  beast.log_file = "path_to_log"
 43 |  beast.log_user = "user"
 44 |  beast.log_level = "debug"
 45 |  beast.enable = On
 46 | 
47 | 48 | beast.log_level支持参数: 49 |
 50 |  1. DEBUG
 51 |  2. NOTICE
 52 |  3. ERROR
 53 | 
54 | 55 | 支持的模块有: 56 |
 57 |  1. AES
 58 |  2. DES
 59 |  3. Base64
 60 | 
61 | 62 | 通过测试环境: 63 |

 64 |  Nginx + Fastcgi + (PHP-5.2.x ~ PHP-7.1.x)
 65 | 
66 | 67 | ------------------------------ 68 | 69 | ## 怎么加密项目 70 | **加密方案1** 71 | 72 | 安装完 `php-beast` 后可以使用 `tools` 目录下的 `encode_files.php` 来加密你的项目。使用 `encode_files.php` 之前先修改 `tools` 目录下的 `configure.ini` 文件,如下: 73 | ```ini 74 | ; source path 75 | src_path = "" 76 | 77 | ; destination path 78 | dst_path = "" 79 | 80 | ; expire time 81 | expire = "" 82 | 83 | ; encrypt type (selection: DES, AES, BASE64) 84 | encrypt_type = "DES" 85 | ``` 86 | `src_path` 是要加密项目的路径,`dst_path` 是保存加密后项目的路径,`expire` 是设置项目可使用的时间 (`expire` 的格式是:`YYYY-mm-dd HH:ii:ss`)。`encrypt_type`是加密的方式,选择项有:DES、AES、BASE64。 87 | 修改完 `configure.ini` 文件后就可以使用命令 `php encode_files.php` 开始加密项目。 88 | 89 | **加密方案2** 90 | 91 | 使用`beast_encode_file()`函数加密文件,函数原型如下:
92 | `beast_encode_file(string $input_file, string $output_file, int expire_timestamp, int encrypt_type)`。 93 |
 94 | 1. $input_file: 要加密的文件
 95 | 2. $output_file: 输出的加密文件路径
 96 | 3. $expire_timestamp: 文件过期时间戳
 97 | 4. $encrypt_type: 加密使用的算法(支持:BEAST_ENCRYPT_TYPE_DES、BEAST_ENCRYPT_TYPE_AES)
 98 | 
99 | 100 | ------------------------------ 101 | 102 | ## 制定自己的php-beast 103 | 104 | `php-beast` 有多个地方可以定制的,以下一一列出: 105 | 106 | *1.* 使用 `header.c` 文件可以修改 `php-beast` 加密后的文件头结构,这样网上的解密软件就不能认识我们的加密文件,就不能进行解密,增加加密的安全性。 107 | 108 | *2.* `php-beast` 提供只能在指定的机器上运行的功能。要使用此功能可以在 `networkcards.c` 文件添加能够运行机器的网卡号,例如: 109 | ```c 110 | char *allow_networkcards[] = { 111 | "fa:16:3e:08:88:01", 112 | NULL, 113 | }; 114 | ``` 115 | 这样设置之后,`php-beast` 扩展就只能在 `fa:16:3e:08:88:01` 这台机器上运行。另外要注意的是,由于有些机器网卡名可能不一样,所以如果你的网卡名不是 `eth0` 的话,可以在 `php.ini` 中添加配置项: `beast.networkcard = "xxx"` 其中 `xxx` 就是你的网卡名,也可以配置多张网卡,如:`beast.networkcard = "eth0,eth1,eth2"`。 116 | 117 | *3.* 使用 `php-beast` 时最好不要使用默认的加密key,因为扩展是开源的,如果使用默认加密key的话,很容易被人发现。所以最好编译的时候修改加密的key,`aes模块` 可以在 `aes_algo_handler.c` 文件修改,而 `des模块` 可以在 `des_algo_handler.c` 文件修改。 118 | 119 | ------------------------------ 120 | 121 | ## 开启debug模式 122 | 可以在configure时加上 `--enable-beast-debug` 选项来开启debug模式。开启debug模式后需要在php.ini配置文件中加入配置项:`beast.debug_path` 和 `beast.debug_mode`。`beast.debug_mode` 用于指定是否使用debug模式,而 `beast.debug_path` 用于输出解密后的php脚本源码。这样就可以在 `beast.debug_path` 目录中看到php-beast解密后的源代码,可以方便知道扩展解密是否正确。 123 | 124 | ## 开启禁止执行未加密的脚本 125 | 可以在configure时加上 `--enable-execute-normal-script=off` 选项来禁止执行未加密的PHP脚本。 126 | 127 | ------------------------------ 128 | 129 | ## 函数列表 130 | *1.* beast_encode_file(): 用于加密一个文件 131 | 132 | *2.* beast_avail_cache(): 获取可以缓存大小 133 | 134 | *3.* beast_support_filesize(): 获取beast支持的最大可加密文件大小 135 | 136 | *4.* beast_file_expire(): 获取一个文件的过期时间 137 | 138 | *5.* beast_clean_cache(): 清空beast的所有缓存(如果有文件更新, 可以使用此函数清空缓存) 139 | 140 | ------------------------------ 141 | 142 | ## 常见问题 143 | 144 | *1.* linux:如果出现502错误,一般是由于GCC版本太低导致,请先升级GCC再安装本模块。 145 | 146 | *2.* Windows:IIS环境下FastCGI进程异常退出:尝试将IIS的运行用户从ApplicationPoolIdentity改为LocalSystem 147 | 148 | ------------------------------ 149 | 150 | ### 我们的公众号 151 | 152 | ![](https://image-static.segmentfault.com/376/558/3765589661-607fef350658b_fix732) 153 | 154 | ------------------------------ 155 | -------------------------------------------------------------------------------- /aes_algo_handler.c: -------------------------------------------------------------------------------- 1 | /** 2 | * AES encrypt algorithms handler module for Beast 3 | * @author: liexusong 4 | */ 5 | 6 | #include 7 | #include 8 | #include "beast_log.h" 9 | #include "beast_module.h" 10 | #include "aes_algo_lib.c" 11 | 12 | static uint8_t key[] = { 13 | 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 14 | 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c, 15 | }; 16 | 17 | int aes_encrypt_handler(char *inbuf, int len, 18 | char **outbuf, int *outlen) 19 | { 20 | int blocks, i; 21 | char *out; 22 | char in[16]; 23 | 24 | blocks = len / 16; 25 | if (len % 16) { /* not enough one block (16 bytes) */ 26 | blocks += 1; 27 | } 28 | 29 | out = malloc(blocks * 16); 30 | if (!out) { 31 | beast_write_log(beast_log_error, 32 | "Out of memory when allocate `%d' size by encrypt(AES)", blocks*16); 33 | return -1; 34 | } 35 | 36 | for (i = 0; i < blocks; i++) { 37 | int size; 38 | 39 | memset(in, 0, 16); 40 | 41 | if (i == blocks - 1 && (len % 16)) { /* the last block */ 42 | size = len % 16; 43 | } else { 44 | size = 16; 45 | } 46 | 47 | memcpy(in, inbuf + i * 16, size); 48 | 49 | AES128_ECB_encrypt(in, key, out + i * 16); 50 | } 51 | 52 | *outbuf = out; 53 | *outlen = blocks * 16; 54 | 55 | return 0; 56 | } 57 | 58 | 59 | int aes_decrypt_handler(char *inbuf, int len, 60 | char **outbuf, int *outlen) 61 | { 62 | int blocks, i; 63 | char *out; 64 | 65 | if (len % 16) { 66 | return -1; 67 | } 68 | 69 | blocks = len / 16; 70 | 71 | out = malloc(blocks * 16); 72 | if (!out) { 73 | beast_write_log(beast_log_error, 74 | "Out of memory when allocate `%d' size by decrypt(AES)", blocks*16); 75 | return -1; 76 | } 77 | 78 | for (i = 0; i < blocks; i++) { 79 | AES128_ECB_decrypt(inbuf + i * 16, key, out + i * 16); 80 | } 81 | 82 | *outbuf = out; 83 | *outlen = blocks * 16; 84 | 85 | return 0; 86 | } 87 | 88 | 89 | void aes_free_handler(void *ptr) 90 | { 91 | if (ptr) { 92 | free(ptr); 93 | } 94 | } 95 | 96 | struct beast_ops aes_handler_ops = { 97 | "aes-algo", 98 | aes_encrypt_handler, 99 | aes_decrypt_handler, 100 | aes_free_handler, 101 | NULL 102 | }; 103 | -------------------------------------------------------------------------------- /aes_algo_lib.c: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | This is an implementation of the AES128 algorithm, specifically ECB and CBC mode. 4 | 5 | The implementation is verified against the test vectors in: 6 | National Institute of Standards and Technology Special Publication 800-38A 2001 ED 7 | 8 | ECB-AES128 9 | ---------- 10 | 11 | plain-text: 12 | 6bc1bee22e409f96e93d7e117393172a 13 | ae2d8a571e03ac9c9eb76fac45af8e51 14 | 30c81c46a35ce411e5fbc1191a0a52ef 15 | f69f2445df4f9b17ad2b417be66c3710 16 | 17 | key: 18 | 2b7e151628aed2a6abf7158809cf4f3c 19 | 20 | resulting cipher 21 | 3ad77bb40d7a3660a89ecaf32466ef97 22 | f5d3d58503b9699de785895a96fdbaaf 23 | 43b1cd7f598ece23881b00e3ed030688 24 | 7b0c785e27e8ad3f8223207104725dd4 25 | 26 | 27 | NOTE: String length must be evenly divisible by 16byte (str_len % 16 == 0) 28 | You should pad the end of the string with zeros if this is not the case. 29 | 30 | */ 31 | 32 | 33 | /*****************************************************************************/ 34 | /* Includes: */ 35 | /*****************************************************************************/ 36 | #include 37 | #include // CBC mode, for memset 38 | 39 | /*****************************************************************************/ 40 | /* Defines: */ 41 | /*****************************************************************************/ 42 | // The number of columns comprising a state in AES. This is a constant in AES. Value=4 43 | #define Nb 4 44 | // The number of 32 bit words in a key. 45 | #define Nk 4 46 | // Key length in bytes [128 bit] 47 | #define KEYLEN 16 48 | // The number of rounds in AES Cipher. 49 | #define Nr 10 50 | 51 | // jcallan@github points out that declaring Multiply as a function 52 | // reduces code size considerably with the Keil ARM compiler. 53 | // See this link for more information: https://github.com/kokke/tiny-AES128-C/pull/3 54 | #ifndef MULTIPLY_AS_A_FUNCTION 55 | #define MULTIPLY_AS_A_FUNCTION 0 56 | #endif 57 | 58 | 59 | /*****************************************************************************/ 60 | /* Private variables: */ 61 | /*****************************************************************************/ 62 | // state - array holding the intermediate results during decryption. 63 | typedef uint8_t state_t[4][4]; 64 | static state_t* state; 65 | 66 | // The array that stores the round keys. 67 | static uint8_t RoundKey[176]; 68 | 69 | // The Key input to the AES Program 70 | static const uint8_t* Key; 71 | 72 | // The lookup-tables are marked const so they can be placed in read-only storage instead of RAM 73 | // The numbers below can be computed dynamically trading ROM for RAM - 74 | // This can be useful in (embedded) bootloader applications, where ROM is often limited. 75 | static const uint8_t sbox[256] = { 76 | //0 1 2 3 4 5 6 7 8 9 A B C D E F 77 | 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, 78 | 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, 79 | 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, 80 | 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, 81 | 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, 82 | 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, 83 | 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, 84 | 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, 85 | 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, 86 | 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, 87 | 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, 88 | 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, 89 | 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, 90 | 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, 91 | 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, 92 | 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16 }; 93 | 94 | static const uint8_t rsbox[256] = 95 | { 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb, 96 | 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb, 97 | 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e, 98 | 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25, 99 | 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92, 100 | 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84, 101 | 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06, 102 | 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b, 103 | 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73, 104 | 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e, 105 | 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b, 106 | 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4, 107 | 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f, 108 | 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef, 109 | 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61, 110 | 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d }; 111 | 112 | 113 | // The round constant word array, Rcon[i], contains the values given by 114 | // x to th e power (i-1) being powers of x (x is denoted as {02}) in the field GF(2^8) 115 | // Note that i starts at 1, not 0). 116 | static const uint8_t Rcon[255] = { 117 | 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 118 | 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 119 | 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 120 | 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 121 | 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 122 | 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 123 | 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 124 | 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 125 | 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 126 | 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 127 | 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 128 | 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 129 | 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 130 | 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 131 | 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 132 | 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb }; 133 | 134 | 135 | /*****************************************************************************/ 136 | /* Private functions: */ 137 | /*****************************************************************************/ 138 | static uint8_t getSBoxValue(uint8_t num) 139 | { 140 | return sbox[num]; 141 | } 142 | 143 | static uint8_t getSBoxInvert(uint8_t num) 144 | { 145 | return rsbox[num]; 146 | } 147 | 148 | // This function produces Nb(Nr+1) round keys. The round keys are used in each round to decrypt the states. 149 | static void KeyExpansion(void) 150 | { 151 | uint32_t i, j, k; 152 | uint8_t tempa[4]; // Used for the column/row operations 153 | 154 | // The first round key is the key itself. 155 | for(i = 0; i < Nk; ++i) 156 | { 157 | RoundKey[(i * 4) + 0] = Key[(i * 4) + 0]; 158 | RoundKey[(i * 4) + 1] = Key[(i * 4) + 1]; 159 | RoundKey[(i * 4) + 2] = Key[(i * 4) + 2]; 160 | RoundKey[(i * 4) + 3] = Key[(i * 4) + 3]; 161 | } 162 | 163 | // All other round keys are found from the previous round keys. 164 | for(; (i < (Nb * (Nr + 1))); ++i) 165 | { 166 | for(j = 0; j < 4; ++j) 167 | { 168 | tempa[j]=RoundKey[(i-1) * 4 + j]; 169 | } 170 | if (i % Nk == 0) 171 | { 172 | // This function rotates the 4 bytes in a word to the left once. 173 | // [a0,a1,a2,a3] becomes [a1,a2,a3,a0] 174 | 175 | // Function RotWord() 176 | { 177 | k = tempa[0]; 178 | tempa[0] = tempa[1]; 179 | tempa[1] = tempa[2]; 180 | tempa[2] = tempa[3]; 181 | tempa[3] = k; 182 | } 183 | 184 | // SubWord() is a function that takes a four-byte input word and 185 | // applies the S-box to each of the four bytes to produce an output word. 186 | 187 | // Function Subword() 188 | { 189 | tempa[0] = getSBoxValue(tempa[0]); 190 | tempa[1] = getSBoxValue(tempa[1]); 191 | tempa[2] = getSBoxValue(tempa[2]); 192 | tempa[3] = getSBoxValue(tempa[3]); 193 | } 194 | 195 | tempa[0] = tempa[0] ^ Rcon[i/Nk]; 196 | } 197 | else if (Nk > 6 && i % Nk == 4) 198 | { 199 | // Function Subword() 200 | { 201 | tempa[0] = getSBoxValue(tempa[0]); 202 | tempa[1] = getSBoxValue(tempa[1]); 203 | tempa[2] = getSBoxValue(tempa[2]); 204 | tempa[3] = getSBoxValue(tempa[3]); 205 | } 206 | } 207 | RoundKey[i * 4 + 0] = RoundKey[(i - Nk) * 4 + 0] ^ tempa[0]; 208 | RoundKey[i * 4 + 1] = RoundKey[(i - Nk) * 4 + 1] ^ tempa[1]; 209 | RoundKey[i * 4 + 2] = RoundKey[(i - Nk) * 4 + 2] ^ tempa[2]; 210 | RoundKey[i * 4 + 3] = RoundKey[(i - Nk) * 4 + 3] ^ tempa[3]; 211 | } 212 | } 213 | 214 | // This function adds the round key to state. 215 | // The round key is added to the state by an XOR function. 216 | static void AddRoundKey(uint8_t round) 217 | { 218 | uint8_t i,j; 219 | for(i=0;i<4;++i) 220 | { 221 | for(j = 0; j < 4; ++j) 222 | { 223 | (*state)[i][j] ^= RoundKey[round * Nb * 4 + i * Nb + j]; 224 | } 225 | } 226 | } 227 | 228 | // The SubBytes Function Substitutes the values in the 229 | // state matrix with values in an S-box. 230 | static void SubBytes(void) 231 | { 232 | uint8_t i, j; 233 | for(i = 0; i < 4; ++i) 234 | { 235 | for(j = 0; j < 4; ++j) 236 | { 237 | (*state)[j][i] = getSBoxValue((*state)[j][i]); 238 | } 239 | } 240 | } 241 | 242 | // The ShiftRows() function shifts the rows in the state to the left. 243 | // Each row is shifted with different offset. 244 | // Offset = Row number. So the first row is not shifted. 245 | static void ShiftRows(void) 246 | { 247 | uint8_t temp; 248 | 249 | // Rotate first row 1 columns to left 250 | temp = (*state)[0][1]; 251 | (*state)[0][1] = (*state)[1][1]; 252 | (*state)[1][1] = (*state)[2][1]; 253 | (*state)[2][1] = (*state)[3][1]; 254 | (*state)[3][1] = temp; 255 | 256 | // Rotate second row 2 columns to left 257 | temp = (*state)[0][2]; 258 | (*state)[0][2] = (*state)[2][2]; 259 | (*state)[2][2] = temp; 260 | 261 | temp = (*state)[1][2]; 262 | (*state)[1][2] = (*state)[3][2]; 263 | (*state)[3][2] = temp; 264 | 265 | // Rotate third row 3 columns to left 266 | temp = (*state)[0][3]; 267 | (*state)[0][3] = (*state)[3][3]; 268 | (*state)[3][3] = (*state)[2][3]; 269 | (*state)[2][3] = (*state)[1][3]; 270 | (*state)[1][3] = temp; 271 | } 272 | 273 | static uint8_t xtime(uint8_t x) 274 | { 275 | return ((x<<1) ^ (((x>>7) & 1) * 0x1b)); 276 | } 277 | 278 | // MixColumns function mixes the columns of the state matrix 279 | static void MixColumns(void) 280 | { 281 | uint8_t i; 282 | uint8_t Tmp,Tm,t; 283 | for(i = 0; i < 4; ++i) 284 | { 285 | t = (*state)[i][0]; 286 | Tmp = (*state)[i][0] ^ (*state)[i][1] ^ (*state)[i][2] ^ (*state)[i][3] ; 287 | Tm = (*state)[i][0] ^ (*state)[i][1] ; Tm = xtime(Tm); (*state)[i][0] ^= Tm ^ Tmp ; 288 | Tm = (*state)[i][1] ^ (*state)[i][2] ; Tm = xtime(Tm); (*state)[i][1] ^= Tm ^ Tmp ; 289 | Tm = (*state)[i][2] ^ (*state)[i][3] ; Tm = xtime(Tm); (*state)[i][2] ^= Tm ^ Tmp ; 290 | Tm = (*state)[i][3] ^ t ; Tm = xtime(Tm); (*state)[i][3] ^= Tm ^ Tmp ; 291 | } 292 | } 293 | 294 | // Multiply is used to multiply numbers in the field GF(2^8) 295 | #if MULTIPLY_AS_A_FUNCTION 296 | static uint8_t Multiply(uint8_t x, uint8_t y) 297 | { 298 | return (((y & 1) * x) ^ 299 | ((y>>1 & 1) * xtime(x)) ^ 300 | ((y>>2 & 1) * xtime(xtime(x))) ^ 301 | ((y>>3 & 1) * xtime(xtime(xtime(x)))) ^ 302 | ((y>>4 & 1) * xtime(xtime(xtime(xtime(x)))))); 303 | } 304 | #else 305 | #define Multiply(x, y) \ 306 | ( ((y & 1) * x) ^ \ 307 | ((y>>1 & 1) * xtime(x)) ^ \ 308 | ((y>>2 & 1) * xtime(xtime(x))) ^ \ 309 | ((y>>3 & 1) * xtime(xtime(xtime(x)))) ^ \ 310 | ((y>>4 & 1) * xtime(xtime(xtime(xtime(x)))))) \ 311 | 312 | #endif 313 | 314 | // MixColumns function mixes the columns of the state matrix. 315 | // The method used to multiply may be difficult to understand for the inexperienced. 316 | // Please use the references to gain more information. 317 | static void InvMixColumns(void) 318 | { 319 | int i; 320 | uint8_t a,b,c,d; 321 | for(i=0;i<4;++i) 322 | { 323 | a = (*state)[i][0]; 324 | b = (*state)[i][1]; 325 | c = (*state)[i][2]; 326 | d = (*state)[i][3]; 327 | 328 | (*state)[i][0] = Multiply(a, 0x0e) ^ Multiply(b, 0x0b) ^ Multiply(c, 0x0d) ^ Multiply(d, 0x09); 329 | (*state)[i][1] = Multiply(a, 0x09) ^ Multiply(b, 0x0e) ^ Multiply(c, 0x0b) ^ Multiply(d, 0x0d); 330 | (*state)[i][2] = Multiply(a, 0x0d) ^ Multiply(b, 0x09) ^ Multiply(c, 0x0e) ^ Multiply(d, 0x0b); 331 | (*state)[i][3] = Multiply(a, 0x0b) ^ Multiply(b, 0x0d) ^ Multiply(c, 0x09) ^ Multiply(d, 0x0e); 332 | } 333 | } 334 | 335 | 336 | // The SubBytes Function Substitutes the values in the 337 | // state matrix with values in an S-box. 338 | static void InvSubBytes(void) 339 | { 340 | uint8_t i,j; 341 | for(i=0;i<4;++i) 342 | { 343 | for(j=0;j<4;++j) 344 | { 345 | (*state)[j][i] = getSBoxInvert((*state)[j][i]); 346 | } 347 | } 348 | } 349 | 350 | static void InvShiftRows(void) 351 | { 352 | uint8_t temp; 353 | 354 | // Rotate first row 1 columns to right 355 | temp=(*state)[3][1]; 356 | (*state)[3][1]=(*state)[2][1]; 357 | (*state)[2][1]=(*state)[1][1]; 358 | (*state)[1][1]=(*state)[0][1]; 359 | (*state)[0][1]=temp; 360 | 361 | // Rotate second row 2 columns to right 362 | temp=(*state)[0][2]; 363 | (*state)[0][2]=(*state)[2][2]; 364 | (*state)[2][2]=temp; 365 | 366 | temp=(*state)[1][2]; 367 | (*state)[1][2]=(*state)[3][2]; 368 | (*state)[3][2]=temp; 369 | 370 | // Rotate third row 3 columns to right 371 | temp=(*state)[0][3]; 372 | (*state)[0][3]=(*state)[1][3]; 373 | (*state)[1][3]=(*state)[2][3]; 374 | (*state)[2][3]=(*state)[3][3]; 375 | (*state)[3][3]=temp; 376 | } 377 | 378 | 379 | // Cipher is the main function that encrypts the PlainText. 380 | static void Cipher(void) 381 | { 382 | uint8_t round = 0; 383 | 384 | // Add the First round key to the state before starting the rounds. 385 | AddRoundKey(0); 386 | 387 | // There will be Nr rounds. 388 | // The first Nr-1 rounds are identical. 389 | // These Nr-1 rounds are executed in the loop below. 390 | for(round = 1; round < Nr; ++round) 391 | { 392 | SubBytes(); 393 | ShiftRows(); 394 | MixColumns(); 395 | AddRoundKey(round); 396 | } 397 | 398 | // The last round is given below. 399 | // The MixColumns function is not here in the last round. 400 | SubBytes(); 401 | ShiftRows(); 402 | AddRoundKey(Nr); 403 | } 404 | 405 | static void InvCipher(void) 406 | { 407 | uint8_t round=0; 408 | 409 | // Add the First round key to the state before starting the rounds. 410 | AddRoundKey(Nr); 411 | 412 | // There will be Nr rounds. 413 | // The first Nr-1 rounds are identical. 414 | // These Nr-1 rounds are executed in the loop below. 415 | for(round=Nr-1;round>0;round--) 416 | { 417 | InvShiftRows(); 418 | InvSubBytes(); 419 | AddRoundKey(round); 420 | InvMixColumns(); 421 | } 422 | 423 | // The last round is given below. 424 | // The MixColumns function is not here in the last round. 425 | InvShiftRows(); 426 | InvSubBytes(); 427 | AddRoundKey(0); 428 | } 429 | 430 | static void BlockCopy(uint8_t* output, uint8_t* input) 431 | { 432 | uint8_t i; 433 | for (i=0;i 7 | #include 8 | #include "beast_log.h" 9 | #include "beast_module.h" 10 | 11 | static const char base64_table[] = 12 | { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 13 | 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 14 | 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 15 | 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 16 | '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/', '\0' 17 | }; 18 | 19 | static const char base64_pad = '='; 20 | 21 | static const short base64_reverse_table[256] = { 22 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 23 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 24 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, 25 | 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, 26 | -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 27 | 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, 28 | -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 29 | 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1, 30 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 31 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 32 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 33 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 34 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 35 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 36 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 37 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 38 | }; 39 | 40 | char *base64_encode(char *str, int length, int *ret_length) 41 | { 42 | char *current = str; 43 | char *p; 44 | char *result; 45 | int alen; 46 | 47 | if ((length + 2) < 0 48 | || ((length + 2) / 3) >= (1 << (sizeof(int) * 8 - 2))) 49 | { 50 | if (ret_length != NULL) { 51 | *ret_length = 0; 52 | } 53 | return NULL; 54 | } 55 | 56 | alen = ((length + 2) / 3) * 4 + 1; 57 | 58 | result = malloc(alen); 59 | if (!result) { 60 | beast_write_log(beast_log_error, 61 | "Out of memory when allocate `%d' size by encrypt(BASE64)", alen); 62 | return NULL; 63 | } 64 | 65 | p = result; 66 | 67 | while (length > 2) { /* keep going until we have less than 24 bits */ 68 | *p++ = base64_table[current[0] >> 2]; 69 | *p++ = base64_table[((current[0] & 0x03) << 4) + (current[1] >> 4)]; 70 | *p++ = base64_table[((current[1] & 0x0f) << 2) + (current[2] >> 6)]; 71 | *p++ = base64_table[current[2] & 0x3f]; 72 | 73 | current += 3; 74 | length -= 3; /* we just handle 3 octets of data */ 75 | } 76 | 77 | /* now deal with the tail end of things */ 78 | if (length != 0) { 79 | *p++ = base64_table[current[0] >> 2]; 80 | if (length > 1) { 81 | *p++ = base64_table[((current[0] & 0x03) << 4) + (current[1] >> 4)]; 82 | *p++ = base64_table[(current[1] & 0x0f) << 2]; 83 | *p++ = base64_pad; 84 | } else { 85 | *p++ = base64_table[(current[0] & 0x03) << 4]; 86 | *p++ = base64_pad; 87 | *p++ = base64_pad; 88 | } 89 | } 90 | 91 | if (ret_length != NULL) { 92 | *ret_length = (int)(p - result); 93 | } 94 | 95 | *p = '\0'; 96 | 97 | return result; 98 | } 99 | 100 | 101 | char *base64_decode(char *str, int length, int *ret_length) 102 | { 103 | char *current = str; 104 | int ch, i = 0, j = 0, k; 105 | char *result; 106 | 107 | result = malloc(length + 1); 108 | if (result == NULL) { 109 | beast_write_log(beast_log_error, 110 | "Out of memory when allocate `%d' size by decrypt(BASE64)", length+1); 111 | return NULL; 112 | } 113 | 114 | /* run through the whole string, converting as we go */ 115 | while ((ch = *current++) != '\0' && length-- > 0) { 116 | if (ch == base64_pad) break; 117 | 118 | ch = base64_reverse_table[ch]; 119 | if (ch < 0) continue; 120 | 121 | switch(i % 4) { 122 | case 0: 123 | result[j] = ch << 2; 124 | break; 125 | case 1: 126 | result[j++] |= ch >> 4; 127 | result[j] = (ch & 0x0f) << 4; 128 | break; 129 | case 2: 130 | result[j++] |= ch >>2; 131 | result[j] = (ch & 0x03) << 6; 132 | break; 133 | case 3: 134 | result[j++] |= ch; 135 | break; 136 | } 137 | i++; 138 | } 139 | 140 | k = j; 141 | /* mop things up if we ended on a boundary */ 142 | if (ch == base64_pad) { 143 | switch(i % 4) { 144 | case 1: 145 | free(result); 146 | return NULL; 147 | case 2: 148 | k++; 149 | case 3: 150 | result[k++] = 0; 151 | } 152 | } 153 | 154 | if(ret_length) { 155 | *ret_length = j; 156 | } 157 | 158 | result[j] = '\0'; 159 | 160 | return result; 161 | } 162 | 163 | 164 | int base64_encrypt_handler(char *inbuf, int len, 165 | char **outbuf, int *outlen) 166 | { 167 | char *result; 168 | int reslen; 169 | 170 | result = base64_encode(inbuf, len, &reslen); 171 | if (!result) { 172 | return -1; 173 | } 174 | 175 | *outbuf = result; 176 | *outlen = reslen; 177 | 178 | return 0; 179 | } 180 | 181 | 182 | int base64_decrypt_handler(char *inbuf, int len, 183 | char **outbuf, int *outlen) 184 | { 185 | char *result; 186 | int reslen; 187 | 188 | result = base64_decode(inbuf, len, &reslen); 189 | if (!result) { 190 | return -1; 191 | } 192 | 193 | *outbuf = result; 194 | *outlen = reslen; 195 | 196 | return 0; 197 | } 198 | 199 | 200 | void base64_free_handler(void *ptr) 201 | { 202 | if (ptr) { 203 | free(ptr); 204 | } 205 | } 206 | 207 | 208 | struct beast_ops base64_handler_ops = { 209 | "base64-algo", 210 | base64_encrypt_handler, 211 | base64_decrypt_handler, 212 | base64_free_handler, 213 | NULL 214 | }; 215 | -------------------------------------------------------------------------------- /beast.c: -------------------------------------------------------------------------------- 1 | /* 2 | +----------------------------------------------------------------------+ 3 | | PHP Version 5 | 4 | +----------------------------------------------------------------------+ 5 | | Copyright (c) 1997-2007 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 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: Liexusong | 16 | | maben | 17 | +----------------------------------------------------------------------+ 18 | */ 19 | 20 | /* $Id: header,v 1.16.2.1.2.1 2007/01/01 19:32:09 iliaa Exp $ */ 21 | 22 | #ifdef HAVE_CONFIG_H 23 | #include "config.h" 24 | #endif 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | typedef struct yy_buffer_state *YY_BUFFER_STATE; 33 | 34 | #include "zend.h" 35 | #include "zend_operators.h" 36 | #include "zend_globals.h" 37 | #include "zend_highlight.h" 38 | #include "zend_language_scanner.h" 39 | 40 | #include "zend_API.h" 41 | #include "zend_compile.h" 42 | 43 | #include "php.h" 44 | #include "php_main.h" 45 | #include "php_globals.h" 46 | #include "php_ini.h" 47 | #include "main/SAPI.h" 48 | #include "ext/standard/info.h" 49 | #include "ext/date/php_date.h" 50 | #include "php_streams.h" 51 | #include "php_beast.h" 52 | #include "beast_mm.h" 53 | #include "cache.h" 54 | #include "beast_log.h" 55 | #include "beast_module.h" 56 | #include "file_handler.h" 57 | 58 | #ifdef PHP_WIN32 59 | #include 60 | #include 61 | #pragma comment(lib, PHP_LIB) 62 | #pragma comment(lib, "Iphlpapi.lib") 63 | #else 64 | #include 65 | #include 66 | #include 67 | #endif 68 | 69 | #if ZEND_MODULE_API_NO >= 20151012 70 | # define BEAST_RETURN_STRING(str, dup) RETURN_STRING(str) 71 | #else 72 | # define BEAST_RETURN_STRING(str, dup) RETURN_STRING(str, dup) 73 | #endif 74 | 75 | #define BEAST_VERSION "2.7" 76 | #define DEFAULT_CACHE_SIZE 10485760 /* 10MB */ 77 | #define HEADER_MAX_SIZE 256 78 | #define INT_SIZE (sizeof(int)) 79 | 80 | extern struct beast_ops *ops_handler_list[]; 81 | 82 | /* 83 | * Global vaiables for extension 84 | */ 85 | char *beast_log_file = NULL; 86 | char *beast_log_user = NULL; 87 | int log_level = beast_log_notice; 88 | int beast_ncpu = 1; 89 | int beast_is_root = 0; 90 | int beast_pid = -1; 91 | 92 | /* True global resources - no need for thread safety here */ 93 | static zend_op_array* (*old_compile_file)(zend_file_handle*, int TSRMLS_DC); 94 | 95 | static int le_beast; 96 | static int max_cache_size = DEFAULT_CACHE_SIZE; 97 | static int beast_enable = 1; 98 | static int beast_max_filesize = 0; 99 | static char *local_networkcard = NULL; 100 | static int beast_now_time = 0; 101 | static int log_normal_file = 0; 102 | static char *beast_debug_path = NULL; 103 | static int beast_debug_mode = 0; 104 | 105 | /* {{{ beast_functions[] 106 | * 107 | * Every user visible function must have an entry in beast_functions[]. 108 | */ 109 | zend_function_entry beast_functions[] = { 110 | PHP_FE(beast_encode_file, NULL) 111 | PHP_FE(beast_avail_cache, NULL) 112 | PHP_FE(beast_support_filesize, NULL) 113 | PHP_FE(beast_file_expire, NULL) 114 | PHP_FE(beast_clean_cache, NULL) 115 | {NULL, NULL, NULL} /* Must be the last line in beast_functions[] */ 116 | }; 117 | /* }}} */ 118 | 119 | /* {{{ beast_module_entry 120 | */ 121 | zend_module_entry beast_module_entry = { 122 | #if ZEND_MODULE_API_NO >= 20010901 123 | STANDARD_MODULE_HEADER, 124 | #endif 125 | "beast", 126 | beast_functions, 127 | PHP_MINIT(beast), 128 | PHP_MSHUTDOWN(beast), 129 | PHP_RINIT(beast), 130 | PHP_RSHUTDOWN(beast), 131 | PHP_MINFO(beast), 132 | #if ZEND_MODULE_API_NO >= 20010901 133 | BEAST_VERSION, /* Replace with version number for your extension */ 134 | #endif 135 | STANDARD_MODULE_PROPERTIES 136 | }; 137 | /* }}} */ 138 | 139 | #ifdef COMPILE_DL_BEAST 140 | ZEND_GET_MODULE(beast) 141 | #endif 142 | 143 | extern struct file_handler tmpfile_handler; 144 | extern struct file_handler pipe_handler; 145 | 146 | static struct file_handler *default_file_handler = NULL; 147 | static struct file_handler *file_handlers[] = { 148 | &tmpfile_handler, 149 | #ifndef PHP_WIN32 150 | &pipe_handler, 151 | #endif 152 | NULL 153 | }; 154 | 155 | extern char encrypt_file_header_sign[]; 156 | extern int encrypt_file_header_length; 157 | extern char *file_handler_switch; 158 | 159 | #define swab32(x) \ 160 | ((x & 0x000000FF) << 24 | (x & 0x0000FF00) << 8 | \ 161 | (x & 0x00FF0000) >> 8 | (x & 0xFF000000) >> 24) 162 | 163 | 164 | #define little_endian() (!big_endian()) 165 | 166 | static int big_endian() 167 | { 168 | unsigned short num = 0x1122; 169 | 170 | if(*((unsigned char *)&num) == 0x11) { 171 | return 1; 172 | } 173 | 174 | return 0; 175 | } 176 | 177 | 178 | int filter_code_comments(char *filename, zval *retval TSRMLS_DC) 179 | { 180 | zend_lex_state original_lex_state; 181 | zend_file_handle file_handle = {0}; 182 | 183 | #if PHP_API_VERSION > 20090626 184 | 185 | php_output_start_default(TSRMLS_C); 186 | 187 | file_handle.type = ZEND_HANDLE_FILENAME; 188 | file_handle.filename = filename; 189 | file_handle.free_filename = 0; 190 | file_handle.opened_path = NULL; 191 | 192 | zend_save_lexical_state(&original_lex_state TSRMLS_CC); 193 | if (open_file_for_scanning(&file_handle TSRMLS_CC) == FAILURE) { 194 | zend_restore_lexical_state(&original_lex_state TSRMLS_CC); 195 | php_output_end(TSRMLS_C); 196 | return -1; 197 | } 198 | 199 | zend_strip(TSRMLS_C); 200 | 201 | zend_destroy_file_handle(&file_handle TSRMLS_CC); 202 | zend_restore_lexical_state(&original_lex_state TSRMLS_CC); 203 | 204 | php_output_get_contents(retval TSRMLS_CC); 205 | php_output_discard(TSRMLS_C); 206 | 207 | #else 208 | 209 | file_handle.type = ZEND_HANDLE_FILENAME; 210 | file_handle.filename = filename; 211 | file_handle.free_filename = 0; 212 | file_handle.opened_path = NULL; 213 | 214 | zend_save_lexical_state(&original_lex_state TSRMLS_CC); 215 | if (open_file_for_scanning(&file_handle TSRMLS_CC) == FAILURE) { 216 | zend_restore_lexical_state(&original_lex_state TSRMLS_CC); 217 | return -1; 218 | } 219 | 220 | php_start_ob_buffer(NULL, 0, 1 TSRMLS_CC); 221 | 222 | zend_strip(TSRMLS_C); 223 | 224 | zend_destroy_file_handle(&file_handle TSRMLS_CC); 225 | zend_restore_lexical_state(&original_lex_state TSRMLS_CC); 226 | 227 | php_ob_get_buffer(retval TSRMLS_CC); 228 | php_end_ob_buffer(0, 0 TSRMLS_CC); 229 | 230 | #endif 231 | 232 | return 0; 233 | } 234 | 235 | 236 | struct beast_ops *beast_get_encrypt_algo(int type) 237 | { 238 | int index = type - 1; 239 | 240 | if (index < 0 || index >= BEAST_ENCRYPT_TYPE_ERROR) { 241 | return ops_handler_list[0]; 242 | } 243 | 244 | return ops_handler_list[index]; 245 | } 246 | 247 | 248 | /***************************************************************************** 249 | * * 250 | * Encrypt a plain text file and output a cipher file * 251 | * * 252 | *****************************************************************************/ 253 | 254 | int encrypt_file(const char *inputfile, 255 | const char *outputfile, int expire, 256 | int encrypt_type TSRMLS_DC) 257 | { 258 | php_stream *output_stream = NULL; 259 | zval codes; 260 | int need_free_code = 0; 261 | char *inbuf, *outbuf; 262 | int inlen, outlen, dumplen, expireval, dumptype; 263 | struct beast_ops *encrypt_ops = beast_get_encrypt_algo(encrypt_type); 264 | 265 | /* Get php codes from script file */ 266 | if (filter_code_comments((char *)inputfile, &codes TSRMLS_CC) == -1) { 267 | php_error_docref(NULL TSRMLS_CC, E_ERROR, 268 | "Unable get codes from php file `%s'", inputfile); 269 | return -1; 270 | } 271 | 272 | need_free_code = 1; 273 | 274 | #if ZEND_MODULE_API_NO >= 20151012 275 | inlen = Z_STRLEN(codes); 276 | inbuf = Z_STRVAL(codes); 277 | #else 278 | inlen = codes.value.str.len; 279 | inbuf = codes.value.str.val; 280 | #endif 281 | 282 | /* PHP file size can not large than beast_max_filesize */ 283 | if (beast_max_filesize > 0 && inlen > beast_max_filesize) { 284 | return -1; 285 | } 286 | 287 | /* Open output file */ 288 | #if ZEND_MODULE_API_NO >= 20151012 289 | output_stream = php_stream_open_wrapper((char *)outputfile, "w+", 290 | IGNORE_URL_WIN|REPORT_ERRORS, NULL); 291 | #else 292 | output_stream = php_stream_open_wrapper((char *)outputfile, "w+", 293 | ENFORCE_SAFE_MODE|REPORT_ERRORS, NULL); 294 | #endif 295 | 296 | if (!output_stream) { 297 | php_error_docref(NULL TSRMLS_CC, E_ERROR, 298 | "Unable to open file `%s'", outputfile); 299 | goto failed; 300 | } 301 | 302 | /* if computer is little endian, change file size to big endian */ 303 | if (little_endian()) { 304 | dumplen = swab32(inlen); 305 | expireval = swab32(expire); 306 | dumptype = swab32(encrypt_type); 307 | 308 | } else { 309 | dumplen = inlen; 310 | expireval = expire; 311 | dumptype = encrypt_type; 312 | } 313 | 314 | php_stream_write(output_stream, 315 | encrypt_file_header_sign, encrypt_file_header_length); 316 | php_stream_write(output_stream, (const char *)&dumplen, INT_SIZE); 317 | php_stream_write(output_stream, (const char *)&expireval, INT_SIZE); 318 | php_stream_write(output_stream, (const char *)&dumptype, INT_SIZE); 319 | 320 | if (encrypt_ops->encrypt(inbuf, inlen, &outbuf, &outlen) == -1) { 321 | php_error_docref(NULL TSRMLS_CC, E_ERROR, 322 | "Unable to encrypt file `%s'", outputfile); 323 | goto failed; 324 | } 325 | 326 | php_stream_write(output_stream, outbuf, outlen); 327 | php_stream_close(output_stream); 328 | zval_dtor(&codes); 329 | 330 | if (encrypt_ops->free) { 331 | encrypt_ops->free(outbuf); 332 | } 333 | 334 | return 0; 335 | 336 | failed: 337 | if (output_stream) 338 | php_stream_close(output_stream); 339 | if (need_free_code) 340 | zval_dtor(&codes); 341 | return -1; 342 | } 343 | 344 | 345 | /***************************************************************************** 346 | * * 347 | * Decrypt a cipher text file and output plain buffer * 348 | * * 349 | *****************************************************************************/ 350 | 351 | int decrypt_file(const char *filename, int stream, 352 | char **retbuf, int *retlen, int *free_buffer, 353 | struct beast_ops **ret_encrypt TSRMLS_DC) 354 | { 355 | struct stat stat_ssb; 356 | cache_key_t findkey; 357 | cache_item_t *cache; 358 | int reallen, bodylen, expire; 359 | char header[HEADER_MAX_SIZE]; 360 | int headerlen; 361 | char *buffer = NULL, *decbuf; 362 | int declen; 363 | int entype; 364 | struct beast_ops *encrypt_ops; 365 | int retval = -1; 366 | int n = 0; 367 | int filesize = 0; 368 | 369 | #ifdef PHP_WIN32 370 | ULARGE_INTEGER ull; 371 | BY_HANDLE_FILE_INFORMATION fileinfo; 372 | HANDLE hFile = (HANDLE)_get_osfhandle(stream); 373 | if (!GetFileInformationByHandle(hFile, &fileinfo)) { 374 | beast_write_log(beast_log_error, 375 | "Failed to get file information from file `%s'", filename); 376 | retval = -1; 377 | goto failed; 378 | } 379 | findkey.device = fileinfo.dwVolumeSerialNumber; 380 | findkey.inode = fileinfo.nFileIndexHigh * (MAXDWORD + 1) + fileinfo.nFileIndexLow; 381 | 382 | 383 | ull.LowPart = fileinfo.ftLastWriteTime.dwLowDateTime; 384 | ull.HighPart = fileinfo.ftLastWriteTime.dwHighDateTime; 385 | 386 | findkey.mtime = ull.QuadPart / 10000000ULL - 11644473600ULL; 387 | filesize = fileinfo.nFileSizeHigh * (MAXDWORD + 1) + fileinfo.nFileSizeLow; 388 | 389 | #else 390 | if (fstat(stream, &stat_ssb) == -1) { 391 | beast_write_log(beast_log_error, 392 | "Failed to readed state buffer from file `%s'", filename); 393 | retval = -1; 394 | goto failed; 395 | } 396 | findkey.device = stat_ssb.st_dev; 397 | findkey.inode = stat_ssb.st_ino; 398 | findkey.mtime = stat_ssb.st_mtime; 399 | filesize = stat_ssb.st_size; 400 | #endif 401 | 402 | /** 403 | * 1) 1 int is dump length, 404 | * 2) 1 int is expire time. 405 | * 3) 1 int is encrypt type. 406 | */ 407 | headerlen = encrypt_file_header_length + INT_SIZE * 3; 408 | 409 | if (filesize < headerlen) { /* This file is not a encrypt file */ 410 | retval = -1; 411 | goto failed; 412 | } 413 | 414 | cache = beast_cache_find(&findkey); 415 | 416 | if (cache != NULL) { /* Found cache */ 417 | *retbuf = beast_cache_data(cache); 418 | *retlen = beast_cache_size(cache); 419 | return 0; 420 | } 421 | 422 | *free_buffer = 0; /* Set free buffer flag to false */ 423 | 424 | /* Not found cache and decrypt file */ 425 | 426 | if ((n = read(stream, header, headerlen)) != headerlen) { 427 | beast_write_log(beast_log_error, 428 | "Failed to readed header from file `%s', headerlen:%d, readlen:%d", 429 | filename, headerlen, n); 430 | retval = -1; 431 | goto failed; 432 | } 433 | 434 | /* Not a encrypted file */ 435 | if (memcmp(header, 436 | encrypt_file_header_sign, 437 | encrypt_file_header_length)) 438 | { 439 | if (log_normal_file) { 440 | beast_write_log(beast_log_error, 441 | "File `%s' isn't a encrypted file", filename); 442 | } 443 | 444 | retval = -1; 445 | goto failed; 446 | } 447 | 448 | /* Real php script file's size */ 449 | reallen = *((int *)&header[encrypt_file_header_length]); 450 | expire = *((int *)&header[encrypt_file_header_length + INT_SIZE]); 451 | entype = *((int *)&header[encrypt_file_header_length + 2 * INT_SIZE]); 452 | 453 | if (little_endian()) { 454 | reallen = swab32(reallen); 455 | expire = swab32(expire); 456 | entype = swab32(entype); 457 | } 458 | 459 | /* Check file size is vaild */ 460 | if (beast_max_filesize > 0 && reallen > beast_max_filesize) { 461 | beast_write_log(beast_log_error, 462 | "File size `%d' out of max size `%d'", 463 | reallen, beast_max_filesize); 464 | retval = -1; 465 | goto failed; 466 | } 467 | 468 | /* Check file is not expired */ 469 | if (expire > 0 && expire < beast_now_time) { 470 | beast_write_log(beast_log_error, "File `%s' was expired", filename); 471 | retval = -2; 472 | goto failed; 473 | } 474 | 475 | *ret_encrypt = encrypt_ops = beast_get_encrypt_algo(entype); 476 | 477 | /** 478 | * How many bytes would be read from encrypt file, 479 | * subtract encrypt file's header size, 480 | * because we had read the header yet. 481 | */ 482 | 483 | bodylen = filesize - headerlen; 484 | 485 | /* 1) Alloc memory for decrypt file */ 486 | if (!(buffer = malloc(bodylen))) { 487 | beast_write_log(beast_log_error, 488 | "Failed to alloc memory to file `%s' size `%d'", 489 | filename, bodylen); 490 | retval = -1; 491 | goto failed; 492 | } 493 | 494 | /* 2) Read file stream */ 495 | if (read(stream, buffer, bodylen) != bodylen) { 496 | beast_write_log(beast_log_error, 497 | "Failed to readed stream from file `%s'", filename); 498 | retval = -1; 499 | goto failed; 500 | } 501 | 502 | /* 3) Decrypt file stream */ 503 | if (encrypt_ops->decrypt(buffer, bodylen, &decbuf, &declen) == -1) { 504 | beast_write_log(beast_log_error, 505 | "Failed to decrypted file `%s', using `%s' handler", 506 | filename, encrypt_ops->name); 507 | retval = -1; 508 | goto failed; 509 | } 510 | 511 | free(buffer); /* Buffer don't need right now and free it */ 512 | 513 | findkey.fsize = reallen; /* How many size would we alloc from cache */ 514 | 515 | /* Try to add decrypt result to cache */ 516 | if ((cache = beast_cache_create(&findkey))) { 517 | 518 | memcpy(beast_cache_data(cache), decbuf, reallen); 519 | 520 | cache = beast_cache_push(cache); /* Push cache into hash table */ 521 | 522 | *retbuf = beast_cache_data(cache); 523 | *retlen = beast_cache_size(cache); 524 | 525 | if (encrypt_ops->free) { 526 | encrypt_ops->free(decbuf); 527 | } 528 | 529 | } else { /* Return raw buffer and we need free after PHP finished */ 530 | 531 | *retbuf = decbuf; 532 | *retlen = reallen; 533 | 534 | *free_buffer = 1; 535 | } 536 | 537 | return 0; 538 | 539 | failed: 540 | if (buffer) { 541 | free(buffer); 542 | } 543 | 544 | return retval; 545 | } 546 | 547 | 548 | int beast_super_mkdir(char *path) 549 | { 550 | char *head, *last; 551 | char temp[1024]; 552 | 553 | for (head = last = path; *last; last++) { 554 | 555 | if (*last == '/') { 556 | 557 | if (last > head) { 558 | 559 | memset(temp, 0, 1024); 560 | memcpy(temp, path, last - path); 561 | 562 | if (access(temp, F_OK) == -1) { 563 | if (mkdir(temp, 0777) != 0) { 564 | beast_write_log(beast_log_error, 565 | "Failed to make new directory `%s'", 566 | temp); 567 | return -1; 568 | } 569 | } 570 | } 571 | 572 | head = last + 1; 573 | } 574 | } 575 | 576 | return 0; 577 | } 578 | 579 | 580 | /* 581 | * CGI compile file 582 | */ 583 | zend_op_array * 584 | cgi_compile_file(zend_file_handle *h, int type TSRMLS_DC) 585 | { 586 | #if ZEND_MODULE_API_NO >= 20151012 587 | zend_string *opened_path; 588 | #else 589 | char *opened_path; 590 | #endif 591 | char *buf; 592 | int fd; 593 | FILE *fp = NULL; 594 | int size, free_buffer = 0; 595 | int retval; 596 | struct beast_ops *ops = NULL; 597 | int destroy_file_handler = 0; 598 | 599 | #if 0 600 | fp = zend_fopen(h->filename, &opened_path TSRMLS_CC); 601 | #else 602 | fp = fopen(h->filename, "rb"); 603 | #endif 604 | if (fp != NULL) { 605 | fd = fileno(fp); 606 | } else { 607 | goto final; 608 | } 609 | 610 | retval = decrypt_file(h->filename, fd, &buf, &size, 611 | &free_buffer, &ops TSRMLS_CC); 612 | if (retval == -2) { 613 | php_error_docref(NULL TSRMLS_CC, E_ERROR, 614 | "This program was expired, please contact administrator"); 615 | return NULL; 616 | } 617 | 618 | if (retval == -1) { 619 | #if BEAST_EXECUTE_NORMAL_SCRIPT 620 | goto final; 621 | #else 622 | php_error_docref(NULL TSRMLS_CC, E_ERROR, 623 | "Not allow execute normal PHP script"); 624 | return NULL; 625 | #endif 626 | } 627 | 628 | #if BEAST_DEBUG_MODE 629 | 630 | if (beast_debug_mode && beast_debug_path) { 631 | 632 | if (access(beast_debug_path, F_OK) == 0) { 633 | 634 | char realpath[1024]; 635 | 636 | sprintf(realpath, "%s/%s", beast_debug_path, h->filename); 637 | 638 | if (beast_super_mkdir(realpath) == 0) { 639 | 640 | FILE *debug_fp = fopen(realpath, "w+"); 641 | 642 | if (debug_fp) { 643 | fwrite(buf, size, 1, debug_fp); 644 | fclose(debug_fp); 645 | } 646 | } 647 | } 648 | } 649 | 650 | #endif 651 | 652 | if (default_file_handler->open(default_file_handler) == -1 || 653 | default_file_handler->write(default_file_handler, buf, size) == -1 || 654 | default_file_handler->rewind(default_file_handler) == -1) 655 | { 656 | destroy_file_handler = 1; 657 | goto final; 658 | } 659 | 660 | if (h->type == ZEND_HANDLE_FP) fclose(h->handle.fp); 661 | #ifdef ZEND_HANDLE_FD 662 | if (h->type == ZEND_HANDLE_FD) close(h->handle.fd); 663 | #endif 664 | /* 665 | * Get file handler and free context 666 | */ 667 | switch (default_file_handler->type) { 668 | case BEAST_FILE_HANDLER_FP: 669 | h->type = ZEND_HANDLE_FP; 670 | h->handle.fp = default_file_handler->get_fp(default_file_handler); 671 | break; 672 | #ifdef ZEND_HANDLE_FD 673 | case BEAST_FILE_HANDLER_FD: 674 | h->type = ZEND_HANDLE_FD; 675 | h->handle.fd = default_file_handler->get_fd(default_file_handler); 676 | break; 677 | #endif 678 | } 679 | 680 | final: 681 | if (free_buffer && ops) { 682 | if (ops->free) { 683 | ops->free(buf); 684 | } 685 | } 686 | 687 | if (fp) fclose(fp); 688 | 689 | if (destroy_file_handler) { 690 | default_file_handler->destroy(default_file_handler); 691 | } 692 | 693 | return old_compile_file(h, type TSRMLS_CC); 694 | } 695 | 696 | 697 | /* Configure entries */ 698 | 699 | void beast_atoi(const char *str, int *ret, int *len) 700 | { 701 | const char *ptr = str; 702 | char ch; 703 | int absolute = 1; 704 | int rlen, result; 705 | 706 | ch = *ptr; 707 | 708 | if (ch == '-') { 709 | absolute = -1; 710 | ++ptr; 711 | } else if (ch == '+') { 712 | absolute = 1; 713 | ++ptr; 714 | } 715 | 716 | for (rlen = 0, result = 0; *ptr != '\0'; ptr++) { 717 | ch = *ptr; 718 | 719 | if (ch >= '0' && ch <= '9') { 720 | result = result * 10 + (ch - '0'); 721 | rlen++; 722 | } else { 723 | break; 724 | } 725 | } 726 | 727 | if (ret) *ret = absolute * result; 728 | if (len) *len = rlen; 729 | } 730 | 731 | ZEND_INI_MH(php_beast_cache_size) 732 | { 733 | #if ZEND_MODULE_API_NO >= 20151012 734 | 735 | char *value = ZSTR_VAL(new_value); 736 | int length = ZSTR_LEN(new_value); 737 | int retlen; 738 | 739 | if (length == 0) { 740 | return FAILURE; 741 | } 742 | 743 | beast_atoi(value, &max_cache_size, &retlen); 744 | 745 | if (retlen > 0 && retlen < length) { 746 | switch (value[retlen]) { 747 | case 'k': 748 | case 'K': 749 | max_cache_size *= 1024; 750 | break; 751 | case 'm': 752 | case 'M': 753 | max_cache_size *= 1024 * 1024; 754 | break; 755 | case 'g': 756 | case 'G': 757 | max_cache_size *= 1024 * 1024 * 1024; 758 | break; 759 | default: 760 | return FAILURE; 761 | } 762 | 763 | } else if (retlen == 0) { 764 | return FAILURE; 765 | } 766 | 767 | return SUCCESS; 768 | 769 | #else 770 | 771 | int len; 772 | 773 | if (new_value_length == 0) { 774 | return FAILURE; 775 | } 776 | 777 | beast_atoi(new_value, &max_cache_size, &len); 778 | 779 | if (len > 0 && len < new_value_length) { 780 | switch (new_value[len]) { 781 | case 'k': 782 | case 'K': 783 | max_cache_size *= 1024; 784 | break; 785 | case 'm': 786 | case 'M': 787 | max_cache_size *= 1024 * 1024; 788 | break; 789 | case 'g': 790 | case 'G': 791 | max_cache_size *= 1024 * 1024 * 1024; 792 | break; 793 | default: 794 | return FAILURE; 795 | } 796 | 797 | } else if (len == 0) { 798 | return FAILURE; 799 | } 800 | 801 | return SUCCESS; 802 | 803 | #endif 804 | } 805 | 806 | ZEND_INI_MH(php_beast_log_file) 807 | { 808 | #if ZEND_MODULE_API_NO >= 20151012 809 | 810 | if (ZSTR_LEN(new_value) == 0) { 811 | return SUCCESS; 812 | } 813 | 814 | beast_log_file = estrdup(ZSTR_VAL(new_value)); 815 | if (beast_log_file == NULL) { 816 | return FAILURE; 817 | } 818 | 819 | return SUCCESS; 820 | 821 | #else 822 | 823 | if (new_value_length == 0) { 824 | return SUCCESS; 825 | } 826 | 827 | beast_log_file = strdup(new_value); 828 | if (beast_log_file == NULL) { 829 | return FAILURE; 830 | } 831 | 832 | return SUCCESS; 833 | 834 | #endif 835 | } 836 | 837 | 838 | ZEND_INI_MH(php_beast_log_user) 839 | { 840 | #if ZEND_MODULE_API_NO >= 20151012 841 | 842 | if (ZSTR_LEN(new_value) == 0) { 843 | return SUCCESS; 844 | } 845 | 846 | beast_log_user = estrdup(ZSTR_VAL(new_value)); 847 | if (beast_log_user == NULL) { 848 | return FAILURE; 849 | } 850 | 851 | return SUCCESS; 852 | 853 | #else 854 | 855 | if (new_value_length == 0) { 856 | return SUCCESS; 857 | } 858 | 859 | beast_log_user = strdup(new_value); 860 | if (beast_log_user == NULL) { 861 | return FAILURE; 862 | } 863 | 864 | return SUCCESS; 865 | 866 | #endif 867 | } 868 | 869 | ZEND_INI_MH(php_beast_log_level) 870 | { 871 | char *level = NULL; 872 | #if ZEND_MODULE_API_NO >= 20151012 873 | 874 | if (ZSTR_LEN(new_value) == 0) { 875 | return SUCCESS; 876 | } 877 | 878 | level = ZSTR_VAL(new_value); 879 | 880 | #else 881 | 882 | if (new_value_length == 0) { 883 | return SUCCESS; 884 | } 885 | 886 | level = new_value; 887 | 888 | #endif 889 | if (level == NULL) { 890 | return FAILURE; 891 | } 892 | 893 | if (strcasecmp(level, "debug") == 0) { 894 | log_level = beast_log_debug; 895 | } else if (strcasecmp(level, "notice") == 0) { 896 | log_level = beast_log_notice; 897 | } else if (strcasecmp(level, "error") == 0) { 898 | log_level = beast_log_error; 899 | } else { 900 | return FAILURE; 901 | } 902 | 903 | return SUCCESS; 904 | } 905 | 906 | 907 | ZEND_INI_MH(php_beast_enable) 908 | { 909 | #if ZEND_MODULE_API_NO >= 20151012 910 | 911 | if (ZSTR_LEN(new_value) == 0) { 912 | return FAILURE; 913 | } 914 | 915 | if (!strcasecmp(ZSTR_VAL(new_value), "on") 916 | || !strcmp(ZSTR_VAL(new_value), "1")) 917 | { 918 | beast_enable = 1; 919 | } else { 920 | beast_enable = 0; 921 | } 922 | 923 | return SUCCESS; 924 | 925 | #else 926 | 927 | if (new_value_length == 0) { 928 | return FAILURE; 929 | } 930 | 931 | if (!strcasecmp(new_value, "on") 932 | || !strcmp(new_value, "1")) 933 | { 934 | beast_enable = 1; 935 | } else { 936 | beast_enable = 0; 937 | } 938 | 939 | return SUCCESS; 940 | #endif 941 | } 942 | 943 | 944 | ZEND_INI_MH(php_beast_set_networkcard) 945 | { 946 | #if ZEND_MODULE_API_NO >= 20151012 947 | 948 | if (ZSTR_LEN(new_value) == 0) { 949 | return FAILURE; 950 | } 951 | 952 | local_networkcard = estrdup(ZSTR_VAL(new_value)); 953 | if (local_networkcard == NULL) { 954 | return FAILURE; 955 | } 956 | 957 | return SUCCESS; 958 | 959 | #else 960 | 961 | if (new_value_length == 0) { 962 | return FAILURE; 963 | } 964 | 965 | local_networkcard = strdup(new_value); 966 | if (local_networkcard == NULL) { 967 | return FAILURE; 968 | } 969 | 970 | return SUCCESS; 971 | 972 | #endif 973 | } 974 | 975 | 976 | ZEND_INI_MH(php_beast_set_log_normal_file) 977 | { 978 | #if ZEND_MODULE_API_NO >= 20151012 979 | 980 | if (ZSTR_LEN(new_value) == 0) { 981 | return FAILURE; 982 | } 983 | 984 | if (!strcasecmp(ZSTR_VAL(new_value), "on") 985 | || !strcmp(ZSTR_VAL(new_value), "1")) 986 | { 987 | log_normal_file = 1; 988 | } else { 989 | log_normal_file = 0; 990 | } 991 | 992 | return SUCCESS; 993 | 994 | #else 995 | 996 | if (new_value_length == 0) { 997 | return FAILURE; 998 | } 999 | 1000 | if (!strcasecmp(new_value, "on") 1001 | || !strcmp(new_value, "1")) 1002 | { 1003 | log_normal_file = 1; 1004 | } else { 1005 | log_normal_file = 0; 1006 | } 1007 | 1008 | return SUCCESS; 1009 | 1010 | #endif 1011 | } 1012 | 1013 | 1014 | ZEND_INI_MH(php_beast_debug_path) 1015 | { 1016 | #if ZEND_MODULE_API_NO >= 20151012 1017 | 1018 | if (ZSTR_LEN(new_value) == 0) { 1019 | return SUCCESS; 1020 | } 1021 | 1022 | beast_debug_path = estrdup(ZSTR_VAL(new_value)); 1023 | if (beast_debug_path == NULL) { 1024 | return FAILURE; 1025 | } 1026 | 1027 | return SUCCESS; 1028 | 1029 | #else 1030 | 1031 | if (new_value_length == 0) { 1032 | return SUCCESS; 1033 | } 1034 | 1035 | beast_debug_path = strdup(new_value); 1036 | if (beast_debug_path == NULL) { 1037 | return FAILURE; 1038 | } 1039 | 1040 | return SUCCESS; 1041 | 1042 | #endif 1043 | } 1044 | 1045 | 1046 | ZEND_INI_MH(php_beast_debug_mode) 1047 | { 1048 | #if ZEND_MODULE_API_NO >= 20151012 1049 | 1050 | if (ZSTR_LEN(new_value) == 0) { 1051 | return FAILURE; 1052 | } 1053 | 1054 | if (!strcasecmp(ZSTR_VAL(new_value), "on") 1055 | || !strcmp(ZSTR_VAL(new_value), "1")) 1056 | { 1057 | beast_debug_mode = 1; 1058 | } else { 1059 | beast_debug_mode = 0; 1060 | } 1061 | 1062 | return SUCCESS; 1063 | 1064 | #else 1065 | 1066 | if (new_value_length == 0) { 1067 | return FAILURE; 1068 | } 1069 | 1070 | if (!strcasecmp(new_value, "on") 1071 | || !strcmp(new_value, "1")) 1072 | { 1073 | beast_debug_mode = 1; 1074 | } else { 1075 | beast_debug_mode = 0; 1076 | } 1077 | 1078 | return SUCCESS; 1079 | 1080 | #endif 1081 | } 1082 | 1083 | 1084 | PHP_INI_BEGIN() 1085 | PHP_INI_ENTRY("beast.cache_size", "10485760", PHP_INI_ALL, 1086 | php_beast_cache_size) 1087 | PHP_INI_ENTRY("beast.log_file", "./php-beast.log", PHP_INI_ALL, 1088 | php_beast_log_file) 1089 | PHP_INI_ENTRY("beast.log_user", "root", PHP_INI_ALL, 1090 | php_beast_log_user) 1091 | PHP_INI_ENTRY("beast.log_level", "notice", PHP_INI_ALL, 1092 | php_beast_log_level) 1093 | PHP_INI_ENTRY("beast.enable", "1", PHP_INI_ALL, 1094 | php_beast_enable) 1095 | PHP_INI_ENTRY("beast.networkcard", "eth0", PHP_INI_ALL, 1096 | php_beast_set_networkcard) 1097 | PHP_INI_ENTRY("beast.log_normal_file", "0", PHP_INI_ALL, 1098 | php_beast_set_log_normal_file) 1099 | #if BEAST_DEBUG_MODE 1100 | PHP_INI_ENTRY("beast.debug_path", "/tmp", PHP_INI_ALL, 1101 | php_beast_debug_path) 1102 | PHP_INI_ENTRY("beast.debug_mode", "0", PHP_INI_ALL, 1103 | php_beast_debug_mode) 1104 | #endif 1105 | PHP_INI_END() 1106 | 1107 | /* }}} */ 1108 | 1109 | 1110 | void segmentfault_deadlock_fix(int sig) 1111 | { 1112 | #ifdef PHP_WIN32 // windows not support backtrace 1113 | beast_write_log(beast_log_error, "Segmentation fault and fix deadlock"); 1114 | #else 1115 | void *array[10] = {0}; 1116 | size_t size; 1117 | char **info = NULL; 1118 | int i; 1119 | 1120 | size = backtrace(array, 10); 1121 | info = backtrace_symbols(array, (int)size); 1122 | 1123 | beast_write_log(beast_log_error, "Segmentation fault and fix deadlock"); 1124 | 1125 | if (info) { 1126 | for (i = 0; i < size; i++) { 1127 | beast_write_log(beast_log_error, info[i]); 1128 | } 1129 | free(info); 1130 | } 1131 | #endif 1132 | beast_mm_unlock(); /* Maybe lock mm so free here */ 1133 | beast_cache_unlock(); /* Maybe lock cache so free here */ 1134 | 1135 | exit(sig); 1136 | } 1137 | 1138 | 1139 | static char *get_mac_address(char *networkcard) 1140 | { 1141 | #ifdef PHP_WIN32 1142 | 1143 | // For windows 1144 | ULONG size = sizeof(IP_ADAPTER_INFO); 1145 | int ret, i; 1146 | char *address = NULL; 1147 | char buf[128] = { 0 }, *pos; 1148 | 1149 | PIP_ADAPTER_INFO pCurrentAdapter = NULL; 1150 | PIP_ADAPTER_INFO pIpAdapterInfo = (PIP_ADAPTER_INFO)malloc(sizeof(*pIpAdapterInfo)); 1151 | if (!pIpAdapterInfo) { 1152 | beast_write_log(beast_log_error, "Failed to allocate memory for IP_ADAPTER_INFO"); 1153 | return NULL; 1154 | } 1155 | 1156 | ret = GetAdaptersInfo(pIpAdapterInfo, &size); 1157 | if (ERROR_BUFFER_OVERFLOW == ret) { 1158 | // see ERROR_BUFFER_OVERFLOW https://msdn.microsoft.com/en-us/library/aa365917(VS.85).aspx 1159 | free(pIpAdapterInfo); 1160 | pIpAdapterInfo = (PIP_ADAPTER_INFO)malloc(size); 1161 | 1162 | ret = GetAdaptersInfo(pIpAdapterInfo, &size); 1163 | } 1164 | 1165 | if (ERROR_SUCCESS != ret) { 1166 | beast_write_log(beast_log_error, "Failed to get network adapter information"); 1167 | free(pIpAdapterInfo); 1168 | return NULL; 1169 | } 1170 | 1171 | pCurrentAdapter = pIpAdapterInfo; 1172 | do { 1173 | if (strcmp(pCurrentAdapter->AdapterName, networkcard) == 0) { 1174 | for (i = 0, pos = buf; i < pCurrentAdapter->AddressLength; i++, pos += 3) { 1175 | sprintf(pos, "%.2X-", (int)pCurrentAdapter->Address[i]); 1176 | } 1177 | *(--pos) = '\0'; // remove last - 1178 | address = strdup(buf); 1179 | break; 1180 | } 1181 | pCurrentAdapter = pCurrentAdapter->Next; 1182 | } while (pCurrentAdapter); 1183 | 1184 | free(pIpAdapterInfo); 1185 | return address; 1186 | 1187 | #else 1188 | 1189 | // For linux / unix 1190 | char netfile[128] = { 0 }, cmd[128] = { 0 }, buf[128] = { 0 }; 1191 | FILE *fp; 1192 | char *retbuf, *curr, *last; 1193 | 1194 | snprintf(netfile, 128, "/sys/class/net/%s/address", networkcard); 1195 | 1196 | if (access((const char *)netfile, R_OK) != 0) { /* File not exists */ 1197 | snprintf(cmd, 128, "ifconfig %s|awk '/ether/ {print $2}'", networkcard); 1198 | } else { 1199 | snprintf(cmd, 128, "cat %s", netfile); 1200 | } 1201 | 1202 | fp = popen(cmd, "r"); 1203 | if (!fp) { 1204 | return NULL; 1205 | } 1206 | 1207 | retbuf = fgets(buf, 128, fp); 1208 | 1209 | for (curr = buf, last = NULL; *curr; curr++) { 1210 | if (*curr != '\n') { 1211 | last = curr; 1212 | } 1213 | } 1214 | 1215 | if (!last) { 1216 | return NULL; 1217 | } 1218 | 1219 | for (last += 1; *last; last++) { 1220 | *last = '\0'; 1221 | } 1222 | 1223 | pclose(fp); 1224 | 1225 | return strdup(buf); 1226 | 1227 | #endif 1228 | } 1229 | 1230 | static int validate_networkcard() 1231 | { 1232 | extern char *allow_networkcards[]; 1233 | char **ptr; 1234 | char *networkcard_start, *networkcard_end; 1235 | int endof_networkcard = 0; 1236 | int active = 0; 1237 | char *address; 1238 | 1239 | for (ptr = allow_networkcards; *ptr; ptr++, active++); 1240 | 1241 | if (!active) { 1242 | return 0; 1243 | } 1244 | 1245 | networkcard_start = networkcard_end = local_networkcard; 1246 | 1247 | while (1) { 1248 | while (*networkcard_end && *networkcard_end != ',') { 1249 | networkcard_end++; 1250 | } 1251 | 1252 | if (networkcard_start == networkcard_end) { /* empty string */ 1253 | break; 1254 | } 1255 | 1256 | if (*networkcard_end == ',') { 1257 | *networkcard_end = '\0'; 1258 | } 1259 | else { 1260 | endof_networkcard = 1; 1261 | } 1262 | 1263 | address = get_mac_address(networkcard_start); 1264 | if (address) { 1265 | for (ptr = allow_networkcards; *ptr; ptr++) { 1266 | if (!strcasecmp(address, *ptr)) { 1267 | free(address); /* release buffer */ 1268 | return 0; 1269 | } 1270 | } 1271 | free(address); 1272 | } 1273 | 1274 | if (endof_networkcard) { 1275 | break; 1276 | } 1277 | 1278 | networkcard_start = networkcard_end + 1; 1279 | } 1280 | 1281 | return -1; 1282 | } 1283 | 1284 | /* {{{ PHP_MINIT_FUNCTION 1285 | */ 1286 | PHP_MINIT_FUNCTION(beast) 1287 | { 1288 | int i; 1289 | #ifdef PHP_WIN32 1290 | SYSTEM_INFO info; 1291 | #endif 1292 | 1293 | /* If you have INI entries, uncomment these lines */ 1294 | REGISTER_INI_ENTRIES(); 1295 | 1296 | if (!beast_enable) { 1297 | return SUCCESS; 1298 | } 1299 | 1300 | if (validate_networkcard() == -1) { 1301 | php_error_docref(NULL TSRMLS_CC, E_ERROR, 1302 | "Not allow run at this computer"); 1303 | return FAILURE; 1304 | } 1305 | 1306 | if ((encrypt_file_header_length + INT_SIZE * 2) > HEADER_MAX_SIZE) { 1307 | php_error_docref(NULL TSRMLS_CC, E_ERROR, 1308 | "Header size overflow max size `%d'", HEADER_MAX_SIZE); 1309 | return FAILURE; 1310 | } 1311 | 1312 | /* Check module support the max file size */ 1313 | for (i = 0; ; i++) { 1314 | default_file_handler = file_handlers[i]; 1315 | if (!default_file_handler || 1316 | !strcasecmp(file_handler_switch, default_file_handler->name)) 1317 | { 1318 | break; 1319 | } 1320 | } 1321 | 1322 | if (!default_file_handler) { 1323 | return FAILURE; 1324 | } 1325 | 1326 | beast_max_filesize = default_file_handler->check(); 1327 | if (beast_max_filesize == -1) { 1328 | return FAILURE; 1329 | } 1330 | 1331 | if (beast_cache_init(max_cache_size) == -1) { 1332 | php_error_docref(NULL TSRMLS_CC, 1333 | E_ERROR, "Unable initialize cache for beast"); 1334 | return FAILURE; 1335 | } 1336 | 1337 | if (beast_log_init(beast_log_file, log_level) == -1) { 1338 | php_error_docref(NULL TSRMLS_CC, 1339 | E_ERROR, "Unable open log file for beast"); 1340 | return FAILURE; 1341 | } 1342 | 1343 | #ifndef PHP_WIN32 1344 | if (getuid() == 0 && beast_log_user) { /* Change log file owner user */ 1345 | struct passwd *pwd; 1346 | 1347 | pwd = getpwnam((const char *)beast_log_user); 1348 | if (!pwd) { 1349 | php_error_docref(NULL TSRMLS_CC, 1350 | E_ERROR, "Unable get user passwd information"); 1351 | return FAILURE; 1352 | } 1353 | 1354 | if (beast_log_chown(pwd->pw_uid, pwd->pw_gid) != 0) { 1355 | php_error_docref(NULL TSRMLS_CC, 1356 | E_ERROR, "Unable change log file owner"); 1357 | return FAILURE; 1358 | } 1359 | } 1360 | #endif 1361 | 1362 | old_compile_file = zend_compile_file; 1363 | zend_compile_file = cgi_compile_file; 1364 | 1365 | #ifdef PHP_WIN32 1366 | GetSystemInfo(&info); 1367 | beast_ncpu = info.dwNumberOfProcessors; 1368 | #else 1369 | beast_ncpu = sysconf(_SC_NPROCESSORS_ONLN); /* Get CPU nums */ 1370 | #endif 1371 | if (beast_ncpu <= 0) { 1372 | beast_ncpu = 1; 1373 | } 1374 | 1375 | signal(SIGSEGV, segmentfault_deadlock_fix); 1376 | 1377 | REGISTER_LONG_CONSTANT("BEAST_ENCRYPT_TYPE_DES", 1378 | BEAST_ENCRYPT_TYPE_DES, CONST_CS|CONST_PERSISTENT); 1379 | REGISTER_LONG_CONSTANT("BEAST_ENCRYPT_TYPE_AES", 1380 | BEAST_ENCRYPT_TYPE_AES, CONST_CS|CONST_PERSISTENT); 1381 | REGISTER_LONG_CONSTANT("BEAST_ENCRYPT_TYPE_BASE64", 1382 | BEAST_ENCRYPT_TYPE_BASE64, CONST_CS|CONST_PERSISTENT); 1383 | 1384 | beast_write_log(beast_log_debug, "Beast module was initialized"); 1385 | 1386 | return SUCCESS; 1387 | } 1388 | /* }}} */ 1389 | 1390 | /* {{{ PHP_MSHUTDOWN_FUNCTION 1391 | */ 1392 | PHP_MSHUTDOWN_FUNCTION(beast) 1393 | { 1394 | /* uncomment this line if you have INI entries */ 1395 | UNREGISTER_INI_ENTRIES(); 1396 | 1397 | if (!beast_enable) { 1398 | return SUCCESS; 1399 | } 1400 | 1401 | beast_cache_destroy(); 1402 | beast_log_destroy(); 1403 | 1404 | zend_compile_file = old_compile_file; 1405 | 1406 | return SUCCESS; 1407 | } 1408 | /* }}} */ 1409 | 1410 | /* {{{ PHP_RINIT_FUNCTION 1411 | */ 1412 | PHP_RINIT_FUNCTION(beast) 1413 | { 1414 | if (beast_pid == -1) { 1415 | beast_pid = getpid(); 1416 | } 1417 | 1418 | beast_now_time = time(NULL); /* Update now time */ 1419 | 1420 | return SUCCESS; 1421 | } 1422 | /* }}} */ 1423 | 1424 | /* {{{ PHP_RSHUTDOWN_FUNCTION 1425 | */ 1426 | PHP_RSHUTDOWN_FUNCTION(beast) 1427 | { 1428 | return SUCCESS; 1429 | } 1430 | /* }}} */ 1431 | 1432 | /* {{{ PHP_MINFO_FUNCTION 1433 | */ 1434 | PHP_MINFO_FUNCTION(beast) 1435 | { 1436 | php_info_print_table_start(); 1437 | php_info_print_table_header(2, 1438 | "beast V" BEAST_VERSION " support", "enabled"); 1439 | php_info_print_table_end(); 1440 | 1441 | DISPLAY_INI_ENTRIES(); 1442 | } 1443 | /* }}} */ 1444 | 1445 | 1446 | PHP_FUNCTION(beast_file_expire) 1447 | { 1448 | char *file; 1449 | int file_len; 1450 | char header[HEADER_MAX_SIZE] = {0}; 1451 | int header_len; 1452 | signed long expire = 0; 1453 | int fd = -1; 1454 | char *string; 1455 | char *format = "Y-m-d H:i:s"; 1456 | 1457 | #if ZEND_MODULE_API_NO >= 20151012 1458 | 1459 | zend_string *input_file; 1460 | 1461 | if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "S", 1462 | &input_file TSRMLS_CC) == FAILURE) 1463 | { 1464 | RETURN_FALSE; 1465 | } 1466 | 1467 | file = ZSTR_VAL(input_file); 1468 | file_len = ZSTR_LEN(input_file); 1469 | 1470 | #else 1471 | 1472 | if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", 1473 | &file, &file_len TSRMLS_CC) == FAILURE) 1474 | { 1475 | RETURN_FALSE; 1476 | } 1477 | 1478 | #endif 1479 | 1480 | fd = open(file, O_RDONLY); 1481 | if (fd < 0) { 1482 | goto error; 1483 | } 1484 | 1485 | header_len = encrypt_file_header_length + INT_SIZE * 2; 1486 | 1487 | if (read(fd, header, header_len) != header_len 1488 | || memcmp(header, encrypt_file_header_sign, encrypt_file_header_length)) 1489 | { 1490 | goto error; 1491 | } 1492 | 1493 | close(fd); 1494 | 1495 | expire = *((int *)&header[encrypt_file_header_length + INT_SIZE]); 1496 | 1497 | if (little_endian()) { 1498 | expire = swab32(expire); 1499 | } 1500 | 1501 | if (expire > 0) { 1502 | string = (char *)php_format_date(format, strlen(format), expire, 1 TSRMLS_CC); 1503 | BEAST_RETURN_STRING(string, 0); 1504 | } else { 1505 | BEAST_RETURN_STRING("+Infinity", 1); 1506 | } 1507 | 1508 | error: 1509 | if (fd >= 0) { 1510 | close(fd); 1511 | } 1512 | 1513 | RETURN_FALSE; 1514 | } 1515 | 1516 | 1517 | PHP_FUNCTION(beast_encode_file) 1518 | { 1519 | char *input, *output; 1520 | int input_len, output_len; 1521 | long expire = 0; 1522 | long encrypt_type = BEAST_ENCRYPT_TYPE_DES; 1523 | int ret; 1524 | 1525 | #if ZEND_MODULE_API_NO >= 20151012 1526 | 1527 | zend_string *in, *out; 1528 | 1529 | if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "SS|ll", 1530 | &in, &out, &expire, &encrypt_type) == FAILURE) 1531 | { 1532 | RETURN_FALSE; 1533 | } 1534 | 1535 | input = ZSTR_VAL(in); 1536 | output = ZSTR_VAL(out); 1537 | input_len = ZSTR_LEN(in); 1538 | output_len = ZSTR_LEN(out); 1539 | 1540 | #else 1541 | 1542 | if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|ll", 1543 | &input, &input_len, &output, &output_len, 1544 | &expire, &encrypt_type TSRMLS_CC) == FAILURE) 1545 | { 1546 | RETURN_FALSE; 1547 | } 1548 | 1549 | #endif 1550 | 1551 | if (encrypt_type <= 0 1552 | || encrypt_type >= BEAST_ENCRYPT_TYPE_ERROR) 1553 | { 1554 | RETURN_FALSE; 1555 | } 1556 | 1557 | ret = encrypt_file(input, output, 1558 | (int)expire, (int)encrypt_type TSRMLS_CC); 1559 | if (ret == -1) { 1560 | RETURN_FALSE; 1561 | } 1562 | 1563 | RETURN_TRUE; 1564 | } 1565 | 1566 | 1567 | PHP_FUNCTION(beast_avail_cache) 1568 | { 1569 | RETURN_LONG(beast_mm_availspace()); 1570 | } 1571 | 1572 | 1573 | PHP_FUNCTION(beast_support_filesize) 1574 | { 1575 | RETURN_LONG(beast_max_filesize); 1576 | } 1577 | 1578 | 1579 | PHP_FUNCTION(beast_clean_cache) 1580 | { 1581 | beast_cache_flush(); 1582 | } 1583 | 1584 | /* 1585 | * Local variables: 1586 | * tab-width: 4 1587 | * c-basic-offset: 4 1588 | * End: 1589 | * vim600: noet sw=4 ts=4 fdm=marker expandtab 1590 | * vim<600: noet sw=4 ts=4 1591 | */ 1592 | -------------------------------------------------------------------------------- /beast_log.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #ifdef PHP_WIN32 6 | 7 | #else 8 | #include 9 | #endif 10 | #include "main/php_reentrancy.h" 11 | #include "beast_log.h" 12 | 13 | static FILE *beast_log_fp = NULL; 14 | static int log_level = beast_log_notice; 15 | 16 | int beast_log_init(char *log_file, int level) 17 | { 18 | if (!log_file || strlen(log_file) == 0) { 19 | return 0; 20 | } 21 | 22 | beast_log_fp = fopen(log_file, "a+"); 23 | if (!beast_log_fp) 24 | return -1; 25 | log_level = level; 26 | return 0; 27 | } 28 | 29 | 30 | int beast_log_chown(uid_t uid, gid_t gid) 31 | { 32 | #ifdef PHP_WIN32 33 | return 1; 34 | #else 35 | int fd; 36 | 37 | if (!beast_log_fp) { 38 | return 0; 39 | } 40 | 41 | fd = fileno(beast_log_fp); 42 | 43 | return fchown(fd, uid, gid); 44 | #endif 45 | } 46 | 47 | 48 | void beast_write_log(beast_log_level level, const char *fmt, ...) 49 | { 50 | 51 | struct tm local_tm, *result_tm; 52 | time_t the_time; 53 | char buf[64]; 54 | char *headers[] = {"DEBUG", "NOTICE", "ERROR"}; 55 | va_list ap; 56 | 57 | if (beast_log_fp == NULL || 58 | level > beast_log_error || 59 | level < log_level) 60 | { 61 | return; 62 | } 63 | 64 | va_start(ap, fmt); 65 | 66 | the_time = time(NULL); 67 | result_tm = php_localtime_r(&the_time, &local_tm); 68 | strftime(buf, 64, "%d %b %H:%M:%S", result_tm); 69 | 70 | fprintf(beast_log_fp, "[%s] %s: ", buf, headers[level]); 71 | vfprintf(beast_log_fp, fmt, ap); 72 | fprintf(beast_log_fp, "\n"); 73 | fflush(beast_log_fp); 74 | 75 | va_end(ap); 76 | 77 | return; 78 | } 79 | 80 | void beast_log_destroy() 81 | { 82 | if (beast_log_fp) { 83 | fclose(beast_log_fp); 84 | beast_log_fp = NULL; 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /beast_log.h: -------------------------------------------------------------------------------- 1 | #ifndef BEAST_LOG_H 2 | #define BEAST_LOG_H 3 | 4 | #ifdef PHP_WIN32 5 | #include "win95nt.h" 6 | #else 7 | #include 8 | #endif 9 | 10 | typedef enum { 11 | beast_log_debug, /* 0 */ 12 | beast_log_notice, /* 1 */ 13 | beast_log_error /* 2 */ 14 | } beast_log_level; 15 | 16 | int beast_log_init(char *log_file, int level); 17 | int beast_log_chown(uid_t uid, gid_t gid); 18 | void beast_write_log(beast_log_level level, const char *fmt, ...); 19 | void beast_log_destroy(); 20 | 21 | #endif 22 | -------------------------------------------------------------------------------- /beast_mm.c: -------------------------------------------------------------------------------- 1 | /* 2 | +----------------------------------------------------------------------+ 3 | | PHP Version 5 | 4 | +----------------------------------------------------------------------+ 5 | | Copyright (c) 1997-2007 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 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: Liexusong | 16 | +----------------------------------------------------------------------+ 17 | */ 18 | 19 | /* 20 | * The simple share memory manager algorithm 21 | */ 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #ifdef PHP_WIN32 29 | #include 30 | #else 31 | #include 32 | #endif 33 | 34 | #include "spinlock.h" 35 | #include "beast_log.h" 36 | #include "shm.h" 37 | 38 | #define BEAST_SEGMENT_DEFAULT_SIZE (256 * 1024) 39 | 40 | #define BLOCKAT(addr, offset) ((beast_block_t *)((char *)(addr) + (offset))) 41 | 42 | #ifdef max 43 | #undef max 44 | #endif 45 | #define max(a, b) ((a) > (b) ? (a) : (b)) 46 | 47 | typedef struct beast_header_s { 48 | int segsize; /* size of entire segment */ 49 | int avail; /* bytes available memorys */ 50 | } beast_header_t; 51 | 52 | typedef struct beast_block_s { 53 | int size; /* size of this block */ 54 | int next; /* offset in segment of next free block */ 55 | } beast_block_t; 56 | 57 | static int beast_mm_initialized = 0; 58 | static void *beast_mm_block = NULL; 59 | static int beast_mm_block_size = 0; 60 | static beast_atomic_t *mm_lock; 61 | extern int beast_pid; 62 | 63 | void beast_mm_lock() 64 | { 65 | beast_spinlock(mm_lock, beast_pid); 66 | } 67 | 68 | void beast_mm_unlock() 69 | { 70 | beast_spinunlock(mm_lock, beast_pid); 71 | } 72 | 73 | /* 74 | * memory align function 75 | * @param bits, align bits 76 | */ 77 | static inline int beast_mm_alignmem(int bits) 78 | { 79 | typedef union { 80 | void* p; 81 | int i; 82 | long l; 83 | double d; 84 | void (*f)(); 85 | } beast_word_t; /* may be 8 bits */ 86 | 87 | return sizeof(beast_word_t) * (1 + ((bits - 1) / sizeof(beast_word_t))); 88 | } 89 | 90 | static int beast_mm_allocate(void *shmaddr, int size) 91 | { 92 | beast_header_t *header; /* header of shared memory segment */ 93 | beast_block_t *prv; /* block prior to working block */ 94 | beast_block_t *cur; /* working block in list */ 95 | beast_block_t *prvbestfit; /* block before best fit */ 96 | int realsize; /* actual size of block needed, including header */ 97 | int minsize; /* for finding best fit */ 98 | int offset; 99 | 100 | /* Realsize must be aligned to a word boundary on some architectures. */ 101 | realsize = size + beast_mm_alignmem(sizeof(int)); 102 | realsize = beast_mm_alignmem(max(realsize, sizeof(beast_block_t))); 103 | 104 | /* 105 | * First, insure that the segment contains at least realsize free bytes, 106 | * even if they are not contiguous. 107 | */ 108 | header = (beast_header_t *)shmaddr; 109 | if (header->avail < realsize) { 110 | beast_write_log(beast_log_error, 111 | "Not enough memory for beast_mm_alloc()"); 112 | return -1; 113 | } 114 | 115 | prvbestfit = 0; /* Best block prev's node */ 116 | minsize = INT_MAX; 117 | 118 | prv = BLOCKAT(shmaddr, sizeof(beast_header_t)); /* Free list header */ 119 | 120 | while (prv->next != 0) { 121 | cur = BLOCKAT(shmaddr, prv->next); /* Current active block */ 122 | if (cur->size == realsize) { 123 | prvbestfit = prv; 124 | break; 125 | } 126 | else if (cur->size > (sizeof(beast_block_t) + realsize) 127 | && cur->size < minsize) 128 | { 129 | prvbestfit = prv; 130 | minsize = cur->size; 131 | } 132 | prv = cur; 133 | } 134 | 135 | if (prvbestfit == 0) { /* Not found best block */ 136 | return -1; 137 | } 138 | 139 | prv = prvbestfit; 140 | cur = BLOCKAT(shmaddr, prv->next); 141 | 142 | /* update the block header */ 143 | header->avail -= realsize; 144 | 145 | if (cur->size == realsize) { 146 | prv->next = cur->next; 147 | 148 | } else { 149 | beast_block_t *nxt; /* The new block (chopped part of cur) */ 150 | int nxtoffset; /* Offset of the block currently after cur */ 151 | int oldsize; /* Size of cur before split */ 152 | 153 | /* bestfit is too big; split it into two smaller blocks */ 154 | nxtoffset = cur->next; 155 | oldsize = cur->size; 156 | prv->next += realsize; 157 | cur->size = realsize; 158 | nxt = BLOCKAT(shmaddr, prv->next); 159 | nxt->next = nxtoffset; 160 | nxt->size = oldsize - realsize; 161 | } 162 | 163 | /* skip size field */ 164 | 165 | offset = (char *)cur - (char *)shmaddr; 166 | 167 | return offset + beast_mm_alignmem(sizeof(int)); 168 | } 169 | 170 | static int beast_mm_deallocate(void *shmaddr, int offset) 171 | { 172 | beast_header_t *header; /* Header of shared memory segment */ 173 | beast_block_t *cur; /* The new block to insert */ 174 | beast_block_t *prv; /* The block before cur */ 175 | beast_block_t *nxt; /* The block after cur */ 176 | int size; /* Size of deallocated block */ 177 | 178 | offset -= beast_mm_alignmem(sizeof(int)); /* Really offset */ 179 | 180 | /* Find position of new block in free list */ 181 | prv = BLOCKAT(shmaddr, sizeof(beast_header_t)); 182 | 183 | while (prv->next != 0 && prv->next < offset) { 184 | prv = BLOCKAT(shmaddr, prv->next); 185 | } 186 | 187 | /* Insert new block after prv */ 188 | cur = BLOCKAT(shmaddr, offset); 189 | cur->next = prv->next; 190 | prv->next = offset; 191 | 192 | /* Update the block header */ 193 | header = (beast_header_t *)shmaddr; 194 | header->avail += cur->size; 195 | size = cur->size; 196 | 197 | if (((char *)prv) + prv->size == (char *) cur) { 198 | /* cur and prv share an edge, combine them */ 199 | prv->size += cur->size; 200 | prv->next = cur->next; 201 | cur = prv; 202 | } 203 | 204 | nxt = BLOCKAT(shmaddr, cur->next); 205 | if (((char *)cur) + cur->size == (char *) nxt) { 206 | /* cur and nxt shared an edge, combine them */ 207 | cur->size += nxt->size; 208 | cur->next = nxt->next; 209 | } 210 | 211 | return size; 212 | } 213 | 214 | void beast_mm_reinit() 215 | { 216 | beast_header_t *header; 217 | beast_block_t *block; 218 | 219 | header = (beast_header_t *)beast_mm_block; 220 | header->segsize = beast_mm_block_size; 221 | header->avail = beast_mm_block_size 222 | - sizeof(beast_header_t) 223 | - sizeof(beast_block_t) 224 | - beast_mm_alignmem(sizeof(int)); 225 | 226 | /* The free list head block node */ 227 | block = BLOCKAT(beast_mm_block, sizeof(beast_header_t)); 228 | block->size = 0; 229 | block->next = sizeof(beast_header_t) + sizeof(beast_block_t); 230 | 231 | /* The avail block */ 232 | block = BLOCKAT(beast_mm_block, block->next); 233 | block->size = header->avail; 234 | block->next = 0; 235 | } 236 | 237 | /* 238 | * Init memory manager 239 | */ 240 | int beast_mm_init(int block_size) 241 | { 242 | if (beast_mm_initialized) { 243 | return 0; 244 | } 245 | 246 | /* Init memory manager lock */ 247 | mm_lock = (int *)beast_shm_alloc(sizeof(beast_atomic_t)); 248 | if (!mm_lock) { 249 | beast_write_log(beast_log_error, 250 | "Unable alloc share memory for memory manager lock"); 251 | return -1; 252 | } 253 | 254 | *mm_lock = 0; 255 | 256 | /* Init share memory for beast */ 257 | if (block_size < BEAST_SEGMENT_DEFAULT_SIZE) { 258 | beast_mm_block_size = BEAST_SEGMENT_DEFAULT_SIZE; 259 | } else { 260 | beast_mm_block_size = block_size; 261 | } 262 | 263 | beast_mm_block = (void *)beast_shm_alloc(beast_mm_block_size); 264 | if (!beast_mm_block) { 265 | beast_write_log(beast_log_error, 266 | "Unable alloc share memory for beast"); 267 | beast_shm_free((void *)mm_lock, sizeof(beast_atomic_t)); 268 | return -1; 269 | } 270 | 271 | beast_mm_reinit(); 272 | 273 | beast_mm_initialized = 1; 274 | 275 | return 0; 276 | } 277 | 278 | void *beast_mm_malloc(int size) 279 | { 280 | int offset; 281 | void *p = NULL; 282 | 283 | beast_mm_lock(); 284 | 285 | offset = beast_mm_allocate(beast_mm_block, size); 286 | if (offset != -1) { 287 | p = (void *)(((char *)beast_mm_block) + offset); 288 | } 289 | 290 | beast_mm_unlock(); 291 | 292 | return p; 293 | } 294 | 295 | void *beast_mm_calloc(int size) 296 | { 297 | int offset; 298 | void *p = NULL; 299 | 300 | beast_mm_lock(); 301 | 302 | offset = beast_mm_allocate(beast_mm_block, size); 303 | if (offset != -1) { 304 | p = (void *)(((char *)beast_mm_block) + offset); 305 | } 306 | 307 | beast_mm_unlock(); 308 | 309 | if (NULL != p) { 310 | memset(p, 0, size); 311 | } 312 | 313 | return p; 314 | } 315 | 316 | void beast_mm_free(void *p) 317 | { 318 | int offset; 319 | 320 | offset = (unsigned int)((char *)p - (char *)beast_mm_block); 321 | if (offset <= 0) { 322 | return; 323 | } 324 | 325 | beast_mm_lock(); 326 | beast_mm_deallocate(beast_mm_block, offset); 327 | beast_mm_unlock(); 328 | } 329 | 330 | void beast_mm_flush() 331 | { 332 | beast_mm_lock(); 333 | beast_mm_reinit(); 334 | beast_mm_unlock(); 335 | } 336 | 337 | /* 338 | * Get the avail's memory space 339 | */ 340 | int beast_mm_availspace() 341 | { 342 | int size; 343 | beast_header_t *header = (beast_header_t *)beast_mm_block; 344 | 345 | beast_mm_lock(); 346 | size = header->avail; 347 | beast_mm_unlock(); 348 | 349 | return size; 350 | } 351 | 352 | /* 353 | * Don't locked here, because the segsize not change forever 354 | */ 355 | int beast_mm_realspace() 356 | { 357 | int size; 358 | 359 | beast_mm_lock(); 360 | size = ((beast_header_t *)beast_mm_block)->segsize; 361 | beast_mm_unlock(); 362 | 363 | return size; 364 | } 365 | 366 | /* 367 | * Destroy memory's manager 368 | */ 369 | void beast_mm_destroy() 370 | { 371 | if (beast_mm_initialized) { 372 | beast_shm_free((void *)beast_mm_block, beast_mm_block_size); 373 | beast_shm_free((void *)mm_lock, sizeof(beast_atomic_t)); 374 | beast_mm_initialized = 0; 375 | } 376 | } 377 | -------------------------------------------------------------------------------- /beast_mm.h: -------------------------------------------------------------------------------- 1 | #ifndef __BEAST_MM_H 2 | #define __BEAST_MM_H 3 | 4 | int beast_mm_init(int block_size); 5 | void *beast_mm_malloc(int size); 6 | void *beast_mm_calloc(int size); 7 | void beast_mm_free(void *p); 8 | void beast_mm_flush(); 9 | int beast_mm_availspace(); 10 | int beast_mm_realspace(); 11 | void beast_mm_destroy(); 12 | 13 | void beast_mm_lock(); 14 | void beast_mm_unlock(); 15 | 16 | #endif 17 | -------------------------------------------------------------------------------- /beast_module.h: -------------------------------------------------------------------------------- 1 | #ifndef __BEAST_MODULE_H 2 | #define __BEAST_MODULE_H 3 | 4 | typedef int beast_encrypt_op_t(char *inbuf, int inlen, 5 | char **outbuf, int *outlen); 6 | typedef int beast_decrypt_op_t(char *inbuf, int inlen, 7 | char **outbuf, int *outlen); 8 | typedef void beast_free_buf_t(void *buf); 9 | 10 | typedef enum { 11 | BEAST_ENCRYPT_TYPE_DES = 1, 12 | BEAST_ENCRYPT_TYPE_AES, 13 | BEAST_ENCRYPT_TYPE_BASE64, 14 | BEAST_ENCRYPT_TYPE_ERROR 15 | } beast_encrypt_type_t; 16 | 17 | struct beast_ops { 18 | char *name; 19 | beast_encrypt_op_t *encrypt; 20 | beast_decrypt_op_t *decrypt; 21 | beast_free_buf_t *free; 22 | struct beast_ops *next; 23 | }; 24 | 25 | #endif 26 | -------------------------------------------------------------------------------- /cache.c: -------------------------------------------------------------------------------- 1 | /* 2 | +----------------------------------------------------------------------+ 3 | | PHP Version 5 | 4 | +----------------------------------------------------------------------+ 5 | | Copyright (c) 1997-2007 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 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: Liexusong <280259971@qq.com> | 16 | +----------------------------------------------------------------------+ 17 | */ 18 | 19 | #include 20 | #include 21 | #ifndef PHP_WIN32 22 | #include 23 | #endif 24 | 25 | #include "beast_mm.h" 26 | #include "spinlock.h" 27 | #include "php.h" 28 | #include "cache.h" 29 | #include "beast_log.h" 30 | #include "shm.h" 31 | 32 | #define BUCKETS_DEFAULT_SIZE 8191 33 | 34 | static int beast_cache_initialization = 0; 35 | static cache_item_t **beast_cache_buckets = NULL; 36 | static beast_atomic_t *cache_lock; 37 | extern int beast_pid; 38 | 39 | void beast_cache_lock() 40 | { 41 | beast_spinlock(cache_lock, beast_pid); 42 | } 43 | 44 | void beast_cache_unlock() 45 | { 46 | beast_spinunlock(cache_lock, beast_pid); 47 | } 48 | 49 | static inline unsigned int 50 | beast_cache_hash(cache_key_t *key) 51 | { 52 | unsigned int retval; 53 | 54 | retval = (unsigned int)key->device * 3 55 | + (unsigned int)key->inode * 7; 56 | 57 | return retval; 58 | } 59 | 60 | 61 | int beast_cache_init(int size) 62 | { 63 | int index, bucket_size; 64 | 65 | if (beast_cache_initialization) { 66 | return 0; 67 | } 68 | 69 | if (beast_mm_init(size) == -1) { 70 | return -1; 71 | } 72 | 73 | /* init cache lock */ 74 | cache_lock = (int *)beast_shm_alloc(sizeof(int)); 75 | if (!cache_lock) { 76 | beast_write_log(beast_log_error, 77 | "Unable alloc share memory for cache lock"); 78 | beast_mm_destroy(); 79 | return -1; 80 | } 81 | 82 | *cache_lock = 0; 83 | 84 | /* init cache buckets's memory */ 85 | bucket_size = sizeof(cache_item_t *) * BUCKETS_DEFAULT_SIZE; 86 | 87 | beast_cache_buckets = (cache_item_t **)beast_shm_alloc(bucket_size); 88 | 89 | if (!beast_cache_buckets) { 90 | beast_write_log(beast_log_error, 91 | "Unable alloc share memory for cache buckets"); 92 | beast_shm_free((void *)cache_lock, sizeof(int)); 93 | beast_mm_destroy(); 94 | return -1; 95 | } 96 | 97 | for (index = 0; index < BUCKETS_DEFAULT_SIZE; index++) { 98 | beast_cache_buckets[index] = NULL; 99 | } 100 | 101 | beast_cache_initialization = 1; 102 | 103 | return 0; 104 | } 105 | 106 | 107 | cache_item_t *beast_cache_find(cache_key_t *key) 108 | { 109 | unsigned int hashval = beast_cache_hash(key); 110 | unsigned int index = hashval % BUCKETS_DEFAULT_SIZE; 111 | cache_item_t *item, *temp; 112 | 113 | beast_cache_lock(); 114 | 115 | item = beast_cache_buckets[index]; 116 | while (item) { 117 | if (item->key.device == key->device && 118 | item->key.inode == key->inode) 119 | { 120 | break; 121 | } 122 | item = item->next; 123 | } 124 | 125 | if (item && item->key.mtime < key->mtime) /* cache exprie */ 126 | { 127 | temp = beast_cache_buckets[index]; 128 | if (temp == item) { /* the header node */ 129 | beast_cache_buckets[index] = item->next; 130 | } else { 131 | while (temp->next != item) { /* find prev node */ 132 | temp = temp->next; 133 | } 134 | temp->next = item->next; 135 | } 136 | 137 | beast_mm_free(item); 138 | 139 | item = NULL; 140 | } 141 | 142 | beast_cache_unlock(); 143 | 144 | return item; 145 | } 146 | 147 | 148 | cache_item_t *beast_cache_create(cache_key_t *key) 149 | { 150 | cache_item_t *item; 151 | int msize, bsize; 152 | 153 | msize = sizeof(*item) + key->fsize; 154 | bsize = sizeof(cache_item_t *) * BUCKETS_DEFAULT_SIZE; 155 | 156 | if ((msize + bsize) > beast_mm_realspace()) { 157 | beast_write_log(beast_log_error, 158 | "Cache item size too big"); 159 | return NULL; 160 | } 161 | 162 | item = beast_mm_malloc(msize); 163 | 164 | if (!item) { 165 | beast_write_log(beast_log_notice, 166 | "Not enough memory for alloc cache"); 167 | return NULL; 168 | } 169 | 170 | item->key.device = key->device; 171 | item->key.inode = key->inode; 172 | item->key.fsize = key->fsize; 173 | item->key.mtime = key->mtime; 174 | 175 | item->next = NULL; 176 | 177 | return item; 178 | } 179 | 180 | 181 | /* 182 | * Push cache item into cache manager, 183 | * this function return a cache item, 184 | * may be return value not equals push item, 185 | * so we must use return value. 186 | */ 187 | cache_item_t *beast_cache_push(cache_item_t *item) 188 | { 189 | unsigned int hashval = beast_cache_hash(&item->key); 190 | unsigned int index = hashval % BUCKETS_DEFAULT_SIZE; 191 | 192 | beast_cache_lock(); 193 | 194 | item->next = beast_cache_buckets[index]; 195 | beast_cache_buckets[index] = item; 196 | 197 | beast_cache_unlock(); 198 | 199 | return item; 200 | } 201 | 202 | 203 | int beast_cache_destroy() 204 | { 205 | if (!beast_cache_initialization) { 206 | return 0; 207 | } 208 | 209 | beast_mm_destroy(); /* Destroy memory manager */ 210 | 211 | /* Free cache buckets's mmap memory */ 212 | beast_shm_free((void *)beast_cache_buckets, 213 | sizeof(cache_item_t *) * BUCKETS_DEFAULT_SIZE); 214 | beast_shm_free((void *)cache_lock, sizeof(int)); 215 | beast_cache_initialization = 0; 216 | 217 | return 0; 218 | } 219 | 220 | 221 | void beast_cache_info(zval *retval) 222 | { 223 | char key[128]; 224 | int i; 225 | cache_item_t *item; 226 | 227 | beast_cache_lock(); 228 | 229 | for (i = 0; i < BUCKETS_DEFAULT_SIZE; i++) { 230 | item = beast_cache_buckets[i]; 231 | while (item) { 232 | sprintf(key, "{device(%d)#inode(%d)}", 233 | item->key.device, item->key.inode); 234 | add_assoc_long(retval, key, item->key.fsize); 235 | item = item->next; 236 | } 237 | } 238 | 239 | beast_cache_unlock(); 240 | } 241 | 242 | void beast_cache_flush() 243 | { 244 | int index; 245 | 246 | beast_cache_lock(); 247 | 248 | /* Flush hash buckets */ 249 | for (index = 0; index < BUCKETS_DEFAULT_SIZE; index++) { 250 | beast_cache_buckets[index] = NULL; 251 | } 252 | 253 | /* Flush share memory */ 254 | beast_mm_flush(); 255 | 256 | beast_cache_unlock(); 257 | } 258 | -------------------------------------------------------------------------------- /cache.h: -------------------------------------------------------------------------------- 1 | #ifndef __BEAST_CACHE_H 2 | #define __BEAST_CACHE_H 3 | 4 | typedef struct cache_key_s { 5 | int device; 6 | int inode; 7 | int mtime; 8 | int fsize; 9 | } cache_key_t; 10 | 11 | 12 | typedef struct cache_item_s { 13 | cache_key_t key; 14 | struct cache_item_s *next; 15 | char data[0]; 16 | } cache_item_t; 17 | 18 | 19 | #define beast_cache_data(item) (item)->data 20 | #define beast_cache_size(item) (item)->key.fsize 21 | 22 | int beast_cache_init(); 23 | cache_item_t *beast_cache_find(cache_key_t *key); 24 | cache_item_t *beast_cache_create(cache_key_t *key); 25 | cache_item_t *beast_cache_push(cache_item_t *item); 26 | int beast_cache_destroy(); 27 | void beast_cache_flush(); 28 | 29 | void beast_cache_lock(); 30 | void beast_cache_unlock(); 31 | void beast_cache_info(zval *); 32 | 33 | #endif 34 | -------------------------------------------------------------------------------- /config.m4: -------------------------------------------------------------------------------- 1 | dnl $Id$ 2 | dnl config.m4 for extension beast 3 | 4 | dnl Comments in this file start with the string 'dnl'. 5 | dnl Remove where necessary. This file will not work 6 | dnl without editing. 7 | 8 | dnl If your extension references something external, use with: 9 | 10 | dnl PHP_ARG_WITH(beast, for beast support, 11 | dnl Make sure that the comment is aligned: 12 | dnl [ --with-beast Include beast support]) 13 | 14 | dnl Otherwise use enable: 15 | 16 | PHP_ARG_ENABLE(beast, whether to enable beast support, 17 | dnl Make sure that the comment is aligned: 18 | [ --enable-beast Enable beast support]) 19 | 20 | PHP_ARG_ENABLE(beast-debug, whether to enable beast debug mode, 21 | dnl Make sure that the comment is aligned: 22 | [ --enable-beast-debug Enable beast debug mode], no, no) 23 | 24 | PHP_ARG_ENABLE(execute-normal-script, whether to enable execute normal PHP script mode, 25 | dnl Make sure that the comment is aligned: 26 | [ --enable-execute-normal-script Enable execute normal PHP script], yes, yes) 27 | 28 | if test "$PHP_BEAST" != "no"; then 29 | dnl Write more examples of tests here... 30 | 31 | if test "$PHP_BEAST_DEBUG" != "yes"; then 32 | AC_DEFINE(BEAST_DEBUG_MODE, 0, [ ]) 33 | else 34 | AC_DEFINE(BEAST_DEBUG_MODE, 1, [ ]) 35 | fi 36 | 37 | if test "$PHP_EXECUTE_NORMAL_SCRIPT" != "yes"; then 38 | AC_DEFINE(BEAST_EXECUTE_NORMAL_SCRIPT, 0, [ ]) 39 | else 40 | AC_DEFINE(BEAST_EXECUTE_NORMAL_SCRIPT, 1, [ ]) 41 | fi 42 | 43 | dnl # --with-beast -> check with-path 44 | dnl SEARCH_PATH="/usr/local /usr" # you might want to change this 45 | dnl SEARCH_FOR="/include/beast.h" # you most likely want to change this 46 | dnl if test -r $PHP_BEAST/$SEARCH_FOR; then # path given as parameter 47 | dnl BEAST_DIR=$PHP_BEAST 48 | dnl else # search default path list 49 | dnl AC_MSG_CHECKING([for beast files in default path]) 50 | dnl for i in $SEARCH_PATH ; do 51 | dnl if test -r $i/$SEARCH_FOR; then 52 | dnl BEAST_DIR=$i 53 | dnl AC_MSG_RESULT(found in $i) 54 | dnl fi 55 | dnl done 56 | dnl fi 57 | dnl 58 | dnl if test -z "$BEAST_DIR"; then 59 | dnl AC_MSG_RESULT([not found]) 60 | dnl AC_MSG_ERROR([Please reinstall the beast distribution]) 61 | dnl fi 62 | 63 | dnl # --with-beast -> add include path 64 | dnl PHP_ADD_INCLUDE($BEAST_DIR/include) 65 | 66 | dnl # --with-beast -> check for lib and symbol presence 67 | dnl LIBNAME=beast # you may want to change this 68 | dnl LIBSYMBOL=beast # you most likely want to change this 69 | 70 | dnl PHP_CHECK_LIBRARY($LIBNAME,$LIBSYMBOL, 71 | dnl [ 72 | dnl PHP_ADD_LIBRARY_WITH_PATH($LIBNAME, $BEAST_DIR/lib, BEAST_SHARED_LIBADD) 73 | dnl AC_DEFINE(HAVE_BEASTLIB,1,[ ]) 74 | dnl ],[ 75 | dnl AC_MSG_ERROR([wrong beast lib version or lib not found]) 76 | dnl ],[ 77 | dnl -L$BEAST_DIR/lib -lm -ldl 78 | dnl ]) 79 | dnl 80 | dnl PHP_SUBST(BEAST_SHARED_LIBADD) 81 | 82 | PHP_NEW_EXTENSION(beast, beast.c aes_algo_handler.c des_algo_handler.c base64_algo_handler.c beast_mm.c spinlock.c cache.c beast_log.c global_algo_modules.c header.c networkcards.c tmpfile_file_handler.c pipe_file_handler.c file_handler_switch.c shm.c, $ext_shared) 83 | fi 84 | -------------------------------------------------------------------------------- /config.w32: -------------------------------------------------------------------------------- 1 | // $Id$ 2 | // vim:ft=javascript 3 | 4 | // If your extension references something external 5 | ARG_WITH("beast", "for beast support", "yes,shared"); 6 | 7 | 8 | ARG_ENABLE("beast", "enable beast support", "yes,shared"); 9 | 10 | ARG_ENABLE("beast-debug", "enable beast debug mode", "no"); 11 | 12 | if (PHP_BEAST != "no") { 13 | if (PHP_BEAST_DEBUG != "no") { 14 | AC_DEFINE('BEAST_DEBUG_MODE', 1, 'Debug support in beast'); 15 | } 16 | 17 | EXTENSION("beast", "beast.c aes_algo_handler.c des_algo_handler.c base64_algo_handler.c beast_mm.c spinlock.c cache.c beast_log.c global_algo_modules.c header.c networkcards.c tmpfile_file_handler.c file_handler_switch.c shm.c", true); 18 | } 19 | 20 | -------------------------------------------------------------------------------- /des_algo_handler.c: -------------------------------------------------------------------------------- 1 | /** 2 | * DES encrypt algorithms handler module for Beast 3 | * @author: liexusong 4 | */ 5 | 6 | #include 7 | #include 8 | #include "beast_log.h" 9 | #include "beast_module.h" 10 | #include "des_algo_lib.c" 11 | 12 | 13 | static char key[8] = { 14 | 0x01, 0x1f, 0x01, 0x1f, 15 | 0x01, 0x0e, 0x01, 0x0e, 16 | }; 17 | 18 | 19 | int des_encrypt_handler(char *inbuf, int len, 20 | char **outbuf, int *outlen) 21 | { 22 | int blocks, i, fixcnt; 23 | char input[8], output[8]; 24 | char *out; 25 | int retlen; 26 | 27 | if ((len % 8) == 0) { 28 | fixcnt = 0; 29 | blocks = len / 8; 30 | 31 | } else { 32 | fixcnt = len % 8; 33 | blocks = len / 8 + 1; 34 | } 35 | 36 | retlen = blocks * 8; 37 | 38 | out = malloc(retlen); 39 | if (!out) { 40 | beast_write_log(beast_log_error, 41 | "Out of memory when allocate `%d' size by encrypt(DES)", retlen); 42 | return -1; 43 | } 44 | 45 | for (i = 0; i < blocks; i++) { 46 | memset(input, 0, 8); 47 | 48 | /* The last block not enough 8 bytes, fix me */ 49 | if (i + 1 == blocks && fixcnt > 0) { 50 | memcpy(input, &inbuf[i*8], fixcnt); 51 | } else { 52 | memcpy(input, &inbuf[i*8], 8); 53 | } 54 | 55 | DES_encipher(input, output, key); 56 | 57 | memcpy(&out[i * 8], output, 8); 58 | } 59 | 60 | *outbuf = out; 61 | *outlen = retlen; 62 | 63 | return 0; 64 | } 65 | 66 | 67 | int des_decrypt_handler(char *inbuf, int len, 68 | char **outbuf, int *outlen) 69 | { 70 | int blocks, retlen, i; 71 | char *out; 72 | 73 | if (len % 8 == 0) { 74 | blocks = len / 8; 75 | } else { 76 | blocks = len / 8 + 1; 77 | } 78 | 79 | retlen = blocks * 8; 80 | 81 | out = malloc(retlen); 82 | if (!out) { 83 | beast_write_log(beast_log_error, 84 | "Out of memory when allocate `%d' size by decrypt(DES)", retlen); 85 | return -1; 86 | } 87 | 88 | for (i = 0; i < blocks; i++) { 89 | DES_decipher(&inbuf[i*8], &out[i*8], key); 90 | } 91 | 92 | *outbuf = out; 93 | *outlen = retlen; 94 | 95 | return 0; 96 | } 97 | 98 | 99 | void des_free_handler(void *ptr) 100 | { 101 | if (ptr) { 102 | free(ptr); 103 | } 104 | } 105 | 106 | struct beast_ops des_handler_ops = { 107 | "des-algo", 108 | des_encrypt_handler, 109 | des_decrypt_handler, 110 | des_free_handler, 111 | NULL 112 | }; 113 | -------------------------------------------------------------------------------- /des_algo_lib.c: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | * * 3 | * --------------------------------- des.c -------------------------------- * 4 | * * 5 | *****************************************************************************/ 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | /***************************************************************************** 13 | * * 14 | * -------------------------------- bit_get ------------------------------- * 15 | * * 16 | *****************************************************************************/ 17 | 18 | int bit_get(const unsigned char *bits, int pos) { 19 | 20 | unsigned char mask; 21 | 22 | int i; 23 | 24 | /***************************************************************************** 25 | * * 26 | * Set a mask for the bit to get. * 27 | * * 28 | *****************************************************************************/ 29 | 30 | mask = 0x80; 31 | 32 | for (i = 0; i < (pos % 8); i++) 33 | mask = mask >> 1; 34 | 35 | /***************************************************************************** 36 | * * 37 | * Get the bit. * 38 | * * 39 | *****************************************************************************/ 40 | 41 | return (((mask & bits[(int)(pos / 8)]) == mask) ? 1 : 0); 42 | 43 | } 44 | 45 | /***************************************************************************** 46 | * * 47 | * -------------------------------- bit_set ------------------------------- * 48 | * * 49 | *****************************************************************************/ 50 | 51 | void bit_set(unsigned char *bits, int pos, int state) { 52 | 53 | unsigned char mask; 54 | 55 | int i; 56 | 57 | /***************************************************************************** 58 | * * 59 | * Set a mask for the bit to set. * 60 | * * 61 | *****************************************************************************/ 62 | 63 | mask = 0x80; 64 | 65 | for (i = 0; i < (pos % 8); i++) 66 | mask = mask >> 1; 67 | 68 | /***************************************************************************** 69 | * * 70 | * Set the bit. * 71 | * * 72 | *****************************************************************************/ 73 | 74 | if (state) 75 | bits[pos / 8] = bits[pos / 8] | mask; 76 | else 77 | bits[pos / 8] = bits[pos / 8] & (~mask); 78 | 79 | return; 80 | 81 | } 82 | 83 | /***************************************************************************** 84 | * * 85 | * -------------------------------- bit_xor ------------------------------- * 86 | * * 87 | *****************************************************************************/ 88 | 89 | void bit_xor(const unsigned char *bits1, const unsigned char *bits2, unsigned 90 | char *bitsx, int size) { 91 | 92 | int i; 93 | 94 | /***************************************************************************** 95 | * * 96 | * Compute the bitwise XOR (exclusive OR) of the two buffers. * 97 | * * 98 | *****************************************************************************/ 99 | 100 | for (i = 0; i < size; i++) { 101 | 102 | if (bit_get(bits1, i) != bit_get(bits2, i)) 103 | bit_set(bitsx, i, 1); 104 | else 105 | bit_set(bitsx, i, 0); 106 | 107 | } 108 | 109 | return; 110 | 111 | } 112 | 113 | /***************************************************************************** 114 | * * 115 | * ----------------------------- bit_rot_left ----------------------------- * 116 | * * 117 | *****************************************************************************/ 118 | 119 | void bit_rot_left(unsigned char *bits, int size, int count) { 120 | 121 | int fbit, 122 | lbit, 123 | i, 124 | j; 125 | 126 | /***************************************************************************** 127 | * * 128 | * Rotate the buffer to the left the specified number of bits. * 129 | * * 130 | *****************************************************************************/ 131 | 132 | if (size > 0) { 133 | 134 | for (j = 0; j < count; j++) { 135 | 136 | for (i = 0; i <= ((size - 1) / 8); i++) { 137 | 138 | /******************************************************************** 139 | * * 140 | * Get the bit about to be shifted off the current byte. * 141 | * * 142 | ********************************************************************/ 143 | 144 | lbit = bit_get(&bits[i], 0); 145 | 146 | if (i == 0) { 147 | 148 | /***************************************************************** 149 | * * 150 | * Save the bit shifted off the first byte for later. * 151 | * * 152 | *****************************************************************/ 153 | 154 | fbit = lbit; 155 | 156 | } 157 | 158 | else { 159 | 160 | /***************************************************************** 161 | * * 162 | * Set the rightmost bit of the previous byte to the leftmost * 163 | * bit about to be shifted off the current byte. * 164 | * * 165 | *****************************************************************/ 166 | 167 | bit_set(&bits[i - 1], 7, lbit); 168 | 169 | } 170 | 171 | /******************************************************************** 172 | * * 173 | * Shift the current byte to the left. * 174 | * * 175 | ********************************************************************/ 176 | 177 | bits[i] = bits[i] << 1; 178 | 179 | } 180 | 181 | /*********************************************************************** 182 | * * 183 | * Set the rightmost bit of the buffer to the bit shifted off the * 184 | * first byte. * 185 | * * 186 | ***********************************************************************/ 187 | 188 | bit_set(bits, size - 1, fbit); 189 | 190 | } 191 | 192 | } 193 | 194 | return; 195 | 196 | } 197 | 198 | /***************************************************************************** 199 | * * 200 | * Define a mapping for the key transformation. * 201 | * * 202 | *****************************************************************************/ 203 | 204 | static const int DesTransform[56] = { 205 | 206 | 57, 49, 41, 33, 25, 17, 9, 1, 58, 50, 42, 34, 26, 18, 207 | 10, 2, 59, 51, 43, 35, 27, 19, 11, 3, 60, 52, 44, 36, 208 | 63, 55, 47, 39, 31, 23, 15, 7, 62, 54, 46, 38, 30, 22, 209 | 14, 6, 61, 53, 45, 37, 29, 21, 13, 5, 28, 20, 12, 4 210 | 211 | }; 212 | 213 | /***************************************************************************** 214 | * * 215 | * Define the number of rotations for computing subkeys. * 216 | * * 217 | *****************************************************************************/ 218 | 219 | static const int DesRotations[16] = { 220 | 221 | 1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1 222 | 223 | }; 224 | 225 | /***************************************************************************** 226 | * * 227 | * Define a mapping for the permuted choice for subkeys. * 228 | * * 229 | *****************************************************************************/ 230 | 231 | static const int DesPermuted[48] = { 232 | 233 | 14, 17, 11, 24, 1, 5, 3, 28, 15, 6, 21, 10, 234 | 23, 19, 12, 4, 26, 8, 16, 7, 27, 20, 13, 2, 235 | 41, 52, 31, 37, 47, 55, 30, 40, 51, 45, 33, 48, 236 | 44, 49, 39, 56, 34, 53, 46, 42, 50, 36, 29, 32 237 | 238 | }; 239 | 240 | /***************************************************************************** 241 | * * 242 | * Define a mapping for the initial permutation of data blocks. * 243 | * * 244 | *****************************************************************************/ 245 | 246 | static const int DesInitial[64] = { 247 | 248 | 58, 50, 42, 34, 26, 18, 10, 2, 60, 52, 44, 36, 28, 20, 12, 4, 249 | 62, 54, 46, 38, 30, 22, 14, 6, 64, 56, 48, 40, 32, 24, 16, 8, 250 | 57, 49, 41, 33, 25, 17, 9, 1, 59, 51, 43, 35, 27, 19, 11, 3, 251 | 61, 53, 45, 37, 29, 21, 13, 5, 63, 55, 47, 39, 31, 23, 15, 7 252 | 253 | }; 254 | 255 | /***************************************************************************** 256 | * * 257 | * Define a mapping for the expansion permutation of data blocks. * 258 | * * 259 | *****************************************************************************/ 260 | 261 | static const int DesExpansion[48] = { 262 | 263 | 32, 1, 2, 3, 4, 5, 4, 5, 6, 7, 8, 9, 264 | 8, 9, 10, 11, 12, 13, 12, 13, 14, 15, 16, 17, 265 | 16, 17, 18, 19, 20, 21, 20, 21, 22, 23, 24, 25, 266 | 24, 25, 26, 27, 28, 29, 28, 29, 30, 31, 32, 1 267 | 268 | }; 269 | 270 | /***************************************************************************** 271 | * * 272 | * Define tables for the S-box substitutions performed for data blocks. * 273 | * * 274 | *****************************************************************************/ 275 | 276 | static const int DesSbox[8][4][16] = { 277 | 278 | { 279 | {14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7}, 280 | { 0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8}, 281 | { 4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0}, 282 | {15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13}, 283 | }, 284 | 285 | { 286 | {15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10}, 287 | { 3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5}, 288 | { 0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15}, 289 | {13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9}, 290 | }, 291 | 292 | { 293 | {10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8}, 294 | {13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1}, 295 | {13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7}, 296 | { 1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12}, 297 | }, 298 | 299 | { 300 | { 7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15}, 301 | {13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9}, 302 | {10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4}, 303 | { 3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14}, 304 | }, 305 | 306 | { 307 | { 2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9}, 308 | {14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6}, 309 | { 4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14}, 310 | {11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3}, 311 | }, 312 | 313 | { 314 | {12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11}, 315 | {10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8}, 316 | { 9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6}, 317 | { 4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13}, 318 | }, 319 | 320 | { 321 | { 4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1}, 322 | {13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6}, 323 | { 1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2}, 324 | { 6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12}, 325 | }, 326 | 327 | { 328 | {13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7}, 329 | { 1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2}, 330 | { 7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8}, 331 | { 2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11}, 332 | }, 333 | 334 | }; 335 | 336 | /***************************************************************************** 337 | * * 338 | * Define a mapping for the P-box permutation of data blocks. * 339 | * * 340 | *****************************************************************************/ 341 | 342 | static const int DesPbox[32] = { 343 | 344 | 16, 7, 20, 21, 29, 12, 28, 17, 1, 15, 23, 26, 5, 18, 31, 10, 345 | 2, 8, 24, 14, 32, 27, 3, 9, 19, 13, 30, 6, 22, 11, 4, 25 346 | 347 | }; 348 | 349 | /***************************************************************************** 350 | * * 351 | * Define a mapping for the final permutation of data blocks. * 352 | * * 353 | *****************************************************************************/ 354 | 355 | static const int DesFinal[64] = { 356 | 357 | 40, 8, 48, 16, 56, 24, 64, 32, 39, 7, 47, 15, 55, 23, 63, 31, 358 | 38, 6, 46, 14, 54, 22, 62, 30, 37, 5, 45, 13, 53, 21, 61, 29, 359 | 36, 4, 44, 12, 52, 20, 60, 28, 35, 3, 43, 11, 51, 19, 59, 27, 360 | 34, 2, 42, 10, 50, 18, 58, 26, 33, 1, 41, 9, 49, 17, 57, 25 361 | 362 | }; 363 | 364 | /***************************************************************************** 365 | * * 366 | * Define a type for whether to encipher or decipher data. * 367 | * * 368 | *****************************************************************************/ 369 | 370 | typedef enum DesEorD_ {encipher, decipher} DesEorD; 371 | 372 | /***************************************************************************** 373 | * * 374 | * -------------------------------- permute ------------------------------- * 375 | * * 376 | *****************************************************************************/ 377 | 378 | static void permute(unsigned char *bits, const int *mapping, int n) { 379 | 380 | unsigned char temp[8]; 381 | 382 | int i; 383 | 384 | /***************************************************************************** 385 | * * 386 | * Permute the buffer using an n-entry mapping. * 387 | * * 388 | *****************************************************************************/ 389 | 390 | memset(temp, 0, (int)ceil(n / 8)); 391 | 392 | for (i = 0; i < n; i++) 393 | bit_set(temp, i, bit_get(bits, mapping[i] - 1)); 394 | 395 | memcpy(bits, temp, (int)ceil(n / 8)); 396 | 397 | return; 398 | 399 | } 400 | 401 | /***************************************************************************** 402 | * * 403 | * ------------------------------- des_main ------------------------------- * 404 | * * 405 | *****************************************************************************/ 406 | 407 | static int DES_main(const unsigned char *source, unsigned char *target, const 408 | unsigned char *key, DesEorD direction) { 409 | 410 | static unsigned char subkeys[16][7]; 411 | 412 | unsigned char temp[8], 413 | lkey[4], 414 | rkey[4], 415 | lblk[6], 416 | rblk[6], 417 | fblk[6], 418 | xblk[6], 419 | sblk; 420 | 421 | int row, 422 | col, 423 | i, 424 | j, 425 | k, 426 | p; 427 | 428 | /***************************************************************************** 429 | * * 430 | * If key is NULL, use the subkeys as computed in a previous call. * 431 | * * 432 | *****************************************************************************/ 433 | 434 | if (key != NULL) { 435 | 436 | /************************************************************************** 437 | * * 438 | * Make a local copy of the key. * 439 | * * 440 | **************************************************************************/ 441 | 442 | memcpy(temp, key, 8); 443 | 444 | /************************************************************************** 445 | * * 446 | * Permute and compress the key into 56 bits. * 447 | * * 448 | **************************************************************************/ 449 | 450 | permute(temp, DesTransform, 56); 451 | 452 | /************************************************************************** 453 | * * 454 | * Split the key into two 28-bit blocks. * 455 | * * 456 | **************************************************************************/ 457 | 458 | memset(lkey, 0, 4); 459 | memset(rkey, 0, 4); 460 | 461 | for (j = 0; j < 28; j++) 462 | bit_set(lkey, j, bit_get(temp, j)); 463 | 464 | for (j = 0; j < 28; j++) 465 | bit_set(rkey, j, bit_get(temp, j + 28)); 466 | 467 | /************************************************************************** 468 | * * 469 | * Compute the subkeys for each round. * 470 | * * 471 | **************************************************************************/ 472 | 473 | for (i = 0; i < 16; i++) { 474 | 475 | /*********************************************************************** 476 | * * 477 | * Rotate each block according to its round. * 478 | * * 479 | ***********************************************************************/ 480 | 481 | bit_rot_left(lkey, 28, DesRotations[i]); 482 | bit_rot_left(rkey, 28, DesRotations[i]); 483 | 484 | /*********************************************************************** 485 | * * 486 | * Concatenate the blocks into a single subkey. * 487 | * * 488 | ***********************************************************************/ 489 | 490 | for (j = 0; j < 28; j++) 491 | bit_set(subkeys[i], j, bit_get(lkey, j)); 492 | 493 | for (j = 0; j < 28; j++) 494 | bit_set(subkeys[i], j + 28, bit_get(rkey, j)); 495 | 496 | /*********************************************************************** 497 | * * 498 | * Do the permuted choice permutation. * 499 | * * 500 | ***********************************************************************/ 501 | 502 | permute(subkeys[i], DesPermuted, 48); 503 | 504 | } 505 | 506 | } 507 | 508 | /***************************************************************************** 509 | * * 510 | * Make a local copy of the source text. * 511 | * * 512 | *****************************************************************************/ 513 | 514 | memcpy(temp, source, 8); 515 | 516 | /***************************************************************************** 517 | * * 518 | * Do the initial permutation. * 519 | * * 520 | *****************************************************************************/ 521 | 522 | permute(temp, DesInitial, 64); 523 | 524 | /***************************************************************************** 525 | * * 526 | * Split the source text into a left and right block of 32 bits. * 527 | * * 528 | *****************************************************************************/ 529 | 530 | memcpy(lblk, &temp[0], 4); 531 | memcpy(rblk, &temp[4], 4); 532 | 533 | /***************************************************************************** 534 | * * 535 | * Encipher or decipher the source text. * 536 | * * 537 | *****************************************************************************/ 538 | 539 | for (i = 0; i < 16; i++) { 540 | 541 | /************************************************************************** 542 | * * 543 | * Begin the computation of f. * 544 | * * 545 | **************************************************************************/ 546 | 547 | memcpy(fblk, rblk, 4); 548 | 549 | /************************************************************************** 550 | * * 551 | * Permute and expand the copy of the right block into 48 bits. * 552 | * * 553 | **************************************************************************/ 554 | 555 | permute(fblk, DesExpansion, 48); 556 | 557 | /************************************************************************** 558 | * * 559 | * Apply the appropriate subkey for the round. * 560 | * * 561 | **************************************************************************/ 562 | 563 | if (direction == encipher) { 564 | 565 | /*********************************************************************** 566 | * * 567 | * For enciphering, subkeys are applied in increasing order. * 568 | * * 569 | ***********************************************************************/ 570 | 571 | bit_xor(fblk, subkeys[i], xblk, 48); 572 | memcpy(fblk, xblk, 6); 573 | 574 | } 575 | 576 | else { 577 | 578 | /*********************************************************************** 579 | * * 580 | * For deciphering, subkeys are applied in decreasing order. * 581 | * * 582 | ***********************************************************************/ 583 | 584 | bit_xor(fblk, subkeys[15 - i], xblk, 48); 585 | memcpy(fblk, xblk, 6); 586 | 587 | } 588 | 589 | /************************************************************************** 590 | * * 591 | * Do the S-box substitutions. * 592 | * * 593 | **************************************************************************/ 594 | 595 | p = 0; 596 | 597 | for (j = 0; j < 8; j++) { 598 | 599 | /*********************************************************************** 600 | * * 601 | * Compute a row and column into the S-box tables. * 602 | * * 603 | ***********************************************************************/ 604 | 605 | row = (bit_get(fblk, (j * 6)+0) * 2) + (bit_get(fblk, (j * 6)+5) * 1); 606 | col = (bit_get(fblk, (j * 6)+1) * 8) + (bit_get(fblk, (j * 6)+2) * 4) + 607 | (bit_get(fblk, (j * 6)+3) * 2) + (bit_get(fblk, (j * 6)+4) * 1); 608 | 609 | /*********************************************************************** 610 | * * 611 | * Do the S-box substitution for the current six-bit block. * 612 | * * 613 | ***********************************************************************/ 614 | 615 | sblk = (unsigned char)DesSbox[j][row][col]; 616 | 617 | for (k = 4; k < 8; k++) { 618 | 619 | bit_set(fblk, p, bit_get(&sblk, k)); 620 | p++; 621 | 622 | } 623 | 624 | } 625 | 626 | /************************************************************************** 627 | * * 628 | * Do the P-box permutation to complete f. * 629 | * * 630 | **************************************************************************/ 631 | 632 | permute(fblk, DesPbox, 32); 633 | 634 | /************************************************************************** 635 | * * 636 | * Compute the XOR of the left block and f. * 637 | * * 638 | **************************************************************************/ 639 | 640 | bit_xor(lblk, fblk, xblk, 32); 641 | 642 | /************************************************************************** 643 | * * 644 | * Set the left block for the round. * 645 | * * 646 | **************************************************************************/ 647 | 648 | memcpy(lblk, rblk, 4); 649 | 650 | /************************************************************************** 651 | * * 652 | * Set the right block for the round. * 653 | * * 654 | **************************************************************************/ 655 | 656 | memcpy(rblk, xblk, 4); 657 | 658 | } 659 | 660 | /***************************************************************************** 661 | * * 662 | * Set the target text to the rejoined final right and left blocks. * 663 | * * 664 | *****************************************************************************/ 665 | 666 | memcpy(&target[0], rblk, 4); 667 | memcpy(&target[4], lblk, 4); 668 | 669 | /***************************************************************************** 670 | * * 671 | * Do the final permutation. * 672 | * * 673 | *****************************************************************************/ 674 | 675 | permute(target, DesFinal, 64); 676 | 677 | return 0; 678 | 679 | } 680 | 681 | /***************************************************************************** 682 | * * 683 | * ----------------------------- DES_encipher ----------------------------- * 684 | * * 685 | *****************************************************************************/ 686 | 687 | void DES_encipher(const unsigned char *plaintext, unsigned char *ciphertext, 688 | const unsigned char *key) { 689 | 690 | DES_main(plaintext, ciphertext, key, encipher); 691 | 692 | return; 693 | 694 | } 695 | 696 | /***************************************************************************** 697 | * * 698 | * ----------------------------- DES_decipher ----------------------------- * 699 | * * 700 | *****************************************************************************/ 701 | 702 | void DES_decipher(const unsigned char *ciphertext, unsigned char *plaintext, 703 | const unsigned char *key) { 704 | 705 | DES_main(ciphertext, plaintext, key, decipher); 706 | 707 | return; 708 | 709 | } 710 | 711 | -------------------------------------------------------------------------------- /file_handler.h: -------------------------------------------------------------------------------- 1 | #ifndef __FILE_HANDLER_H 2 | #define __FILE_HANDLER_H 3 | 4 | #include 5 | 6 | #define BEAST_FILE_HANDLER_FP 1 7 | #define BEAST_FILE_HANDLER_FD 2 8 | 9 | struct file_handler { 10 | char *name; 11 | int type; 12 | void *ctx; 13 | int (*check)(); 14 | int (*open)(struct file_handler *self); 15 | int (*write)(struct file_handler *self, char *buf, int size); 16 | int (*rewind)(struct file_handler *self); 17 | int (*get_fd)(struct file_handler *self); 18 | FILE *(*get_fp)(struct file_handler *self); 19 | int (*destroy)(struct file_handler *self); 20 | }; 21 | 22 | #endif 23 | -------------------------------------------------------------------------------- /file_handler_switch.c: -------------------------------------------------------------------------------- 1 | 2 | char *file_handler_switch = "tmpfile"; 3 | -------------------------------------------------------------------------------- /global_algo_modules.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "beast_module.h" 3 | 4 | extern struct beast_ops des_handler_ops; 5 | extern struct beast_ops aes_handler_ops; 6 | extern struct beast_ops base64_handler_ops; 7 | 8 | struct beast_ops *ops_handler_list[] = { 9 | &des_handler_ops, 10 | &aes_handler_ops, 11 | &base64_handler_ops, 12 | NULL, 13 | }; 14 | -------------------------------------------------------------------------------- /header.c: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * You can modify this sign to disguise your encrypt file 4 | */ 5 | char encrypt_file_header_sign[] = { 6 | 0xe8, 0x16, 0xa4, 0x0c, 7 | 0xf2, 0xb2, 0x60, 0xee 8 | }; 9 | 10 | int encrypt_file_header_length = sizeof(encrypt_file_header_sign); 11 | -------------------------------------------------------------------------------- /images/beast1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liexusong/php-beast/4549b2a642a9b04408b4bfbb3af64131c7f1f2dd/images/beast1.png -------------------------------------------------------------------------------- /images/beast2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liexusong/php-beast/4549b2a642a9b04408b4bfbb3af64131c7f1f2dd/images/beast2.png -------------------------------------------------------------------------------- /images/pay.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liexusong/php-beast/4549b2a642a9b04408b4bfbb3af64131c7f1f2dd/images/pay.jpg -------------------------------------------------------------------------------- /networkcards.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /* 4 | * Allow network card. if this list empty, this feature was closed! 5 | */ 6 | 7 | char *allow_networkcards[] = { 8 | NULL, 9 | }; 10 | -------------------------------------------------------------------------------- /php_beast.h: -------------------------------------------------------------------------------- 1 | /* 2 | +----------------------------------------------------------------------+ 3 | | PHP Version 5 | 4 | +----------------------------------------------------------------------+ 5 | | Copyright (c) 1997-2007 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 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: | 16 | +----------------------------------------------------------------------+ 17 | */ 18 | 19 | /* $Id: header,v 1.16.2.1.2.1 2007/01/01 19:32:09 iliaa Exp $ */ 20 | 21 | #ifndef PHP_BEAST_H 22 | #define PHP_BEAST_H 23 | 24 | extern zend_module_entry beast_module_entry; 25 | #define phpext_beast_ptr &beast_module_entry 26 | 27 | #ifdef PHP_WIN32 28 | #define PHP_BEAST_API __declspec(dllexport) 29 | #else 30 | #define PHP_BEAST_API 31 | #endif 32 | 33 | #ifdef ZTS 34 | #include "TSRM.h" 35 | #endif 36 | 37 | PHP_MINIT_FUNCTION(beast); 38 | PHP_MSHUTDOWN_FUNCTION(beast); 39 | PHP_RINIT_FUNCTION(beast); 40 | PHP_RSHUTDOWN_FUNCTION(beast); 41 | PHP_MINFO_FUNCTION(beast); 42 | 43 | PHP_FUNCTION(beast_encode_file); 44 | PHP_FUNCTION(beast_avail_cache); 45 | PHP_FUNCTION(beast_support_filesize); 46 | PHP_FUNCTION(beast_file_expire); 47 | PHP_FUNCTION(beast_clean_cache); 48 | 49 | /* 50 | Declare any global variables you may need between the BEGIN 51 | and END macros here: 52 | 53 | ZEND_BEGIN_MODULE_GLOBALS(beast) 54 | long global_value; 55 | char *global_string; 56 | ZEND_END_MODULE_GLOBALS(beast) 57 | */ 58 | 59 | /* In every utility function you add that needs to use variables 60 | in php_beast_globals, call TSRMLS_FETCH(); after declaring other 61 | variables used by that function, or better yet, pass in TSRMLS_CC 62 | after the last function argument and declare your utility function 63 | with TSRMLS_DC after the last declared argument. Always refer to 64 | the globals in your function as BEAST_G(variable). You are 65 | encouraged to rename these macros something shorter, see 66 | examples in any other php module directory. 67 | */ 68 | 69 | #ifdef ZTS 70 | #define BEAST_G(v) TSRMG(beast_globals_id, zend_beast_globals *, v) 71 | #else 72 | #define BEAST_G(v) (beast_globals.v) 73 | #endif 74 | 75 | #endif /* PHP_BEAST_H */ 76 | 77 | 78 | /* 79 | * Local variables: 80 | * tab-width: 4 81 | * c-basic-offset: 4 82 | * End: 83 | * vim600: noet sw=4 ts=4 fdm=marker expandtab 84 | * vim<600: noet sw=4 ts=4 85 | */ 86 | -------------------------------------------------------------------------------- /pipe_file_handler.c: -------------------------------------------------------------------------------- 1 | 2 | #ifndef PHP_WIN32 3 | 4 | #include 5 | #include 6 | #include 7 | #include "file_handler.h" 8 | 9 | struct pipe_handler_ctx { 10 | int fd[2]; 11 | }; 12 | 13 | int pipe_handler_check() 14 | { 15 | return 64 * 1024; 16 | } 17 | 18 | int pipe_handler_open(struct file_handler *self) 19 | { 20 | struct pipe_handler_ctx *ctx = self->ctx; 21 | 22 | if (pipe(ctx->fd) == -1) { 23 | ctx->fd[0] = -1; 24 | ctx->fd[1] = -1; 25 | return -1; 26 | } 27 | 28 | return 0; 29 | } 30 | 31 | int pipe_handler_write(struct file_handler *self, char *buf, int size) 32 | { 33 | struct pipe_handler_ctx *ctx = self->ctx; 34 | 35 | if (write(ctx->fd[1], buf, size) == size) { 36 | return 0; 37 | } 38 | 39 | return -1; 40 | } 41 | 42 | int pipe_handler_rewind(struct file_handler *self) 43 | { 44 | return 0; 45 | } 46 | 47 | FILE *pipe_handler_get_fp(struct file_handler *self) 48 | { 49 | return NULL; 50 | } 51 | 52 | int pipe_handler_get_fd(struct file_handler *self) 53 | { 54 | struct pipe_handler_ctx *ctx = self->ctx; 55 | int retval; 56 | 57 | retval = ctx->fd[0]; 58 | 59 | close(ctx->fd[1]); /* Closed write pipe */ 60 | 61 | ctx->fd[0] = -1; 62 | ctx->fd[1] = -1; 63 | 64 | return retval; 65 | } 66 | 67 | int pipe_handler_destroy(struct file_handler *self) 68 | { 69 | struct pipe_handler_ctx *ctx = self->ctx; 70 | 71 | if (ctx->fd[0] != -1) 72 | close(ctx->fd[0]); 73 | if (ctx->fd[1] != -1) 74 | close(ctx->fd[1]); 75 | 76 | ctx->fd[0] = -1; 77 | ctx->fd[1] = -1; 78 | 79 | return 0; 80 | } 81 | 82 | static struct pipe_handler_ctx _ctx = { 83 | {-1, -1} 84 | }; 85 | 86 | struct file_handler pipe_handler = { 87 | "pipe", 88 | BEAST_FILE_HANDLER_FD, 89 | &_ctx, 90 | pipe_handler_check, 91 | pipe_handler_open, 92 | pipe_handler_write, 93 | pipe_handler_rewind, 94 | pipe_handler_get_fd, 95 | pipe_handler_get_fp, 96 | pipe_handler_destroy 97 | }; 98 | 99 | #endif 100 | -------------------------------------------------------------------------------- /shm.c: -------------------------------------------------------------------------------- 1 | #include "shm.h" 2 | 3 | #ifdef PHP_WIN32 4 | #include 5 | #else 6 | #include 7 | 8 | #ifndef MAP_NOSYNC 9 | #define MAP_NOSYNC 0 10 | #endif 11 | #endif 12 | 13 | void *beast_shm_alloc(size_t size) 14 | { 15 | void *p; 16 | #ifdef PHP_WIN32 17 | HANDLE hMapFile = CreateFileMapping(INVALID_HANDLE_VALUE, 18 | NULL, PAGE_READWRITE, 0, size, NULL); 19 | 20 | if (hMapFile == INVALID_HANDLE_VALUE) { 21 | return NULL; 22 | } 23 | 24 | p = MapViewOfFile( 25 | hMapFile, 26 | FILE_MAP_ALL_ACCESS, 27 | 0, 28 | 0, 29 | size); 30 | CloseHandle(hMapFile); 31 | 32 | #else 33 | 34 | p = mmap(NULL, 35 | size, 36 | PROT_READ|PROT_WRITE, 37 | MAP_SHARED|MAP_ANON, 38 | -1, 39 | 0); 40 | 41 | #endif 42 | return p; 43 | } 44 | 45 | int beast_shm_free(void *p, size_t size) 46 | { 47 | #ifdef PHP_WIN32 48 | return UnmapViewOfFile(p) ? 0 : -1; 49 | #else 50 | return munmap(p, size); 51 | #endif 52 | } 53 | 54 | -------------------------------------------------------------------------------- /shm.h: -------------------------------------------------------------------------------- 1 | #ifndef __SHM_H 2 | #define __SHM_H 3 | 4 | #include 5 | 6 | void *beast_shm_alloc(size_t size); 7 | int beast_shm_free(void *p, size_t size); 8 | 9 | #endif 10 | -------------------------------------------------------------------------------- /spinlock.c: -------------------------------------------------------------------------------- 1 | /* 2 | +----------------------------------------------------------------------+ 3 | | PHP Version 5 | 4 | +----------------------------------------------------------------------+ 5 | | Copyright (c) 1997-2007 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 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: Liexusong <280259971@qq.com> | 16 | +----------------------------------------------------------------------+ 17 | */ 18 | 19 | #include 20 | #include "spinlock.h" 21 | #ifdef PHP_WIN32 22 | #include 23 | #else 24 | #include 25 | #endif 26 | #include "beast_log.h" 27 | 28 | #ifdef PHP_WIN32 29 | #define compare_and_swap(lock, o, n) \ 30 | (InterlockedCompareExchange(lock, n, o) == n) 31 | #define pause() YieldProcessor() 32 | #define yield() SwitchToThread() 33 | #else 34 | #define compare_and_swap(lock, o, n) \ 35 | __sync_bool_compare_and_swap(lock, o, n) 36 | #ifdef __arm__ 37 | #define pause() __asm__("NOP"); 38 | #elif __aarch64__ 39 | #define pause() __asm__("NOP"); 40 | #else 41 | #define pause() __asm__("pause") 42 | #endif 43 | #define yield() sched_yield() 44 | #endif 45 | 46 | extern int beast_ncpu; 47 | 48 | void beast_spinlock(beast_atomic_t *lock, int pid) 49 | { 50 | int i, n; 51 | 52 | for ( ;; ) { 53 | if (compare_and_swap(lock, 0, pid)) { 54 | return; 55 | } 56 | 57 | if (beast_ncpu > 1) { 58 | 59 | for (n = 1; n < 129; n <<= 1) { 60 | 61 | if (compare_and_swap(lock, 0, pid)) { 62 | return; 63 | } 64 | 65 | for (i = 0; i < n; i++) { 66 | pause(); 67 | } 68 | } 69 | } 70 | 71 | yield(); 72 | } 73 | } 74 | 75 | void beast_spinunlock(beast_atomic_t *lock, int pid) 76 | { 77 | compare_and_swap(lock, pid, 0); 78 | } 79 | -------------------------------------------------------------------------------- /spinlock.h: -------------------------------------------------------------------------------- 1 | #ifndef __BEAST_SPINLOCK_H 2 | #define __BEAST_SPINLOCK_H 3 | 4 | typedef volatile unsigned int beast_atomic_t; 5 | 6 | void beast_spinlock(beast_atomic_t *lock, int pid); 7 | void beast_spinunlock(beast_atomic_t *lock, int pid); 8 | 9 | #endif 10 | -------------------------------------------------------------------------------- /tests/001.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Check for beast presence 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | 20 | --EXPECT-- 21 | beast extension is available 22 | -------------------------------------------------------------------------------- /tests/encrypt.php: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include "file_handler.h" 4 | 5 | struct tmpfile_handler_ctx { 6 | FILE *fp; 7 | }; 8 | 9 | int tmpfile_handler_check() 10 | { 11 | return 0; 12 | } 13 | 14 | int tmpfile_handler_open(struct file_handler *self) 15 | { 16 | struct tmpfile_handler_ctx *ctx = self->ctx; 17 | 18 | ctx->fp = tmpfile(); 19 | if (!ctx->fp) { 20 | return -1; 21 | } 22 | 23 | return 0; 24 | } 25 | 26 | int tmpfile_handler_write(struct file_handler *self, char *buf, int size) 27 | { 28 | struct tmpfile_handler_ctx *ctx = self->ctx; 29 | 30 | if (fwrite(buf, 1, size, ctx->fp) == size) { 31 | return 0; 32 | } 33 | 34 | return -1; 35 | } 36 | 37 | int tmpfile_handler_rewind(struct file_handler *self) 38 | { 39 | struct tmpfile_handler_ctx *ctx = self->ctx; 40 | 41 | rewind(ctx->fp); 42 | 43 | return 0; 44 | } 45 | 46 | FILE *tmpfile_handler_get_fp(struct file_handler *self) 47 | { 48 | struct tmpfile_handler_ctx *ctx = self->ctx; 49 | FILE *retval; 50 | 51 | retval = ctx->fp; 52 | ctx->fp = NULL; 53 | 54 | return retval; 55 | } 56 | 57 | int tmpfile_handler_get_fd(struct file_handler *self) 58 | { 59 | return -1; 60 | } 61 | 62 | int tmpfile_handler_destroy(struct file_handler *self) 63 | { 64 | struct tmpfile_handler_ctx *ctx = self->ctx; 65 | 66 | if (ctx->fp) { 67 | fclose(ctx->fp); 68 | } 69 | 70 | ctx->fp = NULL; 71 | 72 | return 0; 73 | } 74 | 75 | static struct tmpfile_handler_ctx _ctx = { 76 | NULL 77 | }; 78 | 79 | struct file_handler tmpfile_handler = { 80 | "tmpfile", 81 | BEAST_FILE_HANDLER_FP, 82 | &_ctx, 83 | tmpfile_handler_check, 84 | tmpfile_handler_open, 85 | tmpfile_handler_write, 86 | tmpfile_handler_rewind, 87 | tmpfile_handler_get_fd, 88 | tmpfile_handler_get_fp, 89 | tmpfile_handler_destroy 90 | }; 91 | -------------------------------------------------------------------------------- /tools/configure.ini: -------------------------------------------------------------------------------- 1 | ; source path 2 | src_path = "" 3 | 4 | ; destination path 5 | dst_path = "" 6 | 7 | ; expire time 8 | expire = "" 9 | 10 | ; encrypt type 11 | encrypt_type = "DES" 12 | -------------------------------------------------------------------------------- /tools/encode_file.php: -------------------------------------------------------------------------------- 1 | 0) 76 | { 77 | if ($expire > 0) { 78 | $result = beast_encode_file($path, $new_path, 79 | $expire, $type); 80 | } else { 81 | $result = beast_encode_file($path, $new_path, 0, $type); 82 | } 83 | 84 | if (!$result) { 85 | echo "Failed to encode file `{$path}'\n"; 86 | } 87 | 88 | $finish++; 89 | 90 | $percent = intval($finish / $nfiles * 100); 91 | 92 | printf("\rProcessed encrypt files [%d%%] - 100%%", $percent); 93 | 94 | } else { 95 | copy($path, $new_path); 96 | } 97 | } 98 | } 99 | 100 | closedir($handle); 101 | } 102 | 103 | //////////////////////////////// run here //////////////////////////////////// 104 | 105 | $conf = parse_ini_file(dirname(__FILE__) . '/configure.ini'); 106 | if (!$conf) { 107 | exit("Fatal: failed to read configure.ini file\n"); 108 | } 109 | 110 | $src_path = trim($conf['src_path']); 111 | $dst_path = trim($conf['dst_path']); 112 | $expire = trim($conf['expire']); 113 | $encrypt_type = strtoupper(trim($conf['encrypt_type'])); 114 | 115 | if (empty($src_path) || !is_dir($src_path)) { 116 | exit("Fatal: source path `{$src_path}' not exists\n\n"); 117 | } 118 | 119 | if (empty($dst_path) 120 | || (!is_dir($dst_path) 121 | && !mkdir($dst_path, 0777))) 122 | { 123 | exit("Fatal: can not create directory `{$dst_path}'\n\n"); 124 | } 125 | 126 | switch ($encrypt_type) 127 | { 128 | case 'AES': 129 | $entype = BEAST_ENCRYPT_TYPE_AES; 130 | break; 131 | case 'BASE64': 132 | $entype = BEAST_ENCRYPT_TYPE_BASE64; 133 | break; 134 | case 'DES': 135 | default: 136 | $entype = BEAST_ENCRYPT_TYPE_DES; 137 | break; 138 | } 139 | 140 | printf("Source code path: %s\n", $src_path); 141 | printf("Destination code path: %s\n", $dst_path); 142 | printf("Expire time: %s\n", $expire); 143 | printf("------------- start process -------------\n"); 144 | 145 | $expire_time = 0; 146 | if ($expire) { 147 | $expire_time = strtotime($expire); 148 | } 149 | 150 | $time = microtime(TRUE); 151 | 152 | calculate_directory_schedule($src_path); 153 | encrypt_directory($src_path, $dst_path, $expire_time, $entype); 154 | 155 | $used = microtime(TRUE) - $time; 156 | 157 | printf("\nFinish processed encrypt files, used %f seconds\n", $used); 158 | --------------------------------------------------------------------------------