[PATCH] custom access-log format

Stipe Tolj <[email protected]>
Newsgroups gmane.comp.mobile.kannel.devel
Organization Wapme Systems AG
Message-ID <[email protected]>
Hi list,

the attached patches is a feature add in terms of customizing the
access-log format for bearerbox. This will allow to use custom format
access-log lines using escape codes (commonly known from the
sms-service groups).

Here are the changes:

  * gw/bb_alog.c: handles the custom bearerbox access-log formating
  * gw/bb_smscconn.c: moved log_sms() to gw/bb_alog.c:bb_alog_sms()
  * gw/bearerbox.h: added bb_alog_ prototypes
  * gw/[sms|wap]box.c: harmonized access-log config directive reading
  * gwlib/accesslog.[ch]: alog_open() changed to indicate if markers
should be written to access-log file. If no markers are set, then the
default timestamp prefix is not written, allowing users to
individually set the timestamp in their custom access-log format.
  * gwlib/cfg.def: added config directives 'access-log-time' to
indicate if localtime or gmt should be used within access-log,
'access-log-format' holding the escape code formated line to log,
'access-log-clean' (boolean) indicating if standard markers shoould be
avoided and hence the access-log should be "clean".

Which means you can use this core group for bearerbox in your
configuration:

  group = core
  admin-port = 13000
  smsbox-port = 13001
  admin-password = bar
  ...
  access-log = "/var/log/kannel/access.log"
  access-log-clean = yes
  #access-log-time = gmt
  access-log-format = "%t %l [SMSC:%i] [SVC:%n] [ACT:%A] [BINF:%B]
[from:%p] [to:%P] [flags:%m:%c:%M:%C:%d] [msg:%L:%b] [udh:%U:%u]"
  ...
  store-file = "/var/log/kannel/kannel.store"

which would cause bearerbox to log in our "default" access-log style.


Please try and have a vote on it. If no vetos occur, I'll commit this
to cvs.

Stipe

mailto:[email protected]
-------------------------------------------------------------------
Wapme Systems AG

Münsterstr. 248
40470 Düsseldorf, NRW, Germany

phone: +49.211.74845.0
fax: +49.211.74845.299

mailto:[email protected]
http://www.wapme-systems.de/
-------------------------------------------------------------------

-----BEGIN PGP PUBLIC KEY BLOCK-----
Version: GnuPG v1.2.2 (Cygwin)

mIsEP6mcYwEEAMDnUiUwrbb+xwTFWN6TxF2+XZu7/alwJMeCwMBRvXtPZqfjpPhS
OkBpU0F4TrVuugz1HINTSaJTYq10AzDQXp5NkyWgckqW79nPAWuOX0dicbJk+cN2
nM2TI4KaxUDe6u8hghNEnH/i2lXsUu9apnP/iixzV81VC2je3uc9hZpnAAYptEVT
dGlwZSBUb2xqIChUZWNobm9sb2d5IENlbnRlciAmIFJlc2VhcmNoIExhYikgPHRv
bGpAd2FwbWUtc3lzdGVtcy5kZT6ItAQTAQIAHgUCP6mcYwIbAwYLCQgHAwIDFQID
AxYCAQIeAQIXgAAKCRABV0w1BqPYRuSqA/wPzsQxao2YePENCtgRTrO86U6zg3sl
OcS6CJFI4FZP5h/xD3GRsNH1+MPSvZlomDdpFnr547DGz/Kq9MXuQwVvlVig5yWZ
K5dtKp1r5YLhxJQBhfirZbRFFnYmf19f18J8OoS28tuFVftDl1AIwJS3HLyBTv6H
g2HyLAEKQIp30Q==
=aYCI
-----END PGP PUBLIC KEY BLOCK-----
access-log-format.patch (application/x-unknown-content-type-patch_auto_file, 25.2 KB)
diff -ur ./gw/bb_smscconn.c ../../cvs/gateway/gw/bb_smscconn.c
--- ./gw/bb_smscconn.c	2003-11-24 15:18:32.248534400 +0100
+++ ../../cvs/gateway/gw/bb_smscconn.c	2003-11-21 16:01:02.626726100 +0100
@@ -118,34 +118,6 @@
 int route_incoming_to_boxc(Msg *sms);
 static int route_incoming_to_smsc(SMSCConn *conn, Msg *msg);
 
