Browse code

textopsx: added body line iterator functions

- iterate through lines of message body, get the value via
$blitval(iname)

Daniel-Constantin Mierla authored on 30/07/2021 10:24:02
Showing 2 changed files
... ...
@@ -512,7 +512,7 @@ hf_iterator_start("i1");
512 512
 		</title>
513 513
 		<para>
514 514
 			Close the iterator identified by iname parameter. The iname value
515
-			must be the same used for sht_iterator_start().
515
+			must be the same used for hf_iterator_start().
516 516
 		</para>
517 517
 		<para>
518 518
 			The parameter can be dynamic string with variables.
... ...
@@ -535,7 +535,7 @@ hf_iterator_end("i1");
535 535
 		</title>
536 536
 		<para>
537 537
 			Move the iterator to the next header. It must
538
-			be called also after sht_iterator_start() to get the first
538
+			be called also after bl_iterator_start() to get the first
539 539
 			header.
540 540
 		</para>
541 541
 		<para>
... ...
@@ -570,7 +570,7 @@ hf_iterator_end("i1");
570 570
 		</title>
571 571
 		<para>
572 572
 			Move the iterator to the previous header. It must
573
-			be called also after sht_iterator_start() and sht_iterator_next().
573
+			be called also after hf_iterator_start() and hf_iterator_next().
574 574
 		</para>
575 575
 		<para>
576 576
 			The parameter can be dynamic string with variables.
... ...
@@ -677,6 +677,116 @@ hf_iterator_end("i1");
677 677
     }
678 678
     hf_iterator_end("i1");
679 679
 ...
680
+</programlisting>
681
+		</example>
682
+	</section>
683
+	<section id="textopsx.f.bl_iterator_start">
684
+		<title>
685
+		<function moreinfo="none">bl_iterator_start(iname)</function>
686
+		</title>
687
+		<para>
688
+			Start an iterator for lines in the body of the current SIP message.
689
+			The parameter iname is used to identify the iterator. There
690
+			can be up to 4 iterators at the same time, with different name.
691
+		</para>
692
+		<para>
693
+			The parameter can be a dynamic string with variables.
694
+		</para>
695
+		<para>
696
+			This function can be used from ANY_ROUTE.
697
+		</para>
698
+		<example>
699
+		<title><function>bl_iterator_start</function> usage</title>
700
+		<programlisting format="linespecific">
701
+...
702
+bl_iterator_start("b1");
703
+...
704
+</programlisting>
705
+		</example>
706
+	</section>
707
+	<section id="textopsx.f.bl_iterator_end">
708
+		<title>
709
+		<function moreinfo="none">bl_iterator_end(iname)</function>
710
+		</title>
711
+		<para>
712
+			Close the iterator identified by iname parameter. The iname value
713
+			must be the same used for bl_iterator_start().
714
+		</para>
715
+		<para>
716
+			The parameter can be dynamic string with variables.
717
+		</para>
718
+		<para>
719
+			This function can be used from ANY_ROUTE.
720
+		</para>
721
+		<example>
722
+		<title><function>bl_iterator_end</function> usage</title>
723
+		<programlisting format="linespecific">
724
+...
725
+bl_iterator_end("b1");
726
+...
727
+</programlisting>
728
+		</example>
729
+	</section>
730
+	<section id="textopsx.f.bl_iterator_next">
731
+		<title>
732
+		<function moreinfo="none">textopsx.f.bl_iterator_next(iname)</function>
733
+		</title>
734
+		<para>
735
+			Move the iterator to the next line in the body. It must
736
+			be called also after bl_iterator_start() to get the first
737
+			header.
738
+		</para>
739
+		<para>
740
+			The return code is false when there is no other header in the list.
741
+		</para>
742
+		<para>
743
+			The body line accessible via variable $blitval(iname) - it contains
744
+			also the EOL chars.
745
+		</para>
746
+		<para>
747
+			The parameter can be dynamic string with variables.
748
+		</para>
749
+		<para>
750
+			This function can be used from ANY_ROUTE.
751
+		</para>
752
+		<example>
753
+		<title><function>bl_iterator_next</function> usage</title>
754
+		<programlisting format="linespecific">
755
+...
756
+    bl_iterator_start("b1");
757
+    while(hf_iterator_next("b1")) {
758
+        xlog("body line: hdr[$hfitname(b1)]\n");
759
+    }
760
+    bl_iterator_end("b1");
761
+...
762
+</programlisting>
763
+		</example>
764
+	</section>
765
+	<section id="textopsx.f.bl_iterator_rm">
766
+		<title>
767
+		<function moreinfo="none">bl_iterator_rm(iname)</function>
768
+		</title>
769
+		<para>
770
+			Remove the body line at the current iterator position.
771
+		</para>
772
+		<para>
773
+			The parameter can be dynamic string with variables.
774
+		</para>
775
+		<para>
776
+			This function can be used from ANY_ROUTE.
777
+		</para>
778
+		<example>
779
+		<title><function>bl_iterator_rm</function> usage</title>
780
+		<programlisting format="linespecific">
781
+...
782
+    bl_iterator_start("b1");
783
+    while(bl_iterator_next("b1")) {
784
+        if($blitval(b1)=~"abc") {
785
+            bl_iterator_rm("b1");
786
+        }
787
+    }
788
+    bl_iterator_end("b1");
789
+...
680 790
 </programlisting>
