Coverage Report

Created: 2026-09-14 06:45

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/opensips/db/pi_framework.c
Line
Count
Source
1
/* Core PI framework parser.  XML parsing is deliberately transport-independent. */
2
#include "../str.h"
3
#include "../ut.h"
4
#include "../db/db_ut.h"
5
#include "../mem/mem.h"
6
#include "../mem/shm_mem.h"
7
#include "../config.h"
8
#include "../globals.h"
9
#include "../socket_info.h"
10
#include "../resolve.h"
11
#include "../parser/parse_uri.h"
12
#include "../sr_module.h"
13
#include "pi_xml.h"
14
#include "pi_framework.h"
15
16
#include "pi_framework_db.h"
17
18
0
#define PI_XML_FRAMEWORK_NODE "framework"
19
0
#define PI_XML_DB_URL_NODE "db_url"
20
0
#define PI_XML_DB_TABLE_NODE "db_table"
21
0
#define PI_XML_TABLE_NAME_NODE "table_name"
22
0
#define PI_XML_DB_URL_ID_NODE "db_url_id"
23
0
#define PI_XML_MOD_NODE "mod"
24
0
#define PI_XML_MOD_NAME_NODE "mod_name"
25
0
#define PI_XML_CMD_NODE "cmd"
26
0
#define PI_XML_DB_TABLE_ID_NODE "db_table_id"
27
0
#define PI_XML_CMD_NAME_NODE "cmd_name"
28
0
#define PI_XML_CMD_TYPE_NODE "cmd_type"
29
0
#define PI_XML_CLAUSE_COLS_NODE "clause_cols"
30
0
#define PI_XML_QUERY_COLS_NODE "query_cols"
31
0
#define PI_XML_ORDER_BY_COLS_NODE "order_by_cols"
32
0
#define PI_XML_COLUMN_NODE "column"
33
0
#define PI_XML_COL_NODE "col"
34
0
#define PI_XML_FIELD_NODE "field"
35
0
#define PI_XML_LINK_CMD_NODE "link_cmd"
36
0
#define PI_XML_TYPE_NODE "type"
37
0
#define PI_XML_OPERATOR_NODE "operator"
38
0
#define PI_XML_VALUE_NODE "value"
39
0
#define PI_XML_VALIDATE_NODE "validate"
40
0
#define PI_XML_ID_ATTR "id"
41
42
pi_framework_t *pi_framework_data = NULL;
43
44
45
xmlAttrPtr pi_xml_node_get_attr_by_name(xmlNodePtr node, const char *name)
46
0
{
47
0
  xmlAttrPtr attr = node->properties;
48
0
  while (attr) {
49
0
    if(pi_xml_strcasecmp(attr->name, (const xmlChar*)name)==0)
50
0
      return attr;
51
0
    attr = attr->next;
52
0
  }
53
0
  return NULL;
54
0
}
55
56
char *pi_xml_node_get_attr_content_by_name(xmlNodePtr node, const char *name)
57
0
{
58
0
  xmlAttrPtr attr = pi_xml_node_get_attr_by_name(node, name);
59
0
  if (attr) return (char*)pi_xml_node_get_content(attr->children);
60
0
  else return NULL;
61
0
}
62
63
xmlNodePtr pi_xml_node_get_node_by_name(xmlNodePtr node, const char *name)
64
0
{
65
0
  xmlNodePtr cur = node;
66
0
  while (cur) {
67
0
    if(pi_xml_strcasecmp(cur->name, (const xmlChar*)name)==0)
68
0
      return cur;
69
0
    cur = cur->next;
70
0
  }
71
0
  return NULL;
72
0
}
73
74
char *pi_xml_node_get_node_content_by_name(xmlNodePtr node, const char *name)
75
0
{
76
0
  xmlNodePtr node1 = pi_xml_node_get_node_by_name(node, name);
77
0
  if (node1) return (char*)pi_xml_node_get_content(node1);
78
0
  else return NULL;
79
0
}
80
81
82
int pi_getDbUrlNodes(pi_framework_t *_pi_framework_data, xmlNodePtr framework_node)
83
0
{
84
0
  int i;
85
0
  xmlNodePtr node;
86
0
  pi_db_url_t *db_urls;
87
0
  pi_db_url_t *pi_db_urls = NULL;
88
0
  str id, db_url;
89
90
  //_pi_framework_data->pi_db_urls_size=0;
91
0
  for(node=framework_node->children;node;node=node->next){
92
0
    if (pi_xml_strcasecmp(node->name,
93
0
      (const xmlChar*)PI_XML_DB_URL_NODE) == 0) {
94
0
      if(_pi_framework_data->pi_db_urls_size)
95
0
        db_urls = (pi_db_url_t*)
96
0
          shm_realloc(_pi_framework_data->pi_db_urls,
97
0
          (_pi_framework_data->pi_db_urls_size+1)*
98
0
          sizeof(pi_db_url_t));
99
0
      else
100
0
        db_urls = (pi_db_url_t*)
101
0
            shm_malloc(sizeof(pi_db_url_t));
102
0
      if(db_urls==NULL) {LM_ERR("oom\n");return -1;}
103
0
      _pi_framework_data->pi_db_urls = db_urls;
104
105
0
      pi_db_urls = _pi_framework_data->pi_db_urls;
106
0
      db_urls = &pi_db_urls[_pi_framework_data->pi_db_urls_size];
107
0
      memset(db_urls, 0, sizeof(pi_db_url_t));
108
109
0
      id.s = pi_xml_node_get_attr_content_by_name(node,
110
0
            PI_XML_ID_ATTR);
111
0
      if(id.s==NULL){
112
0
        LM_ERR("No attribute for node %d [%s]\n",
113
0
          _pi_framework_data->pi_db_urls_size,
114
0
          node->name);
115
0
        return -1;
116
0
      }
117
0
      id.len = strlen(id.s);
118
0
      if(id.len==0){
119
0
        LM_ERR("Empty attr for node %d [%s]\n",
120
0
          _pi_framework_data->pi_db_urls_size,
121
0
          node->name);
122
0
        return -1;
123
0
      }
124
0
      if(shm_str_dup(&db_urls->id, &id)!=0) return -1;
125
0
      pi_xml_free(id.s);id.s=NULL;id.len=0;
126
127
0
      db_url.s = (char*)pi_xml_node_get_content(node);
128
0
      if(db_url.s==NULL){
129
0
        LM_ERR("No content for node [%.*s][%s]\n",
130
0
          db_urls->id.len, db_urls->id.s, node->name);
131
0
        return -1;
132
0
      }
133
0
      db_url.len = strlen(db_url.s);
134
0
      if(db_url.len==0){
135
0
        LM_ERR("Empty content for node [%.*s][%s]\n",
136
0
          db_urls->id.len, db_urls->id.s, node->name);
137
0
        return -1;
138
0
      }
139
0
      if(shm_str_dup(&db_urls->db_url, &db_url)!=0) return -1;
140
0
      pi_xml_free(db_url.s);db_url.s=NULL;db_url.len=0;
141
142
0
      for(i=0;i<_pi_framework_data->pi_db_urls_size;i++){
143
0
        if(db_urls->id.len==pi_db_urls[i].id.len &&
144
0
                                        strncmp(pi_db_urls[i].id.s,
145
0
                                                db_urls->id.s,
146
0
            db_urls->id.len)==0){
147
0
          LM_ERR("duplicated %s %s [%.*s]\n",
148
0
            PI_XML_DB_URL_NODE,
149
0
            PI_XML_ID_ATTR,
150
0
            db_urls->id.len,
151
0
            db_urls->id.s);
152
0
          return -1;
153
0
        }
154
0
        if(db_urls->db_url.len==pi_db_urls[i].db_url.len &&
155
0
                                        strncmp(pi_db_urls[i].db_url.s,
156
0
                                                db_urls->db_url.s,
157
0
            db_urls->db_url.len)==0){
158
0
          LM_ERR("duplicated %s [%.*s]\n",
159
0
            PI_XML_DB_URL_NODE,
160
0
            db_urls->db_url.len,
161
0
            db_urls->db_url.s);
162
0
          return -1;
163
0
        }
164
0
      }
165
      /* */
166
0
      LM_DBG("got node [%s]->[%.*s][%.*s]\n",
167
0
        node->name,
168
0
        db_urls->id.len, db_urls->id.s,
169
0
        db_urls->db_url.len, db_urls->db_url.s);
170
      /* */
171
0
      _pi_framework_data->pi_db_urls_size++;
172
0
    }
173
0
  }
174
0
  if(_pi_framework_data->pi_db_urls_size==0){
175
0
    LM_DBG("No [%s] nodes in config file; connectors will be resolved "
176
0
        "from modules\n", PI_XML_DB_URL_NODE);
177
0
    return 0;
178
0
  }
179
  /* */
180
0
  for(i=0;i<_pi_framework_data->pi_db_urls_size;i++){
181
0
    LM_DBG("got node %s [%d][%.*s][%.*s]\n", PI_XML_DB_URL_NODE,
182
0
      i, pi_db_urls[i].id.len, pi_db_urls[i].id.s,
183
0
      pi_db_urls[i].db_url.len, pi_db_urls[i].db_url.s);
184
0
  }
185
  /* */
186
0
  return 0;
187
0
}
188
189
int pi_getDbTableCols(pi_db_url_t *pi_db_urls, pi_db_table_t *db_tables,
190
      const xmlNodePtr table_node)
191
0
{
192
0
  int i;
193
0
  char *val;
194
0
  int val_len;
195
0
  xmlNodePtr node;
196
0
  pi_table_col_t *cols;
197
0
  str field;
198
199
0
  for(node=table_node->children,db_tables->cols_size=0;node;node=node->next){
200
0
    if (pi_xml_strcasecmp(node->name,
201
0
      (const xmlChar*)PI_XML_COLUMN_NODE) == 0) {
202
0
      if(db_tables->cols_size)
203
0
        cols = (pi_table_col_t*)shm_realloc(db_tables->cols,
204
0
            (db_tables->cols_size+1)*
205
0
            sizeof(pi_table_col_t));
206
0
      else
207
0
        cols = (pi_table_col_t*)
208
0
          shm_malloc(sizeof(pi_table_col_t));
209
0
      if(cols==NULL) {LM_ERR("oom\n");return -1;}
210
0
      db_tables->cols = cols;
211
0
      cols = &db_tables->cols[db_tables->cols_size];
212
0
      memset(cols, 0, sizeof(pi_table_col_t));
213
0
      cols->type=(db_type_t)-1;
214
      /* Populate the field */
215
0
      field.s =
216
0
        pi_xml_node_get_node_content_by_name(node->children,
217
0
              PI_XML_FIELD_NODE);
218
0
      if(field.s==NULL){
219
0
        LM_ERR("missing node %s [%.*s] %s %s\n",
220
0
          table_node->name,
221
0
          db_tables->name.len, db_tables->name.s,
222
0
          node->name, PI_XML_FIELD_NODE);
223
0
        return -1;
224
0
      }
225
0
      field.len = strlen(field.s);
226
0
      if(field.len==0){
227
0
        LM_ERR("empty node %s [%.*s] %s %s \n",
228
0
          table_node->name,
229
0
          db_tables->name.len, db_tables->name.s,
230
0
          node->name, PI_XML_FIELD_NODE);
231
0
        return -1;
232
0
      }
233
0
      if(shm_str_dup(&cols->field, &field)!=0) return -1;
234
0
      pi_xml_free(field.s);field.s=NULL;field.len=0;
235
      /* Each field MUST be unique */
236
0
      for(i=0;i<db_tables->cols_size;i++){
237
0
        if(cols->field.len==db_tables->cols[i].field.len &&
238
0
          strncmp(db_tables->cols[i].field.s,
239
0
            cols->field.s,
240
0
            cols->field.len)==0){
241
0
          LM_ERR("duplicated %s %s [%.*s] in %s [%.*s]\n",
242
0
            node->name, PI_XML_FIELD_NODE,
243
0
            cols->field.len, cols->field.s,
244
0
            table_node->name,
245
0
            db_tables->name.len, db_tables->name.s);
246
0
          return -1;
247
0
        }
248
0
      }
249
      /* Populate the validation */
250
0
      val = pi_xml_node_get_node_content_by_name(node->children,
251
0
            PI_XML_VALIDATE_NODE);
252
0
      if(val){
253
0
        val_len = strlen(val);
254
0
        switch(val_len){
255
0
        case 0:
256
0
          break;
257
0
        case 3:
258
0
          if(strncmp("URI",val,3)==0)
259
0
            cols->validation|=PI_FLAG_URI;
260
0
          break;
261
0
        case 11:
262
0
          if(strncmp("P_HOST_PORT",val,11)==0)
263
0
            cols->validation|=PI_FLAG_P_HOST_PORT;
264
0
          else
265
0
          if(strncmp("P_IPV4_PORT",val,11)==0)
266
0
            cols->validation|=PI_FLAG_P_IPV4_PORT;
267
0
          break;
268
0
        case 12:
269
0
          if(strncmp("URI_IPV4HOST",val,12)==0)
270
0
            cols->validation|=PI_FLAG_URI_IPV4HOST;
271
0
          break;
272
0
        default:
273
0
          LM_ERR("unexpected validation flag [%s] for "
274
0
            "%s %s %s\n",
275
0
            val, table_node->name, node->name,
276
0
            PI_XML_VALIDATE_NODE);
277
0
          pi_xml_free(val);
278
0
          return -1;
279
0
        }
280
0
        pi_xml_free(val);
281
0
      }
282
      /* Populate the type */
283
0
      val = pi_xml_node_get_node_content_by_name(node->children,
284
0
              PI_XML_TYPE_NODE);
285
0
      if(val==NULL){
286
0
        LM_ERR("missing node %s %s %s\n",
287
0
          table_node->name, node->name,
288
0
          PI_XML_TYPE_NODE);
289
0
        return -1;
290
0
      }
291
0
      val_len = strlen(val);
292
0
      if(val_len==0){
293
0
        LM_ERR("empty node %s %s %s\n",
294
0
          table_node->name, node->name,
295
0
          PI_XML_TYPE_NODE);
296
0
        pi_xml_free(val);
297
0
        return -1;
298
0
      }else if(val_len==6){
299
0
        if(strncmp("DB_INT",val,6)==0)
300
0
          cols->type=DB_INT;
301
0
        else if(strncmp("DB_STR",val,6)==0)
302
0
          cols->type=DB_STR;
303
0
      }else if(val_len==7){
304
0
        if(strncmp("DB_BLOB",val,7)==0)
305
0
          cols->type=DB_BLOB;
306
0
      }else if(val_len==9){
307
0
        if(strncmp("DB_BIGINT",val,9)==0)
308
0
          cols->type=DB_BIGINT;
309
0
        else if(strncmp("DB_DOUBLE",val,9)==0)
310
0
          cols->type=DB_DOUBLE;
311
0
        else if(strncmp("DB_STRING",val,9)==0)
312
0
          cols->type=DB_STRING;
313
0
        else if(strncmp("DB_BITMAP",val,9)==0)
314
0
          cols->type=DB_BITMAP;
315
0
      }else if(val_len==11){
316
0
        if(strncmp("DB_DATETIME",val,11)==0)
317
0
          cols->type=DB_DATETIME;
318
0
      }
319
0
      if(cols->type== (db_type_t)-1){
320
0
        LM_ERR("unexpected type [%s] for %s %s %s\n",
321
0
          val, table_node->name, node->name,
322
0
          PI_XML_TYPE_NODE);
323
0
        pi_xml_free(val);
324
0
        return -1;
325
0
      }
326
0
      pi_xml_free(val);
327
      /* */
328
0
      LM_DBG("got node %s [%d][%.*s][%d]\n",
329
0
        PI_XML_COLUMN_NODE,
330
0
        db_tables->cols_size,
331
0
        db_tables->cols[db_tables->cols_size].field.len,
332
0
        db_tables->cols[db_tables->cols_size].field.s,
333
0
        db_tables->cols[db_tables->cols_size].type);
334
      /* */
335
0
      db_tables->cols_size++;
336
0
    }
337
0
  }
338
0
  if(db_tables->cols_size==0){
339
0
    LM_ERR("missing node: %s %s\n",
340
0
      table_node->name, PI_XML_COLUMN_NODE);
341
0
    return -1;
342
0
  }
343
0
  return 0;
344
0
}
345
346
int pi_getDbTables(pi_framework_t *_pi_framework_data, xmlNodePtr framework_node)
347
0
{
348
0
  int i;
349
0
  int j;
350
0
  char *val;
351
0
  int val_len;
352
0
  xmlNodePtr node;
353
0
  pi_db_table_t *db_tables;
354
0
  pi_db_table_t *pi_db_tables = NULL;
355
0
  str id, name;
356
357
  //_pi_framework_data->pi_db_tables_size=0;
358
0
  for(node=framework_node->children;node;node=node->next){
359
0
    if (pi_xml_strcasecmp(node->name,
360
0
      (const xmlChar*)PI_XML_DB_TABLE_NODE) == 0) {
361
0
      if(_pi_framework_data->pi_db_tables_size)
362
0
        db_tables = (pi_db_table_t*)
363
0
          shm_realloc(_pi_framework_data->pi_db_tables,
364
0
          (_pi_framework_data->pi_db_tables_size+1)*
365
0
          sizeof(pi_db_table_t));
366
0
      else
367
0
        db_tables = (pi_db_table_t*)
368
0
            shm_malloc(sizeof(pi_db_table_t));
369
0
      if(db_tables==NULL) {LM_ERR("oom\n"); return -1;}
370
0
      _pi_framework_data->pi_db_tables = db_tables;
371
372
0
      pi_db_tables = _pi_framework_data->pi_db_tables;
373
0
      db_tables = &pi_db_tables[_pi_framework_data->pi_db_tables_size];
374
0
      memset(db_tables, 0, sizeof(pi_db_table_t));
375
376
      /* Populate table ids */
377
0
      id.s = pi_xml_node_get_attr_content_by_name(node,
378
0
            PI_XML_ID_ATTR);
379
0
      if(id.s==NULL){
380
0
        LM_ERR("No attribute for node %d [%s]\n",
381
0
          _pi_framework_data->pi_db_tables_size,
382
0
          node->name);
383
0
        return -1;
384
0
      }
385
0
      id.len = strlen(id.s);
386
0
      if(id.len==0){
387
0
        LM_ERR("Empty attr for node %d [%s]\n",
388
0
          _pi_framework_data->pi_db_tables_size,
389
0
          node->name);
390
0
        return -1;
391
0
      }
392
0
      if(shm_str_dup(&db_tables->id, &id)!=0) return -1;
393
0
      pi_xml_free(id.s);id.s=NULL;id.len=0;
394
      /* Populate table name */
395
0
      name.s =
396
0
        pi_xml_node_get_node_content_by_name(node->children,
397
0
            PI_XML_TABLE_NAME_NODE);
398
0
      if(name.s==NULL){
399
0
        LM_ERR("No content for node [%.*s][%s]\n",
400
0
          db_tables->id.len, db_tables->id.s,
401
0
          node->name);
402
0
        return -1;
403
0
      }
404
0
      name.len = strlen(name.s);
405
0
      if(name.len==0){
406
0
        LM_ERR("Empty content for node [%.*s][%s]\n",
407
0
          db_tables->id.len, db_tables->id.s,
408
0
          node->name);
409
0
        return -1;
410
0
      }
411
0
      if(shm_str_dup(&db_tables->name, &name)!=0) return -1;
412
0
      pi_xml_free(name.s);name.s=NULL;name.len=0;
413
      /* Each table_id MUST be unique */
414
0
      for(i=0;i<_pi_framework_data->pi_db_tables_size;i++){
415
0
        if(db_tables->id.len==pi_db_tables[i].id.len &&
416
0
                                        strncmp(pi_db_tables[i].id.s,
417
0
                                                db_tables->id.s,
418
0
            db_tables->id.len)==0){
419
0
          LM_ERR("duplicated id %s %s [%.*s]\n",
420
0
            PI_XML_DB_TABLE_NODE,
421
0
            PI_XML_ID_ATTR,
422
0
            db_tables->id.len, db_tables->id.s);
423
0
          return -1;
424
0
        }
425
0
      }
426
      /* Populate the optional db_url index.  If omitted, the
427
       * owning module's db_url will be used during finalization. */
428
0
      val = pi_xml_node_get_node_content_by_name(node->children,
429
0
              PI_XML_DB_URL_ID_NODE);
430
0
      if(val!=NULL)
431
0
        val_len = strlen(val);
432
0
      if(val && val_len==0){
433
0
        LM_ERR("empty %s for node %s [%.*s]\n",
434
0
          PI_XML_DB_URL_ID_NODE,
435
0
          PI_XML_DB_TABLE_NODE,
436
0
          db_tables->name.len, db_tables->name.s);
437
0
        return -1;
438
0
      }
439
0
      if (val) {
440
0
        str db_url_id = {val, val_len};
441
0
        if (shm_str_dup(&db_tables->db_url_id, &db_url_id) != 0)
442
0
          return -1;
443
0
        pi_xml_free(val);
444
0
      }
445
446
0
      if(pi_getDbTableCols(_pi_framework_data->pi_db_urls,
447
0
              db_tables, node)!=0)
448
0
        return -1;
449
450
0
      _pi_framework_data->pi_db_tables_size++;
451
      /*
452
      LM_DBG("got node [%s]->[%s][%s]\n",
453
        node->name, db_tables->id.s, db_tables->db_table.s);
454
      */
455
0
    }
456
0
  }
457
0
  if(_pi_framework_data->pi_db_tables_size==0){
458
0
    LM_ERR("No [%s] node in config file\n", PI_XML_DB_TABLE_NODE);
459
0
    return -1;
460
0
  }
461
  /* */
462
0
  for(i=0;i<_pi_framework_data->pi_db_tables_size;i++){
463
0
    LM_DBG("got node %s [%d][%.*s]->[%.*s/%.*s]\n",
464
0
      PI_XML_DB_TABLE_NODE, i,
465
0
      pi_db_tables[i].id.len, pi_db_tables[i].id.s,
466
0
      pi_db_tables[i].db_url_id.len,
467
0
      pi_db_tables[i].db_url_id.s ? pi_db_tables[i].db_url_id.s : "(module)",
468
0
      pi_db_tables[i].name.len, pi_db_tables[i].name.s);
469
0
    db_tables = &pi_db_tables[i];
470
0
    for(j=0;j<db_tables->cols_size;j++){
471
0
      LM_DBG("got node %s [%.*s][%d]\n",
472
0
        PI_XML_COLUMN_NODE,
473
0
        db_tables->cols[j].field.len,
474
0
        db_tables->cols[j].field.s,
475
0
        db_tables->cols[j].type);
476
0
    }
477
0
  }
478
  /* */
479
0
  return 0;
480
0
}
481
482
int pi_getColVals(pi_mod_t *module, pi_cmd_t *cmd,
483
    pi_vals_t *cmd_col_vals, xmlNodePtr col_node)
484
0
{
485
0
  xmlNodePtr node;
486
0
  str *vals, *col_vals = NULL;
487
0
  str *ids, *col_ids = NULL;
488
0
  int size = 0;
489
0
  int i;
490
0
  str attr;
491
0
  str val;
492
493
0
  for(node=col_node->children;node;node=node->next){
494
0
    if (pi_xml_strcasecmp(node->name,
495
0
      (const xmlChar*)PI_XML_VALUE_NODE) == 0) {
496
0
      if(size){
497
0
        vals = (str*)shm_realloc(col_vals,
498
0
          (size+1)*sizeof(str));
499
0
        ids = (str*)shm_realloc(col_ids,
500
0
          (size+1)*sizeof(str));
501
0
      }else{
502
0
        vals = (str*)shm_malloc(sizeof(str));
503
0
        ids = (str*)shm_malloc(sizeof(str));
504
0
      }
505
0
      if(vals==NULL||ids==NULL) {LM_ERR("oom\n"); return -1;}
506
0
      col_vals = vals; col_ids = ids;
507
0
      vals = &col_vals[size]; ids = &col_ids[size];
508
0
      memset(vals, 0, sizeof *vals); memset(ids, 0, sizeof *ids);
509
      /* Retrieve the node attribute */
510
0
      attr.s = pi_xml_node_get_attr_content_by_name(node,
511
0
              PI_XML_ID_ATTR);
512
0
      if(attr.s==NULL){
513
0
        LM_ERR("No attribute for node\n");
514
0
        return -1;
515
0
      }
516
0
      attr.len = strlen(attr.s);
517
0
      if(attr.len==0){
518
0
        LM_ERR("No attribute for node\n");
519
0
        return -1;
520
0
      }
521
0
      if(shm_str_dup(ids, &attr)!=0) return -1;
522
0
      pi_xml_free(attr.s); attr.s = NULL; attr.len = 0;
523
      /* Retrieve the node value */
524
0
      val.s = (char*)pi_xml_node_get_content(node);
525
0
      if(val.s==NULL){
526
0
        LM_ERR("No content for node\n");
527
0
        return -1;
528
0
      }
529
0
      val.len = strlen(val.s);
530
0
      if(val.len==0){
531
0
        LM_ERR("No content for node\n");
532
0
        return -1;
533
0
      }
534
0
      if(shm_str_dup(vals, &val)!=0) return -1;
535
0
      pi_xml_free(val.s); val.s = NULL; val.len = 0;
536
      /*
537
      LM_DBG(">  > [%d] [%p]->[%s] [%p]->[%s]\n",
538
          size, ids, ids->s, vals, vals->s);
539
      */
540
0
      size++;
541
0
    }
542
0
  }
543
0
  if(size){
544
0
    cmd_col_vals->ids = col_ids;
545
0
    cmd_col_vals->vals = col_vals;
546
0
    cmd_col_vals->vals_size = size;
547
    /* */
548
0
    for(i=0;i<size;i++)
549
0
      LM_DBG(">>> [%d] [%p]->[%.*s] [%p]->[%.*s]\n", i,
550
0
        cmd_col_vals->ids[i].s,
551
0
        cmd_col_vals->ids[i].len, cmd_col_vals->ids[i].s,
552
0
        cmd_col_vals->vals[i].s,
553
0
        cmd_col_vals->vals[i].len, cmd_col_vals->vals[i].s);
554
    /* */
555
0
  }
556
0
  return 0;
557
0
}
558
559
int pi_getCols(pi_mod_t *module, pi_cmd_t *cmd,
560
    db_op_t **mod_cmd_ops, db_key_t **mod_cmd_keys,
561
    db_type_t **mod_cmd_types, pi_vals_t **mod_cmd_vals, str **mod_cmd_linkCmd,
562
    int *key_size, xmlNodePtr cmd_node)
