r_sms.cc
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "r_sms.h"
00024 #include "record-internal.h"
00025 #include "protostructs.h"
00026 #include "data.h"
00027 #include "time.h"
00028 #include "debug.h"
00029 #include "iconv.h"
00030 #include "strnlen.h"
00031 #include <ostream>
00032 #include <iomanip>
00033 #include <string.h>
00034
00035 using namespace std;
00036 using namespace Barry::Protocol;
00037
00038 namespace Barry {
00039
00040
00041
00042
00043
00044 #define SMSFC_METADATA 0x01
00045 #define SMSFC_ADDRESS 0x02
00046 #define SMSFC_BODY 0x04
00047
00048
00049 #define SMS_ADDRESS_HEADER_SIZE 0x04
00050
00051 #define MILLISECONDS_IN_A_SECOND 1000
00052
00053 time_t Sms::GetTime() const
00054 {
00055 return (time_t)(Timestamp / MILLISECONDS_IN_A_SECOND);
00056 }
00057
00058 time_t Sms::GetServiceCenterTime() const
00059 {
00060 return (time_t)(ServiceCenterTimestamp / MILLISECONDS_IN_A_SECOND);
00061 }
00062
00063 void Sms::SetTime(const time_t timestamp, const unsigned milliseconds)
00064 {
00065 Timestamp = (uint64_t)timestamp * MILLISECONDS_IN_A_SECOND + milliseconds;
00066 }
00067
00068 void Sms::SetServiceCenterTime(const time_t timestamp, const unsigned milliseconds)
00069 {
00070 ServiceCenterTimestamp = (uint64_t)timestamp * MILLISECONDS_IN_A_SECOND + milliseconds;
00071 }
00072
00073 Sms::Sms()
00074 {
00075 Clear();
00076 }
00077
00078 Sms::~Sms()
00079 {
00080 }
00081
00082 const unsigned char* Sms::ParseField(const unsigned char *begin,
00083 const unsigned char *end,
00084 const IConverter *ic)
00085 {
00086 const CommonField *field = (const CommonField *)begin;
00087
00088
00089 begin += COMMON_FIELD_HEADER_SIZE + btohs(field->size);
00090 if (begin > end)
00091 return begin;
00092
00093 if (!btohs(field->size))
00094 return begin;
00095
00096 switch (field->type)
00097 {
00098 case SMSFC_METADATA:
00099 {
00100 if (btohs(field->size) < SMS_METADATA_SIZE)
00101 break;
00102
00103 const SMSMetaData &metadata = field->u.sms_metadata;
00104 NewConversation = metadata.flags & SMS_FLG_NEW_CONVERSATION;
00105 Saved = metadata.flags & SMS_FLG_SAVED;
00106 Deleted = metadata.flags & SMS_FLG_DELETED;
00107 Opened = metadata.flags & SMS_FLG_OPENED;
00108
00109 IsNew = metadata.new_flag;
00110
00111 uint32_t status = btohl(metadata.status);
00112
00113 switch (status)
00114 {
00115 case SMS_STA_RECEIVED:
00116 MessageStatus = Received;
00117 break;
00118 case SMS_STA_DRAFT:
00119 MessageStatus = Draft;
00120 break;
00121 default:
00122 MessageStatus = Sent;
00123 }
00124
00125 ErrorId = btohl(metadata.error_id);
00126
00127 Timestamp = btohll(metadata.timestamp);
00128 ServiceCenterTimestamp = btohll(metadata.service_center_timestamp);
00129
00130 switch (metadata.dcs)
00131 {
00132 case SMS_DCS_7BIT:
00133 DataCodingScheme = SevenBit;
00134 break;
00135 case SMS_DCS_8BIT:
00136 DataCodingScheme = EightBit;
00137 break;
00138 case SMS_DCS_UCS2:
00139 DataCodingScheme = UCS2;
00140 break;
00141 default:
00142 DataCodingScheme = SevenBit;
00143 }
00144
00145 return begin;
00146 }
00147
00148 case SMSFC_ADDRESS:
00149 {
00150 uint16_t length = btohs(field->size);
00151 if (length < SMS_ADDRESS_HEADER_SIZE + 1)
00152 break;
00153
00154 length -= SMS_ADDRESS_HEADER_SIZE;
00155 const char *address = (const char *)field->u.raw + SMS_ADDRESS_HEADER_SIZE;
00156 Addresses.push_back(std::string(address, strnlen(address, length)));
00157 return begin;
00158 }
00159
00160 case SMSFC_BODY:
00161 {
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173 const char *str = (const char *)field->u.raw;
00174 uint16_t maxlen = btohs(field->size);
00175 if (DataCodingScheme != UCS2) {
00176 for (uint16_t i = 0; i < maxlen; ++i) {
00177 if (str[i])
00178 Body += str[i];
00179 }
00180
00181 if (ic) {
00182 Body = ic->FromBB(Body);
00183 }
00184 }
00185 else {
00186 for (uint16_t i = 0; maxlen && i < (maxlen-1); i += 2) {
00187 if (str[i] || str[i + 1])
00188 Body += std::string(str + i, 2);
00189 }
00190
00191 if (ic) {
00192 IConvHandle ucs2("UCS-2BE", *ic);
00193 Body = ic->Convert(ucs2, Body);
00194 }
00195 }
00196 return begin;
00197 }
00198 }
00199
00200
00201 UnknownField uf;
00202 uf.type = field->type;
00203 uf.data.assign((const char*)field->u.raw, btohs(field->size));
00204 Unknowns.push_back(uf);
00205
00206
00207 return begin;
00208 }
00209
00210 void Sms::ParseHeader(const Data &data, size_t &offset)
00211 {
00212
00213 }
00214
00215 void Sms::ParseFields(const Data &data, size_t &offset, const IConverter *ic)
00216 {
00217 const unsigned char *finish = ParseCommonFields(*this,
00218 data.GetData() + offset, data.GetData() + data.GetSize(), ic);
00219 offset += finish - (data.GetData() + offset);
00220 }
00221
00222 void Sms::Clear()
00223 {
00224 MessageStatus = Unknown;
00225 DeliveryStatus = NoReport;
00226 DataCodingScheme = SevenBit;
00227
00228 IsNew = NewConversation = Saved = Deleted = Opened = false;
00229
00230 Timestamp = ServiceCenterTimestamp = 0;
00231 ErrorId = 0;
00232
00233 Addresses.clear();
00234 Body.clear();
00235
00236 Unknowns.clear();
00237 }
00238
00239 void Sms::Dump(std::ostream &os) const
00240 {
00241
00242 os << "SMS record: 0x" << setbase(16) << RecordId
00243 << " (" << (unsigned int)RecType << ")\n";
00244 time_t t = GetTime();
00245 os << "\tTimestamp: " << ctime(&t);
00246
00247 if (MessageStatus == Received)
00248 {
00249 t = GetServiceCenterTime();
00250 os << "\tService Center Timestamp: " << ctime(&t);
00251 }
00252
00253 if (ErrorId)
00254 os << "\tSend Error: 0x" << setbase(16) << ErrorId << "\n";
00255
00256 switch (MessageStatus)
00257 {
00258 case Received:
00259 os << "\tReceived From:\n";
00260 break;
00261 case Sent:
00262 os << "\tSent to:\n";
00263 break;
00264 case Draft:
00265 os << "\tDraft for:\n";
00266 break;
00267 case Unknown:
00268 os << "\tUnknown status for:\n";
00269 break;
00270 }
00271
00272 os << "\t";
00273 for (std::vector<std::string>::const_iterator Iterator = Addresses.begin(); Iterator < Addresses.end(); ++Iterator)
00274 {
00275 if (Iterator != Addresses.begin())
00276 os << ", ";
00277 os << *Iterator;
00278 }
00279 os << "\n";
00280
00281 if (IsNew || Opened || Saved || Deleted || NewConversation)
00282 {
00283 os << "\t";
00284 if (IsNew)
00285 os << "New ";
00286 if (Opened)
00287 os << "Opened ";
00288 if (Saved)
00289 os << "Saved ";
00290 if (Deleted)
00291 os << "Deleted ";
00292 os << "Message" << (NewConversation ? " that starts a new conversation" : "") << "\n";
00293 }
00294 os << "\tContent: " << Body << "\n";
00295 os << "\n";
00296 }
00297
00298 }