681 791
 		</example>
682 792
 	</section>
... ...
@@ -81,24 +81,36 @@ static int w_hf_iterator_rm(sip_msg_t *msg, char *piname, char *p2);
81 81
 static int w_hf_iterator_append(sip_msg_t *msg, char *piname, char *phtext);
82 82
 static int w_hf_iterator_insert(sip_msg_t *msg, char *piname, char *phtext);
83 83
 
84
+static int w_bl_iterator_start(sip_msg_t *msg, char *piname, char *p2);
85
+static int w_bl_iterator_next(sip_msg_t *msg, char *piname, char *p2);
86
+static int w_bl_iterator_end(sip_msg_t *msg, char *piname, char *p2);
87
+static int w_bl_iterator_rm(sip_msg_t *msg, char *piname, char *p2);
88
+
84 89
 static int bind_textopsx(textopsx_api_t *tob);
85 90
 
86 91
 static int mod_init(void);
87 92
 
88 93
 extern select_row_t sel_declaration[];
89 94
 
90
-void hf_iterator_init(void);
95
+static void hf_iterator_init(void);
91 96
 static int pv_parse_hf_iterator_name(pv_spec_t *sp, str *in);
92 97
 static int pv_get_hf_iterator_hname(sip_msg_t *msg, pv_param_t *param,
93 98
 		pv_value_t *res);
94 99
 static int pv_get_hf_iterator_hbody(sip_msg_t *msg, pv_param_t *param,
95 100
 		pv_value_t *res);
96 101
 
102
+static void bl_iterator_init(void);
103
+static int pv_parse_bl_iterator_name(pv_spec_t *sp, str *in);
104
+static int pv_get_bl_iterator_value(sip_msg_t *msg, pv_param_t *param,
105
+		pv_value_t *res);
106
+
97 107
 static pv_export_t mod_pvs[] = {
98 108
 	{ {"hfitname", sizeof("hfitname")-1}, PVT_OTHER, pv_get_hf_iterator_hname, 0,
99 109
 		pv_parse_hf_iterator_name, 0, 0, 0 },
100 110
 	{ {"hfitbody", sizeof("hfitbody")-1}, PVT_OTHER, pv_get_hf_iterator_hbody, 0,
101 111
 		pv_parse_hf_iterator_name, 0, 0, 0 },
112
+	{ {"blitval", sizeof("blitval")-1}, PVT_OTHER, pv_get_bl_iterator_value, 0,
113
+		pv_parse_bl_iterator_name, 0, 0, 0 },
102 114
 	{ {0, 0}, 0, 0, 0, 0, 0, 0, 0 }
103 115
 };
104 116
 
... ...
@@ -148,6 +160,14 @@ static cmd_export_t cmds[] = {
148 160
 			fixup_free_spve_spve, ANY_ROUTE},
149 161
 	{"hf_iterator_insert", w_hf_iterator_insert, 2, fixup_spve_spve,
150 162
 			fixup_free_spve_spve, ANY_ROUTE},
163
+	{"bl_iterator_start", w_bl_iterator_start, 1, fixup_spve_null,
164
+			fixup_free_spve_null, ANY_ROUTE},
165
+	{"bl_iterator_next", w_bl_iterator_next, 1, fixup_spve_null,
166
+			fixup_free_spve_null, ANY_ROUTE},
167
+	{"bl_iterator_end", w_bl_iterator_end, 1, fixup_spve_null,
168
+			fixup_free_spve_null, ANY_ROUTE},
169
+	{"bl_iterator_rm", w_bl_iterator_rm, 1, fixup_spve_null,
170
+			fixup_free_spve_null, ANY_ROUTE},
151 171
 
152 172
 	{"bind_textopsx", (cmd_function)bind_textopsx, 1, 0, 0, ANY_ROUTE},
153 173
 
... ...
@@ -180,6 +200,7 @@ static int mod_init(void)
180 200
 #endif
181 201
 	register_select_table(sel_declaration);
182 202
 	hf_iterator_init();
203
+	bl_iterator_init();
183 204
 
184 205
 	return 0;
185 206
 }
... ...
@@ -1848,7 +1869,7 @@ static hf_iterator_t _hf_iterators[HF_ITERATOR_SIZE];
1848 1869
 /**
1849 1870
  *
1850 1871
  */
1851
-void hf_iterator_init(void)
1872
+static void hf_iterator_init(void)
1852 1873
 {
1853 1874
 	memset(_hf_iterators, 0, HF_ITERATOR_SIZE*sizeof(hf_iterator_t));
1854 1875
 }