563
0
{
564
0
  xmlNodePtr node;
565
0
  str *key;
566
0
  str field;
567
0
  db_key_t *keys;
568
0
  db_key_t *cmd_keys = NULL;
569
0
  int op_len;
570
0
  char *operator;
571
0
  char *_operator;
572
0
  db_op_t *ops;
573
0
  db_op_t *cmd_ops = NULL;
574
0
  db_type_t *types;
575
0
  db_type_t *cmd_types = NULL;
576
0
  pi_vals_t *vals;
577
0
  pi_vals_t *cmd_vals = NULL;
578
0
  str link_cmd;
579
0
  str *linkCmd;
580
0
  str *cmd_linkCmd = NULL;
581
0
  int i;
582
0
  int size = 0;
583
0
  int table_size;
584
0
  pi_table_col_t *table_cols;
585
586
0
  for(node=cmd_node->children;node;node=node->next){
587
0
    if (pi_xml_strcasecmp(node->name,
588
0
      (const xmlChar*)PI_XML_COL_NODE) == 0) {
589
0
      if(size)
590
0
        keys = (db_key_t*)shm_realloc(cmd_keys,
591
0
          (size+1)*sizeof(db_key_t));
592
0
      else
593
0
        keys = (db_key_t*)shm_malloc(sizeof(db_key_t));
594
0
      if (keys==NULL) {LM_ERR("oom\n");return -1;}
595
0
      cmd_keys = keys;
596
0
      keys = &cmd_keys[size];
597
0
      memset(keys, 0, sizeof(db_key_t));
598
0
      key = (str*)shm_malloc(sizeof(str));
599
0
      if (key==NULL) {LM_ERR("oom\n");return -1;}
600
      /* get the col field */
601
0
      field.s = pi_xml_node_get_node_content_by_name(node->children,
602
0
            PI_XML_FIELD_NODE);
603
0
      if(field.s==NULL){
604
0
        LM_ERR("no %s in %s [%.*s] %s [%.*s] %s %s\n",
605
0
          PI_XML_FIELD_NODE,
606
0
          cmd_node->parent->parent->name,
607
0
          module->module.len, module->module.s,
608
0
          cmd_node->parent->name,
609
0
          cmd->name.len, cmd->name.s,
610
0
          cmd_node->name, node->name);
611
0
        return -1;
612
0
      }
613
0
      field.len = strlen(field.s);
614
0
      if(field.len==0){
615
0
        LM_ERR("empty %s in %s [%.*s] %s [%.*s] %s %s\n",
616
0
          PI_XML_FIELD_NODE,
617
0
          cmd_node->parent->parent->name,
618
0
          module->module.len, module->module.s,
619
0
          cmd_node->parent->name,
620
0
          cmd->name.len, cmd->name.s,
621
0
          cmd_node->name, node->name);
622
0
        return -1;
623
0
      }
624
      /* Each field must be valid */
625
0
      table_size = cmd->db_table->cols_size;
626
0
      table_cols = cmd->db_table->cols;
627
0
      for(i=0;i<table_size;i++){
628
0
        if(field.len==table_cols[i].field.len &&
629
0
          strncmp(table_cols[i].field.s,
630
0
            field.s,
631
0
            field.len)==0) break;
632
0
      }
633
0
      if(i==table_size){
634
0
        LM_ERR("invalid %s [%.*s] in %s [%.*s] %s [%.*s] %s %s"
635
0
          " for [%.*s]\n",
636
0
          PI_XML_FIELD_NODE,
637
0
          field.len, field.s,
638
0
          cmd_node->parent->parent->name,
639
0
          module->module.len, module->module.s,
640
0
          cmd_node->parent->name,
641
0
          cmd->name.len, cmd->name.s,
642
0
          cmd_node->name, node->name,
643
0
          cmd->db_table->name.len, cmd->db_table->name.s);
644
0
        return -1;
645
0
      }
646
0
      if(shm_str_dup(key, &field)) return -1;
647
0
      *keys = key;
648
0
      pi_xml_free(field.s); field.s = NULL; field.len = 0;
649
0
      LM_DBG("cmd_keys=[%p] keys=[%p]->[%p]->[%.*s]\n",
650
0
            cmd_keys, keys, *keys,
651
0
            (*keys)->len, (*keys)->s);
652
      /* Retrieve the type */
653
0
      if(mod_cmd_types){
654
0
        if(size)
655
0
          types = (db_type_t*)shm_realloc(cmd_types,
656
0
            (size+1)*sizeof(db_type_t));
657
0
        else
658
0
          types =
659
0
          (db_type_t*)shm_malloc(sizeof(db_type_t));
660
0
        if (types==NULL) {LM_ERR("oom\n");return -1;}
661
0
        cmd_types = types;
662
0
        types = &cmd_types[size];
663
0
        memset(types, 0, sizeof(db_type_t));
664
0
        *types = table_cols[i].type;
665
0
      }
666
      /* Retrieve the ops */
667
0
      if(mod_cmd_ops){
668
0
        if(size)
669
0
          ops = (db_op_t*)shm_realloc(cmd_ops,
670
0
            (size+1)*sizeof(db_op_t));
671
0
        else
672
0
          ops = (db_op_t*)shm_malloc(sizeof(db_op_t));
673
0
        if (ops==NULL) {LM_ERR("oom\n");return -1;}
674
0
        cmd_ops = ops;
675
0
        ops = &cmd_ops[size];
676
0
        memset(ops, 0, sizeof(db_op_t));
677
        /* Retrieve the col op */
678
0
        operator =
679
0
          pi_xml_node_get_node_content_by_name(node->children,
680
0
            PI_XML_OPERATOR_NODE);
681
0
        if(operator==NULL){
682
0
          LM_ERR("no %s in %s [%.*s] %s [%.*s] %s %s\n",
683
0
            PI_XML_OPERATOR_NODE,
684
0
            cmd_node->parent->parent->name,
685
0
            module->module.len, module->module.s,
686
0
            cmd_node->parent->name,
687
0
            cmd->name.len, cmd->name.s,
688
0
            cmd_node->name, node->name);
689
0
          return -1;
690
0
        }
691
0
        op_len = strlen(operator);
692
0
        if(op_len==0){
693
0
          LM_ERR("empty %s in %s [%.*s] %s [%.*s] %s %s\n",
694
0
            PI_XML_OPERATOR_NODE,
695
0
            cmd_node->parent->parent->name,
696
0
            module->module.len, module->module.s,
697
0
            cmd_node->parent->name,
698
0
            cmd->name.len, cmd->name.s,
699
0
            cmd_node->name, node->name);
700
0
          return -1;
701
0
        }else if(op_len==1){
702
0
          if(strncmp(OP_LT,operator,1)==0)
703
0
            *ops = operator;
704
0
          else if(strncmp(OP_GT,operator,1)==0)
705
0
            *ops = operator;
706
0
          else if(strncmp(OP_EQ,operator,1)==0)
707
0
            *ops = operator;
708
0
        }else if(op_len==2){
709
0
          if(strncmp(OP_LEQ,operator,2)==0)
710
0
            *ops = operator;
711
0
          else if(strncmp(OP_GEQ,operator,2)==0)
712
0
            *ops = operator;
713
0
          else if(strncmp(OP_NEQ,operator,2)==0)
714
0
            *ops = operator;
715
0
        }
716
0
        if(*ops==NULL){
717
0
          LM_ERR("unexpected %s [%s] in "
718
0
            "%s [%.*s] %s [%.*s] %s %s\n",
719
0
            PI_XML_OPERATOR_NODE,
720
0
            operator,
721
0
            cmd_node->parent->parent->name,
722
0
            module->module.len, module->module.s,
723
0
            cmd_node->parent->name,
724
0
            cmd->name.len, cmd->name.s,
725
0
            cmd_node->name, node->name);
726
0
          return -1;
727
0
        }
728
        /* We need to copy the null string terminator */
729
0
        op_len++;
730
0
        _operator = shm_malloc(op_len);
731
0
        if(_operator==NULL){LM_ERR("oom\n"); return -1;}
732
0
        memcpy(_operator, operator, op_len);
733
0
        *ops = _operator;
734
0
        pi_xml_free(operator); operator = NULL; op_len = 0;
735
0
        LM_DBG("%s [%p]=>[%p]=>[%.*s] %s [%.*s] %s %s [%.*s][%s]\n",
736
0
          cmd_node->parent->parent->name, module,
737
0
          module->module.s,
738
0
          module->module.len, module->module.s,
739
0
          cmd_node->parent->name,
740
0
          cmd->name.len, cmd->name.s,
741
0
          cmd_node->name, node->name,
742
0
          (**keys).len, (**keys).s, *ops);
743
0
      }else{
744
0
        LM_DBG("%s [%p]=>[%p]=>[%.*s] %s [%.*s] %s %s [%.*s][]\n",
745
0
          cmd_node->parent->parent->name, module,
746
0
          module->module.s,
747
0
          module->module.len, module->module.s,
748
0
          cmd_node->parent->name,
749
0
          cmd->name.len, cmd->name.s,
750
0
          cmd_node->name, node->name,
751
0
          (**keys).len, (**keys).s);
752
0
      }
753
      /* Retrieve the vals */
754
0
      if(mod_cmd_vals){
755
0
        if(size)
756
0
          vals = (pi_vals_t*)shm_realloc(cmd_vals,
757
0
            (size+1)*sizeof(pi_vals_t));
758
0
        else
759
0
          vals =
760
0
          (pi_vals_t*)shm_malloc(sizeof(pi_vals_t));
761
0
        if(vals==NULL) {LM_ERR("oom\n");return -1;}
762
0
        cmd_vals = vals;
763
0
        vals = &cmd_vals[size];
764
0
        memset(vals, 0, sizeof(pi_vals_t));
765
0
        if(pi_getColVals(module, cmd, vals, node)!=0)
766
0
          return -1;
767
0
      }
768
      /* Retrieve the link_cmds */
769
0
      if(mod_cmd_linkCmd){
770
0
        if(size)
771
0
          linkCmd = (str*)shm_realloc(cmd_linkCmd,
772
0
            (size+1)*sizeof(str));
773
0
        else
774
0
          linkCmd = (str*)shm_malloc(sizeof(str));
775
0
        if(linkCmd==NULL) {LM_ERR("oom\n");return -1;}
776
0
        cmd_linkCmd = linkCmd;
777
0
        linkCmd = &cmd_linkCmd[size];
778
0
        memset(linkCmd, 0, sizeof(str));
779
        /* get the link_cmd */
780
0
        link_cmd.s = pi_xml_node_get_node_content_by_name(node->children,
781
0
            PI_XML_LINK_CMD_NODE);
782
0
        if(link_cmd.s!=NULL){
783
0
          link_cmd.len = strlen(link_cmd.s);
784
0
          if(link_cmd.len!=0){
785
0
            LM_DBG("got %s=[%.*s] in %s [%.*s] %s [%.*s] %s %s\n",
786
0
              PI_XML_LINK_CMD_NODE,
787
0
              link_cmd.len, link_cmd.s,
788
0
              cmd_node->parent->parent->name,
789
0
              module->module.len, module->module.s,
790
0
              cmd_node->parent->name,
791
0
              cmd->name.len, cmd->name.s,
792
0
              cmd_node->name, node->name);
793
0
            if(shm_str_dup(linkCmd, &link_cmd)) return -1;
794
0
          }
795
0
          pi_xml_free(link_cmd.s); link_cmd.s = NULL; link_cmd.len = 0;
796
0
        }
797
0
      }
798
0
      size++;
799
0
    }
800
0
  }
801
0
  if(size==0){
802
0
    LM_ERR("empty %s in %s [%.*s] %s [%.*s]\n",
803
0
      cmd_node->name, cmd_node->parent->parent->name,
804
0
      module->module.len, module->module.s,
805
0
      cmd_node->parent->name, cmd->name.len, cmd->name.s);
806
0
    return -1;
807
0
  }else if(cmd_keys!=NULL){
808
0
    *mod_cmd_keys = cmd_keys;
809
0
    LM_DBG("***  mod_cmd_keys=[%p] *mod_cmd_keys=[%p] cmd_keys=[%p]\n",
810
0
        mod_cmd_keys, *mod_cmd_keys, cmd_keys);
811
0
    if(cmd_keys) for(i=0;i<size;i++)
812
0
      LM_DBG("cmd_keys[%d]=[%p]->[%p]->[%.*s]\n",
813
0
        i, &cmd_keys[i], cmd_keys[i]->s,
814
0
        cmd_keys[i]->len, cmd_keys[i]->s);
815
0
    if(mod_cmd_ops) *mod_cmd_ops = cmd_ops;
816
0
    if(mod_cmd_types) *mod_cmd_types = cmd_types;
817
0
    if(mod_cmd_vals&&cmd_vals) *mod_cmd_vals = cmd_vals;
818
0
    if(mod_cmd_linkCmd) *mod_cmd_linkCmd = cmd_linkCmd;
819
0
    if(cmd_vals) for(i=0;i<size;i++){
820
0
      LM_DBG("cmd_vals[%d]=[%p]->[%d][%p][%p]\n",
821
0
        i, &cmd_vals[i], cmd_vals[i].vals_size,
822
0
        cmd_vals[i].ids, cmd_vals[i].vals);
823
0
      for(op_len=0;op_len<cmd_vals[i].vals_size;op_len++)
824
0
        LM_DBG("    [%d][%d] [%p]->[%.*s] [%p]->[%.*s]\n",
825
0
          i, op_len,
826
0
          &cmd_vals[i].ids[op_len],
827
0
          cmd_vals[i].ids[op_len].len,
828
0
          cmd_vals[i].ids[op_len].s,
829
0
          &cmd_vals[i].vals[op_len],
830
0
          cmd_vals[i].vals[op_len].len,
831
0
          cmd_vals[i].vals[op_len].s);
832
0
    }
833
0
    if(mod_cmd_linkCmd&&cmd_linkCmd) *mod_cmd_linkCmd = cmd_linkCmd;
834
0
    *key_size = size;
835
0
    if(cmd_ops) for(i=0;i<size;i++)
836
0
      LM_DBG("cmd_ops[%d]=[%p]->[%s]\n",
837
0
        i, &cmd_ops[i], cmd_ops[i]);
838
0
    LM_DBG("\n");
839
0
  }
840
0
  return 0;
841
0
}
842
843
int pi_getCmds(pi_db_table_t *pi_db_tables, int pi_db_tables_size,
844
    pi_mod_t *modules, xmlNodePtr mod_node)