-static void log_sms(SMSCConn *conn, Msg *sms, char *message)
-{
-    Octstr *text, *udh;
-
-    text = sms->sms.msgdata ? octstr_duplicate(sms->sms.msgdata) : octstr_create("");
-    udh = sms->sms.udhdata ? octstr_duplicate(sms->sms.udhdata) : octstr_create("");
-    if ((sms->sms.coding == DC_8BIT || sms->sms.coding == DC_UCS2))
-	octstr_binary_to_hex(text, 1);
-    octstr_binary_to_hex(udh, 1);
-
-    alog("%s [SMSC:%s] [SVC:%s] [ACT:%s] [BINF:%s] [from:%s] [to:%s] [flags:%d:%d:%d:%d:%d] [msg:%d:%s]"
-	" [udh:%d:%s]",
-	 message,
-	 conn ? (smscconn_id(conn) ? octstr_get_cstr(smscconn_id(conn)) : "")
-	 : "",
-	 sms->sms.service ? octstr_get_cstr(sms->sms.service) : "",
-	 sms->sms.account ? octstr_get_cstr(sms->sms.account) : "",
-	 sms->sms.binfo ? octstr_get_cstr(sms->sms.binfo) : "",
-	 sms->sms.sender ? octstr_get_cstr(sms->sms.sender) : "",
-	 sms->sms.receiver ? octstr_get_cstr(sms->sms.receiver) : "",
-	 sms->sms.mclass, sms->sms.coding, sms->sms.mwi, sms->sms.compress,
-	 sms->sms.dlr_mask,
-	 octstr_len(sms->sms.msgdata), octstr_get_cstr(text),
-	 octstr_len(sms->sms.udhdata), octstr_get_cstr(udh)
-    );
-    octstr_destroy(udh);
-    octstr_destroy(text);
-}
 
 /*---------------------------------------------------------------------------
  * CALLBACK FUNCTIONS
@@ -194,7 +166,7 @@
     (void) store_save(mack);
     msg_destroy(mack);
 
-    log_sms(conn, sms, "Sent SMS");
+    bb_alog_sms(conn, sms, "Sent SMS");
 
     /* generate relay confirmancy message */
     if (DLR_IS_SMSC_SUCCESS(sms->sms.dlr_mask)) {
@@ -240,9 +212,9 @@
 
 	if (conn) counter_increase(conn->failed);
 	if (reason == SMSCCONN_FAILED_DISCARDED)
-	    log_sms(conn, sms, "DISCARDED SMS");
+	    bb_alog_sms(conn, sms, "DISCARDED SMS");
 	else
-	    log_sms(conn, sms, "FAILED Send SMS");
+	    bb_alog_sms(conn, sms, "FAILED Send SMS");
 
         /* generate relay confirmancy message */
         if (DLR_IS_SMSC_FAIL(sms->sms.dlr_mask) ||
@@ -285,7 +257,7 @@
 	numhash_find_number(white_list, sms->sms.sender) < 1) {
 	info(0, "Number <%s> is not in white-list, message discarded",
 	     octstr_get_cstr(sms->sms.sender));
-	log_sms(conn, sms, "REJECTED - not white-listed SMS");
+	bb_alog_sms(conn, sms, "REJECTED - not white-listed SMS");
 	msg_destroy(sms);
         return SMSCCONN_FAILED_REJECTED;
     }
@@ -293,7 +265,7 @@
 	numhash_find_number(black_list, sms->sms.sender) == 1) {
 	info(0, "Number <%s> is in black-list, message discarded",
 	     octstr_get_cstr(sms->sms.sender));
-	log_sms(conn, sms, "REJECTED - black-listed SMS");
+	bb_alog_sms(conn, sms, "REJECTED - black-listed SMS");
 	msg_destroy(sms);
 	return SMSCCONN_FAILED_REJECTED;
     }
@@ -323,9 +295,9 @@
         if (route_incoming_to_boxc(copy) == -1) {
             warning(0, "incoming messages queue too long, dropping a message.");
             if (sms->sms.sms_type == report)
-                log_sms(conn, sms, "DROPPED Received DLR");
+                bb_alog_sms(conn, sms, "DROPPED Received DLR");
             else
-                log_sms(conn, sms, "DROPPED Received SMS");
+                bb_alog_sms(conn, sms, "DROPPED Received SMS");
             msg_destroy(copy);
             /* put nack into store-file */
             copy = msg_create(ack);
@@ -342,9 +314,9 @@
     }
 
     if (sms->sms.sms_type != report)
