ports/117199: [UPDATE] net/asterisk to 1.4.13

Vladimir Korkodinov viper at perm.raid.ru
Mon Oct 15 04:40:02 UTC 2007


>Number:         117199
>Category:       ports
>Synopsis:       [UPDATE] net/asterisk to 1.4.13
>Confidential:   no
>Severity:       serious
>Priority:       low
>Responsible:    freebsd-ports-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          update
>Submitter-Id:   current-users
>Arrival-Date:   Mon Oct 15 04:40:02 UTC 2007
>Closed-Date:
>Last-Modified:
>Originator:     Vladimir Korkodinov
>Release:        FreeBSD 6.2-STABLE
>Organization:
>Environment:
FreeBSD monitor4 6.2-STABLE FreeBSD 6.2-STABLE #3: Wed Aug 29 14:50:03 YEKST 2007     viper at monitor4:/usr/obj/usr/src/sys/viper2  i386

>Description:
http://www.asterisk.org/node/48390
"The Asterisk Development Team has released version 1.4.13.

This release fixes a couple of security issues in the implementation of IMAP
storage for voicemail. One of the issues is remotely exploitable. Any systems
that do not use IMAP storage for voicemail are not affected by these issues.
For more details on this issue, see the Asterisk security advisory here:

    * http://downloads.digium.com/pub/asa/AST-2007-022.pdf

This release also contains some other bug fixes that have been merged in the
past week or so. The other fixes include resolutions for a few different
deadlocks, a couple of problems in res_jabber, chan_sip and RTP fixes, and a few
more minor issues. See the ChangeLog for a full listing of the changes:

    * http://downloads.digium.com/pub/telephony/asterisk/ChangeLog-1.4.13
"


>From page http://www.soft-switch.org/spandsp-known-issues.html
"spandsp-0.0.2pre4

The following are known issues with version 0.0.2pre4 of spandsp.

    * The FAX image handling in libtiff 3.6.1 is broken, so this version of libtiff will not function correctly with spandsp (or HylaFAX, or any other FAX software, I guess).
    * It seems possible for the libtiff library to fall over when handling some bad TIFF files. If spandsp is being used with Asterisk, this might bring the entire PBX down. So far only one person has reported this. Recent security update patches for libtiff 3.5.7, 3.6.0, and 3.6.1 hopefully correct this problem."
Now is present in the ports version 0.3 of spandsp and version 3.8.2 of libtiff.

>How-To-Repeat:

>Fix:
Apply patch
What makes this patch.
1. Adds support for faxes(rxfax and txfax). Compiled only with spandsp> 0.0.3
2. Adds option to build asterisk with the option IMAP STORAGE.
3. Upgrading to version 1.4.13


Patch attached with submission follows:

diff -ruN asterisk.old/Makefile asterisk/Makefile
--- asterisk.old/Makefile	2007-10-09 09:33:47.000000000 +0600
+++ asterisk/Makefile	2007-10-15 10:11:25.000000000 +0600
@@ -6,8 +6,8 @@
 #
 
 PORTNAME=	asterisk
-PORTVERSION=	1.4.11
-PORTREVISION=	2
+PORTVERSION=	1.4.13
+PORTREVISION=	1
 CATEGORIES=	net
 MASTER_SITES=	http://ftp.digium.com/pub/asterisk/ \
 		http://ftp.digium.com/pub/asterisk/old-releases/
@@ -48,7 +48,10 @@
 		FREETDS		"Enable FreeTDS support" on \
 		JABBER		"Enable Jabber and Gtalk support" on \
 		SQLITE          "Enable SQLITE support" on \
-		CODEC_PATCH	"Apply codec negotiation patch" off
+		IMAP            "Enable IMAP support" off \
+		FAX             "Enable FAX support" on	
+
+##		CODEC_PATCH	"Apply codec negotiation patch" off
 
 .include <bsd.port.pre.mk>
 
@@ -156,16 +159,60 @@
 LIB_DEPENDS+=	sqlite:${PORTSDIR}/databases/sqlite2
 .endif
 
-.if defined(WITH_CODEC_PATCH)
-PATCHFILES=	asterisk-1.4.11-codec-negotiation-20070831.diff.gz
-PATCH_SITES=	http://b2bua.org/chrome/site/
-EXTRA_PATCHES+=	${PATCHDIR}/codecnego-patch-Makefile
-.else
-EXTRA_PATCHES+=	${PATCHDIR}/nocodecnego-patch-Makefile
+#.if defined(WITH_CODEC_PATCH)
+#PATCHFILES=	asterisk-1.4.11-codec-negotiation-20070831.diff.gz
+#PATCH_SITES=	http://b2bua.org/chrome/site/
+#EXTRA_PATCHES+=	${PATCHDIR}/codecnego-patch-Makefile
+#.else
+#EXTRA_PATCHES+=	${PATCHDIR}/nocodecnego-patch-Makefile
+#.endif
+
+.if defined(WITHOUT_FAX)
+PLIST_SUB+=    WITH_FAX="@comment "
+.else
+MAKE_ENV+=     WITH_FAX=yes
+CONFIGURE_ARGS+= --with-spandsp=yes
+BUILD_DEPENDS+= spandsp>=0.0.3:${PORTSDIR}/comms/spandsp
+LIB_DEPENDS+=  spandsp.0:${PORTSDIR}/comms/spandsp
+PLIST_SUB+=    WITH_FAX=""
+.endif
+
+.if defined(WITHOUT_IMAP)
+PLIST_SUB+=    WITH_IMAP="@comment "
+.else
+MAKE_ENV+=     WITH_IMAP=yes
+CONFIGURE_ARGS+= --with-imap=${LOCALBASE}
+LIB_DEPENDS+=  c-client4.9:${PORTSDIR}/mail/cclient
+PLIST_SUB+=    WITH_IMAP=""
 .endif
 
 
 post-patch:
 	${REINPLACE_CMD} -e 's|/var/lib|${PREFIX}/share|g' ${WRKSRC}/configs/musiconhold.conf.sample
 
