[Asterisk-code-review] app_voicemail: Refactor email generation functions (asterisk[master])

N A asteriskteam at digium.com
Mon Nov 1 10:42:33 CDT 2021


N A has uploaded this change for review. ( https://gerrit.asterisk.org/c/asterisk/+/16665 )


Change subject: app_voicemail: Refactor email generation functions
......................................................................

app_voicemail: Refactor email generation functions

Refactors generic functions used for email generation
into a separate file that can be included by multiple
modules, including app_voicemail, to avoid code
duplication.

ASTERISK-29715 #close

Change-Id: I1de0ed3483623e9599711129edc817c45ad237ee
---
M apps/app_voicemail.c
A include/asterisk/mail.h
A main/mail.c
3 files changed, 236 insertions(+), 150 deletions(-)



  git pull ssh://gerrit.asterisk.org:29418/asterisk refs/changes/65/16665/1

diff --git a/apps/app_voicemail.c b/apps/app_voicemail.c
index cb70ed6..57dd575 100644
--- a/apps/app_voicemail.c
+++ b/apps/app_voicemail.c
@@ -100,6 +100,7 @@
 #include "asterisk/taskprocessor.h"
 #include "asterisk/test.h"
 #include "asterisk/format_cache.h"
+#include "asterisk/mail.h"
 
 #ifdef ODBC_STORAGE
 #include "asterisk/res_odbc.h"
@@ -539,8 +540,6 @@
 
 #define MINPASSWORD 0 /*!< Default minimum mailbox password length */
 
-#define BASELINELEN 72
-#define BASEMAXINLINE 256
 #ifdef IMAP_STORAGE
 #define ENDL "\r\n"
 #else
@@ -1928,22 +1927,6 @@
 	return snprintf(dest, len, "%s/msg%04d", dir, num);
 }
 
-/* same as mkstemp, but return a FILE * */
-static FILE *vm_mkftemp(char *template)
-{
-	FILE *p = NULL;
-	int pfd = mkstemp(template);
-	chmod(template, VOICEMAIL_FILE_MODE & ~my_umask);
-	if (pfd > -1) {
-		p = fdopen(pfd, "w+");
-		if (!p) {
-			close(pfd);
-			pfd = -1;
-		}
-	}
-	return p;
-}
-
 /*! \brief basically mkdir -p $dest/$context/$ext/$folder
  * \param dest    String. base directory.
  * \param len     Length of dest.
@@ -2697,7 +2680,7 @@
 
 	/* Make a temporary file instead of piping directly to sendmail, in case the mail
 	   command hangs. */
