Module: sip-router Branch: master Commit: 9b11c8362a0b07cb3fc8779582a92cdc56c07752 URL: http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=9b11c836...
Author: Carsten Bock carsten@ng-voice.com Committer: Carsten Bock carsten@ng-voice.com Date: Thu Oct 16 20:58:28 2014 +0200
modules/pv: Add 7Bit Encoding/Decoding (e.g. for 3GPP-SMS)
---
modules/pv/pv_trans.c | 84 +++++++++++++++++++++++++++++++++++++++++++++++++ modules/pv/pv_trans.h | 2 +- 2 files changed, 85 insertions(+), 1 deletions(-)
diff --git a/modules/pv/pv_trans.c b/modules/pv/pv_trans.c index 96516f5..5c476b3 100644 --- a/modules/pv/pv_trans.c +++ b/modules/pv/pv_trans.c @@ -179,6 +179,62 @@ static int urldecode_param(str *sin, str *sout) { return 0; }
+/* Encode 7BIT PDU */ +static int pdu_7bit_encode(str sin) { + int i, j; + unsigned char hex; + unsigned char nleft; + unsigned char fill; + char HexTbl[] = {"0123456789ABCDEF"}; + + nleft = 1; + j = 0; + for(i = 0; i < sin.len; i++) { + hex = *(sin.s) >> (nleft - 1); + fill = *(sin.s+1) << (8-nleft); + hex = hex | fill; + _tr_buffer[j++] = HexTbl[hex >> 4]; + _tr_buffer[j++] = HexTbl[hex & 0x0F]; + nleft++; + if(nleft == 8) { + sin.s++; + i++; + nleft = 1; + } + sin.s++; + } + _tr_buffer[j] = '\0'; + return j; +} + +/* Decode 7BIT PDU */ +static int pdu_7bit_decode(str sin) { + int i, j; + unsigned char nleft = 1; + unsigned char fill = 0; + unsigned char oldfill = 0; + j = 0; + for(i = 0; i < sin.len; i += 2) { + _tr_buffer[j] = (unsigned char)pv_from_hex(sin.s[i]) << 4; + _tr_buffer[j] |= (unsigned char)pv_from_hex(sin.s[i+1]); + fill = (unsigned char)_tr_buffer[j]; + fill >>= (8 - nleft); + _tr_buffer[j] <<= (nleft -1 ); + _tr_buffer[j] &= 0x7F; + _tr_buffer[j] |= oldfill; + oldfill = fill; + j++; + nleft++; + if(nleft == 8) { + _tr_buffer[j++] = oldfill; + nleft = 1; + oldfill = 0; + } + } + _tr_buffer[j] = '\0'; + return j; +} + /* -- transformations functions */
/*! @@ -312,6 +368,28 @@ int tr_eval_string(struct sip_msg *msg, tr_param_t *tp, int subtype, val->rs.s = _tr_buffer; val->rs.len = i; break; + case TR_S_ENCODE7BIT: + if(!(val->flags&PV_VAL_STR)) + val->rs.s = int2str(val->ri, &val->rs.len); + if(val->rs.len > (TR_BUFFER_SIZE*7/8) -1) + return -1; + i = pdu_7bit_encode(val->rs); + memset(val, 0, sizeof(pv_value_t)); + val->flags = PV_VAL_STR; + val->rs.s = _tr_buffer; + val->rs.len = i; + break; + case TR_S_DECODE7BIT: + if(!(val->flags&PV_VAL_STR)) + val->rs.s = int2str(val->ri, &val->rs.len); + if(val->rs.len>TR_BUFFER_SIZE/2-1) + return -1; + i = pdu_7bit_decode(val->rs); + memset(val, 0, sizeof(pv_value_t)); + val->flags = PV_VAL_STR; + val->rs.s = _tr_buffer; + val->rs.len = i; + break; case TR_S_ENCODEBASE64: if(!(val->flags&PV_VAL_STR)) val->rs.s = int2str(val->ri, &val->rs.len); @@ -1960,6 +2038,12 @@ char* tr_parse_string(str* in, trans_t *t) } else if(name.len==11 && strncasecmp(name.s, "decode.hexa", 11)==0) { t->subtype = TR_S_DECODEHEXA; goto done; + } else if(name.len==11 && strncasecmp(name.s, "encode.7bit", 11)==0) { + t->subtype = TR_S_ENCODE7BIT; + goto done; + } else if(name.len==11 && strncasecmp(name.s, "decode.7bit", 11)==0) { + t->subtype = TR_S_DECODE7BIT; + goto done; } else if(name.len==13 && strncasecmp(name.s, "encode.base64", 13)==0) { t->subtype = TR_S_ENCODEBASE64; goto done; diff --git a/modules/pv/pv_trans.h b/modules/pv/pv_trans.h index 346fd32..be3c7ac 100644 --- a/modules/pv/pv_trans.h +++ b/modules/pv/pv_trans.h @@ -37,7 +37,7 @@ enum _tr_type { TR_NONE=0, TR_STRING, TR_URI, TR_PARAMLIST, TR_NAMEADDR, enum _tr_s_subtype { TR_S_NONE=0, TR_S_LEN, TR_S_INT, TR_S_MD5, TR_S_SHA256, TR_S_SHA384, TR_S_SHA512, TR_S_SUBSTR, TR_S_SELECT, TR_S_ENCODEHEXA, TR_S_DECODEHEXA, - TR_S_ENCODEBASE64, TR_S_DECODEBASE64, + TR_S_ENCODE7BIT, TR_S_DECODE7BIT, TR_S_ENCODEBASE64, TR_S_DECODEBASE64, TR_S_ESCAPECOMMON, TR_S_UNESCAPECOMMON, TR_S_ESCAPEUSER, TR_S_UNESCAPEUSER, TR_S_ESCAPEPARAM, TR_S_UNESCAPEPARAM, TR_S_TOLOWER, TR_S_TOUPPER, TR_S_STRIP, TR_S_STRIPTAIL, TR_S_PREFIXES, TR_S_PREFIXES_QUOT, TR_S_REPLACE,