... ...
@@ -2008,7 +2029,7 @@ static int ki_hf_iterator_prev(sip_msg_t *msg, str *iname)
2008 2029
 			if(hf->next->next) {
2009 2030
 				if(_hf_iterators[k].it==hf->next->next) {
2010 2031
 					_hf_iterators[k].it = hf->next;
2011
-					_hf_iterators[k].prev = it;
2032
+					_hf_iterators[k].prev = hf;
2012 2033
 					return 1;
2013 2034
 				}
2014 2035
 			} else {
... ...
@@ -2329,6 +2350,303 @@ static int pv_get_hf_iterator_hbody(sip_msg_t *msg, pv_param_t *param, pv_value_
2329 2350
 	return pv_get_strval(msg, param, res, &_hf_iterators[i].it->body);
2330 2351
 }
2331 2352
 
2353
+
2354
+/*** body line iterator */
2355
+#define BL_ITERATOR_SIZE	4
2356
+#define BL_ITERATOR_NAME_SIZE	32
2357
+
2358
+typedef struct bl_iterator {
2359
+	str name;
2360
+	char bname[HF_ITERATOR_NAME_SIZE];
2361
+	str body;
2362
+	str it;
2363
+	int eob;
2364
+} bl_iterator_t;
2365
+
2366
+static bl_iterator_t _bl_iterators[BL_ITERATOR_SIZE];
2367
+
2368
+/**
2369
+ *
2370
+ */
2371
+static void bl_iterator_init(void)
2372
+{
2373
+	memset(_bl_iterators, 0, BL_ITERATOR_SIZE*sizeof(bl_iterator_t));
2374
+}
2375
+
2376
+/**
2377
+ *
2378
+ */
2379
+static int ki_bl_iterator_start(sip_msg_t *msg, str *iname)
2380
+{
2381
+	int i;
2382
+	int k;
2383
+
2384
+	k = -1;
2385
+	for(i=0; i<BL_ITERATOR_SIZE; i++) {
2386
+		if(_bl_iterators[i].name.len>0) {
2387
+			if(_bl_iterators[i].name.len==iname->len
2388
+					&& strncmp(_bl_iterators[i].name.s, iname->s, iname->len)==0) {
2389
+				k = i;
2390
+				break;
2391
+			}
2392
+		} else {
2393
+			if(k==-1) k = i;
2394
+		}
2395
+	}
2396
+	if(k==-1) {
2397
+		LM_ERR("no iterator available - max number is %d\n", BL_ITERATOR_SIZE);
2398
+		return -1;
2399
+	}
2400
+	if(_bl_iterators[k].name.len<=0) {
2401
+		if(iname->len>=BL_ITERATOR_NAME_SIZE) {
2402
+			LM_ERR("iterator name is too big [%.*s] (max %d)\n",
2403
+					iname->len, iname->s, BL_ITERATOR_NAME_SIZE);
2404
+			return -1;
2405
+		}
2406
+		strncpy(_bl_iterators[k].bname, iname->s, iname->len);
2407
+		_bl_iterators[k].bname[iname->len] = '\0';
2408
+		_bl_iterators[k].name.len = iname->len;
2409
+		_bl_iterators[k].name.s = _bl_iterators[k].bname;
2410
+	}
2411
+	_bl_iterators[k].it.s = NULL;
2412
+	_bl_iterators[k].it.len = 0;
2413
+	_bl_iterators[k].eob = 0;
2414
+	_bl_iterators[k].body.s = get_body(msg);
2415
+	if(_bl_iterators[k].body.s==NULL) {
2416
+		LM_DBG("no message body\n");
2417
+		return -1;
2418
+	}
2419
+	_bl_iterators[k].body.len = msg->buf + msg->len - _bl_iterators[k].body.s;
2420
+	return 1;
2421
+}
2422
+
2423
+/**
2424
+ *
2425
+ */
2426
+static int w_bl_iterator_start(sip_msg_t *msg, char *piname, char *p2)
2427
+{
2428
+	str iname = STR_NULL;
2429
+	if(fixup_get_svalue(msg, (gparam_t*)piname, &iname)<0) {
2430
+		LM_ERR("failed to get iterator name\n");
2431
+		return -1;
2432
+	}
2433
+	return ki_bl_iterator_start(msg, &iname);
2434
+}
2435
+
2436
+/**
2437
+ *
2438
+ */
2439
+static int ki_bl_iterator_next(sip_msg_t *msg, str *iname)
2440
+{
2441
+	int i;
2442
+	int k;
2443
+	char *p;
2444
+
2445
+	k = -1;
2446
+	for(i=0; i<BL_ITERATOR_SIZE; i++) {
2447
+		if(_bl_iterators[i].name.len>0) {
2448
+			if(_bl_iterators[i].name.len==iname->len
2449
+					&& strncmp(_bl_iterators[i].name.s, iname->s, iname->len)==0) {
2450
+				k = i;
2451
+				break;
2452
+			}
2453
+		}
2454
+	}
2455
+	if(k==-1) {
2456
+		LM_ERR("iterator not available [%.*s]\n", iname->len, iname->s);
2457
+		return -1;
2458
+	}
2459
+	if(_bl_iterators[k].eob == 1) {
2460
+		return -1;
2461
+	}
2462
+
2463
+	if(_bl_iterators[k].it.s==NULL) {
2464
+		_bl_iterators[k].it.s = _bl_iterators[k].body.s;
2465
+	}
2466
+	p = _bl_iterators[k].it.s + _bl_iterators[k].it.len;
2467
+	if(p>=_bl_iterators[k].body.s + _bl_iterators[k].body.len) {
2468
+		_bl_iterators[k].it.s = NULL;
2469
+		_bl_iterators[k].it.len = 0;
2470
+		_bl_iterators[k].eob = 1;
2471
+		return -1;
2472
+	}
2473
+	_bl_iterators[k].it.s = p;
2474
+	while(p < _bl_iterators[k].body.s + _bl_iterators[k].body.len) {
2475
+		if(*p=='\n') {
2476
+			break;
2477
+		}
2478
+		p++;
2479
+	}
2480
+	_bl_iterators[k].it.len = p - _bl_iterators[k].it.s + 1;
2481
+
2482
+	return 1;
2483
+}
2484
+
2485
+/**
2486
+ *
2487
+ */
2488
+static int w_bl_iterator_next(sip_msg_t *msg, char *piname, char *p2)
2489
+{
2490
+	str iname = STR_NULL;
2491
+	if(fixup_get_svalue(msg, (gparam_t*)piname, &iname)<0) {
2492
+		LM_ERR("failed to get iterator name\n");
2493
+		return -1;
2494
+	}
2495
+	return ki_bl_iterator_next(msg, &iname);
2496
+}
2497
+
2498
+/**
2499
+ *
2500
+ */
2501
+static int ki_bl_iterator_end(sip_msg_t *msg, str *iname)
2502
+{
2503
+	int i;
2504
+	int k;
2505
+
2506
+	k = -1;
2507
+	for(i=0; i<BL_ITERATOR_SIZE; i++) {
2508
+		if(_bl_iterators[i].name.len>0) {
2509
+			if(_bl_iterators[i].name.len==iname->len
2510
+					&& strncmp(_bl_iterators[i].name.s, iname->s, iname->len)==0) {
2511
+				k = i;
2512
+				break;
2513
+			}
2514
+		}
2515
+	}
2516
+	if(k==-1) {
2517
+		LM_ERR("iterator not available [%.*s]\n", iname->len, iname->s);
2518
+		return -1;
2519
+	}
2520
+	_bl_iterators[k].it.s = NULL;
2521
+	_bl_iterators[k].it.len = 0;
2522
+	_bl_iterators[k].body.s = NULL;
2523
+	_bl_iterators[k].body.len = 0;
2524
+	_bl_iterators[k].eob = 0;
2525
+	return 1;
2526
+}
2527
+
2528
+/**
2529
+ *
2530
+ */
2531
+static int w_bl_iterator_end(sip_msg_t *msg, char *piname, char *p2)
2532
+{
2533
+	str iname = STR_NULL;
2534
+	if(fixup_get_svalue(msg, (gparam_t*)piname, &iname)<0) {
2535
+		LM_ERR("failed to get iterator name\n");
2536
+		return -1;
2537
+	}
2538
+	return ki_bl_iterator_end(msg, &iname);
2539
+}
2540
+
2541
+/**
2542
+ *
2543
+ */
2544
+static int ki_bl_iterator_index(sip_msg_t *msg, str *iname)
2545
+{
2546
+	int i;
2547
+	int k;
2548
+
2549
+	k = -1;
2550
+	for(i=0; i<BL_ITERATOR_SIZE; i++) {
2551
+		if(_bl_iterators[i].name.len>0) {
2552
+			if(_bl_iterators[i].name.len==iname->len
2553
+					&& strncmp(_bl_iterators[i].name.s, iname->s, iname->len)==0) {
2554
+				k = i;
2555
+				break;
2556
+			}
2557
+		}
2558
+	}
2559
+	if(k==-1) {
2560
+		LM_ERR("iterator not available [%.*s]\n", iname->len, iname->s);
2561
+		return -1;
2562
+	}
2563
+
2564
+	return k;
2565
+}
2566
+
2567
+/**
2568
+ *
2569
+ */
2570
+static int ki_bl_iterator_rm(sip_msg_t *msg, str *iname)
2571
+{
2572
+	int k;
2573
+	sr_lump_t *anchor;
2574
+
2575
+	k = ki_bl_iterator_index(msg, iname);
2576
+	if(k<0 || _bl_iterators[k].it.s==NULL || _bl_iterators[k].it.len<=0) {
2577
+		return -1;
2578
+	}
2579
+	anchor = del_lump(msg, _bl_iterators[k].it.s - msg->buf,
2580
+			_bl_iterators[k].it.len, 0);
2581
+	if (anchor==0) {
2582
+		LM_ERR("cannot remove line %.*s\n", _bl_iterators[k].it.len,
2583
+				_bl_iterators[k].it.s);
2584
+		return -1;
2585
+	}
2586
+	return 1;
2587
+}
2588
+
2589
+/**
2590
+ *
2591
+ */
2592
+static int w_bl_iterator_rm(sip_msg_t *msg, char *piname, char *p2)
2593
+{
2594
+	str iname = STR_NULL;
2595
+	if(fixup_get_svalue(msg, (gparam_t*)piname, &iname)<0) {
2596
+		LM_ERR("failed to get iterator name\n");
2597
+		return -1;
2598
+	}
2599
+	return ki_bl_iterator_rm(msg, &iname);
2600
+}
2601
+
2602
+/**
2603
+ *
2604
+ */
2605
+static int pv_parse_bl_iterator_name(pv_spec_t *sp, str *in)
2606
+{
2607
+	if(in->len<=0) {
2608
+		return -1;
2609
+	}
2610
+
2611
+	sp->pvp.pvn.u.isname.name.s.s = in->s;
2612
+	sp->pvp.pvn.u.isname.name.s.len = in->len;
2613
+	sp->pvp.pvn.u.isname.type = 0;
2614
+	sp->pvp.pvn.type = PV_NAME_INTSTR;
2615
+
2616
+	return 0;
2617
+}
2618
+
2619
+/**
2620
+ *
2621
+ */
2622
+static int pv_get_bl_iterator_value(sip_msg_t *msg, pv_param_t *param, pv_value_t *res)
2623
+{
2624
+	int i;
2625
+	int k;
2626
+	str *iname;
2627
+
2628
+	iname = &param->pvn.u.isname.name.s;
2629
+	k = -1;
2630
+	for(i=0; i<BL_ITERATOR_SIZE; i++) {
2631
+		if(_bl_iterators[i].name.len>0) {
2632
+			if(_bl_iterators[i].name.len==iname->len
2633
+					&& strncmp(_bl_iterators[i].name.s, iname->s, iname->len)==0) {
2634
+				k = i;
2635
+				break;
2636
+			}
2637
+		}
2638
+	}
2639
+	if(k==-1) {
2640
+		LM_ERR("iterator not available [%.*s]\n", iname->len, iname->s);
2641
+		return pv_get_null(msg, param, res);
2642
+	}
2643
+
2644
+	if(_bl_iterators[i].it.s==NULL) {
2645
+		return pv_get_null(msg, param, res);
2646
+	}
2647
+	return pv_get_strval(msg, param, res, &_bl_iterators[i].it);
2648
+}
2649
+
2332 2650
 /* select implementation */
2333 2651
 static int sel_hf_value(str *res, select_t *s, struct sip_msg *msg)
2334 2652
 { /* dummy */
... ...
@@ -2883,6 +3201,26 @@ static sr_kemi_t sr_kemi_textopsx_exports[] = {
2883 3201
 		{ SR_KEMIP_STR, SR_KEMIP_STR, SR_KEMIP_NONE,
2884 3202
 			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
2885 3203
 	},
3204
+	{ str_init("textopsx"), str_init("bl_iterator_start"),
3205
+		SR_KEMIP_INT, ki_bl_iterator_start,
3206
+		{ SR_KEMIP_STR, SR_KEMIP_NONE, SR_KEMIP_NONE,
3207
+			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
3208
+	},
3209
+	{ str_init("textopsx"), str_init("bl_iterator_end"),
3210
+		SR_KEMIP_INT, ki_bl_iterator_end,
3211
+		{ SR_KEMIP_STR, SR_KEMIP_NONE, SR_KEMIP_NONE,
3212
+			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
3213
+	},
3214
+	{ str_init("textopsx"), str_init("bl_iterator_next"),
3215
+		SR_KEMIP_INT, ki_bl_iterator_next,
3216
+		{ SR_KEMIP_STR, SR_KEMIP_NONE, SR_KEMIP_NONE,
3217
+			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
3218
+	},
3219
+	{ str_init("textopsx"), str_init("bl_iterator_rm"),
3220
+		SR_KEMIP_INT, ki_bl_iterator_rm,
3221
+		{ SR_KEMIP_STR, SR_KEMIP_NONE, SR_KEMIP_NONE,
3222
+			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
3223
+	},
2886 3224
 
2887 3225
 	{ {0, 0}, {0, 0}, 0, NULL, { 0, 0, 0, 0, 0, 0 } }
2888 3226
 };