-	if (!(p = vm_mkftemp(tmp))) {
+	if (!(p = ast_file_mkftemp(tmp))) {
 		ast_log(AST_LOG_WARNING, "Unable to store '%s' (can't create temporary file)\n", fn);
 		if (tempcopy) {
 			ast_free(vmu->email);
@@ -4771,134 +4754,6 @@
 	return ast_filedelete(file, NULL);
 }
 
-/*!
- * \brief utility used by inchar(), for base_encode()
- */
-static int inbuf(struct baseio *bio, FILE *fi)
-{
-	int l;
-
-	if (bio->ateof)
-		return 0;
-
-	if ((l = fread(bio->iobuf, 1, BASEMAXINLINE, fi)) != BASEMAXINLINE) {
-		bio->ateof = 1;
-		if (l == 0) {
-			/* Assume EOF */
-			return 0;
-		}
-	}
-
-	bio->iolen = l;
-	bio->iocp = 0;
-
-	return 1;
-}
-
-/*!
- * \brief utility used by base_encode()
- */
-static int inchar(struct baseio *bio, FILE *fi)
-{
-	if (bio->iocp>=bio->iolen) {
-		if (!inbuf(bio, fi))
-			return EOF;
-	}
-
-	return bio->iobuf[bio->iocp++];
-}
-
-/*!
- * \brief utility used by base_encode()
- */
-static int ochar(struct baseio *bio, int c, FILE *so)
-{
-	if (bio->linelength >= BASELINELEN) {
-		if (fputs(ENDL, so) == EOF) {
-			return -1;
-		}
-
-		bio->linelength = 0;
-	}
-
-	if (putc(((unsigned char) c), so) == EOF) {
-		return -1;
-	}
-
-	bio->linelength++;
-
-	return 1;
-}
-
-/*!
- * \brief Performs a base 64 encode algorithm on the contents of a File
- * \param filename The path to the file to be encoded. Must be readable, file is opened in read mode.
- * \param so A FILE handle to the output file to receive the base 64 encoded contents of the input file, identified by filename.
- *
- * TODO: shouldn't this (and the above 3 support functions) be put into some kind of external utility location, such as funcs/func_base64.c ?
- *
- * \return zero on success, -1 on error.
- */
-static int base_encode(char *filename, FILE *so)
-{
-	static const unsigned char dtable[] = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K',
-		'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
-		'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0',
-		'1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'};
-	int i, hiteof = 0;
-	FILE *fi;
-	struct baseio bio;
-
-	memset(&bio, 0, sizeof(bio));
-	bio.iocp = BASEMAXINLINE;
-
-	if (!(fi = fopen(filename, "rb"))) {
-		ast_log(AST_LOG_WARNING, "Failed to open file: %s: %s\n", filename, strerror(errno));
-		return -1;
-	}
-
-	while (!hiteof){
-		unsigned char igroup[3], ogroup[4];
-		int c, n;
-
-		memset(igroup, 0, sizeof(igroup));
-
-		for (n = 0; n < 3; n++) {
-			if ((c = inchar(&bio, fi)) == EOF) {
-				hiteof = 1;
-				break;
-			}
-
-			igroup[n] = (unsigned char) c;
-		}
-
-		if (n > 0) {
-			ogroup[0]= dtable[igroup[0] >> 2];
-			ogroup[1]= dtable[((igroup[0] & 3) << 4) | (igroup[1] >> 4)];
-			ogroup[2]= dtable[((igroup[1] & 0xF) << 2) | (igroup[2] >> 6)];
-			ogroup[3]= dtable[igroup[2] & 0x3F];
-
-			if (n < 3) {
-				ogroup[3] = '=';
-
-				if (n < 2)
-					ogroup[2] = '=';
-			}
-
-			for (i = 0; i < 4; i++)
-				ochar(&bio, ogroup[i], so);
-		}
-	}
-
-	fclose(fi);
-
-	if (fputs(ENDL, so) == EOF) {
-		return 0;
-	}
-
-	return 1;
-}
-
 static void prep_email_sub_vars(struct ast_channel *ast, struct ast_vm_user *vmu, int msgnum, char *context, char *mailbox, const char *fromfolder, char *cidnum, char *cidname, char *dur, char *date, const char *category, const char *flag)
 {
 	char callerid[256];
@@ -5509,7 +5364,7 @@
 		fprintf(p, "Content-Disposition: attachment; filename=\"%s\"" ENDL ENDL, filename);
 	else
 		fprintf(p, "Content-Disposition: attachment; filename=\"%s.%s\"" ENDL ENDL, greeting_attachment, format);
-	base_encode(fname, p);
+	ast_base_encode(fname, p);
 	if (last)
 		fprintf(p, ENDL ENDL "--%s--" ENDL "." ENDL, bound);
 
@@ -5562,7 +5417,7 @@
 	ast_debug(3, "Attaching file '%s', format '%s', uservm is '%d', global is %u\n", attach, format, attach_user_voicemail, ast_test_flag((&globalflags), VM_ATTACH));
 	/* Make a temporary file instead of piping directly to sendmail, in case the mail
 	   command hangs */
-	if ((p = vm_mkftemp(tmp)) == NULL) {
+	if ((p = ast_file_mkftemp(tmp)) == NULL) {
 		ast_log(AST_LOG_WARNING, "Unable to launch '%s' (can't create temporary file)\n", mailcmd);
 		return -1;
 	} else {
@@ -5601,7 +5456,7 @@
 		strip_control_and_high(cidname, enc_cidname, sizeof(enc_cidname));
 	}
 
-	if ((p = vm_mkftemp(tmp)) == NULL) {
+	if ((p = ast_file_mkftemp(tmp)) == NULL) {
 		ast_log(AST_LOG_WARNING, "Unable to launch '%s' (can't create temporary file)\n", mailcmd);
 		ast_free(str1);
 		ast_free(str2);
diff --git a/include/asterisk/mail.h b/include/asterisk/mail.h
new file mode 100644
index 0000000..52e4007
--- /dev/null
+++ b/include/asterisk/mail.h
@@ -0,0 +1,44 @@
+/*
+ * Asterisk -- An open source telephony toolkit.
+ *
+ * Copyright (C) 2021, Naveen Albert
+ *
+ * Naveen Albert <asterisk at phreaknet.org>
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE file
+ * at the top of the source tree.
+ */
+
+/*!\file
+ * \brief Email generation functions
+ */
+
+#define	VOICEMAIL_FILE_MODE	0666
+#define BASELINELEN 72
+#define BASEMAXINLINE 256
+#define SENDMAIL "/usr/sbin/sendmail -t"
+#define ENDL "\n"
+
+/*!
+ * \brief Performs a base 64 encode algorithm on the contents of a File
+ * \param filename The path to the file to be encoded. Must be readable, file is opened in read mode.
+ * \param so A FILE handle to the output file to receive the base 64 encoded contents of the input file, identified by filename.
+ *
+ * \return zero on success, -1 on error.
+ */
+int ast_base_encode(char *filename, FILE *so);
+
+/*!
+ * \brief same as mkstemp, but return a FILE
+ * \param template The template for the unique file name to generate
+ *
+ * \return FILE handle to the temporary file on success or NULL if creation failed
+ */
+FILE *ast_file_mkftemp(char *template);
diff --git a/main/mail.c b/main/mail.c
new file mode 100644
index 0000000..739c9f6
--- /dev/null
+++ b/main/mail.c
@@ -0,0 +1,187 @@
+/*
+ * Asterisk -- An open source telephony toolkit.
+ *
+ * Copyright (C) 2021, Naveen Albert
+ *
+ * Naveen Albert <asterisk at phreaknet.org>
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE file
+ * at the top of the source tree.
+ */
+
+/*! \file
+ *
+ * \brief Email generation functions
+ *
+ * \author Naveen Albert <asterisk at phreaknet.org>
+ */
+
+/*** MODULEINFO
+	<support_level>core</support_level>
+ ***/
+
+#include "asterisk.h"
+
+#include <sys/stat.h>
+
+#include "asterisk/logger.h"
+#include "asterisk/mail.h"
+
+static int my_umask;
+
+struct baseio {
+	int iocp;
+	int iolen;
+	int linelength;
+	int ateof;
+	unsigned char iobuf[BASEMAXINLINE];
+};
+
+/*!
+ * \brief utility used by inchar(), for base_encode()
+ */
+static int inbuf(struct baseio *bio, FILE *fi)
+{
+	int l;
+
+	if (bio->ateof)
+		return 0;
+
+	if ((l = fread(bio->iobuf, 1, BASEMAXINLINE, fi)) != BASEMAXINLINE) {
+		bio->ateof = 1;
+		if (l == 0) {
+			/* Assume EOF */
+			return 0;
+		}
+	}
+
+	bio->iolen = l;
+	bio->iocp = 0;
+
+	return 1;
+}
+
+/*!
+ * \brief utility used by base_encode()
+ */
+static int inchar(struct baseio *bio, FILE *fi)
+{
+	if (bio->iocp>=bio->iolen) {
+		if (!inbuf(bio, fi))
+			return EOF;
+	}
+
+	return bio->iobuf[bio->iocp++];
+}
+
+/*!
+ * \brief utility used by base_encode()
+ */
+static int ochar(struct baseio *bio, int c, FILE *so)
+{
+	if (bio->linelength >= BASELINELEN) {
+		if (fputs(ENDL, so) == EOF) {
+			return -1;
+		}
+
+		bio->linelength = 0;
+	}
+
+	if (putc(((unsigned char) c), so) == EOF) {
+		return -1;
+	}
+
+	bio->linelength++;
+
+	return 1;
+}
+
+/*!
+ * \brief Performs a base 64 encode algorithm on the contents of a File
+ * \param filename The path to the file to be encoded. Must be readable, file is opened in read mode.
+ * \param so A FILE handle to the output file to receive the base 64 encoded contents of the input file, identified by filename.
+ *
+ * \return zero on success, -1 on error.
+ */
+int ast_base_encode(char *filename, FILE *so)
+{
+	static const unsigned char dtable[] = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K',
+		'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
+		'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0',
+		'1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'};
+	int i, hiteof = 0;
+	FILE *fi;
+	struct baseio bio;
+
+	memset(&bio, 0, sizeof(bio));
+	bio.iocp = BASEMAXINLINE;
+
+	if (!(fi = fopen(filename, "rb"))) {
+		ast_log(AST_LOG_WARNING, "Failed to open file: %s: %s\n", filename, strerror(errno));
+		return -1;
+	}
+
+	while (!hiteof){
+		unsigned char igroup[3], ogroup[4];
+		int c, n;
+
+		memset(igroup, 0, sizeof(igroup));
+
+		for (n = 0; n < 3; n++) {
+			if ((c = inchar(&bio, fi)) == EOF) {
+				hiteof = 1;
+				break;
+			}
+
+			igroup[n] = (unsigned char) c;
+		}
+
+		if (n > 0) {
+			ogroup[0]= dtable[igroup[0] >> 2];
+			ogroup[1]= dtable[((igroup[0] & 3) << 4) | (igroup[1] >> 4)];
+			ogroup[2]= dtable[((igroup[1] & 0xF) << 2) | (igroup[2] >> 6)];
+			ogroup[3]= dtable[igroup[2] & 0x3F];
+
+			if (n < 3) {
+				ogroup[3] = '=';
+
+				if (n < 2)
+					ogroup[2] = '=';
+			}
+
+			for (i = 0; i < 4; i++)
+				ochar(&bio, ogroup[i], so);
+		}
+	}
+
+	fclose(fi);
+
+	if (fputs(ENDL, so) == EOF) {
+		return 0;
+	}
+
+	return 1;
+}
+
+/* same as mkstemp, but return a FILE * */
+FILE *ast_file_mkftemp(char *template)
+{
+	FILE *p = NULL;
+	int pfd = mkstemp(template);
+	chmod(template, VOICEMAIL_FILE_MODE & ~my_umask);
+	if (pfd > -1) {
+		p = fdopen(pfd, "w+");
+		if (!p) {
+			close(pfd);
+			pfd = -1;
+		}
+	}
+	return p;
+}

-- 
To view, visit https://gerrit.asterisk.org/c/asterisk/+/16665
To unsubscribe, or for help writing mail filters, visit https://gerrit.asterisk.org/settings

Gerrit-Project: asterisk
Gerrit-Branch: master
Gerrit-Change-Id: I1de0ed3483623e9599711129edc817c45ad237ee
Gerrit-Change-Number: 16665
Gerrit-PatchSet: 1
Gerrit-Owner: N A <mail at interlinked.x10host.com>
Gerrit-MessageType: newchange
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.digium.com/pipermail/asterisk-code-review/attachments/20211101/0c1ccb0d/attachment-0001.html>


More information about the asterisk-code-review mailing list