📄 gsm_sms_codec.c
字号:
++_op;
}
}
alignOctet();
return result;
}
unsigned long SMSDecoder::getTimeZone(bool &negativeTimeZone)
{
unsigned long result = 0;
alignOctet();
for (unsigned short i = 0; i < 2; ++i)
{
if (_bi == 0)
{
if (_op >= _maxop)
throw GsmException(_("premature end of PDU"), SMSFormatError);
// bits 0..3 are most significant
if (i == 0)
{ // get sign
result = result * 10 + (*_op & 0x7);
negativeTimeZone = (*_op & 0x8 == 0);
}
else
result = result * 10 + (*_op & 0xf);
_bi = 4;
}
else
{
if (_op >= _maxop)
throw GsmException(_("premature end of PDU"), SMSFormatError);
// bits 4..7 are least significant
result = result * 10 + (*_op >> 4);
_bi = 0;
++_op;
}
}
alignOctet();
return result * 15; // compute minutes
}
unsigned long SMSDecoder::getInteger(unsigned short length)
{
unsigned long result = 0;
for (unsigned short i = 0; i < length; ++i)
result |= (getBit() << i);
return result;
}
string SMSDecoder::getString(unsigned short length)
{
string result;
alignSeptet();
for (unsigned short i = 0; i < length; ++i)
{
unsigned char c = 0;
for (unsigned short j = 0; j < 7; ++j)
c |= getBit() << j;
result += c;
}
return result;
}
Address SMSDecoder::getAddress(bool scAddressFormat)
{
Address result;
alignOctet();
unsigned char addressLength = getOctet();
if (addressLength == 0 && scAddressFormat)
return result; // special case for SUBMIT-PDUs
// parse Type-of-Address
result._plan = (Address::NumberingPlan)getInteger(4);
result._type = (Address::Type)getInteger(3);
// get address
if (result._type == Address::Alphanumeric)
{
markSeptet();
// addressLength is number of semi-octets
// (addressLength / 2) * 8 is number of available bits
// divided by 7 is number of 7-bit characters
result._number = gsmToLatin1(getString((addressLength / 2) * 8 / 7));
alignOctet();
}
else
result._number = getSemiOctets(scAddressFormat ?
(addressLength - 1) * 2 : addressLength);
return result;
}
Timestamp SMSDecoder::getTimestamp()
{
Timestamp result;
result._year = getSemiOctetsInteger(2);
result._month = getSemiOctetsInteger(2);
result._day = getSemiOctetsInteger(2);
result._hour = getSemiOctetsInteger(2);
result._minute = getSemiOctetsInteger(2);
result._seconds = getSemiOctetsInteger(2);
result._timeZoneMinutes = getTimeZone(result._negativeTimeZone);
return result;
}
TimePeriod SMSDecoder::getTimePeriod(TimePeriod::Format format)
{
TimePeriod result;
result._format = format;
switch (format)
{
case TimePeriod::NotPresent:
break;
case TimePeriod::Relative:
result._relativeTime = getOctet();
break;
case TimePeriod::Absolute:
result._absoluteTime = getTimestamp();
break;
default:
throw GsmException(_("unknown time period format"), SMSFormatError);
break;
}
return result;
}
SMSDecoder::~SMSDecoder()
{
delete _p;
}
// SMSEncoder members
SMSEncoder::SMSEncoder() : _bi(0), _op(_p)
{
memset((void*)_p, 0, sizeof(_p));
}
void SMSEncoder::alignOctet()
{
if (_bi != 0)
{
_bi = 0;
++_op;
}
}
void SMSEncoder::alignSeptet()
{
while (((_op - _septetStart) * 8 + _bi) % 7 != 0) setBit();
}
void SMSEncoder::set2Bits(unsigned char twoBits)
{
setBit(twoBits & 1);
setBit((twoBits & 2) == 2);
}
void SMSEncoder::setOctet(unsigned char octet)
{
alignOctet();
*_op++ = octet;
}
void SMSEncoder::setOctets(const unsigned char* octets, unsigned short length)
{
alignOctet();
for (unsigned short i = 0; i < length; ++i)
*_op++ = octets[i];
}
void SMSEncoder::setSemiOctets(string semiOctets)
{
alignOctet();
for (unsigned int i = 0; i < semiOctets.length(); ++i)
{
if (_bi == 0)
{
*_op = semiOctets[i] - '0';
_bi = 4;
}
else
{
*_op++ |= (semiOctets[i] - '0') << 4;
_bi = 0;
}
}
if (_bi == 4)
*_op++ |= 0xf0;
_bi = 0;
}
void SMSEncoder::setSemiOctetsInteger(unsigned long intValue,
unsigned short length)
{
ostrstream os;
os << intValue << ends;
char *ss = os.str();
string s(ss);
delete[] ss;
assert(s.length() <= length);
while (s.length() < length) s = '0' + s;
setSemiOctets(s);
}
void SMSEncoder::setTimeZone(bool negativeTimeZone, unsigned long timeZone)
{
setSemiOctetsInteger(timeZone / 15, 2);
if (!negativeTimeZone)
*(_op - 1) |= 8;
}
void SMSEncoder::setInteger(unsigned long intvalue, unsigned short length)
{
for (unsigned short i = 0; i < length; ++i)
setBit((intvalue & (1 << i)) != 0);
}
void SMSEncoder::setString(string stringValue)
{
alignSeptet();
for (unsigned int i = 0; i < stringValue.length(); ++i)
{
unsigned char c = stringValue[i];
for (unsigned short j = 0; j < 7; ++j)
setBit(((1 << j) & c) != 0);
}
}
void SMSEncoder::setAddress(Address &address, bool scAddressFormat)
{
alignOctet();
if (scAddressFormat)
{
unsigned int numberLen = address._number.length();
if (numberLen == 0)
{
setOctet(0); // special case: use default SC address
return; // (set by +CSCA=)
}
setOctet(numberLen / 2 + numberLen % 2 + 1);
// not supported for SCA format
assert(address._type != Address::Alphanumeric);
}
else
if (address._type == Address::Alphanumeric)
// address in GSM default encoding, see also comment in getAddress()
setOctet((address._number.length() * 7 + 6) / 8 * 2);
else
setOctet(address._number.length());
setInteger(address._plan, 4);
setInteger(address._type, 3);
setBit(1);
if (address._number.length() > 0)
if (address._type == Address::Alphanumeric)
{
markSeptet();
setString(latin1ToGsm(address._number));
}
else
setSemiOctets(address._number);
alignOctet();
}
void SMSEncoder::setTimestamp(Timestamp timestamp)
{
setSemiOctetsInteger(timestamp._year, 2);
setSemiOctetsInteger(timestamp._month, 2);
setSemiOctetsInteger(timestamp._day, 2);
setSemiOctetsInteger(timestamp._hour, 2);
setSemiOctetsInteger(timestamp._minute, 2);
setSemiOctetsInteger(timestamp._seconds, 2);
setTimeZone(timestamp._negativeTimeZone, timestamp._timeZoneMinutes);
}
void SMSEncoder::setTimePeriod(TimePeriod period)
{
switch (period._format)
{
case TimePeriod::NotPresent:
break;
case TimePeriod::Relative:
setOctet(period._relativeTime);
break;
case TimePeriod::Absolute:
setTimestamp(period._absoluteTime);
break;
default:
assert(0);
break;
}
}
string SMSEncoder::getHexString()
{
short bi = _bi;
unsigned char *op = _op;
alignOctet();
string result = bufToHex(_p, _op - _p);
_bi = bi;
_op = op;
return result;
}
unsigned int SMSEncoder::getLength()
{
short bi = _bi;
unsigned char *op = _op;
alignOctet();
unsigned int result = _op - _p;
_bi = bi;
_op = op;
return result;
}
// UserDataHeader members
void UserDataHeader::encode(SMSEncoder &e)
{
e.setOctet(_udh.length());
e.setOctets((unsigned char*)_udh.data(), _udh.length());
}
void UserDataHeader::decode(SMSDecoder &d)
{
unsigned char udhLen = d.getOctet();
unsigned char *s =
(unsigned char*)alloca(sizeof(unsigned char) * udhLen);
d.getOctets(s, udhLen);
string ss((char*)s, (unsigned int)udhLen);
_udh = ss;
}
string UserDataHeader::getIE(unsigned char id)
{
int udhl, pos = 0;
udhl = _udh.length();
while (pos < udhl)
{
unsigned char iei = _udh[pos++];
unsigned char ieidl = _udh[pos++];
if (iei == id) return _udh.substr(pos, ieidl);
pos += ieidl;
}
return "";
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -