/*
* TeleStax, Open Source Cloud Communications Copyright 2012.
* and individual contributors
* by the @authors tag. See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.mobicents.protocols.ss7.map.datacoding;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertTrue;
import static org.testng.Assert.assertFalse;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.Charset;
import org.mobicents.protocols.ss7.map.api.smstpdu.AbsoluteTimeStamp;
import org.mobicents.protocols.ss7.map.api.smstpdu.NumberingPlanIdentification;
import org.mobicents.protocols.ss7.map.api.smstpdu.TypeOfNumber;
import org.mobicents.protocols.ss7.map.api.smstpdu.UserDataHeader;
import org.mobicents.protocols.ss7.map.api.smstpdu.UserDataHeaderElement;
import org.mobicents.protocols.ss7.map.datacoding.GSMCharset;
import org.mobicents.protocols.ss7.map.datacoding.GSMCharsetDecoder;
import org.mobicents.protocols.ss7.map.datacoding.GSMCharsetDecodingData;
import org.mobicents.protocols.ss7.map.datacoding.GSMCharsetEncoder;
import org.mobicents.protocols.ss7.map.datacoding.GSMCharsetEncodingData;
import org.mobicents.protocols.ss7.map.datacoding.Gsm7EncodingStyle;
import org.mobicents.protocols.ss7.map.service.sms.SmsSignalInfoImpl;
import org.mobicents.protocols.ss7.map.smstpdu.AbsoluteTimeStampImpl;
import org.mobicents.protocols.ss7.map.smstpdu.AddressFieldImpl;
import org.mobicents.protocols.ss7.map.smstpdu.ConcatenatedShortMessagesIdentifierImpl;
import org.mobicents.protocols.ss7.map.smstpdu.DataCodingSchemeImpl;
import org.mobicents.protocols.ss7.map.smstpdu.ProtocolIdentifierImpl;
import org.mobicents.protocols.ss7.map.smstpdu.SmsDeliverTpduImpl;
import org.mobicents.protocols.ss7.map.smstpdu.UserDataHeaderImpl;
import org.mobicents.protocols.ss7.map.smstpdu.UserDataImpl;
import org.testng.annotations.Test;
/**
*
* @author amit bhayani
* @author sergey vetyutnev
*
*/
public class GSMCharsetTest {
@Test(groups = { "functional.encode", "datacoding" })
public void testEncode() throws Exception {
this.doTestEncode("123456\r", new byte[] { 49, -39, -116, 86, -77, 53, 26 }, Gsm7EncodingStyle.bit7_ussd_style, null, 7);
this.doTestEncode("1\r", new byte[] { -79, 6 }, Gsm7EncodingStyle.bit7_ussd_style, null, 2);
this.doTestEncode("1", new byte[] { 49 }, Gsm7EncodingStyle.bit7_ussd_style, null, 1);
// case: adding '\r' instead of '@' - USSD style
this.doTestEncode("1234567", new byte[] { 49, -39, -116, 86, -77, -35, 26 }, Gsm7EncodingStyle.bit7_ussd_style, null, 7);
// case: adding double '\r' when '\r' will be removed at the decoder side - USSD style
this.doTestEncode("1234567\r", new byte[] { 49, -39, -116, 86, -77, -35, 26, 13 }, Gsm7EncodingStyle.bit7_ussd_style, null, 8);
// case: adding '@' (not '\r') - SMS style
this.doTestEncode("1234567", new byte[] { 49, -39, -116, 86, -77, -35, 0 }, Gsm7EncodingStyle.bit7_sms_style, null, 7);
// case: do not adding double '\r' when '\r' will be removed at the decoder side - SMS style
this.doTestEncode("1234567\r", new byte[] { 49, -39, -116, 86, -77, -35, 26 }, Gsm7EncodingStyle.bit7_sms_style, null, 8);
// This raw data is from nad1053.pcap, 2nd packet.
this.doTestEncode("*125*+31628839999#", new byte[] { (byte) 0xaa, (byte) 0x98, (byte) 0xac, (byte) 0xa6, 0x5a,
(byte) 0xcd, 0x62, 0x36, 0x19, 0x0e, 0x37, (byte) 0xcb, (byte) 0xe5, 0x72, (byte) 0xb9, 0x11 }, Gsm7EncodingStyle.bit7_ussd_style, null, 18);
// This raw data is from nad1053.pcap, last packet.
this.doTestEncode("You don t have enough credit to call this number. ", new byte[] { (byte) 0xd9, (byte) 0x77, 0x1d,
0x44, (byte) 0x7e, (byte) 0xbb, 0x41, 0x74, 0x10, 0x3a, 0x6c, 0x2f, (byte) 0x83, (byte) 0xca, (byte) 0xee,
0x77, (byte) 0xfd, (byte) 0x8c, 0x06, (byte) 0x8d, (byte) 0xe5, 0x65, 0x72, (byte) 0x9a, 0x0e, (byte) 0xa2,
(byte) 0xbf, 0x41, (byte) 0xe3, 0x30, (byte) 0x9b, 0x0d, (byte) 0xa2, (byte) 0xa3, (byte) 0xd3, 0x73,
(byte) 0x90, (byte) 0xbb, (byte) 0xde, 0x16, (byte) 0x97, (byte) 0xe5, 0x2e, 0x10 }, Gsm7EncodingStyle.bit7_ussd_style, null, 50);
// The USSD String represented by above raw data
this.doTestEncode("ndmgapp2ndmgapp2", new byte[] { 0x6e, 0x72, (byte) 0xfb, 0x1c, (byte) 0x86, (byte) 0xc3, 0x65, 0x6e,
0x72, (byte) 0xfb, 0x1c, (byte) 0x86, (byte) 0xc3, 0x65 }, Gsm7EncodingStyle.bit7_ussd_style, null, 16);
this.doTestEncode("*88#", new byte[] { 0x2a, 0x1c, 0x6e, (byte) 0x4 }, Gsm7EncodingStyle.bit7_ussd_style, null, 4);
this.doTestEncode("Hell", new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 0, -78, -52, 102, 3 }, Gsm7EncodingStyle.bit7_sms_style,
new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 }, 14);
this.doTestEncode("[88]", new byte[] { 27, 30, 14, -73, -15, 1 }, Gsm7EncodingStyle.bit7_sms_style, null, 6);
this.doTestEncode("[88]", new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, -64, -122, -121, -61, 109, 124 },
Gsm7EncodingStyle.bit7_sms_style, new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 }, 16);
this.doTestEncode("Hell", new byte[] { 72, 101, 108, 108 }, Gsm7EncodingStyle.bit8_smpp_style, null, 0);
this.doTestEncode("Hell", new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 72, 101, 108, 108 }, Gsm7EncodingStyle.bit8_smpp_style,
new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 }, 0);
this.doTestEncode("[88]", new byte[] { 27, 60, 56, 56, 27, 62 }, Gsm7EncodingStyle.bit8_smpp_style, null, 0);
this.doTestEncode("[88]", new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 27, 60, 56, 56, 27, 62 },
Gsm7EncodingStyle.bit8_smpp_style, new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 }, 0);
}
@Test(groups = { "functional.decode", "datacoding" })
public void testDecode() throws Exception {
int octetOffset = 8;
int septetOffset = GSMCharset.octetsToSeptets(octetOffset);
this.doTestDecode("123456\r", new byte[] { 49, -39, -116, 86, -77, 53, 26 }, Gsm7EncodingStyle.bit7_ussd_style, 0, 0);
this.doTestDecode("1\r", new byte[] { -79, 6 }, Gsm7EncodingStyle.bit7_ussd_style, 0, 0);
this.doTestDecode("1", new byte[] { 49 }, Gsm7EncodingStyle.bit7_ussd_style, 0, 0);
this.doTestDecode("1234567", new byte[] { 49, -39, -116, 86, -77, -35, 26 }, Gsm7EncodingStyle.bit7_ussd_style, 0, 0);
this.doTestDecode("1234567\r\r", new byte[] { 49, -39, -116, 86, -77, -35, 26, 13 }, Gsm7EncodingStyle.bit7_ussd_style,
0, 0);
this.doTestDecode("1234567", new byte[] { 49, -39, -116, 86, -77, -35, 0 }, Gsm7EncodingStyle.bit7_sms_style, 7, 0);
this.doTestDecode("1234567\r", new byte[] { 49, -39, -116, 86, -77, -35, 26 }, Gsm7EncodingStyle.bit7_sms_style, 8, 0);
// This raw data is from nad1053.pcap, 2nd packet.
this.doTestDecode("*125*+31628839999#", new byte[] { (byte) 0xaa, (byte) 0x98, (byte) 0xac, (byte) 0xa6, 0x5a,
(byte) 0xcd, 0x62, 0x36, 0x19, 0x0e, 0x37, (byte) 0xcb, (byte) 0xe5, 0x72, (byte) 0xb9, 0x11 },
Gsm7EncodingStyle.bit7_ussd_style, 0, 0);
// This raw data is from nad1053.pcap, last packet.
this.doTestDecode("You don t have enough credit to call this number. ", new byte[] { (byte) 0xd9, (byte) 0x77, 0x1d,
0x44, (byte) 0x7e, (byte) 0xbb, 0x41, 0x74, 0x10, 0x3a, 0x6c, 0x2f, (byte) 0x83, (byte) 0xca, (byte) 0xee,
0x77, (byte) 0xfd, (byte) 0x8c, 0x06, (byte) 0x8d, (byte) 0xe5, 0x65, 0x72, (byte) 0x9a, 0x0e, (byte) 0xa2,
(byte) 0xbf, 0x41, (byte) 0xe3, 0x30, (byte) 0x9b, 0x0d, (byte) 0xa2, (byte) 0xa3, (byte) 0xd3, 0x73,
(byte) 0x90, (byte) 0xbb, (byte) 0xde, 0x16, (byte) 0x97, (byte) 0xe5, 0x2e, 0x10 },
Gsm7EncodingStyle.bit7_ussd_style, 0, 0);
// The USSD String represented by above raw data
this.doTestDecode("ndmgapp2ndmgapp2", new byte[] { 0x6e, 0x72, (byte) 0xfb, 0x1c, (byte) 0x86, (byte) 0xc3, 0x65, 0x6e,
0x72, (byte) 0xfb, 0x1c, (byte) 0x86, (byte) 0xc3, 0x65 }, Gsm7EncodingStyle.bit7_ussd_style, 0, 0);
this.doTestDecode("*88#", new byte[] { 0x2a, 0x1c, 0x6e, (byte) 0xd4 }, Gsm7EncodingStyle.bit7_ussd_style, 0, 0);
this.doTestDecode("[88]", new byte[] { 27, 30, 14, -73, -15, 1 }, Gsm7EncodingStyle.bit7_sms_style, 6, 0);
this.doTestDecode("[88]", new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, -64, -122, -121, -61, 109, 124 },
Gsm7EncodingStyle.bit7_sms_style, 16, septetOffset);
this.doTestDecode("Hell", new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 0, -78, -52, 102, 3 }, Gsm7EncodingStyle.bit7_sms_style, 14, septetOffset);
this.doTestDecode("Hell", new byte[] { 72, 101, 108, 108 }, Gsm7EncodingStyle.bit8_smpp_style, 0, 0);
this.doTestDecode("Hell", new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 72, 101, 108, 108 }, Gsm7EncodingStyle.bit8_smpp_style, 0, octetOffset);
this.doTestDecode("[88]", new byte[] { 27, 60, 56, 56, 27, 62 }, Gsm7EncodingStyle.bit8_smpp_style, 0, 0);
this.doTestDecode("[88]", new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 27, 60, 56, 56, 27, 62 },
Gsm7EncodingStyle.bit8_smpp_style, 0, octetOffset);
this.doTestDecode("He l", new byte[] { 72, 101, (byte) 200, 108 }, Gsm7EncodingStyle.bit8_smpp_style, 0, 0);
}
private void doTestEncode(String decodedString, byte[] encodedData, Gsm7EncodingStyle gsm7EncodingStyle, byte[] bufUDH,
int totalSeptetCount) throws Exception {
GSMCharset cs = new GSMCharset("GSM", new String[] {});
GSMCharsetEncoder encoder = (GSMCharsetEncoder) cs.newEncoder();
encoder.setGSMCharsetEncodingData(new GSMCharsetEncodingData(gsm7EncodingStyle, bufUDH));
ByteBuffer bb = encoder.encode(CharBuffer.wrap(decodedString));
byte[] data = new byte[bb.limit()];
bb.get(data);
int len = encoder.getGSMCharsetEncodingData().getTotalSeptetCount();
assertEquals(encodedData, data);
assertEquals(totalSeptetCount, len);
}
private void doTestDecode(String decodedString, byte[] encodedData, Gsm7EncodingStyle gsm7EncodingStyle, int totalSeptetCount,
int leadingSeptetSkipCount) throws Exception {
ByteBuffer bb = ByteBuffer.wrap(encodedData);
GSMCharset cs = new GSMCharset("GSM", new String[] {});
GSMCharsetDecoder decoder = (GSMCharsetDecoder) cs.newDecoder();
switch (gsm7EncodingStyle) {
case bit7_ussd_style:
decoder.setGSMCharsetDecodingData(new GSMCharsetDecodingData(gsm7EncodingStyle, Integer.MAX_VALUE, 0));
break;
case bit7_sms_style:
decoder.setGSMCharsetDecodingData(new GSMCharsetDecodingData(gsm7EncodingStyle, totalSeptetCount,
leadingSeptetSkipCount));
break;
case bit8_smpp_style:
decoder.setGSMCharsetDecodingData(new GSMCharsetDecodingData(gsm7EncodingStyle, Integer.MAX_VALUE, leadingSeptetSkipCount));
break;
}
CharBuffer bf = null;
bf = decoder.decode(bb);
String s1 = bf.toString();
assertEquals(s1, decodedString);
}
@Test(groups = { "functional.decode", "datacoding" })
public void testBufferOverflowTest() throws Exception {
AbsoluteTimeStamp serviceCentreTimeStamp = new AbsoluteTimeStampImpl(15, 5, 12, 2, 20, 11, 0);
DataCodingSchemeImpl dcs = new DataCodingSchemeImpl(0);
UserDataHeader userDataHeader = new UserDataHeaderImpl();
int messageReferenceNumber = 5;
int messageSegmentCount = 1;
int messageSegmentNumber = 3;
UserDataHeaderElement concatenatedShortMessagesIdentifier = new ConcatenatedShortMessagesIdentifierImpl(
messageReferenceNumber > 255, messageReferenceNumber, messageSegmentCount, messageSegmentNumber);
userDataHeader.addInformationElement(concatenatedShortMessagesIdentifier);
UserDataImpl ud = new UserDataImpl("Hell", dcs, userDataHeader, null);
SmsDeliverTpduImpl smsDeliverTpduImpl = new SmsDeliverTpduImpl(true, false, false, false, new AddressFieldImpl(
TypeOfNumber.InternationalNumber, NumberingPlanIdentification.ISDNTelephoneNumberingPlan, "1111"),
new ProtocolIdentifierImpl(0), serviceCentreTimeStamp, ud);
SmsSignalInfoImpl smsSignalInfo = new SmsSignalInfoImpl(smsDeliverTpduImpl, null);
byte[] data = smsSignalInfo.getData();
assertEquals(data, new byte[] { 64, 4, -111, 17, 17, 0, 0, 81, 80, 33, 32, 2, 17, 0, 11, 5, 0, 3, 5, 1, 3, -112, 101,
54, 27 });
}
@Test(groups = { "datacoding" })
public void testCedilla() throws Exception {
Charset ucs2Charset = Charset.forName("UTF-16BE");
Charset utf8Charset = Charset.forName("UTF-8");
byte[] textPart0 = new byte[] { 0, (byte) 0xE7 };
String msg0 = new String(textPart0, ucs2Charset);
byte[] testPart0Utf8 = msg0.getBytes(utf8Charset);
byte[] textPart = new byte[] { 0x74, 0x65, 0x73, 0x74, 0x73, 0x65, 0x6e, 0x64, 0x20, (byte) 0xc3, (byte) 0x87 };
String msg = new String(textPart, utf8Charset);
String s1 = "testsend Ç";
String s2 = "Ç";
int i2 = msg.charAt(9);
GSMCharset gsm7Charset = new GSMCharset("GSM", new String[] {});
Charset cSet = gsm7Charset;
GSMCharsetEncoder encoder = (GSMCharsetEncoder) cSet.newEncoder();
// encoder.setGSMCharsetEncodingData(new GSMCharsetEncodingData(buf2));
ByteBuffer bb = null;
try {
bb = encoder.encode(CharBuffer.wrap(msg));
} catch (Exception e) {
// This can not occur
}
// int encodedUserDataLength = encoder.getGSMCharsetEncodingData().getTotalSeptetCount();
byte[] encodedData = new byte[bb.limit()];
bb.get(encodedData);
}
@Test(groups = { "datacoding" })
public void testNationalLanguage() throws Exception {
GSMCharset gsm7Charset = new GSMCharset("GSM", new String[] {});
Charset cSet = gsm7Charset;
// Gsm7NationalLanguageIdentifier nationalLanguageLockingShift = null;
// Gsm7NationalLanguageIdentifier nationalLanguageSingleShift = null;
// NationalLanguageIdentifier nationalLanguageLockingShiftIdentifier = null;
// NationalLanguageIdentifier nationalLanguageSingleShiftIdentifier = null;
// if (this.decodedUserDataHeader != null) {
// nationalLanguageLockingShift = this.decodedUserDataHeader.getNationalLanguageLockingShift();
// nationalLanguageSingleShift = this.decodedUserDataHeader.getNationalLanguageSingleShift();
// if (nationalLanguageLockingShift != null)
// nationalLanguageLockingShiftIdentifier = nationalLanguageLockingShift
// .getNationalLanguageIdentifier();
// if (nationalLanguageSingleShift != null)
// nationalLanguageSingleShiftIdentifier = nationalLanguageSingleShift.getNationalLanguageIdentifier();
// }
// if (nationalLanguageLockingShift != null || nationalLanguageSingleShift != null) {
// cSet = new GSMCharset("GSM", new String[] {}, nationalLanguageLockingShiftIdentifier,
// nationalLanguageSingleShiftIdentifier);
// }
GSMCharsetEncoder encoder = (GSMCharsetEncoder) cSet.newEncoder();
// encoder.setGSMCharsetEncodingData(new GSMCharsetEncodingData(buf2));
ByteBuffer bb = null;
}
@Test(groups = { "datacoding" })
public void testCheckAllCharsCanBeEncoded() throws Exception {
GSMCharset gsm7Charset = new GSMCharset("GSM", new String[] {});
assertTrue(gsm7Charset.checkAllCharsCanBeEncoded(""));
assertTrue(gsm7Charset.checkAllCharsCanBeEncoded("[ **]"));
assertFalse(gsm7Charset.checkAllCharsCanBeEncoded("w\u044Bw"));
}
@Test(groups = { "datacoding" })
public void testCheckEncodedDataLengthInChars() throws Exception {
GSMCharset gsm7Charset = new GSMCharset("GSM", new String[] {});
assertEquals(gsm7Charset.checkEncodedDataLengthInChars(""), 0);
assertEquals(gsm7Charset.checkEncodedDataLengthInChars("123[]\u044B4"), 9);
}
@Test(groups = { "datacoding" })
public void testSliceString() throws Exception {
GSMCharset gsm7Charset = new GSMCharset("GSM", new String[] {});
String[] ss = gsm7Charset.sliceString("123", 8);
assertEquals(ss.length, 1);
assertEquals(ss[0], "123");
ss = gsm7Charset.sliceString("123", 3);
assertEquals(ss.length, 1);
assertEquals(ss[0], "123");
ss = gsm7Charset.sliceString("123", 2);
assertEquals(ss.length, 2);
assertEquals(ss[0], "12");
assertEquals(ss[1], "3");
ss = gsm7Charset.sliceString("12[3", 6);
assertEquals(ss.length, 1);
assertEquals(ss[0], "12[3");
ss = gsm7Charset.sliceString("12[3", 5);
assertEquals(ss.length, 1);
assertEquals(ss[0], "12[3");
ss = gsm7Charset.sliceString("12[3", 4);
assertEquals(ss.length, 2);
assertEquals(ss[0], "12[");
assertEquals(ss[1], "3");
ss = gsm7Charset.sliceString("12[3", 3);
assertEquals(ss.length, 2);
assertEquals(ss[0], "12");
assertEquals(ss[1], "[3");
ss = gsm7Charset.sliceString("12[3", 2);
assertEquals(ss.length, 3);
assertEquals(ss[0], "12");
assertEquals(ss[1], "[");
assertEquals(ss[2], "3");
ss = gsm7Charset.sliceString("12[3]", 2);
assertEquals(ss.length, 4);
assertEquals(ss[0], "12");
assertEquals(ss[1], "[");
assertEquals(ss[2], "3");
assertEquals(ss[3], "]");
ss = gsm7Charset.sliceString("12\u044B3", 3);
assertEquals(ss.length, 2);
assertEquals(ss[0], "12\u044B");
assertEquals(ss[1], "3");
}
}