845
0
{
846
0
  int i;
847
0
  int j;
848
0
  char *val;
849
0
  int val_len;
850
0
  pi_cmd_t *cmds;
851
0
  xmlNodePtr node, cmd_cols;
852
0
  str name;
853
854
0
  for(node=mod_node->children,modules->cmds_size=0;node;node=node->next){
855
0
    if (pi_xml_strcasecmp(node->name,
856
0
      (const xmlChar*)PI_XML_CMD_NODE) == 0) {
857
0
      if(modules->cmds_size)
858
0
        cmds = (pi_cmd_t*)shm_realloc(modules->cmds,
859
0
          (modules->cmds_size+1)*sizeof(pi_cmd_t));
860
0
      else
861
0
        cmds = (pi_cmd_t*)shm_malloc(sizeof(pi_cmd_t));;
862
0
      if (cmds==NULL) {LM_ERR("oom\n");return -1;}
863
0
      modules->cmds = cmds;
864
0
      cmds = &modules->cmds[modules->cmds_size];
865
0
      memset(cmds, 0, sizeof(pi_cmd_t));
866
0
      cmds->type = -1;
867
      /* Populate the cmd name */
868
0
      name.s =
869
0
        pi_xml_node_get_node_content_by_name(node->children,
870
0
            PI_XML_CMD_NAME_NODE);
871
0
      if(name.s==NULL){
872
0
        LM_ERR("no %s for %s [%.*s]\n",
873
0
          PI_XML_CMD_NAME_NODE,
874
0
          mod_node->name,
875
0
          modules->module.len, modules->module.s);
876
0
        return -1;
877
0
      }
878
0
      name.len = strlen(name.s);
879
0
      if(name.len==0){
880
0
        LM_ERR("empty %s for %s [%.*s]\n",
881
0
          PI_XML_CMD_NAME_NODE,
882
0
          mod_node->name,
883
0
          modules->module.len, modules->module.s);
884
0
        return -1;
885
0
      }
886
0
      if(shm_str_dup(&cmds->name, &name)!=0) return -1;
887
0
      pi_xml_free(name.s);name.s=NULL;name.len=0;
888
      /* Each cmd name MUST be unique */
889
0
      for(i=0;i<modules->cmds_size;i++){
890
0
        if(cmds->name.len==modules->cmds[i].name.len &&
891
0
                                        strncmp(modules->cmds[i].name.s,
892
0
                                                cmds->name.s,
893
0
            cmds->name.len)==0){
894
0
          LM_ERR("duplicated %s %s %s [%.*s]\n",
895
0
            mod_node->name, modules->module.s,
896
0
            node->name,
897
0
            cmds->name.len, cmds->name.s);
898
0
          return -1;
899
0
        }
900
0
      }
901
      /* Populate the db_table_index */
902
0
      val = pi_xml_node_get_node_content_by_name(node->children,
903
0
            PI_XML_DB_TABLE_ID_NODE);
904
0
      if(val==NULL){
905
0
        LM_ERR("no %s for %s [%.*s] %s [%.*s]\n",
906
0
          PI_XML_DB_TABLE_ID_NODE,
907
0
          mod_node->name,
908
0
          modules->module.len, modules->module.s,
909
0
          PI_XML_CMD_NODE,
910
0
          cmds->name.len, cmds->name.s);
911
0
        return -1;
912
0
      }
913
0
      val_len = strlen(val);
914
0
      if(val_len==0){
915
0
        LM_ERR("empty %s for %s [%.*s] %s [%.*s]\n",
916
0
          PI_XML_DB_URL_ID_NODE,
917
0
          mod_node->name,
918
0
          modules->module.len, modules->module.s,
919
0
          PI_XML_CMD_NODE,
920
0
          cmds->name.len, cmds->name.s);
921
0
        pi_xml_free(val);
922
0
        return -1;
923
0
      }
924
      /* Get db_table */
925
0
      for(i=0;i<pi_db_tables_size;i++){
926
0
        if(val_len==pi_db_tables[i].id.len &&
927
0
          strncmp(pi_db_tables[i].id.s,
928
0
            val, val_len)==0){
929
0
          cmds->db_table = &pi_db_tables[i];
930
0
          break;
931
0
        }
932
0
      }
933
0
      if (i==pi_db_tables_size){
934
0
        LM_ERR("bogus %s [%s] for %s [%.*s] %s [%.*s]\n",
935
0
          PI_XML_DB_TABLE_ID_NODE, val,
936
0
          mod_node->name,
937
0
          modules->module.len, modules->module.s,
938
0
          PI_XML_CMD_NODE,
939
0
          cmds->name.len, cmds->name.s);
940
0
        pi_xml_free(val);
941
0
        return -1;
942
0
      }
943
0
      pi_xml_free(val);
944
      /* Get cmd_type */
945
0
      val = pi_xml_node_get_node_content_by_name(node->children,
946
0
            PI_XML_CMD_TYPE_NODE);
947
0
      if(val==NULL){
948
0
        LM_ERR("no %s for %s [%.*s] %s [%.*s]\n",
949
0
          PI_XML_CMD_TYPE_NODE,
950
0
          mod_node->name,
951
0
          modules->module.len, modules->module.s,
952
0
          PI_XML_CMD_NODE,
953
0
          cmds->name.len, cmds->name.s);
954
0
        return -1;
955
0
      }
956
0
      val_len = strlen(val);
957
0
      if(val_len==0){
958
0
        LM_ERR("empty %s for %s [%.*s] %s [%.*s]\n",
959
0
          PI_XML_CMD_TYPE_NODE,
960
0
          mod_node->name,
961
0
          modules->module.len, modules->module.s,
962
0
          PI_XML_CMD_NODE,
963
0
          cmds->name.len, cmds->name.s);
964
0
        pi_xml_free(val);
965
0
        return -1;
966
0
      }else if(val_len==8){
967
0
        if(strncmp("DB_QUERY",val,8)==0){
968
0
          cmds->type = DB_CAP_QUERY;
969
0
          cmd_cols =
970
0
          pi_xml_node_get_node_by_name(node->children,
971
0
            PI_XML_CLAUSE_COLS_NODE);
972
0
          if(cmd_cols!=NULL)
973
0
            if (pi_getCols( modules,
974
0
                cmds,
975
0
                &cmds->c_ops,
976
0
                &cmds->c_keys,
977
0
                &cmds->c_types,
978
0
                &cmds->c_vals,
979
0
                NULL,
980
0
                &cmds->c_keys_size,
981
0
                cmd_cols)!=0)
982
0
              return -1;
983
0
          cmd_cols =
984
0
          pi_xml_node_get_node_by_name(node->children,
985
0
            PI_XML_QUERY_COLS_NODE);
986
0
          if(cmd_cols!=NULL){
987
0
            if (pi_getCols( modules,
988
0
                cmds,
989
0
                NULL,
990
0
                &cmds->q_keys,
991
0
                &cmds->q_types,
992
0
                NULL,
993
0
                &cmds->link_cmd,
994
0
                &cmds->q_keys_size,
995
0
                cmd_cols)!=0)
996
0
              return -1;
997
0
          }else{
998
0
            LM_ERR("no %s in %s [%.*s] %s [%.*s]\n",
999
0
              PI_XML_QUERY_COLS_NODE,
1000
0
              mod_node->name,
1001
0
              modules->module.len,
1002
0
              modules->module.s,
1003
0
              node->name,
1004
0
              cmds->name.len,
1005
0
              cmds->name.s);
1006
0
            return -1;
1007
0
          }
1008
0
          cmd_cols =
1009
0
          pi_xml_node_get_node_by_name(node->children,
1010
0
            PI_XML_ORDER_BY_COLS_NODE);
1011
0
          if(cmd_cols!=NULL){
1012
0
            if (pi_getCols( modules,
1013
0
                cmds,
1014
0
                NULL,
1015
0
                &cmds->o_keys,
1016
0
                NULL,
1017
0
                NULL,
1018
0
                NULL,
1019
0
                &cmds->o_keys_size,
1020
0
                cmd_cols)!=0)
1021
0
              return -1;
1022
0
          }
1023
0
        }
1024
0
      }else if(val_len==9){
1025
0
        if(strncmp("DB_INSERT",val,9)==0){
1026
0
          cmds->type = DB_CAP_INSERT;
1027
0
          cmd_cols =
1028
0
          pi_xml_node_get_node_by_name(node->children,
1029
0
            PI_XML_QUERY_COLS_NODE);
1030
0
          if(cmd_cols!=NULL){
1031
0
            if (pi_getCols( modules,
1032
0
                cmds,
1033
0
                NULL,
1034
0
                &cmds->q_keys,
1035
0
                &cmds->q_types,
1036
0
                &cmds->q_vals,
1037
0
                NULL,
1038
0
                &cmds->q_keys_size,
1039
0
                cmd_cols)!=0)
1040
0
              return -1;
1041
0
          }else{
1042
0
            LM_ERR("no %s in %s [%.*s] %s [%.*s]\n",
1043
0
              PI_XML_QUERY_COLS_NODE,
1044
0
              mod_node->name,
1045
0
              modules->module.len,
1046
0
              modules->module.s,
1047
0
              node->name,
1048
0
              cmds->name.len,
1049
0
              cmds->name.s);
1050
0
            return -1;
1051
0
          }
1052
0
        }else if(strncmp("DB_DELETE",val,9)==0){
1053
0
          cmds->type = DB_CAP_DELETE;
1054
0
          cmd_cols =
1055
0
          pi_xml_node_get_node_by_name(node->children,
1056
0
            PI_XML_CLAUSE_COLS_NODE);
1057
0
          if(cmd_cols!=NULL){
1058
0
            if (pi_getCols( modules,
1059
0
                cmds,
1060
0
                &cmds->c_ops,
1061
0
                &cmds->c_keys,
1062
0
                &cmds->c_types,
1063
0
                &cmds->c_vals,
1064
0
                NULL,
1065
0
                &cmds->c_keys_size,
1066
0
                cmd_cols)!=0)
1067
0
              return -1;
1068
0
          }else{
1069
0
            LM_ERR("no %s in %s [%.*s] %s [%.*s]\n",
1070
0
              PI_XML_CLAUSE_COLS_NODE,
1071
0
              mod_node->name,
1072
0
              modules->module.len,
1073
0
              modules->module.s,
1074
0
              node->name,
1075
0
              cmds->name.len,
1076
0
              cmds->name.s);
1077
0
            return -1;
1078
0
          }
1079
1080
0
        }else if(strncmp("DB_UPDATE",val,9)==0){
1081
0
          cmds->type = DB_CAP_UPDATE;
1082
0
          cmd_cols =
1083
0
          pi_xml_node_get_node_by_name(node->children,
1084
0
            PI_XML_CLAUSE_COLS_NODE);
1085
0
          if(cmd_cols!=NULL)
1086
0
            if (pi_getCols( modules,
1087
0
                cmds,
1088
0
                &cmds->c_ops,
1089
0
                &cmds->c_keys,
1090
0
                &cmds->c_types,
1091
0
                &cmds->c_vals,
1092
0
                NULL,
1093
0
                &cmds->c_keys_size,
1094
0
                cmd_cols)!=0)
1095
0
              return -1;
1096
0
          cmd_cols =
1097
0
          pi_xml_node_get_node_by_name(node->children,
1098
0
            PI_XML_QUERY_COLS_NODE);
1099
0
          if(cmd_cols!=NULL){
1100
0
            if (pi_getCols( modules,
1101
0
                cmds,
1102
0
                NULL,
1103
0
                &cmds->q_keys,
1104
0
                &cmds->q_types,
1105
0
                &cmds->q_vals,
1106
0
                NULL,
1107
0
                &cmds->q_keys_size,
1108
0
                cmd_cols)!=0)
1109
0
              return -1;
1110
0
          }else{
1111
0
            LM_ERR("no %s in %s [%.*s] %s [%.*s]\n",
1112
0
              PI_XML_QUERY_COLS_NODE,
1113
0
              mod_node->name,
1114
0
              modules->module.len,
1115
0
              modules->module.s,
1116
0
              node->name,
1117
0
              cmds->name.len,
1118
0
              cmds->name.s);
1119
0
            return -1;
1120
0
          }
1121
0
        }
1122
0
      }else if(val_len==10){
1123
0
        if(strncmp("DB_REPLACE",val,10)==0){
1124
0
          cmds->type = DB_CAP_REPLACE;
1125
0
          cmd_cols =
1126
0
          pi_xml_node_get_node_by_name(node->children,
1127
0
            PI_XML_QUERY_COLS_NODE);
1128
0
          if(cmd_cols!=NULL){
1129
0
            if (pi_getCols( modules,
1130
0
                cmds,
1131
0
                NULL,
1132
0
                &cmds->q_keys,
1133
0
                &cmds->q_types,
1134
0
                &cmds->q_vals,
1135
0
                NULL,
1136
0
                &cmds->q_keys_size,
1137
0
                cmd_cols)!=0)
1138
0
              return -1;
1139
0
          }else{
1140
0
            LM_ERR("no %s in %s [%.*s] %s [%.*s]\n",
1141
0
              PI_XML_QUERY_COLS_NODE,
1142
0
              mod_node->name,
1143
0
              modules->module.len,
1144
0
              modules->module.s,
1145
0
              node->name,
1146
0
              cmds->name.len,
1147
0
              cmds->name.s);
1148
0
            return -1;
1149
0
          }
1150
0
        }
1151
0
      }
1152
0
      if(cmds->type==-1){
1153
0
        LM_ERR("unexpected type [%s] for %s [%.*s] %s [%.*s]\n",
1154
0
          val, mod_node->name,
1155
0
          modules->module.len,
1156
0
          modules->module.s,
1157
0
          PI_XML_CMD_NODE,
1158
0
          cmds->name.len, cmds->name.s);
1159
0
        pi_xml_free(val);
1160
0
        return -1;
1161
0
      }
1162
0
      pi_xml_free(val);
1163
      /**/
1164
0
      LM_DBG("got node %s %s %s [%.*s] [%p]=>[%.*s]\n",
1165
0
          mod_node->name, node->name,
1166
0
          PI_XML_CMD_NAME_NODE,
1167
0
          cmds->name.len, cmds->name.s,
1168
0
          cmds->db_table->name.s,
1169
0
          cmds->db_table->name.len,
1170
0
          cmds->db_table->name.s);
1171
0
      if(cmds->c_keys)
1172
0
        for(i=0;i<cmds->c_keys_size;i++){
1173
0
          LM_DBG("    [%d] c_keys=[%.*s] "
1174
0
            "c_ops=[%s] c_types=[%d]\n",
1175
0
            i, (*(cmds->c_keys[i])).len,
1176
0
            (*(cmds->c_keys[i])).s,
1177
0
            cmds->c_ops[i], cmds->c_types[i]);
1178
0
          if(cmds->c_vals)
1179
0
            for(j=0;j<cmds->c_vals->vals_size;j++)
1180
0
              LM_DBG("      c_vals[%d] "
1181
0
              "id=[%.*s] val=[%.*s]\n",
1182
0
              j,
1183
0
              cmds->c_vals->ids->len,
1184
0
              cmds->c_vals->ids->s,
1185
0
              cmds->c_vals->vals->len,
1186
0
              cmds->c_vals->vals->s);
1187
0
        }
1188
0
      if(cmds->q_keys)
1189
0
        for(i=0;i<cmds->q_keys_size;i++){
1190
0
          LM_DBG("    [%d] q_keys=[%.*s] "
1191
0
            "q_types=[%d] link_cmd=[%.*s]\n",
1192
0
            i, (*(cmds->q_keys[i])).len,
1193
0
            (*(cmds->q_keys[i])).s,
1194
0
            cmds->q_types[i],
1195
0
            (cmds->link_cmd)?(cmds->link_cmd[i]).len:0,
1196
0
            (cmds->link_cmd)?(cmds->link_cmd[i]).s:NULL);
1197
0
          if(cmds->q_vals)
1198
0
            for(j=0;j<cmds->q_vals->vals_size;j++)
1199
0
              LM_DBG("      c_vals[%d] "
1200
0
              "id=[%.*s] val=[%.*s]\n",
1201
0
              j,
1202
0
              cmds->q_vals->ids->len,
1203
0
              cmds->q_vals->ids->s,
1204
0
              cmds->q_vals->vals->len,
1205
0
              cmds->q_vals->vals->s);
1206
0
        }
1207
0
      if(cmds->o_keys)
1208
0
        for(i=0;i<cmds->o_keys_size;i++)
1209
0
          LM_DBG("    o_keys[%d]=[%.*s]\n",
1210
0
            i, (*(cmds->o_keys[i])).len,
1211
0
            (*(cmds->o_keys[i])).s);
1212
      /**/
1213
0
      modules->cmds_size++;
1214
0
    }
1215
0
  }
1216
0
  return 0;
1217
0
}
1218
1219
int pi_getMods(pi_framework_t *_pi_framework_data, xmlNodePtr framework_node)
1220
0
{
1221
0
  int i;
1222
0
  pi_mod_t *modules;
1223
0
  xmlNodePtr mod_node;
1224
0
  pi_mod_t *pi_modules;
1225
0
  str module;
1226
1227
  /* Build pi commands skeleton */
1228
0
  for(mod_node=framework_node->children,_pi_framework_data->pi_modules_size=0;
1229
0
          mod_node;mod_node=mod_node->next){
1230
0
    if (pi_xml_strcasecmp(mod_node->name,
1231
0
      (const xmlChar*)PI_XML_MOD_NODE) == 0) {
1232
0
      if(_pi_framework_data->pi_modules_size)
1233
0
        modules = (pi_mod_t*)shm_realloc(_pi_framework_data->pi_modules,
1234
0
          (_pi_framework_data->pi_modules_size+1)*
1235
0
          sizeof(pi_mod_t));
1236
0
      else
1237
0
        modules = (pi_mod_t*)shm_malloc(sizeof(pi_mod_t));
1238
0
      if(modules==NULL){
1239
0
        LM_ERR("oom\n");
1240
0
        return -1;
1241
0
      }
1242
0
      _pi_framework_data->pi_modules = modules;
1243
0
      pi_modules = _pi_framework_data->pi_modules;
1244
0
      modules = &pi_modules[_pi_framework_data->pi_modules_size];
1245
0
      memset(modules, 0, sizeof(pi_mod_t));
1246
1247
      /* Populate module name */
1248
0
      module.s =
1249
0
        pi_xml_node_get_node_content_by_name(mod_node->children,
1250
0
              PI_XML_MOD_NAME_NODE);
1251
0
      if(module.s==NULL){
1252
0
        LM_ERR("no %s for node %s\n",
1253
0
          PI_XML_MOD_NAME_NODE,
1254
0
          PI_XML_MOD_NODE);
1255
0
        return -1;
1256
0
      }
1257
0
      module.len = strlen(module.s);
1258
0
      if(module.len==0){
1259
0
        LM_ERR("empty %s for node %s\n",
1260
0
          PI_XML_MOD_NAME_NODE,
1261
0
          PI_XML_MOD_NODE);
1262
0
        return -1;
1263
0
      }
1264
0
      if(shm_str_dup(&modules->module, &module)!=0) return -1;
1265
0
      pi_xml_free(module.s);module.s=NULL;module.len=0;
1266
      /* Each mod name MUST be unique */
1267
0
      for(i=0;i<_pi_framework_data->pi_modules_size;i++){
1268
0
        if(modules->module.len==pi_modules[i].module.len &&
1269
0
                                        strncmp(pi_modules[i].module.s,
1270
0
                                                modules->module.s,
1271
0
            modules->module.len)==0){
1272
0
          LM_ERR("duplicated %s [%.*s]\n",
1273
0
            mod_node->name,
1274
0
            modules->module.len,
1275
0
            modules->module.s);
1276
0
          return -1;
1277
0
        }
1278
0
      }
1279
      /* Get cmds */
1280
0
      if(pi_getCmds(_pi_framework_data->pi_db_tables,
1281
0
          _pi_framework_data->pi_db_tables_size,
1282
0
          modules, mod_node)!=0)
1283
0
        return -1;
1284
0
      _pi_framework_data->pi_modules_size++;
1285
0
      LM_DBG("got node %s [%.*s]\n",
1286
0
        mod_node->name,
1287
0
        modules->module.len, modules->module.s);
1288
0
    }
1289
0
  }
1290
0
  if(_pi_framework_data->pi_modules_size==0){
1291
0
    LM_ERR("no %s node in config file\n", PI_XML_MOD_NODE);
1292
0
    return -1;
1293
0
  }
1294
0
  return 0;
1295
0
}
1296
1297
1298
void pi_freeDbUrlNodes(pi_db_url_t **pi_db_urls, int pi_db_urls_size)
1299
0
{
1300
0
  int i;
1301
0
  pi_db_url_t *_pi_db_urls = *pi_db_urls;
1302
1303
0
  if(_pi_db_urls==NULL) return;
1304
0
  for(i=0;i<pi_db_urls_size;i++){
1305
0
    shm_free(_pi_db_urls[i].id.s);
1306
0
    _pi_db_urls[i].id.s = NULL;
1307
0
    shm_free(_pi_db_urls[i].db_url.s);
1308
0
    _pi_db_urls[i].db_url.s = NULL;
1309
0
  }
1310
0
  shm_free(*pi_db_urls); *pi_db_urls = NULL;
1311
0
  return;
1312
0
}
1313
void pi_freeDbTables(pi_db_table_t **pi_db_tables, int pi_db_tables_size)
1314
0
{
1315
0
  int i, j;
1316
0
  pi_db_table_t *_pi_db_tables = *pi_db_tables;
1317
1318
0
  if(_pi_db_tables==NULL) return;
1319
0
  for(i=0;i<pi_db_tables_size;i++){
1320
0
    shm_free(_pi_db_tables[i].id.s);
1321
0
    _pi_db_tables[i].id.s = NULL;
1322
0
    shm_free(_pi_db_tables[i].name.s);
1323
0
    _pi_db_tables[i].name.s = NULL;
1324
0
    shm_free(_pi_db_tables[i].db_url_id.s);
1325
0
    _pi_db_tables[i].db_url_id.s = NULL;
1326
0
    for(j=0;j<_pi_db_tables[i].cols_size;j++){
1327
0
      shm_free(_pi_db_tables[i].cols[j].field.s);
1328
0
      _pi_db_tables[i].cols[j].field.s = NULL;
1329
0
    }
1330
0
    shm_free(_pi_db_tables[i].cols);
1331
0
    _pi_db_tables[i].cols = NULL;
1332
0
  }
1333
0
  shm_free(*pi_db_tables); *pi_db_tables = NULL;
1334
0
  return;
1335
0
}
1336
void pi_freeMods(pi_mod_t **pi_modules, int pi_modules_size)
1337
0
{
1338
0
  int i, j, k;
1339
0
  pi_mod_t *_pi_modules = *pi_modules;
1340
0
  db_key_t *cmd_keys;
1341
0
  db_op_t *cmd_ops;
1342
0
  pi_vals_t *cmd_vals;
1343
0
  str *cmd_linkCmd;
1344
1345
0
  if(_pi_modules==NULL) return;
1346
0
  for(i=0;i<pi_modules_size;i++){
1347
0
    if(_pi_modules[i].module.s){
1348
0
      shm_free(_pi_modules[i].module.s);
1349
0
      _pi_modules[i].module.s = NULL;
1350
0
    }
1351
0
    for(j=0;j<_pi_modules[i].cmds_size;j++){
1352
0
      if(_pi_modules[i].cmds[j].name.s){
1353
0
        shm_free(_pi_modules[i].cmds[j].name.s);
1354
0
        _pi_modules[i].cmds[j].name.s = NULL;
1355
0
      }
1356
      /* */
1357
0
      cmd_keys = _pi_modules[i].cmds[j].c_keys;
1358
0
      cmd_ops = _pi_modules[i].cmds[j].c_ops;
1359
0
      cmd_vals = _pi_modules[i].cmds[j].c_vals;
1360
0
      for(k=0;k<_pi_modules[i].cmds[j].c_keys_size;k++){
1361
0
        if(cmd_ops && cmd_ops[k]){
1362
0
          shm_free((char*)cmd_ops[k]);
1363
0
          cmd_ops[k] = NULL;
1364
0
        }
1365
0
        if(cmd_keys && cmd_keys[k]){
1366
0
          if(cmd_keys[k]->s){
1367
0
            shm_free(cmd_keys[k]->s);
1368
0
            cmd_keys[k]->s = NULL;
1369
0
          }
1370
0
          shm_free(cmd_keys[k]);
1371
0
          cmd_keys[k] = NULL;
1372
0
        }
1373
0
        if(cmd_vals){
1374
0
          if(cmd_vals[k].ids){
1375
0
            if(cmd_vals[k].ids->s){
1376
0
              shm_free(cmd_vals[k].ids->s);
1377
0
              cmd_vals[k].ids->s = NULL;
1378
0
            }
1379
0
            shm_free(cmd_vals[k].ids);
1380
0
            cmd_vals[k].ids = NULL;
1381
0
          }
1382
0
          if(cmd_vals[k].vals){
1383
0
            if(cmd_vals[k].vals->s){
1384
0
              shm_free(cmd_vals[k].vals->s);
1385
0
              cmd_vals[k].vals->s = NULL;
1386
0
            }
1387
0
            shm_free(cmd_vals[k].vals);
1388
0
            cmd_vals[k].vals = NULL;
1389
0
          }
1390
0
        }
1391
0
      }
1392
0
      if(_pi_modules[i].cmds[j].c_keys){
1393
0
        shm_free(_pi_modules[i].cmds[j].c_keys);
1394
0
        _pi_modules[i].cmds[j].c_keys = NULL;
1395
0
      }
1396
0
      if(_pi_modules[i].cmds[j].c_ops){
1397
0
        shm_free(_pi_modules[i].cmds[j].c_ops);
1398
0
        _pi_modules[i].cmds[j].c_ops = NULL;
1399
0
      }
1400
0
      if(_pi_modules[i].cmds[j].c_types){
1401
0
        shm_free(_pi_modules[i].cmds[j].c_types);
1402
0
        _pi_modules[i].cmds[j].c_types = NULL;
1403
0
      }
1404
0
      if(_pi_modules[i].cmds[j].c_vals){
1405
0
        shm_free(_pi_modules[i].cmds[j].c_vals);
1406
0
        _pi_modules[i].cmds[j].c_vals = NULL;
1407
0
      }
1408
      /* */
1409
0
      cmd_keys = _pi_modules[i].cmds[j].q_keys;
1410
0
      cmd_vals = _pi_modules[i].cmds[j].q_vals;
1411
0
      cmd_linkCmd = _pi_modules[i].cmds[j].link_cmd;
1412
0
      for(k=0;k<_pi_modules[i].cmds[j].q_keys_size;k++){
1413
0
        if(cmd_keys && cmd_keys[k]){
1414
0
          if(cmd_keys[k]->s){
1415
0
            shm_free(cmd_keys[k]->s);
1416
0
            cmd_keys[k]->s = NULL;
1417
0
          }
1418
0
          shm_free(cmd_keys[k]);
1419
0
          cmd_keys[k] = NULL;
1420
0
        }
1421
0
        if(cmd_vals){
1422
0
          if(cmd_vals[k].ids){
1423
0
            if(cmd_vals[k].ids->s){
1424
0
              shm_free(cmd_vals[k].ids->s);
1425
0
              cmd_vals[k].ids->s = NULL;
1426
0
            }
1427
0
            shm_free(cmd_vals[k].ids);
1428
0
            cmd_vals[k].ids = NULL;
1429
0
          }
1430
0
          if(cmd_vals[k].vals){
1431
0
            if(cmd_vals[k].vals->s){
1432
0
              shm_free(cmd_vals[k].vals->s);
1433
0
              cmd_vals[k].vals->s = NULL;
1434
0
            }
1435
0
            shm_free(cmd_vals[k].vals);
1436
0
            cmd_vals[k].vals = NULL;
1437
0
          }
1438
0
        }
1439
0
        if(cmd_linkCmd && cmd_linkCmd[k].s){
1440
0
          shm_free(cmd_linkCmd[k].s);
1441
0
          cmd_linkCmd[k].s = NULL;
1442
0
        }
1443
0
      }
1444
0
      if(_pi_modules[i].cmds[j].q_keys){
1445
0
        shm_free(_pi_modules[i].cmds[j].q_keys);
1446
0
        _pi_modules[i].cmds[j].q_keys = NULL;
1447
0
      }
1448
0
      if(_pi_modules[i].cmds[j].q_types){
1449
0
        shm_free(_pi_modules[i].cmds[j].q_types);
1450
0
        _pi_modules[i].cmds[j].q_types = NULL;
1451
0
      }
1452
0
      if(_pi_modules[i].cmds[j].q_vals){
1453
0
        shm_free(_pi_modules[i].cmds[j].q_vals);
1454
0
        _pi_modules[i].cmds[j].q_vals = NULL;
1455
0
      }
1456
0
      if(_pi_modules[i].cmds[j].link_cmd){
1457
0
        shm_free(_pi_modules[i].cmds[j].link_cmd);
1458
0
        _pi_modules[i].cmds[j].link_cmd = NULL;
1459
0
      }
1460
0
      cmd_keys = NULL; cmd_vals = NULL;
1461
      /* */
1462
0
      cmd_keys = _pi_modules[i].cmds[j].c_keys;
1463
0
      for(k=0;k<_pi_modules[i].cmds[j].c_keys_size;k++){
1464
0
        if(cmd_keys && cmd_keys[k]){
1465
0
          if(cmd_keys[k]->s){
1466
0
            shm_free(cmd_keys[k]->s);
1467
0
            cmd_keys[k]->s = NULL;
1468
0
          }
1469
0
          shm_free(cmd_keys[k]);
1470
0
          cmd_keys[k] = NULL;
1471
0
        }
1472
0
      }
1473
0
      if(_pi_modules[i].cmds[j].c_keys){
1474
0
        shm_free(_pi_modules[i].cmds[j].c_keys);
1475
0
        _pi_modules[i].cmds[j].c_keys = NULL;
1476
0
      }
1477
0
      cmd_keys = NULL;
1478
0
    }
1479
0
    if(_pi_modules[i].cmds){
1480
0
      shm_free(_pi_modules[i].cmds);
1481
0
      _pi_modules[i].cmds = NULL;
1482
0
    }
1483
0
  }
1484
0
  if(*pi_modules){
1485
0
    shm_free(*pi_modules); *pi_modules = NULL;
1486
0
  }
1487
0
  return;
1488
0
}
1489
1490
int pi_init_cmds(pi_framework_t **framework_data, const char* filename)
1491
0
{
1492
0
  xmlDocPtr doc;
1493
0
  xmlNodePtr framework_node;
1494
0
  pi_framework_t *_framework_data = NULL;
1495
0
  pi_db_table_t *_pi_db_tables;
1496
0
  int _pi_db_tables_size;
1497
0
  pi_mod_t *_pi_modules;
1498
0
  int _pi_modules_size;
1499
1500
0
  if(filename==NULL) {LM_ERR("NULL filename\n");return -1;}
1501
0
  doc = pi_xml_parse_file(filename);
1502
0
  if(doc==NULL){
1503
0
    LM_ERR("Failed to parse xml file: %s\n", filename);
1504
0
    return -1;
1505
0
  }
1506
1507
  /* Extract the framework node */
1508
0
  framework_node = pi_xml_node_get_node_by_name(doc->children,
1509
0
            PI_XML_FRAMEWORK_NODE);
1510
0
  if (framework_node==NULL) {
1511
0
    LM_ERR("missing node %s\n", PI_XML_FRAMEWORK_NODE);
1512
0
    goto xml_error;
1513
0
  }
1514
1515
0
  _framework_data = *framework_data;
1516
0
  if(_framework_data==NULL){
1517
0
    _framework_data =
1518
0
    (pi_framework_t*)shm_malloc(sizeof(pi_framework_t));
1519
0
    if(_framework_data==NULL) {LM_ERR("oom\n");goto xml_error;}
1520
0
    memset(_framework_data, 0, sizeof(pi_framework_t));
1521
1522
    /* Extract the db_url nodes */
1523
0
    if(pi_getDbUrlNodes(_framework_data, framework_node)!=0)
1524
0
      goto xml_error;
1525
1526
    /* Extract the db_url nodes */
1527
0
    if(pi_getDbTables(_framework_data, framework_node)!=0)
1528
0
      goto xml_error;
1529
1530
    /* Build pi commands skeleton */
1531
0
    if(pi_getMods(_framework_data, framework_node)!=0)
1532
0
      goto xml_error;
1533
1534
0
    if(doc)pi_xml_free(doc);
1535
0
    doc=NULL;
1536
0
    *framework_data = _framework_data;
1537
0
  }else{ /* This is a reload */
1538
0
    _pi_db_tables = _framework_data->pi_db_tables;
1539
0
    _pi_db_tables_size = _framework_data->pi_db_tables_size;
1540
0
    _framework_data->pi_db_tables = NULL;
1541
0
    _framework_data->pi_db_tables_size = 0;
1542
0
    _pi_modules = _framework_data->pi_modules;
1543
0
    _pi_modules_size = _framework_data->pi_modules_size;
1544
0
    _framework_data->pi_modules = NULL;
1545
0
    _framework_data->pi_modules_size = 0;
1546
1547
    /* Extract the db_url nodes */
1548
0
    if(pi_getDbTables(_framework_data, framework_node)!=0)
1549
0
      goto xml_reload_error;
1550
1551
    /* Build pi commands skeleton */
1552
0
    if(pi_getMods(_framework_data, framework_node)!=0)
1553
0
      goto xml_reload_error;
1554
1555
0
    if(doc)pi_xml_free(doc);
1556
0
    doc=NULL;
1557
0
    *framework_data = _framework_data;
1558
1559
0
  }
1560
0
  return 0;
1561
0
xml_error:
1562
  /* FIXME: free thw whole structure */
1563
0
  if(_framework_data){shm_free(_framework_data);}
1564
0
  if(doc)pi_xml_free(doc);
1565
0
  doc=NULL;
1566
0
  return -1;
1567
0
xml_reload_error:
1568
0
  pi_freeDbTables(&_framework_data->pi_db_tables,
1569
0
      _framework_data->pi_db_tables_size);
1570
0
  pi_freeMods(&_framework_data->pi_modules,
1571
0
      _framework_data->pi_modules_size);
1572
0
  _framework_data->pi_db_tables = _pi_db_tables;
1573
0
  _framework_data->pi_db_tables_size = _pi_db_tables_size;
1574
0
  _framework_data->pi_modules = _pi_modules;
1575
0
  _framework_data->pi_modules_size = _pi_modules_size;
1576
0
  if(doc)pi_xml_free(doc);
1577
0
  doc=NULL;
1578
0
  return -1;
1579
0
}
1580
1581
int pi_framework_init(void)
1582
0
{
1583
0
  if (!pi_framework.s)
1584
0
    return 0;
1585
0
  return pi_init_cmds(&pi_framework_data, pi_framework.s);
1586
0
}
1587
1588
static pi_db_url_t *pi_find_db_url(pi_framework_t *framework,
1589
    const str *url)
