1 /**
2 *
3 * Hoel database abstraction library
4 *
5 * hoel.c: main functions
6 *
7 * Copyright 2015-2016 Nicolas Mora <mail@babelouest.org>
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public License
11 * as published by the Free Software Foundation;
12 * version 2.1 of the License.
13 *
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU GENERAL PUBLIC LICENSE for more details.
18 *
19 * You should have received a copy of the GNU General Public
20 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
21 *
22 */
23 #include <ctype.h>
24 #include <string.h>
25
26 #include "hoel.h"
27 #include "h-private.h"
28
29 /**
30 * free data allocated by hoel functions
31 */
h_free(void * data)32 void h_free(void * data) {
33 o_free(data);
34 }
35
36 /**
37 * Close a database connection
38 * return H_OK on success
39 */
h_close_db(struct _h_connection * conn)40 int h_close_db(struct _h_connection * conn) {
41 if (conn != NULL && conn->connection != NULL) {
42 if (0) {
43 /* Not happening */
44 #ifdef _HOEL_SQLITE
45 } else if (conn->type == HOEL_DB_TYPE_SQLITE) {
46 h_close_sqlite(conn);
47 return H_OK;
48 #endif
49 #ifdef _HOEL_MARIADB
50 } else if (conn->type == HOEL_DB_TYPE_MARIADB) {
51 h_close_mariadb(conn);
52 return H_OK;
53 #endif
54 #ifdef _HOEL_PGSQL
55 } else if (conn->type == HOEL_DB_TYPE_PGSQL) {
56 h_close_pgsql(conn);
57 return H_OK;
58 #endif
59 } else {
60 return H_ERROR_PARAMS;
61 }
62 } else {
63 return H_ERROR_PARAMS;
64 }
65 }
66
67 /**
68 * h_escape_string
69 * Escapes a string
70 * returned value must be free'd after use
71 */
h_escape_string(const struct _h_connection * conn,const char * unsafe)72 char * h_escape_string(const struct _h_connection * conn, const char * unsafe) {
73 if (conn != NULL && conn->connection != NULL && unsafe != NULL) {
74 if (0) {
75 /* Not happening */
76 #ifdef _HOEL_SQLITE
77 } else if (conn->type == HOEL_DB_TYPE_SQLITE) {
78 return h_escape_string_sqlite(conn, unsafe);
79 #endif
80 #ifdef _HOEL_MARIADB
81 } else if (conn->type == HOEL_DB_TYPE_MARIADB) {
82 return h_escape_string_mariadb(conn, unsafe);
83 #endif
84 #ifdef _HOEL_PGSQL
85 } else if (conn->type == HOEL_DB_TYPE_PGSQL) {
86 return h_escape_string_pgsql(conn, unsafe);
87 #endif
88 } else {
89 return NULL;
90 }
91 } else {
92 return NULL;
93 }
94 }
95
96 /**
97 * h_escape_string_with_quotes
98 * Escapes a string and returns it ready to be inserted in the query
99 * returned value must be h_h_free'd after use
100 */
h_escape_string_with_quotes(const struct _h_connection * conn,const char * unsafe)101 char * h_escape_string_with_quotes(const struct _h_connection * conn, const char * unsafe) {
102 if (conn != NULL && conn->connection != NULL && unsafe != NULL) {
103 if (0) {
104 /* Not happening */
105 #ifdef _HOEL_SQLITE
106 } else if (conn->type == HOEL_DB_TYPE_SQLITE) {
107 return h_escape_string_with_quotes_sqlite(conn, unsafe);
108 #endif
109 #ifdef _HOEL_MARIADB
110 } else if (conn->type == HOEL_DB_TYPE_MARIADB) {
111 return h_escape_string_with_quotes_mariadb(conn, unsafe);
112 #endif
113 #ifdef _HOEL_PGSQL
114 } else if (conn->type == HOEL_DB_TYPE_PGSQL) {
115 return h_escape_string_with_quotes_pgsql(conn, unsafe);
116 #endif
117 } else {
118 return NULL;
119 }
120 } else {
121 return NULL;
122 }
123 }
124
125 /**
126 * h_execute_query
127 * Execute a query, set the result structure with the returned values if available
128 * if result is NULL, the query is executed but no value will be returned
129 * options available
130 * H_OPTION_NONE (0): no option
131 * H_OPTION_SELECT: Execute a prepare statement (sqlite only)
132 * H_OPTION_EXEC: Execute an exec statement (sqlite only)
133 * return H_OK on success
134 */
h_execute_query(const struct _h_connection * conn,const char * query,struct _h_result * result,int options)135 int h_execute_query(const struct _h_connection * conn, const char * query, struct _h_result * result, int options) {
136 if (conn != NULL && conn->connection != NULL && query != NULL) {
137 if (0) {
138 /* Not happening */
139 #ifdef _HOEL_SQLITE
140 } else if (conn->type == HOEL_DB_TYPE_SQLITE) {
141 if (options & H_OPTION_EXEC) {
142 return h_exec_query_sqlite(conn, query);
143 } else {
144 return h_select_query_sqlite(conn, query, result);
145 }
146 #else
147 UNUSED(options);
148 #endif
149 #ifdef _HOEL_MARIADB
150 } else if (conn->type == HOEL_DB_TYPE_MARIADB) {
151 return h_execute_query_mariadb(conn, query, result);
152 #endif
153 #ifdef _HOEL_PGSQL
154 } else if (conn->type == HOEL_DB_TYPE_PGSQL) {
155 return h_execute_query_pgsql(conn, query, result);
156 #endif
157 } else {
158 return H_ERROR_PARAMS;
159 }
160 } else {
161 return H_ERROR_PARAMS;
162 }
163 }
164
165 /**
166 * h_execute_query_json
167 * Execute a query, set the returned values in the json result
168 * return H_OK on success
169 */
h_execute_query_json(const struct _h_connection * conn,const char * query,json_t ** j_result)170 int h_execute_query_json(const struct _h_connection * conn, const char * query, json_t ** j_result) {
171 if (conn != NULL && conn->connection != NULL && query != NULL && j_result != NULL) {
172 if (0) {
173 /* Not happening */
174 #ifdef _HOEL_SQLITE
175 } else if (conn->type == HOEL_DB_TYPE_SQLITE) {
176 return h_execute_query_json_sqlite(conn, query, j_result);
177 #endif
178 #ifdef _HOEL_MARIADB
179 } else if (conn->type == HOEL_DB_TYPE_MARIADB) {
180 return h_execute_query_json_mariadb(conn, query, j_result);
181 #endif
182 #ifdef _HOEL_PGSQL
183 } else if (conn->type == HOEL_DB_TYPE_PGSQL) {
184 return h_execute_query_json_pgsql(conn, query, j_result);
185 #endif
186 } else {
187 return H_ERROR_PARAMS;
188 }
189 } else {
190 return H_ERROR_PARAMS;
191 }
192 }
193
194 /**
195 * Add a new struct _h_data * to an array of struct _h_data *, which already has cols columns
196 * return H_OK on success
197 */
h_row_add_data(struct _h_data ** row,struct _h_data * data,int cols)198 int h_row_add_data(struct _h_data ** row, struct _h_data * data, int cols) {
199 struct _h_data * tmp = o_realloc(*row, (cols+1)*sizeof(struct _h_data));
200 * row = tmp;
201 if (tmp == NULL) {
202 y_log_message(Y_LOG_LEVEL_ERROR, "Hoel - Error allocating memory for h_row_add_data");
203 return H_ERROR_MEMORY;
204 } else {
205 switch (data->type) {
206 case HOEL_COL_TYPE_INT:
207 tmp[cols].type = HOEL_COL_TYPE_INT;
208 tmp[cols].t_data = o_malloc(sizeof(struct _h_type_int));
209 if (tmp[cols].t_data == NULL) {
210 y_log_message(Y_LOG_LEVEL_ERROR, "Hoel - Error allocating memory for tmp[cols].t_data");
211 return H_ERROR_MEMORY;
212 } else {
213 ((struct _h_type_int *)tmp[cols].t_data)->value = ((struct _h_type_int *)data->t_data)->value;
214 return H_OK;
215 }
216 break;
217 case HOEL_COL_TYPE_DOUBLE:
218 tmp[cols].type = HOEL_COL_TYPE_DOUBLE;
219 tmp[cols].t_data = o_malloc(sizeof(struct _h_type_double));
220 if (tmp[cols].t_data == NULL) {
221 y_log_message(Y_LOG_LEVEL_ERROR, "Hoel - Error allocating memory for tmp[cols].t_data");
222 return H_ERROR_MEMORY;
223 } else {
224 ((struct _h_type_double *)tmp[cols].t_data)->value = ((struct _h_type_double *)data->t_data)->value;
225 return H_OK;
226 }
227 break;
228 case HOEL_COL_TYPE_TEXT:
229 tmp[cols].type = HOEL_COL_TYPE_TEXT;
230 tmp[cols].t_data = o_malloc(sizeof(struct _h_type_text));
231 if (tmp[cols].t_data == NULL) {
232 y_log_message(Y_LOG_LEVEL_ERROR, "Hoel - Error allocating memory for tmp[cols].t_data");
233 return H_ERROR_MEMORY;
234 } else {
235 ((struct _h_type_text *)tmp[cols].t_data)->value = o_malloc(((struct _h_type_text *)data->t_data)->length+sizeof(char));
236 if (((struct _h_type_text *)tmp[cols].t_data)->value == NULL) {
237 y_log_message(Y_LOG_LEVEL_ERROR, "Hoel - Error allocating memory for ((struct _h_type_text *)tmp[cols].t_data)->value");
238 o_free(tmp[cols].t_data);
239 return H_ERROR_MEMORY;
240 }
241 memcpy(((struct _h_type_text *)tmp[cols].t_data)->value, ((struct _h_type_text *)data->t_data)->value, (((struct _h_type_text *)data->t_data)->length+1));
242 ((struct _h_type_text *)tmp[cols].t_data)->length = ((struct _h_type_text *)data->t_data)->length;
243 return H_OK;
244 }
245 break;
246 case HOEL_COL_TYPE_BLOB:
247 tmp[cols].type = HOEL_COL_TYPE_BLOB;
248 tmp[cols].t_data = o_malloc(sizeof(struct _h_type_blob));
249 if (tmp[cols].t_data == NULL) {
250 y_log_message(Y_LOG_LEVEL_ERROR, "Hoel - Error allocating memory for tmp[cols].t_data");
251 return H_ERROR_MEMORY;
252 } else {
253 ((struct _h_type_blob *)tmp[cols].t_data)->length = ((struct _h_type_blob *)data->t_data)->length;
254 ((struct _h_type_blob *)tmp[cols].t_data)->value = o_malloc(((struct _h_type_blob *)data->t_data)->length);
255 if (((struct _h_type_blob *)tmp[cols].t_data)->value == NULL) {
256 y_log_message(Y_LOG_LEVEL_ERROR, "Hoel - Error allocating memory for ((struct _h_type_blob *)tmp[cols].t_data)->value");
257 o_free(tmp[cols].t_data);
258 return H_ERROR_MEMORY;
259 }
260 memcpy(((struct _h_type_blob *)tmp[cols].t_data)->value, ((struct _h_type_blob *)data->t_data)->value, ((struct _h_type_blob *)data->t_data)->length);
261 return H_OK;
262 }
263 break;
264 case HOEL_COL_TYPE_DATE:
265 tmp[cols].type = HOEL_COL_TYPE_DATE;
266 tmp[cols].t_data = o_malloc(sizeof(struct _h_type_datetime));
267 if (tmp[cols].t_data == NULL) {
268 y_log_message(Y_LOG_LEVEL_ERROR, "Hoel - Error allocating memory for tmp[cols].t_data");
269 return H_ERROR_MEMORY;
270 } else {
271 ((struct _h_type_datetime *)tmp[cols].t_data)->value = ((struct _h_type_datetime *)data->t_data)->value;
272 return H_OK;
273 }
274 break;
275 case HOEL_COL_TYPE_NULL:
276 tmp[cols].type = HOEL_COL_TYPE_NULL;
277 tmp[cols].t_data = NULL;
278 break;
279 default:
280 return H_ERROR_PARAMS;
281 break;
282 }
283 return H_OK;
284 }
285 }
286
287 /**
288 * Add a new row of struct _h_data * in a struct _h_result *
289 * return H_OK on success
290 */
h_result_add_row(struct _h_result * result,struct _h_data * row,int rows)291 int h_result_add_row(struct _h_result * result, struct _h_data * row, int rows) {
292 result->data = o_realloc(result->data, (rows+1)*sizeof(struct _h_data *));
293 if (result->data == NULL) {
294 y_log_message(Y_LOG_LEVEL_ERROR, "Hoel - Error allocating memory for result->data");
295 return H_ERROR_MEMORY;
296 } else {
297 result->data[rows] = row;
298 result->nb_rows++;
299 return H_OK;
300 }
301 }
302
303 /**
304 * h_query_insert
305 * Execute an insert query
306 * return H_OK on success
307 */
h_query_insert(const struct _h_connection * conn,const char * query)308 int h_query_insert(const struct _h_connection * conn, const char * query) {
309 if (conn != NULL && conn->connection != NULL && query != NULL && o_strcasestr(query, "insert") != NULL) {
310 return h_execute_query(conn, query, NULL, H_OPTION_EXEC);
311 } else {
312 return H_ERROR_PARAMS;
313 }
314 }
315
316 /**
317 * h_query_last_insert_id
318 * return the id of the last inserted value
319 * return H_OK on success
320 */
h_query_last_insert_id(const struct _h_connection * conn)321 struct _h_data * h_query_last_insert_id(const struct _h_connection * conn) {
322 struct _h_data * data = NULL;
323 if (conn != NULL && conn->connection != NULL) {
324 if (0) {
325 /* Not happening */
326 #ifdef _HOEL_SQLITE
327 } else if (conn->type == HOEL_DB_TYPE_SQLITE) {
328 int last_id = h_last_insert_id_sqlite(conn);
329 if (last_id > 0) {
330 data = h_new_data_int(last_id);
331 } else {
332 data = h_new_data_null();
333 }
334 #endif
335 #ifdef _HOEL_MARIADB
336 } else if (conn->type == HOEL_DB_TYPE_MARIADB) {
337 int last_id = h_last_insert_id_mariadb(conn);
338 if (last_id > 0) {
339 data = h_new_data_int(last_id);
340 } else {
341 data = h_new_data_null();
342 }
343 #endif
344 #ifdef _HOEL_PGSQL
345 } else if (conn->type == HOEL_DB_TYPE_PGSQL) {
346 int last_id = h_last_insert_id_pgsql(conn);
347 if (last_id > 0) {
348 data = h_new_data_int(last_id);
349 } else {
350 data = h_new_data_null();
351 }
352 #endif
353 } else {
354 data = h_new_data_null();
355 }
356 }
357 return data;
358 }
359
360 /**
361 * h_query_update
362 * Execute an update query
363 * return H_OK on success
364 */
h_query_update(const struct _h_connection * conn,const char * query)365 int h_query_update(const struct _h_connection * conn, const char * query) {
366 if (conn != NULL && conn->connection != NULL && query != NULL && o_strcasestr(query, "update") != NULL) {
367 return h_execute_query(conn, query, NULL, H_OPTION_EXEC);
368 } else {
369 return H_ERROR_PARAMS;
370 }
371 }
372
373 /**
374 * h_query_delete
375 * Execute an delete query
376 * return H_OK on success
377 */
h_query_delete(const struct _h_connection * conn,const char * query)378 int h_query_delete(const struct _h_connection * conn, const char * query) {
379 if (conn != NULL && conn->connection != NULL && query != NULL && o_strcasestr(query, "delete") != NULL) {
380 return h_execute_query(conn, query, NULL, H_OPTION_EXEC);
381 } else {
382 return H_ERROR_PARAMS;
383 }
384 }
385
386 /**
387 * h_query_select
388 * Execute a select query, set the result structure with the returned values
389 * return H_OK on success
390 */
h_query_select(const struct _h_connection * conn,const char * query,struct _h_result * result)391 int h_query_select(const struct _h_connection * conn, const char * query, struct _h_result * result) {
392 if (conn != NULL && conn->connection != NULL && query != NULL && o_strcasestr(query, "select") != NULL) {
393 return h_execute_query(conn, query, result, H_OPTION_SELECT);
394 } else {
395 return H_ERROR_PARAMS;
396 }
397 }
398
399 /**
400 * h_query_select_json
401 * Execute a select query, set the returned values in the json results
402 * return H_OK on success
403 */
h_query_select_json(const struct _h_connection * conn,const char * query,json_t ** j_result)404 int h_query_select_json(const struct _h_connection * conn, const char * query, json_t ** j_result) {
405 if (conn != NULL && conn->connection != NULL && query != NULL && o_strcasestr(query, "select") != NULL) {
406 return h_execute_query_json(conn, query, j_result);
407 } else {
408 return H_ERROR_PARAMS;
409 }
410 }
411
412 /**
413 * h_clean_result
414 * Free all the memory allocated by the struct _h_result
415 */
h_clean_result(struct _h_result * result)416 int h_clean_result(struct _h_result * result) {
417 unsigned int col, row;
418 if (result != NULL) {
419 for (row=0; row<result->nb_rows; row++) {
420 for (col=0; col<result->nb_columns; col++) {
421 if (h_clean_data(&result->data[row][col]) != H_OK) {
422 return H_ERROR_MEMORY;
423 }
424 }
425 o_free(result->data[row]);
426 }
427 o_free(result->data);
428 return H_OK;
429 } else {
430 return H_ERROR_PARAMS;
431 }
432 }
433
434 /**
435 * h_clean_data
436 * Free memory allocated by the struct _h_data
437 * return H_OK on success
438 */
h_clean_data(struct _h_data * data)439 int h_clean_data(struct _h_data * data) {
440 if (data != NULL) {
441 if (data->type == HOEL_COL_TYPE_TEXT) {
442 o_free(((struct _h_type_text *)data->t_data)->value);
443 } else if (data->type == HOEL_COL_TYPE_BLOB) {
444 o_free(((struct _h_type_blob *)data->t_data)->value);
445 }
446 if (data->t_data != NULL) {
447 o_free(data->t_data);
448 }
449 return H_OK;
450 } else {
451 return H_ERROR_PARAMS;
452 }
453 }
454
455 /**
456 * h_clean_data_full
457 * Free memory allocated by the struct _h_data and the struct _h_data pointer
458 * return H_OK on success
459 */
h_clean_data_full(struct _h_data * data)460 int h_clean_data_full(struct _h_data * data) {
461 if (data != NULL) {
462 h_clean_data(data);
463 o_free(data);
464 return H_OK;
465 } else {
466 return H_ERROR_PARAMS;
467 }
468 }
469
470 /**
471 * Allocate memory for a new struct _h_data * containing an int
472 * return pointer to the new structure
473 * return NULL on error
474 */
h_new_data_int(const long long int value)475 struct _h_data * h_new_data_int(const long long int value) {
476 struct _h_data * data = o_malloc(sizeof(struct _h_data));
477 if (data != NULL) {
478 data->t_data = o_malloc(sizeof(struct _h_type_int));
479 if (data->t_data == NULL) {
480 y_log_message(Y_LOG_LEVEL_ERROR, "Hoel - Error allocating memory for data->t_data");
481 o_free(data);
482 return NULL;
483 }
484 data->type = HOEL_COL_TYPE_INT;
485 ((struct _h_type_int *)data->t_data)->value = value;
486 } else {
487 y_log_message(Y_LOG_LEVEL_ERROR, "Hoel - Error allocating memory for data");
488 }
489 return data;
490 }
491
492 /**
493 * Allocate memory for a new struct _h_data * containing a double
494 * return pointer to the new structure
495 * return NULL on error
496 */
h_new_data_double(const double value)497 struct _h_data * h_new_data_double(const double value) {
498 struct _h_data * data = o_malloc(sizeof(struct _h_data));
499 if (data != NULL) {
500 data->t_data = o_malloc(sizeof(struct _h_type_double));
501 if (data->t_data == NULL) {
502 y_log_message(Y_LOG_LEVEL_ERROR, "Hoel - Error allocating memory for data->t_data");
503 o_free(data);
504 return NULL;
505 }
506 data->type = HOEL_COL_TYPE_DOUBLE;
507 ((struct _h_type_double *)data->t_data)->value = value;
508 } else {
509 y_log_message(Y_LOG_LEVEL_ERROR, "Hoel - Error allocating memory for data");
510 }
511 return data;
512 }
513
514 /**
515 * Allocate memory for a new struct _h_data * containing a text
516 * return pointer to the new structure
517 * return NULL on error
518 */
h_new_data_text(const char * value,const size_t length)519 struct _h_data * h_new_data_text(const char * value, const size_t length) {
520 struct _h_data * data = o_malloc(sizeof(struct _h_data));
521 if (data != NULL) {
522 data->t_data = o_malloc(sizeof(struct _h_type_text));
523 if (data->t_data == NULL) {
524 y_log_message(Y_LOG_LEVEL_ERROR, "Hoel - Error allocating memory for data->t_data");
525 o_free(data);
526 return NULL;
527 }
528 data->type = HOEL_COL_TYPE_TEXT;
529 ((struct _h_type_text *)data->t_data)->value = o_malloc(length+sizeof(char));
530 if (((struct _h_type_text *)data->t_data)->value == NULL) {
531 y_log_message(Y_LOG_LEVEL_ERROR, "Hoel - Error allocating memory for data->t_data->value");
532 o_free(data);
533 return NULL;
534 } else {
535 memcpy(((struct _h_type_text *)data->t_data)->value, value, length);
536 ((struct _h_type_text *)data->t_data)->length = length;
537 ((struct _h_type_text *)data->t_data)->value[length] = '\0';
538 }
539 } else {
540 y_log_message(Y_LOG_LEVEL_ERROR, "Hoel - Error allocating memory for data");
541 }
542 return data;
543 }
544
545 /**
546 * Allocate memory for a new struct _h_data * containing a blob
547 * return pointer to the new structure
548 * return NULL on error
549 */
h_new_data_blob(const void * value,const size_t length)550 struct _h_data * h_new_data_blob(const void * value, const size_t length) {
551 struct _h_data * data = o_malloc(sizeof(struct _h_data));
552 if (data != NULL) {
553 data->t_data = o_malloc(sizeof(struct _h_type_blob));
554 if (data->t_data == NULL) {
555 y_log_message(Y_LOG_LEVEL_ERROR, "Hoel - Error allocating memory for data");
556 o_free(data);
557 return NULL;
558 }
559 data->type = HOEL_COL_TYPE_BLOB;
560 ((struct _h_type_blob *)data->t_data)->length = length;
561 ((struct _h_type_blob *)data->t_data)->value = o_malloc(length);
562 if (((struct _h_type_blob *)data->t_data)->value == NULL) {
563 y_log_message(Y_LOG_LEVEL_ERROR, "Hoel - Error allocating memory for t_data->value");
564 o_free(data);
565 return NULL;
566 } else {
567 memcpy(((struct _h_type_blob *)data->t_data)->value, value, length);
568 }
569 } else {
570 y_log_message(Y_LOG_LEVEL_ERROR, "Hoel - Error allocating memory for data");
571 }
572 return data;
573 }
574
575 /**
576 * Allocate memory for a new struct _h_data * containing a null value
577 * return pointer to the new structure
578 * return NULL on error
579 */
h_new_data_null()580 struct _h_data * h_new_data_null() {
581 struct _h_data * data = o_malloc(sizeof(struct _h_data));
582 if (data != NULL) {
583 data->type = HOEL_COL_TYPE_NULL;
584 data->t_data = NULL;
585 } else {
586 y_log_message(Y_LOG_LEVEL_ERROR, "Hoel - Error allocating memory for data");
587 }
588 return data;
589 }
590
591 /**
592 * Allocate memory for a new struct _h_data * containing a date time structure
593 * return pointer to the new structure
594 * return NULL on error
595 */
h_new_data_datetime(const struct tm * datetime)596 struct _h_data * h_new_data_datetime(const struct tm * datetime) {
597 struct _h_data * data = NULL;
598 if (datetime != NULL) {
599 data = o_malloc(sizeof(struct _h_data));
600 if (data != NULL) {
601 data->type = HOEL_COL_TYPE_DATE;
602 data->t_data = o_malloc(sizeof(struct _h_type_datetime));
603
604 if (data->t_data == NULL) {
605 y_log_message(Y_LOG_LEVEL_ERROR, "Hoel - Error allocating memory for data->t_data");
606 o_free(data);
607 return NULL;
608 }
609 ((struct _h_type_datetime *)data->t_data)->value = * datetime;
610 } else {
611 y_log_message(Y_LOG_LEVEL_ERROR, "Hoel - Error allocating memory for data");
612 }
613 }
614 return data;
615 }
616
617 /**
618 * h_clean_connection
619 * free memory allocated by the struct _h_connection
620 * return H_OK on success
621 */
h_clean_connection(struct _h_connection * conn)622 int h_clean_connection(struct _h_connection * conn) {
623 if (conn != NULL) {
624 o_free(conn->connection);
625 o_free(conn);
626 return H_OK;
627 } else {
628 return H_ERROR_PARAMS;
629 }
630 }
631