-	log_sms(conn, sms, "Receive SMS");
+	bb_alog_sms(conn, sms, "Receive SMS");
     else
-	log_sms(conn, sms, "DLR SMS");
+	bb_alog_sms(conn, sms, "DLR SMS");
 
     counter_increase(incoming_sms_counter);
     if (conn != NULL) counter_increase(conn->received);
diff -ur ./gw/bearerbox.c ../../cvs/gateway/gw/bearerbox.c
--- ./gw/bearerbox.c	2003-11-24 15:18:32.278577600 +0100
+++ ../../cvs/gateway/gw/bearerbox.c	2003-11-21 16:01:05.951506900 +0100
@@ -351,12 +351,15 @@
     CfgGroup *grp;
     Octstr *log, *val;
     long loglevel;
+    int lf, m;
 #ifdef HAVE_LIBSSL
     Octstr *ssl_server_cert_file;
     Octstr *ssl_server_key_file;
     int ssl_enabled = 0;
 #endif /* HAVE_LIBSSL */
 
+    /* defaults: use localtime and markers for access-log */
+    lf = m = 1;
 	
     grp = cfg_get_single_group(cfg, octstr_imm("core"));
 
@@ -369,14 +372,27 @@
     }
 
     if (check_config(cfg) == -1)
-	panic(0, "Cannot start with corrupted configuration");
+        panic(0, "Cannot start with corrupted configuration");
 
-    log = cfg_get(grp, octstr_imm("access-log"));
-    if (log != NULL) {
-	alog_open(octstr_get_cstr(log), 1);
-	/* use localtime; XXX let user choose that */
+    /* determine which timezone we use for access logging */
+    if ((log = cfg_get(grp, octstr_imm("access-log-time"))) != NULL) {
+        lf = (octstr_case_compare(log, octstr_imm("gmt")) == 0) ? 0 : 1;
+        octstr_destroy(log);
+    }
 
-	octstr_destroy(log);
+    /* should predefined markers be used, ie. prefixing timestamp */
+    cfg_get_bool(&m, grp, octstr_imm("access-log-clean"));
+
+    /* custom access-log format  */
+    if ((log = cfg_get(grp, octstr_imm("access-log-format"))) != NULL) {
+        bb_alog_init(log);
+        octstr_destroy(log);
+    }
+
+    /* open access-log file */
+    if ((log = cfg_get(grp, octstr_imm("access-log"))) != NULL) {
+        alog_open(octstr_get_cstr(log), lf, m ? 0 : 1);
+        octstr_destroy(log);
     }
 
     log = cfg_get(grp, octstr_imm("store-file"));
diff -ur ./gw/bearerbox.h ../../cvs/gateway/gw/bearerbox.h
--- ./gw/bearerbox.h	2003-11-24 15:18:32.288592000 +0100
+++ ../../cvs/gateway/gw/bearerbox.h	2003-11-21 16:17:27.623081300 +0100
@@ -62,6 +62,8 @@
 
 #include "gwlib/gwlib.h"
 #include "msg.h"
+#include "smscconn.h"
+
 
 /* general bearerbox state */
 
@@ -196,6 +198,19 @@
 /* return all containing messages in the current store */
 Octstr *store_status(int status_type);
 
+
+/*-----------------
+ * bb_alog.c (Custom access-log format handling)
+ */
+
+/* passes the access-log-format string from config to the module */
+void bb_alog_init(Octstr *format);
+
+/* called from bb_smscconn.c to log the various access-log events */
+void bb_alog_sms(SMSCConn *conn, Msg *sms, char *message);
+
+
+
 /*----------------------------------------------------------------
  * Core bearerbox public functions;
  * used only via HTTP adminstration
diff -ur ./gw/smsbox.c ../../cvs/gateway/gw/smsbox.c
--- ./gw/smsbox.c	2003-11-24 15:18:32.308620800 +0100
+++ ../../cvs/gateway/gw/smsbox.c	2003-11-21 15:11:03.674444500 +0100
@@ -3076,12 +3076,14 @@
     Octstr *http_proxy_username = NULL;
     Octstr *http_proxy_password = NULL;
     int ssl = 0;
+    int lf, m;
 
     bb_port = BB_DEFAULT_SMSBOX_PORT;
     bb_ssl = 0;
     bb_host = octstr_create(BB_DEFAULT_HOST);
     logfile = NULL;
     lvl = 0;
+    lf = m = 1;
 
     /*
      * first we take the port number in bearerbox and other values from the
@@ -3199,12 +3201,20 @@
 	     octstr_get_cstr(global_sender));
     }
     
-    p = cfg_get(grp, octstr_imm("access-log"));
-    if (p != NULL) {
-	info(0, "Logging accesses to '%s'.", octstr_get_cstr(p));
-	alog_open(octstr_get_cstr(p), 1);
-	    /* XXX should be able to use gmtime, too */
-	octstr_destroy(p);
+    /* determine which timezone we use for access logging */
+    if ((p = cfg_get(grp, octstr_imm("access-log-time"))) != NULL) {
+        lf = (octstr_case_compare(p, octstr_imm("gmt")) == 0) ? 0 : 1;
+        octstr_destroy(p);
+    }
+
+    /* should predefined markers be used, ie. prefixing timestamp */
+    cfg_get_bool(&m, grp, octstr_imm("access-log-clean"));
+
+    /* open access-log file */
+    if ((p = cfg_get(grp, octstr_imm("access-log"))) != NULL) {
+        info(0, "Logging accesses to '%s'.", octstr_get_cstr(p));
+        alog_open(octstr_get_cstr(p), lf, m ? 0 : 1);
+        octstr_destroy(p);
     }
 
     /* HTTP queueing values */
diff -ur ./gw/wapbox.c ../../cvs/gateway/gw/wapbox.c
--- ./gw/wapbox.c	2003-11-24 15:18:32.328649600 +0100
+++ ../../cvs/gateway/gw/wapbox.c	2003-11-21 15:11:08.641586900 +0100
@@ -124,6 +124,9 @@
     CfgGroup *grp;
     Octstr *s;
     Octstr *logfile;
+    int lf, m;
+
+    lf = m = 1;
 
     cfg_dump(cfg);
     
@@ -179,14 +182,21 @@
         log_set_syslog(NULL, 0);
         debug("wap", 0, "no syslog parameter");
     }
-    s = cfg_get(grp, octstr_imm("access-log"));
-    if (s != NULL) {
+
+    /* determine which timezone we use for access logging */
+    if ((s = cfg_get(grp, octstr_imm("access-log-time"))) != NULL) {
+        lf = (octstr_case_compare(s, octstr_imm("gmt")) == 0) ? 0 : 1;
+        octstr_destroy(s);
+    }
+
+    /* should predefined markers be used, ie. prefixing timestamp */
+    cfg_get_bool(&m, grp, octstr_imm("access-log-clean"));
+
+    /* open access-log file */
+    if ((s = cfg_get(grp, octstr_imm("access-log"))) != NULL) {
         info(0, "Logging accesses to '%s'.", octstr_get_cstr(s));
-        alog_open(octstr_get_cstr(s), 1);
-            /* XXX should be able to use gmtime, too */
+        alog_open(octstr_get_cstr(s), lf, m ? 0 : 1);
         octstr_destroy(s);
-    } else {
-        debug("wap", 0, "Could not open access-log");
     }
 
     /* configure the 'wtls' group */
diff -ur ./gwlib/accesslog.c ../../cvs/gateway/gwlib/accesslog.c
--- ./gwlib/accesslog.c	2003-11-24 15:18:32.348678400 +0100
+++ ../../cvs/gateway/gwlib/accesslog.c	2003-11-21 15:27:16.843793300 +0100
@@ -74,8 +74,8 @@
 
 static FILE *file = NULL;
 static char filename[FILENAME_MAX + 1]; /* to allow re-open */
-
 static int use_localtime;
+static int markers = 1;     /* can be turned-off by 'access-log-clean = yes' */
 
 /*
  * Reopen/rotate lock.
@@ -87,7 +87,8 @@
     if (file == NULL)
 	return;
 
-    alog("Log ends");
+    if (markers)
+        alog("Log ends");
 
     list_lock(writers);
     /* wait for writers to complete */
@@ -99,10 +100,11 @@
     list_unlock(writers);
 
     if (file == NULL) {
-	error(errno, "Couldn't re-open access logfile `%s'.",
-	      filename);
-    } else
-	alog("Log begins");
+        error(errno, "Couldn't re-open access logfile `%s'.", filename);
+    } 
+    else if (markers) {
+        alog("Log begins");
+    }
 }
 
 
@@ -110,12 +112,13 @@
 {
 
     if (file != NULL) {
-	alog("Log ends");
+        if (markers)
+            alog("Log ends");
         list_lock(writers);
         /* wait for writers to complete */
         list_consume(writers);
-	fclose(file);
-	file = NULL;
+        fclose(file);
+        file = NULL;
         list_unlock(writers);
         list_destroy(writers, NULL);
         writers = NULL;
@@ -123,17 +126,20 @@
 }
 
 
-void alog_open(char *fname, int use_localtm)
+void alog_open(char *fname, int use_localtm, int use_markers)
 {
     FILE *f;
     
+    use_localtime = use_localtm;
+    markers = use_markers;
+
     if (file != NULL) {
-	warning(0, "Opening an already opened access log");
-	alog_close();
+        warning(0, "Opening an already opened access log");
+        alog_close();
     }
     if (strlen(fname) > FILENAME_MAX) {
-	error(0, "Access Log filename too long: `%s', cannot open.", fname);
-	return;
+        error(0, "Access Log filename too long: `%s', cannot open.", fname);
+        return;
     }
 
     if (writers == NULL)
@@ -141,14 +147,14 @@
 
     f = fopen(fname, "a");
     if (f == NULL) {
-	error(errno, "Couldn't open logfile `%s'.", fname);
-	return;
+        error(errno, "Couldn't open logfile `%s'.", fname);
+        return;
     }
     file = f;
     strcpy(filename, fname);
     info(0, "Started access logfile `%s'.", filename);
-    use_localtime = use_localtm;
-    alog("Log begins");
+    if (markers)
+        alog("Log begins");
 }
 
 
@@ -157,11 +163,13 @@
     use_localtime = 1;
 }
 
+
 void alog_use_gmtime(void)
 {
     use_localtime = 0;
 }
 
+
 #define FORMAT_SIZE (10*1024)
 static void format(char *buf, const char *fmt)
 {
@@ -170,23 +178,29 @@
     char *p, prefix[1024];
 	
     p = prefix;
-    time(&t);
-    if (use_localtime)
-	tm = gw_localtime(t);
-    else
-	tm = gw_gmtime(t);
-
-    sprintf(p, "%04d-%02d-%02d %02d:%02d:%02d ",
-	    tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
-	    tm.tm_hour, tm.tm_min, tm.tm_sec);
+
+    if (markers) {
+        time(&t);
+        if (use_localtime)
+            tm = gw_localtime(t);
+        else
+            tm = gw_gmtime(t);
+
+        sprintf(p, "%04d-%02d-%02d %02d:%02d:%02d ",
+                tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
+                tm.tm_hour, tm.tm_min, tm.tm_sec);
+    } else {
+        sprintf(p, "");
+    }
 
     if (strlen(prefix) + strlen(fmt) > FORMAT_SIZE / 2) {
-	sprintf(buf, "%s <OUTPUT message too long>\n", prefix);
-	return;
+        sprintf(buf, "%s <OUTPUT message too long>\n", prefix);
+        return;
     }
     sprintf(buf, "%s%s\n", prefix, fmt);
 }
 
+
 /* XXX should we also log automatically into main log, too? */
 
 void alog(const char *fmt, ...)
@@ -195,7 +209,7 @@
     va_list args;
 
     if (file == NULL)
-	return;
+        return;
 
     buf = gw_malloc(FORMAT_SIZE + 1);
     format(buf, fmt);
@@ -213,3 +227,4 @@
     va_end(args);
     gw_free(buf);
 }
+
diff -ur ./gwlib/accesslog.h ../../cvs/gateway/gwlib/accesslog.h
--- ./gwlib/accesslog.h	2003-11-24 15:18:32.368707200 +0100
+++ ../../cvs/gateway/gwlib/accesslog.h	2003-11-21 14:30:53.578897300 +0100
@@ -75,7 +75,7 @@
 /* open access log with filename fname. if use_localtime != 0 then
  * all events are logged with localtime, not GMT
  */
-void alog_open(char *fname, int use_localtime);
+void alog_open(char *fname, int use_localtime, int use_markers);
 
 /* close access log. Do nothing if no open file */
 void alog_close(void);
diff -ur ./gwlib/cfg.def ../../cvs/gateway/gwlib/cfg.def
--- ./gwlib/cfg.def	2003-11-24 15:18:32.378721600 +0100
+++ ../../cvs/gateway/gwlib/cfg.def	2003-11-21 14:47:42.830129300 +0100
@@ -94,6 +94,9 @@
     OCTSTR(log-file)
     OCTSTR(log-level)
     OCTSTR(access-log)
+    OCTSTR(access-log-time)
+    OCTSTR(access-log-format)
+    OCTSTR(access-log-clean)
     OCTSTR(store-file)
     OCTSTR(unified-prefix)
     OCTSTR(white-list)

diff -urN ./gw/bb_alog.c ../../cvs/gateway/gw/bb_alog.c
--- ./gw/bb_alog.c	1970-01-01 01:00:00.000000000 +0100
+++ ../../cvs/gateway/gw/bb_alog.c	2003-11-24 15:32:59.816035200 +0100
@@ -0,0 +1,368 @@
+/* ==================================================================== 
+ * The Kannel Software License, Version 1.0 
+ * 
+ * Copyright (c) 2001-2003 Kannel Group  
+ * Copyright (c) 1998-2001 WapIT Ltd.   
+ * All rights reserved. 
+ * 
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions 
+ * are met: 
+ * 
+ * 1. Redistributions of source code must retain the above copyright 
+ *    notice, this list of conditions and the following disclaimer. 
+ * 
+ * 2. Redistributions in binary form must reproduce the above copyright 
+ *    notice, this list of conditions and the following disclaimer in 
+ *    the documentation and/or other materials provided with the 
+ *    distribution. 
+ * 
+ * 3. The end-user documentation included with the redistribution, 
+ *    if any, must include the following acknowledgment: 
+ *       "This product includes software developed by the 
+ *        Kannel Group (http://www.kannel.org/)." 
+ *    Alternately, this acknowledgment may appear in the software itself, 
+ *    if and wherever such third-party acknowledgments normally appear. 
+ * 
+ * 4. The names "Kannel" and "Kannel Group" must not be used to 
+ *    endorse or promote products derived from this software without 
+ *    prior written permission. For written permission, please  
+ *    contact [email protected]. 
+ * 
+ * 5. Products derived from this software may not be called "Kannel", 
+ *    nor may "Kannel" appear in their name, without prior written 
+ *    permission of the Kannel Group. 
+ * 
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED 
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
+ * DISCLAIMED.  IN NO EVENT SHALL THE KANNEL GROUP OR ITS CONTRIBUTORS 
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,  
+ * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT  
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR  
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,  
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE  
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,  
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ * ==================================================================== 
+ * 
+ * This software consists of voluntary contributions made by many 
+ * individuals on behalf of the Kannel Group.  For more information on  
+ * the Kannel Group, please see <http://www.kannel.org/>. 
+ * 
+ * Portions of this software are based upon software originally written at  
+ * WapIT Ltd., Helsinki, Finland for the Kannel project.  
+ */ 
+
+/*
+ * gw/bb_alog.c -- encapsulate custom access log logic and escape code parsing
+ *
+ * Stipe Tolj <[email protected]
+ */
+
+#include "gwlib/gwlib.h"
+#include "msg.h"
+#include "sms.h"
+#include "bearerbox.h"
+#include "smscconn.h"
+
+static Octstr *custom_log_format = NULL;
+
+
+/********************************************************************
+ * Routine to escape the values into the custom log format.
+ *
+ * The following escape code values are acceptable within the 
+ * 'access-log-format' config directive of bearerbox:
+ *
+ *   %l - log message
+ *   %i - smsc-id
+ *   %n - service-name (for MO) or sendsms-user (for MT)
+ *   %A  - account
+ *   %B - billing identifier/information
+ *   %p - sender (from) 
+ *   %P - receiver (to)
+ *   %m - message class (mclass)
+ *   %c - coding
+ *   %M - message waiting indicator (mwi)
+ *   %C - compress indicator
+ *   %d - dlr_mask
+ *   %a - the orginal SMS message, spaces squeezed
+ *   %u - UDH data (in escaped form)
+ *   %U - length of UDH data
+ *   %k - the keyword in the SMS request (the first word in the SMS message) 
+ *   %s - next word from the SMS message, starting with the second one
+ *   %S - same as %s, but '*' is converted to '~' 
+ *   %r - words not yet used by %s
+ *   %b - the orginal SMS message
+ *   %L - length of SMS message
+ *   %t - the time of the message, formatted as "YYYY-MM-DD HH:MM:SS"
+ *   %T - the time of the message, in UNIX epoch timestamp format
+ *   %I - the internal message ID
+ *
+ * Most escape codes should be compatibel with escape codes used in
+ * sms-service groups.
+ *
+ * The default access-log-format would look like this (if access-log-clean is true):
+ *   "%t %l [SMSC:%i] [SVC:%n] [ACT:%A] [BINF:%B] [from:%p] [to:%P] \
+ *    [flags:%m:%c:%M:%C:%d] [msg:%L:%b] [udh:%U:%u]"
+ */
+  
+static Octstr *get_pattern(SMSCConn *conn, Msg *msg, char *message)
+{
+    int nextarg, j;
+    struct tm tm;
+    int num_words;
+    List *word_list;
+    Octstr *result, *pattern;
+    long pattern_len;
+    long pos;
+    int c;
+    long i;
+    Octstr *temp, *text, *udh;
+ 
+    text = msg->sms.msgdata ? octstr_duplicate(msg->sms.msgdata) : octstr_create("");
+    udh = msg->sms.udhdata ? octstr_duplicate(msg->sms.udhdata) : octstr_create("");
+    if ((msg->sms.coding == DC_8BIT || msg->sms.coding == DC_UCS2))
+        octstr_binary_to_hex(text, 1);
+    octstr_binary_to_hex(udh, 1);
+
+    if (octstr_len(text)) {
+        word_list = octstr_split_words(text);
+        num_words = list_len(word_list);
+    } else {
+    	word_list = list_create();
+        num_words = 0;
+    }
+
+    result = octstr_create("");
+    pattern = octstr_duplicate(custom_log_format);
+
+    pattern_len = octstr_len(pattern);
+    nextarg = 1;
+    pos = 0;
+
+    for (;;) {
+        while (pos < pattern_len) {
+            c = octstr_get_char(pattern, pos);
+            if (c == '%' && pos + 1 < pattern_len)
+                break;
+            octstr_append_char(result, c);
+            ++pos;
+        }
+
+        if (pos == pattern_len)
+            break;
+
+    switch (octstr_get_char(pattern, pos + 1)) {
+	case 'k':
+	    if (num_words <= 0)
+            break;
+	    octstr_append(result, list_get(word_list, 0));
+	    break;
+
+    case 's':
+	    if (nextarg >= num_words)
+            break;
+	    octstr_append(result, list_get(word_list, nextarg));
+	    ++nextarg;
+	    break;
+
+	case 'S':
+	    if (nextarg >= num_words)
+            break;
+	    temp = list_get(word_list, nextarg);
+	    for (i = 0; i < octstr_len(temp); ++i) {
+		if (octstr_get_char(temp, i) == '*')
+		    octstr_append_char(result, '~');
+		else
+		    octstr_append_char(result, octstr_get_char(temp, i));
+	    }
+	    ++nextarg;
+	    break;
+
+	case 'r':
+	    for (j = nextarg; j < num_words; ++j) {
+		if (j != nextarg)
+		    octstr_append_char(result, '+');
+		octstr_append(result, list_get(word_list, j));
+	    }
+	    break;
+    
+	case 'l':
+	    octstr_append_cstr(result, message);
+	    break;
+
+	case 'P':
+	    octstr_append(result, msg->sms.receiver);
+	    break;
+
+	case 'p':
+	    octstr_append(result, msg->sms.sender);
+	    break;
+
+	case 'a':
+	    for (j = 0; j < num_words; ++j) {
+            if (j > 0)
+                octstr_append_char(result, ' ');
+            octstr_append(result, list_get(word_list, j));
+        }
+        break;
+
+	case 'b':
+	    octstr_append(result, text);
+	    break;
+
+	case 'L':
+	    octstr_append_decimal(result, octstr_len(msg->sms.msgdata));
+	    break;
+
+	case 't':
+	    tm = gw_gmtime(msg->sms.time);
+	    octstr_format_append(result, "%04d-%02d-%02d %02d:%02d:%02d",
+				 tm.tm_year + 1900,
+				 tm.tm_mon + 1,
+				 tm.tm_mday,
+				 tm.tm_hour,
+				 tm.tm_min,
+				 tm.tm_sec);
+	    break;
+
+	case 'T':
+	    if (msg->sms.time == -1)
+            break;
+	    octstr_format_append(result, "%ld", msg->sms.time);
+	    break;
+
+	case 'i':
+	    if (msg->sms.smsc_id == NULL)
+            break;
+	    octstr_append(result, msg->sms.smsc_id);
+	    break;
+
+	case 'I':
+	    if (msg->sms.id == -1)
+            break;
+	    octstr_format_append(result, "%ld", msg->sms.id);
+	    break;
+
+	case 'n':
+	    if (msg->sms.service == NULL)
+            break;
+	    octstr_append(result, msg->sms.service);
+	    break;
+
+	case 'd':
+	    octstr_append_decimal(result, msg->sms.dlr_mask);
+	    break;
+
+	case 'c':
+	    octstr_append_decimal(result, msg->sms.coding);
+	    break;
+
+	case 'm':
+	    octstr_append_decimal(result, msg->sms.mclass);
+	    break;
+
+	case 'C':
+	    octstr_append_decimal(result, msg->sms.compress);
+	    break;
+
+	case 'M':
+	    octstr_append_decimal(result, msg->sms.mwi);
+	    break;
+
+	case 'u':
+	    if (octstr_len(udh)) {
+            octstr_append(result, udh);
+	    }
+	    break;
+
+	case 'U':
+	    octstr_append_decimal(result, octstr_len(msg->sms.udhdata));
+	    break;
+
+	case 'B':  /* billing identifier/information */
+	    if (octstr_len(msg->sms.binfo)) {
+            octstr_append(result, msg->sms.binfo);
+        }
+        break;
+
+	case 'A':  /* account */
+	    if (octstr_len(msg->sms.account)) {
+            octstr_append(result, msg->sms.account);
+        }
+        break;
+
+    /* XXX add more here if needed */
+
+	case '%':
+	    octstr_format_append(result, "%%");
+	    break;
+
+	default:
+	    octstr_format_append(result, "%%%c",
+	    	    	    	 octstr_get_char(pattern, pos + 1));
+	    break;
+	}
+
+	pos += 2;
+    }
+
+    list_destroy(word_list, octstr_destroy_item);
+
+    return result;
+}
+
+
+/********************************************************************
+ * 
+ */
+
+void bb_alog_init(Octstr *format)
+{
+    gw_assert(format != NULL);
+
+    custom_log_format = octstr_duplicate(format);
+}
+
+
+void bb_alog_sms(SMSCConn *conn, Msg *sms, char *message)
+{
+    Octstr *text, *udh;
+
+    text = udh = NULL;
+
+    /* if we don't have any custom log, then use our "default" one */
+    
+    if (custom_log_format == NULL) {
+        text = sms->sms.msgdata ? octstr_duplicate(sms->sms.msgdata) : octstr_create("");
+        udh = sms->sms.udhdata ? octstr_duplicate(sms->sms.udhdata) : octstr_create("");
+        if ((sms->sms.coding == DC_8BIT || sms->sms.coding == DC_UCS2))
+            octstr_binary_to_hex(text, 1);
+        octstr_binary_to_hex(udh, 1);
+
+        alog("%s [SMSC:%s] [SVC:%s] [ACT:%s] [BINF:%s] [from:%s] [to:%s] [flags:%d:%d:%d:%d:%d] "
+             "[msg:%d:%s] [udh:%d:%s]",
+             message,
+             conn ? (smscconn_id(conn) ? octstr_get_cstr(smscconn_id(conn)) : "") : "",
+             sms->sms.service ? octstr_get_cstr(sms->sms.service) : "",
+             sms->sms.account ? octstr_get_cstr(sms->sms.account) : "",
+             sms->sms.binfo ? octstr_get_cstr(sms->sms.binfo) : "",
+             sms->sms.sender ? octstr_get_cstr(sms->sms.sender) : "",
+             sms->sms.receiver ? octstr_get_cstr(sms->sms.receiver) : "",
+             sms->sms.mclass, sms->sms.coding, sms->sms.mwi, sms->sms.compress,
+             sms->sms.dlr_mask, 
+             octstr_len(sms->sms.msgdata), octstr_get_cstr(text),
+             octstr_len(sms->sms.udhdata), octstr_get_cstr(udh)
+        );
+
+    } else {
+        text = get_pattern(conn, sms, message);
+        alog("%s", octstr_get_cstr(text));
+    }
+
+    octstr_destroy(udh);
+    octstr_destroy(text);
+}
+
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.