Browse code

posops: function to get the position of a regexp match

Daniel-Constantin Mierla authored on 27/09/2021 10:35:47
Showing 2 changed files
... ...
@@ -347,6 +347,35 @@ $var(idx) = pos_rfind_str("100", "kamailio");
347 347
 				<programlisting format="linespecific">
348 348
 ...
349 349
 $var(idx) = pos_rfindi_str("100", "kamailio");
350
+...
351
+				</programlisting>
352
+			</example>
353
+		</section>
354
+		<section id="posops.f.pos_search">
355
+			<title>
356
+				<function moreinfo="none">pos_search(idx, re)</function>
357
+			</title>
358
+			<para>
359
+			Return the position that starts matching the regular expression re
360
+			in message buffer starting at idx. In case of not finding it or error,
361
+			the return code is negative. If val is at index 0, it returns the
362
+			value specified by modparam idx0.
363
+			</para>
364
+			<para>
365
+			The idx can be an integer value or a variable holding an integer. If
366
+			the value is negative, the position is counted from the end of the buffer.
367
+			</para>
368
+			<para>
369
+			The re can be a static regular expression string.
370
+			</para>
371
+			<para>
372
+			This function can be used from ANY_ROUTE.
373
+			</para>
374
+			<example>
375
+				<title><function>pos_search()</function> usage</title>
376
+				<programlisting format="linespecific">
377
+...
378
+$var(idx) = pos_search("100", "[0-9]+");
350 379
 ...
351 380
 				</programlisting>
352 381
 			</example>
... ...
@@ -49,6 +49,7 @@ static int w_posops_pos_find_str(sip_msg_t* msg, char* p1idx, char* p2val);
49 49
 static int w_posops_pos_findi_str(sip_msg_t* msg, char* p1idx, char* p2val);
50 50
 static int w_posops_pos_rfind_str(sip_msg_t* msg, char* p1idx, char* p2val);
51 51
 static int w_posops_pos_rfindi_str(sip_msg_t* msg, char* p1idx, char* p2val);
52
+static int w_posops_pos_search(sip_msg_t* msg, char* p1idx, char* p2re);
52 53
 
53 54
 typedef struct posops_data {
54 55
 	int ret;
... ...
@@ -96,6 +97,8 @@ static cmd_export_t cmds[]={
96 97
 		fixup_free_igp_spve, ANY_ROUTE},
97 98
 	{"pos_rfindi_str", (cmd_function)w_posops_pos_rfindi_str, 2, fixup_igp_spve,
98 99
 		fixup_free_igp_spve, ANY_ROUTE},
100
+	{"pos_search",    (cmd_function)w_posops_pos_search, 2, fixup_igp_regexp,
101
+		fixup_free_igp_regexp, ANY_ROUTE},
99 102
 
100 103
 	{0, 0, 0, 0, 0, 0}
101 104
 };
... ...
@@ -633,6 +636,68 @@ static int w_posops_pos_rfindi_str(sip_msg_t* msg, char* p1idx, char* p2val)
633 636
 	return ki_posops_pos_rfindi_str(msg, idx, &val);
634 637
 }
635 638
 
639
+/**
640
+ *
641
+ */
642
+static int ki_posops_pos_search_helper(sip_msg_t *msg, int idx, regex_t *re)
643
+{
644
+	regmatch_t pmatch;
645
+
646
+	if(idx<0) {
647
+		idx += msg->len;
648
+	}
649
+	if(idx<0 || idx >= msg->len) {
650
+		return -1;
651
+	}
652
+
653
+	if (regexec(re, msg->buf + idx, 1, &pmatch, 0)!=0) {
654
+		return -1;
655
+	}
656
+	if (pmatch.rm_so==-1) {
657
+		return -1;
658
+	}
659
+
660
+	_posops_data.idx = (int)(msg->buf + idx + pmatch.rm_so);
661
+	_posops_data.ret = (_posops_data.idx==0)?posops_idx0:_posops_data.idx;
662
+
663
+	return _posops_data.ret;
664
+}
665
+
666
+static int ki_posops_pos_search(sip_msg_t* msg, int idx, str* sre)
667
+{
668
+	regex_t mre;
669
+	int ret;
670
+
671
+	memset(&mre, 0, sizeof(regex_t));
672
+	if (regcomp(&mre, sre->s, REG_EXTENDED|REG_ICASE|REG_NEWLINE)!=0) {
673
+		LM_ERR("failed to compile regex: %.*s\n", sre->len, sre->s);
674
+		return -1;
675
+	}
676
+
677
+	ret = ki_posops_pos_search_helper(msg, idx, &mre);
678
+
679
+	regfree(&mre);
680
+
681
+	return ret;
682
+}
683
+
684
+/**
685
+ *
686
+ */
687
+static int w_posops_pos_search(sip_msg_t* msg, char* p1idx, char* p2re)
688
+{
689
+	int idx = 0;
690
+	regex_t *re = NULL;
691
+
692
+	if(fixup_get_ivalue(msg, (gparam_t*)p1idx, &idx)!=0) {
693
+		LM_ERR("unable to get idx parameter\n");
694
+		return -1;
695
+	}
696
+	re = (regex_t*)p2re;
697
+
698
+	return ki_posops_pos_search_helper(msg, idx, re);
699
+}
700
+
636 701
 /**
637 702
  *
638 703
  */
... ...
@@ -735,6 +800,11 @@ static sr_kemi_t sr_kemi_posops_exports[] = {
735 800
 		{ SR_KEMIP_INT, SR_KEMIP_STR, SR_KEMIP_NONE,
736 801
 			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
737 802
 	},
803
+	{ str_init("posops"), str_init("pos_search"),
804
+		SR_KEMIP_INT, ki_posops_pos_search,
805
+		{ SR_KEMIP_INT, SR_KEMIP_STR, SR_KEMIP_NONE,
806
+			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
807
+	},
738 808
 
739 809
 	{ {0, 0}, {0, 0}, 0, NULL, { 0, 0, 0, 0, 0, 0 } }
740 810
 };