You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
asterisk-voicemail/debian/patches/sipwise_vm_add_pcre_support...

286 lines
9.1 KiB

From: Sipwise Development Team <support@sipwise.com>
Date: Mon, 4 Nov 2024 15:37:29 +0100
Subject: sipwise_vm_add_pcre_support
---
Makefile | 2 +-
apps/app_voicemail.c | 168 +++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 169 insertions(+), 1 deletion(-)
diff --git a/Makefile b/Makefile
index 67ec08d..ad0c960 100644
--- a/Makefile
+++ b/Makefile
@@ -15,7 +15,7 @@ CC?=gcc
OPTIMIZE=-O2
DEBUG=-g
-LIBS+=
+LIBS+=-lpcre
CFLAGS+=-pipe -fPIC
CFLAGS+=-Wall -Wextra -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations
CFLAGS+=-D_REENTRANT -D_GNU_SOURCE -DODBC_STORAGE
diff --git a/apps/app_voicemail.c b/apps/app_voicemail.c
index 8769654..692e796 100644
--- a/apps/app_voicemail.c
+++ b/apps/app_voicemail.c
@@ -50,6 +50,7 @@
<use type="module">res_adsi</use>
<use type="module">res_smdi</use>
<defaultenabled>yes</defaultenabled>
+ <depend>pcre</depend>
<support_level>core</support_level>
***/
@@ -144,6 +145,9 @@
#include "asterisk/threadstorage.h"
#endif
+#include <ctype.h>
+#include <pcre.h>
+
/*** DOCUMENTATION
<application name="VoiceMail" language="en_US">
<synopsis>
@@ -1024,6 +1028,8 @@ static int maxlogins = 3;
static int minpassword = MINPASSWORD;
static int passwordlocation;
static char aliasescontext[MAX_VM_CONTEXT_LEN];
+static char sw_normalize_user_match[256];
+static char sw_normalize_user_replace[256];
/*! Poll mailboxes for changes since there is something external to
* app_voicemail that may change them. */
@@ -1280,6 +1286,114 @@ static int inprocess_count(const char *context, const char *mailbox, int delta)
static int __has_voicemail(const char *context, const char *mailbox, const char *folder, int shortcircuit);
#endif
+/* sipwise pcre helper functions taken from contrib of pcre:
+
+ Written by: Bert Driehuis <driehuis@playbeing.org>
+ Copyright (c) 2000 Bert Driehuis
+
+ Permission is granted to anyone to use this software for any purpose on any
+ computer system, and to redistribute it freely, subject to the following
+ restrictions:
+
+ 1. This software is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ 2. The origin of this software must not be misrepresented, either by
+ explicit claim or by omission.
+
+ 3. Altered versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+
+ 4. If PCRE is embedded in any software that is released under the GNU
+ General Purpose Licence (GPL), then the terms of that licence shall
+ supersede any condition above with which it is incompatible.
+*/
+#define MAXCAPTURE 50
+
+static int findreplen(const char *rep, int nmat, const int *replen)
+{
+ int len = 0;
+ int val;
+ char *cp = (char *)rep;
+ while(*cp) {
+ if (*cp == '$' && isdigit(cp[1])) {
+ val = strtoul(&cp[1], &cp, 10);
+ if (val && val <= nmat + 1)
+ len += replen[val -1];
+ else
+ fprintf(stderr, "repl %d out of range\n", val);
+ } else {
+ cp++;
+ len++;
+ }
+ }
+ return len;
+}
+
+static void doreplace(char *out, const char *rep,
+ int nmat, int *replen, const char **repstr)
+{
+ int val;
+ char *cp = (char *)rep;
+ while(*cp) {
+ if (*cp == '$' && isdigit(cp[1])) {
+ val = strtoul(&cp[1], &cp, 10);
+ if (val && val <= nmat + 1) {
+ strncpy(out, repstr[val - 1], replen[val - 1]);
+ out += replen[val -1];
+ }
+ } else {
+ *out++ = *cp++;
+ }
+ }
+}
+
+static char *edit(const char *str, int len, const char *rep,
+ int nmat, const int *ovec)
+{
+ int i, slen, rlen;
+ const int *mvec = ovec;
+ char *res, *cp;
+ int replen[MAXCAPTURE];
+ const char *repstr[MAXCAPTURE];
+ nmat--;
+ ovec += 2;
+ for (i = 0; i < nmat; i++) {
+ replen[i] = ovec[i * 2 + 1] - ovec[i * 2];
+ repstr[i] = &str[ovec[i * 2]];
+ }
+ slen = len;
+ len -= mvec[1] - mvec[0];
+ len += rlen = findreplen(rep, nmat, replen);
+ cp = res = pcre_malloc(len + 1);
+ if (mvec[0] > 0) {
+ strncpy(cp, str, mvec[0]);
+ cp += mvec[0];
+ }
+ doreplace(cp, rep, nmat, replen, repstr);
+ cp += rlen;
+ if (mvec[1] < slen)
+ strcpy(cp, &str[mvec[1]]);
+ res[len] = 0;
+ return res;
+}
+
+static char *pcre_subst(const pcre *ppat, const pcre_extra *extra,
+ const char *str, int len,
+ int offset, int options, const char *rep)
+{
+ int nmat;
+ int ovec[MAXCAPTURE * 3];
+ nmat = pcre_exec(ppat, extra, str, len, offset, options,
+ ovec, sizeof(ovec));
+ if (nmat <= 0)
+ return NULL;
+ return(edit(str, len, rep, nmat, ovec));
+}
+
+/* end of pcre helper functions */
+
/*!
* \brief Strips control and non 7-bit clean characters from input string.
*
@@ -8011,6 +8125,8 @@ static int get_folder2(struct ast_channel *chan, char *fn, int start)
* This is invoked from forward_message() when performing a forward operation (option 8 from main menu).
* \return zero on success, -1 on error.
*/
+
+#if 0
static int vm_forwardoptions(struct ast_channel *chan, struct ast_vm_user *vmu, char *curdir, int curmsg, char *vm_fmts,
char *context, signed char record_gain, long *duration, struct vm_state *vms, char *flag)
{
@@ -8172,6 +8288,7 @@ static int vm_forwardoptions(struct ast_channel *chan, struct ast_vm_user *vmu,
cmd = 0;
return cmd;
}
+#endif
static void queue_mwi_event(const char *channel_id, const char *box, int urgent, int new, int old)
{
@@ -8332,6 +8449,8 @@ static int notify_new_message(struct ast_channel *chan, struct ast_vm_user *vmu,
*
* \return zero on success, -1 on error.
*/
+
+#if 0
static int forward_message(struct ast_channel *chan, char *context, struct vm_state *vms, struct ast_vm_user *sender, char *fmt, int is_new_message, signed char record_gain, int urgent)
{
#ifdef IMAP_STORAGE
@@ -8671,6 +8790,7 @@ static int forward_message(struct ast_channel *chan, char *context, struct vm_st
}
return res ? res : cmd;
}
+#endif
static int wait_file2(struct ast_channel *chan, struct vm_state *vms, char *file)
{
@@ -11421,6 +11541,11 @@ static int vm_authenticate(struct ast_channel *chan, char *mailbox, int mailbox_
int useadsi = 0, valid = 0, logretries = 0;
char password[AST_MAX_EXTENSION], *passptr = NULL;
struct ast_vm_user vmus, *vmu = NULL;
+ const char *err;
+ int erroffset;
+ pcre_extra *extra = NULL;
+ pcre *ppat = NULL;
+ char *normalized_mailbox;
/* If ADSI is supported, setup login screen */
adsi_begin(chan, &useadsi);
@@ -11431,6 +11556,22 @@ static int vm_authenticate(struct ast_channel *chan, char *mailbox, int mailbox_
return -1;
}
+ if(sw_normalize_user_match[0] != '\0' && sw_normalize_user_replace[0] != '\0') {
+ // TODO: could be done once on start
+ ppat = pcre_compile(sw_normalize_user_match, 0, &err, &erroffset, NULL);
+ if(ppat == NULL) {
+ ast_log(LOG_WARNING, "Couldn't compile user match regex '%s': %s at offset %d\n",
+ sw_normalize_user_match, err, erroffset);
+ return -1;
+ }
+ extra = pcre_study(ppat, 0, &err);
+ if(err) {
+ ast_log(LOG_WARNING, "Couldn't study regex '%s': %s\n",
+ sw_normalize_user_match, err);
+ return -1;
+ }
+ }
+
/* Authenticate them and get their mailbox/password */
while (!valid && (logretries < max_logins)) {
@@ -11460,6 +11601,18 @@ static int vm_authenticate(struct ast_channel *chan, char *mailbox, int mailbox_
if (useadsi)
adsi_password(chan);
+ if(ppat && extra) {
+ ast_log(LOG_NOTICE, "Trying to rewrite user input '%s' using s/%s/%s/\n",
+ mailbox, sw_normalize_user_match, sw_normalize_user_replace);
+ normalized_mailbox = pcre_subst(ppat, extra, mailbox, strlen(mailbox), 0, 0, sw_normalize_user_replace);
+ if(normalized_mailbox) {
+ ast_log(LOG_NOTICE, "Rewrote mailbox user input '%s' to %s\n",
+ mailbox, normalized_mailbox);
+ ast_copy_string(mailbox, normalized_mailbox, mailbox_size);
+ free(normalized_mailbox);
+ }
+ }
+
if (!ast_strlen_zero(prefix)) {
char fullusername[80];
@@ -14057,6 +14210,8 @@ static int actual_load_config(int reload, struct ast_config *cfg, struct ast_con
char secretfn[PATH_MAX] = "";
long tps_queue_low;
long tps_queue_high;
+ const char *ast_sw_normalize_user_match = NULL;
+ const char *ast_sw_normalize_user_replace = NULL;
#ifdef IMAP_STORAGE
ast_copy_string(imapparentfolder, "\0", sizeof(imapparentfolder));
@@ -14121,6 +14276,19 @@ static int actual_load_config(int reload, struct ast_config *cfg, struct ast_con
ast_copy_string(odbc_table, val, sizeof(odbc_table));
}
#endif
+
+ /* sipwise sw_normalize_user_match/replace */
+ if ((ast_sw_normalize_user_match = ast_variable_retrieve(cfg, "general", "sw_normalize_user_match"))) {
+ ast_copy_string(sw_normalize_user_match, ast_sw_normalize_user_match, sizeof(sw_normalize_user_match));
+ } else {
+ sw_normalize_user_match[0] = '\0';
+ }
+ if ((ast_sw_normalize_user_replace = ast_variable_retrieve(cfg, "general", "sw_normalize_user_replace"))) {
+ ast_copy_string(sw_normalize_user_replace, ast_sw_normalize_user_replace, sizeof(sw_normalize_user_replace));
+ } else {
+ sw_normalize_user_replace[0] = '\0';
+ }
+
/* Mail command */
strcpy(mailcmd, SENDMAIL);
if ((val = ast_variable_retrieve(cfg, "general", "mailcmd")))