├── CREDITS
├── EXPERIMENTAL
├── LICENSE
├── README.md
├── config.m4
├── config.w32
├── handlersocketi class
├── handlersocketi.c
├── handlersocketi_class.c
├── handlersocketi_class.h
├── handlersocketi_exception.c
├── handlersocketi_exception.h
├── handlersocketi_index.c
├── handlersocketi_index.h
├── php_handlersocketi.h
├── php_verdep.h
└── util
├── common.h
├── request.c
├── request.h
├── response.c
└── response.h
/CREDITS:
--------------------------------------------------------------------------------
1 | handlersocketi
2 |
--------------------------------------------------------------------------------
/EXPERIMENTAL:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kjdev/php-ext-handlersocketi/ff47ad829bd152ab4c2c37b4e48982bb975cffcb/EXPERIMENTAL
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | --------------------------------------------------------------------
2 | The PHP License, version 3.01
3 | Copyright (c) 1999 - 2012 The PHP Group. All rights reserved.
4 | --------------------------------------------------------------------
5 |
6 | Redistribution and use in source and binary forms, with or without
7 | modification, is permitted provided that the following conditions
8 | are met:
9 |
10 | 1. Redistributions of source code must retain the above copyright
11 | notice, this list of conditions and the following disclaimer.
12 |
13 | 2. Redistributions in binary form must reproduce the above copyright
14 | notice, this list of conditions and the following disclaimer in
15 | the documentation and/or other materials provided with the
16 | distribution.
17 |
18 | 3. The name "PHP" must not be used to endorse or promote products
19 | derived from this software without prior written permission. For
20 | written permission, please contact group@php.net.
21 |
22 | 4. Products derived from this software may not be called "PHP", nor
23 | may "PHP" appear in their name, without prior written permission
24 | from group@php.net. You may indicate that your software works in
25 | conjunction with PHP by saying "Foo for PHP" instead of calling
26 | it "PHP Foo" or "phpfoo"
27 |
28 | 5. The PHP Group may publish revised and/or new versions of the
29 | license from time to time. Each version will be given a
30 | distinguishing version number.
31 | Once covered code has been published under a particular version
32 | of the license, you may always continue to use it under the terms
33 | of that version. You may also choose to use such covered code
34 | under the terms of any subsequent version of the license
35 | published by the PHP Group. No one other than the PHP Group has
36 | the right to modify the terms applicable to covered code created
37 | under this License.
38 |
39 | 6. Redistributions of any form whatsoever must retain the following
40 | acknowledgment:
41 | "This product includes PHP software, freely available from
42 | ".
43 |
44 | THIS SOFTWARE IS PROVIDED BY THE PHP DEVELOPMENT TEAM ``AS IS'' AND
45 | ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
46 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
47 | PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE PHP
48 | DEVELOPMENT TEAM OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
49 | INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
50 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
51 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
52 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
53 | STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
54 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
55 | OF THE POSSIBILITY OF SUCH DAMAGE.
56 |
57 | --------------------------------------------------------------------
58 |
59 | This software consists of voluntary contributions made by many
60 | individuals on behalf of the PHP Group.
61 |
62 | The PHP Group can be contacted via Email at group@php.net.
63 |
64 | For more information on the PHP Group and the PHP project,
65 | please see .
66 |
67 | PHP includes the Zend Engine, freely available at
68 | .
69 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # HandlerSocket plugin for MySQL Improved Extension #
2 |
3 | The handlersocketi extension allows you to access the functionality
4 | provided by HandlerSocket plugin for MySQL.
5 |
6 | More information about the HandlerSocket plugin for MySQL can be found at
7 | [» http://github.com/ahiguti/HandlerSocket-Plugin-for-MySQL](http://github.com/ahiguti/HandlerSocket-Plugin-for-MySQL)
8 |
--------------------------------------------------------------------------------
/config.m4:
--------------------------------------------------------------------------------
1 | dnl config.m4 for extension handlersocketi
2 |
3 | dnl Check PHP version:
4 | AC_MSG_CHECKING(PHP version)
5 | if test ! -z "$phpincludedir"; then
6 | PHP_VERSION=`grep 'PHP_VERSION ' $phpincludedir/main/php_version.h | sed -e 's/.*"\([[0-9\.]]*\)".*/\1/g' 2>/dev/null`
7 | elif test ! -z "$PHP_CONFIG"; then
8 | PHP_VERSION=`$PHP_CONFIG --version 2>/dev/null`
9 | fi
10 |
11 | if test x"$PHP_VERSION" = "x"; then
12 | AC_MSG_WARN([none])
13 | else
14 | PHP_MAJOR_VERSION=`echo $PHP_VERSION | sed -e 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\).*/\1/g' 2>/dev/null`
15 | PHP_MINOR_VERSION=`echo $PHP_VERSION | sed -e 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\).*/\2/g' 2>/dev/null`
16 | PHP_RELEASE_VERSION=`echo $PHP_VERSION | sed -e 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\).*/\3/g' 2>/dev/null`
17 | AC_MSG_RESULT([$PHP_VERSION])
18 | fi
19 |
20 | if test $PHP_MAJOR_VERSION -lt 5; then
21 | AC_MSG_ERROR([need at least PHP 5 or newer])
22 | fi
23 |
24 | PHP_ARG_ENABLE(handlersocketi, whether to enable handlersocketi support,
25 | [ --enable-handlersocketi Enable handlersocketi support])
26 |
27 | if test "$PHP_HANDLERSOCKETI" != "no"; then
28 |
29 | PHP_NEW_EXTENSION(handlersocketi, handlersocketi.c handlersocketi_exception.c handlersocketi_class.c handlersocketi_index.c util/request.c util/response.c, $ext_shared)
30 |
31 | ifdef([PHP_INSTALL_HEADERS],
32 | [
33 | PHP_INSTALL_HEADERS([ext/handlersocketi/], [php_handlersocketi.h handlersocketi_exception.h handlersocketi_class.h handlersocketi_index.h])
34 | ], [
35 | PHP_ADD_MAKEFILE_FRAGMENT
36 | ])
37 | fi
38 |
--------------------------------------------------------------------------------
/config.w32:
--------------------------------------------------------------------------------
1 | ARG_ENABLE("handlersocketi", "enable handlersocketi support", "no");
2 |
3 | if (PHP_HANDLERSOCKETI != "no") {
4 | handlersocketi_source =
5 | "handlersocketi.c " +
6 | "handlersocketi_exception.c " +
7 | "handlersocketi_class.c " +
8 | "handlersocketi_index.c " +
9 | "util/request.c " +
10 | "util/response.c";
11 | EXTENSION("handlersocketi", handlersocketi_source);
12 | PHP_INSTALL_HEADERS("ext/handlersocketi/", "php_handlersocketi.h handlersocketi_exception.h handlersocketi_class.h handlersocketi_index.h");
13 | }
14 |
--------------------------------------------------------------------------------
/handlersocketi class:
--------------------------------------------------------------------------------
1 | (string) What host to connect to, defaults to localhost
68 | * port => (int) The port of the database read
69 | * port_wr => (string) What host to connect to, defaults to localhost => (int) The port of the database write, update, delete
70 | * database => (string) The name of the database to user
71 | * table => (string) The table of the database table
72 | * options => (array) set timeout, default 5s
73 | *
74 | * @param array $config
75 | */
76 |
77 | /**
78 | * Constructor
79 | *
80 | * @param array $config
81 | */
82 | public function __construct(array $config = array())
83 | {
84 | $this->_config = $config + array('host' => '127.0.0.1', 'port' => 9998, 'port_wr' => 9999, 'options' => array('timeout' => 5));
85 |
86 | $this->_port = $this->_config['port'];
87 | $this->_portWr = $this->_config['port_wr'];
88 |
89 | if (isset($this->_config['database'])) {
90 | $this->_db = $this->_config['database'];
91 | }
92 |
93 | if (isset($this->_config['table'])) {
94 | $this->_table = $this->_config['table'];
95 | }
96 |
97 | return $this->connection();
98 | }
99 |
100 | /**
101 | * Get HandlerSocketi connection
102 | *
103 | * @return HandlerSocketi
104 | */
105 | public function connection()
106 | {
107 | if (NULL === $this->_connection) {
108 | $this->_connection = new HandlerSocketi($this->_config['host'], $this->_port, $this->_config['options']);
109 | }
110 | if (isset($this->_config['auth'])) {
111 | $this->_connection->auth($this->_config['auth']['user'], $this->_config['auth']['password']);
112 | }
113 | return $this->_connection;
114 | }
115 |
116 | /**
117 | * Get HandlerSocketi write connection
118 | *
119 | * @return HandlerSocketi
120 | */
121 | public function writeConnection()
122 | {
123 | if (NULL === $this->_writeConnection) {
124 | $this->_writeConnection = new HandlerSocketi($this->_config['host'], $this->_portWr, $this->_config['options']);
125 | }
126 | if (isset($this->_config['auth'])) {
127 | $this->_writeConnection->auth($this->_config['auth']['user'], $this->_config['auth']['password']);
128 | }
129 |
130 | return $this->_writeConnection;
131 | }
132 |
133 | /**
134 | * Select Database
135 | *
136 | * @param string $db
137 | * @return database name
138 | */
139 | public function db($db = null)
140 | {
141 | if ($db) {
142 | return $this->_db->$db;
143 | }
144 |
145 | return $this->_db;
146 | }
147 |
148 | /**
149 | * Select table
150 | *
151 | * @param string $table
152 | * @return table name
153 | */
154 | public function talbe($table = NULL)
155 | {
156 | if ($table) {
157 | return $this->_table->$table;
158 | }
159 |
160 | return $this->_table;
161 | }
162 |
163 | /**
164 | * select and return query result array.
165 | *
166 | * Pass the query and options as array objects (this is more convenient than the standard HandlerSocketi API especially when caching)
167 | *
168 | * $query may contain:
169 | * op - string comparison operator, supported '=', '<', '<=', '>', '>='
170 | * criteria - string | array comparison values
171 | * limit - int limit number
172 | * skip - int skip number
173 | *
174 | * $options may contain:
175 | * dbname - string database name
176 | * table - string select table name
177 | * fields - string | array the fields to retrieve
178 | * index - string index name.
179 | *
180 | * @param array $query
181 | * @param array $options
182 | * @return false|array
183 | * */
184 | public function select(array $query = array(), array $options = array())
185 | {
186 | $query += array('op' => '=', 'criteria' => array(), 'limit' => 1, 'skip' => 0,);
187 | $options += array('dbname' => '', 'table' => '', 'fields' => '', 'index' => '');
188 |
189 | $dbname = $options['dbname'] ? : $this->_db;
190 | $table = $options['table'] ? : $this->_table;
191 | $index = $options['index'] ? : 'PRIMARY';
192 | $hsi = $this->connection()->open_index($dbname, $table, $options['fields'], ['index' => $index]);
193 | $result = $hsi->find([$query['op'] => $query['criteria']], ['limit' => $query['limit'], 'offset' => $query['skip']]);
194 | if (!$result) {
195 | $this->_errorLog = $hsi->getError();
196 | }
197 | return $result;
198 | }
199 |
200 | /**
201 | * selectMulti and return query result array.
202 | *
203 | * Pass the query and options as array objects (this is more convenient than the standard HandlerSocketi API especially when caching)
204 | *
205 | * $query may multi select parameter
206 | *
207 | * $options may contain:
208 | * dbname - string database name
209 | * table - string select table name
210 | * fields - string | array the fields to retrieve
211 | * index - string index name.
212 | *
213 | * @param array $querys
214 | * @param array $options
215 | * @return false|array
216 | * */
217 | public function selectMulti($querys = array(), $options = array())
218 | {
219 | $options += array('dbname' => '', 'table' => '', 'fields' => '', 'index' => '');
220 |
221 | $dbname = $options['dbname'] ? : $this->_db;
222 | $table = $options['table'] ? : $this->_table;
223 | $index = $options['index'] ? : 'PRIMARY';
224 | $hsi = $this->connection()->open_index($dbname, $table, $options['fields'], ['index' => $index]);
225 |
226 | foreach ($querys as $key => $value) {
227 | $query[$key] = ['find', [$value['op'] => $value['criteria']], ['limit' => $value['limit'], 'offset' => $value['skip']]];
228 | }
229 | $result = $hsi->multi($query);
230 | if (!$result) {
231 | $this->_errorLog = $hsi->getError();
232 | }
233 | return $result;
234 | }
235 |
236 | /**
237 | * Insert data
238 | *
239 | * $data is insert fields array values
240 | *
241 | * $options may contain:
242 | * dbname - database name
243 | * table - select table name
244 | *
245 | * @param array $data
246 | * @param array $options
247 | * @return false|int
248 | * */
249 | public function insert($data, $options = array())
250 | {
251 | $options += array('dbname' => '', 'table' => '');
252 | $dbname = $options['dbname'] ? : $this->_db;
253 | $table = $options['table'] ? : $this->_table;
254 | $hsi = $this->writeConnection()->open_index($dbname, $table, implode(',', array_keys($data)));
255 | $resutl = $hsi->insert($data);
256 | if (!$resutl) {
257 | $this->_errorLog = $hsi->getError();
258 | }
259 | return $resutl;
260 | }
261 |
262 | /**
263 | * Update data
264 | *
265 | * $query may contain:
266 | * op - string comparison operator, supported '=', '<', '<=', '>', '>='
267 | * criteria - string | array comparison values
268 | * limit - int limit number
269 | * skip - int skip number
270 | *
271 | * $options may contain:
272 | * dbname - string database name
273 | * table - string select table name
274 | * index - string index name.
275 | *
276 | * @param array $query
277 | * @param array $data
278 | * @param array $options
279 | * @return false|int
280 | */
281 | public function update($query, $data, $options = array())
282 | {
283 | $query += array('op' => '=', 'criteria' => array(), 'limit' => 1, 'skip' => 0);
284 | $options += array('dbname' => '', 'table' => '', 'index' => '');
285 |
286 | $dbname = $options['dbname'] ? : $this->_db;
287 | $table = $options['table'] ? : $this->_table;
288 | $index = $options['index'] ? : 'PRIMARY';
289 |
290 | $hsi = $this->writeConnection()->open_index($dbname, $table, implode(',', array_keys($data)), ['index' => $index]);
291 | $result = $hsi->update([$query['op'] => $query['criteria']], array_values($data), ['limit' => $query['limit'], 'offset' => $query['skip']]);
292 | if (!$result) {
293 | $this->_errorLog = $hsi->getError();
294 | }
295 | return $result;
296 | }
297 |
298 | /**
299 | * delete data
300 | * $query may contain:
301 | * op - string comparison operator, supported '=', '<', '<=', '>', '>='
302 | * criteria - string | array comparison values
303 | * limit - int limit number
304 | * skip - int skip number
305 | *
306 | * $options may contain:
307 | * dbname - string database name
308 | * table - string select table name
309 | * fields - string | array the fields to retrieve
310 | * index - string index name.
311 | *
312 | * @param array $query
313 | * @param array $options
314 | * @return false|int
315 | */
316 | public function delete($query, $options = array())
317 | {
318 | $query += array('op' => '=', 'criteria' => array(), 'limit' => 1, 'skip' => 0,);
319 | $options += array('dbname' => '', 'table' => '', 'fields' => '', 'index' => '');
320 |
321 | $dbname = $options['dbname'] ? : $this->_db;
322 | $table = $options['table'] ? : $this->_table;
323 | $index = $options['index'] ? : 'PRIMARY';
324 |
325 | $hsi = $this->writeConnection()->open_index($dbname, $table, $options['fields'], ['index' => $index]);
326 | $result = $hsi->remove([$query['op'] => $query['criteria']], ['limit' => $query['limit'], 'offset' => $query['skip']]);
327 | if (!$result) {
328 | $this->_errorLog = $hsi->getError();
329 | }
330 | return $result;
331 | }
332 |
333 | /**
334 | * Last error
335 | *
336 | * @return array
337 | */
338 | public function error($log = NULL)
339 | {
340 | if (NULL == $log) {
341 | return $this->_errorLog;
342 | }
343 | $this->_errorLog = $log;
344 | }
345 |
346 | }
347 |
--------------------------------------------------------------------------------
/handlersocketi.c:
--------------------------------------------------------------------------------
1 |
2 | #ifdef HAVE_CONFIG_H
3 | #include "config.h"
4 | #endif
5 |
6 | #include "php.h"
7 | #include "php_ini.h"
8 | #include "ext/standard/info.h"
9 |
10 | #include "php_verdep.h"
11 | #include "php_handlersocketi.h"
12 | #include "handlersocketi_exception.h"
13 | #include "handlersocketi_class.h"
14 | #include "handlersocketi_index.h"
15 |
16 | ZEND_DECLARE_MODULE_GLOBALS(handlersocketi)
17 |
18 | static void
19 | hs_init_globals(zend_handlersocketi_globals *hs_globals)
20 | {
21 | hs_globals->id = 1;
22 | }
23 |
24 | ZEND_MINIT_FUNCTION(handlersocketi)
25 | {
26 | ZEND_INIT_MODULE_GLOBALS(handlersocketi, hs_init_globals, NULL);
27 | /*
28 | REGISTER_INI_ENTRIES();
29 | */
30 |
31 | handlersocketi_register_exception(TSRMLS_C);
32 | handlersocketi_register_class(TSRMLS_C);
33 | handlersocketi_register_index(TSRMLS_C);
34 |
35 | /*
36 | REGISTER_LONG_CONSTANT("MSGPACKI_MODE_ORIGIN", PHP_MSGPACKI_MODE_ORIGIN,
37 | CONST_CS | CONST_PERSISTENT);
38 |
39 | REGISTER_STRING_CONSTANT("MSGPACKI_FILTER_REGISTER",
40 | PHP_MSGPACKI_FILTER_REGISTER,
41 | CONST_CS | CONST_PERSISTENT);
42 | */
43 |
44 |
45 | /* constant
46 | #if ZEND_MODULE_API_NO < 20050922
47 | REGISTER_STRING_CONSTANT(
48 | "HANDLERSOCKETI_PRIMARY", HS_PRIMARY, CONST_CS | CONST_PERSISTENT);
49 | REGISTER_STRING_CONSTANT(
50 | "HANDLERSOCKETI_UPDATE", HS_MODIFY_UPDATE, CONST_CS | CONST_PERSISTENT);
51 | REGISTER_STRING_CONSTANT(
52 | "HANDLERSOCKETI_DELETE", HS_MODIFY_REMOVE, CONST_CS | CONST_PERSISTENT);
53 | #else
54 | zend_declare_class_constant_string(
55 | hs_ce, "PRIMARY", strlen("PRIMARY"), HS_PRIMARY TSRMLS_CC);
56 | zend_declare_class_constant_string(
57 | hs_ce, "UPDATE", strlen("UPDATE"), HS_MODIFY_UPDATE TSRMLS_CC);
58 | zend_declare_class_constant_string(
59 | hs_ce, "DELETE", strlen("DELETE"), HS_MODIFY_REMOVE TSRMLS_CC);
60 | #endif
61 | */
62 |
63 | return SUCCESS;
64 | }
65 |
66 | ZEND_MSHUTDOWN_FUNCTION(handlersocketi)
67 | {
68 | /*
69 | UNREGISTER_INI_ENTRIES();
70 | */
71 |
72 | return SUCCESS;
73 | }
74 |
75 | /*
76 | ZEND_RINIT_FUNCTION(handlersocketi)
77 | {
78 | return SUCCESS;
79 | }
80 |
81 | ZEND_RSHUTDOWN_FUNCTION(handlersocketi)
82 | {
83 | return SUCCESS;
84 | }
85 | */
86 |
87 | ZEND_MINFO_FUNCTION(handlersocketi)
88 | {
89 | php_info_print_table_start();
90 | php_info_print_table_header(2, "handlersocketi support", "enabled");
91 | php_info_print_table_header(2, "extension version",
92 | HANDLERSOCKETI_EXT_VERSION);
93 | php_info_print_table_end();
94 |
95 | DISPLAY_INI_ENTRIES();
96 | }
97 |
98 | const zend_function_entry handlersocketi_functions[] = {
99 | ZEND_FE_END
100 | };
101 |
102 | zend_module_entry handlersocketi_module_entry = {
103 | #if ZEND_MODULE_API_NO >= 20010901
104 | STANDARD_MODULE_HEADER,
105 | #endif
106 | "handlersocketi",
107 | NULL,
108 | ZEND_MINIT(handlersocketi),
109 | ZEND_MSHUTDOWN(handlersocketi),
110 | NULL, /* ZEND_RINIT(handlersocketi), */
111 | NULL, /* ZEND_RSHUTDOWN(handlersocketi), */
112 | ZEND_MINFO(handlersocketi),
113 | #if ZEND_MODULE_API_NO >= 20010901
114 | HANDLERSOCKETI_EXT_VERSION,
115 | #endif
116 | STANDARD_MODULE_PROPERTIES
117 | };
118 |
119 | #ifdef COMPILE_DL_HANDLERSOCKETI
120 | ZEND_GET_MODULE(handlersocketi)
121 | #endif
122 |
--------------------------------------------------------------------------------
/handlersocketi_class.c:
--------------------------------------------------------------------------------
1 |
2 | #include "php.h"
3 | #include "php_ini.h"
4 | #include "php_streams.h"
5 | #include "ext/standard/php_smart_str.h"
6 |
7 | #include "php_verdep.h"
8 | #include "php_handlersocketi.h"
9 | #include "handlersocketi_exception.h"
10 | #include "handlersocketi_class.h"
11 | #include "util/common.h"
12 | #include "util/request.h"
13 | #include "util/response.h"
14 |
15 | ZEND_EXTERN_MODULE_GLOBALS(handlersocketi);
16 |
17 | #define HS_STREAM_DEFAULT_TIMEOUT 5
18 |
19 | static zend_class_entry *hs_ce;
20 | static zend_object_handlers hs_object_handlers;
21 |
22 | typedef struct hs_obj {
23 | zend_object std;
24 | php_stream *stream;
25 | long timeout;
26 | zval *server;
27 | zval *auth;
28 | zval *error;
29 | zval *persistent;
30 | zend_bool is_persistent;
31 | } hs_obj_t;
32 |
33 | ZEND_BEGIN_ARG_INFO_EX(arginfo_hs_method__construct, 0, 0, 2)
34 | ZEND_ARG_INFO(0, host)
35 | ZEND_ARG_INFO(0, port)
36 | ZEND_ARG_INFO(0, options)
37 | ZEND_END_ARG_INFO()
38 |
39 | ZEND_BEGIN_ARG_INFO_EX(arginfo_hs_method_auth, 0, 0, 1)
40 | ZEND_ARG_INFO(0, key)
41 | ZEND_ARG_INFO(0, type)
42 | ZEND_END_ARG_INFO()
43 |
44 | ZEND_BEGIN_ARG_INFO_EX(arginfo_hs_method_open_index, 0, 0, 3)
45 | ZEND_ARG_INFO(0, db)
46 | ZEND_ARG_INFO(0, table)
47 | ZEND_ARG_INFO(0, fields)
48 | ZEND_ARG_INFO(0, options)
49 | ZEND_END_ARG_INFO()
50 |
51 | ZEND_METHOD(HandlerSocketi, __construct);
52 | ZEND_METHOD(HandlerSocketi, auth);
53 | ZEND_METHOD(HandlerSocketi, open_index);
54 |
55 | const zend_function_entry hs_methods[] = {
56 | ZEND_ME(HandlerSocketi, __construct,
57 | arginfo_hs_method__construct, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR)
58 | ZEND_ME(HandlerSocketi, auth,
59 | arginfo_hs_method_open_index, ZEND_ACC_PUBLIC)
60 | ZEND_ME(HandlerSocketi, open_index,
61 | arginfo_hs_method_open_index, ZEND_ACC_PUBLIC)
62 | ZEND_MALIAS(HandlerSocketi, openIndex, open_index,
63 | arginfo_hs_method_open_index, ZEND_ACC_PUBLIC)
64 | ZEND_FE_END
65 | };
66 |
67 | static void
68 | hs_object_free_storage(void *object TSRMLS_DC)
69 | {
70 | hs_obj_t *intern = (hs_obj_t *)object;
71 | zend_object_std_dtor(&intern->std TSRMLS_CC);
72 |
73 | if (intern->stream) {
74 | if (!intern->persistent) {
75 | php_stream_close(intern->stream);
76 | }
77 | }
78 |
79 | if (intern->server) {
80 | zval_ptr_dtor(&intern->server);
81 | }
82 |
83 | if (intern->auth) {
84 | zval_ptr_dtor(&intern->auth);
85 | }
86 |
87 | if (intern->error) {
88 | zval_ptr_dtor(&intern->error);
89 | }
90 |
91 | if (intern->persistent) {
92 | zval_ptr_dtor(&intern->persistent);
93 | }
94 |
95 | efree(object);
96 | }
97 |
98 | #define HS_EXCEPTION(...) \
99 | zend_throw_exception_ex(handlersocketi_get_ce_exception(), \
100 | 0 TSRMLS_CC, \
101 | "HandlerSocketi::" __VA_ARGS__)
102 |
103 | #define HS_CHECK_OBJECT(object, classname) \
104 | if (!(object)) { \
105 | HS_EXCEPTION("The " #classname " object has not been " \
106 | "correctly initialized by its constructor"); \
107 | RETURN_FALSE; \
108 | }
109 |
110 | static inline zend_object_value
111 | hs_object_new_ex(zend_class_entry *ce, hs_obj_t **ptr TSRMLS_DC)
112 | {
113 | hs_obj_t *intern;
114 | zend_object_value retval;
115 | #if ZEND_MODULE_API_NO < 20100525
116 | zval *tmp;
117 | #endif
118 |
119 | intern = emalloc(sizeof(hs_obj_t));
120 | memset(intern, 0, sizeof(hs_obj_t));
121 | if (ptr) {
122 | *ptr = intern;
123 | }
124 |
125 | zend_object_std_init(&intern->std, ce TSRMLS_CC);
126 |
127 | #if ZEND_MODULE_API_NO >= 20100525
128 | object_properties_init(&intern->std, ce);
129 | #else
130 | zend_hash_copy(intern->std.properties, &ce->default_properties,
131 | (copy_ctor_func_t)zval_add_ref, (void *)&tmp, sizeof(zval *));
132 | #endif
133 |
134 | retval.handle = zend_objects_store_put(
135 | intern, (zend_objects_store_dtor_t)zend_objects_destroy_object,
136 | (zend_objects_free_object_storage_t)hs_object_free_storage,
137 | NULL TSRMLS_CC);
138 | retval.handlers = &hs_object_handlers;
139 |
140 | intern->timeout = 0;
141 | intern->stream = NULL;
142 | intern->server = NULL;
143 | intern->auth = NULL;
144 | intern->error = NULL;
145 | intern->persistent = NULL;
146 |
147 | return retval;
148 | }
149 |
150 | static inline int
151 | hs_object_connection(hs_obj_t *obj)
152 | {
153 | char *hashkey = NULL;
154 | char *errstr = NULL;
155 | int err;
156 | struct timeval tv;
157 | TSRMLS_FETCH();
158 |
159 | if (obj->timeout > 0) {
160 | tv.tv_sec = obj->timeout;
161 | tv.tv_usec = 0;
162 | }
163 |
164 | if (obj->persistent) {
165 | hashkey = Z_STRVAL_P(obj->persistent);
166 | }
167 |
168 | obj->stream = php_stream_xport_create(Z_STRVAL_P(obj->server),
169 | Z_STRLEN_P(obj->server),
170 | ENFORCE_SAFE_MODE|REPORT_ERRORS,
171 | STREAM_XPORT_CLIENT|
172 | STREAM_XPORT_CONNECT,
173 | hashkey, &tv, NULL, &errstr, &err);
174 |
175 | if (!obj->stream) {
176 | if (errstr) {
177 | efree(errstr);
178 | }
179 | return FAILURE;
180 | }
181 |
182 | if (errstr) {
183 | efree(errstr);
184 | }
185 |
186 | /* non-blocking */
187 | if (php_stream_set_option(obj->stream, PHP_STREAM_OPTION_BLOCKING,
188 | 0, NULL) == -1) {
189 | zend_error(E_WARNING,
190 | "HandlerSocketi: Un set non-blocking mode on a stream");
191 | }
192 |
193 | return SUCCESS;
194 | }
195 |
196 | static inline zend_object_value
197 | hs_object_new(zend_class_entry *ce TSRMLS_DC)
198 | {
199 | return hs_object_new_ex(ce, NULL TSRMLS_CC);
200 | }
201 |
202 | static inline zend_object_value
203 | hs_object_clone(zval *this_ptr TSRMLS_DC)
204 | {
205 | hs_obj_t *new_obj = NULL;
206 | hs_obj_t *old_obj =
207 | (hs_obj_t *)zend_object_store_get_object(this_ptr TSRMLS_CC);
208 | zend_object_value new_ov = hs_object_new_ex(old_obj->std.ce,
209 | &new_obj TSRMLS_CC);
210 |
211 | zend_objects_clone_members(&new_obj->std, new_ov, &old_obj->std,
212 | Z_OBJ_HANDLE_P(this_ptr) TSRMLS_CC);
213 |
214 | new_obj->timeout = old_obj->timeout;
215 |
216 | MAKE_STD_ZVAL(new_obj->server);
217 | *new_obj->server = *old_obj->server;
218 | zval_copy_ctor(new_obj->server);
219 |
220 | if (old_obj->auth) {
221 | MAKE_STD_ZVAL(new_obj->auth);
222 | *new_obj->auth = *old_obj->auth;
223 | zval_copy_ctor(new_obj->auth);
224 | } else {
225 | new_obj->auth = NULL;
226 | }
227 |
228 | new_obj->error = NULL;
229 |
230 | if (old_obj->persistent) {
231 | MAKE_STD_ZVAL(new_obj->persistent);
232 | *new_obj->persistent = *old_obj->persistent;
233 | zval_copy_ctor(new_obj->persistent);
234 | } else {
235 | new_obj->persistent = NULL;
236 | }
237 |
238 | hs_object_connection(new_obj);
239 |
240 | return new_ov;
241 | }
242 |
243 | PHP_HANDLERSOCKETI_API int
244 | handlersocketi_register_class(TSRMLS_D)
245 | {
246 | zend_class_entry ce;
247 |
248 | INIT_CLASS_ENTRY(ce, "HandlerSocketi", hs_methods);
249 |
250 | ce.create_object = hs_object_new;
251 |
252 | hs_ce = zend_register_internal_class(&ce TSRMLS_CC);
253 | if (hs_ce == NULL) {
254 | return FAILURE;
255 | }
256 |
257 | memcpy(&hs_object_handlers, zend_get_std_object_handlers(),
258 | sizeof(zend_object_handlers));
259 |
260 | hs_object_handlers.clone_obj = hs_object_clone;
261 |
262 | return SUCCESS;
263 | }
264 |
265 | PHP_HANDLERSOCKETI_API zend_class_entry
266 | *handlersocketi_get_ce(void)
267 | {
268 | return hs_ce;
269 | }
270 |
271 | PHP_HANDLERSOCKETI_API php_stream
272 | *handlersocketi_object_store_get_stream(zval *link)
273 | {
274 | hs_obj_t *hs;
275 | TSRMLS_FETCH();
276 |
277 | hs = (hs_obj_t *)zend_object_store_get_object(link TSRMLS_CC);
278 | if (hs) {
279 | return hs->stream;
280 | } else {
281 | return NULL;
282 | }
283 | }
284 |
285 | PHP_HANDLERSOCKETI_API long
286 | handlersocketi_object_store_get_timeout(zval *link)
287 | {
288 | hs_obj_t *hs;
289 | TSRMLS_FETCH();
290 |
291 | hs = (hs_obj_t *)zend_object_store_get_object(link TSRMLS_CC);
292 | if (hs) {
293 | return hs->timeout;
294 | } else {
295 | return 0;
296 | }
297 | }
298 |
299 | ZEND_METHOD(HandlerSocketi, __construct)
300 | {
301 | char *server, *host = NULL;
302 | int server_len, host_len = 0;
303 | long port = -1;
304 | zval *options = NULL;
305 | hs_obj_t *hs;
306 |
307 | if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sl|z",
308 | &host, &host_len, &port, &options) == FAILURE) {
309 | zval *object = getThis();
310 | ZVAL_NULL(object);
311 | return;
312 | }
313 |
314 | if (!host || host_len <= 0) {
315 | HS_EXCEPTION("__construct(): no host name");
316 | zval *object = getThis();
317 | ZVAL_NULL(object);
318 | return;
319 | }
320 |
321 | if (port > 0) {
322 | server_len = spprintf(&server, 0, "%s:%ld", host, port);
323 | } else {
324 | server_len = spprintf(&server, 0, "%s", host);
325 | }
326 |
327 | hs = (hs_obj_t *)zend_object_store_get_object(getThis() TSRMLS_CC);
328 | HS_CHECK_OBJECT(hs, HandlerSocketi);
329 |
330 | MAKE_STD_ZVAL(hs->server);
331 | ZVAL_STRINGL(hs->server, server, server_len, 1);
332 | efree(server);
333 |
334 | hs->timeout = HS_STREAM_DEFAULT_TIMEOUT;
335 |
336 | if (options && Z_TYPE_P(options) == IS_ARRAY) {
337 | zval **tmp;
338 | if (zend_hash_find(Z_ARRVAL_P(options), "timeout",
339 | sizeof("timeout"), (void **)&tmp) == SUCCESS) {
340 | convert_to_long_ex(tmp);
341 | hs->timeout = Z_LVAL_PP(tmp);
342 | }
343 |
344 | if (zend_hash_find(Z_ARRVAL_P(options), "persistent",
345 | sizeof("persistent"), (void **)&tmp) == SUCCESS) {
346 | convert_to_string_ex(tmp);
347 | MAKE_STD_ZVAL(hs->persistent);
348 | ZVAL_STRINGL(hs->persistent, Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp), 1);
349 | }
350 | }
351 |
352 | if (hs_object_connection(hs) != SUCCESS) {
353 | HS_EXCEPTION("__construct(): unable to connect %s",
354 | Z_STRVAL_P(hs->server));
355 | RETURN_FALSE;
356 | }
357 | }
358 |
359 | ZEND_METHOD(HandlerSocketi, auth)
360 | {
361 | char *key, *type = NULL;
362 | long key_len, type_len = 0;
363 | hs_obj_t *hs;
364 | smart_str request = {0};
365 |
366 | if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|s",
367 | &key, &key_len, &type, &type_len) == FAILURE) {
368 | RETURN_FALSE;
369 | }
370 |
371 | if (key_len <= 0) {
372 | RETURN_FALSE;
373 | }
374 |
375 | /* handerlsocket: object */
376 | hs = (hs_obj_t *)zend_object_store_get_object(getThis() TSRMLS_CC);
377 | HS_CHECK_OBJECT(hs, HandlerSocketi);
378 |
379 | MAKE_STD_ZVAL(hs->auth);
380 | ZVAL_STRINGL(hs->auth, key, key_len, 1);
381 |
382 | /* auth */
383 | hs_request_string(&request, HS_PROTOCOL_AUTH, 1);
384 | hs_request_delim(&request);
385 | hs_request_string(&request, "1", 1);
386 | hs_request_delim(&request);
387 | hs_request_string(&request, Z_STRVAL_P(hs->auth), Z_STRLEN_P(hs->auth));
388 | hs_request_next(&request);
389 |
390 | /* request: send */
391 | if (hs_request_send(hs->stream, &request TSRMLS_CC) < 0) {
392 | ZVAL_BOOL(return_value, 0);
393 | } else {
394 | zval *retval;
395 | MAKE_STD_ZVAL(retval);
396 |
397 | /* response */
398 | hs_response_value(hs->stream, hs->timeout, retval, NULL, 0 TSRMLS_CC);
399 | if (Z_TYPE_P(retval) == IS_BOOL && Z_LVAL_P(retval) == 1) {
400 | ZVAL_BOOL(return_value, 1);
401 | } else {
402 | ZVAL_BOOL(return_value, 0);
403 | }
404 |
405 | zval_ptr_dtor(&retval);
406 | }
407 |
408 | smart_str_free(&request);
409 | }
410 |
411 | ZEND_METHOD(HandlerSocketi, open_index)
412 | {
413 | char *db, *table;
414 | int db_len, table_len;
415 | zval *fields, *options = NULL;
416 |
417 | if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ssz|z",
418 | &db, &db_len, &table, &table_len,
419 | &fields, &options) == FAILURE) {
420 | return;
421 | }
422 |
423 | handlersocketi_create_index(return_value, getThis(), db, db_len,
424 | table, table_len, fields, options TSRMLS_CC);
425 | }
426 |
--------------------------------------------------------------------------------
/handlersocketi_class.h:
--------------------------------------------------------------------------------
1 | #ifndef HANDLERSOCKETI_CLASS_H
2 | #define HANDLERSOCKETI_CLASS_H
3 |
4 | PHP_HANDLERSOCKETI_API int handlersocketi_register_class(TSRMLS_D);
5 | PHP_HANDLERSOCKETI_API zend_class_entry *handlersocketi_get_ce(void);
6 |
7 | PHP_HANDLERSOCKETI_API php_stream *handlersocketi_object_store_get_stream(zval *link);
8 | PHP_HANDLERSOCKETI_API long handlersocketi_object_store_get_timeout(zval *link);
9 |
10 | #endif /* HANDLERSOCKETI_CLASS_H */
11 |
--------------------------------------------------------------------------------
/handlersocketi_exception.c:
--------------------------------------------------------------------------------
1 |
2 | #include "php.h"
3 | #include "php_ini.h"
4 | #include "Zend/zend_exceptions.h"
5 |
6 | #include "php_handlersocketi.h"
7 | #include "handlersocketi_exception.h"
8 |
9 | ZEND_EXTERN_MODULE_GLOBALS(handlersocketi);
10 |
11 | static zend_class_entry *hs_ce_exception;
12 |
13 | PHP_HANDLERSOCKETI_API int
14 | handlersocketi_register_exception(TSRMLS_D)
15 | {
16 | zend_class_entry ce;
17 |
18 | INIT_CLASS_ENTRY(ce, "HandlerSocketi_Exception", NULL);
19 |
20 | hs_ce_exception = zend_register_internal_class_ex(
21 | &ce, zend_exception_get_default(TSRMLS_C), NULL TSRMLS_CC);
22 | if (hs_ce_exception == NULL) {
23 | return FAILURE;
24 | }
25 |
26 | return SUCCESS;
27 | }
28 |
29 | PHP_HANDLERSOCKETI_API zend_class_entry
30 | *handlersocketi_get_ce_exception(void) {
31 | return hs_ce_exception;
32 | }
33 |
--------------------------------------------------------------------------------
/handlersocketi_exception.h:
--------------------------------------------------------------------------------
1 | #ifndef HANDLERSOCKETI_EXCEPTION_H
2 | #define HANDLERSOCKETI_EXCEPTION_H
3 |
4 | PHP_HANDLERSOCKETI_API int handlersocketi_register_exception(TSRMLS_D);
5 | PHP_HANDLERSOCKETI_API zend_class_entry *handlersocketi_get_ce_exception(void);
6 |
7 | #endif /* HANDLERSOCKETI_EXCEPTION_H */
8 |
--------------------------------------------------------------------------------
/handlersocketi_index.c:
--------------------------------------------------------------------------------
1 |
2 | #include "php.h"
3 | #include "php_ini.h"
4 | #include "ext/standard/php_smart_str.h"
5 | #include "ext/standard/php_string.h"
6 |
7 | #include "php_verdep.h"
8 | #include "php_handlersocketi.h"
9 | #include "handlersocketi_exception.h"
10 | #include "handlersocketi_class.h"
11 | #include "handlersocketi_index.h"
12 | #include "util/common.h"
13 | #include "util/request.h"
14 | #include "util/response.h"
15 |
16 | ZEND_EXTERN_MODULE_GLOBALS(handlersocketi);
17 |
18 | #define HS_DEFAULT_LIMIT 1
19 | #define HS_DEFAULT_OFFSET 0
20 |
21 | static zend_class_entry *hs_ce_index;
22 | static zend_object_handlers hs_index_object_handlers;
23 |
24 | typedef struct hs_index_obj {
25 | zend_object std;
26 | long id;
27 | zval *name;
28 | zval *db;
29 | zval *table;
30 | zval *field;
31 | long field_num;
32 | zval *filter;
33 | zval *link;
34 | zval *error;
35 | } hs_index_obj_t;
36 |
37 | ZEND_BEGIN_ARG_INFO_EX(arginfo_hs_index_method__construct, 0, 0, 4)
38 | ZEND_ARG_INFO(0, hs)
39 | ZEND_ARG_INFO(0, db)
40 | ZEND_ARG_INFO(0, table)
41 | ZEND_ARG_INFO(0, fields)
42 | ZEND_ARG_INFO(0, options)
43 | ZEND_END_ARG_INFO()
44 |
45 | ZEND_BEGIN_ARG_INFO_EX(arginfo_hs_index_method_find, 0, 0, 1)
46 | ZEND_ARG_INFO(0, query)
47 | ZEND_ARG_INFO(0, options)
48 | ZEND_END_ARG_INFO()
49 |
50 | ZEND_BEGIN_ARG_INFO_EX(arginfo_hs_index_method_insert, 0, 0, 0)
51 | ZEND_END_ARG_INFO()
52 |
53 | ZEND_BEGIN_ARG_INFO_EX(arginfo_hs_index_method_update, 0, 0, 2)
54 | ZEND_ARG_INFO(0, query)
55 | ZEND_ARG_INFO(0, update)
56 | ZEND_ARG_INFO(0, options)
57 | ZEND_END_ARG_INFO()
58 |
59 | ZEND_BEGIN_ARG_INFO_EX(arginfo_hs_index_method_remove, 0, 0, 1)
60 | ZEND_ARG_INFO(0, query)
61 | ZEND_ARG_INFO(0, options)
62 | ZEND_END_ARG_INFO()
63 |
64 | ZEND_BEGIN_ARG_INFO_EX(arginfo_hs_index_method_multi, 0, 0, 1)
65 | ZEND_ARG_INFO(0, args)
66 | ZEND_END_ARG_INFO()
67 |
68 | ZEND_BEGIN_ARG_INFO_EX(arginfo_hs_index_method_get_error, 0, 0, 0)
69 | ZEND_END_ARG_INFO()
70 |
71 | ZEND_BEGIN_ARG_INFO_EX(arginfo_hs_index_method_get_id, 0, 0, 0)
72 | ZEND_END_ARG_INFO()
73 |
74 | ZEND_BEGIN_ARG_INFO_EX(arginfo_hs_index_method_get_name, 0, 0, 0)
75 | ZEND_END_ARG_INFO()
76 |
77 | ZEND_BEGIN_ARG_INFO_EX(arginfo_hs_index_method_get_db, 0, 0, 0)
78 | ZEND_END_ARG_INFO()
79 |
80 | ZEND_BEGIN_ARG_INFO_EX(arginfo_hs_index_method_get_table, 0, 0, 0)
81 | ZEND_END_ARG_INFO()
82 |
83 | ZEND_BEGIN_ARG_INFO_EX(arginfo_hs_index_method_get_field, 0, 0, 0)
84 | ZEND_END_ARG_INFO()
85 |
86 | ZEND_BEGIN_ARG_INFO_EX(arginfo_hs_index_method_get_filter, 0, 0, 0)
87 | ZEND_END_ARG_INFO()
88 |
89 | ZEND_BEGIN_ARG_INFO_EX(arginfo_hs_index_method_get_operator, 0, 0, 0)
90 | ZEND_END_ARG_INFO()
91 |
92 | ZEND_METHOD(HandlerSocketi_Index, __construct);
93 | ZEND_METHOD(HandlerSocketi_Index, find);
94 | ZEND_METHOD(HandlerSocketi_Index, insert);
95 | ZEND_METHOD(HandlerSocketi_Index, update);
96 | ZEND_METHOD(HandlerSocketi_Index, remove);
97 | ZEND_METHOD(HandlerSocketi_Index, multi);
98 | ZEND_METHOD(HandlerSocketi_Index, get_error);
99 | ZEND_METHOD(HandlerSocketi_Index, get_id);
100 | ZEND_METHOD(HandlerSocketi_Index, get_name);
101 | ZEND_METHOD(HandlerSocketi_Index, get_db);
102 | ZEND_METHOD(HandlerSocketi_Index, get_table);
103 | ZEND_METHOD(HandlerSocketi_Index, get_field);
104 | ZEND_METHOD(HandlerSocketi_Index, get_filter);
105 | ZEND_METHOD(HandlerSocketi_Index, get_operator);
106 |
107 | const zend_function_entry hs_index_methods[] = {
108 | ZEND_ME(HandlerSocketi_Index, __construct,
109 | arginfo_hs_index_method__construct, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR)
110 | ZEND_ME(HandlerSocketi_Index, find,
111 | arginfo_hs_index_method_find, ZEND_ACC_PUBLIC)
112 | ZEND_ME(HandlerSocketi_Index, insert,
113 | arginfo_hs_index_method_insert, ZEND_ACC_PUBLIC)
114 | ZEND_ME(HandlerSocketi_Index, update,
115 | arginfo_hs_index_method_update, ZEND_ACC_PUBLIC)
116 | ZEND_ME(HandlerSocketi_Index, remove,
117 | arginfo_hs_index_method_remove, ZEND_ACC_PUBLIC)
118 | ZEND_ME(HandlerSocketi_Index, multi,
119 | arginfo_hs_index_method_multi, ZEND_ACC_PUBLIC)
120 | ZEND_ME(HandlerSocketi_Index, get_error,
121 | arginfo_hs_index_method_get_error, ZEND_ACC_PUBLIC)
122 | ZEND_ME(HandlerSocketi_Index, get_id,
123 | arginfo_hs_index_method_get_id, ZEND_ACC_PUBLIC)
124 | ZEND_ME(HandlerSocketi_Index, get_name,
125 | arginfo_hs_index_method_get_name, ZEND_ACC_PUBLIC)
126 | ZEND_ME(HandlerSocketi_Index, get_db,
127 | arginfo_hs_index_method_get_db, ZEND_ACC_PUBLIC)
128 | ZEND_ME(HandlerSocketi_Index, get_table,
129 | arginfo_hs_index_method_get_table, ZEND_ACC_PUBLIC)
130 | ZEND_ME(HandlerSocketi_Index, get_field,
131 | arginfo_hs_index_method_get_field, ZEND_ACC_PUBLIC)
132 | ZEND_ME(HandlerSocketi_Index, get_filter,
133 | arginfo_hs_index_method_get_filter, ZEND_ACC_PUBLIC)
134 | ZEND_ME(HandlerSocketi_Index, get_operator,
135 | arginfo_hs_index_method_get_operator, ZEND_ACC_PUBLIC)
136 | ZEND_MALIAS(HandlerSocketi_Index, getError, get_error,
137 | arginfo_hs_index_method_get_error, ZEND_ACC_PUBLIC)
138 | ZEND_MALIAS(HandlerSocketi_Index, getId, get_id,
139 | arginfo_hs_index_method_get_id, ZEND_ACC_PUBLIC)
140 | ZEND_MALIAS(HandlerSocketi_Index, getName, get_name,
141 | arginfo_hs_index_method_get_name, ZEND_ACC_PUBLIC)
142 | ZEND_MALIAS(HandlerSocketi_Index, getDb, get_db,
143 | arginfo_hs_index_method_get_db, ZEND_ACC_PUBLIC)
144 | ZEND_MALIAS(HandlerSocketi_Index, getTable, get_table,
145 | arginfo_hs_index_method_get_table, ZEND_ACC_PUBLIC)
146 | ZEND_MALIAS(HandlerSocketi_Index, getField, get_field,
147 | arginfo_hs_index_method_get_field, ZEND_ACC_PUBLIC)
148 | ZEND_MALIAS(HandlerSocketi_Index, getFilter, get_filter,
149 | arginfo_hs_index_method_get_filter, ZEND_ACC_PUBLIC)
150 | ZEND_MALIAS(HandlerSocketi_Index, getOperator, get_operator,
151 | arginfo_hs_index_method_get_operator, ZEND_ACC_PUBLIC)
152 | ZEND_FE_END
153 | };
154 |
155 | #define HS_EXCEPTION(...) \
156 | zend_throw_exception_ex(handlersocketi_get_ce_exception(), \
157 | 0 TSRMLS_CC, \
158 | "HandlerSocketi_Index::" __VA_ARGS__)
159 |
160 | #define HS_CHECK_OBJECT(object, classname) \
161 | if (!(object)) { \
162 | HS_EXCEPTION("The " #classname " object has not been " \
163 | "correctly initialized by its constructor"); \
164 | RETURN_FALSE; \
165 | }
166 |
167 | #define HS_ERROR_RESET(error) \
168 | if (error) { \
169 | zval_ptr_dtor(&error); \
170 | } \
171 | MAKE_STD_ZVAL(error); \
172 | ZVAL_NULL(error)
173 |
174 | static inline void
175 | hs_index_object_free_storage(void *object TSRMLS_DC)
176 | {
177 | hs_index_obj_t *intern = (hs_index_obj_t *)object;
178 | zend_object_std_dtor(&intern->std TSRMLS_CC);
179 |
180 | if (intern->link) {
181 | zval_ptr_dtor(&intern->link);
182 | }
183 |
184 | if (intern->name) {
185 | zval_ptr_dtor(&intern->name);
186 | }
187 |
188 | if (intern->db) {
189 | zval_ptr_dtor(&intern->db);
190 | }
191 |
192 | if (intern->table) {
193 | zval_ptr_dtor(&intern->table);
194 | }
195 |
196 | if (intern->field) {
197 | zval_ptr_dtor(&intern->field);
198 | }
199 |
200 | if (intern->filter) {
201 | zval_ptr_dtor(&intern->filter);
202 | }
203 |
204 | if (intern->error) {
205 | zval_ptr_dtor(&intern->error);
206 | }
207 |
208 | efree(object);
209 | }
210 |
211 | static inline zend_object_value
212 | hs_index_object_new_ex(zend_class_entry *ce, hs_index_obj_t **ptr TSRMLS_DC)
213 | {
214 | hs_index_obj_t *intern;
215 | zend_object_value retval;
216 | #if ZEND_MODULE_API_NO < 20100525
217 | zval *tmp;
218 | #endif
219 |
220 | intern = emalloc(sizeof(hs_index_obj_t));
221 | memset(intern, 0, sizeof(hs_index_obj_t));
222 | if (ptr) {
223 | *ptr = intern;
224 | }
225 |
226 | zend_object_std_init(&intern->std, ce TSRMLS_CC);
227 |
228 | #if ZEND_MODULE_API_NO >= 20100525
229 | object_properties_init(&intern->std, ce);
230 | #else
231 | zend_hash_copy(intern->std.properties, &ce->default_properties,
232 | (copy_ctor_func_t)zval_add_ref, (void *)&tmp, sizeof(zval *));
233 | #endif
234 |
235 | retval.handle = zend_objects_store_put(
236 | intern, (zend_objects_store_dtor_t)zend_objects_destroy_object,
237 | (zend_objects_free_object_storage_t)hs_index_object_free_storage,
238 | NULL TSRMLS_CC);
239 | retval.handlers = &hs_index_object_handlers;
240 |
241 | intern->id = 0;
242 | intern->name = NULL;
243 | intern->db = NULL;
244 | intern->table = NULL;
245 | intern->field = NULL;
246 | intern->field_num = 0;
247 | intern->filter = NULL;
248 | intern->link = NULL;
249 | intern->error = NULL;
250 |
251 | return retval;
252 | }
253 |
254 |
255 | static inline zend_object_value
256 | hs_index_object_new(zend_class_entry *ce TSRMLS_DC)
257 | {
258 | return hs_index_object_new_ex(ce, NULL TSRMLS_CC);
259 | }
260 |
261 | static inline zend_object_value
262 | hs_index_object_clone(zval *this_ptr TSRMLS_DC)
263 | {
264 | hs_index_obj_t *new_obj = NULL;
265 | hs_index_obj_t *old_obj =
266 | (hs_index_obj_t *)zend_object_store_get_object(this_ptr TSRMLS_CC);
267 | zend_object_value new_ov = hs_index_object_new_ex(old_obj->std.ce,
268 | &new_obj TSRMLS_CC);
269 |
270 | zend_objects_clone_members(&new_obj->std, new_ov, &old_obj->std,
271 | Z_OBJ_HANDLE_P(this_ptr) TSRMLS_CC);
272 |
273 | new_obj->id = old_obj->id;
274 |
275 | MAKE_STD_ZVAL(new_obj->name);
276 | *new_obj->name = *old_obj->name;
277 | zval_copy_ctor(new_obj->name);
278 |
279 | MAKE_STD_ZVAL(new_obj->db);
280 | *new_obj->db = *old_obj->db;
281 | zval_copy_ctor(new_obj->db);
282 |
283 | MAKE_STD_ZVAL(new_obj->table);
284 | *new_obj->table = *old_obj->table;
285 | zval_copy_ctor(new_obj->table);
286 |
287 | MAKE_STD_ZVAL(new_obj->field);
288 | *new_obj->field = *old_obj->field;
289 | zval_copy_ctor(new_obj->field);
290 |
291 | new_obj->field_num = old_obj->field_num;
292 |
293 | if (old_obj->filter) {
294 | MAKE_STD_ZVAL(new_obj->filter);
295 | *new_obj->filter = *old_obj->filter;
296 | zval_copy_ctor(new_obj->filter);
297 | } else {
298 | new_obj->filter = NULL;
299 | }
300 |
301 | MAKE_STD_ZVAL(new_obj->link);
302 | *new_obj->link = *old_obj->link;
303 | zval_copy_ctor(new_obj->link);
304 |
305 | new_obj->error = NULL;
306 |
307 | return new_ov;
308 | }
309 |
310 | static inline zval
311 | *hs_zval_to_comma_string(zval *val)
312 | {
313 | smart_str comma = {0};
314 | zval *retval;
315 | TSRMLS_FETCH();
316 |
317 | if (Z_TYPE_P(val) == IS_ARRAY) {
318 | zval **tmp;
319 | HashTable *ht;
320 | HashPosition pos;
321 |
322 | ht = HASH_OF(val);
323 | if (zend_hash_num_elements(ht) >= 0) {
324 | zend_hash_internal_pointer_reset_ex(ht, &pos);
325 | while (zend_hash_get_current_data_ex(ht, (void **)&tmp,
326 | &pos) == SUCCESS) {
327 | switch ((*tmp)->type) {
328 | case IS_STRING:
329 | if (Z_STRLEN_PP(tmp) > 0) {
330 | smart_str_appendl(&comma, Z_STRVAL_PP(tmp),
331 | Z_STRLEN_PP(tmp));
332 | smart_str_appendl(&comma, ",", strlen(","));
333 | }
334 | break;
335 | default:
336 | convert_to_string(*tmp);
337 | if (Z_STRLEN_PP(tmp) > 0) {
338 | smart_str_appendl(&comma, Z_STRVAL_PP(tmp),
339 | Z_STRLEN_PP(tmp));
340 | smart_str_appendl(&comma, ",", strlen(","));
341 | }
342 | break;
343 | }
344 | zend_hash_move_forward_ex(ht, &pos);
345 | }
346 | if (comma.len > 0) {
347 | comma.len--;
348 | comma.a--;
349 | }
350 | }
351 | } else if (Z_TYPE_P(val) == IS_STRING) {
352 | if (Z_STRLEN_P(val) > 0) {
353 | smart_str_appendl(&comma, Z_STRVAL_P(val), Z_STRLEN_P(val));
354 | }
355 | } else {
356 | convert_to_string(val);
357 | if (Z_STRLEN_P(val) > 0) {
358 | smart_str_appendl(&comma, Z_STRVAL_P(val), Z_STRLEN_P(val));
359 | }
360 | }
361 |
362 | smart_str_0(&comma);
363 |
364 | MAKE_STD_ZVAL(retval);
365 | ZVAL_STRINGL(retval, comma.c, comma.len, 1);
366 | smart_str_free(&comma);
367 |
368 | return retval;
369 | }
370 |
371 | static inline zval
372 | *hs_zval_to_comma_array(zval *val)
373 | {
374 | zval *retval;
375 |
376 | MAKE_STD_ZVAL(retval);
377 |
378 | if (Z_TYPE_P(val) == IS_ARRAY) {
379 | long n, i;
380 | /*
381 | array_init(retval);
382 | n = zend_hash_num_elements(HASH_OF(*tmp));
383 | for (i = 0; i < n; i++) {
384 | zval **val;
385 | if (zend_hash_index_find(HASH_OF(*tmp), i,
386 | (void **)&val) == SUCCESS) {
387 | convert_to_string(*val);
388 | add_next_index_stringl(retval, Z_STRVAL_PP(val),
389 | Z_STRLEN_PP(val), 1);
390 | }
391 | }
392 | */
393 | *retval = *val;
394 | zval_copy_ctor(retval);
395 | } else if (Z_TYPE_P(val) == IS_STRING) {
396 | zval delim;
397 | ZVAL_STRINGL(&delim, ",", strlen(","), 0);
398 |
399 | array_init(retval);
400 | php_explode(&delim, val, retval, LONG_MAX);
401 | } else {
402 | ZVAL_NULL(retval);
403 | }
404 |
405 | return retval;
406 | }
407 |
408 | static inline int
409 | hs_get_options_long(HashTable *options, char *item, long def TSRMLS_DC)
410 | {
411 | zval **tmp;
412 |
413 | if (zend_hash_find(options, item, strlen(item)+1,
414 | (void**)&tmp) == SUCCESS &&
415 | Z_TYPE_PP(tmp) == IS_LONG) {
416 | return Z_LVAL_PP(tmp);
417 | }
418 | return def;
419 | }
420 |
421 | static inline int
422 | hs_is_options_safe(HashTable *options TSRMLS_DC)
423 | {
424 | zval **tmp;
425 |
426 | if (zend_hash_find(options, "safe", sizeof("safe"),
427 | (void**)&tmp) == SUCCESS) {
428 | if (Z_TYPE_PP(tmp) == IS_STRING ||
429 | ((Z_TYPE_PP(tmp) == IS_LONG || Z_TYPE_PP(tmp) == IS_BOOL) &&
430 | Z_LVAL_PP(tmp) >= 1)) {
431 | return 1;
432 | }
433 | }
434 | return 0;
435 | }
436 |
437 | static inline int
438 | hs_zval_to_operate_criteria(zval *query, zval *operate,
439 | zval **criteria, char *defaults TSRMLS_DC)
440 | {
441 | if (query == NULL) {
442 | return FAILURE;
443 | }
444 |
445 | if (Z_TYPE_P(query) == IS_ARRAY) {
446 | char *key;
447 | uint key_len;
448 | ulong index;
449 | HashTable *ht;
450 | zval **tmp;
451 |
452 | ht = HASH_OF(query);
453 | if (zend_hash_get_current_data_ex(ht, (void **)&tmp, NULL) != SUCCESS) {
454 | return FAILURE;
455 | }
456 |
457 | if (zend_hash_get_current_key_ex(ht, &key, &key_len, &index,
458 | 0, NULL) == HASH_KEY_IS_STRING) {
459 | ZVAL_STRINGL(operate, key, key_len-1, 1);
460 | *criteria = *tmp;
461 | } else {
462 | ZVAL_STRINGL(operate, defaults, strlen(defaults), 1);
463 | *criteria = query;
464 | }
465 | } else {
466 | ZVAL_STRINGL(operate, defaults, strlen(defaults), 1);
467 | *criteria = query;
468 | }
469 |
470 | return SUCCESS;
471 | }
472 |
473 | static inline zval
474 | *hs_zval_search_key(zval *value, zval *array TSRMLS_DC)
475 | {
476 | zval *return_value, **entry, res;
477 | HashPosition pos;
478 | HashTable *ht;
479 | ulong index;
480 | uint key_len;
481 | char *key;
482 | int (*is_equal_func)(zval *, zval *, zval * TSRMLS_DC) = is_equal_function;
483 |
484 | MAKE_STD_ZVAL(return_value);
485 |
486 | ht = HASH_OF(array);
487 | zend_hash_internal_pointer_reset_ex(ht, &pos);
488 | while (zend_hash_get_current_data_ex(ht, (void **)&entry,
489 | &pos) == SUCCESS) {
490 | is_equal_func(&res, value, *entry TSRMLS_CC);
491 | if (Z_LVAL(res)) {
492 | switch (zend_hash_get_current_key_ex(ht, &key, &key_len,
493 | &index, 0, &pos)) {
494 | case HASH_KEY_IS_STRING:
495 | ZVAL_STRINGL(return_value, key, key_len - 1, 1);
496 | break;
497 | case HASH_KEY_IS_LONG:
498 | ZVAL_LONG(return_value, index);
499 | break;
500 | default:
501 | ZVAL_NULL(return_value);
502 | break;
503 | }
504 | return return_value;
505 | }
506 | zend_hash_move_forward_ex(ht, &pos);
507 | }
508 | ZVAL_NULL(return_value);
509 | return return_value;
510 | }
511 |
512 | static inline void
513 | hs_zval_to_filter(zval **return_value, zval *filter,
514 | zval *value, char *type TSRMLS_DC)
515 | {
516 | HashTable *ht;
517 | HashPosition pos;
518 | zval **tmp, **ftmp, **vtmp, *index, *item;
519 | long n;
520 |
521 | if (value == NULL || Z_TYPE_P(value) != IS_ARRAY) {
522 | return;
523 | }
524 |
525 | ht = HASH_OF(value);
526 | n = zend_hash_num_elements(ht);
527 |
528 | if (n <= 0 || zend_hash_index_find(ht, 0, (void **)&ftmp) != SUCCESS) {
529 | return;
530 | }
531 |
532 | zend_hash_internal_pointer_reset_ex(ht, &pos);
533 |
534 | if (Z_TYPE_PP(ftmp) == IS_ARRAY) {
535 | do {
536 | if (zend_hash_move_forward_ex(ht, &pos) < 0) {
537 | break;
538 | }
539 | hs_zval_to_filter(return_value, filter, *ftmp, type TSRMLS_CC);
540 | } while (zend_hash_get_current_data_ex(
541 | ht, (void **)&ftmp, &pos) == SUCCESS);
542 | return;
543 | } else if (n < 3) {
544 | return;
545 | }
546 |
547 | if (zend_hash_index_find(ht, 1, (void **)&tmp) != SUCCESS) {
548 | return;
549 | }
550 |
551 | index = hs_zval_search_key(*ftmp, filter TSRMLS_CC);
552 | if (Z_TYPE_P(index) != IS_LONG) {
553 | zval_ptr_dtor(&index);
554 | return;
555 | }
556 |
557 | if (zend_hash_index_find(ht, 2, (void **)&vtmp) != SUCCESS) {
558 | zval_ptr_dtor(&index);
559 | return;
560 | }
561 |
562 | MAKE_STD_ZVAL(item);
563 | array_init(item);
564 |
565 | add_next_index_stringl(item, type, strlen(type), 1);
566 |
567 | convert_to_string(*tmp);
568 | add_next_index_stringl(item, Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp), 1);
569 |
570 | add_next_index_long(item, Z_LVAL_P(index));
571 |
572 | if (Z_TYPE_PP(vtmp) == IS_NULL) {
573 | add_next_index_null(item);
574 | } else if (Z_TYPE_PP(vtmp) == IS_LONG) {
575 | add_next_index_long(item, Z_LVAL_PP(vtmp));
576 | } else if (Z_TYPE_PP(vtmp) == IS_DOUBLE) {
577 | add_next_index_double(item, Z_DVAL_PP(vtmp));
578 | } else {
579 | convert_to_string(*tmp);
580 | add_next_index_stringl(item, Z_STRVAL_PP(vtmp), Z_STRLEN_PP(vtmp), 1);
581 | }
582 |
583 | if (!(*return_value)) {
584 | MAKE_STD_ZVAL(*return_value);
585 | array_init(*return_value);
586 | }
587 |
588 | add_next_index_zval(*return_value, item);
589 |
590 | zval_ptr_dtor(&index);
591 | }
592 |
593 | static inline void
594 | hs_array_to_in_filter(HashTable *ht, zval *filter, zval **filters,
595 | long *in_key, zval **in_values TSRMLS_DC)
596 | {
597 | HashPosition pos;
598 | zval **val;
599 | char *key;
600 | ulong key_index;
601 | uint key_len;
602 |
603 | if (!filter) {
604 | return;
605 | }
606 |
607 | zend_hash_internal_pointer_reset_ex(ht, &pos);
608 | while (zend_hash_get_current_data_ex(ht, (void **)&val, &pos) == SUCCESS) {
609 | if (zend_hash_get_current_key_ex(ht, &key, &key_len,
610 | &key_index, 0, &pos)
611 | != HASH_KEY_IS_STRING) {
612 | zend_hash_move_forward_ex(ht, &pos);
613 | continue;
614 | }
615 |
616 | if (strcmp(key, "in") == 0) {
617 | /* in */
618 | if (Z_TYPE_PP(val) == IS_ARRAY) {
619 | HashTable *in_ht;
620 | HashPosition in_pos;
621 | zval **tmp;
622 | char *in_key_name;
623 | ulong in_key_index;
624 | uint in_key_len;
625 |
626 | in_ht = HASH_OF(*val);
627 |
628 | zend_hash_internal_pointer_reset_ex(in_ht, &in_pos);
629 | if (zend_hash_get_current_data_ex(in_ht, (void **)&tmp,
630 | &in_pos) == SUCCESS) {
631 | if (Z_TYPE_PP(tmp) == IS_ARRAY) {
632 | switch (zend_hash_get_current_key_ex(
633 | in_ht, &in_key_name, &in_key_len,
634 | &in_key_index, 0, &in_pos)) {
635 | case HASH_KEY_NON_EXISTANT:
636 | *in_key = 0;
637 | break;
638 | case HASH_KEY_IS_LONG:
639 | *in_key = in_key_index;
640 | break;
641 | default:
642 | {
643 | zval *key;
644 | MAKE_STD_ZVAL(key);
645 | ZVAL_STRINGL(key, in_key_name, in_key_len, 1);
646 | convert_to_long(key);
647 | *in_key = Z_LVAL_P(key);
648 | zval_ptr_dtor(&key);
649 | break;
650 |
651 | }
652 | }
653 | *in_values = *tmp;
654 | } else {
655 | *in_key = 0;
656 | *in_values = *val;
657 | }
658 | }
659 | } else {
660 | *in_key = 0;
661 | *in_values = *val;
662 | }
663 | } else if (strcmp(key, "filter") == 0 && filter != NULL) {
664 | /* filter */
665 | hs_zval_to_filter(filters, filter, *val,
666 | HS_PROTOCOL_FILTER TSRMLS_CC);
667 | } else if (strcmp(key, "while") == 0 && filter != NULL) {
668 | /* while */
669 | hs_zval_to_filter(filters, filter, *val,
670 | HS_PROTOCOL_WHILE TSRMLS_CC);
671 | }
672 |
673 | zend_hash_move_forward_ex(ht, &pos);
674 | }
675 | }
676 |
677 | static inline void
678 | hs_index_object_init(hs_index_obj_t *hsi,
679 | zval *link, char *db, long db_len,
680 | char *table, long table_len,
681 | zval *fields, zval *options TSRMLS_DC)
682 | {
683 | int id = 0;
684 | zval *index = NULL, *fields_str = NULL, *filter = NULL, *retval;
685 | php_stream *stream;
686 | long timeout;
687 | smart_str request = {0};
688 |
689 | if (db_len == 0) {
690 | HS_EXCEPTION("__construct(): invalid database %s", db);
691 | return;
692 | }
693 |
694 | if (table_len == 0) {
695 | HS_EXCEPTION("__construct(): invalid table %s", table);
696 | return;
697 | }
698 |
699 | fields_str = hs_zval_to_comma_string(fields);
700 | if (!fields_str) {
701 | HS_EXCEPTION("__construct(): invalid fields");
702 | return;
703 | }
704 |
705 | if (options && Z_TYPE_P(options) == IS_ARRAY) {
706 | zval **tmp;
707 | if (zend_hash_find(Z_ARRVAL_P(options), "id",
708 | sizeof("id"), (void **)&tmp) == SUCCESS) {
709 | convert_to_long_ex(tmp);
710 | id = Z_LVAL_PP(tmp);
711 | }
712 |
713 | if (zend_hash_find(Z_ARRVAL_P(options), "index",
714 | sizeof("index"), (void **)&tmp) == SUCCESS) {
715 | convert_to_string_ex(tmp);
716 | MAKE_STD_ZVAL(index);
717 | ZVAL_STRINGL(index, Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp), 1);
718 | }
719 |
720 | if (zend_hash_find(Z_ARRVAL_P(options), "filter",
721 | sizeof("filter"), (void **)&tmp) == SUCCESS) {
722 | filter = hs_zval_to_comma_array(*tmp);
723 | }
724 | }
725 |
726 | if (!index) {
727 | MAKE_STD_ZVAL(index);
728 | ZVAL_STRINGL(index, "PRIMARY", sizeof("PRIMARY")-1, 1);
729 | } else if (Z_STRLEN_P(index) <= 0) {
730 | if (index) {
731 | zval_ptr_dtor(&index);
732 | }
733 | if (fields_str) {
734 | zval_ptr_dtor(&fields_str);
735 | }
736 | if (filter) {
737 | zval_ptr_dtor(&filter);
738 | }
739 | HS_EXCEPTION("__construct(): invalid index");
740 | return;
741 | }
742 |
743 | if (id <= 0) {
744 | id = HANDLERSOCKETI_G(id)++;
745 | }
746 |
747 | /* handerlsocket: object */
748 | //hsi = (hs_index_obj_t *)zend_object_store_get_object(getThis() TSRMLS_CC);
749 | //HS_CHECK_OBJECT(hsi, HandlersocketiIndex);
750 | if (!hsi) {
751 | HS_EXCEPTION("The HandlerSocketi_Index object has not been "
752 | "correctly initialized by its constructor");
753 | return;
754 | }
755 |
756 | hsi->link = link;
757 | zval_add_ref(&hsi->link);
758 |
759 | /* id */
760 | hsi->id = id;
761 |
762 | /* name */
763 | MAKE_STD_ZVAL(hsi->name);
764 | *hsi->name = *index;
765 | zval_copy_ctor(hsi->name);
766 |
767 | /* db */
768 | MAKE_STD_ZVAL(hsi->db);
769 | ZVAL_STRINGL(hsi->db, db, db_len, 1);
770 |
771 | /* table */
772 | MAKE_STD_ZVAL(hsi->table);
773 | ZVAL_STRINGL(hsi->table, table, db_len, 1);
774 |
775 | /* field */
776 | MAKE_STD_ZVAL(hsi->field);
777 | if (Z_TYPE_P(fields) == IS_STRING) {
778 | zval delim, *arr;
779 | MAKE_STD_ZVAL(arr);
780 | array_init(arr);
781 |
782 | ZVAL_STRINGL(&delim, ",", strlen(","), 0);
783 | php_explode(&delim, fields, arr, LONG_MAX);
784 |
785 | hsi->field_num = zend_hash_num_elements(HASH_OF(arr));
786 |
787 | *hsi->field = *arr;
788 | zval_copy_ctor(hsi->field);
789 | zval_ptr_dtor(&arr);
790 | } else {
791 | hsi->field_num = zend_hash_num_elements(HASH_OF(fields));
792 | *hsi->field = *fields;
793 | zval_copy_ctor(hsi->field);
794 | }
795 |
796 | if (filter) {
797 | MAKE_STD_ZVAL(hsi->filter);
798 | *hsi->filter = *filter;
799 | zval_copy_ctor(hsi->filter);
800 | }
801 |
802 | /* stream */
803 | stream = handlersocketi_object_store_get_stream(hsi->link);
804 | timeout = handlersocketi_object_store_get_timeout(hsi->link);
805 |
806 | hs_request_string(&request, HS_PROTOCOL_OPEN, 1);
807 | hs_request_delim(&request);
808 |
809 | /* id */
810 | hs_request_long(&request, hsi->id);
811 | hs_request_delim(&request);
812 |
813 | /* db */
814 | hs_request_string(&request, db, db_len);
815 | hs_request_delim(&request);
816 |
817 | /* table */
818 | hs_request_string(&request, table, table_len);
819 | hs_request_delim(&request);
820 |
821 | /* index */
822 | hs_request_string(&request, Z_STRVAL_P(index), Z_STRLEN_P(index));
823 | hs_request_delim(&request);
824 |
825 | /* fields */
826 | hs_request_string(&request, Z_STRVAL_P(fields_str), Z_STRLEN_P(fields_str));
827 |
828 | /* filters */
829 | if (hsi->filter) {
830 | hs_request_filter(&request, HASH_OF(hsi->filter) TSRMLS_CC);
831 | }
832 |
833 | /* eol */
834 | hs_request_next(&request);
835 |
836 | /* request: send */
837 | if (hs_request_send(stream, &request TSRMLS_CC) < 0) {
838 | smart_str_free(&request);
839 | zval_ptr_dtor(&index);
840 | if (fields_str) {
841 | zval_ptr_dtor(&fields_str);
842 | }
843 | HS_EXCEPTION("__construct(): invalid request send");
844 | return;
845 | }
846 |
847 | smart_str_free(&request);
848 |
849 | /* response */
850 | MAKE_STD_ZVAL(retval);
851 | hs_response_value(stream, timeout, retval, hsi->error, 0 TSRMLS_CC);
852 | if (Z_TYPE_P(retval) == IS_BOOL && Z_LVAL_P(retval) == 0) {
853 | HS_EXCEPTION("__construct(): unable to open index: %ld: %s",
854 | id,
855 | hsi->error == NULL ?
856 | "Unknwon error" : Z_STRVAL_P(hsi->error));
857 | return;
858 | }
859 |
860 | /* cleanup */
861 | zval_ptr_dtor(&retval);
862 | zval_ptr_dtor(&index);
863 | if (fields_str) {
864 | zval_ptr_dtor(&fields_str);
865 | }
866 | }
867 |
868 | PHP_HANDLERSOCKETI_API int
869 | handlersocketi_register_index(TSRMLS_D)
870 | {
871 | zend_class_entry ce;
872 |
873 | INIT_CLASS_ENTRY(ce, "HandlerSocketi_Index", hs_index_methods);
874 |
875 | ce.create_object = hs_index_object_new;
876 |
877 | hs_ce_index = zend_register_internal_class(&ce TSRMLS_CC);
878 | if (hs_ce_index == NULL) {
879 | return FAILURE;
880 | }
881 |
882 | memcpy(&hs_index_object_handlers, zend_get_std_object_handlers(),
883 | sizeof(zend_object_handlers));
884 |
885 | hs_index_object_handlers.clone_obj = hs_index_object_clone;
886 |
887 | return SUCCESS;
888 | }
889 |
890 | PHP_HANDLERSOCKETI_API zend_class_entry
891 | *handlersocketi_get_ce_index(void) {
892 | return hs_ce_index;
893 | }
894 |
895 | PHP_HANDLERSOCKETI_API void
896 | handlersocketi_create_index(zval *return_value,
897 | zval *link, char *db, long db_len,
898 | char *table, long table_len,
899 | zval *fields, zval *options TSRMLS_DC)
900 | {
901 | object_init_ex(return_value, hs_ce_index);
902 |
903 | hs_index_object_init(zend_object_store_get_object(return_value TSRMLS_CC),
904 | link, db, db_len, table, table_len,
905 | fields, options TSRMLS_CC);
906 | }
907 |
908 | ZEND_METHOD(HandlerSocketi_Index, __construct)
909 | {
910 | zval *link;
911 | char *db, *table;
912 | int db_len, table_len, id = 0;
913 | zval *fields, *options = NULL;
914 | zval *index = NULL, *fields_str = NULL, *filter = NULL;
915 | hs_index_obj_t *hsi;
916 | php_stream *stream;
917 | long timeout;
918 | smart_str request = {0};
919 |
920 | if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Ossz|z",
921 | &link, handlersocketi_get_ce(),
922 | &db, &db_len, &table, &table_len,
923 | &fields, &options) == FAILURE) {
924 | HS_EXCEPTION("__construct(): expects parameters");
925 | zval *object = getThis();
926 | ZVAL_NULL(object);
927 | return;
928 | }
929 |
930 | if (db_len == 0) {
931 | HS_EXCEPTION("__construct(): invalid database %s", db);
932 | return;
933 | }
934 |
935 | if (table_len == 0) {
936 | HS_EXCEPTION("__construct(): invalid table %s", table);
937 | return;
938 | }
939 |
940 | fields_str = hs_zval_to_comma_string(fields);
941 | if (!fields_str) {
942 | HS_EXCEPTION("__construct(): invalid fields");
943 | return;
944 | }
945 |
946 | if (options && Z_TYPE_P(options) == IS_ARRAY) {
947 | zval **tmp;
948 | if (zend_hash_find(Z_ARRVAL_P(options), "id",
949 | sizeof("id"), (void **)&tmp) == SUCCESS) {
950 | convert_to_long_ex(tmp);
951 | id = Z_LVAL_PP(tmp);
952 | }
953 |
954 | if (zend_hash_find(Z_ARRVAL_P(options), "index",
955 | sizeof("index"), (void **)&tmp) == SUCCESS) {
956 | convert_to_string_ex(tmp);
957 | MAKE_STD_ZVAL(index);
958 | ZVAL_STRINGL(index, Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp), 1);
959 | }
960 |
961 | if (zend_hash_find(Z_ARRVAL_P(options), "filter",
962 | sizeof("filter"), (void **)&tmp) == SUCCESS) {
963 | filter = hs_zval_to_comma_array(*tmp);
964 | }
965 | }
966 |
967 | if (!index) {
968 | MAKE_STD_ZVAL(index);
969 | ZVAL_STRINGL(index, "PRIMARY", sizeof("PRIMARY")-1, 1);
970 | } else if (Z_STRLEN_P(index) <= 0) {
971 | if (index) {
972 | zval_ptr_dtor(&index);
973 | }
974 | if (fields_str) {
975 | zval_ptr_dtor(&fields_str);
976 | }
977 | if (filter) {
978 | zval_ptr_dtor(&filter);
979 | }
980 | HS_EXCEPTION("__construct(): invalid index");
981 | return;
982 | }
983 |
984 | if (id <= 0) {
985 | id = HANDLERSOCKETI_G(id)++;
986 | }
987 |
988 | /* handerlsocket: object */
989 | hsi = (hs_index_obj_t *)zend_object_store_get_object(getThis() TSRMLS_CC);
990 | HS_CHECK_OBJECT(hsi, HandlerSocketi_Index);
991 |
992 | hsi->link = link;
993 | zval_add_ref(&hsi->link);
994 |
995 | /* id */
996 | hsi->id = id;
997 |
998 | /* name */
999 | MAKE_STD_ZVAL(hsi->name);
1000 | *hsi->name = *index;
1001 | zval_copy_ctor(hsi->name);
1002 |
1003 | /* db */
1004 | MAKE_STD_ZVAL(hsi->db);
1005 | ZVAL_STRINGL(hsi->db, db, db_len, 1);
1006 |
1007 | /* table */
1008 | MAKE_STD_ZVAL(hsi->table);
1009 | ZVAL_STRINGL(hsi->table, table, db_len, 1);
1010 |
1011 | /* field */
1012 | MAKE_STD_ZVAL(hsi->field);
1013 | if (Z_TYPE_P(fields) == IS_STRING) {
1014 | zval delim, *arr;
1015 | MAKE_STD_ZVAL(arr);
1016 | array_init(arr);
1017 |
1018 | ZVAL_STRINGL(&delim, ",", strlen(","), 0);
1019 | php_explode(&delim, fields, arr, LONG_MAX);
1020 |
1021 | hsi->field_num = zend_hash_num_elements(HASH_OF(arr));
1022 |
1023 | *hsi->field = *arr;
1024 | zval_copy_ctor(hsi->field);
1025 | zval_ptr_dtor(&arr);
1026 | } else {
1027 | hsi->field_num = zend_hash_num_elements(HASH_OF(fields));
1028 | *hsi->field = *fields;
1029 | zval_copy_ctor(hsi->field);
1030 | }
1031 |
1032 | if (filter) {
1033 | MAKE_STD_ZVAL(hsi->filter);
1034 | *hsi->filter = *filter;
1035 | zval_copy_ctor(hsi->filter);
1036 | }
1037 |
1038 | /* stream */
1039 | stream = handlersocketi_object_store_get_stream(hsi->link);
1040 | timeout = handlersocketi_object_store_get_timeout(hsi->link);
1041 |
1042 | hs_request_string(&request, HS_PROTOCOL_OPEN, 1);
1043 | hs_request_delim(&request);
1044 |
1045 | /* id */
1046 | hs_request_long(&request, hsi->id);
1047 | hs_request_delim(&request);
1048 |
1049 | /* db */
1050 | hs_request_string(&request, db, db_len);
1051 | hs_request_delim(&request);
1052 |
1053 | /* table */
1054 | hs_request_string(&request, table, table_len);
1055 | hs_request_delim(&request);
1056 |
1057 | /* index */
1058 | hs_request_string(&request, Z_STRVAL_P(index), Z_STRLEN_P(index));
1059 | hs_request_delim(&request);
1060 |
1061 | /* fields */
1062 | hs_request_string(&request, Z_STRVAL_P(fields_str), Z_STRLEN_P(fields_str));
1063 |
1064 | /* filters */
1065 | if (hsi->filter) {
1066 | hs_request_filter(&request, HASH_OF(hsi->filter) TSRMLS_CC);
1067 | }
1068 |
1069 | /* eol */
1070 | hs_request_next(&request);
1071 |
1072 | /* request: send */
1073 | if (hs_request_send(stream, &request TSRMLS_CC) < 0) {
1074 | smart_str_free(&request);
1075 | zval_ptr_dtor(&index);
1076 | if (fields_str) {
1077 | zval_ptr_dtor(&fields_str);
1078 | }
1079 | HS_EXCEPTION("__construct(): invalid request send");
1080 | return;
1081 | }
1082 |
1083 | smart_str_free(&request);
1084 |
1085 | /* response */
1086 | hs_response_value(stream, timeout, return_value, hsi->error, 0 TSRMLS_CC);
1087 |
1088 | if (Z_TYPE_P(return_value) == IS_BOOL && Z_LVAL_P(return_value) == 0) {
1089 | HS_EXCEPTION("__construct(): unable to open index: %ld: %s",
1090 | id,
1091 | hsi->error == NULL ?
1092 | "Unknwon error" : Z_STRVAL_P(hsi->error));
1093 | return;
1094 | }
1095 |
1096 | /* cleanup */
1097 | zval_ptr_dtor(&index);
1098 | if (fields_str) {
1099 | zval_ptr_dtor(&fields_str);
1100 | }
1101 | }
1102 |
1103 | ZEND_METHOD(HandlerSocketi_Index, find)
1104 | {
1105 | zval *query, *operate, *criteria;
1106 | zval *options = NULL;
1107 | long safe = -1, limit = HS_DEFAULT_LIMIT, offset = HS_DEFAULT_OFFSET;
1108 | zval *filters = NULL, *in_values = NULL;
1109 | long in_key = -1;
1110 | hs_index_obj_t *hsi;
1111 | php_stream *stream;
1112 | long timeout;
1113 | smart_str request = {0};
1114 |
1115 | if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|z",
1116 | &query, &options) == FAILURE) {
1117 | RETURN_FALSE;
1118 | }
1119 |
1120 | /* handerlsocket: object */
1121 | hsi = (hs_index_obj_t *)zend_object_store_get_object(getThis() TSRMLS_CC);
1122 | HS_CHECK_OBJECT(hsi, HandlerSocketi_Index);
1123 | HS_ERROR_RESET(hsi->error);
1124 |
1125 | /* options */
1126 | if (options != NULL && Z_TYPE_P(options) == IS_ARRAY) {
1127 | /* limit */
1128 | limit = hs_get_options_long(HASH_OF(options), "limit",
1129 | limit TSRMLS_CC);
1130 | /* offset */
1131 | offset = hs_get_options_long(HASH_OF(options), "offset",
1132 | offset TSRMLS_CC);
1133 | /* safe */
1134 | safe = hs_is_options_safe(HASH_OF(options) TSRMLS_CC);
1135 | /* in, fiter, while */
1136 | hs_array_to_in_filter(HASH_OF(options), hsi->filter,
1137 | &filters, &in_key, &in_values TSRMLS_CC);
1138 | }
1139 |
1140 | /* stream */
1141 | stream = handlersocketi_object_store_get_stream(hsi->link);
1142 | timeout = handlersocketi_object_store_get_timeout(hsi->link);
1143 |
1144 | /* operate : criteria */
1145 | MAKE_STD_ZVAL(operate);
1146 | if (hs_zval_to_operate_criteria(query, operate, &criteria,
1147 | HS_FIND_EQUAL TSRMLS_CC) != SUCCESS) {
1148 | zval_ptr_dtor(&operate);
1149 | RETURN_FALSE;
1150 | }
1151 |
1152 | /* command */
1153 | hs_request_command(&request, hsi->id, operate, criteria,
1154 | limit, offset, filters, in_key, in_values TSRMLS_CC);
1155 |
1156 | /* eol */
1157 | hs_request_next(&request);
1158 |
1159 | /* request: send */
1160 | if (hs_request_send(stream, &request TSRMLS_CC) < 0) {
1161 | ZVAL_BOOL(return_value, 0);
1162 | } else {
1163 | /* response */
1164 | hs_response_value(stream, timeout, return_value,
1165 | hsi->error, 0 TSRMLS_CC);
1166 | }
1167 |
1168 | zval_ptr_dtor(&operate);
1169 | if (filters) {
1170 | zval_ptr_dtor(&filters);
1171 | }
1172 | smart_str_free(&request);
1173 |
1174 | /* exception */
1175 | if (safe > 0 &&
1176 | Z_TYPE_P(return_value) == IS_BOOL && Z_LVAL_P(return_value) == 0) {
1177 | HS_EXCEPTION("find(): response error: %s",
1178 | hsi->error == NULL ?
1179 | "Unknown error" : Z_STRVAL_P(hsi->error));
1180 | RETURN_FALSE;
1181 | }
1182 | }
1183 |
1184 | ZEND_METHOD(HandlerSocketi_Index, insert)
1185 | {
1186 | zval ***args;
1187 | zval *operate, *fields;
1188 | long i, argc = ZEND_NUM_ARGS();
1189 | hs_index_obj_t *hsi;
1190 | php_stream *stream;
1191 | long timeout;
1192 | smart_str request = {0};
1193 | long fnum = 0;
1194 |
1195 | if (argc < 1) {
1196 | zend_wrong_param_count(TSRMLS_C);
1197 | RETURN_FALSE;
1198 | }
1199 |
1200 | args = safe_emalloc(argc, sizeof(zval **), 0);
1201 | if (zend_get_parameters_array_ex(argc, args) == FAILURE) {
1202 | efree(args);
1203 | zend_wrong_param_count(TSRMLS_C);
1204 | RETURN_FALSE;
1205 | }
1206 |
1207 | if (Z_TYPE_PP(args[0]) == IS_ARRAY) {
1208 | fields = *args[0];
1209 | } else {
1210 | MAKE_STD_ZVAL(fields);
1211 | array_init(fields);
1212 |
1213 | for (i = 0; i < argc; i++) {
1214 | switch (Z_TYPE_P(*args[i])) {
1215 | case IS_NULL:
1216 | add_next_index_null(fields);
1217 | break;
1218 | case IS_LONG:
1219 | add_next_index_long(fields, Z_LVAL_P(*args[i]));
1220 | break;
1221 | case IS_DOUBLE:
1222 | add_next_index_double(fields, Z_DVAL_P(*args[i]));
1223 | break;
1224 | default:
1225 | convert_to_string(*args[i]);
1226 | add_next_index_stringl(fields, Z_STRVAL_P(*args[i]),
1227 | Z_STRLEN_P(*args[i]), 1);
1228 | break;
1229 | }
1230 | }
1231 | }
1232 |
1233 | /* handerlsocket: object */
1234 | hsi = (hs_index_obj_t *)zend_object_store_get_object(getThis() TSRMLS_CC);
1235 | HS_CHECK_OBJECT(hsi, HandlerSocketi_Index);
1236 | HS_ERROR_RESET(hsi->error);
1237 |
1238 | /* fiedls check */
1239 | fnum = zend_hash_num_elements(HASH_OF(fields));
1240 | if (fnum < hsi->field_num) {
1241 | for (i = 0; i < fnum; i++) {
1242 | add_next_index_null(fields);
1243 | }
1244 | } else if (fnum > hsi->field_num) {
1245 | /*
1246 | efree(args);
1247 | ZVAL_STRINGL(hsi->error, "invalid field count",
1248 | strlen("invalid field count"), 1);
1249 | RETURN_FALSE;
1250 | */
1251 | zend_error(E_WARNING,
1252 | "HandlerSocketi_Index::insert(): invalid field count");
1253 | }
1254 |
1255 | stream = handlersocketi_object_store_get_stream(hsi->link);
1256 | timeout = handlersocketi_object_store_get_timeout(hsi->link);
1257 |
1258 | /* operate */
1259 | MAKE_STD_ZVAL(operate);
1260 | ZVAL_STRINGL(operate, HS_PROTOCOL_INSERT, 1, 1);
1261 |
1262 | /* command */
1263 | hs_request_command(&request, hsi->id, operate, fields,
1264 | 0, 0, NULL, -1, NULL TSRMLS_CC);
1265 |
1266 | /* eol */
1267 | hs_request_next(&request);
1268 |
1269 | /* request: send */
1270 | if (hs_request_send(stream, &request TSRMLS_CC) < 0) {
1271 | ZVAL_BOOL(return_value, 0);
1272 | } else {
1273 | /* response */
1274 | hs_response_value(stream, timeout, return_value,
1275 | hsi->error, 1 TSRMLS_CC);
1276 | }
1277 |
1278 | zval_ptr_dtor(&operate);
1279 | //zval_ptr_dtor(&fields);
1280 | smart_str_free(&request);
1281 | efree(args);
1282 | }
1283 |
1284 | ZEND_METHOD(HandlerSocketi_Index, update)
1285 | {
1286 | zval *query, *update, *options = NULL;
1287 | long safe = -1, modify = 1;
1288 | long limit = HS_DEFAULT_LIMIT, offset = HS_DEFAULT_OFFSET;
1289 | zval *operate, *criteria, *modify_operate, *modify_criteria;
1290 | zval *filters = NULL, *in_values = NULL;
1291 | long in_key = -1;
1292 | hs_index_obj_t *hsi;
1293 | php_stream *stream;
1294 | long timeout;
1295 | smart_str request = {0};
1296 | long fnum = 0;
1297 |
1298 | if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz|z",
1299 | &query, &update, &options) == FAILURE) {
1300 | RETURN_FALSE;
1301 | }
1302 |
1303 | /* handerlsocket: object */
1304 | hsi = (hs_index_obj_t *)zend_object_store_get_object(getThis() TSRMLS_CC);
1305 | HS_CHECK_OBJECT(hsi, HandlerSocketi_Index);
1306 | HS_ERROR_RESET(hsi->error);
1307 |
1308 | if (options != NULL && Z_TYPE_P(options) == IS_ARRAY) {
1309 | /* limit */
1310 | limit = hs_get_options_long(HASH_OF(options), "limit",
1311 | limit TSRMLS_CC);
1312 | /* offset */
1313 | offset = hs_get_options_long(HASH_OF(options), "offset",
1314 | offset TSRMLS_CC);
1315 | /* safe */
1316 | safe = hs_is_options_safe(HASH_OF(options) TSRMLS_CC);
1317 | /* in, fiter, while */
1318 | hs_array_to_in_filter(HASH_OF(options), hsi->filter,
1319 | &filters, &in_key, &in_values TSRMLS_CC);
1320 | }
1321 |
1322 | /* stream */
1323 | stream = handlersocketi_object_store_get_stream(hsi->link);
1324 | timeout = handlersocketi_object_store_get_timeout(hsi->link);
1325 |
1326 | /* operate : criteria */
1327 | MAKE_STD_ZVAL(operate);
1328 | if (hs_zval_to_operate_criteria(query, operate, &criteria,
1329 | HS_FIND_EQUAL TSRMLS_CC) != SUCCESS) {
1330 | zval_ptr_dtor(&operate);
1331 | RETURN_FALSE;
1332 | }
1333 |
1334 | /* modify_operete : modify_criteria */
1335 | MAKE_STD_ZVAL(modify_operate);
1336 | if (hs_zval_to_operate_criteria(update, modify_operate, &modify_criteria,
1337 | HS_MODIFY_UPDATE TSRMLS_CC) != SUCCESS) {
1338 | zval_ptr_dtor(&operate);
1339 | zval_ptr_dtor(&modify_operate);
1340 | RETURN_FALSE;
1341 | }
1342 |
1343 | /* fiedls check */
1344 | if (Z_TYPE_P(modify_criteria) == IS_ARRAY) {
1345 | fnum = zend_hash_num_elements(HASH_OF(modify_criteria));
1346 | } else {
1347 | fnum = 1;
1348 | }
1349 |
1350 | if (fnum > hsi->field_num) {
1351 | /*
1352 | ZVAL_STRINGL(hsi->error, "invalid field count",
1353 | strlen("invalid field count"), 1);
1354 | RETURN_FALSE;
1355 | */
1356 | zend_error(E_WARNING,
1357 | "HandlerSocketi_Index::update(): invalid field count");
1358 | }
1359 |
1360 | /* command */
1361 | hs_request_command(&request, hsi->id, operate, criteria,
1362 | limit, offset, filters, in_key, in_values TSRMLS_CC);
1363 |
1364 | /* command: modify */
1365 | modify = hs_request_command_modify(&request, modify_operate,
1366 | modify_criteria, -1 TSRMLS_CC);
1367 | if (modify >= 0) {
1368 | /* eol */
1369 | hs_request_next(&request);
1370 |
1371 | /* request: send */
1372 | if (hs_request_send(stream, &request TSRMLS_CC) < 0) {
1373 | ZVAL_BOOL(return_value, 0);
1374 | } else {
1375 | /* response */
1376 | hs_response_value(stream, timeout, return_value,
1377 | hsi->error, modify TSRMLS_CC);
1378 | }
1379 | } else {
1380 | ZVAL_BOOL(return_value, 0);
1381 | ZVAL_STRINGL(hsi->error, "unable to update parameter",
1382 | strlen("unable to update parameter"), 1);
1383 | }
1384 |
1385 | zval_ptr_dtor(&operate);
1386 | zval_ptr_dtor(&modify_operate);
1387 | if (filters) {
1388 | zval_ptr_dtor(&filters);
1389 | }
1390 | smart_str_free(&request);
1391 |
1392 | /* exception */
1393 | if (safe > 0 &&
1394 | Z_TYPE_P(return_value) == IS_BOOL && Z_LVAL_P(return_value) == 0) {
1395 | HS_EXCEPTION("update(): response error: %s",
1396 | hsi->error == NULL ?
1397 | "Unknown error" : Z_STRVAL_P(hsi->error));
1398 | }
1399 | }
1400 |
1401 | ZEND_METHOD(HandlerSocketi_Index, remove)
1402 | {
1403 | zval *query, *options = NULL;
1404 | zval *operate, *criteria;
1405 | long safe = -1, limit = HS_DEFAULT_LIMIT, offset = HS_DEFAULT_OFFSET;
1406 | zval *filters = NULL, *in_values = NULL;
1407 | long in_key = -1;
1408 | hs_index_obj_t *hsi;
1409 | php_stream *stream;
1410 | long timeout;
1411 | smart_str request = {0};
1412 |
1413 | if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|z",
1414 | &query, &options) == FAILURE) {
1415 | RETURN_FALSE;
1416 | }
1417 |
1418 | /* handelrsocket : object */
1419 | hsi = (hs_index_obj_t *)zend_object_store_get_object(getThis() TSRMLS_CC);
1420 | HS_CHECK_OBJECT(hsi, HandlerSocketi_Index);
1421 | HS_ERROR_RESET(hsi->error);
1422 |
1423 | if (options != NULL && Z_TYPE_P(options) == IS_ARRAY) {
1424 | /* limit */
1425 | limit = hs_get_options_long(HASH_OF(options), "limit",
1426 | limit TSRMLS_CC);
1427 | /* offset */
1428 | offset = hs_get_options_long(HASH_OF(options), "offset",
1429 | offset TSRMLS_CC);
1430 | /* safe */
1431 | safe = hs_is_options_safe(HASH_OF(options) TSRMLS_CC);
1432 | /* in, fiter, while */
1433 | hs_array_to_in_filter(HASH_OF(options), hsi->filter,
1434 | &filters, &in_key, &in_values TSRMLS_CC);
1435 | }
1436 |
1437 | /* stream */
1438 | stream = handlersocketi_object_store_get_stream(hsi->link);
1439 | timeout = handlersocketi_object_store_get_timeout(hsi->link);
1440 |
1441 | /* operate : criteria */
1442 | MAKE_STD_ZVAL(operate);
1443 | if (hs_zval_to_operate_criteria(query, operate, &criteria,
1444 | HS_FIND_EQUAL TSRMLS_CC) != SUCCESS) {
1445 | zval_ptr_dtor(&operate);
1446 | RETURN_FALSE;
1447 | }
1448 |
1449 | /* command */
1450 | hs_request_command(&request, hsi->id, operate, criteria,
1451 | limit, offset, filters, in_key, in_values TSRMLS_CC);
1452 |
1453 | /* find: modify: D */
1454 | hs_request_delim(&request);
1455 | hs_request_string(&request, HS_MODIFY_REMOVE, 1);
1456 |
1457 | /* eol */
1458 | hs_request_next(&request);
1459 |
1460 | /* request: send */
1461 | if (hs_request_send(stream, &request TSRMLS_CC) < 0) {
1462 | ZVAL_BOOL(return_value, 0);
1463 | } else {
1464 | /* response */
1465 | hs_response_value(stream, timeout, return_value,
1466 | hsi->error, 1 TSRMLS_CC);
1467 | }
1468 |
1469 | zval_ptr_dtor(&operate);
1470 | if (filters) {
1471 | zval_ptr_dtor(&filters);
1472 | }
1473 | smart_str_free(&request);
1474 |
1475 | /* exception */
1476 | if (safe > 0 &&
1477 | Z_TYPE_P(return_value) == IS_BOOL && Z_LVAL_P(return_value) == 0) {
1478 | HS_EXCEPTION("remove(): response error: %s",
1479 | hsi->error == NULL ?
1480 | "Unknown error" : Z_STRVAL_P(hsi->error));
1481 | }
1482 | }
1483 |
1484 | ZEND_METHOD(HandlerSocketi_Index, multi)
1485 | {
1486 | zval *args = NULL;
1487 |
1488 | zval *mreq;
1489 | HashPosition pos;
1490 | zval **val;
1491 | int err = -1;
1492 |
1493 | hs_index_obj_t *hsi;
1494 | php_stream *stream;
1495 | long timeout;
1496 | smart_str request = {0};
1497 |
1498 | if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a",
1499 | &args) == FAILURE) {
1500 | RETURN_FALSE;
1501 | }
1502 |
1503 | /* handlersocket: object */
1504 | hsi = (hs_index_obj_t *)zend_object_store_get_object(getThis() TSRMLS_CC);
1505 | HS_CHECK_OBJECT(hsi, HandlerSocketi_Index);
1506 | HS_ERROR_RESET(hsi->error);
1507 |
1508 | MAKE_STD_ZVAL(mreq);
1509 | array_init(mreq);
1510 |
1511 | zend_hash_internal_pointer_reset_ex(HASH_OF(args), &pos);
1512 | while (zend_hash_get_current_data_ex(HASH_OF(args),
1513 | (void **)&val, &pos) == SUCCESS) {
1514 | zval **method;
1515 | HashTable *ht;
1516 |
1517 | if (Z_TYPE_PP(val) != IS_ARRAY) {
1518 | err = -1;
1519 | break;
1520 | }
1521 |
1522 | ht = HASH_OF(*val);
1523 |
1524 | /* 0: method */
1525 | if (zend_hash_index_find(ht, 0, (void **)&method) != SUCCESS) {
1526 | err = -1;
1527 | break;
1528 | }
1529 |
1530 | convert_to_string(*method);
1531 |
1532 | if (strncmp(Z_STRVAL_PP(method), "find", strlen("find")) == 0) {
1533 | /* method: find */
1534 | zval **query, **options, *operate, *criteria;
1535 | zval *filters = NULL, *in_values = NULL;
1536 | long in_key = -1;
1537 | long limit = HS_DEFAULT_LIMIT, offset = HS_DEFAULT_OFFSET;
1538 |
1539 | if (zend_hash_num_elements(ht) <= 1) {
1540 | err = -1;
1541 | break;
1542 | }
1543 |
1544 | /* 1: query */
1545 | if (zend_hash_index_find(ht, 1, (void **)&query) != SUCCESS) {
1546 | err = -1;
1547 | break;
1548 | }
1549 |
1550 | /* 2: options */
1551 | if (zend_hash_index_find(ht, 2, (void **)&options) == SUCCESS &&
1552 | options != NULL && Z_TYPE_PP(options) == IS_ARRAY) {
1553 | limit = hs_get_options_long(HASH_OF(*options),
1554 | "limit", limit TSRMLS_CC);
1555 | offset = hs_get_options_long(HASH_OF(*options),
1556 | "offset", offset TSRMLS_CC);
1557 | hs_array_to_in_filter(HASH_OF(*options), hsi->filter,
1558 | &filters, &in_key, &in_values TSRMLS_CC);
1559 | }
1560 |
1561 | /* operete : criteria */
1562 | MAKE_STD_ZVAL(operate);
1563 | if (hs_zval_to_operate_criteria(*query, operate, &criteria,
1564 | HS_FIND_EQUAL TSRMLS_CC)
1565 | != SUCCESS) {
1566 | err = -1;
1567 | zval_ptr_dtor(&operate);
1568 | break;
1569 | }
1570 |
1571 | if (*query == NULL) {
1572 | err = -1;
1573 | zval_ptr_dtor(&operate);
1574 | break;
1575 | }
1576 |
1577 | /* command */
1578 | hs_request_command(&request, hsi->id, operate, criteria,
1579 | limit, offset, filters, in_key,
1580 | in_values TSRMLS_CC);
1581 |
1582 | /* eol */
1583 | hs_request_next(&request);
1584 |
1585 | add_next_index_long(mreq, 0);
1586 | err = 0;
1587 |
1588 | zval_ptr_dtor(&operate);
1589 | if (filters) {
1590 | zval_ptr_dtor(&filters);
1591 | }
1592 | } else if (strncmp(Z_STRVAL_PP(method),
1593 | "insert", strlen("insert")) == 0) {
1594 | /* method: insert */
1595 | zval *operate, *fields;
1596 | zval **tmp;
1597 | long i, n, fnum = 0;
1598 |
1599 | if (zend_hash_num_elements(ht) <= 1) {
1600 | err = -1;
1601 | break;
1602 | }
1603 |
1604 | if (zend_hash_index_find(ht, 1, (void **)&tmp) != SUCCESS) {
1605 | err = -1;
1606 | break;
1607 | }
1608 |
1609 | MAKE_STD_ZVAL(fields);
1610 | array_init(fields);
1611 |
1612 | if (Z_TYPE_PP(tmp) == IS_ARRAY) {
1613 | n = zend_hash_num_elements(HASH_OF(*tmp));
1614 | for (i = 0; i < n; i++) {
1615 | zval **val;
1616 | if (zend_hash_index_find(HASH_OF(*tmp),
1617 | i, (void **)&val) == SUCCESS) {
1618 | if (Z_TYPE_PP(val) == IS_NULL) {
1619 | add_next_index_null(fields);
1620 | } else {
1621 | convert_to_string(*val);
1622 | add_next_index_stringl(fields, Z_STRVAL_PP(val),
1623 | Z_STRLEN_PP(val), 1);
1624 | }
1625 | }
1626 | }
1627 | } else {
1628 | i = 1;
1629 | do {
1630 | if (Z_TYPE_PP(tmp) == IS_NULL) {
1631 | add_next_index_null(fields);
1632 | } else {
1633 | convert_to_string(*tmp);
1634 | add_next_index_stringl(fields, Z_STRVAL_PP(tmp),
1635 | Z_STRLEN_PP(tmp), 1);
1636 | }
1637 |
1638 | i++;
1639 |
1640 | if (zend_hash_index_find(ht, i, (void **)&tmp) != SUCCESS) {
1641 | break;
1642 | }
1643 | } while (i < n);
1644 | }
1645 |
1646 | /* fields check */
1647 | fnum = zend_hash_num_elements(HASH_OF(fields));
1648 | if (fnum < hsi->field_num) {
1649 | for (i = 0; i < fnum; i++) {
1650 | add_next_index_null(fields);
1651 | }
1652 | }
1653 |
1654 | MAKE_STD_ZVAL(operate);
1655 | ZVAL_STRINGL(operate, HS_PROTOCOL_INSERT, 1, 1);
1656 |
1657 | /* command */
1658 | hs_request_command(&request, hsi->id, operate, fields, 0, 0,
1659 | NULL, -1, NULL TSRMLS_CC);
1660 |
1661 | /* eol */
1662 | hs_request_next(&request);
1663 |
1664 | add_next_index_long(mreq, 1);
1665 | err = 0;
1666 |
1667 | zval_ptr_dtor(&operate);
1668 | zval_ptr_dtor(&fields);
1669 | } else if (strncmp(Z_STRVAL_PP(method),
1670 | "remove", strlen("remove")) == 0) {
1671 | /* method: remove */
1672 | zval **query, **options, *operate, *criteria;
1673 | zval *filters = NULL, *in_values = NULL;
1674 | long in_key = -1;
1675 | long limit = HS_DEFAULT_LIMIT, offset = HS_DEFAULT_OFFSET;
1676 |
1677 | if (zend_hash_num_elements(ht) <= 1) {
1678 | err = -1;
1679 | break;
1680 | }
1681 |
1682 | /* 1: query */
1683 | if (zend_hash_index_find(ht, 1, (void **)&query) != SUCCESS) {
1684 | if (operate) {
1685 | zval_ptr_dtor(&operate);
1686 | }
1687 | err = -1;
1688 | break;
1689 | }
1690 |
1691 | /* 2: options */
1692 | if (zend_hash_index_find(ht, 2, (void **)&options) == SUCCESS &&
1693 | options != NULL && Z_TYPE_PP(options) == IS_ARRAY) {
1694 | limit = hs_get_options_long(HASH_OF(*options),
1695 | "limit", limit TSRMLS_CC);
1696 | offset = hs_get_options_long(HASH_OF(*options),
1697 | "offset", offset TSRMLS_CC);
1698 | hs_array_to_in_filter(HASH_OF(*options), hsi->filter,
1699 | &filters, &in_key, &in_values TSRMLS_CC);
1700 | }
1701 |
1702 | /* operete : criteria */
1703 | MAKE_STD_ZVAL(operate);
1704 | if (hs_zval_to_operate_criteria(*query, operate, &criteria,
1705 | HS_FIND_EQUAL TSRMLS_CC)
1706 | != SUCCESS) {
1707 | zval_ptr_dtor(&operate);
1708 | err = -1;
1709 | break;
1710 | }
1711 |
1712 | /* command */
1713 | hs_request_command(&request, hsi->id, operate, criteria,
1714 | limit, offset, filters, in_key,
1715 | in_values TSRMLS_CC);
1716 |
1717 | /* find: modify: D */
1718 | hs_request_delim(&request);
1719 |
1720 | hs_request_string(&request, HS_MODIFY_REMOVE, 1);
1721 |
1722 | /* eol */
1723 | hs_request_next(&request);
1724 |
1725 | add_next_index_long(mreq, 1);
1726 | err = 0;
1727 |
1728 | zval_ptr_dtor(&operate);
1729 | if (filters) {
1730 | zval_ptr_dtor(&filters);
1731 | }
1732 | } else if (strncmp(Z_STRVAL_PP(method),
1733 | "update", strlen("update")) == 0) {
1734 | /* method: update */
1735 | zval **query, **update, **options;
1736 | zval *operate, *criteria, *modify_operate, *modify_criteria;
1737 | zval *filters = NULL, *in_values = NULL;
1738 | long in_key = -1;
1739 | long limit = HS_DEFAULT_LIMIT, offset = HS_DEFAULT_OFFSET;
1740 | int modify;
1741 |
1742 | if (zend_hash_num_elements(ht) <= 2) {
1743 | err = -1;
1744 | break;
1745 | }
1746 |
1747 | /* 1: query */
1748 | if (zend_hash_index_find(ht, 1, (void **)&query) != SUCCESS) {
1749 | err = -1;
1750 | break;
1751 | }
1752 |
1753 | /* 2: update */
1754 | if (zend_hash_index_find(ht, 2, (void **)&update) != SUCCESS) {
1755 | err = -1;
1756 | break;
1757 | }
1758 |
1759 | /* 3: options */
1760 | if (zend_hash_index_find(ht, 3, (void **)&options) == SUCCESS &&
1761 | options != NULL && Z_TYPE_PP(options) == IS_ARRAY) {
1762 | limit = hs_get_options_long(HASH_OF(*options),
1763 | "limit", limit TSRMLS_CC);
1764 | offset = hs_get_options_long(HASH_OF(*options),
1765 | "offset", offset TSRMLS_CC);
1766 | hs_array_to_in_filter(HASH_OF(*options), hsi->filter,
1767 | &filters, &in_key, &in_values TSRMLS_CC);
1768 | }
1769 |
1770 | /* operete : criteria */
1771 | MAKE_STD_ZVAL(operate);
1772 | if (hs_zval_to_operate_criteria(*query, operate, &criteria,
1773 | HS_FIND_EQUAL TSRMLS_CC)
1774 | != SUCCESS) {
1775 | zval_ptr_dtor(&operate);
1776 | err = -1;
1777 | break;
1778 | }
1779 |
1780 | /* modify_operete : modify_criteria */
1781 | MAKE_STD_ZVAL(modify_operate);
1782 | if (hs_zval_to_operate_criteria(*update, modify_operate,
1783 | &modify_criteria,
1784 | HS_MODIFY_UPDATE TSRMLS_CC)
1785 | != SUCCESS) {
1786 | zval_ptr_dtor(&operate);
1787 | zval_ptr_dtor(&modify_operate);
1788 | err = -1;
1789 | break;
1790 | }
1791 |
1792 | /* command */
1793 | hs_request_command(&request, hsi->id, operate, criteria,
1794 | limit, offset, filters, in_key,
1795 | in_values TSRMLS_CC);
1796 |
1797 | /* command: modify */
1798 | modify = hs_request_command_modify(&request, modify_operate,
1799 | modify_criteria, -1 TSRMLS_CC);
1800 | if (modify < 0) {
1801 | err = -1;
1802 | break;
1803 | }
1804 |
1805 | /* eol */
1806 | hs_request_next(&request);
1807 |
1808 | add_next_index_long(mreq, modify);
1809 | err = 0;
1810 |
1811 | zval_ptr_dtor(&operate);
1812 | zval_ptr_dtor(&modify_operate);
1813 | if (filters) {
1814 | zval_ptr_dtor(&filters);
1815 | }
1816 | } else {
1817 | err = -1;
1818 | break;
1819 | }
1820 |
1821 | zend_hash_move_forward_ex(HASH_OF(args), &pos);
1822 | }
1823 |
1824 | /* stream */
1825 | stream = handlersocketi_object_store_get_stream(hsi->link);
1826 | timeout = handlersocketi_object_store_get_timeout(hsi->link);
1827 |
1828 | /* request: send */
1829 | if (err < 0 || hs_request_send(stream, &request TSRMLS_CC) < 0) {
1830 | smart_str_free(&request);
1831 | zval_ptr_dtor(&mreq);
1832 | RETURN_FALSE;
1833 | }
1834 | smart_str_free(&request);
1835 |
1836 | /* response */
1837 | hs_response_multi(stream, timeout, return_value, hsi->error, mreq TSRMLS_CC);
1838 |
1839 | zval_ptr_dtor(&mreq);
1840 | }
1841 |
1842 | ZEND_METHOD(HandlerSocketi_Index, get_error)
1843 | {
1844 | hs_index_obj_t *hsi;
1845 |
1846 | hsi = (hs_index_obj_t *)zend_object_store_get_object(getThis() TSRMLS_CC);
1847 | HS_CHECK_OBJECT(hsi, HandlerSocketi_Index);
1848 |
1849 | if (hsi->error == NULL) {
1850 | RETURN_NULL();
1851 | } else {
1852 | RETVAL_ZVAL(hsi->error, 1, 0);
1853 | }
1854 | }
1855 |
1856 | ZEND_METHOD(HandlerSocketi_Index, get_id)
1857 | {
1858 | hs_index_obj_t *hsi;
1859 |
1860 | hsi = (hs_index_obj_t *)zend_object_store_get_object(getThis() TSRMLS_CC);
1861 | HS_CHECK_OBJECT(hsi, HandlerSocketi_Index);
1862 |
1863 | RETVAL_LONG(hsi->id);
1864 | }
1865 |
1866 | ZEND_METHOD(HandlerSocketi_Index, get_name)
1867 | {
1868 | hs_index_obj_t *hsi;
1869 |
1870 | hsi = (hs_index_obj_t *)zend_object_store_get_object(getThis() TSRMLS_CC);
1871 | HS_CHECK_OBJECT(hsi, HandlerSocketi_Index);
1872 |
1873 | RETVAL_ZVAL(hsi->name, 1, 0);
1874 | }
1875 |
1876 | ZEND_METHOD(HandlerSocketi_Index, get_db)
1877 | {
1878 | hs_index_obj_t *hsi;
1879 |
1880 | hsi = (hs_index_obj_t *)zend_object_store_get_object(getThis() TSRMLS_CC);
1881 | HS_CHECK_OBJECT(hsi, HandlerSocketi_Index);
1882 |
1883 | RETVAL_ZVAL(hsi->db, 1, 0);
1884 | }
1885 |
1886 | ZEND_METHOD(HandlerSocketi_Index, get_table)
1887 | {
1888 | hs_index_obj_t *hsi;
1889 |
1890 | hsi = (hs_index_obj_t *)zend_object_store_get_object(getThis() TSRMLS_CC);
1891 | HS_CHECK_OBJECT(hsi, HandlerSocketi_Index);
1892 |
1893 | RETVAL_ZVAL(hsi->table, 1, 0);
1894 | }
1895 |
1896 | ZEND_METHOD(HandlerSocketi_Index, get_field)
1897 | {
1898 | hs_index_obj_t *hsi;
1899 |
1900 | hsi = (hs_index_obj_t *)zend_object_store_get_object(getThis() TSRMLS_CC);
1901 | HS_CHECK_OBJECT(hsi, HandlerSocketi_Index);
1902 |
1903 | RETVAL_ZVAL(hsi->field, 1, 0);
1904 | }
1905 |
1906 | ZEND_METHOD(HandlerSocketi_Index, get_filter)
1907 | {
1908 | hs_index_obj_t *hsi;
1909 |
1910 | hsi = (hs_index_obj_t *)zend_object_store_get_object(getThis() TSRMLS_CC);
1911 | HS_CHECK_OBJECT(hsi, HandlerSocketi_Index);
1912 |
1913 | if (hsi->filter) {
1914 | RETVAL_ZVAL(hsi->filter, 1, 0);
1915 | } else {
1916 | RETVAL_NULL();
1917 | }
1918 | }
1919 |
1920 | ZEND_METHOD(HandlerSocketi_Index, get_operator)
1921 | {
1922 | zval *query, *modify;
1923 |
1924 | MAKE_STD_ZVAL(query);
1925 | array_init(query);
1926 |
1927 | add_next_index_stringl(query, HS_FIND_EQUAL, strlen(HS_FIND_EQUAL), 1);
1928 | add_next_index_stringl(query, HS_FIND_LESS, strlen(HS_FIND_LESS), 1);
1929 | add_next_index_stringl(query, HS_FIND_LESS_EQUAL,
1930 | strlen(HS_FIND_LESS_EQUAL), 1);
1931 | add_next_index_stringl(query, HS_FIND_GREATER, strlen(HS_FIND_GREATER), 1);
1932 | add_next_index_stringl(query, HS_FIND_GREATER_EQUAL,
1933 | strlen(HS_FIND_GREATER_EQUAL), 1);
1934 |
1935 | MAKE_STD_ZVAL(modify);
1936 | array_init(modify);
1937 |
1938 | add_next_index_stringl(modify, HS_MODIFY_UPDATE,
1939 | strlen(HS_MODIFY_UPDATE), 1);
1940 | add_next_index_stringl(modify, HS_MODIFY_INCREMENT,
1941 | strlen(HS_MODIFY_INCREMENT), 1);
1942 | add_next_index_stringl(modify, HS_MODIFY_DECREMENT,
1943 | strlen(HS_MODIFY_DECREMENT), 1);
1944 | add_next_index_stringl(modify, HS_MODIFY_REMOVE,
1945 | strlen(HS_MODIFY_REMOVE), 1);
1946 | add_next_index_stringl(modify, HS_MODIFY_GET_UPDATE,
1947 | strlen(HS_MODIFY_GET_UPDATE), 1);
1948 | add_next_index_stringl(modify, HS_MODIFY_GET_INCREMENT,
1949 | strlen(HS_MODIFY_GET_INCREMENT), 1);
1950 | add_next_index_stringl(modify, HS_MODIFY_GET_DECREMENT,
1951 | strlen(HS_MODIFY_GET_DECREMENT), 1);
1952 | add_next_index_stringl(modify, HS_MODIFY_GET_REMOVE,
1953 | strlen(HS_MODIFY_GET_REMOVE), 1);
1954 |
1955 | array_init(return_value);
1956 | add_assoc_zval(return_value, "query", query);
1957 | add_assoc_zval(return_value, "modify", modify);
1958 | }
1959 |
--------------------------------------------------------------------------------
/handlersocketi_index.h:
--------------------------------------------------------------------------------
1 | #ifndef HANDLERSOCKETI_INDEX_H
2 | #define HANDLERSOCKETI_INDEX_H
3 |
4 | PHP_HANDLERSOCKETI_API int handlersocketi_register_index(TSRMLS_D);
5 | PHP_HANDLERSOCKETI_API zend_class_entry *handlersocketi_get_ce_index(void);
6 | PHP_HANDLERSOCKETI_API void handlersocketi_create_index(
7 | zval *return_value, zval *link, char *db, long db_len,
8 | char *table, long table_len, zval *fields, zval *options TSRMLS_DC);
9 |
10 | #endif /* HANDLERSOCKETI_INDEX_H */
11 |
--------------------------------------------------------------------------------
/php_handlersocketi.h:
--------------------------------------------------------------------------------
1 |
2 | #ifndef PHP_HANDLERSOCKETI_H
3 | #define PHP_HANDLERSOCKETI_H
4 |
5 | #define HANDLERSOCKETI_EXT_VERSION "0.0.1"
6 |
7 | extern zend_module_entry handlersocketi_module_entry;
8 | #define phpext_handlersocketi_ptr &handlersocketi_module_entry
9 |
10 | #ifdef PHP_WIN32
11 | # define PHP_HANDLERSOCKETI_API __declspec(dllexport)
12 | #elif defined(__GNUC__) && __GNUC__ >= 4
13 | # define PHP_HANDLERSOCKETI_API __attribute__ ((visibility("default")))
14 | #else
15 | # define PHP_HANDLERSOCKETI_API
16 | #endif
17 |
18 | #ifdef ZTS
19 | #include "TSRM.h"
20 | #endif
21 |
22 | ZEND_BEGIN_MODULE_GLOBALS(handlersocketi)
23 | long id;
24 | ZEND_END_MODULE_GLOBALS(handlersocketi)
25 |
26 | #ifdef ZTS
27 | #define HANDLERSOCKETI_G(v) TSRMG(handlersocketi_globals_id, zend_handlersocketi_globals *, v)
28 | #else
29 | #define HANDLERSOCKETI_G(v) (handlersocketi_globals.v)
30 | #endif
31 |
32 | #endif /* PHP_HANDLERSOCKETI_H */
33 |
--------------------------------------------------------------------------------
/php_verdep.h:
--------------------------------------------------------------------------------
1 | #ifndef PHP_VERDEP_H
2 | #define PHP_VERDEP_H
3 |
4 | #ifndef ZED_FE_END
5 | #define ZEND_FE_END { NULL, NULL, NULL, 0, 0 }
6 | #endif
7 |
8 | #ifndef Z_SET_REFCOUNT_P
9 | #define Z_SET_REFCOUNT_P(pz, rc) ((pz)->refcount = rc)
10 | #endif
11 |
12 | #ifndef Z_UNSET_ISREF_PP
13 | #define Z_UNSET_ISREF_PP(ppz) Z_UNSET_ISREF_P(*(ppz))
14 | #endif
15 |
16 | #ifndef Z_UNSET_ISREF_P
17 | #define Z_UNSET_ISREF_P(pz) ((pz)->is_ref = 0)
18 | #endif
19 |
20 | #ifndef Z_ISREF_PP
21 | #define Z_ISREF_PP(ppz) Z_ISREF_P(*(ppz))
22 | #endif
23 |
24 | #ifndef Z_ISREF_P
25 | #if ZEND_MODULE_API_NO >= 20090626
26 | #define Z_ISREF_P(pz) zval_isref_p(pz)
27 | #else
28 | #define Z_ISREF_P(pz) ((pz)->is_ref)
29 | #endif
30 | #endif
31 |
32 | #ifndef Z_ADDREF_PP
33 | #define Z_ADDREF_PP(ppz) Z_ADDREF_P(*(ppz))
34 | #endif
35 |
36 | #ifndef Z_ADDREF_P
37 | #if ZEND_MODULE_API_NO >= 20090626
38 | #define Z_ADDREF_P(pz) zval_addref_p(pz)
39 | #else
40 | #define Z_ADDREF_P(pz) (++(pz)->refcount)
41 | #endif
42 | #endif
43 |
44 | #ifndef Z_SET_ISREF_PP
45 | #define Z_SET_ISREF_PP(ppz) Z_SET_ISREF_P(*(ppz))
46 | #endif
47 |
48 | #ifndef Z_SET_ISREF_P
49 | #if ZEND_MODULE_API_NO >= 20090626
50 | #define Z_SET_ISREF_P(pz) zval_set_isref_p(pz)
51 | #else
52 | #define Z_SET_ISREF_P(pz) ((pz)->is_ref = 1)
53 | #endif
54 | #endif
55 |
56 | #ifndef array_init_size
57 | #define array_init_size(arg, size) _array_init((arg) ZEND_FILE_LINE_CC)
58 | #endif
59 |
60 | #ifndef zend_parse_parameters_none
61 | #define zend_parse_parameters_none() \
62 | zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "")
63 | #endif
64 |
65 | #endif /* PHP_VERDEP_H */
66 |
--------------------------------------------------------------------------------
/util/common.h:
--------------------------------------------------------------------------------
1 | #ifndef HANDLERSOCKET_COMMON_H
2 | #define HANDLERSOCKET_COMMON_H
3 |
4 | #define HS_PROTOCOL_OPEN "P"
5 | #define HS_PROTOCOL_AUTH "A"
6 | #define HS_PROTOCOL_INSERT "+"
7 | #define HS_PROTOCOL_FILTER "F"
8 | #define HS_PROTOCOL_WHILE "W"
9 | #define HS_PROTOCOL_IN "@"
10 |
11 | #define HS_FIND_EQUAL "="
12 | #define HS_FIND_LESS "<"
13 | #define HS_FIND_LESS_EQUAL "<="
14 | #define HS_FIND_GREATER ">"
15 | #define HS_FIND_GREATER_EQUAL ">="
16 |
17 | #define HS_MODIFY_UPDATE "U"
18 | #define HS_MODIFY_INCREMENT "+"
19 | #define HS_MODIFY_DECREMENT "-"
20 | #define HS_MODIFY_REMOVE "D"
21 | #define HS_MODIFY_GET_UPDATE "U?"
22 | #define HS_MODIFY_GET_INCREMENT "+?"
23 | #define HS_MODIFY_GET_DECREMENT "-?"
24 | #define HS_MODIFY_GET_REMOVE "D?"
25 |
26 | #define HS_CODE_NULL 0x00
27 | #define HS_CODE_DELIMITER 0x09
28 | #define HS_CODE_EOL 0x0a
29 | #define HS_CODE_ESCAPE 0x10
30 | #define HS_CODE_ESCAPE_PREFIX 0x01
31 | #define HS_CODE_ESCAPE_ADD 0x40
32 |
33 | #endif /* HANDLERSOCKET_COMMON_H */
34 |
--------------------------------------------------------------------------------
/util/request.c:
--------------------------------------------------------------------------------
1 |
2 | #include "php.h"
3 | #include "php_network.h"
4 |
5 | #include "common.h"
6 | #include "request.h"
7 |
8 | static inline void
9 | hs_request_zval_scalar(smart_str *buf, zval *val, int delim)
10 | {
11 | switch (Z_TYPE_P(val)) {
12 | case IS_LONG:
13 | hs_request_long(buf, Z_LVAL_P(val));
14 | break;
15 | case IS_STRING:
16 | hs_request_string(buf, Z_STRVAL_P(val), Z_STRLEN_P(val));
17 | break;
18 | case IS_DOUBLE:
19 | convert_to_string(val);
20 | hs_request_string(buf, Z_STRVAL_P(val), Z_STRLEN_P(val));
21 | break;
22 | case IS_BOOL:
23 | convert_to_long(val);
24 | hs_request_long(buf, Z_LVAL_P(val));
25 | break;
26 | case IS_NULL:
27 | hs_request_null(buf);
28 | break;
29 | default:
30 | //IS_ARRAY
31 | //IS_OBJECT
32 | //IS_RESOURCE
33 | hs_request_long(buf, 0);
34 | break;
35 | }
36 |
37 | if (delim > 0) {
38 | hs_request_delim(buf);
39 | }
40 | }
41 |
42 | void
43 | hs_request_string(smart_str *buf, char *str, long str_len)
44 | {
45 | long i;
46 |
47 | if (str_len <= 0) {
48 | return;
49 | } else {
50 | for (i = 0; i < str_len; i++) {
51 | if ((unsigned char)str[i] > HS_CODE_ESCAPE) {
52 | smart_str_appendc(buf, str[i]);
53 | } else {
54 | smart_str_appendc(buf, HS_CODE_ESCAPE_PREFIX);
55 | smart_str_appendc(buf, (unsigned char)str[i]+HS_CODE_ESCAPE_ADD);
56 | }
57 | }
58 | }
59 | }
60 |
61 | void
62 | hs_request_array(smart_str *buf, HashTable *ht, int num, int i TSRMLS_DC)
63 | {
64 | long n;
65 | HashPosition pos;
66 | zval **data;
67 |
68 | n = zend_hash_num_elements(ht);
69 | if (i > 0 && i < n) {
70 | n = i;
71 | }
72 |
73 | if (n == 0) {
74 | if (num == 1) {
75 | hs_request_long(buf, 1);
76 | hs_request_delim(buf);
77 | }
78 | hs_request_null(buf);
79 | return;
80 | }
81 |
82 | if (num == 1) {
83 | hs_request_long(buf, n);
84 | hs_request_delim(buf);
85 | }
86 |
87 | zend_hash_internal_pointer_reset_ex(ht, &pos);
88 | while (zend_hash_get_current_data_ex(ht, (void **)&data, &pos) == SUCCESS) {
89 | if (n <= 0) {
90 | break;
91 | }
92 | n--;
93 | hs_request_zval_scalar(buf, *data, n);
94 | zend_hash_move_forward_ex(ht, &pos);
95 | }
96 | }
97 |
98 | void
99 | hs_request_filter(smart_str *request, HashTable *ht TSRMLS_DC)
100 | {
101 | zval **tmp;
102 | HashPosition pos;
103 | long n, i = 0;
104 |
105 | n = zend_hash_num_elements(ht);
106 | if (n >= 0) {
107 | hs_request_delim(request);
108 |
109 | zend_hash_internal_pointer_reset_ex(ht, &pos);
110 | while (zend_hash_get_current_data_ex(ht,
111 | (void **)&tmp, &pos) == SUCCESS) {
112 | switch ((*tmp)->type) {
113 | case IS_STRING:
114 | hs_request_string(request, Z_STRVAL_PP(tmp),
115 | Z_STRLEN_PP(tmp));
116 | break;
117 | case IS_LONG:
118 | hs_request_long(request, Z_LVAL_PP(tmp));
119 | break;
120 | default:
121 | convert_to_string(*tmp);
122 | hs_request_string(request, Z_STRVAL_PP(tmp),
123 | Z_STRLEN_PP(tmp));
124 | break;
125 | }
126 |
127 | if (++i != n) {
128 | hs_request_string(request, ",", strlen(","));
129 | }
130 |
131 | zend_hash_move_forward_ex(ht, &pos);
132 | }
133 | }
134 | }
135 |
136 | void
137 | hs_request_command(smart_str *buf, long id, zval * operate, zval *criteria,
138 | long limit, long offset, zval *filters, long in_key,
139 | zval *in_values TSRMLS_DC)
140 | {
141 | hs_request_long(buf, id);
142 | hs_request_delim(buf);
143 |
144 | convert_to_string(operate);
145 | hs_request_string(buf, Z_STRVAL_P(operate), Z_STRLEN_P(operate));
146 | hs_request_delim(buf);
147 |
148 | if (Z_TYPE_P(criteria) == IS_ARRAY) {
149 | hs_request_array(buf, HASH_OF(criteria), 1, -1 TSRMLS_CC);
150 | } else {
151 | hs_request_long(buf, 1);
152 | hs_request_delim(buf);
153 | hs_request_zval_scalar(buf, criteria, 0);
154 | }
155 |
156 | hs_request_delim(buf);
157 | hs_request_long(buf, limit);
158 |
159 | hs_request_delim(buf);
160 | hs_request_long(buf, offset);
161 |
162 | if (in_key >= 0 && in_values != NULL) {
163 | hs_request_delim(buf);
164 |
165 | hs_request_string(buf, HS_PROTOCOL_IN, 1);
166 | hs_request_delim(buf);
167 |
168 | hs_request_long(buf, in_key);
169 | hs_request_delim(buf);
170 |
171 | if (Z_TYPE_P(in_values) == IS_ARRAY) {
172 | hs_request_array(buf, HASH_OF(in_values), 1, -1 TSRMLS_CC);
173 | } else {
174 | hs_request_zval_scalar(buf, in_values, 0);
175 | }
176 | }
177 |
178 | if (filters != NULL && Z_TYPE_P(filters) == IS_ARRAY) {
179 | HashTable *ht;
180 | HashPosition pos;
181 | zval **tmp;
182 |
183 | ht = HASH_OF(filters);
184 |
185 | zend_hash_internal_pointer_reset_ex(ht, &pos);
186 | while (zend_hash_get_current_data_ex(ht, (void **)&tmp,
187 | &pos) == SUCCESS) {
188 | if (Z_TYPE_PP(tmp) != IS_ARRAY ||
189 | zend_hash_num_elements(HASH_OF(*tmp)) < 4) {
190 | zend_hash_move_forward_ex(ht, &pos);
191 | continue;
192 | }
193 |
194 | hs_request_delim(buf);
195 |
196 | hs_request_array(buf, HASH_OF(*tmp), -1, 4 TSRMLS_CC);
197 |
198 | zend_hash_move_forward_ex(ht, &pos);
199 | }
200 | }
201 | }
202 |
203 | int
204 | hs_request_command_modify(smart_str *buf, zval *update,
205 | zval *values, long field TSRMLS_DC)
206 | {
207 | int ret = -1;
208 | long len;
209 |
210 | if (update == NULL || Z_TYPE_P(update) != IS_STRING) {
211 | return -1;
212 | }
213 |
214 | len = Z_STRLEN_P(update);
215 | if (len == 1) {
216 | ret = 1;
217 | } else if (len == 2) {
218 | ret = 0;
219 | } else {
220 | return -1;
221 | }
222 |
223 | if (values == NULL) {
224 | hs_request_delim(buf);
225 | hs_request_string(buf, Z_STRVAL_P(update), Z_STRLEN_P(update));
226 |
227 | hs_request_delim(buf);
228 | hs_request_null(buf);
229 | } else if (Z_TYPE_P(values) == IS_ARRAY) {
230 | if (field > 0 &&
231 | zend_hash_num_elements(HASH_OF(values)) < field) {
232 | return -1;
233 | }
234 |
235 | hs_request_delim(buf);
236 | hs_request_string(buf, Z_STRVAL_P(update), Z_STRLEN_P(update));
237 |
238 | hs_request_delim(buf);
239 | hs_request_array(buf, HASH_OF(values), 0, -1 TSRMLS_CC);
240 | } else {
241 | if (field > 0 && field != 1) {
242 | return -1;
243 | }
244 |
245 | hs_request_delim(buf);
246 | hs_request_string(buf, Z_STRVAL_P(update), Z_STRLEN_P(update));
247 |
248 | hs_request_delim(buf);
249 | hs_request_zval_scalar(buf, values, 0);
250 | }
251 |
252 | return ret;
253 | }
254 |
255 | long
256 | hs_request_send(php_stream *stream, smart_str *request TSRMLS_DC)
257 | {
258 | #ifdef HS_DEBUG
259 | long i;
260 | smart_str debug = {0};
261 | if (request->len <= 0) {
262 | return -1;
263 | }
264 | for (i = 0; i < request->len; i++) {
265 | if ((unsigned char)request->c[i] == HS_CODE_NULL) {
266 | smart_str_appendl_ex(&debug, "\\0", strlen("\\0"), 1);
267 | } else {
268 | smart_str_appendc(&debug, request->c[i]);
269 | }
270 | }
271 | smart_str_0(&debug);
272 | php_printf("[handlersocket] (request) %ld : \"%s\"\n",
273 | request->len, debug.c);
274 | smart_str_free(&debug);
275 | #endif
276 |
277 | if (!stream) {
278 | return -1;
279 | }
280 |
281 | return php_stream_write(stream, request->c, request->len);
282 | }
283 |
--------------------------------------------------------------------------------
/util/request.h:
--------------------------------------------------------------------------------
1 | #ifndef HANDLERSOCKET_REQUEST_H
2 | #define HANDLERSOCKET_REQUEST_H
3 |
4 | #include "ext/standard/php_smart_str.h"
5 | #include "php_streams.h"
6 |
7 | #define hs_request_long(buf, num) smart_str_append_long(buf, num)
8 | #define hs_request_null(buf) smart_str_appendc(buf, HS_CODE_NULL)
9 | #define hs_request_delim(buf) smart_str_appendc(buf, HS_CODE_DELIMITER)
10 | #define hs_request_next(buf) smart_str_appendc(buf, HS_CODE_EOL)
11 |
12 | void hs_request_string(smart_str *buf, char *str, long str_len);
13 |
14 | void hs_request_array(smart_str *buf, HashTable *ht, int num, int i TSRMLS_DC);
15 | void hs_request_filter(smart_str *request, HashTable *ht TSRMLS_DC);
16 |
17 | void hs_request_command(smart_str *buf, long id, zval * operate, zval *criteria,
18 | long limit, long offset, zval *filters, long in_key,
19 | zval *in_values TSRMLS_DC);
20 | int hs_request_command_modify(smart_str *buf, zval *update,
21 | zval *values, long field TSRMLS_DC);
22 |
23 | long hs_request_send(php_stream *stream, smart_str *request TSRMLS_DC);
24 |
25 | #endif /* HANDLERSOCKET_REQUEST_H */
26 |
--------------------------------------------------------------------------------
/util/response.c:
--------------------------------------------------------------------------------
1 |
2 | #include "php.h"
3 | #include "php_network.h"
4 | #include "ext/standard/php_smart_str.h"
5 |
6 | #include "common.h"
7 | #include "response.h"
8 |
9 | #define HS_SOCKET_BLOCK_SIZE 4096
10 |
11 | #ifndef PHP_WIN32
12 | #define php_select(m, r, w, e, t) select(m, r, w, e, t)
13 | #else
14 | #include "win32/select.h"
15 | #endif
16 |
17 | static inline long
18 | hs_response_select(php_stream *stream, long timeout TSRMLS_DC)
19 | {
20 | php_socket_t max_fd = 0;
21 | int retval, max_set_count = 0;
22 | struct timeval tv;
23 | struct timeval *tv_p = NULL;
24 | fd_set fds;
25 |
26 | FD_ZERO(&fds);
27 |
28 | if (php_stream_cast(stream,
29 | PHP_STREAM_AS_FD_FOR_SELECT|PHP_STREAM_CAST_INTERNAL,
30 | (void*)&max_fd, 1) == SUCCESS && max_fd != -1) {
31 | PHP_SAFE_FD_SET(max_fd, &fds);
32 | max_set_count++;
33 | }
34 |
35 | PHP_SAFE_MAX_FD(max_fd, max_set_count);
36 |
37 | if (timeout > 0) {
38 | tv.tv_sec = timeout;
39 | tv.tv_usec = 0;
40 | tv_p = &tv;
41 | }
42 |
43 | retval = php_select(max_fd+1, &fds, NULL, NULL, tv_p);
44 | if (retval == -1) {
45 | zend_error(E_WARNING, "[HandlerSocket] unable to select");
46 | return -1;
47 | }
48 |
49 | if (!PHP_SAFE_FD_ISSET(max_fd, &fds)) {
50 | return -1;
51 | }
52 |
53 | return 0;
54 | }
55 |
56 | static inline long
57 | hs_response_recv(php_stream *stream, char *recv, size_t size TSRMLS_DC)
58 | {
59 | long ret;
60 | #ifdef HS_DEBUG
61 | long i;
62 | smart_str debug = {0};
63 | #endif
64 |
65 | ret = php_stream_read(stream, recv, size);
66 | if (ret <= 0) {
67 | return -1;
68 | }
69 | recv[size] = '\0';
70 |
71 | #ifdef HS_DEBUG
72 | for (i = 0; i < ret; i++) {
73 | if ((unsigned char)recv[i] == HS_CODE_NULL) {
74 | smart_str_appendl_ex(&debug, "\\0", strlen("\\0"), 1);
75 | } else {
76 | smart_str_appendc(&debug, recv[i]);
77 | }
78 | }
79 | smart_str_0(&debug);
80 | php_printf("[handlersocket] (recv) %ld : \"%s\"", ret, debug.c);
81 | smart_str_free(&debug);
82 | #endif
83 |
84 | return ret;
85 | }
86 |
87 | static inline zval
88 | *hs_response_add(zval *return_value TSRMLS_DC)
89 | {
90 | zval *value;
91 | MAKE_STD_ZVAL(value);
92 | array_init(value);
93 | add_next_index_zval(return_value, value);
94 | return value;
95 | }
96 |
97 | static inline zval
98 | *hs_response_zval(smart_str *buf TSRMLS_DC)
99 | {
100 | zval *val;
101 | MAKE_STD_ZVAL(val);
102 | ZVAL_STRINGL(val, buf->c, buf->len, 1);
103 | return val;
104 | }
105 |
106 | void
107 | hs_response_value(php_stream *stream, long timeout, zval *return_value,
108 | zval *error, int modify TSRMLS_DC)
109 | {
110 | char *recv;
111 | long i, j, len;
112 | zval *val, *item;
113 |
114 | smart_str response = {0};
115 | long n = 0, block_size = HS_SOCKET_BLOCK_SIZE;
116 | int escape = 0, flag = 0, null = 0;
117 | long ret[2] = {-1, -1};
118 |
119 | if (hs_response_select(stream, timeout TSRMLS_CC) < 0) {
120 | ZVAL_BOOL(return_value, 0);
121 | }
122 |
123 | recv = emalloc(block_size+1);
124 | len = hs_response_recv(stream, recv, block_size TSRMLS_CC);
125 | if (len <= 0) {
126 | efree(recv);
127 | ZVAL_BOOL(return_value, 0);
128 | return;
129 | }
130 |
131 | do {
132 | for (i = 0; i < len; i++) {
133 | if (recv[i] == HS_CODE_DELIMITER || recv[i] == HS_CODE_EOL) {
134 | val = hs_response_zval(&response TSRMLS_CC);
135 | convert_to_long(val);
136 | ret[flag] = Z_LVAL_P(val);
137 | flag++;
138 | zval_ptr_dtor(&val);
139 | smart_str_free(&response);
140 | } else {
141 | smart_str_appendc(&response, recv[i]);
142 | }
143 |
144 | if (flag > 1) {
145 | break;
146 | }
147 | }
148 |
149 | if (flag > 1) {
150 | break;
151 | } else {
152 | i = 0;
153 | len = hs_response_recv(stream, recv, block_size TSRMLS_CC);
154 | if (len <= 0) {
155 | break;
156 | }
157 | }
158 | } while (1);
159 |
160 | if (ret[0] != 0) {
161 | if (recv[i] != HS_CODE_EOL) {
162 | smart_str err = {0};
163 |
164 | i++;
165 |
166 | if (i > len) {
167 | i = 0;
168 | len = -1;
169 | }
170 |
171 | do {
172 | for (j = i; j < len; j++) {
173 | if (recv[j] == HS_CODE_EOL) {
174 | break;
175 | }
176 |
177 | if (recv[j] == HS_CODE_ESCAPE_PREFIX) {
178 | escape = 1;
179 | } else if (escape) {
180 | escape = 0;
181 | smart_str_appendc(
182 | &err, (unsigned char)recv[j]-HS_CODE_ESCAPE_ADD);
183 | } else {
184 | smart_str_appendc(&err, recv[j]);
185 | }
186 | }
187 |
188 | if (recv[j] == HS_CODE_EOL) {
189 | break;
190 | }
191 |
192 | i = 0;
193 | } while ((len = hs_response_recv(
194 | stream, recv, block_size TSRMLS_CC)) > 0);
195 |
196 | if (error) {
197 | ZVAL_STRINGL(error, err.c, err.len, 1);
198 | }
199 |
200 | smart_str_free(&err);
201 | } else if (error) {
202 | ZVAL_NULL(error);
203 | }
204 |
205 | efree(recv);
206 | ZVAL_BOOL(return_value, 0);
207 |
208 | return;
209 | }
210 |
211 | if (ret[1] == 1 && recv[i] == HS_CODE_EOL) {
212 | efree(recv);
213 | ZVAL_BOOL(return_value, 1);
214 | return;
215 | }
216 |
217 | i++;
218 |
219 | if (i > len) {
220 | i = 0;
221 | len = -1;
222 | }
223 |
224 | if (modify) {
225 | if (i > 0 && recv[i-1] == HS_CODE_EOL) {
226 | efree(recv);
227 | ZVAL_LONG(return_value, 0);
228 | return;
229 | }
230 |
231 | do {
232 | for (j = i; j < len; j++) {
233 | if (recv[j] == HS_CODE_EOL) {
234 | ZVAL_STRINGL(return_value, response.c, response.len, 1);
235 | break;
236 | }
237 |
238 | if (recv[j] == HS_CODE_ESCAPE_PREFIX) {
239 | escape = 1;
240 | } else if (escape) {
241 | escape = 0;
242 | smart_str_appendc(
243 | &response, (unsigned char)recv[j]-HS_CODE_ESCAPE_ADD);
244 | } else {
245 | smart_str_appendc(&response, recv[j]);
246 | }
247 | }
248 |
249 | if (recv[j] == HS_CODE_EOL) {
250 | break;
251 | }
252 | i = 0;
253 | } while ((len = hs_response_recv(
254 | stream, recv, block_size TSRMLS_CC)) > 0);
255 |
256 | convert_to_long(return_value);
257 | } else {
258 | array_init(return_value);
259 |
260 | if (i > 0 && recv[i-1] == HS_CODE_EOL) {
261 | efree(recv);
262 | return;
263 | }
264 |
265 | item = hs_response_add(return_value TSRMLS_CC);
266 |
267 | do {
268 | for (j = i; j < len; j++) {
269 | if (recv[j] == HS_CODE_DELIMITER) {
270 | if (response.len == 0 && null == 1) {
271 | add_next_index_null(item);
272 | } else {
273 | add_next_index_stringl(item, response.c,
274 | response.len, 1);
275 | }
276 |
277 | n++;
278 | null = 0;
279 | if (n == ret[1]) {
280 | item = hs_response_add(return_value TSRMLS_CC);
281 | n = 0;
282 | }
283 |
284 | smart_str_free(&response);
285 |
286 | continue;
287 | } else if (recv[j] == HS_CODE_EOL) {
288 | if (response.len == 0 && null == 1) {
289 | add_next_index_null(item);
290 | } else {
291 | add_next_index_stringl(item, response.c,
292 | response.len, 1);
293 | }
294 | null = 0;
295 | break;
296 | }
297 |
298 | if (recv[j] == HS_CODE_ESCAPE_PREFIX) {
299 | escape = 1;
300 | } else if (escape) {
301 | escape = 0;
302 | smart_str_appendc(
303 | &response, (unsigned char)recv[j]-HS_CODE_ESCAPE_ADD);
304 | } else if (recv[j] == HS_CODE_NULL) {
305 | null = 1;
306 | } else {
307 | smart_str_appendc(&response, recv[j]);
308 | }
309 | }
310 |
311 | if (recv[j] == HS_CODE_EOL) {
312 | break;
313 | }
314 | i = 0;
315 | } while ((len = hs_response_recv(
316 | stream, recv, block_size TSRMLS_CC)) > 0);
317 | }
318 |
319 | efree(recv);
320 |
321 | smart_str_free(&response);
322 | }
323 |
324 | void
325 | hs_response_multi(php_stream *stream, long timeout, zval *return_value,
326 | zval *error, zval *mreq TSRMLS_DC)
327 | {
328 | char *recv;
329 | long i, len, count;
330 | long current = 0;
331 | smart_str response = {0};
332 | long block_size = HS_SOCKET_BLOCK_SIZE;
333 |
334 | if (hs_response_select(stream, timeout TSRMLS_CC) < 0) {
335 | ZVAL_BOOL(return_value, 0);
336 | }
337 |
338 | recv = emalloc(block_size+1);
339 | len = hs_response_recv(stream, recv, block_size TSRMLS_CC);
340 | if (len <= 0) {
341 | efree(recv);
342 | RETVAL_BOOL(0);
343 | }
344 |
345 | count = zend_hash_num_elements(HASH_OF(mreq));
346 |
347 | array_init(return_value);
348 |
349 | array_init(error);
350 |
351 | for(i = 0; i < count; i++) {
352 | long j, k;
353 | zval *rval, *item, *val, **tmp;
354 |
355 | int flag = 0, escape = 0, null = 0;
356 | long n = 0, modify = 0;
357 | long ret[2] = {-1, -1};
358 |
359 | if (zend_hash_index_find(HASH_OF(mreq), i, (void **)&tmp) == SUCCESS) {
360 | modify = Z_LVAL_PP(tmp);
361 | }
362 |
363 | smart_str_free(&response);
364 |
365 | do {
366 | for (j = current; j < len; j++) {
367 | if (recv[j] == HS_CODE_DELIMITER || recv[j] == HS_CODE_EOL) {
368 | rval = hs_response_zval(&response TSRMLS_CC);
369 | convert_to_long(rval);
370 | ret[flag] = Z_LVAL_P(rval);
371 | flag++;
372 | zval_ptr_dtor(&rval);
373 | smart_str_free(&response);
374 | } else {
375 | smart_str_appendc(&response, recv[j]);
376 | }
377 |
378 | if (flag > 1) {
379 | break;
380 | }
381 | }
382 |
383 | if (flag > 1) {
384 | break;
385 | } else {
386 | j = 0;
387 | current = 0;
388 | len = hs_response_recv(stream, recv, block_size TSRMLS_CC);
389 | if (len <= 0) {
390 | break;
391 | }
392 | }
393 | } while (1);
394 |
395 | if (ret[0] != 0) {
396 | if (recv[j] != HS_CODE_EOL) {
397 | smart_str err = {0};
398 |
399 | j++;
400 |
401 | if (j > len) {
402 | j = 0;
403 | current = 0;
404 | len = -1;
405 | }
406 |
407 | do {
408 | for (k = j; k < len; k++) {
409 | if (recv[k] == HS_CODE_EOL) {
410 | break;
411 | }
412 |
413 | if (recv[k] == HS_CODE_ESCAPE_PREFIX) {
414 | escape = 1;
415 | } else if (escape) {
416 | escape = 0;
417 | smart_str_appendc(
418 | &err,
419 | (unsigned char)recv[k] - HS_CODE_ESCAPE_ADD);
420 | } else {
421 | smart_str_appendc(&err, recv[k]);
422 | }
423 | }
424 |
425 | if (recv[k] == HS_CODE_EOL) {
426 | current = k;
427 | break;
428 | }
429 |
430 | j = 0;
431 | current = 0;
432 |
433 | } while ((len = hs_response_recv(
434 | stream, recv, block_size TSRMLS_CC)) > 0);
435 |
436 | add_next_index_stringl(error, err.c, err.len, 1);
437 |
438 | smart_str_free(&err);
439 | } else {
440 | add_next_index_null(error);
441 | }
442 |
443 | add_next_index_bool(return_value, 0);
444 |
445 | current++;
446 |
447 | continue;
448 | }
449 |
450 | add_next_index_null(error);
451 |
452 | if (ret[1] == 1 && recv[j] == HS_CODE_EOL) {
453 | add_next_index_bool(return_value, 1);
454 |
455 | current = j + 1;
456 |
457 | continue;
458 | }
459 |
460 | j++;
461 |
462 | if (j > len) {
463 | j = 0;
464 | current = 0;
465 | len = -1;
466 | }
467 |
468 | if (modify) {
469 | zval *num_z;
470 |
471 | if (j > 0 && recv[j-1] == HS_CODE_EOL) {
472 | current = j;
473 |
474 | add_next_index_long(return_value, 0);
475 |
476 | continue;
477 | }
478 |
479 | MAKE_STD_ZVAL(num_z);
480 |
481 | do {
482 | for (k = j; k < len; k++) {
483 | if (recv[k] == HS_CODE_EOL) {
484 | ZVAL_STRINGL(num_z, response.c, response.len, 1);
485 | break;
486 | }
487 |
488 | if (recv[k] == HS_CODE_ESCAPE_PREFIX) {
489 | escape = 1;
490 | } else if (escape) {
491 | escape = 0;
492 | smart_str_appendc(
493 | &response,
494 | (unsigned char)recv[k] - HS_CODE_ESCAPE_ADD);
495 | } else {
496 | smart_str_appendc(&response, recv[k]);
497 | }
498 | }
499 |
500 | if (recv[k] == HS_CODE_EOL) {
501 | current = k;
502 | break;
503 | }
504 |
505 | j = 0;
506 | current = 0;
507 |
508 | } while ((len = hs_response_recv(
509 | stream, recv, block_size TSRMLS_CC)) > 0);
510 |
511 | convert_to_long(num_z);
512 |
513 | add_next_index_long(return_value, Z_LVAL_P(num_z));
514 |
515 | zval_ptr_dtor(&num_z);
516 | } else {
517 | item = hs_response_add(return_value TSRMLS_CC);
518 |
519 | if (j > 0 && recv[j-1] == HS_CODE_EOL) {
520 | current = j;
521 | continue;
522 | }
523 |
524 | val = hs_response_add(item TSRMLS_CC);
525 |
526 | do {
527 | for (k = j; k < len; k++) {
528 | if (recv[k] == HS_CODE_DELIMITER) {
529 | if (response.len == 0 && null == 1) {
530 | add_next_index_null(val);
531 | } else {
532 | add_next_index_stringl(val, response.c,
533 | response.len, 1);
534 | }
535 |
536 | null = 0;
537 | n++;
538 | if (n == ret[1]) {
539 | val = hs_response_add(item TSRMLS_CC);
540 | n = 0;
541 | }
542 |
543 | smart_str_free(&response);
544 |
545 | continue;
546 | } else if (recv[k] == HS_CODE_EOL) {
547 | if (response.len == 0 && null == 1) {
548 | add_next_index_null(val);
549 | } else {
550 | add_next_index_stringl(val, response.c,
551 | response.len, 1);
552 | }
553 | null = 0;
554 | break;
555 | }
556 |
557 | if (recv[k] == HS_CODE_ESCAPE_PREFIX) {
558 | escape = 1;
559 | } else if (escape) {
560 | escape = 0;
561 | smart_str_appendc(
562 | &response,
563 | (unsigned char)recv[k] - HS_CODE_ESCAPE_ADD);
564 | } else if (recv[k] == HS_CODE_NULL) {
565 | null = 1;
566 | } else {
567 | smart_str_appendc(&response, recv[k]);
568 | }
569 | }
570 |
571 | if (recv[k] == HS_CODE_EOL) {
572 | current = k;
573 | break;
574 | }
575 |
576 | j = 0;
577 | current = 0;
578 |
579 | } while ((len = hs_response_recv(
580 | stream, recv, block_size TSRMLS_CC)) > 0);
581 | }
582 |
583 | current++;
584 | }
585 |
586 | efree(recv);
587 |
588 | smart_str_free(&response);
589 | }
590 |
--------------------------------------------------------------------------------
/util/response.h:
--------------------------------------------------------------------------------
1 | #ifndef HANDLERSOCKET_RESPONSE_H
2 | #define HANDLERSOCKET_RESPONSE_H
3 |
4 | #include "php_streams.h"
5 |
6 | #define HS_CODE_NULL 0x00
7 | #define HS_CODE_DELIMITER 0x09
8 | #define HS_CODE_EOL 0x0a
9 | #define HS_CODE_ESCAPE 0x10
10 | #define HS_CODE_ESCAPE_PREFIX 0x01
11 | #define HS_CODE_ESCAPE_ADD 0x40
12 |
13 | void hs_response_value(php_stream *stream, long timeout, zval *return_value,
14 | zval *error, int modify TSRMLS_DC);
15 | void hs_response_multi(php_stream *stream, long timeout, zval *return_value,
16 | zval *error, zval *mreq TSRMLS_DC);
17 |
18 | #endif /* HANDLERSOCKET_RESPONSE_H */
19 |
--------------------------------------------------------------------------------