1590
0
{
1591
0
  int i;
1592
0
  for (i = 0; i < framework->pi_db_urls_size; i++)
1593
0
    if (framework->pi_db_urls[i].db_url.len == url->len &&
1594
0
      !memcmp(framework->pi_db_urls[i].db_url.s, url->s, url->len))
1595
0
      return &framework->pi_db_urls[i];
1596
0
  return NULL;
1597
0
}
1598
1599
static pi_db_url_t *pi_add_module_db_url(pi_framework_t *framework,
1600
    const str *module, const str *url)
1601
0
{
1602
0
  pi_db_url_t *urls, *db_url;
1603
0
  str id;
1604
0
  char *id_buf;
1605
1606
0
  db_url = pi_find_db_url(framework, url);
1607
0
  if (db_url)
1608
0
    return db_url;
1609
0
  urls = shm_realloc(framework->pi_db_urls,
1610
0
      (framework->pi_db_urls_size + 1) * sizeof(*urls));
1611
0
  if (!urls)
1612
0
    return NULL;
1613
0
  framework->pi_db_urls = urls;
1614
0
  db_url = &urls[framework->pi_db_urls_size];
1615
0
  memset(db_url, 0, sizeof(*db_url));
1616
0
  id_buf = shm_malloc(module->len + 8);
1617
0
  if (!id_buf)
1618
0
    return NULL;
1619
0
  memcpy(id_buf, "module:", 7);
1620
0
  memcpy(id_buf + 7, module->s, module->len);
1621
0
  id_buf[module->len + 7] = '\0';
1622
0
  id.s = id_buf;
1623
0
  id.len = module->len + 7;
1624
0
  if (shm_str_dup(&db_url->id, &id) != 0 ||
1625
0
    shm_str_dup(&db_url->db_url, url) != 0) {
1626
0
    shm_free(id_buf);
1627
0
    return NULL;
1628
0
  }
1629
0
  shm_free(id_buf);
1630
0
  framework->pi_db_urls_size++;
1631
0
  return db_url;
1632
0
}
1633
1634
static pi_db_url_t *pi_find_db_url_id(pi_framework_t *framework,
1635
    const str *id)