+pre-configure:
+
+.if defined(WITH_ODBC) && defined(WITH_IMAP)
+	@${ECHO_MSG}    ""
+	@${ECHO_MSG}    "WARNING!!! You can choose only one option for build app_voicemail"
+	@${ECHO_MSG}    ""
+.endif
+.if defined(WITH_ODBC)
+	@${ECHO_MSG}    ""
+	@${ECHO_MSG}    "If necessary, build  with the option ODBC_STORAGE"
+	@${ECHO_MSG}    "press Ctrl-C and run following command:"
+	@${ECHO_MSG}    "1. cd work/asterisk-1.4.x"
+	@${ECHO_MSG}    "2. gmake menuselect"
+	@${ECHO_MSG}    "3. Select 'Voicemail Build Options->ODBC_STORAGE'"
+.endif
+
+.if defined(WITH_IMAP)
+	@${ECHO_MSG}    ""
+	@${ECHO_MSG}    "If necessary, build  with the option IMAP_STORAGE"
+	@${ECHO_MSG}    "press Ctrl-C and run following command:"
+	@${ECHO_MSG}    "1. cd work/asterisk-1.4.x"
+	@${ECHO_MSG}    "2. gmake menuselect"
+	@${ECHO_MSG}    "3. Select 'Voicemail Build Options->IMAP_STORAGE'"
+.endif
+
 .include <bsd.port.post.mk>
