From owner-freebsd-ports-bugs@FreeBSD.ORG Wed Aug 22 10:40:02 2007 Return-Path: Delivered-To: freebsd-ports-bugs@hub.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 0275616A469 for ; Wed, 22 Aug 2007 10:40:02 +0000 (UTC) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (freefall.freebsd.org [IPv6:2001:4f8:fff6::28]) by mx1.freebsd.org (Postfix) with ESMTP id CC76813C469 for ; Wed, 22 Aug 2007 10:40:01 +0000 (UTC) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (gnats@localhost [127.0.0.1]) by freefall.freebsd.org (8.14.1/8.14.1) with ESMTP id l7MAe1wM070388 for ; Wed, 22 Aug 2007 10:40:01 GMT (envelope-from gnats@freefall.freebsd.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.14.1/8.14.1/Submit) id l7MAe1ov070387; Wed, 22 Aug 2007 10:40:01 GMT (envelope-from gnats) Resent-Date: Wed, 22 Aug 2007 10:40:01 GMT Resent-Message-Id: <200708221040.l7MAe1ov070387@freefall.freebsd.org> Resent-From: FreeBSD-gnats-submit@FreeBSD.org (GNATS Filer) Resent-To: freebsd-ports-bugs@FreeBSD.org Resent-Reply-To: FreeBSD-gnats-submit@FreeBSD.org, Vladimir Korkodinov Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 1FE8016A417 for ; Wed, 22 Aug 2007 10:31:38 +0000 (UTC) (envelope-from nobody@FreeBSD.org) Received: from www.freebsd.org (www.freebsd.org [IPv6:2001:4f8:fff6::21]) by mx1.freebsd.org (Postfix) with ESMTP id 0B6A013C48A for ; Wed, 22 Aug 2007 10:31:38 +0000 (UTC) (envelope-from nobody@FreeBSD.org) Received: from www.freebsd.org (localhost [127.0.0.1]) by www.freebsd.org (8.14.1/8.14.1) with ESMTP id l7MAVb7q082008 for ; Wed, 22 Aug 2007 10:31:37 GMT (envelope-from nobody@www.freebsd.org) Received: (from nobody@localhost) by www.freebsd.org (8.14.1/8.14.1/Submit) id l7MAVbga082005; Wed, 22 Aug 2007 10:31:37 GMT (envelope-from nobody) Message-Id: <200708221031.l7MAVbga082005@www.freebsd.org> Date: Wed, 22 Aug 2007 10:31:37 GMT From: Vladimir Korkodinov To: freebsd-gnats-submit@FreeBSD.org X-Send-Pr-Version: www-3.1 Cc: Subject: ports/115710: [UPDATE] net/asterisk to 1.4.11(numerous bug fixes) X-BeenThere: freebsd-ports-bugs@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Ports bug reports List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 22 Aug 2007 10:40:02 -0000 >Number: 115710 >Category: ports >Synopsis: [UPDATE] net/asterisk to 1.4.11(numerous bug fixes) >Confidential: no >Severity: serious >Priority: high >Responsible: freebsd-ports-bugs >State: open >Quarter: >Keywords: >Date-Required: >Class: update >Submitter-Id: current-users >Arrival-Date: Wed Aug 22 10:40:01 GMT 2007 >Closed-Date: >Last-Modified: >Originator: Vladimir Korkodinov >Release: STABLE6 >Organization: >Environment: FreeBSD xxxxxx 6.2-STABLE FreeBSD 6.2-STABLE #2: Fri Jul 27 01:04:19 YEKST 2007 viper@xxxxxxx:/usr/obj/usr/src/sys/viper2 i386 >Description: >From asterisk.org "This version contains numerous bug fixes. One of these is for a security issue in chan_sip. The issue is that SIP dialog history was being stored in memory regardless if the option for this was turned on or off. This could be abused to cause a system using chan_sip to run out of memory. The security issue is documented in AST-2007-020. Affected systems include any that are using chan_sip. Also, only Asterisk 1.4 is affected. Asterisk 1.2 is not vulnerable to this issue. * http://downloads.digium.com/pub/asa/AST-2007-020.pdf" >How-To-Repeat: >Fix: Apply patch o Upgrade to 1.4.11. o Adds to build asterisk with the option IMAP STORAGE. o Enable fax-related modules. Taken from the site http://soft-switch.org/downloads/snapshots/spandsp/test-apps-asterisk-1.4/ Compiled only with spandsp> 0.0.3 I am not leaving the idea to solve the problem with faxes within the existing port. I really do not want to open a new port. I hope maintainer will be forthcoming. Patch attached with submission follows: diff -ruN asterisk.orig/Makefile asterisk/Makefile --- asterisk.orig/Makefile 2007-08-13 23:35:37.000000000 +0600 +++ asterisk/Makefile 2007-08-22 16:09:58.000000000 +0600 @@ -6,7 +6,7 @@ # PORTNAME= asterisk -PORTVERSION= 1.4.10 +PORTVERSION= 1.4.11 CATEGORIES= net MASTER_SITES= http://ftp.digium.com/pub/asterisk/ \ http://ftp.digium.com/pub/asterisk/old-releases/ @@ -47,8 +47,11 @@ 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 \ +WITH_CODEC_PATCH=no# don`t want build with new release .include .if ${ARCH} == "i386" || ${ARCH} == "amd64" @@ -163,8 +166,50 @@ 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.8:${PORTSDIR}/mail/cclient +PLIST_SUB+= WITH_IMAP +.endif + post-patch: ${REINPLACE_CMD} -e 's|/var/lib|${PREFIX}/share|g' ${WRKSRC}/configs/musiconhold.conf.sample +.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 diff -ruN asterisk.orig/distinfo asterisk/distinfo --- asterisk.orig/distinfo 2007-08-13 23:35:37.000000000 +0600 +++ asterisk/distinfo 2007-08-22 16:03:50.000000000 +0600 @@ -1,6 +1,6 @@ -MD5 (asterisk-1.4.10.tar.gz) = 69057e2916287f6e2a1e36dba6d6800d -SHA256 (asterisk-1.4.10.tar.gz) = 72bbb19e35ec304df06dca717b7ac2cae0d3409fe47c17c2dcf75850f61ddbe1 -SIZE (asterisk-1.4.10.tar.gz) = 11208127 +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.10-codec-negotiation-20070810.diff.gz) = ddcd2c8beda46ae569174b3f50d4af2d SHA256 (asterisk-1.4.10-codec-negotiation-20070810.diff.gz) = a714f5c9db8d34fb55a601472ae7b6b6555341acc7d774c3a91fd26cdf10476c SIZE (asterisk-1.4.10-codec-negotiation-20070810.diff.gz) = 37676 diff -ruN asterisk.orig/files/patch-apps::app_rxfax.c asterisk/files/patch-apps::app_rxfax.c --- asterisk.orig/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 ++ * ++ * This program is free software, distributed under the terms of ++ * the GNU General Public License ++ */ ++ ++/*** MODULEINFO ++ spandsp ++***/ ++ ++#include "asterisk.h" ++ ++ASTERISK_FILE_VERSION(__FILE__, "$Revision:$") ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#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.orig/files/patch-apps::app_txfax.c asterisk/files/patch-apps::app_txfax.c --- asterisk.orig/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 ++ * ++ * This program is free software, distributed under the terms of ++ * the GNU General Public License ++ */ ++ ++/*** MODULEINFO ++ spandsp ++***/ ++ ++#include "asterisk.h" ++ ++ASTERISK_FILE_VERSION(__FILE__, "$Revision:$") ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#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 ------------------------------------------------------------*/ >Release-Note: >Audit-Trail: >Unformatted: