1 /*
2    +----------------------------------------------------------------------+
3    | Copyright (c) The PHP Group                                          |
4    +----------------------------------------------------------------------+
5    | This source file is subject to version 3.01 of the PHP license,      |
6    | that is bundled with this package in the file LICENSE, and is        |
7    | available through the world-wide-web at the following url:           |
8    | http://www.php.net/license/3_01.txt                                  |
9    | If you did not receive a copy of the PHP license and are unable to   |
10    | obtain it through the world-wide-web, please send a note to          |
11    | license@php.net so we can mail you a copy immediately.               |
12    +----------------------------------------------------------------------+
13    | Authors:                                                             |
14    |          Israel Ekpo <iekpo@php.net>                                 |
15    |          Omar Shaban <omars@php.net>                                 |
16    +----------------------------------------------------------------------+
17 */
18 
19 #include "php_solr.h"
20 
21 /* {{{ static void solr_serialize_xml_set_param_props(xmlNode *xml_param_node, solr_param_t *param) */
solr_serialize_xml_set_param_props(xmlNode * xml_param_node,solr_param_t * param)22 static void solr_serialize_xml_set_param_props(xmlNode *xml_param_node, solr_param_t *param)
23 {
24 	char tmp_buffer[32]; /* This should be enough to hold any value */
25 
26 	memset(tmp_buffer, 0, sizeof(tmp_buffer));
27 
28 	/* Set the name attribute on the param node */
29 	xmlNewProp(xml_param_node, (xmlChar *) "name", (xmlChar *) param->param_name);
30 
31 	php_sprintf(tmp_buffer, "%d", param->type);
32 
33 	/* Set the type attribute on the param node */
34 	xmlNewProp(xml_param_node, (xmlChar *) "type", (xmlChar *) tmp_buffer);
35 
36 	php_sprintf(tmp_buffer, "%d", param->allow_multiple);
37 
38 	/* Set the allow_multiple attribute on the param node */
39 	xmlNewProp(xml_param_node, (xmlChar *) "allow_multiple", (xmlChar *) tmp_buffer);
40 
41 	php_sprintf(tmp_buffer, "%u", param->count);
42 
43 	/* Set the count attribute on the param node */
44 	xmlNewProp(xml_param_node, (xmlChar *) "count", (xmlChar *) tmp_buffer);
45 
46 	php_sprintf(tmp_buffer, "%d", param->delimiter);
47 
48 	/* Set the delimiter attribute on the param node */
49 	xmlNewProp(xml_param_node, (xmlChar *) "delimiter", (xmlChar *) tmp_buffer);
50 
51 	php_sprintf(tmp_buffer, "%d", param->arg_separator);
52 
53 	/* Set the arg_separator attribute on the param node */
54 	xmlNewProp(xml_param_node, (xmlChar *) "arg_separator", (xmlChar *) tmp_buffer);
55 }
56 /* }}} */
57 
58 /* {{{ static void solr_serialize_normal_param_value(xmlNode *xml_params_node, solr_param_t *param) */
solr_serialize_normal_param_value(xmlNode * xml_params_node,solr_param_t * param)59 static void solr_serialize_normal_param_value(xmlNode *xml_params_node, solr_param_t *param)
60 {
61 	xmlNode *xml_param_node = xmlNewChild(xml_params_node, NULL, (xmlChar *) "param", NULL);
62 
63 	solr_param_value_t *curr_value = param->head;
64 
65 	solr_serialize_xml_set_param_props(xml_param_node, param);
66 
67 	while(curr_value != NULL)
68 	{
69 		xmlChar *param_value_txt = xmlEncodeEntitiesReentrant(xml_params_node->doc, (xmlChar *) curr_value->contents.normal.str);
70 
71 		xmlNewChild(xml_param_node, NULL, (xmlChar *) "param_value", param_value_txt);
72 
73 		xmlFree(param_value_txt);
74 
75 		curr_value = curr_value->next; /* Go to the next value in the list */
76 	}
77 }
78 /* }}} */
79 
80 /* {{{ static void solr_serialize_simple_list_param_value(xmlNode *xml_params_node, solr_param_t *param) */
solr_serialize_simple_list_param_value(xmlNode * xml_params_node,solr_param_t * param)81 static void solr_serialize_simple_list_param_value(xmlNode *xml_params_node, solr_param_t *param)
82 {
83 	xmlNode *xml_param_node = xmlNewChild(xml_params_node, NULL, (xmlChar *) "param", NULL);
84 
85 	solr_param_value_t *curr_value = param->head;
86 
87 	solr_serialize_xml_set_param_props(xml_param_node, param);
88 
89 	while(curr_value != NULL)
90 	{
91 		xmlChar *param_value_txt = xmlEncodeEntitiesReentrant(xml_params_node->doc, (xmlChar *) curr_value->contents.simple_list.str);
92 
93 		xmlNewChild(xml_param_node, NULL, (xmlChar *) "param_value", param_value_txt);
94 
95 		xmlFree(param_value_txt);
96 
97 		curr_value = curr_value->next; /* Go to the next value in the list */
98 	}
99 }
100 /* }}} */
101 
102 /* {{{ static void solr_serialize_arg_list_param_value(xmlNode *xml_params_node, solr_param_t *param)  */
solr_serialize_arg_list_param_value(xmlNode * xml_params_node,solr_param_t * param)103 static void solr_serialize_arg_list_param_value(xmlNode *xml_params_node, solr_param_t *param)
104 {
105 	xmlNode *xml_param_node = xmlNewChild(xml_params_node, NULL, (xmlChar *) "param", NULL);
106 
107 	solr_param_value_t *curr_value = param->head;
108 
109 	solr_serialize_xml_set_param_props(xml_param_node, param);
110 
111 	while(curr_value != NULL)
112 	{
113 		xmlChar *param_value_txt = xmlEncodeEntitiesReentrant(xml_params_node->doc, (xmlChar *) curr_value->contents.arg_list.value.str);
114 
115 		xmlChar *arg_value_txt = xmlEncodeEntitiesReentrant(xml_params_node->doc, (xmlChar *) curr_value->contents.arg_list.arg.str);
116 
117 		xmlNode *xml_param_value = xmlNewChild(xml_param_node, NULL, (xmlChar *) "param_value", param_value_txt);
118 
119 		xmlNewProp(xml_param_value, (xmlChar *) "argument", arg_value_txt);
120 
121 		xmlFree(param_value_txt);
122 
123 		xmlFree(arg_value_txt);
124 
125 		curr_value = curr_value->next; /* Go to the next value in the list */
126 	}
127 }
128 /* }}} */
129 
130 /* {{{ static int solr_serialize_solr_params_object(xmlChar **serialized, int *size, zval *objptr) */
solr_serialize_solr_params_object(xmlChar ** serialized,int * size,zval * objptr)131 static int solr_serialize_solr_params_object(xmlChar **serialized, int *size, zval *objptr)
132 {
133 	solr_params_t *solr_params = NULL;
134 	xmlNode *xml_solr_params = NULL, *xml_params = NULL;
135 	xmlDoc *doc_ptr = NULL;
136 	HashTable *params = NULL;
137 	int format = 1;
138 
139 	if (solr_fetch_params_entry(objptr, &solr_params) == FAILURE) {
140 
141 		return FAILURE;
142 	}
143 
144 	if (!serialized || !size || !objptr)
145 	{
146 		return FAILURE;
147 	}
148 
149 	doc_ptr = solr_xml_create_xml_doc((xmlChar *) "solr_params", &xml_solr_params);
150 	xml_params = xmlNewChild(xml_solr_params, NULL, (xmlChar *) "params", NULL);
151 
152 	params = solr_params->params;
153 
154 	SOLR_HASHTABLE_FOR_LOOP(params)
155 	{
156 		solr_param_t *solr_param_ptr = NULL;
157 		solr_param_ptr = zend_hash_get_current_data_ptr(params);
158 
159 		switch(solr_param_ptr->type)
160 		{
161 			case SOLR_PARAM_TYPE_NORMAL :
162 			{
163 				solr_serialize_normal_param_value(xml_params, solr_param_ptr);
164 			}
165 			break;
166 
167 			case SOLR_PARAM_TYPE_SIMPLE_LIST :
168 			{
169 				solr_serialize_simple_list_param_value(xml_params, solr_param_ptr);
170 			}
171 			break;
172 
173 			case SOLR_PARAM_TYPE_ARG_LIST :
174 			{
175 				solr_serialize_arg_list_param_value(xml_params, solr_param_ptr);
176 			}
177 			break;
178 
179 			default :
180 			{
181 				php_error_docref(NULL, E_WARNING, "Invalid Solr Param Type %d", solr_param_ptr->type);
182 			}
183 		}
184 	}
185 
186 	xmlIndentTreeOutput = 1;
187 
188 	xmlDocDumpFormatMemoryEnc(doc_ptr, serialized, size, "UTF-8", format);
189 	xmlFreeDoc(doc_ptr);
190 
191 	return SUCCESS;
192 }
193 /* }}} */
194 
195 /* {{{ static void solr_unserialize_get_param_normal(xmlNode *normal_param, HashTable *params_ht) */
solr_unserialize_get_param_normal(xmlNode * normal_param,HashTable * params_ht)196 static void solr_unserialize_get_param_normal(xmlNode *normal_param, HashTable *params_ht)
197 {
198 	solr_char_t *param_name = NULL;
199 	size_t param_name_len   = 0U;
200 	solr_bool allow_multiple = 0;
201 	solr_param_type_t param_type = SOLR_PARAM_TYPE_NORMAL;
202 	xmlAttr *currAttr = normal_param->properties;
203 	solr_param_t *param = NULL;
204 	xmlNode *currNode = normal_param->children;
205 
206 	solr_param_value_equal_func_t equal_func = solr_normal_param_value_equal;
207 	solr_param_fetch_func_t fetch_func = (solr_param_fetch_func_t) solr_normal_param_value_fetch;
208 	solr_param_value_free_func_t free_func = solr_normal_param_value_free;
209 
210 	/* Grab the name and setting for this parameter */
211 	while(currAttr != NULL)
212 	{
213 		if (solr_xml_match_node(currAttr, "name"))
214 		{
215 			param_name = (solr_char_t *) solr_xml_get_node_contents(currAttr);
216 
217 			param_name_len = solr_strlen(param_name);
218 		}
219 
220 		if (solr_xml_match_node(currAttr, "allow_multiple"))
221 		{
222 			allow_multiple = solr_xml_get_node_contents_int(currAttr);
223 		}
224 
225 		currAttr = currAttr->next;
226 	}
227 
228 	param = solr_create_new_param(param_name, param_name_len, param_type, allow_multiple, equal_func, fetch_func, free_func, '&', 0);
229 
230 	/* Retrieve all the values for this parameter */
231 	while(currNode != NULL)
232 	{
233 		if (solr_xml_match_node(currNode, "param_value"))
234 		{
235 			xmlChar *pvalue = solr_xml_get_node_contents(currNode);
236 
237 			size_t pvalue_length = solr_strlen((char *)pvalue);
238 
239 			solr_param_value_t *parameter_value = (solr_param_value_t *) pemalloc(sizeof(solr_param_value_t), SOLR_PARAMS_PERSISTENT);
240 
241 			memset(parameter_value, 0, sizeof(solr_param_value_t));
242 
243 			solr_string_appends(&(parameter_value->contents.normal), (solr_char_t *) pvalue, pvalue_length);
244 
245 			solr_params_insert_param_value(param, parameter_value);
246 		}
247 
248 		currNode = currNode->next;
249 	}
250 
251 	/* Add this parameter to the hash table */
252 	if (zend_hash_str_add_ptr(params_ht, (char *) param_name, param_name_len, (void *) param) == NULL) {
253 
254 		/* Release all the memory allocated to this paramter */
255 		solr_destroy_param(&param);
256 
257 		php_error_docref(NULL, E_WARNING, "Error from %s %s", __func__, (char *) param_name);
258 
259 		return;
260 	}
261 }
262 /* }}} */
263 
264 /* {{{ static void solr_unserialize_get_param_simple_list(xmlNode *list_param, HashTable *params_ht) */
solr_unserialize_get_param_simple_list(xmlNode * list_param,HashTable * params_ht)265 static void solr_unserialize_get_param_simple_list(xmlNode *list_param, HashTable *params_ht)
266 {
267 	solr_char_t *param_name = NULL;
268 	size_t param_name_len = 0U;
269 	solr_bool allow_multiple = 0;
270 	solr_param_type_t param_type = SOLR_PARAM_TYPE_SIMPLE_LIST;
271 	solr_param_t *param = NULL;
272 	xmlNode *currNode = list_param->children;
273 	xmlAttr *currAttr = list_param->properties;
274 
275 	solr_param_value_equal_func_t equal_func = solr_simple_list_param_value_equal;
276 	solr_param_fetch_func_t fetch_func = (solr_param_fetch_func_t) solr_simple_list_param_value_fetch;
277 	solr_param_value_free_func_t free_func = solr_simple_list_param_value_free;
278 
279 	/* Grab the name and setting for this parameter */
280 	while(currAttr != NULL)
281 	{
282 		if (solr_xml_match_node(currAttr, "name"))
283 		{
284 			param_name = (solr_char_t *) solr_xml_get_node_contents(currAttr);
285 
286 			param_name_len = solr_strlen(param_name);
287 		}
288 
289 		if (solr_xml_match_node(currAttr, "allow_multiple"))
290 		{
291 			allow_multiple = solr_xml_get_node_contents_int(currAttr);
292 		}
293 
294 		currAttr = currAttr->next;
295 	}
296 
297 	param = solr_create_new_param(param_name, param_name_len, param_type, allow_multiple, equal_func, fetch_func, free_func, ',', 0);
298 
299 	/* Retrieve all the values for this parameter */
300 	while(currNode != NULL)
301 	{
302 		if (solr_xml_match_node(currNode, "param_value"))
303 		{
304 			solr_char_t *pvalue = (solr_char_t *) solr_xml_get_node_contents(currNode);
305 			size_t pvalue_length = solr_strlen(pvalue);
306 			solr_param_value_t *parameter_value = (solr_param_value_t *) pemalloc(sizeof(solr_param_value_t), SOLR_PARAMS_PERSISTENT);
307 
308 			memset(parameter_value, 0, sizeof(solr_param_value_t));
309 
310 			solr_string_appends(&(parameter_value->contents.simple_list), pvalue, pvalue_length);
311 
312 			solr_params_insert_param_value(param, parameter_value);
313 		}
314 
315 		currNode = currNode->next;
316 	}
317 
318 	/* Add this parameter to the hash table */
319 	if (zend_hash_str_add_ptr(params_ht, (char *) param_name, param_name_len, (void *) param) == NULL) {
320 
321 		/* Release all the memory allocated to this paramter */
322 		solr_destroy_param(&param);
323 
324 		php_error_docref(NULL, E_WARNING, "Error from %s %s", __func__, (char *) param_name);
325 
326 		return;
327 	}
328 }
329 /* }}} */
330 
331 /* {{{ static void solr_unserialize_get_param_arg_list(xmlNode *sort_param, HashTable *params_ht) */
solr_unserialize_get_param_arg_list(xmlNode * sort_param,HashTable * params_ht)332 static void solr_unserialize_get_param_arg_list(xmlNode *sort_param, HashTable *params_ht)
333 {
334 	solr_char_t *param_name = NULL;
335 	size_t param_name_len = 0U;
336 	solr_bool allow_multiple = 0;
337 	solr_char_t delimiter = 0;
338 	solr_char_t separator = 0;
339 	xmlAttr *currAttr = sort_param->properties;
340 	solr_param_type_t param_type = SOLR_PARAM_TYPE_ARG_LIST;
341 	solr_param_t *param = NULL;
342 	xmlNode *currNode = sort_param->children;
343 
344 	solr_param_value_equal_func_t equal_func = solr_arg_list_param_value_equal;
345 	solr_param_fetch_func_t fetch_func = (solr_param_fetch_func_t) solr_arg_list_param_value_fetch;
346 	solr_param_value_free_func_t free_func = solr_arg_list_param_value_free;
347 
348 	/* Grab the name and setting for this parameter */
349 	while(currAttr != NULL)
350 	{
351 		if (solr_xml_match_node(currAttr, "name"))
352 		{
353 			param_name = (solr_char_t *) solr_xml_get_node_contents(currAttr);
354 
355 			param_name_len = solr_strlen(param_name);
356 		}
357 
358 		if (solr_xml_match_node(currAttr, "allow_multiple"))
359 		{
360 			allow_multiple = solr_xml_get_node_contents_int(currAttr);
361 		}
362 
363 		if (solr_xml_match_node(currAttr, "delimiter"))
364 		{
365 			delimiter = solr_xml_get_node_contents_int(currAttr);
366 		}
367 
368 		if (solr_xml_match_node(currAttr, "arg_separator"))
369 		{
370 			separator = solr_xml_get_node_contents_int(currAttr);
371 		}
372 
373 		currAttr = currAttr->next;
374 	}
375 
376 	param = solr_create_new_param(param_name, param_name_len, param_type, allow_multiple, equal_func, fetch_func, free_func, delimiter, separator);
377 
378 	/* Retrieve all the values for this parameter */
379 	while(currNode != NULL)
380 	{
381 		if (solr_xml_match_node(currNode, "param_value"))
382 		{
383 			solr_char_t *pvalue = (solr_char_t *) solr_xml_get_node_contents(currNode);
384 
385 			xmlAttr *argument = currNode->properties; /* the argument is the only property */
386 
387 			solr_char_t *avalue = (solr_char_t *) solr_xml_get_node_contents(argument);
388 
389 			size_t pvalue_length = solr_strlen(pvalue);
390 			size_t avalue_length = solr_strlen(avalue);
391 
392 			solr_param_value_t *parameter_value = (solr_param_value_t *) pemalloc(sizeof(solr_param_value_t), SOLR_PARAMS_PERSISTENT);
393 
394 			memset(parameter_value, 0, sizeof(solr_param_value_t));
395 
396 			solr_string_appends(&(parameter_value->contents.arg_list.value), pvalue, pvalue_length);
397 
398 			solr_string_appends(&(parameter_value->contents.arg_list.arg), avalue, avalue_length);
399 
400 			solr_params_insert_param_value(param, parameter_value);
401 		}
402 
403 		currNode = currNode->next;
404 	}
405 
406 	/* Add this parameter to the hash table */
407 	if (zend_hash_str_add_ptr(params_ht, (char *) param_name, param_name_len, (void *) param) == NULL) {
408 
409 		/* Release all the memory allocated to this paramter */
410 		solr_destroy_param(&param);
411 
412 		php_error_docref(NULL, E_WARNING, "Error from %s %s", __func__, (char *) param_name);
413 
414 		return;
415 	}
416 }
417 /* }}} */
418 
419 /* {{{ static int solr_unserialize_solr_params_object(const char *serialized, int size, zval *objptr) */
solr_unserialize_solr_params_object(const char * serialized,int size,zval * objptr)420 static int solr_unserialize_solr_params_object(const char *serialized, int size, zval *objptr)
421 {
422 	solr_params_t *solr_params = NULL;
423 	long int params_index = SOLR_UNIQUE_PARAMS_INDEX();
424 	solr_params_t tmp_solr_params;
425 	uint32_t nSize = SOLR_INITIAL_HASH_TABLE_SIZE;
426 	HashTable *params_ht = NULL;
427 	xmlDoc *doc = NULL;
428 	xmlXPathContext *xpathctxt;
429 	const xmlChar *xpath_expression = (xmlChar *) "/solr_params/params/param/@type";
430 	xmlXPathObject *xpathObj;
431 	xmlNodeSet *result = NULL;
432 	register size_t num_nodes;
433 	register size_t i = 0U;
434 	int return_status = SUCCESS;
435 
436 #ifdef PHP_7
437 	solr_params = pemalloc(sizeof(solr_params_t), SOLR_PARAMS_PERSISTENT);
438 #endif
439 
440 	zend_update_property_long(Z_OBJCE_P(objptr), OBJ_FOR_PROP(objptr), SOLR_INDEX_PROPERTY_NAME, sizeof(SOLR_INDEX_PROPERTY_NAME) - 1, params_index);
441 
442 	memset(&tmp_solr_params, 0, sizeof(solr_params_t));
443 
444 	if ((solr_params = zend_hash_index_update_ptr(SOLR_GLOBAL(params), params_index, (void *) solr_params)) == NULL) {
445 
446 		php_error_docref(NULL, E_WARNING, "Error while registering SolrParam object in HashTable");
447 
448 		return FAILURE;
449 	}
450 
451 	solr_params->params_index = params_index;
452 
453 	/* Allocate memory for the parameters HashTable using fast cache for HashTables */
454 	ALLOC_HASHTABLE(solr_params->params);
455 
456 	zend_hash_init(solr_params->params, nSize, NULL, (dtor_func_t) solr_destory_param_ht_dtor, SOLR_PARAMS_PERSISTENT);
457 
458 	params_ht = solr_params->params;
459 
460 	doc = xmlReadMemory(serialized, size, NULL, "UTF-8", 0);
461 
462 	if (doc == NULL)
463 	{
464 		php_error_docref(NULL, E_WARNING, "Error while parsing serialized XML string");
465 
466 		return FAILURE;
467 	}
468 
469 	xpathctxt = xmlXPathNewContext(doc);
470 
471 	if (xpathctxt == NULL)
472 	{
473 		xmlFreeDoc(doc);
474 
475 		php_error_docref(NULL, E_WARNING, "Error while creating XML Xpath context");
476 
477 		return FAILURE;
478 	}
479 
480 	xpathObj = xmlXPathEval(xpath_expression, xpathctxt);
481 
482 	if (xpathObj == NULL)
483 	{
484 		xmlXPathFreeContext(xpathctxt);
485 
486 		xmlFreeDoc(doc);
487 
488 		php_error_docref(NULL, E_WARNING, "Error while evaluation XML Xpath expression");
489 
490 		return FAILURE;
491 	}
492 
493 	result = xpathObj->nodesetval;
494 
495 	if (result == NULL)
496 	{
497 		xmlXPathFreeObject(xpathObj);
498 
499 		xmlXPathFreeContext(xpathctxt);
500 
501 		xmlFreeDoc(doc);
502 
503 		php_error_docref(NULL, E_WARNING, "Error while extracting result from XML xpath object during unserialization");
504 
505 		return FAILURE;
506 	}
507 
508 	num_nodes = result->nodeNr; /* Number of parameter nodes matches in the xmlDocument */
509 
510 	/* Loop through all the parameter nodes and create an entry in the HashTable for each one */
511 	for (i = 0U; i < num_nodes; i++)
512 	{
513 		xmlNode *currNode = result->nodeTab[i];
514 
515 		/* Absolutely No assumptions. I have to make sure that this is an attribute node */
516 		if (currNode->type == XML_ATTRIBUTE_NODE)
517 		{
518 			/* Find out what type of parameter this is */
519 			const solr_param_type_t param_type = solr_xml_get_node_contents_int(currNode);
520 
521 			/* Get the /solr_params/params/param node */
522 			xmlNode *param_xml_node = currNode->parent;
523 
524 			/* Handle each parameter type separately */
525 			switch(param_type)
526 			{
527 				case SOLR_PARAM_TYPE_NORMAL :
528 				{
529 					solr_unserialize_get_param_normal(param_xml_node, params_ht);
530 				}
531 				break;
532 
533 				case SOLR_PARAM_TYPE_SIMPLE_LIST :
534 				{
535 					solr_unserialize_get_param_simple_list(param_xml_node, params_ht);
536 				}
537 				break;
538 
539 				case SOLR_PARAM_TYPE_ARG_LIST :
540 				{
541 					solr_unserialize_get_param_arg_list(param_xml_node, params_ht);
542 				}
543 				break;
544 
545 				default :
546 				{
547 					php_error_docref(NULL, E_WARNING, "Invalid parameter type");
548 
549 					return_status = FAILURE;
550 
551 					goto loop_complete;
552 				}
553 
554 			} /* End switch */
555 
556 		} /* End if (currNode->type == XML_ATTRIBUTE_NODE) */
557 
558 	} /* End for */
559 
560 loop_complete:
561 
562 	xmlXPathFreeObject(xpathObj);
563 
564 	xmlXPathFreeContext(xpathctxt);
565 
566 	xmlFreeDoc(doc);
567 
568 	return return_status;
569 }
570 /* }}} */
571 
572 /* {{{ SolrParams object constructor inner */
solr_params_obj_ctor(zval * obj)573 PHP_SOLR_API int solr_params_obj_ctor(zval *obj)
574 {
575     long int params_index = SOLR_UNIQUE_PARAMS_INDEX();
576     solr_params_t solr_params;
577 
578     if (solr_init_params(&solr_params, params_index) == FAILURE)
579     {
580         return FAILURE;
581     }
582     zend_update_property_long(Z_OBJCE_P(obj), OBJ_FOR_PROP(obj), SOLR_INDEX_PROPERTY_NAME, sizeof(SOLR_INDEX_PROPERTY_NAME) - 1, params_index);
583     return SUCCESS;
584 }
585 /* }}} */
586 
587 /* {{{ SolrParams object destructor inner */
solr_params_obj_dtor(zval * obj)588 PHP_SOLR_API void solr_params_obj_dtor(zval *obj)
589 {
590     solr_params_t *solr_params = NULL;
591 
592     /* Retrieve the document entry for this SolrDocument */
593     if (solr_fetch_params_entry(obj, &solr_params) == SUCCESS)  {
594         zend_hash_index_del(SOLR_GLOBAL(params), solr_params->params_index);
595         return ;
596     }
597 }
598 /* }}} */
599 
600 /* {{{ proto SolrParams::__clone(void)
601    Should never be called directly. Throws exceptions whenever there is an attempt to clone a SolrParams instance */
PHP_METHOD(SolrParams,__clone)602 PHP_METHOD(SolrParams, __clone)
603 {
604     long int params_index = SOLR_UNIQUE_PARAMS_INDEX();
605     solr_params_t solr_params;
606 
607     if (solr_init_params(&solr_params, params_index) == FAILURE) {
608         return;
609     }
610 
611     zend_update_property_long(solr_ce_SolrQuery, OBJ_FOR_PROP(getThis()), SOLR_INDEX_PROPERTY_NAME, sizeof(SOLR_INDEX_PROPERTY_NAME) - 1, params_index);
612 
613 	solr_throw_exception_ex(solr_ce_SolrIllegalOperationException, SOLR_ERROR_4001, SOLR_FILE_LINE_FUNC, "Cloning of SolrParams object instances is currently not supported");
614 }
615 /* }}} */
616 
617 /* {{{ proto SolrParams::setParam(string param_name, string param_value)
618    Sets the parameter to the specified value */
PHP_METHOD(SolrParams,setParam)619 PHP_METHOD(SolrParams, setParam)
620 {
621 	solr_char_t *param_name = NULL;
622 	COMPAT_ARG_SIZE_T param_name_length = 0;
623 
624 	solr_char_t *param_value = NULL;
625 	COMPAT_ARG_SIZE_T param_value_length = 0;
626 
627 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "ss", &param_name, &param_name_length, &param_value, &param_value_length) == FAILURE) {
628 
629 		php_error_docref(NULL, E_WARNING, "Invalid parameters");
630 
631 		RETURN_NULL();
632 	}
633 
634 	if (solr_set_normal_param(getThis(), param_name, param_name_length, param_value, param_value_length) == FAILURE)
635 	{
636 		RETURN_NULL();
637 	}
638 
639 	solr_return_solr_params_object();
640 }
641 /* }}} */
642 
643 /* {{{ proto SolrParams::addParam(string param_name, string param_value)
644    Adds another param_name to the object. */
PHP_METHOD(SolrParams,addParam)645 PHP_METHOD(SolrParams, addParam)
646 {
647 	solr_char_t *param_name = NULL;
648 	COMPAT_ARG_SIZE_T param_name_length = 0;
649 	solr_char_t *param_value = NULL;
650 	COMPAT_ARG_SIZE_T param_value_length = 0;
651 
652 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "ss", &param_name, &param_name_length, &param_value, &param_value_length) == FAILURE) {
653 
654 		php_error_docref(NULL, E_WARNING, "Invalid parameters");
655 
656 		RETURN_NULL();
657 	}
658 
659 	if (solr_add_normal_param(getThis(), param_name, param_name_length, param_value, param_value_length) == FAILURE)
660 	{
661 		RETURN_NULL();
662 	}
663 
664 	solr_return_solr_params_object();
665 }
666 /* }}} */
667 
668 /* {{{ proto SolrParams::getParam(string param_name)
669    Retrieves a parameter value */
PHP_METHOD(SolrParams,getParam)670 PHP_METHOD(SolrParams, getParam)
671 {
672 	solr_char_t *param_name = NULL;
673 	COMPAT_ARG_SIZE_T param_name_length = 0;
674 
675 	solr_param_t *solr_param = NULL;
676 
677 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "|s", &param_name, &param_name_length) == FAILURE) {
678 
679 		php_error_docref(NULL, E_WARNING, "Invalid parameters");
680 
681 		RETURN_FALSE;
682 	}
683 
684 	if (!param_name_length) {
685 
686 		php_error_docref(NULL, E_WARNING, "Invalid parameter name");
687 
688 		RETURN_NULL();
689 	}
690 
691 	if (solr_param_find(getThis(), param_name, param_name_length, (solr_param_t **) &solr_param) == FAILURE) {
692 
693 		RETURN_NULL();
694 	}
695 
696 	if (!solr_param) {
697 
698 		/* This should never happen unless there is a logic error in solr_param_find() */
699 		php_error_docref(NULL, E_ERROR, "Very severe internal error while fetching (solr_param_t **) from solr_param_find() %s", __func__);
700 
701 		return;
702 	}
703 
704 	switch(solr_param->type)
705 	{
706 		case SOLR_PARAM_TYPE_NORMAL :
707 		{
708 			if (solr_param->allow_multiple) {
709 
710 				array_init(return_value);
711 
712 				solr_normal_param_value_display(solr_param, return_value);
713 
714 				return;
715 
716 			} else {
717 
718 				solr_normal_param_value_display_string(solr_param, return_value);
719 
720 				return;
721 			}
722 		}
723 		break;
724 
725 		case SOLR_PARAM_TYPE_SIMPLE_LIST :
726 		{
727 			array_init(return_value);
728 
729 			solr_simple_list_param_value_display(solr_param, return_value);
730 
731 			return;
732 		}
733 		break;
734 
735 		case SOLR_PARAM_TYPE_ARG_LIST :
736 		{
737 			array_init(return_value);
738 
739 			solr_arg_list_param_value_display(solr_param, return_value);
740 
741 			return;
742 		}
743 		break;
744 
745 		default :
746 		{
747 			/* This should never happen. However, never say never! */
748 			php_error_docref(NULL, E_ERROR, "Invalid parameter type in switch case %s", __func__);
749 		}
750 
751 	} /* END switch(solr_param->type) */
752 
753 }
754 /* }}} */
755 
756 /* {{{ proto array SolrParams::getPreparedParams(void)
757    Returns an array of all the parameters (url-encoded) as they will be sent in the name-value pair POST request. */
PHP_METHOD(SolrParams,getPreparedParams)758 PHP_METHOD(SolrParams, getPreparedParams)
759 {
760 	solr_params_t *solr_params = NULL;
761 
762 	array_init(return_value);
763 
764 	/* Retrieve the document entry for this SolrDocument */
765 	if (solr_fetch_params_entry(getThis(), &solr_params) == SUCCESS) {
766 
767 		HashTable *params = solr_params->params;
768 
769 		SOLR_HASHTABLE_FOR_LOOP(params)
770 		{
771 			solr_param_t *solr_param = NULL;
772 			solr_string_t tmp_buffer;
773 
774 			solr_param = zend_hash_get_current_data_ptr(params);
775 
776 			memset(&tmp_buffer, 0, sizeof(solr_string_t));
777 
778 			solr_param->fetch_func(solr_param, &tmp_buffer);
779 
780 			add_assoc_stringl(return_value, solr_param->param_name, tmp_buffer.str, tmp_buffer.len);
781 			solr_string_free(&tmp_buffer);
782 		}
783 
784 		return;
785 	}
786 
787 	php_error_docref(NULL, E_WARNING, "SolrParams instance could not be retrieved from HashTable");
788 
789 	RETURN_NULL();
790 }
791 /* }}} */
792 
793 /* {{{ proto array SolrParams::getParams(void)
794    Returns an array of the parameters in the object. The values are not url-encoded. */
PHP_METHOD(SolrParams,getParams)795 PHP_METHOD(SolrParams, getParams)
796 {
797 	solr_params_t *solr_params = NULL;
798 
799 	array_init(return_value);
800 
801 	/* Retrieve the document entry for this SolrDocument */
802 	if (solr_fetch_params_entry(getThis(), &solr_params) == SUCCESS) {
803 
804 		HashTable *params = solr_params->params;
805 
806 		SOLR_HASHTABLE_FOR_LOOP(params)
807 		{
808 			solr_param_t *solr_param_ptr = NULL;
809 			solr_param_display_func_t display_func = NULL;
810 			zval *current_param = NULL;
811 
812 			solr_param_ptr = zend_hash_get_current_data_ptr(params);
813 
814 			switch(solr_param_ptr->type)
815 			{
816 				case SOLR_PARAM_TYPE_NORMAL :
817 				{
818 					display_func = solr_normal_param_value_display;
819 				}
820 				break;
821 
822 				case SOLR_PARAM_TYPE_SIMPLE_LIST :
823 				{
824 					display_func = solr_simple_list_param_value_display;
825 				}
826 				break;
827 
828 				case SOLR_PARAM_TYPE_ARG_LIST :
829 				{
830 					display_func = solr_arg_list_param_value_display;
831 				}
832 				break;
833 
834 				default :
835 				{
836 					php_error_docref(NULL, E_WARNING, "Invalid parameter type");
837 				}
838 			}
839 
840 			MAKE_STD_ZVAL(current_param);
841 			array_init(current_param);
842 			add_assoc_zval(return_value, solr_param_ptr->param_name, current_param);
843 
844 			display_func(solr_param_ptr, current_param);
845 #ifdef PHP_7
846 			efree(current_param);
847 #endif
848 		}
849 
850 		return;
851 	}
852 
853 	php_error_docref(NULL, E_WARNING, "SolrParams instance could not be retrieved from HashTable");
854 
855 	RETURN_NULL();
856 }
857 /* }}} */
858 
859 /* {{{ proto string SolrParams::__toString(void)
860    Returns a string representation of the object */
PHP_METHOD(SolrParams,__toString)861 PHP_METHOD(SolrParams, __toString)
862 {
863 	solr_params_t *solr_params = NULL;
864 
865 	/* Retrieve the params entry */
866 	if (solr_fetch_params_entry(getThis(), &solr_params) == SUCCESS) {
867 
868 	    solr_string_t params_str = solr_params_to_string(solr_params, 0);
869 
870 	    if (params_str.str && params_str.len)
871 	    {
872 	        RETVAL_STRINGL((char *) params_str.str, params_str.len);
873 	        solr_string_free(&(params_str));
874 	        return;
875 	    }
876 	}
877 
878 	RETVAL_STRINGL(SOLR_SPACE_STRING, sizeof(SOLR_SPACE_STRING)-1);
879 }
880 /* }}} */
881 
882 /* {{{ proto string SolrParams::toString([bool urlEncode=false])
883    Returns a string representation of the object */
PHP_METHOD(SolrParams,toString)884 PHP_METHOD(SolrParams, toString)
885 {
886 	solr_params_t *solr_params = NULL;
887 
888 	zend_bool url_encode = 0;
889 
890 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "|b", &url_encode) == FAILURE) {
891 		return;
892 	}
893 
894 	/* Retrieve the params entry */
895 	if (solr_fetch_params_entry(getThis(), &solr_params) == SUCCESS) {
896 
897 	    solr_string_t params_str = solr_params_to_string(solr_params, url_encode);
898 
899 	    if (params_str.str && params_str.len)
900 	    {
901 	        RETVAL_STRINGL((char *) params_str.str, params_str.len);
902 	        solr_string_free(&(params_str));
903 	        return;
904 	    }
905 	}
906 
907 	RETURN_NULL();
908 }
909 /* }}} */
910 
911 /* {{{ proto string SolrParams::serialize(void)
912    Returns a string representation of the object. Used for custom serialization. */
PHP_METHOD(SolrParams,serialize)913 PHP_METHOD(SolrParams, serialize)
914 {
915 	xmlChar *serialized = NULL;
916 	int size = 0;
917 
918 	if (solr_serialize_solr_params_object(&serialized, &size, getThis()) == FAILURE || !serialized || !size)
919 	{
920 		php_error_docref(NULL, E_WARNING, "Unable to serialize object");
921 
922 		RETURN_NULL();
923 	}
924 
925 	RETVAL_STRINGL((char *) serialized, size);
926 
927 	xmlFree(serialized);
928 }
929 /* }}} */
930 
931 /* {{{ proto void SolrParams::unserialize(string serialized)
932    Brings the serialized object back to life. */
PHP_METHOD(SolrParams,unserialize)933 PHP_METHOD(SolrParams, unserialize)
934 {
935 	char *serialized_object = NULL;
936 	COMPAT_ARG_SIZE_T serialized_object_len = 0;
937 
938 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &serialized_object, &serialized_object_len) == FAILURE) {
939 
940 		php_error_docref(NULL, E_WARNING, "Invalid parameters");
941 
942 		RETURN_NULL();
943 	}
944 
945 	if(serialized_object_len == 0)
946 	{
947 		php_error_docref(NULL, E_WARNING, "Invalid parameters");
948 
949 		RETURN_NULL();
950 	}
951 
952 	if (solr_unserialize_solr_params_object(serialized_object, serialized_object_len, getThis()) == FAILURE)
953 	{
954 		php_error_docref(NULL, E_WARNING, "Error during unserialization");
955 	}
956 }
957 /* }}} */
958 
959 /* {{{ proto void SolrModifiableParams::__construct(void)
960    Constructor. */
PHP_METHOD(SolrModifiableParams,__construct)961 PHP_METHOD(SolrModifiableParams, __construct)
962 {
963     solr_params_obj_ctor(getThis());
964 }
965 /* }}} */
966 
967 /* {{{ proto void SolrModifiableParams::__destruct(void)
968    Destructor. */
PHP_METHOD(SolrModifiableParams,__destruct)969 PHP_METHOD(SolrModifiableParams, __destruct)
970 {
971     solr_params_obj_dtor(getThis());
972 }
973 /* }}} */
974 
975 /*
976  * Local variables:
977  * tab-width: 4
978  * c-basic-offset: 4
979  * indent-tabs-mode: t
980  * End:
981  * vim600: fdm=marker
982  * vim: noet sw=4 ts=4
983  */
984