1636
0
{
1637
0
  int i;
1638
0
  for (i = 0; i < framework->pi_db_urls_size; i++)
1639
0
    if (framework->pi_db_urls[i].id.len == id->len &&
1640
0
      !memcmp(framework->pi_db_urls[i].id.s, id->s, id->len))
1641
0
      return &framework->pi_db_urls[i];
1642
0
  return NULL;
1643
0
}
1644
1645
static int pi_resolve_connectors(pi_framework_t *framework)
1646
0
{
1647
0
  pi_db_url_t *module_url, *table_url;
1648
0
  pi_mod_t *module;
1649
0
  pi_cmd_t *command;
1650
0
  str module_url_str;
1651
0
  char **module_db_url;
1652
0
  int i, j;
1653
1654
0
  for (i = 0; i < framework->pi_modules_size; i++) {
1655
0
    module = &framework->pi_modules[i];
1656
0
    module_url = NULL;
1657
0
    module_db_url = find_param_export(module->module.s, "db_url",
1658
0
        STR_PARAM);
1659
0
    if (module_db_url && *module_db_url && **module_db_url) {
1660
0
      module_url_str.s = *module_db_url;
1661
0
      module_url_str.len = strlen(*module_db_url);
1662
0
      module_url = pi_add_module_db_url(framework, &module->module,
1663
0
          &module_url_str);
1664
0
    } else if (db_default_url) {
1665
0
      module_url_str.s = db_default_url;
1666
0
      module_url_str.len = strlen(db_default_url);
1667
0
      module_url = pi_add_module_db_url(framework, &module->module,
1668
0
          &module_url_str);
1669
0
    }
1670
1671
0
    for (j = 0; j < module->cmds_size; j++) {
1672
0
      command = &module->cmds[j];
1673
0
      if (command->db_table->db_url_id.len) {
1674
0
        table_url = pi_find_db_url_id(framework,
1675
0
            &command->db_table->db_url_id);
1676
0
        if (!table_url) {
1677
0
          LM_ERR("unknown database connector id [%.*s] for table [%.*s]\n",
1678
0
            command->db_table->db_url_id.len,
1679
0
            command->db_table->db_url_id.s,
1680
0
            command->db_table->id.len,
1681
0
            command->db_table->id.s);
1682
0
          return -1;
1683
0
        }
1684
0
      } else
1685
0
        table_url = module_url;
1686
0
      if (!table_url) {
1687
0
        LM_ERR("no database connector for module [%.*s], table [%.*s]; "
1688
0
          "set db_url_id in the PI XML or configure the module db_url\n",
1689
0
          module->module.len, module->module.s,
1690
0
          command->db_table->id.len, command->db_table->id.s);
1691
0
        return -1;
1692
0
      }
1693
0
      if (command->db_table->db_url &&
1694
0
        command->db_table->db_url != table_url) {
1695
0
        LM_ERR("table [%.*s] is used with multiple database connectors; "
1696
0
          "set an explicit db_url_id in the PI XML\n",
1697
0
          command->db_table->id.len, command->db_table->id.s);
1698
0
        return -1;
1699
0
      }
1700
0
      command->db_table->db_url = table_url;
1701
0
    }
1702
0
  }
1703
0
  return 0;
1704
0
}
1705
1706
int pi_framework_init_db(void)
1707
0
{
1708
0
  int i;
1709
0
  if (!pi_framework_data)
1710
0
    return 0;
1711
0
  if (pi_resolve_connectors(pi_framework_data) < 0)
1712
0
    return -1;
1713
0
  for (i = 0; i < pi_framework_data->pi_db_urls_size; i++) {
1714
0
    pi_framework_data->pi_db_urls[i].db_handle =
1715
0
        pkg_malloc(sizeof(db_con_t *));
1716
0
    if (!pi_framework_data->pi_db_urls[i].db_handle)
1717
0
      return -1;
1718
0
    *pi_framework_data->pi_db_urls[i].db_handle = NULL;
1719
0
    if (pi_init_db(pi_framework_data, i) < 0)
1720
0
      return -1;
1721
0
  }
1722
0
  return 0;
1723
0
}
1724
1725
int pi_framework_child_init(void)
1726
0
{
1727
0
  int i;
1728
0
  if (!pi_framework_data)
1729
0
    return 0;
1730
0
  for (i = 0; i < pi_framework_data->pi_db_urls_size; i++)
1731
0
    if (pi_connect_db(pi_framework_data, i) < 0)
1732
0
      return -1;
1733
0
  return 0;
1734
0
}
1735
1736
void pi_framework_destroy_db(void)
1737
0
{
1738
0
  int i;
1739
0
  if (!pi_framework_data)
1740
0
    return;
1741
0
  for (i = 0; i < pi_framework_data->pi_db_urls_size; i++) {
1742
0
    if (!pi_framework_data->pi_db_urls[i].db_handle)
1743
0
      continue;
1744
0
    if (*pi_framework_data->pi_db_urls[i].db_handle)
1745
0
      pi_framework_data->pi_db_urls[i].dbf.close(
1746
0
          *pi_framework_data->pi_db_urls[i].db_handle);
1747
0
    pkg_free(pi_framework_data->pi_db_urls[i].db_handle);
1748
0
    pi_framework_data->pi_db_urls[i].db_handle = NULL;
1749
0
  }
1750
0
}
1751
1752
1753
1754
int pi_parse_url(const char* url, int* mod, int* cmd)
1755
0
{
1756
0
  int url_len = strlen(url);
1757
0
  int index = 0;
1758
0
  int i;
1759
0
  int mod_len, cmd_len;
1760
0
  pi_mod_t *pi_modules = pi_framework_data->pi_modules;
1761
1762
1763
0
  if (url_len<0) {
1764
0
    LM_ERR("Invalid url length [%d]\n", url_len);
1765
0
    return -1;
1766
0
  }
1767
0
  if (url_len==0) return 0;
1768
0
  if (url[0] != '/') {
1769
0
    LM_ERR("URL starting with [%c] instead of'/'\n", *url);
1770
0
    return -1;
1771
0
  }
1772
0
  index++;
1773
1774
  /* Looking for "mod" */
1775
0
  if (index>=url_len)
1776
0
    return 0;
1777
0
  for(i=index;i<url_len && url[i]!='/';i++);
1778
0
  mod_len = i - index;
1779
0
  for(i=0;i<pi_framework_data->pi_modules_size &&
1780
0
    (mod_len!=pi_modules[i].module.len ||
1781
0
    strncmp(&url[index], pi_modules[i].module.s,mod_len)!=0);i++);
1782
0
  if (i==pi_framework_data->pi_modules_size) {
1783
0
    LM_ERR("Invalid mod [%.*s] in url [%s]\n",
1784
0
      mod_len, &url[index], url);
1785
0
    return -1;
1786
0
  }
1787
0
  *mod = i;
1788
0
  LM_DBG("got mod [%d][%.*s]\n", *mod, mod_len, &url[index]);
1789
1790
0
  index += mod_len;
1791
0
  LM_DBG("index=%d url_len=%d\n", index, url_len);
1792
0
  if (index>=url_len)
1793
0
    return 0;
1794
1795
  /* skip over '/' */
1796
0
  index++;
1797
1798
  /* Looking for "cmd" */
1799
0
  if (index>=url_len)
1800
0
    return 0;
1801
0
  for(i=index;i<url_len && url[i]!='/';i++);
1802
0
  cmd_len = i - index;
1803
0
  for(i=0;i<pi_modules[*mod].cmds_size &&
1804
0
    (cmd_len!=pi_modules[*mod].cmds[i].name.len ||
1805
0
    strncmp(&url[index], pi_modules[*mod].cmds[i].name.s, cmd_len)!=0);
1806
0
    i++);
1807
0
  if (i==pi_modules[*mod].cmds_size) {
1808
0
    LM_ERR("Invalid cmd [%.*s] in url [%s]\n",
1809
0
      cmd_len, &url[index], url);
1810
0
    return -1;
1811
0
  }
1812
0
  *cmd = i;
1813
0
  LM_DBG("got cmd [%d][%.*s]\n", *cmd, cmd_len, &url[index]);
1814
0
  index += cmd_len;
1815
0
  if (index>=url_len)
1816
0
    return 0;
1817
  /* skip over '/' */
1818
0
  index++;
1819
0
  if (url_len - index>0) {
1820
0
    LM_DBG("got extra [%s]\n", &url[index]);
1821
0
  }
1822
1823
0
  return 0;
1824
0
}