diff -ruN asterisk.old/distinfo asterisk/distinfo
--- asterisk.old/distinfo	2007-09-03 14:18:57.000000000 +0600
+++ asterisk/distinfo	2007-10-12 12:00:44.000000000 +0600
@@ -1,6 +1,3 @@
-MD5 (asterisk-1.4.11.tar.gz) = 3ba9b399fedc68de4845b1c5603d167c
-SHA256 (asterisk-1.4.11.tar.gz) = 99928f8aab62e532e71fdecbd18d5af2d211f1bbce27cf9cf2efc34e57a20101
-SIZE (asterisk-1.4.11.tar.gz) = 11218944
-MD5 (asterisk-1.4.11-codec-negotiation-20070831.diff.gz) = cf2385047d55ffffcff7197480e54c79
-SHA256 (asterisk-1.4.11-codec-negotiation-20070831.diff.gz) = 9d6b6efcbf20b35f407aa53320b649c0d884cce9b519435c7ea3aa8a51b2b42f
-SIZE (asterisk-1.4.11-codec-negotiation-20070831.diff.gz) = 37651
+MD5 (asterisk-1.4.13.tar.gz) = 49b73114831c21cc9784d3b3f4fb5bec
+SHA256 (asterisk-1.4.13.tar.gz) = 0bea2f612c7b6ebcfb97c77d473a45018a3e112e5610ff7fab83561be7b19449
+SIZE (asterisk-1.4.13.tar.gz) = 11257579
diff -ruN asterisk.old/files/patch-apps::app_rxfax.c asterisk/files/patch-apps::app_rxfax.c
--- asterisk.old/files/patch-apps::app_rxfax.c	1970-01-01 05:00:00.000000000 +0500
+++ asterisk/files/patch-apps::app_rxfax.c	2007-07-23 15:01:57.000000000 +0600
@@ -0,0 +1,383 @@
+--- apps/app_rxfax.c.orig	Tue Jul 10 15:28:04 2007
++++ apps/app_rxfax.c	Tue Jul 10 15:27:28 2007
+@@ -0,0 +1,380 @@
++/*
++ * Asterisk -- A telephony toolkit for Linux.
++ *
++ * Trivial application to receive a TIFF FAX file
++ * 
++ * Copyright (C) 2003, Steve Underwood
++ *
++ * Steve Underwood <steveu at coppice.org>
++ *
++ * This program is free software, distributed under the terms of
++ * the GNU General Public License
++ */
++
++/*** MODULEINFO
++         <depend>spandsp</depend>
++***/
++ 
++#include "asterisk.h"
++
++ASTERISK_FILE_VERSION(__FILE__, "$Revision:$")
++
++#include <string.h>
++#include <stdlib.h>
++#include <stdio.h>
++#include <inttypes.h>
++#include <pthread.h>
++#include <errno.h>
++#include <tiffio.h>
++
++#include <spandsp.h>
++
++#include "asterisk/lock.h"
++#include "asterisk/file.h"
++#include "asterisk/logger.h"
++#include "asterisk/channel.h"
++#include "asterisk/pbx.h"
++#include "asterisk/module.h"
++#include "asterisk/manager.h"
++
++#ifndef AST_MODULE
++#define AST_MODULE "app_rxfax"
++#endif
++
++static char *app = "RxFAX";
++
++static char *synopsis = "Receive a FAX to a file";
++
++static char *descrip = 
++"  RxFAX(filename[|caller][|debug]): Receives a FAX from the channel into the\n"
++"given filename. If the file exists it will be overwritten. The file\n"
++"should be in TIFF/F format.\n"
++"The \"caller\" option makes the application behave as a calling machine,\n"
++"rather than the answering machine. The default behaviour is to behave as\n"
++"an answering machine.\n"
++"Uses LOCALSTATIONID to identify itself to the remote end.\n"
++"     LOCALHEADERINFO to generate a header line on each page.\n"
++"Sets REMOTESTATIONID to the sender CSID.\n"
++"     FAXPAGES to the number of pages received.\n"
++"     FAXBITRATE to the transmition rate.\n"
++"     FAXRESOLUTION to the resolution.\n"
++"Returns -1 when the user hangs up.\n"
++"Returns 0 otherwise.\n";
++
++#define MAX_BLOCK_SIZE 240
++
++static void span_message(int level, const char *msg)
++{
++    int ast_level;
++    
++    if (level == SPAN_LOG_WARNING)
++        ast_level = __LOG_WARNING;
++    else if (level == SPAN_LOG_WARNING)
++        ast_level = __LOG_WARNING;
++    else
++        ast_level = __LOG_DEBUG;
++    ast_log(ast_level, __FILE__, __LINE__, __PRETTY_FUNCTION__, msg);
++}
++/*- End of function --------------------------------------------------------*/
++
++#if 0
++static void t30_flush(t30_state_t *s, int which)
++{
++    /* TODO: */
++}
++/*- End of function --------------------------------------------------------*/
++#endif
++
++static void phase_e_handler(t30_state_t *s, void *user_data, int result)
++{
++    struct ast_channel *chan;
++    t30_stats_t t;
++    char local_ident[21];
++    char far_ident[21];
++    char buf[11];
++    
++    chan = (struct ast_channel *) user_data;
++    if (result == T30_ERR_OK)
++    {
++        t30_get_transfer_statistics(s, &t);
++        t30_get_far_ident(s, far_ident);
++        t30_get_local_ident(s, local_ident);
++        ast_log(LOG_DEBUG, "==============================================================================\n");
++        ast_log(LOG_DEBUG, "Fax successfully received.\n");
++        ast_log(LOG_DEBUG, "Remote station id: %s\n", far_ident);
++        ast_log(LOG_DEBUG, "Local station id:  %s\n", local_ident);
++        ast_log(LOG_DEBUG, "Pages transferred: %i\n", t.pages_transferred);
++        ast_log(LOG_DEBUG, "Image resolution:  %i x %i\n", t.x_resolution, t.y_resolution);
++        ast_log(LOG_DEBUG, "Transfer Rate:     %i\n", t.bit_rate);
++        ast_log(LOG_DEBUG, "==============================================================================\n");
++        manager_event(EVENT_FLAG_CALL,
++                      "FaxReceived", "Channel: %s\nExten: %s\nCallerID: %s\nRemoteStationID: %s\nLocalStationID: %s\nPagesTransferred: %i\nResolution: %i\nTransferRate: %i\nFileName: %s\n",
++                      chan->name,
++                      chan->exten,
++                      (chan->cid.cid_num)  ?  chan->cid.cid_num  :  "",
++                      far_ident,
++                      local_ident,
++                      t.pages_transferred,
++                      t.y_resolution,
++                      t.bit_rate,
++                      s->rx_file);
++        pbx_builtin_setvar_helper(chan, "REMOTESTATIONID", far_ident);
++        snprintf(buf, sizeof(buf), "%i", t.pages_transferred);
++        pbx_builtin_setvar_helper(chan, "FAXPAGES", buf);
++        snprintf(buf, sizeof(buf), "%i", t.y_resolution);
++        pbx_builtin_setvar_helper(chan, "FAXRESOLUTION", buf);
++        snprintf(buf, sizeof(buf), "%i", t.bit_rate);
++        pbx_builtin_setvar_helper(chan, "FAXBITRATE", buf);
++    }
++    else
++    {
++        ast_log(LOG_DEBUG, "==============================================================================\n");
++        ast_log(LOG_DEBUG, "Fax receive not successful - result (%d) %s.\n", result, t30_completion_code_to_str(result));
++        ast_log(LOG_DEBUG, "==============================================================================\n");
++    }
++}
++/*- End of function --------------------------------------------------------*/
++
++static void phase_d_handler(t30_state_t *s, void *user_data, int result)
++{
++    struct ast_channel *chan;
++    t30_stats_t t;
++    
++    chan = (struct ast_channel *) user_data;
++    if (result)
++    {
++        t30_get_transfer_statistics(s, &t);
++        ast_log(LOG_DEBUG, "==============================================================================\n");
++        ast_log(LOG_DEBUG, "Pages transferred:  %i\n", t.pages_transferred);
++        ast_log(LOG_DEBUG, "Image size:         %i x %i\n", t.width, t.length);
++        ast_log(LOG_DEBUG, "Image resolution    %i x %i\n", t.x_resolution, t.y_resolution);
++        ast_log(LOG_DEBUG, "Transfer Rate:      %i\n", t.bit_rate);
++        ast_log(LOG_DEBUG, "Bad rows            %i\n", t.bad_rows);
++        ast_log(LOG_DEBUG, "Longest bad row run %i\n", t.longest_bad_row_run);
++        ast_log(LOG_DEBUG, "Compression type    %i\n", t.encoding);
++        ast_log(LOG_DEBUG, "Image size (bytes)  %i\n", t.image_size);
++        ast_log(LOG_DEBUG, "==============================================================================\n");
++    }
++}
++/*- End of function --------------------------------------------------------*/
++
++static int rxfax_exec(struct ast_channel *chan, void *data)
++{
++    int res = 0;
++    char template_file[256];
++    char target_file[256];
++    char *s;
++    char *t;
++    char *v;
++    const char *x;
++    int option;
++    int len;
++    int i;
++    fax_state_t fax;
++    int calling_party;
++    int verbose;
++    int samples;
++
++    struct ast_module_user *u;
++    struct ast_frame *inf = NULL;
++    struct ast_frame outf;
++
++    int original_read_fmt;
++    int original_write_fmt;
++    
++    uint8_t __buf[sizeof(uint16_t)*MAX_BLOCK_SIZE + 2*AST_FRIENDLY_OFFSET];
++    uint8_t *buf = __buf + AST_FRIENDLY_OFFSET;
++
++    if (chan == NULL)
++    {
++        ast_log(LOG_WARNING, "Fax receive channel is NULL. Giving up.\n");
++        return -1;
++    }
++
++    span_set_message_handler(span_message);
++
++    /* The next few lines of code parse out the filename and header from the input string */
++    if (data == NULL)
++    {
++        /* No data implies no filename or anything is present */
++        ast_log(LOG_WARNING, "Rxfax requires an argument (filename)\n");
++        return -1;
++    }
++    
++    calling_party = FALSE;
++    verbose = FALSE;
++    target_file[0] = '\0';
++
++    for (option = 0, v = s = data;  v;  option++, s++)
++    {
++        t = s;
++        v = strchr(s, '|');
++        s = (v)  ?  v  :  s + strlen(s);
++        strncpy((char *) buf, t, s - t);
++        buf[s - t] = '\0';
++        if (option == 0)
++        {
++            /* The first option is always the file name */
++            len = s - t;
++            if (len > 255)
++                len = 255;
++            strncpy(target_file, t, len);
++            target_file[len] = '\0';
++            /* Allow the use of %d in the file name for a wild card of sorts, to
++               create a new file with the specified name scheme */
++            if ((x = strchr(target_file, '%'))  &&  x[1] == 'd')
++            {
++                strcpy(template_file, target_file);
++                i = 0;
++                do
++                {
++                    snprintf(target_file, 256, template_file, 1);
++                    i++;
++                }
++                while (ast_fileexists(target_file, "", chan->language) != -1);
++            }
++        }
++        else if (strncmp("caller", t, s - t) == 0)
++        {
++            calling_party = TRUE;
++        }
++        else if (strncmp("debug", t, s - t) == 0)
++        {
++            verbose = TRUE;
++        }
++    }
++
++    /* Done parsing */
++
++    u = ast_module_user_add(chan);
++
++    if (chan->_state != AST_STATE_UP)
++    {
++        /* Shouldn't need this, but checking to see if channel is already answered
++         * Theoretically asterisk should already have answered before running the app */
++        res = ast_answer(chan);
++    }
++    
++    if (!res)
++    {
++        original_read_fmt = chan->readformat;
++        if (original_read_fmt != AST_FORMAT_SLINEAR)
++        {
++            res = ast_set_read_format(chan, AST_FORMAT_SLINEAR);
++            if (res < 0)
++            {
++                ast_log(LOG_WARNING, "Unable to set to linear read mode, giving up\n");
++                return -1;
++            }
++        }
++        original_write_fmt = chan->writeformat;
++        if (original_write_fmt != AST_FORMAT_SLINEAR)
++        {
++            res = ast_set_write_format(chan, AST_FORMAT_SLINEAR);
++            if (res < 0)
++            {
++                ast_log(LOG_WARNING, "Unable to set to linear write mode, giving up\n");
++                res = ast_set_read_format(chan, original_read_fmt);
++                if (res)
++                    ast_log(LOG_WARNING, "Unable to restore read format on '%s'\n", chan->name);
++                return -1;
++            }
++        }
++        fax_init(&fax, calling_party);
++        if (verbose)
++            fax.logging.level = SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW;
++        x = pbx_builtin_getvar_helper(chan, "LOCALSTATIONID");
++        if (x  &&  x[0])
++            t30_set_local_ident(&fax.t30_state, x);
++        x = pbx_builtin_getvar_helper(chan, "LOCALHEADERINFO");
++        if (x  &&  x[0])
++            t30_set_header_info(&fax.t30_state, x);
++        t30_set_rx_file(&fax.t30_state, target_file, -1);
++        //t30_set_phase_b_handler(&fax.t30_state, phase_b_handler, chan);
++        t30_set_phase_d_handler(&fax.t30_state, phase_d_handler, chan);
++        t30_set_phase_e_handler(&fax.t30_state, phase_e_handler, chan);
++        t30_set_ecm_capability(&fax.t30_state, TRUE);
++        t30_set_supported_compressions(&fax.t30_state, T30_SUPPORT_T4_1D_COMPRESSION | T30_SUPPORT_T4_2D_COMPRESSION | T30_SUPPORT_T6_COMPRESSION);
++        while (ast_waitfor(chan, -1) > -1)
++        {
++            inf = ast_read(chan);
++            if (inf == NULL)
++            {
++                res = -1;
++                break;
++            }
++            if (inf->frametype == AST_FRAME_VOICE)
++            {
++                if (fax_rx(&fax, inf->data, inf->samples))
++                    break;
++                samples = (inf->samples <= MAX_BLOCK_SIZE)  ?  inf->samples  :  MAX_BLOCK_SIZE;
++                len = fax_tx(&fax, (int16_t *) &buf[AST_FRIENDLY_OFFSET], samples);
++                if (len)
++                {
++                    memset(&outf, 0, sizeof(outf));
++                    outf.frametype = AST_FRAME_VOICE;
++                    outf.subclass = AST_FORMAT_SLINEAR;
++                    outf.datalen = len*sizeof(int16_t);
++                    outf.samples = len;
++                    outf.data = &buf[AST_FRIENDLY_OFFSET];
++                    outf.offset = AST_FRIENDLY_OFFSET;
++                    outf.src = "RxFAX";
++                    if (ast_write(chan, &outf) < 0)
++                    {
++                        ast_log(LOG_WARNING, "Unable to write frame to channel; %s\n", strerror(errno));
++                        break;
++                    }
++                }
++            }
++            ast_frfree(inf);
++        }
++        if (inf == NULL)
++        {
++            ast_log(LOG_DEBUG, "Got hangup\n");
++            res = -1;
++        }
++        if (original_read_fmt != AST_FORMAT_SLINEAR)
++        {
++            res = ast_set_read_format(chan, original_read_fmt);
++            if (res)
++                ast_log(LOG_WARNING, "Unable to restore read format on '%s'\n", chan->name);
++        }
++        if (original_write_fmt != AST_FORMAT_SLINEAR)
++        {
++            res = ast_set_write_format(chan, original_write_fmt);
++            if (res)
++                ast_log(LOG_WARNING, "Unable to restore write format on '%s'\n", chan->name);
++        }
++        t30_terminate(&fax.t30_state);
++    }
++    else
++    {
++        ast_log(LOG_WARNING, "Could not answer channel '%s'\n", chan->name);
++    }
++    ast_module_user_remove(u);
++    return res;
++}
++/*- End of function --------------------------------------------------------*/
++
++static int unload_module(void)
++{
++	int res;
++
++	ast_module_user_hangup_all();
++
++	res = ast_unregister_application(app);	
++	
++
++	return res;
++}
++/*- End of function --------------------------------------------------------*/
++
++static int load_module(void)
++{
++	return ast_register_application(app, rxfax_exec, synopsis, descrip);
++}
++/*- End of function --------------------------------------------------------*/
++
++AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Trivial FAX Receive Application");
++
++/*- End of file ------------------------------------------------------------*/
diff -ruN asterisk.old/files/patch-apps::app_txfax.c asterisk/files/patch-apps::app_txfax.c
--- asterisk.old/files/patch-apps::app_txfax.c	1970-01-01 05:00:00.000000000 +0500
+++ asterisk/files/patch-apps::app_txfax.c	2007-07-23 15:01:57.000000000 +0600
@@ -0,0 +1,309 @@
+--- apps/app_txfax.c.orig	Tue Jul 10 15:28:13 2007
++++ apps/app_txfax.c	Tue Jul 10 15:27:37 2007
+@@ -0,0 +1,306 @@
++/*
++ * Asterisk -- A telephony toolkit for Linux.
++ *
++ * Trivial application to send a TIFF file as a FAX
++ * 
++ * Copyright (C) 2003, Steve Underwood
++ *
++ * Steve Underwood <steveu at coppice.org>
++ *
++ * This program is free software, distributed under the terms of
++ * the GNU General Public License
++ */
++
++/*** MODULEINFO
++         <depend>spandsp</depend>
++***/
++ 
++#include "asterisk.h"
++
++ASTERISK_FILE_VERSION(__FILE__, "$Revision:$")
++
++#include <string.h>
++#include <stdlib.h>
++#include <stdio.h>
++#include <inttypes.h>
++#include <pthread.h>
++#include <errno.h>
++#include <tiffio.h>
++
++#include <spandsp.h>
++
++#include "asterisk/lock.h"
++#include "asterisk/file.h"
++#include "asterisk/logger.h"
++#include "asterisk/channel.h"
++#include "asterisk/pbx.h"
++#include "asterisk/module.h"
++
++#ifndef AST_MODULE
++#define AST_MODULE "app_txfax"
++#endif
++
++static char *app = "TxFAX";
++
++static char *synopsis = "Send a FAX file";
++
++static char *descrip = 
++"  TxFAX(filename[|caller][|debug]):  Send a given TIFF file to the channel as a FAX.\n"
++"The \"caller\" option makes the application behave as a calling machine,\n"
++"rather than the answering machine. The default behaviour is to behave as\n"
++"an answering machine.\n"
++"Uses LOCALSTATIONID to identify itself to the remote end.\n"
++"     LOCALHEADERINFO to generate a header line on each page.\n"
++"Sets REMOTESTATIONID to the receiver CSID.\n"
++"Returns -1 when the user hangs up, or if the file does not exist.\n"
++"Returns 0 otherwise.\n";
++
++#define MAX_BLOCK_SIZE 240
++
++static void span_message(int level, const char *msg)
++{
++    int ast_level;
++    
++    if (level == SPAN_LOG_WARNING)
++        ast_level = __LOG_WARNING;
++    else if (level == SPAN_LOG_WARNING)
++        ast_level = __LOG_WARNING;
++    else
++        ast_level = __LOG_DEBUG;
++    ast_log(ast_level, __FILE__, __LINE__, __PRETTY_FUNCTION__, msg);
++}
++/*- End of function --------------------------------------------------------*/
++
++#if 0
++static void t30_flush(t30_state_t *s, int which)
++{
++    /* TODO: */
++}
++/*- End of function --------------------------------------------------------*/
++#endif
++
++static void phase_e_handler(t30_state_t *s, void *user_data, int result)
++{
++    struct ast_channel *chan;
++    char far_ident[21];
++    
++    chan = (struct ast_channel *) user_data;
++    if (result == T30_ERR_OK)
++    {
++        t30_get_far_ident(s, far_ident);
++        pbx_builtin_setvar_helper(chan, "REMOTESTATIONID", far_ident);
++    }
++    else
++    {
++        ast_log(LOG_DEBUG, "==============================================================================\n");
++        ast_log(LOG_DEBUG, "Fax send not successful - result (%d) %s.\n", result, t30_completion_code_to_str(result));
++        ast_log(LOG_DEBUG, "==============================================================================\n");
++    }
++}
++/*- End of function --------------------------------------------------------*/
++
++static int txfax_exec(struct ast_channel *chan, void *data)
++{
++    int res = 0;
++    char source_file[256];
++    char *s;
++    char *t;
++    char *v;
++    const char *x;
++    int option;
++    int len;
++    fax_state_t fax;
++    int calling_party;
++    int verbose;
++    int samples;
++    
++    struct ast_module_user *u;
++    struct ast_frame *inf = NULL;
++    struct ast_frame outf;
++
++    int original_read_fmt;
++    int original_write_fmt;
++    
++    uint8_t __buf[sizeof(uint16_t)*MAX_BLOCK_SIZE + 2*AST_FRIENDLY_OFFSET];
++    uint8_t *buf = __buf + AST_FRIENDLY_OFFSET;
++
++    if (chan == NULL)
++    {
++        ast_log(LOG_WARNING, "Fax transmit channel is NULL. Giving up.\n");
++        return -1;
++    }
++
++    span_set_message_handler(span_message);
++
++    /* The next few lines of code parse out the filename and header from the input string */
++    if (data == NULL)
++    {
++        /* No data implies no filename or anything is present */
++        ast_log(LOG_WARNING, "Txfax requires an argument (filename)\n");
++        return -1;
++    }
++    
++    calling_party = FALSE;
++    verbose = FALSE;
++    source_file[0] = '\0'; 
++
++    for (option = 0, v = s = data;  v;  option++, s++)
++    {
++        t = s;
++        v = strchr(s, '|');
++        s = (v)  ?  v  :  s + strlen(s);
++        strncpy((char *) buf, t, s - t);
++        buf[s - t] = '\0';
++        if (option == 0)
++        {
++            /* The first option is always the file name */
++            len = s - t;
++            if (len > 255)
++                len = 255;
++            strncpy(source_file, t, len);
++            source_file[len] = '\0';
++        }
++        else if (strncmp("caller", t, s - t) == 0)
++        {
++            calling_party = TRUE;
++        }
++        else if (strncmp("debug", t, s - t) == 0)
++        {
++            verbose = TRUE;
++        }
++    }
++
++    /* Done parsing */
++
++    u = ast_module_user_add(chan);
++
++    if (chan->_state != AST_STATE_UP)
++    {
++        /* Shouldn't need this, but checking to see if channel is already answered
++         * Theoretically asterisk should already have answered before running the app */
++        res = ast_answer(chan);
++    }
++    
++    if (!res)
++    {
++        original_read_fmt = chan->readformat;
++        if (original_read_fmt != AST_FORMAT_SLINEAR)
++        {
++            res = ast_set_read_format(chan, AST_FORMAT_SLINEAR);
++            if (res < 0)
++            {
++                ast_log(LOG_WARNING, "Unable to set to linear read mode, giving up\n");
++                return -1;
++            }
++        }
++        original_write_fmt = chan->writeformat;
++        if (original_write_fmt != AST_FORMAT_SLINEAR)
++        {
++            res = ast_set_write_format(chan, AST_FORMAT_SLINEAR);
++            if (res < 0)
++            {
++                ast_log(LOG_WARNING, "Unable to set to linear write mode, giving up\n");
++                res = ast_set_read_format(chan, original_read_fmt);
++                if (res)
++                    ast_log(LOG_WARNING, "Unable to restore read format on '%s'\n", chan->name);
++                return -1;
++            }
++        }
++        fax_init(&fax, calling_party);
++        if (verbose)
++	    fax.logging.level = SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW;
++
++        x = pbx_builtin_getvar_helper(chan, "LOCALSTATIONID");
++        if (x  &&  x[0])
++            t30_set_local_ident(&fax.t30_state, x);
++        x = pbx_builtin_getvar_helper(chan, "LOCALHEADERINFO");
++        if (x  &&  x[0])
++            t30_set_header_info(&fax.t30_state, x);
++        t30_set_tx_file(&fax.t30_state, source_file, -1, -1);
++        //t30_set_phase_b_handler(&fax.t30_state, phase_b_handler, chan);
++        //t30_set_phase_d_handler(&fax.t30_state, phase_d_handler, chan);
++        t30_set_phase_e_handler(&fax.t30_state, phase_e_handler, chan);
++        t30_set_ecm_capability(&fax.t30_state, TRUE);
++        t30_set_supported_compressions(&fax.t30_state, T30_SUPPORT_T4_1D_COMPRESSION | T30_SUPPORT_T4_2D_COMPRESSION | T30_SUPPORT_T6_COMPRESSION);
++        while (ast_waitfor(chan, -1) > -1)
++        {
++            inf = ast_read(chan);
++            if (inf == NULL)
++            {
++                res = -1;
++                break;
++            }
++            if (inf->frametype == AST_FRAME_VOICE)
++            {
++                if (fax_rx(&fax, inf->data, inf->samples))
++                    break;
++                samples = (inf->samples <= MAX_BLOCK_SIZE)  ?  inf->samples  :  MAX_BLOCK_SIZE;
++                len = fax_tx(&fax, (int16_t *) &buf[AST_FRIENDLY_OFFSET], samples);
++                if (len)
++                {
++                    memset(&outf, 0, sizeof(outf));
++                    outf.frametype = AST_FRAME_VOICE;
++                    outf.subclass = AST_FORMAT_SLINEAR;
++                    outf.datalen = len*sizeof(int16_t);
++                    outf.samples = len;
++                    outf.data = &buf[AST_FRIENDLY_OFFSET];
++                    outf.offset = AST_FRIENDLY_OFFSET;
++                    if (ast_write(chan, &outf) < 0)
++                    {
++                        ast_log(LOG_WARNING, "Unable to write frame to channel; %s\n", strerror(errno));
++                        break;
++                    }
++                }
++            }
++            ast_frfree(inf);
++        }
++        if (inf == NULL)
++        {
++            ast_log(LOG_DEBUG, "Got hangup\n");
++            res = -1;
++        }
++        if (original_read_fmt != AST_FORMAT_SLINEAR)
++        {
++            res = ast_set_read_format(chan, original_read_fmt);
++            if (res)
++                ast_log(LOG_WARNING, "Unable to restore read format on '%s'\n", chan->name);
++        }
++        if (original_write_fmt != AST_FORMAT_SLINEAR)
++        {
++            res = ast_set_write_format(chan, original_write_fmt);
++            if (res)
++                ast_log(LOG_WARNING, "Unable to restore write format on '%s'\n", chan->name);
++        }
++        t30_terminate(&fax.t30_state);
++    }
++    else
++    {
++        ast_log(LOG_WARNING, "Could not answer channel '%s'\n", chan->name);
++    }
++    ast_module_user_remove(u);
++    return res;
++}
++/*- End of function --------------------------------------------------------*/
++
++static int unload_module(void)
++{
++	int res;
++
++	ast_module_user_hangup_all();
++
++	res = ast_unregister_application(app);	
++	
++
++	return res;
++}
++/*- End of function --------------------------------------------------------*/
++
++static int load_module(void)
++{
++    return ast_register_application(app, txfax_exec, synopsis, descrip);
++}
++/*- End of function --------------------------------------------------------*/
++
++AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Trivial FAX Transmit Application");
++
++/*- End of file ------------------------------------------------------------*/
diff -ruN asterisk.old/files/patch-build_tools::menuselect-deps.in asterisk/files/patch-build_tools::menuselect-deps.in
--- asterisk.old/files/patch-build_tools::menuselect-deps.in	1970-01-01 05:00:00.000000000 +0500
+++ asterisk/files/patch-build_tools::menuselect-deps.in	2007-10-09 21:26:38.000000000 +0600
@@ -0,0 +1,10 @@
+--- build_tools/menuselect-deps.in.orig	2007-10-09 21:26:02.000000000 +0600
++++ build_tools/menuselect-deps.in	2007-10-09 21:26:19.000000000 +0600
+@@ -22,6 +22,7 @@
+ PRI=@PBX_PRI@
+ QT=@PBX_QT@
+ RADIUS=@PBX_RADIUS@
++SPANDSP=@PBX_SPANDSP@
+ SPEEX=@PBX_SPEEX@
+ SQLITE=@PBX_SQLITE@
+ SSL=@PBX_OPENSSL@
diff -ruN asterisk.old/files/patch-configure asterisk/files/patch-configure
--- asterisk.old/files/patch-configure	2007-08-10 22:30:40.000000000 +0600
+++ asterisk/files/patch-configure	2007-10-09 21:18:55.000000000 +0600
@@ -1,9 +1,25 @@
-
-$FreeBSD: ports/net/asterisk/files/patch-configure,v 1.3 2007/08/10 16:30:40 sobomax Exp $
-
---- configure.orig
-+++ configure
-@@ -3926,8 +3926,6 @@
+--- configure.orig	2007-09-14 21:50:49.000000000 +0600
++++ configure	2007-10-09 21:18:50.000000000 +0600
+@@ -820,6 +820,10 @@
+ RADIUS_INCLUDE
+ RADIUS_DIR
+ PBX_RADIUS
++SPANDSP_LIB
++SPANDSP_INCLUDE
++SPANDSP_DIR
++PBX_SPANDSP
+ SPEEX_LIB
+ SPEEX_INCLUDE
+ SPEEX_DIR
+@@ -1530,6 +1534,7 @@
+   --with-qt=PATH          use Qt files in PATH
+   --with-radius=PATH      use Radius Client files in PATH
+   --with-speex=PATH       use Speex files in PATH
++  --with-spandsp=PATH     use Spandsp library files in PATH
+   --with-sqlite=PATH      use SQLite files in PATH
+   --with-suppserv=PATH    use mISDN Supplemental Services files in PATH
+   --with-ssl=PATH         use OpenSSL files in PATH
+@@ -3931,8 +3936,6 @@
  case "${host_os}" in
       freebsd*)
       ac_default_prefix=/usr/local
@@ -12,7 +28,69 @@
       ;;
       *)
       ac_default_prefix=/usr
-@@ -26228,6 +26226,7 @@
+@@ -8302,8 +8305,34 @@
+ 
+ PBX_RADIUS=0
+ 
++SPNDSP_DESCRIP="Spandsp Library"
++SPANDSP_OPTION="spandsp"
+ 
++# Check whether --with-spandsp was given.
++if test "${with_spandsp+set}" = set; then
++  withval=$with_spandsp;
++case ${withval} in
++     n|no)
++     USE_SPANDSP=no
++     PBX_SPANDSP=0
++     ;;
++     y|ye|yes)
++     SPANDSP_DIR="/usr/local"
++     SPANDSP_LIB="-L/usr/local/lib -lspandsp"
++     SPANDSP_INCLUDE="-I${SPANDSP_DIR}/include"
++     SPANDSP_MANDATORY="yes"
++     PBX_SPANDSP=1
++     ;;
++     *)
++     SPANDSP_DIR="${withval}"
++     SPANDSP_LIB="-L${SPANDSP_DIR}/lib -lspandsp"
++     SPANDSP_INCLUDE="-I${SPANDSP_DIR}/include"
++     SPANDSP_MANDATORY="yes"
++     PBX_SPANDSP=1
++     ;;
++esac
+ 
++fi
+ 
+ 
+ 
+@@ -18464,11 +18493,11 @@
+ echo $ECHO_N "checking for UW IMAP Toolkit c-client library... $ECHO_C" >&6; }
+    saved_cppflags="${CPPFLAGS}"
+    saved_libs="${LIBS}"
+-   if test -f ${IMAP_TK_DIR}/c-client/LDFLAGS ; then
+-      imap_ldflags=`cat ${IMAP_TK_DIR}/c-client/LDFLAGS`
++   if test -f ${IMAP_TK_DIR}/include/c-client/LDFLAGS ; then
++      imap_ldflags=`cat ${IMAP_TK_DIR}/include/c-client/LDFLAGS`
+    fi
+-   CPPFLAGS="${CPPFLAGS} -I${IMAP_TK_DIR}/c-client"
+-   LIBS="${LIBS} ${IMAP_TK_DIR}/c-client/c-client.a "`echo ${imap_ldflags}`
++   CPPFLAGS="${CPPFLAGS} -I${IMAP_TK_DIR}/include/c-client"
++   LIBS="${LIBS} ${IMAP_TK_DIR}/lib/libc-client4.a "`echo ${imap_ldflags}`
+    cat >conftest.$ac_ext <<_ACEOF
+ /* confdefs.h.  */
+ _ACEOF
+@@ -18660,8 +18689,8 @@
+    if test "${ac_cv_imap_tk}" = "yes"; then
+       { echo "$as_me:$LINENO: result: yes" >&5
+ echo "${ECHO_T}yes" >&6; }
+-      IMAP_TK_LIB="${IMAP_TK_DIR}/c-client/c-client.a "`echo ${imap_ldflags}`
+-      IMAP_TK_INCLUDE="-I${IMAP_TK_DIR}/c-client"
++      IMAP_TK_LIB="${IMAP_TK_DIR}/lib/libc-client4.a "`echo ${imap_ldflags}`
++      IMAP_TK_INCLUDE="-I${IMAP_TK_DIR}/include/c-client"
+       PBX_IMAP_TK=1
+ 
+ cat >>confdefs.h <<\_ACEOF
+@@ -26261,6 +26290,7 @@
  cat >>conftest.$ac_ext <<_ACEOF
  /* end confdefs.h.  */
  $ac_includes_default
