Skip to content

Commit

Permalink
proto_smpp: convert GSM7 to UTF-8 for incoming SM
Browse files Browse the repository at this point in the history
Thanks to @johandeclercqdemocon for reporting this in #1935

(cherry picked from commit 417ac11)
  • Loading branch information
razvancrainea committed Jan 14, 2020
1 parent 5006ab2 commit 2e2143f
Show file tree
Hide file tree
Showing 2 changed files with 96 additions and 7 deletions.
100 changes: 94 additions & 6 deletions modules/proto_smpp/smpp.c
Original file line number Diff line number Diff line change
Expand Up @@ -350,6 +350,95 @@ static int build_enquire_link_request(smpp_enquire_link_req_t **preq, smpp_sessi
err:
return -1;
}
static int convert_gsm7_to_utf8(unsigned char *input, int input_len, char *output)
{
static unsigned int table_gsm7_to_utf8[] = {\
'@', 0xA3, '$', 0xA5, 0xE8, 0xE9, 0xF9, 0xEC,
0xF2, 0xC7, 0x10, 0xd8, 0xF8, 0x13, 0xC5, 0xE5,
0x394, '_', 0x3A6, 0x393, 0x39B, 0x3A9, 0x3A0, 0x3A8,
0x3A3, 0x398, 0x39E, '?', 0xC6, 0xE6, 0xDF, 0xC9,
' ', '!', '"', '#', 0xA4, '%', '&', '\'',
'(', ')', '*', '+', ',', '-', '.', '/',
'0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', ':', ';', '<', '=', '>', '?',
0xA1, 'A', 'B', 'C', 'D', 'E', 'F', 'G',
'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
'X', 'Y', 'Z', 0xC4, 0xD6, 0xD1, 0xDC, 0xA7,
0xBF, 'a', 'b', 'c', 'd', 'e', 'f', 'g',
'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
'x', 'y', 'z', 0xE4, 0xF6, 0xF1, 0xFC, 0xE0,
};
char *p = output;
int i, t;
unsigned char c;
for (i = 0; i < input_len; i++) {
c = input[i];
if (c == 0x1B) {
/* escaped character - check the next char */
switch (input[++i]) {
case 0x0A:
t = 0x0A; /* FF is a Page Break control, treated like LF */
break;
case 0x14:
t = '^';
break;
case 0x28:
t = '{';
break;
case 0x29:
t = '}';
break;
case 0x2F:
t = '\\';
break;
case 0x3C:
t = '[';
break;
case 0x3D:
t = '~';
break;
case 0x3E:
t = ']';
break;
case 0x40:
t = '|';
break;
case 0x65:
t = 0x20AC;
break;
case 0x0D: /* CR2 - control character */
case 0x1B: /* SS2 - Single shift Escape */
t = '?'; /* unknown extended char */
break;
}
} else if (c < 0x80)
t = table_gsm7_to_utf8[c];
else
t = c;
if (t > 0xFF) {
if (t > 0x10000) {
/* four bytes */
*p++ = 0xF0 | ((t >> 18) & 0x07); /* 11110xxx */
*p++ = 0x80 | ((t >> 12) & 0x3F); /* 10xxxxxx */
*p++ = 0x80 | ((t >> 6) & 0x3F); /* 10xxxxxx */
*p++ = 0x80 | (t & 0x3F); /* 10xxxxxx */
} else if (t > 0x800) {
/* three bytes */
*p++ = 0xE0 | ((t >> 12) & 0x0F); /* 1110xxxx */
*p++ = 0x80 | ((t >> 6) & 0x3F); /* 10xxxxxx */
*p++ = 0x80 | (t & 0x3F); /* 10xxxxxx */
} else {
/* two bytes */
*p++ = 0xC0 | ((t >> 6) & 0x1F); /* 110xxxxx */
*p++ = 0x80 | (t & 0x3F); /* 10xxxxxx */
}
} else
*p++ = (unsigned char )t; /* 0xxxxxxx */
}
return p - output;
}

static int build_submit_or_deliver_request(smpp_submit_sm_req_t **preq, str *src, str *dst, str *message, smpp_session_t *session)
{
Expand Down Expand Up @@ -395,7 +484,7 @@ static int build_submit_or_deliver_request(smpp_submit_sm_req_t **preq, str *src
body->dest_addr_npi = session->dest_addr_npi;
strncpy(body->destination_addr, dst->s, dst->len);
body->sm_length = message->len;
strncpy(body->short_message, message->s, message->len);
memcpy(body->short_message, message->s, message->len);

uint32_t body_len = get_payload_from_submit_sm_body(req->payload.s + HEADER_SZ, body);

Expand Down Expand Up @@ -1092,9 +1181,6 @@ int send_submit_or_deliver_request(str *msg, str *src, str *dst,
}

ret = smpp_send_msg(session, &req->payload);
pkg_free(req);

free_req:
free_smpp_msg(req);
return ret;
}
Expand Down Expand Up @@ -1122,6 +1208,7 @@ static int recv_smpp_msg(smpp_header_t *header, smpp_deliver_sm_t *body,
{
static str msg_type = str_init("MESSAGE");

char sms_body[4 * MAX_SMS_CHARACTERS]; /* 4 bytes for each char in UTF-8 */
char hdrs[1024];
char *p = hdrs;
char src[128];
Expand All @@ -1143,8 +1230,9 @@ static int recv_smpp_msg(smpp_header_t *header, smpp_deliver_sm_t *body,
dst_str.len = strlen(dst);

str body_str;
body_str.s = body->short_message;
body_str.len = body->sm_length;
body_str.len = convert_gsm7_to_utf8((unsigned char *)body->short_message,
body->sm_length,sms_body);
body_str.s = sms_body;

tmb.t_request(&msg_type, /* Type of the message */
&dst_str, /* Request-URI */
Expand Down
3 changes: 2 additions & 1 deletion modules/proto_smpp/smpp.h
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ typedef struct smpp_optional{
#define MAX_SCHEDULE_DELIVERY_LEN 1
#define MAX_VALIDITY_PERIOD 1
#define MAX_MESSAGE_ID 65
#define MAX_SMS_CHARACTERS 254

typedef struct {
char system_id[MAX_SYSTEM_ID_LEN];
Expand Down Expand Up @@ -174,7 +175,7 @@ typedef struct {
uint8_t data_coding;
uint8_t sm_default_msg_id;
uint8_t sm_length;
char short_message[254];
char short_message[MAX_SMS_CHARACTERS];
} smpp_submit_sm_t;

typedef struct {
Expand Down

0 comments on commit 2e2143f

Please sign in to comment.