00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
#include <iostream>
00028
#include <iomanip>
00029
#include <string>
00030
#include <sstream>
00031
00032
#include "gm/tocprotocol.h"
00033
#include "gm/basenetwork.h"
00034
#include "gm/protocol.h"
00035
#include "gm/tree.h"
00036
#include "gm/buffer.h"
00037
00038
#include "cryptopp/misc.h"
00039
00040
#define TOC_VER 1
00041
#define TOC_TLV 1
00042
#define UID_AIM_CHAT "748F2420-6287-11D1-8222-444553540000"
00043
00044
namespace GNUMessenger {
00045
00046
using namespace std;
00047
using namespace CryptoPP;
00048
00049 string TocProtocol::getErrorText(
int i,
const string& name)
00050 {
00051
switch (i)
00052 {
00053
case(901):
return name + string(
" not currently available");
break;
00054
case(902):
return string(
"Warning of ") + name + (
" not currently available");
break;
00055
case(903):
return "A message has been dropped, you are exceeding the server speed limit";
break;
00056
00057
case(911):
return "Error validating input";
break;
00058
case(912):
return "Invalid account";
break;
00059
case(913):
return "Error encountered while processing request";
break;
00060
case(914):
return "Service unavailable";
break;
00061
case(950):
return string(
"Chat in ") + name + string(
"is unavailable");
break;
00062
case(960):
return string(
"You are sending message too fast to ") + name;
break;
00063
case(961):
return string(
"You missed an im from ") + name + (
" because it was too big.");
break;
00064
case(962):
return string(
"You missed an im from ") + name + (
" because it sent to fast.");
break;
00065
case(970):
return "Failure";
break;
00066
case(971):
return "Too many matches";
break;
00067
case(972):
return "Need more qualifiers";
break;
00068
case(973):
return "Dir service temporarily unavailable";
break;
00069
case(974):
return "Email lookup restricted";
break;
00070
case(975):
return "Keyword Ignored";
break;
00071
case(976):
return "No Keywords";
break;
00072
case(977):
return "Language not supported";
break;
00073
case(978):
return "Country not supported";
break;
00074
case(979):
return string(
"Failure unknown ") + name;
break;
00075
case(980):
return "Incorrect nickname or password.";
break;
00076
case(981):
return "The service is temporarily unavailable.";
break;
00077
case(982):
return "Your warning level is currently too high to sign on.";
break;
00078
case(983):
return string(
"You have been connecting and disconnecting too frequently. "
00079
"Wait 10 minutes and try again. "
00080
"If you continue to try, you will need to wait even longer.");
break;
00081
case(989):
return string(
"An unknown signon error has occurred ") + name;
break;
00082
default:
return "An unknown error has occured.";
break;
00083 }
00084 }
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
class TocProtocol::FlapHeader {
00133
public:
00134
00135 FlapHeader()
00136 {
00137 m_ast = (byte)
'*';
00138 m_type = (byte)2;
00139 m_seq = Network::NBO(real_seq++);
00140 m_len = (byte)0;
00141 }
00142
00143
static word16 real_seq;
00144
00145
private:
00146 byte m_ast;
00147 word16 m_seq;
00148
00149
public:
00150 byte m_type;
00151 word16 m_len;
00152
00153 VBuffer getHdr()
00154 {
00155 VBuffer header;
00156
00157 header += m_ast;
00158 header += m_type;
00159 header += (byte) (m_seq & 0xff);
00160 header += (byte) ((m_seq >> 8)& 0xff);
00161 header += (byte) (m_len & 0xff);
00162 header += (byte) ((m_len >> 8)& 0xff);
00163
00164
return header;
00165 }
00166
00167 };
00168
00169 word16 TocProtocol::FlapHeader::real_seq = 1;
00170
00171
00172 string
00173 TocProtocol::aim_encode(
const string& s)
00174 {
00175 string buf;
00176 buf.reserve(s.length());
00177
for (
unsigned int i = 0; i < s.length(); i++) {
00178
switch (s[i]) {
00179
case '$':
case '{':
case '}':
00180
case '[':
case ']':
case '(':
00181
case ')':
case '\"':
case '\\':
00182 buf +=
'\\'; buf += s[i];
00183
break;
00184
case '\n': buf +=
"<BR>";
break;
00185
default: buf += s[i];
break;
00186 }
00187 }
00188
return buf;
00189 }
00190
00191 string TocProtocol::aim_normalize(
const string& s)
00192 {
00193 string buf;
00194 buf.reserve(s.length());
00195
00196
for (
unsigned int i=0; i<s.length(); i++) {
00197
char c = s[i];
00198
if (c !=
' ' && c!=
'\t' && c!=
'\n')
00199 buf += tolower(c);
00200 }
00201
return buf;
00202 }
00203
00204 string TocProtocol::roastPassword(
const VBuffer& pass)
00205 {
00206
00207 stringstream pword;
00208 pword <<
"0x";
00209 string roast(
"Tic/Toc");
00210
00211
for (
unsigned int i = 0; i < pass.size(); i++) {
00212 pword << hex << setfill(
'0') << setw(2) << (word16)(pass[i] ^ roast[i % roast.length()]);
00213 }
00214
00215
return pword.str();
00216 }
00217
00218 void TocProtocol::reset()
00219 {
00220
logout();
00221
login();
00222
00223 }
00224
00225
void TocProtocol::send_flap(
int type,
const VBuffer& data)
00226 {
00227 m_net->
sendData(return_flap(type, data));
00228 }
00229
00230 VBuffer TocProtocol::return_flap(
int type,
const VBuffer& data)
00231 {
00232
00233 VBuffer buffer;
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248 FlapHeader fh;
00249
00250
00251 word16 len = (word16)data.size();
00252
00253
00254 fh.m_type = (byte)type;
00255
00256 fh.m_len = Network::NBO(len);
00257
00258
00259 buffer = fh.getHdr();
00260
00261
if (len > 0)
00262 buffer += data;
00263
00264
return buffer;
00265 }
00266
00267 TocProtocol::TocProtocol(
const XMLNode &n, ProtocolManager *manager):
00268 Protocol(n, manager,
"toc"), m_realLength(0)
00269 {
00270 m_away =
false;
00271
m_net = addNet();
00272
00273 LOG_DEBUG(
"New TocProtocol instance, initializing hashmap...");
00274
00275 m_funcMap[
"UPDATE_BUDDY"] = &TocProtocol::processUpdateBuddy;
00276 m_funcMap[
"FLAP SIGNON"] = &TocProtocol::processSignon;
00277 m_funcMap[
"IM_IN"] = &TocProtocol::processIM;
00278 m_funcMap[
"SIGN_ON"] = &TocProtocol::processSignon;
00279 m_funcMap[
"CONFIG"] = &TocProtocol::processGotConfig;
00280 m_funcMap[
"NICK"] = &TocProtocol::processNick;
00281 m_funcMap[
"ERROR"] = &TocProtocol::processError;
00282
00283 }
00284
00285 TocProtocol::~TocProtocol()
00286 {
00287
00288
if (
m_net)
00289 removeNet(m_net);
00290 }
00291
00292
00293 void TocProtocol::login()
00294 {
00295 LOG_DEBUG(
"TOC: login()");
00296
00297
if (!
m_net)
00298
m_net = addNet();
00299
00300
m_net->
connectTo(m_conf.
child(
"server").
property(
"host"),
00301 m_conf.
child(
"server").
intProperty(
"port"));
00302
00303
00304 eventStateChange(S_connecting);
00305
00306 }
00307
00308 void TocProtocol::shutdown() {
00309
m_net->
disconnect();
00310 removeNet(
m_net);
00311
m_net = 0;
00312 }
00313
00314 void TocProtocol::logout()
00315 {
00316 LOG_DEBUG(
"TOC: logout()");
00317
00318
00319 eventStateChange(S_offline);
00320 eventLoggedOut();
00321 }
00322
00323 bool TocProtocol::sendMessage(
const Contact &c,
const string &message)
00324 {
00325 LOG_DEBUG(
"sendMessage [" << c.
getServerId(getProtocol()) <<
"] " << message);
00326
00327
VBuffer msg;
00328 msg += string(
"toc_send_im ");
00329 msg += aim_normalize(c.
getServerId(getProtocol()));
00330 msg += string(
" \"");
00331 msg += aim_encode(message);
00332 msg += string(
"\"");
00333 msg += (byte)0;
00334
00335 send_flap(TYPE_DATA,msg);
00336
return true;
00337 }
00338
00339
00340
void TocProtocol::sendMessageAuto(
const Contact &c,
const string &message)
00341 {
00342 LOG_DEBUG(
"sendMessageAuto");
00343
VBuffer msg;
00344 msg += string(
"toc_send_im ");
00345 msg += aim_normalize(c.
getServerId(getProtocol()));
00346 msg += (byte)
' ';
00347 msg += (byte)
'\"';
00348 msg += aim_encode(message);
00349 msg += string(
"\" \"auto\"");
00350 msg += (byte)0;
00351
00352 send_flap(TYPE_DATA,msg);
00353 }
00354
00355 void TocProtocol::addContact(
const Contact &c)
00356 {
00357 m_buddies[aim_normalize(c.
getServerId(getProtocol()))] = c;
00358
00359
if (
getState() == S_online) {
00363 forceContactUpdate(c);
00364 }
else {
00365 m_buddies[aim_normalize(c.getServerId(getProtocol()))].
00366 setStatus(
getProtocol(), Contact::Offline);
00367 }
00368
00369 LOG_DEBUG(
"TocProtocol::addContact: I am not adding to TOC");
00370
00371
00372
00373
00374
00375
00376 }
00377
00378
void TocProtocol::addBuddies()
00379 {
00380 LOG_DEBUG(
"TocProtocol::addBuddies");
00381
VBuffer msg;
00382 msg += string(
"toc_add_buddy");
00383
00384 map<string, Contact>::const_iterator it = m_buddies.begin();
00385
for (; it != m_buddies.end(); it++) {
00386 msg += string(
" ");
00387 msg += it->first;
00388 }
00389
00390 msg += (byte)0;
00391 send_flap(TYPE_DATA, msg);
00392 }
00393
00394
void TocProtocol::forceContactUpdate(
const Contact& c)
00395 {
00396 LOG_DEBUG(
"TocProtocol::forceContactUpdate");
00397
00398 VBuffer msg;
00399 msg += string(
"toc_get_status ");
00400 msg += c.getServerId(
getProtocol());
00401 msg += (byte)0;
00402 send_flap(TYPE_DATA, msg);
00403
00404 }
00405
00406
void TocProtocol::tocSendKeepalive()
00407 {
00408 send_flap(TYPE_KEEPALIVE, VBuffer());
00409 }
00410
00411 void TocProtocol::delContact(
const Contact &c)
00412 {
00413 map<string, Contact>::iterator it = m_buddies.find(
00414 aim_normalize(c.
getServerId(getProtocol())));
00415
00416
if (it != m_buddies.end())
00417 m_buddies.erase(it);
00418
00419 LOG_DEBUG(
"TocProtocol::delContact: I am not removing from TOC");
00420 }
00421
00422
00423
00424 void TocProtocol::connectionError(
Network *net,
int e)
00425 {
00426 eventError(e,
"A Network error occured.");
00427
00428 LOG_DEBUG(
"TocProtocol::connectionError: Connection closed!");
00429
00430
m_net->
disconnect();
00431
00432 eventStateChange(S_offline);
00433 eventLoggedOut();
00434 }
00435
00436 void TocProtocol::connectedToServer(
Network *net)
00437 {
00438
00439
VBuffer flap(
"FLAPON\r\n\r\n", 10);
00440
m_net->
sendData(flap);
00441
00442 LOG_DEBUG(
"FLAPON");
00443
00444
00445 eventStateChange(S_connecting);
00446 }
00447
00448
void TocProtocol::signup()
00449 {
00450 LOG_DEBUG(
"Doing FLAP SIGNON");
00451
00452 string normalizedUsername(aim_normalize(m_conf.
child(
"user").
property(
"username")));
00453 word16 usernameLength = (word16)normalizedUsername.length();
00454
00455
00456 FlapHeader pre;
00457 pre.m_type = (byte)TYPE_SIGNON;
00458 pre.m_len = Network::NBO(word16(usernameLength + 8));
00459
00460 usernameLength = Network::NBO(usernameLength);
00461
00462 word32 ver = Network::NBO(word32(TOC_VER));
00463 word16 tlv = Network::NBO(word16(TOC_TLV));
00464
00465
00466
VBuffer flapOn;
00467 flapOn += (byte) (ver & 0xff);
00468 flapOn += (byte) ((ver >> 8) & 0xff);
00469 flapOn += (byte) ((ver >> 16) & 0xff);
00470 flapOn += (byte) ((ver >> 24) & 0xff);
00471 flapOn += (byte) (tlv & 0xff);
00472 flapOn += (byte) ((tlv >> 8) & 0xff);
00473
00474 flapOn += (byte) (usernameLength & 0xff);
00475 flapOn += (byte) ((usernameLength >> 8) & 0xff);
00476
00477 flapOn += normalizedUsername;
00478
00479 send_flap(TYPE_SIGNON, flapOn);
00480
00481
00482
00483
00484
00485
00486
VBuffer tocSignon;
00487 tocSignon += string(
"toc_signon ");
00488 tocSignon += m_conf.
child(
"loginserver").
property(
"host");
00489 tocSignon += (byte)
' ';
00490 tocSignon += m_conf.
child(
"loginserver").
property(
"port");
00491 tocSignon += (byte)
' ';
00492 tocSignon += normalizedUsername;
00493 tocSignon += (byte)
' ';
00494 tocSignon += roastPassword(m_conf.
child(
"user").
property(
"password"));
00495 tocSignon += string(
" english \"NNIM\"");
00496 tocSignon += (byte)0;
00497
00498 send_flap(TYPE_DATA, tocSignon);
00499
00500 eventStateChange(S_online);
00501 }
00502
00503
void TocProtocol::sendCap()
00504 {
00505 VBuffer caps;
00506 caps += string(
"toc_set_caps ");
00507 caps += string(UID_AIM_CHAT);
00508 send_flap(TYPE_DATA, caps);
00509 }
00510
00511 vector<string> TocProtocol::splitStr(
const string& str)
00512 {
00513
unsigned int i=0;
00514 vector<string> words;
00515
00516 string tmp;
00517
while (i < str.length())
00518 {
00519
while(str[i]!=
':' && i<str.length())
00520 tmp+=str[i++];
00521 i++;
00522 words.push_back(tmp);
00523
00524 tmp=
"";
00525 }
00526
00527
return words;
00528
00529 }
00530
00531 vector<string> TocProtocol::splitStrLF(
const string& str)
00532 {
00533
unsigned int i=0;
00534 vector<string> words;
00535 string tmp;
00536
00537
while (i < str.length())
00538 {
00539
while(str[i]!=0xA && i<str.length())
00540 tmp+=str[i++];
00541 i++;
00542 words.push_back(tmp);
00543 tmp=
"";
00544 }
00545
return words;
00546
00547 }
00548
00549 void TocProtocol::handleData(
Network *net)
00550 {
00551
VBuffer data;
00552 net->
socketData(data);
00553
00554
if (data.size() == 0)
00555
return;
00556
00557
handleData(net,data);
00558
00559 }
00560
00561
void TocProtocol::handleData(
Network *net,
const VBuffer &data)
00562 {
00563
00564 byte frameType = data[1];
00565
00566
switch (frameType) {
00567
case (1): LOG_DEBUG(
"TOC: Signon Frame");
break;
00568
case (2): LOG_DEBUG(
"TOC: Data Frame");
break;
00569
case (5): LOG_DEBUG(
"TOC: Keep Alive");
return;
00570
default:
00571 LOG_ERROR(
"TOC: Unknown Frame Type: " << (
unsigned char)data[1]);
00572 }
00573
00574
if (m_buffer.size() != 0) {
00575 VBuffer newData;
00576
00577
00578 newData += m_buffer;
00579 m_buffer.clear();
00580
00581 newData += data;
00582
handleData(net, newData);
00583
return;
00584 }
00585
00586
00587 word16 payLoadLength;
00588 payLoadLength = (word16)data[4];
00589 payLoadLength |= (word16)(data[5] << 8);
00590
00591
00592 payLoadLength = Network::NBO(payLoadLength);
00593
00594
00595
00596
00597 LOG_DEBUG(
"Payload length: " << payLoadLength <<
" Data length: " << (
unsigned int)data.size());
00598
00599
if (payLoadLength > (data.size() - 6)) {
00600 m_buffer += data;
00601 }
else {
00602
handleRealData(net, string((
const char *)(data.data()+6), payLoadLength));
00603
00604
00605
if (data.size() > (
unsigned int)(payLoadLength+6)) {
00606 LOG_DEBUG(
"More than one command in data stream.");
00607
handleData(net, data.sub(payLoadLength + 6));
00608 }
00609 }
00610 }
00611
00612 void TocProtocol::handleRealData(
Network *net,
const string& data)
00613 {
00615
if (data.length() < 80)
00616 LOG_DEBUG(
"Got Data: " << data);
00617
00618 string command;
00619
00620
00621
00622
if (
getState() == S_connecting) {
00623 signup();
00624
return;
00625 }
00626
00627
unsigned int position((
unsigned int)data.find(
':', 0));
00628
00629 command = data.substr(0, position);
00630
00631 LOG_DEBUG(command);
00632
00633 FuncMap::iterator it = m_funcMap.find(command);
00634
00635
if (it == m_funcMap.end()) {
00636 LOG_DEBUG(
"TOC: Function not found in hashtable: " << command);
00637 }
else {
00638 (this->*(it->second))(data);
00639 }
00640
00641 }
00642
00643
void TocProtocol::processUpdateBuddy(
const string& data)
00644 {
00645 LOG_DEBUG(
"TOC: UPDATE_BUDDY");
00646 vector <string> words=
splitStr(data);
00647
00648 string user = aim_normalize(words[1]);
00649
00650
00651
bool online = (words[2] ==
"T") ?
true :
false;
00652
00653
if (m_buddies.find(user) != m_buddies.end())
00654 {
00655
if (online) {
00656
if (words[6][2] ==
'U') {
00657 LOG_DEBUG(
"Buddy is away");
00658 m_buddies[user].setStatus(
getProtocol(), Contact::Away);
00659 }
else {
00660 m_buddies[user].setStatus(
getProtocol(), Contact::Online);
00661 }
00662 }
else {
00663 m_buddies[user].setStatus(
getProtocol(), Contact::Offline);
00664 }
00665
00666
switch (words[6][1]) {
00667
case (
'A'): LOG_DEBUG(
"Buddy is Oscar Admin");
break;
00668
case (
'U'): LOG_DEBUG(
"Buddy is Oscar Unconfirmed");
break;
00669
case (
'O'): LOG_DEBUG(
"Buddy is Oscar Normal");
break;
00670 }
00671
00672 eventStatusChange(m_buddies[user]);
00673 }
00674 }
00675
00676
void TocProtocol::processFlapSignon(
const string& data)
00677 {
00678 LOG_DEBUG(
"TocProtocol::processFlapSignon");
00679 signup();
00680 }
00682
void TocProtocol::processSignon(
const string& data)
00683 {
00684 LOG_DEBUG(
"TocProtocol::processSignon");
00685 }
00687
void TocProtocol::processGotConfig(
const string& data)
00688 {
00689 LOG_DEBUG(
"TocProtocol::processGotConfig");
00690
00691 VBuffer
setInfo(
"toc_set_info \"");
00692
setInfo += aim_encode(
"<html><body><b>Yes, I'm using NNIM!<br>"
00693
"Visit NNIM at <a href=\"http://nnim.sf.net\">http://nnim.sf.net</a>.</b>"
00694
"</body></html>");
00695
00696
setInfo +=
'\"';
00697
setInfo += (byte)0;
00698 send_flap(TYPE_DATA, setInfo);
00699
00701 addBuddies();
00702
00703 VBuffer initDone(
"toc_init_done");
00704 initDone += (byte)0;
00705
00706 send_flap(TYPE_DATA, initDone);
00707
00708
00709
00710
00711 eventStateChange(S_online);
00712 eventLoggedIn();
00713
00714 tocParseConfig(data.substr(7,data.length()));
00715 }
00716
00718
void TocProtocol::processIM(
const string& data)
00719 {
00720 LOG_DEBUG(
"TocProtocol::processIM");
00721
00722 vector <string> words =
splitStr(data);
00723
00724 string msg = words[3];
00725 string name = aim_normalize(words[1]);
00726
00727
if (m_buddies.find(name)==m_buddies.end() ||
00728 (!m_buddies[words[1]].isOK()))
00729 {
00730 LOG_DEBUG(
"Anonymous user msg.");
00731
00732 Contact c;
00733 c.addProtocol(
getProtocol());
00734 c.setServerId(
getProtocol(), words[1]);
00735 c.setStatus(
getProtocol(), Contact::Online);
00736
00737 c.setName(words[1]);
00738
00739 eventRecvdMessageNotBuddy(c, msg);
00740
return;
00741 }
00742
00743
00744
if (m_away)
00745 {
00746
if (m_awayMessage ==
"")
00747 sendMessageAuto(m_buddies[name],
"I am away");
00748
else
00749 sendMessageAuto(m_buddies[name], m_awayMessage);
00750 }
00751
00752
if (words[2] ==
"T")
00753 msg =
"Auto responce: " + msg;
00754
00755 eventRecvdMessage(m_buddies[name],msg);
00756
00757 }
00759
void TocProtocol::processError(
const string& data)
00760 {
00761 LOG_DEBUG(
"TocProtocol::processError");
00762
int num;
00763 stringstream err;
00764 err << data.substr(6,data.length());
00765 err >> num;
00766
00767 LOG_DEBUG(
"Err Num: " << num);
00768
00769 eventError(E_protocol,
getErrorText(num, data.substr(6, data.length())));
00770 LOG_ERROR(
getErrorText(num, data.substr(6, data.length())));
00771
00772 eventStateChange(S_offline);
00773 }
00774
00776
void TocProtocol::processNick(
const string& data)
00777 {
00778 LOG_DEBUG(
"TocProtocol::processNick");
00779
00780 m_screenName = data.substr(5, data.length());
00781 }
00782
00783 void TocProtocol::update()
00784 {
00785
00786 }
00787 void TocProtocol::newUser(
const string& userName,
const VBuffer& password)
00788 {
00789
00790 }
00791
00792 void TocProtocol::getPubkey()
00793 {
00794
00795 }
00796
00797 void TocProtocol::getInfo(
const string& contact)
00798 {
00799 LOG_DEBUG(
"TocProtocol::getInfo " << aim_normalize(contact));
00800
00801
VBuffer msg;
00802 msg += string(
"toc_get_info ");
00803 msg += aim_normalize(contact);
00804 msg += (byte)0;
00805
00806 send_flap(TYPE_DATA, msg);
00807 }
00808
00809 void TocProtocol::setAway(
const string& msg)
00810 {
00811 LOG_DEBUG(
"TocProtocol::setAway");
00812
if (msg.length() == 0)
00813 {
00814 m_away =
false;
00815 m_awayMessage =
"";
00816 }
else {
00817 m_away =
true;
00818 m_awayMessage = aim_encode(msg);
00819 }
00820
00821
VBuffer setAway;
00822 setAway += string(
"toc_set_away \"");
00823 setAway += aim_encode(msg);
00824 setAway += (byte)
'\"';
00825 setAway += (byte)0;
00826
00827 send_flap(TYPE_DATA, setAway);
00828
00829 }
00830
00831 void TocProtocol::setInfo(
const string& info)
00832 {
00833 LOG_DEBUG(
"TocProtocol::setInfo");
00834
VBuffer tSetInfo;
00835 tSetInfo += string(
"toc_set_info \"");
00836 tSetInfo += aim_encode(info);
00837 tSetInfo += (byte)
'\"';
00838 tSetInfo += (byte)0;
00839
00840 send_flap(TYPE_DATA, tSetInfo);
00841
00842 }
00843
00844
void TocProtocol::tocParseConfig(
const string& config)
00845 {
00846
00847 vector<string> myContacts =
splitStrLF(config);
00848 LOG_DEBUG(
"TocProtocol::tocParseConfig: " << myContacts.size() <<
" contacts from server");
00849
00850 vector<buddy> buddies;
00851
00853
00854 string currentGroup =
"Buddies";
00855
00856
buddy temp;
00857 temp.
proto =
getProtocol();
00858
00859
for (
unsigned int it = 0; it < myContacts.size(); it++)
00860 {
00861
if (myContacts[it][0] ==
'g') {
00862 currentGroup = myContacts[it].substr(2);
00863 }
00864
else
00865
if (myContacts[it][0] ==
'b') {
00866
00867 temp.
name = myContacts[it].substr(2);
00868 temp.
group = currentGroup;
00869 buddies.push_back(temp);
00870 }
00871 }
00872
00873
if (buddies.size() > 0)
00874 eventGotContacts(buddies);
00875
00876 }
00877
00878 }
00879
00880
00881
00882
00883
00884
00885
00886
00887
00888
00889
00890
00891
00892
00893
00894
00895
00896
00897
00898
00899
00900
00901
00902
00903
00904
00905
00906
00907
00908
00909
00910
00911
00912
00913
00914
00915
00916
00917
00918
00919
00920
00921
00922
00923
00924
00925
00926
00927
00928
00929
00930
00931
00932
00933
00934
00935
00936
00937
00938
00939
00940
00941
00942
00943
00944
00945
00946
00947
00948
00949
00950
00951
00952
00953
00954
00955
00956
00957
00958
00959
00960
00961
00962
00963
00964
00965
00966
00967
00968
00969
00970
00971
00972
00973
00974
00975
00976
00977
00978
00979
00980
00981
00982
00983
00984
00985
00986
00987
00988
00989
00990
00991
00992
00993
00994
00995
00996
00997
00998
00999
01000
01001
01002
01003