@@ -20,7 +98,7 @@
  #include <${HOME}/openh323/include/h323.h>
  _ACEOF
  rm -f conftest.$ac_objext
-@@ -26268,6 +26267,7 @@
+@@ -26301,6 +26331,7 @@
  cat confdefs.h >>conftest.$ac_ext
  cat >>conftest.$ac_ext <<_ACEOF
  /* end confdefs.h.  */
@@ -28,7 +106,7 @@
  #include <${HOME}/openh323/include/h323.h>
  _ACEOF
  if { (ac_try="$ac_cpp conftest.$ac_ext"
-@@ -26365,6 +26365,7 @@
+@@ -26398,6 +26429,7 @@
  cat >>conftest.$ac_ext <<_ACEOF
  /* end confdefs.h.  */
  $ac_includes_default
@@ -36,7 +114,7 @@
  #include </usr/local/include/openh323/h323.h>
  _ACEOF
  rm -f conftest.$ac_objext
-@@ -26405,6 +26406,7 @@
+@@ -26438,6 +26470,7 @@
  cat confdefs.h >>conftest.$ac_ext
  cat >>conftest.$ac_ext <<_ACEOF
  /* end confdefs.h.  */
@@ -44,7 +122,7 @@
  #include </usr/local/include/openh323/h323.h>
  _ACEOF
  if { (ac_try="$ac_cpp conftest.$ac_ext"
-@@ -26652,7 +26654,7 @@
+@@ -26685,7 +26718,7 @@
  
  	fi
  
@@ -53,7 +131,7 @@
  
  	if test "${HAS_OPENH323:-unset}" != "unset"; then
  	   { echo "$as_me:$LINENO: checking OpenH323 installation validity" >&5
-@@ -31800,6 +31802,7 @@
+@@ -32232,6 +32265,7 @@
  cat >>conftest.$ac_ext <<_ACEOF
  /* end confdefs.h.  */
  $ac_includes_default
@@ -61,7 +139,7 @@
  #include <h323.h>
  _ACEOF
  rm -f conftest.$ac_objext
-@@ -31840,6 +31843,7 @@
+@@ -32272,6 +32306,7 @@
  cat confdefs.h >>conftest.$ac_ext
  cat >>conftest.$ac_ext <<_ACEOF
  /* end confdefs.h.  */
@@ -69,3 +147,23 @@
  #include <h323.h>
  _ACEOF
  if { (ac_try="$ac_cpp conftest.$ac_ext"
+@@ -33842,6 +33877,10 @@
+ RADIUS_INCLUDE!$RADIUS_INCLUDE$ac_delim
+ RADIUS_DIR!$RADIUS_DIR$ac_delim
+ PBX_RADIUS!$PBX_RADIUS$ac_delim
++SPANDSP_LIB!$SPANDSP_LIB$ac_delim
++SPANDSP_INCLUDE!$SPANDSP_INCLUDE$ac_delim
++SPANDSP_DIR!$SPANDSP_DIR$ac_delim
++PBX_SPANDSP!$PBX_SPANDSP$ac_delim
+ SPEEX_LIB!$SPEEX_LIB$ac_delim
+ SPEEX_INCLUDE!$SPEEX_INCLUDE$ac_delim
+ SPEEX_DIR!$SPEEX_DIR$ac_delim
+@@ -33933,7 +33972,7 @@
+ LTLIBOBJS!$LTLIBOBJS$ac_delim
+ _ACEOF
+ 
+-  if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 96; then
++  if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 100; then
+     break
+   elif $ac_last_try; then
+     { { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5
diff -ruN asterisk.old/files/patch-configure.ac asterisk/files/patch-configure.ac
--- asterisk.old/files/patch-configure.ac	1970-01-01 05:00:00.000000000 +0500
+++ asterisk/files/patch-configure.ac	2007-10-09 21:09:46.000000000 +0600
@@ -0,0 +1,19 @@
+--- configure.ac.orig	2007-10-09 21:08:41.000000000 +0600
++++ configure.ac	2007-10-09 21:09:29.000000000 +0600
+@@ -196,6 +196,7 @@
+ AST_EXT_LIB_SETUP([OPENH323], [OpenH323], [h323])
+ AST_EXT_LIB_SETUP([QT], [Qt], [qt])
+ AST_EXT_LIB_SETUP([RADIUS], [Radius Client], [radius])
++AST_EXT_LIB_SETUP([SPANDSP], [Spandsp Library], [spandsp])
+ AST_EXT_LIB_SETUP([SPEEX], [Speex], [speex])
+ AST_EXT_LIB_SETUP([SQLITE], [SQLite], [sqlite])
+ AST_EXT_LIB_SETUP([SUPPSERV], [mISDN Supplemental Services], [suppserv])
+@@ -942,6 +943,8 @@
+ 
+ AST_EXT_LIB_CHECK([RADIUS], [radiusclient-ng], [rc_read_config], [radiusclient-ng.h])
+ 
++AST_EXT_LIB_CHECK([SPANDSP], [spandsp], [fax_init], [spandsp.h], [-ltiff])
++
+ AST_EXT_LIB_CHECK([SPEEX], [speex], [speex_encode], [speex/speex.h], [-lm])
+ 
+ AST_EXT_LIB_CHECK([SQLITE], [sqlite], [sqlite_exec], [sqlite.h])
diff -ruN asterisk.old/files/patch-makeopts.in asterisk/files/patch-makeopts.in
--- asterisk.old/files/patch-makeopts.in	1970-01-01 05:00:00.000000000 +0500
+++ asterisk/files/patch-makeopts.in	2007-10-09 21:07:30.000000000 +0600
@@ -0,0 +1,12 @@
+--- makeopts.in.orig	2007-09-14 21:50:49.000000000 +0600
++++ makeopts.in	2007-10-09 21:06:46.000000000 +0600
+@@ -140,6 +140,9 @@
+ RADIUS_INCLUDE=@RADIUS_INCLUDE@
+ RADIUS_LIB=@RADIUS_LIB@
+ 
++SPANDSP_INCLUDE=@SPANDSP_INCLUDE@
++SPANDSP_LIB=@SPANDSP_LIB@
++
+ SPEEX_INCLUDE=@SPEEX_INCLUDE@
+ SPEEX_LIB=@SPEEX_LIB@
+ 
diff -ruN asterisk.old/pkg-plist asterisk/pkg-plist
--- asterisk.old/pkg-plist	2007-07-27 08:41:09.000000000 +0600
+++ asterisk/pkg-plist	2007-10-12 12:16:47.000000000 +0600
@@ -58,8 +58,6 @@
 etc/asterisk/mgcp.conf-dist
 @unexec if cmp -s %D/etc/asterisk/misdn.conf %D/etc/asterisk/misdn.conf-dist; then rm -f %D/etc/asterisk/misdn.conf; fi
 etc/asterisk/misdn.conf-dist
- at unexec if cmp -s %D/etc/asterisk/modem.conf %D/etc/asterisk/modem.conf-dist; then rm -f %D/etc/asterisk/modem.conf; fi
-etc/asterisk/modem.conf-dist
 @unexec if cmp -s %D/etc/asterisk/modules.conf %D/etc/asterisk/modules.conf-dist; then rm -f %D/etc/asterisk/modules.conf; fi
 etc/asterisk/modules.conf-dist
 @unexec if cmp -s %D/etc/asterisk/musiconhold.conf %D/etc/asterisk/musiconhold.conf-dist; then rm -f %D/etc/asterisk/musiconhold.conf; fi
@@ -137,6 +135,7 @@
 include/asterisk/astdb.h
 include/asterisk/astmm.h
 include/asterisk/astobj.h
+include/asterisk/astobj2.h
 include/asterisk/astosp.h
 include/asterisk/autoconfig.h
 include/asterisk/build.h
@@ -768,6 +767,8 @@
 %%WITH_ZAPTEL%%lib/asterisk/modules/codec_zap.so
 %%WITH_ODBC%%lib/asterisk/modules/res_config_odbc.so
 %%WITH_ODBC%%lib/asterisk/modules/res_odbc.so
+%%WITH_FAX%%lib/asterisk/modules/app_rxfax.so
+%%WITH_FAX%%lib/asterisk/modules/app_txfax.so
 @dirrm share/asterisk/static-http
 @dirrm share/asterisk/sounds/silence
 @dirrm share/asterisk/sounds/phonetic


>Release-Note:
>Audit-Trail:
>Unformatted:



More information about the freebsd-ports-bugs mailing list