Chromium Code Reviews| Index: sms_message.cc |
| diff --git a/sms_message.cc b/sms_message.cc |
| index 5f4001bcb08500819efb6cada55ceae95971dfb1..04dbfe48164f2aecbec55ed831ff0d0733521b99 100644 |
| --- a/sms_message.cc |
| +++ b/sms_message.cc |
| @@ -8,9 +8,12 @@ |
| #include "utilities.h" |
| -static const uint8_t INTL_E164_NUMBER_FORMAT = 0x91; |
| -static const uint8_t SMSC_TIMESTAMP_LEN = 7; |
| -static const size_t MIN_PDU_LEN = 7 + SMSC_TIMESTAMP_LEN; |
| +static const uint8_t kIntlE164NumberFormat = 0x91; |
| +static const uint8_t kAlphaFormat = 0xd0; |
| +static const uint8_t kDataCodingSchemeGsm7 = 0; |
| +static const uint8_t kDataCodingSchemeUcs2 = 8; |
| +static const uint8_t kSmscTimestampLen = 7; |
| +static const size_t kMinPduLen = 7 + kSmscTimestampLen; |
| static char NibbleToChar(uint8_t nibble) { |
| switch (nibble) { |
| @@ -58,8 +61,8 @@ SmsMessage* SmsMessage::CreateMessage(const uint8_t* pdu, size_t pdu_len) { |
| utilities::DumpHex(pdu, pdu_len); |
| // Make sure the PDU is of a valid size |
| - if (pdu_len < MIN_PDU_LEN) { |
| - LOG(INFO) << "PDU too short: " << pdu_len << " vs. " << MIN_PDU_LEN; |
| + if (pdu_len < kMinPduLen) { |
| + LOG(INFO) << "PDU too short: " << pdu_len << " vs. " << kMinPduLen; |
| return NULL; |
| } |
| @@ -73,7 +76,7 @@ SmsMessage* SmsMessage::CreateMessage(const uint8_t* pdu, size_t pdu_len) { |
| // 1 octet - type of sender address (value 0x91 is international E.164) |
| // variable - sender address |
| // 1 octet - protocol identifier (value = 0) |
| - // 1 octet - data coding scheme (value = 0) |
| + // 1 octet - data coding scheme (value 0 is GSM7, 8 is UCS2) |
| // 7 octets - SMSC timestamp |
| // 1 octet - user data length in septets |
| // variable - user data (body of message) |
| @@ -86,9 +89,9 @@ SmsMessage* SmsMessage::CreateMessage(const uint8_t* pdu, size_t pdu_len) { |
| uint8_t smsc_addr_num_octets = pdu[0]; |
| uint8_t variable_length_items = smsc_addr_num_octets; |
| - if (pdu_len < variable_length_items + MIN_PDU_LEN) { |
| + if (pdu_len < variable_length_items + kMinPduLen) { |
| LOG(INFO) << "PDU too short: " << pdu_len << " vs. " |
| - << variable_length_items + MIN_PDU_LEN; |
| + << variable_length_items + kMinPduLen; |
| return NULL; |
| } |
| @@ -99,29 +102,29 @@ SmsMessage* SmsMessage::CreateMessage(const uint8_t* pdu, size_t pdu_len) { |
| // and thus an integral number of octets |
| uint8_t sender_addr_num_octets = (sender_addr_num_digits + 1) >> 1; |
| variable_length_items += sender_addr_num_octets; |
| - if (pdu_len < variable_length_items + MIN_PDU_LEN) { |
| + if (pdu_len < variable_length_items + kMinPduLen) { |
| LOG(INFO) << "PDU too short: " << pdu_len << " vs. " |
| - << variable_length_items + MIN_PDU_LEN; |
| + << variable_length_items + kMinPduLen; |
| return NULL; |
| } |
| uint8_t tp_pid_offset = msg_start_offset + 3 + sender_addr_num_octets; |
| - uint8_t user_data_offset = tp_pid_offset + 2 + SMSC_TIMESTAMP_LEN; |
| + uint8_t user_data_offset = tp_pid_offset + 2 + kSmscTimestampLen; |
| uint8_t user_data_num_septets = pdu[user_data_offset]; |
| variable_length_items += (7 * (user_data_num_septets + 1 )) / 8; |
| - if (pdu_len < variable_length_items + MIN_PDU_LEN) { |
| + if (pdu_len < variable_length_items + kMinPduLen) { |
| LOG(INFO) << "PDU too short: " << pdu_len << " vs. " |
| - << variable_length_items + MIN_PDU_LEN; |
| + << variable_length_items + kMinPduLen; |
| return NULL; |
| } |
| - // wow do some validity checks on the values of several fields in the PDU |
| + // now do some validity checks on the values of several fields in the PDU |
| // smsc number format must be international, E.164 |
| - if (pdu[1] != INTL_E164_NUMBER_FORMAT) { |
| + if (pdu[1] != kIntlE164NumberFormat) { |
| LOG(INFO) << "Invalid SMSC address format: " << std::hex << (int)pdu[1] |
| - << " vs. " << std::hex << INTL_E164_NUMBER_FORMAT; |
| + << " vs. " << std::hex << kIntlE164NumberFormat; |
| return NULL; |
| } |
| // we only handle SMS-DELIVER messages, with more-messages-to-send false |
| @@ -130,6 +133,14 @@ SmsMessage* SmsMessage::CreateMessage(const uint8_t* pdu, size_t pdu_len) { |
| << (int)pdu[msg_start_offset] << " vs. 0x04"; |
| return NULL; |
| } |
| + // we only handle E164 and ALPHA sender address formats |
| + uint8_t sender_addr_type = pdu[msg_start_offset + 2]; |
| + if (sender_addr_type != kIntlE164NumberFormat && |
| + sender_addr_type != kAlphaFormat) { |
| + LOG(INFO) << "Unhandled sender address format: " << std::hex << |
| + sender_addr_type; |
| + return NULL; |
| + } |
| // we only handle the basic protocol identifier |
| if (pdu[tp_pid_offset] != 0) { |
| LOG(INFO) << "Unhandled protocol identifier: " << std::hex |
| @@ -137,23 +148,38 @@ SmsMessage* SmsMessage::CreateMessage(const uint8_t* pdu, size_t pdu_len) { |
| return NULL; |
| } |
| // for data coding scheme, we only handle the default alphabet, i.e. GSM7 |
| - if (pdu[tp_pid_offset+1] != 0) { |
| + uint8_t dcs = pdu[tp_pid_offset+1] & 0x0c; |
|
Nathan Williams
2011/03/30 22:31:54
We're losing the detection of some unsupported cas
Eric Shienbrood
2011/03/31 20:03:59
Done.
|
| + if (dcs != kDataCodingSchemeGsm7 && dcs != kDataCodingSchemeUcs2) { |
| LOG(INFO) << "Unhandled data coding scheme: " << std::hex |
| - << (int)pdu[tp_pid_offset+1] << " vs. 0x00"; |
| + << (int)pdu[tp_pid_offset+1]; |
| return NULL; |
| } |
| std::string smsc_addr = SemiOctetsToBcdString(&pdu[2], |
| smsc_addr_num_octets-1); |
| - std::string sender_addr = SemiOctetsToBcdString(&pdu[msg_start_offset+3], |
| - sender_addr_num_octets); |
| + std::string sender_addr; |
| + if (sender_addr_type == kIntlE164NumberFormat) |
| + sender_addr = SemiOctetsToBcdString(&pdu[msg_start_offset+3], |
| + sender_addr_num_octets); |
| + else { |
| + uint8_t *bytes = new uint8_t[sender_addr_num_octets+1]; |
| + bytes[0] = (sender_addr_num_digits * 4) / 7; |
| + memcpy(&bytes[1], &pdu[msg_start_offset+3], sender_addr_num_octets); |
| + sender_addr = utilities::Gsm7ToUtf8String(bytes); |
| + delete [] bytes; |
| + } |
| + |
| std::string sc_timestamp = SemiOctetsToBcdString(&pdu[tp_pid_offset+2], |
| - SMSC_TIMESTAMP_LEN-1); |
| - std::string msg_text = utilities::Gsm7ToUtf8String(&pdu[user_data_offset]); |
| + kSmscTimestampLen-1); |
| + std::string msg_text; |
| + if (dcs == kDataCodingSchemeGsm7) |
| + msg_text = utilities::Gsm7ToUtf8String(&pdu[user_data_offset]); |
| + else |
| + msg_text = utilities::Ucs2ToUtf8String(&pdu[user_data_offset]); |
| // The last two semi-octets of the timestamp indicate an offset from |
| // GMT, and are handled differently than the first 12 semi-octets. |
| - uint8_t toff_octet = pdu[tp_pid_offset+1+SMSC_TIMESTAMP_LEN]; |
| + uint8_t toff_octet = pdu[tp_pid_offset+1+kSmscTimestampLen]; |
| sc_timestamp += (toff_octet & 0x8) ? '-' : '+'; |
| uint8_t offset_in_hours = |
| ((toff_octet & 0x7) << 4 | (toff_octet & 0xf0) >> 4) / 4; |