Lines 23-40
Link Here
|
23 |
#include <msn/notificationserver.h> |
23 |
#include <msn/notificationserver.h> |
24 |
#include <msn/errorcodes.h> |
24 |
#include <msn/errorcodes.h> |
25 |
#include <msn/externals.h> |
25 |
#include <msn/externals.h> |
26 |
#include <md5.h> |
26 |
#include <msn/md5.h> |
27 |
#include <msn/util.h> |
27 |
#include <msn/util.h> |
28 |
#include <curl/curl.h> |
28 |
#include <curl/curl.h> |
29 |
#include <algorithm> |
29 |
#include <algorithm> |
30 |
#include <cassert> |
|
|
31 |
#include <cctype> |
30 |
#include <cctype> |
|
|
31 |
#include <cassert> |
32 |
|
32 |
|
33 |
#ifndef WIN32 |
33 |
#ifndef WIN32 |
34 |
#include <unistd.h> |
34 |
#include <unistd.h> |
35 |
#else |
35 |
#else |
36 |
#include <io.h> |
36 |
#include <io.h> |
37 |
#define EINPROGRESS WSAEINPROGRESS |
37 |
#endif |
|
|
38 |
|
39 |
#include <stdio.h> |
40 |
|
41 |
#ifndef curl_free |
42 |
#define curl_free free |
38 |
#endif |
43 |
#endif |
39 |
|
44 |
|
40 |
namespace MSN |
45 |
namespace MSN |
Lines 43-951
Link Here
|
43 |
|
48 |
|
44 |
static size_t msn_handle_curl_write(void *ptr, size_t size, size_t nmemb, void *stream); |
49 |
static size_t msn_handle_curl_write(void *ptr, size_t size, size_t nmemb, void *stream); |
45 |
static size_t msn_handle_curl_header(void *ptr, size_t size, size_t nmemb, void *stream) ; |
50 |
static size_t msn_handle_curl_header(void *ptr, size_t size, size_t nmemb, void *stream) ; |
46 |
|
51 |
|
47 |
NotificationServerConnection::NotificationServerConnection(NotificationServerConnection::AuthData & auth_) |
52 |
NotificationServerConnection::NotificationServerConnection(NotificationServerConnection::AuthData & auth_, Callbacks & cb_) |
48 |
: Connection(), auth(auth_), connectionStatus(NS_DISCONNECTED) |
53 |
: Connection(), auth(auth_), externalCallbacks(cb_), _connectionState(NS_DISCONNECTED) |
49 |
{ |
54 |
{ |
50 |
registerCommandHandlers(); |
55 |
registerCommandHandlers(); |
51 |
} |
56 |
} |
52 |
|
57 |
|
53 |
NotificationServerConnection::NotificationServerConnection(Passport username_, std::string password_) |
58 |
NotificationServerConnection::NotificationServerConnection(Passport username_, std::string password_, Callbacks & cb_) |
54 |
: Connection(), auth(username_, password_), connectionStatus(NS_DISCONNECTED) |
59 |
: Connection(), auth(username_, password_), externalCallbacks(cb_), _connectionState(NS_DISCONNECTED) |
55 |
{ |
60 |
{ |
56 |
registerCommandHandlers(); |
61 |
registerCommandHandlers(); |
57 |
} |
62 |
} |
58 |
|
63 |
|
59 |
NotificationServerConnection::NotificationServerConnection() : Connection(), auth(Passport(), ""), connectionStatus(NS_DISCONNECTED) |
64 |
NotificationServerConnection::NotificationServerConnection(Callbacks & cb_) : Connection(), auth(Passport(), ""), externalCallbacks(cb_), _connectionState(NS_DISCONNECTED) |
60 |
{ |
65 |
{ |
61 |
registerCommandHandlers(); |
66 |
registerCommandHandlers(); |
62 |
} |
67 |
} |
63 |
|
68 |
|
64 |
NotificationServerConnection::~NotificationServerConnection() |
69 |
NotificationServerConnection::~NotificationServerConnection() |
65 |
{ |
70 |
{ |
66 |
if (connectionStatus != NS_DISCONNECTED) |
71 |
if (this->connectionState() != NS_DISCONNECTED) |
67 |
this->disconnect(); |
72 |
this->disconnect(); |
68 |
} |
73 |
} |
69 |
|
74 |
|
70 |
Connection *NotificationServerConnection::connectionWithSocket(int fd) |
75 |
Connection *NotificationServerConnection::connectionWithSocket(int fd) |
71 |
{ |
76 |
{ |
72 |
assert(connectionStatus != NS_DISCONNECTED); |
77 |
this->assertConnectionStateIsNot(NS_DISCONNECTED); |
73 |
std::list<SwitchboardServerConnection *> & list = _switchboardConnections; |
78 |
std::list<SwitchboardServerConnection *> & list = _switchboardConnections; |
74 |
std::list<SwitchboardServerConnection *>::iterator i = list.begin(); |
79 |
std::list<SwitchboardServerConnection *>::iterator i = list.begin(); |
75 |
|
80 |
|
76 |
if (this->sock == fd) |
81 |
if (this->sock == fd) |
77 |
return this; |
82 |
return this; |
78 |
|
83 |
|
79 |
for (; i != list.end(); i++) |
84 |
for (; i != list.end(); i++) |
80 |
{ |
85 |
{ |
81 |
Connection *c = (*i)->connectionWithSocket(fd); |
86 |
Connection *c = (*i)->connectionWithSocket(fd); |
82 |
if (c) |
87 |
if (c) |
83 |
return c; |
88 |
return c; |
84 |
} |
89 |
} |
85 |
return NULL; |
90 |
return NULL; |
86 |
} |
91 |
} |
87 |
|
92 |
|
88 |
SwitchboardServerConnection *NotificationServerConnection::switchboardWithOnlyUser(Passport username) |
93 |
SwitchboardServerConnection *NotificationServerConnection::switchboardWithOnlyUser(Passport username) |
89 |
{ |
94 |
{ |
90 |
assert(connectionStatus >= NS_CONNECTED); |
95 |
if (this->connectionState() >= NS_CONNECTED) |
91 |
std::list<SwitchboardServerConnection *> & list = _switchboardConnections; |
96 |
{ |
92 |
std::list<SwitchboardServerConnection *>::iterator i = list.begin(); |
97 |
std::list<SwitchboardServerConnection *> & list = _switchboardConnections; |
93 |
|
98 |
std::list<SwitchboardServerConnection *>::iterator i = list.begin(); |
94 |
for (; i != list.end(); i++) |
99 |
|
95 |
{ |
100 |
for (; i != list.end(); i++) |
96 |
if ((*i)->users.size() == 1 && |
101 |
{ |
97 |
*((*i)->users.begin()) == username) |
102 |
if ((*i)->users.size() == 1 && |
98 |
return *i; |
103 |
*((*i)->users.begin()) == username) |
99 |
} |
104 |
return *i; |
100 |
return NULL; |
105 |
} |
|
|
106 |
} |
107 |
return NULL; |
101 |
} |
108 |
} |
102 |
|
109 |
|
103 |
const std::list<SwitchboardServerConnection *> & NotificationServerConnection::switchboardConnections() |
110 |
const std::list<SwitchboardServerConnection *> & NotificationServerConnection::switchboardConnections() |
104 |
{ |
111 |
{ |
105 |
assert(connectionStatus >= NS_CONNECTED); |
112 |
this->assertConnectionStateIsAtLeast(NS_CONNECTED); |
106 |
return _switchboardConnections; |
113 |
return _switchboardConnections; |
107 |
} |
114 |
} |
108 |
|
115 |
|
109 |
void NotificationServerConnection::addSwitchboardConnection(SwitchboardServerConnection *c) |
116 |
void NotificationServerConnection::addSwitchboardConnection(SwitchboardServerConnection *c) |
110 |
{ |
117 |
{ |
111 |
assert(connectionStatus >= NS_CONNECTED); |
118 |
this->assertConnectionStateIsAtLeast(NS_CONNECTED); |
112 |
_switchboardConnections.push_back(c); |
119 |
_switchboardConnections.push_back(c); |
113 |
} |
120 |
} |
114 |
|
121 |
|
115 |
void NotificationServerConnection::removeSwitchboardConnection(SwitchboardServerConnection *c) |
122 |
void NotificationServerConnection::removeSwitchboardConnection(SwitchboardServerConnection *c) |
116 |
{ |
123 |
{ |
117 |
assert(connectionStatus >= NS_CONNECTED); |
124 |
this->assertConnectionStateIsAtLeast(NS_CONNECTED); |
118 |
_switchboardConnections.remove(c); |
125 |
_switchboardConnections.remove(c); |
119 |
} |
126 |
} |
120 |
|
127 |
|
121 |
void NotificationServerConnection::addCallback(NotificationServerCallback callback, |
128 |
void NotificationServerConnection::addCallback(NotificationServerCallback callback, |
122 |
int trid, void *data) |
129 |
int trid, void *data) |
123 |
{ |
130 |
{ |
124 |
assert(connectionStatus >= NS_CONNECTING); |
131 |
this->assertConnectionStateIsAtLeast(NS_CONNECTING); |
125 |
this->callbacks[trid] = std::make_pair(callback, data); |
132 |
this->callbacks[trid] = std::make_pair(callback, data); |
126 |
} |
133 |
} |
127 |
|
134 |
|
128 |
void NotificationServerConnection::removeCallback(int trid) |
135 |
void NotificationServerConnection::removeCallback(int trid) |
129 |
{ |
136 |
{ |
130 |
assert(connectionStatus >= NS_CONNECTING); |
137 |
this->assertConnectionStateIsAtLeast(NS_CONNECTING); |
131 |
this->callbacks.erase(trid); |
138 |
this->callbacks.erase(trid); |
132 |
} |
139 |
} |
133 |
|
140 |
|
134 |
void NotificationServerConnection::registerCommandHandlers() |
141 |
void NotificationServerConnection::registerCommandHandlers() |
135 |
{ |
142 |
{ |
136 |
if (commandHandlers.size() == 0) |
143 |
if (commandHandlers.size() == 0) |
137 |
{ |
144 |
{ |
138 |
commandHandlers["OUT"] = &NotificationServerConnection::handle_OUT; |
145 |
commandHandlers["OUT"] = &NotificationServerConnection::handle_OUT; |
139 |
commandHandlers["ADD"] = &NotificationServerConnection::handle_ADD; |
146 |
commandHandlers["ADD"] = &NotificationServerConnection::handle_ADD; |
140 |
commandHandlers["REM"] = &NotificationServerConnection::handle_REM; |
147 |
commandHandlers["REM"] = &NotificationServerConnection::handle_REM; |
141 |
commandHandlers["BLP"] = &NotificationServerConnection::handle_BLP; |
148 |
commandHandlers["BLP"] = &NotificationServerConnection::handle_BLP; |
142 |
commandHandlers["GTC"] = &NotificationServerConnection::handle_GTC; |
149 |
commandHandlers["GTC"] = &NotificationServerConnection::handle_GTC; |
143 |
commandHandlers["REA"] = &NotificationServerConnection::handle_REA; |
150 |
commandHandlers["REA"] = &NotificationServerConnection::handle_REA; |
144 |
commandHandlers["CHG"] = &NotificationServerConnection::handle_CHG; |
151 |
commandHandlers["CHG"] = &NotificationServerConnection::handle_CHG; |
145 |
commandHandlers["CHL"] = &NotificationServerConnection::handle_CHL; |
152 |
commandHandlers["CHL"] = &NotificationServerConnection::handle_CHL; |
146 |
commandHandlers["ILN"] = &NotificationServerConnection::handle_ILN; |
153 |
commandHandlers["ILN"] = &NotificationServerConnection::handle_ILN; |
147 |
commandHandlers["NLN"] = &NotificationServerConnection::handle_NLN; |
154 |
commandHandlers["NLN"] = &NotificationServerConnection::handle_NLN; |
148 |
commandHandlers["FLN"] = &NotificationServerConnection::handle_FLN; |
155 |
commandHandlers["FLN"] = &NotificationServerConnection::handle_FLN; |
149 |
commandHandlers["MSG"] = &NotificationServerConnection::handle_MSG; |
156 |
commandHandlers["MSG"] = &NotificationServerConnection::handle_MSG; |
150 |
commandHandlers["ADG"] = &NotificationServerConnection::handle_ADG; |
157 |
commandHandlers["ADG"] = &NotificationServerConnection::handle_ADG; |
151 |
commandHandlers["RMG"] = &NotificationServerConnection::handle_RMG; |
158 |
commandHandlers["RMG"] = &NotificationServerConnection::handle_RMG; |
152 |
commandHandlers["REG"] = &NotificationServerConnection::handle_REG; |
159 |
commandHandlers["REG"] = &NotificationServerConnection::handle_REG; |
153 |
} |
160 |
} |
154 |
} |
161 |
} |
155 |
|
162 |
|
156 |
void NotificationServerConnection::dispatchCommand(std::vector<std::string> & args) |
163 |
void NotificationServerConnection::dispatchCommand(std::vector<std::string> & args) |
157 |
{ |
164 |
{ |
158 |
assert(connectionStatus >= NS_CONNECTED); |
165 |
this->assertConnectionStateIsAtLeast(NS_CONNECTED); |
159 |
std::map<std::string, void (NotificationServerConnection::*)(std::vector<std::string> &)>::iterator i = commandHandlers.find(args[0]); |
166 |
std::map<std::string, void (NotificationServerConnection::*)(std::vector<std::string> &)>::iterator i = commandHandlers.find(args[0]); |
160 |
if (i != commandHandlers.end()) |
167 |
if (i != commandHandlers.end()) |
161 |
(this->*commandHandlers[args[0]])(args); |
168 |
(this->*commandHandlers[args[0]])(args); |
162 |
} |
169 |
} |
163 |
|
170 |
|
164 |
void NotificationServerConnection::handle_OUT(std::vector<std::string> & args) |
171 |
void NotificationServerConnection::handle_OUT(std::vector<std::string> & args) |
165 |
{ |
172 |
{ |
166 |
assert(connectionStatus >= NS_CONNECTED); |
173 |
this->assertConnectionStateIsAtLeast(NS_CONNECTED); |
167 |
if (args.size() > 1) |
174 |
if (args.size() > 1) |
168 |
{ |
175 |
{ |
169 |
if (args[1] == "OTH") |
176 |
if (args[1] == "OTH") |
170 |
{ |
177 |
{ |
171 |
ext::showError(this, "You have logged onto MSN twice at once. Your MSN session will now terminate."); |
178 |
this->myNotificationServer()->externalCallbacks.showError(this, "You have logged onto MSN twice at once. Your MSN session will now terminate."); |
172 |
} |
179 |
} |
173 |
else if (args[1] == "SSD") |
180 |
else if (args[1] == "SSD") |
174 |
{ |
181 |
{ |
175 |
ext::showError(this, "This MSN server is going down for maintenance. Your MSN session will now terminate."); |
182 |
this->myNotificationServer()->externalCallbacks.showError(this, "This MSN server is going down for maintenance. Your MSN session will now terminate."); |
176 |
} else { |
183 |
} else { |
177 |
ext::showError(this, (std::string("The MSN server has terminated the connection with an unknown reason code. Please report this code: ") + |
184 |
this->myNotificationServer()->externalCallbacks.showError(this, (std::string("The MSN server has terminated the connection with an unknown reason code. Please report this code: ") + |
178 |
args[1]).c_str()); |
185 |
args[1]).c_str()); |
179 |
} |
186 |
} |
180 |
} |
187 |
} |
181 |
this->disconnect(); |
188 |
this->disconnect(); |
182 |
} |
189 |
} |
183 |
|
190 |
|
184 |
void NotificationServerConnection::handle_ADD(std::vector<std::string> & args) |
191 |
void NotificationServerConnection::handle_ADD(std::vector<std::string> & args) |
185 |
{ |
192 |
{ |
186 |
assert(connectionStatus >= NS_CONNECTED); |
193 |
this->assertConnectionStateIsAtLeast(NS_CONNECTED); |
187 |
if (args[2] == "RL") |
194 |
if (args[2] == "RL") |
188 |
{ |
195 |
{ |
189 |
ext::gotNewReverseListEntry(this, args[4], decodeURL(args[5])); |
196 |
this->myNotificationServer()->externalCallbacks.gotNewReverseListEntry(this, args[4], decodeURL(args[5])); |
190 |
} |
197 |
} |
191 |
else |
198 |
else |
192 |
{ |
199 |
{ |
193 |
int groupID = -1; |
200 |
int groupID = -1; |
194 |
if (args.size() > 5) |
201 |
if (args.size() > 5) |
195 |
groupID = decimalFromString(args[5]); |
202 |
groupID = decimalFromString(args[5]); |
196 |
|
203 |
|
197 |
ext::addedListEntry(this, args[2], args[4], groupID); |
204 |
this->myNotificationServer()->externalCallbacks.addedListEntry(this, args[2], args[4], groupID); |
198 |
} |
205 |
} |
199 |
ext::gotLatestListSerial(this, decimalFromString(args[3])); |
206 |
this->myNotificationServer()->externalCallbacks.gotLatestListSerial(this, decimalFromString(args[3])); |
200 |
} |
207 |
} |
201 |
|
208 |
|
202 |
void NotificationServerConnection::handle_REM(std::vector<std::string> & args) |
209 |
void NotificationServerConnection::handle_REM(std::vector<std::string> & args) |
203 |
{ |
210 |
{ |
204 |
assert(connectionStatus >= NS_CONNECTED); |
211 |
this->assertConnectionStateIsAtLeast(NS_CONNECTED); |
205 |
int groupID = -1; |
212 |
int groupID = -1; |
206 |
if (args.size() > 4) |
213 |
if (args.size() > 4) |
207 |
groupID = decimalFromString(args[4]); |
214 |
groupID = decimalFromString(args[4]); |
208 |
|
215 |
|
209 |
ext::removedListEntry(this, args[2], args[4], groupID); |
216 |
this->myNotificationServer()->externalCallbacks.removedListEntry(this, args[2], args[4], groupID); |
210 |
ext::gotLatestListSerial(this, decimalFromString(args[3])); |
217 |
this->myNotificationServer()->externalCallbacks.gotLatestListSerial(this, decimalFromString(args[3])); |
211 |
} |
218 |
} |
212 |
|
219 |
|
213 |
void NotificationServerConnection::handle_BLP(std::vector<std::string> & args) |
220 |
void NotificationServerConnection::handle_BLP(std::vector<std::string> & args) |
214 |
{ |
221 |
{ |
215 |
assert(connectionStatus >= NS_CONNECTED); |
222 |
this->assertConnectionStateIsAtLeast(NS_CONNECTED); |
216 |
ext::gotBLP(this, args[3][0]); |
223 |
this->myNotificationServer()->externalCallbacks.gotBLP(this, args[3][0]); |
217 |
ext::gotLatestListSerial(this, decimalFromString(args[3])); |
224 |
this->myNotificationServer()->externalCallbacks.gotLatestListSerial(this, decimalFromString(args[3])); |
218 |
} |
225 |
} |
219 |
|
226 |
|
220 |
void NotificationServerConnection::handle_GTC(std::vector<std::string> & args) |
227 |
void NotificationServerConnection::handle_GTC(std::vector<std::string> & args) |
221 |
{ |
228 |
{ |
222 |
assert(connectionStatus >= NS_CONNECTED); |
229 |
this->assertConnectionStateIsAtLeast(NS_CONNECTED); |
223 |
ext::gotGTC(this, args[3][0]); |
230 |
this->myNotificationServer()->externalCallbacks.gotGTC(this, args[3][0]); |
224 |
ext::gotLatestListSerial(this, decimalFromString(args[3])); |
231 |
this->myNotificationServer()->externalCallbacks.gotLatestListSerial(this, decimalFromString(args[3])); |
225 |
} |
232 |
} |
226 |
|
233 |
|
227 |
void NotificationServerConnection::handle_REA(std::vector<std::string> & args) |
234 |
void NotificationServerConnection::handle_REA(std::vector<std::string> & args) |
228 |
{ |
235 |
{ |
229 |
assert(connectionStatus >= NS_CONNECTED); |
236 |
this->assertConnectionStateIsAtLeast(NS_CONNECTED); |
230 |
ext::gotFriendlyName(this, decodeURL(args[4])); |
237 |
this->myNotificationServer()->externalCallbacks.gotFriendlyName(this, decodeURL(args[4])); |
231 |
ext::gotLatestListSerial(this, decimalFromString(args[2])); |
238 |
this->myNotificationServer()->externalCallbacks.gotLatestListSerial(this, decimalFromString(args[2])); |
232 |
} |
239 |
} |
233 |
|
240 |
|
234 |
void NotificationServerConnection::handle_CHG(std::vector<std::string> & args) |
241 |
void NotificationServerConnection::handle_CHG(std::vector<std::string> & args) |
235 |
{ |
242 |
{ |
236 |
assert(connectionStatus >= NS_CONNECTED); |
243 |
this->assertConnectionStateIsAtLeast(NS_CONNECTED); |
237 |
ext::changedStatus(this, buddyStatusFromString(args[2])); |
244 |
this->myNotificationServer()->externalCallbacks.changedStatus(this, buddyStatusFromString(args[2])); |
238 |
} |
245 |
} |
239 |
|
246 |
|
240 |
void NotificationServerConnection::handle_CHL(std::vector<std::string> & args) |
247 |
void NotificationServerConnection::handle_CHL(std::vector<std::string> & args) |
241 |
{ |
248 |
{ |
242 |
assert(connectionStatus >= NS_CONNECTED); |
249 |
this->assertConnectionStateIsAtLeast(NS_CONNECTED); |
243 |
md5_state_t state; |
250 |
md5_state_t state; |
244 |
md5_byte_t digest[16]; |
251 |
md5_byte_t digest[16]; |
245 |
int a; |
252 |
int a; |
246 |
|
253 |
|
247 |
md5_init(&state); |
254 |
md5_init(&state); |
248 |
md5_append(&state, (md5_byte_t *)(args[2].c_str()), (int) args[2].size()); |
255 |
md5_append(&state, (md5_byte_t *)(args[2].c_str()), (int) args[2].size()); |
249 |
md5_append(&state, (md5_byte_t *)"VT6PX?UQTM4WM%YR", 16); |
256 |
md5_append(&state, (md5_byte_t *)"VT6PX?UQTM4WM%YR", 16); |
250 |
md5_finish(&state, digest); |
257 |
md5_finish(&state, digest); |
251 |
|
258 |
|
252 |
std::ostringstream buf_; |
259 |
std::ostringstream buf_; |
253 |
buf_ << "QRY " << trid++ << " PROD0038W!61ZTF9 32\r\n"; |
260 |
buf_ << "QRY " << this->trID++ << " PROD0038W!61ZTF9 32\r\n"; |
254 |
write(buf_); |
261 |
if (write(buf_) != buf_.str().size()) |
255 |
|
262 |
return; |
256 |
|
263 |
|
257 |
char hexdigest[3]; |
264 |
|
258 |
for (a = 0; a < 16; a++) |
265 |
char hexdigest[3]; |
259 |
{ |
266 |
for (a = 0; a < 16; a++) |
260 |
sprintf(hexdigest, "%02x", digest[a]); |
267 |
{ |
261 |
write(std::string(hexdigest, 2), false); |
268 |
sprintf(hexdigest, "%02x", digest[a]); |
262 |
} |
269 |
write(std::string(hexdigest, 2), false); |
|
|
270 |
} |
263 |
} |
271 |
} |
264 |
|
272 |
|
265 |
void NotificationServerConnection::handle_ILN(std::vector<std::string> & args) |
273 |
void NotificationServerConnection::handle_ILN(std::vector<std::string> & args) |
266 |
{ |
274 |
{ |
267 |
assert(connectionStatus == NS_CONNECTED); |
275 |
this->assertConnectionStateIs(NS_CONNECTED); |
268 |
ext::buddyChangedStatus(this, args[3], decodeURL(args[4]), buddyStatusFromString(args[2])); |
276 |
this->myNotificationServer()->externalCallbacks.buddyChangedStatus(this, args[3], decodeURL(args[4]), buddyStatusFromString(args[2])); |
269 |
} |
277 |
} |
270 |
|
278 |
|
271 |
void NotificationServerConnection::handle_NLN(std::vector<std::string> & args) |
279 |
void NotificationServerConnection::handle_NLN(std::vector<std::string> & args) |
272 |
{ |
280 |
{ |
273 |
assert(connectionStatus >= NS_CONNECTED); |
281 |
this->assertConnectionStateIsAtLeast(NS_CONNECTED); |
274 |
ext::buddyChangedStatus(this, args[2], decodeURL(args[3]), buddyStatusFromString(args[1])); |
282 |
this->myNotificationServer()->externalCallbacks.buddyChangedStatus(this, args[2], decodeURL(args[3]), buddyStatusFromString(args[1])); |
275 |
} |
283 |
} |
276 |
|
284 |
|
277 |
void NotificationServerConnection::handle_FLN(std::vector<std::string> & args) |
285 |
void NotificationServerConnection::handle_FLN(std::vector<std::string> & args) |
278 |
{ |
286 |
{ |
279 |
assert(connectionStatus >= NS_CONNECTED); |
287 |
this->assertConnectionStateIsAtLeast(NS_CONNECTED); |
280 |
ext::buddyOffline(this, args[1]); |
288 |
this->myNotificationServer()->externalCallbacks.buddyOffline(this, args[1]); |
281 |
} |
289 |
} |
282 |
|
290 |
|
283 |
void NotificationServerConnection::handle_MSG(std::vector<std::string> & args) |
291 |
void NotificationServerConnection::handle_MSG(std::vector<std::string> & args) |
284 |
{ |
292 |
{ |
285 |
assert(connectionStatus >= NS_CONNECTED); |
293 |
this->assertConnectionStateIsAtLeast(NS_CONNECTED); |
286 |
Connection::handle_MSG(args); |
294 |
Connection::handle_MSG(args); |
287 |
} |
295 |
} |
288 |
|
296 |
|
289 |
void NotificationServerConnection::handle_RNG(std::vector<std::string> & args) |
297 |
void NotificationServerConnection::handle_RNG(std::vector<std::string> & args) |
290 |
{ |
298 |
{ |
291 |
assert(connectionStatus >= NS_CONNECTED); |
299 |
this->assertConnectionStateIsAtLeast(NS_CONNECTED); |
292 |
SwitchboardServerConnection::AuthData auth = SwitchboardServerConnection::AuthData(this->auth.username, |
300 |
SwitchboardServerConnection::AuthData auth = SwitchboardServerConnection::AuthData(this->auth.username, |
293 |
args[1], |
301 |
args[1], |
294 |
args[4]); |
302 |
args[4]); |
295 |
SwitchboardServerConnection *newSBconn = new SwitchboardServerConnection(auth, *this); |
303 |
SwitchboardServerConnection *newSBconn = new SwitchboardServerConnection(auth, *this); |
296 |
this->addSwitchboardConnection(newSBconn); |
304 |
this->addSwitchboardConnection(newSBconn); |
297 |
std::pair<std::string, int> server_address = splitServerAddress(args[2]); |
305 |
std::pair<std::string, int> server_address = splitServerAddress(args[2]); |
298 |
newSBconn->connect(server_address.first, server_address.second); |
306 |
newSBconn->connect(server_address.first, server_address.second); |
299 |
} |
307 |
} |
300 |
|
308 |
|
301 |
void NotificationServerConnection::handle_ADG(std::vector<std::string> & args) |
309 |
void NotificationServerConnection::handle_ADG(std::vector<std::string> & args) |
302 |
{ |
310 |
{ |
303 |
assert(connectionStatus >= NS_CONNECTED); |
311 |
this->assertConnectionStateIsAtLeast(NS_CONNECTED); |
304 |
ext::addedGroup(this, args[3], decimalFromString(args[4])); |
312 |
this->myNotificationServer()->externalCallbacks.addedGroup(this, decodeURL(args[3]), decimalFromString(args[4])); |
305 |
ext::gotLatestListSerial(this, decimalFromString(args[2])); |
313 |
this->myNotificationServer()->externalCallbacks.gotLatestListSerial(this, decimalFromString(args[2])); |
306 |
} |
314 |
} |
307 |
|
315 |
|
308 |
void NotificationServerConnection::handle_RMG(std::vector<std::string> & args) |
316 |
void NotificationServerConnection::handle_RMG(std::vector<std::string> & args) |
309 |
{ |
317 |
{ |
310 |
assert(connectionStatus >= NS_CONNECTED); |
318 |
this->assertConnectionStateIsAtLeast(NS_CONNECTED); |
311 |
ext::removedGroup(this, decimalFromString(args[3])); |
319 |
this->myNotificationServer()->externalCallbacks.removedGroup(this, decimalFromString(args[3])); |
312 |
ext::gotLatestListSerial(this, decimalFromString(args[2])); |
320 |
this->myNotificationServer()->externalCallbacks.gotLatestListSerial(this, decimalFromString(args[2])); |
313 |
} |
321 |
} |
314 |
|
322 |
|
315 |
void NotificationServerConnection::handle_REG(std::vector<std::string> & args) |
323 |
void NotificationServerConnection::handle_REG(std::vector<std::string> & args) |
316 |
{ |
324 |
{ |
317 |
assert(connectionStatus >= NS_CONNECTED); |
325 |
this->assertConnectionStateIsAtLeast(NS_CONNECTED); |
318 |
ext::renamedGroup(this, decimalFromString(args[3]), args[4]); |
326 |
this->myNotificationServer()->externalCallbacks.renamedGroup(this, decimalFromString(args[3]), decodeURL(args[4])); |
319 |
ext::gotLatestListSerial(this, decimalFromString(args[2])); |
327 |
this->myNotificationServer()->externalCallbacks.gotLatestListSerial(this, decimalFromString(args[2])); |
320 |
} |
328 |
} |
321 |
|
329 |
|
322 |
|
330 |
|
323 |
void NotificationServerConnection::setState(BuddyStatus state) |
331 |
void NotificationServerConnection::setState(BuddyStatus state) |
324 |
{ |
332 |
{ |
325 |
assert(connectionStatus >= NS_CONNECTED); |
333 |
this->assertConnectionStateIsAtLeast(NS_CONNECTED); |
326 |
std::ostringstream buf_; |
334 |
std::ostringstream buf_; |
327 |
buf_ << "CHG " << trid++ << " " << buddyStatusToString(state) << " 0\r\n"; |
335 |
buf_ << "CHG " << this->trID++ << " " << buddyStatusToString(state) << " 0\r\n"; |
328 |
write(buf_); |
336 |
write(buf_); |
329 |
} |
337 |
} |
330 |
|
338 |
|
331 |
void NotificationServerConnection::setBLP(char setting) |
339 |
void NotificationServerConnection::setBLP(char setting) |
332 |
{ |
340 |
{ |
333 |
assert(connectionStatus >= NS_CONNECTED); |
341 |
this->assertConnectionStateIsAtLeast(NS_CONNECTED); |
334 |
std::ostringstream buf_; |
342 |
std::ostringstream buf_; |
335 |
buf_ << "BLP " << trid++ << " " << setting << "L\r\n"; |
343 |
buf_ << "BLP " << this->trID++ << " " << setting << "L\r\n"; |
336 |
write(buf_); |
344 |
write(buf_); |
337 |
} |
345 |
} |
338 |
|
346 |
|
339 |
void NotificationServerConnection::setGTC(char setting) |
347 |
void NotificationServerConnection::setGTC(char setting) |
340 |
{ |
348 |
{ |
341 |
assert(connectionStatus >= NS_CONNECTED); |
349 |
this->assertConnectionStateIsAtLeast(NS_CONNECTED); |
342 |
std::ostringstream buf_; |
350 |
std::ostringstream buf_; |
343 |
buf_ << "GTC " << trid++ << " " << setting << "\r\n"; |
351 |
buf_ << "GTC " << this->trID++ << " " << setting << "\r\n"; |
344 |
write(buf_); |
352 |
write(buf_); |
345 |
} |
353 |
} |
346 |
|
354 |
|
347 |
void NotificationServerConnection::setFriendlyName(std::string friendlyName) throw (std::runtime_error) |
355 |
void NotificationServerConnection::setFriendlyName(std::string friendlyName) throw (std::runtime_error) |
348 |
{ |
356 |
{ |
349 |
assert(connectionStatus >= NS_CONNECTED); |
357 |
this->assertConnectionStateIsAtLeast(NS_CONNECTED); |
350 |
if (friendlyName.size() > 387) |
358 |
if (friendlyName.size() > 387) |
351 |
throw std::runtime_error("Friendly name too long!"); |
359 |
throw std::runtime_error("Friendly name too long!"); |
352 |
|
360 |
|
353 |
std::ostringstream buf_; |
361 |
std::ostringstream buf_; |
354 |
buf_ << "REA " << trid++ << " " << this->auth.username << " " << encodeURL(friendlyName) << "\r\n"; |
362 |
buf_ << "REA " << this->trID++ << " " << this->auth.username << " " << encodeURL(friendlyName) << "\r\n"; |
355 |
write(buf_); |
363 |
write(buf_); |
356 |
} |
364 |
} |
357 |
|
365 |
|
358 |
void NotificationServerConnection::addToList(std::string list, Passport buddyName) |
366 |
void NotificationServerConnection::addToList(std::string list, Passport buddyName) |
359 |
{ |
367 |
{ |
360 |
assert(connectionStatus >= NS_CONNECTED); |
368 |
this->assertConnectionStateIsAtLeast(NS_CONNECTED); |
361 |
std::ostringstream buf_; |
369 |
std::ostringstream buf_; |
362 |
buf_ << "ADD " << trid++ << " " << list << " " << buddyName << " " << buddyName << "\r\n"; |
370 |
buf_ << "ADD " << this->trID++ << " " << list << " " << buddyName << " " << buddyName << "\r\n"; |
363 |
write(buf_); |
371 |
write(buf_); |
364 |
} |
372 |
} |
365 |
|
373 |
|
366 |
void NotificationServerConnection::removeFromList(std::string list, Passport buddyName) |
374 |
void NotificationServerConnection::removeFromList(std::string list, Passport buddyName) |
367 |
{ |
375 |
{ |
368 |
assert(connectionStatus >= NS_CONNECTED); |
376 |
this->assertConnectionStateIsAtLeast(NS_CONNECTED); |
369 |
std::ostringstream buf_; |
377 |
std::ostringstream buf_; |
370 |
buf_ << "REM " << trid++ << " " << list << " " << buddyName << "\r\n"; |
378 |
buf_ << "REM " << this->trID++ << " " << list << " " << buddyName << "\r\n"; |
371 |
write(buf_); |
379 |
write(buf_); |
372 |
} |
380 |
} |
373 |
|
381 |
|
374 |
void NotificationServerConnection::addToGroup(Passport buddyName, int groupID) |
382 |
void NotificationServerConnection::addToGroup(Passport buddyName, int groupID) |
375 |
{ |
383 |
{ |
376 |
assert(connectionStatus >= NS_CONNECTED); |
384 |
this->assertConnectionStateIsAtLeast(NS_CONNECTED); |
377 |
std::ostringstream buf_; |
385 |
std::ostringstream buf_; |
378 |
buf_ << "ADD " << trid++ << " " << "FL" << " " << buddyName << " " << buddyName << " " << groupID << "\r\n"; |
386 |
buf_ << "ADD " << this->trID++ << " " << "FL" << " " << buddyName << " " << buddyName << " " << groupID << "\r\n"; |
379 |
write(buf_); |
387 |
write(buf_); |
380 |
} |
388 |
} |
381 |
|
389 |
|
382 |
void NotificationServerConnection::removeFromGroup(Passport buddyName, int groupID) |
390 |
void NotificationServerConnection::removeFromGroup(Passport buddyName, int groupID) |
383 |
{ |
391 |
{ |
384 |
assert(connectionStatus >= NS_CONNECTED); |
392 |
this->assertConnectionStateIsAtLeast(NS_CONNECTED); |
385 |
std::ostringstream buf_; |
393 |
std::ostringstream buf_; |
386 |
buf_ << "REM " << trid++ << " " << "FL" << " " << buddyName << " " << groupID << "\r\n"; |
394 |
buf_ << "REM " << this->trID++ << " " << "FL" << " " << buddyName << " " << groupID << "\r\n"; |
387 |
write(buf_); |
395 |
write(buf_); |
388 |
} |
396 |
} |
389 |
|
397 |
|
390 |
void NotificationServerConnection::addGroup(std::string groupName) |
398 |
void NotificationServerConnection::addGroup(std::string groupName) |
391 |
{ |
399 |
{ |
392 |
assert(connectionStatus >= NS_CONNECTED); |
400 |
this->assertConnectionStateIsAtLeast(NS_CONNECTED); |
393 |
std::ostringstream buf_; |
401 |
std::ostringstream buf_; |
394 |
buf_ << "ADG " << trid++ << " " << encodeURL(groupName) << " " << 0 << "\r\n"; |
402 |
buf_ << "ADG " << this->trID++ << " " << encodeURL(groupName) << " " << 0 << "\r\n"; |
395 |
write(buf_); |
403 |
write(buf_); |
396 |
} |
404 |
} |
397 |
|
405 |
|
398 |
void NotificationServerConnection::removeGroup(int groupID) |
406 |
void NotificationServerConnection::removeGroup(int groupID) |
399 |
{ |
407 |
{ |
400 |
assert(connectionStatus >= NS_CONNECTED); |
408 |
this->assertConnectionStateIsAtLeast(NS_CONNECTED); |
401 |
std::ostringstream buf_; |
409 |
std::ostringstream buf_; |
402 |
buf_ << "RMG " << trid++ << " " << groupID << "\r\n"; |
410 |
buf_ << "RMG " << this->trID++ << " " << groupID << "\r\n"; |
403 |
write(buf_); |
411 |
write(buf_); |
404 |
} |
412 |
} |
405 |
|
413 |
|
406 |
void NotificationServerConnection::renameGroup(int groupID, std::string newGroupName) |
414 |
void NotificationServerConnection::renameGroup(int groupID, std::string newGroupName) |
407 |
{ |
415 |
{ |
408 |
assert(connectionStatus >= NS_CONNECTED); |
416 |
this->assertConnectionStateIsAtLeast(NS_CONNECTED); |
409 |
std::ostringstream buf_; |
417 |
std::ostringstream buf_; |
410 |
buf_ << "REG " << trid++ << " " << groupID << " " << encodeURL(newGroupName) << " " << 0 << "\r\n"; |
418 |
buf_ << "REG " << this->trID++ << " " << groupID << " " << encodeURL(newGroupName) << " " << 0 << "\r\n"; |
411 |
write(buf_); |
419 |
write(buf_); |
412 |
} |
420 |
} |
413 |
|
421 |
|
414 |
|
422 |
|
415 |
void NotificationServerConnection::synchronizeLists(int version) |
423 |
void NotificationServerConnection::synchronizeLists(int version) |
416 |
{ |
424 |
{ |
417 |
assert(connectionStatus >= NS_CONNECTED && connectionStatus != NS_SYNCHRONISING); |
425 |
this->assertConnectionStateIsAtLeast(NS_CONNECTED); |
418 |
ListSyncInfo *info = new ListSyncInfo(version); |
426 |
this->assertConnectionStateIsNot(NS_SYNCHRONISING); |
419 |
|
427 |
ListSyncInfo *info = new ListSyncInfo(version); |
420 |
std::ostringstream buf_; |
428 |
|
421 |
buf_ << "SYN " << trid << " " << version << "\r\n"; |
429 |
std::ostringstream buf_; |
422 |
write(buf_); |
430 |
buf_ << "SYN " << this->trID << " " << version << "\r\n"; |
423 |
|
431 |
if (write(buf_) != buf_.str().size()) |
424 |
this->addCallback(&NotificationServerConnection::callback_SyncData, trid, (void *)info); |
432 |
return; |
425 |
this->synctrid = trid++; |
433 |
|
426 |
connectionStatus = NS_SYNCHRONISING; |
434 |
this->addCallback(&NotificationServerConnection::callback_SyncData, this->trID, (void *)info); |
|
|
435 |
this->synctrid = this->trID++; |
436 |
this->setConnectionState(NS_SYNCHRONISING); |
427 |
} |
437 |
} |
428 |
|
438 |
|
429 |
void NotificationServerConnection::sendPing() |
439 |
void NotificationServerConnection::sendPing() |
430 |
{ |
440 |
{ |
431 |
assert(connectionStatus >= NS_CONNECTED); |
441 |
this->assertConnectionStateIsAtLeast(NS_CONNECTED); |
432 |
write("PNG\r\n"); |
442 |
write("PNG\r\n"); |
433 |
} |
443 |
} |
434 |
|
444 |
|
435 |
void NotificationServerConnection::requestSwitchboardConnection(const void *tag) |
445 |
void NotificationServerConnection::requestSwitchboardConnection(const void *tag) |
436 |
{ |
446 |
{ |
437 |
assert(connectionStatus >= NS_CONNECTED); |
447 |
this->assertConnectionStateIsAtLeast(NS_CONNECTED); |
438 |
SwitchboardServerConnection::AuthData *auth = new SwitchboardServerConnection::AuthData(this->auth.username, tag); |
448 |
SwitchboardServerConnection::AuthData *auth = new SwitchboardServerConnection::AuthData(this->auth.username, tag); |
439 |
std::ostringstream buf_; |
449 |
std::ostringstream buf_; |
440 |
buf_ << "XFR " << trid << " SB\r\n"; |
450 |
buf_ << "XFR " << this->trID << " SB\r\n"; |
441 |
write(buf_); |
451 |
if (write(buf_) != buf_.str().size()) |
442 |
this->addCallback(&NotificationServerConnection::callback_TransferToSwitchboard, trid++, (void *)auth); |
452 |
return; |
|
|
453 |
|
454 |
this->addCallback(&NotificationServerConnection::callback_TransferToSwitchboard, this->trID++, (void *)auth); |
443 |
} |
455 |
} |
444 |
|
456 |
|
445 |
template <class _Tp> |
457 |
template <class _Tp> |
446 |
class _sameUserName |
458 |
class _sameUserName |
447 |
{ |
459 |
{ |
448 |
Buddy buddy; |
460 |
Buddy buddy; |
449 |
public: |
461 |
public: |
450 |
_sameUserName(const _Tp &__u) : buddy(__u) {}; |
462 |
_sameUserName(const _Tp &__u) : buddy(__u) {}; |
451 |
bool operator()(const _Tp &__x) { return __x.userName == buddy.userName; } |
463 |
bool operator()(const _Tp &__x) { return __x.userName == buddy.userName; } |
452 |
}; |
464 |
}; |
453 |
|
465 |
|
454 |
void NotificationServerConnection::checkReverseList(ListSyncInfo *info) |
466 |
void NotificationServerConnection::checkReverseList(ListSyncInfo *info) |
455 |
{ |
467 |
{ |
456 |
std::list<Buddy> & flist = info->reverseList; |
468 |
std::list<Buddy> & flist = info->reverseList; |
457 |
std::list<Buddy> & alist = info->allowList; |
469 |
std::list<Buddy> & alist = info->allowList; |
458 |
std::list<Buddy> & blist = info->blockList; |
470 |
std::list<Buddy> & blist = info->blockList; |
459 |
std::list<Buddy>::iterator flist_i; |
471 |
std::list<Buddy>::iterator flist_i; |
460 |
std::list<Buddy>::iterator alist_i; |
472 |
std::list<Buddy>::iterator alist_i; |
461 |
std::list<Buddy>::iterator blist_i; |
473 |
std::list<Buddy>::iterator blist_i; |
462 |
|
474 |
|
463 |
for (flist_i = flist.begin(); flist_i != flist.end(); flist_i++) |
475 |
for (flist_i = flist.begin(); flist_i != flist.end(); flist_i++) |
464 |
{ |
476 |
{ |
465 |
if (std::count_if(alist.begin(), alist.end(), _sameUserName<Buddy>(*flist_i)) == 0 && |
477 |
if (std::count_if(alist.begin(), alist.end(), _sameUserName<Buddy>(*flist_i)) == 0 && |
466 |
std::count_if(blist.begin(), blist.end(), _sameUserName<Buddy>(*flist_i)) == 0) |
478 |
std::count_if(blist.begin(), blist.end(), _sameUserName<Buddy>(*flist_i)) == 0) |
467 |
{ |
479 |
{ |
468 |
ext::gotNewReverseListEntry(this, (*flist_i).userName, (*flist_i).friendlyName); |
480 |
this->myNotificationServer()->externalCallbacks.gotNewReverseListEntry(this, (*flist_i).userName, (*flist_i).friendlyName); |
469 |
} |
481 |
} |
470 |
} |
482 |
} |
471 |
} |
483 |
} |
472 |
|
484 |
|
473 |
void NotificationServerConnection::socketConnectionCompleted() |
485 |
void NotificationServerConnection::socketConnectionCompleted() |
474 |
{ |
486 |
{ |
475 |
assert(connectionStatus == NS_CONNECTING); |
487 |
this->assertConnectionStateIs(NS_CONNECTING); |
476 |
Connection::socketConnectionCompleted(); |
488 |
this->setConnectionState(NS_CONNECTED); |
477 |
ext::unregisterSocket(this->sock); |
489 |
|
478 |
ext::registerSocket(this->sock, 1, 0); |
490 |
Connection::socketConnectionCompleted(); |
479 |
connectionStatus = NS_CONNECTED; |
491 |
|
|
|
492 |
// If an error occurs in Connection::socketConnectionCompleted, we |
493 |
// will be disconnected before we get here. |
494 |
if (this->connectionState() != NS_DISCONNECTED) |
495 |
{ |
496 |
this->myNotificationServer()->externalCallbacks.unregisterSocket(this->sock); |
497 |
this->myNotificationServer()->externalCallbacks.registerSocket(this->sock, 1, 0); |
498 |
} |
480 |
} |
499 |
} |
481 |
|
500 |
|
482 |
void NotificationServerConnection::connect(const std::string & hostname, unsigned int port) |
501 |
void NotificationServerConnection::connect(const std::string & hostname, unsigned int port) |
483 |
{ |
502 |
{ |
484 |
assert(connectionStatus == NS_DISCONNECTED); |
503 |
this->assertConnectionStateIs(NS_DISCONNECTED); |
485 |
connectinfo *info = new connectinfo(this->auth.username, this->auth.password); |
504 |
connectinfo *info = new connectinfo(this->auth.username, this->auth.password); |
486 |
|
505 |
|
487 |
if ((this->sock = ext::connectToServer(hostname, port, &this->connected)) == -1) |
506 |
if ((this->sock = this->myNotificationServer()->externalCallbacks.connectToServer(hostname, port, &this->connected)) == -1) |
488 |
{ |
507 |
{ |
489 |
ext::showError(this, "Could not connect to MSN server"); |
508 |
this->myNotificationServer()->externalCallbacks.showError(this, "Could not connect to MSN server"); |
490 |
ext::closingConnection(this); |
509 |
this->myNotificationServer()->externalCallbacks.closingConnection(this); |
491 |
return; |
510 |
return; |
492 |
} |
511 |
} |
493 |
|
512 |
this->setConnectionState(NS_CONNECTING); |
494 |
connectionStatus = NS_CONNECTING; |
513 |
this->myNotificationServer()->externalCallbacks.registerSocket(this->sock, 0, 1); |
495 |
ext::registerSocket(this->sock, 0, 1); |
514 |
if (this->connected) |
496 |
|
515 |
this->socketConnectionCompleted(); |
497 |
std::ostringstream buf_; |
516 |
|
498 |
buf_ << "VER " << trid << " MSNP8\r\n"; |
517 |
std::ostringstream buf_; |
499 |
this->write(buf_); |
518 |
buf_ << "VER " << this->trID << " MSNP8\r\n"; |
500 |
this->addCallback(&NotificationServerConnection::callback_NegotiateCVR, trid++, (void *)info); |
519 |
if (this->write(buf_) != buf_.str().size()) |
|
|
520 |
return; |
521 |
|
522 |
this->addCallback(&NotificationServerConnection::callback_NegotiateCVR, this->trID++, (void *)info); |
501 |
} |
523 |
} |
502 |
|
524 |
|
503 |
void NotificationServerConnection::connect(const std::string & hostname, unsigned int port, const Passport & username, const std::string & password) |
525 |
void NotificationServerConnection::connect(const std::string & hostname, unsigned int port, const Passport & username, const std::string & password) |
504 |
{ |
526 |
{ |
505 |
this->auth.username = username; |
527 |
this->auth.username = username; |
506 |
this->auth.password = password; |
528 |
this->auth.password = password; |
507 |
this->connect(hostname, port); |
529 |
this->connect(hostname, port); |
508 |
} |
530 |
} |
509 |
|
531 |
|
510 |
void NotificationServerConnection::disconnect() |
532 |
void NotificationServerConnection::disconnect() |
511 |
{ |
533 |
{ |
512 |
assert(connectionStatus != NS_DISCONNECTED); |
534 |
this->assertConnectionStateIsNot(NS_DISCONNECTED); |
513 |
ext::closingConnection(this); |
535 |
|
514 |
|
536 |
std::list<SwitchboardServerConnection *> list = _switchboardConnections; |
515 |
std::list<SwitchboardServerConnection *> list = _switchboardConnections; |
537 |
std::list<SwitchboardServerConnection *>::iterator i = list.begin(); |
516 |
std::list<SwitchboardServerConnection *>::iterator i = list.begin(); |
538 |
for (; i != list.end(); i++) |
517 |
for (; i != list.end(); i++) |
539 |
{ |
518 |
{ |
540 |
delete *i; |
519 |
delete *i; |
541 |
} |
520 |
} |
542 |
|
521 |
Connection::disconnect(); |
543 |
this->callbacks.clear(); |
522 |
connectionStatus = NS_DISCONNECTED; |
544 |
|
|
|
545 |
this->setConnectionState(NS_DISCONNECTED); |
546 |
this->myNotificationServer()->externalCallbacks.closingConnection(this); |
547 |
Connection::disconnect(); |
523 |
} |
548 |
} |
524 |
|
549 |
|
525 |
void NotificationServerConnection::disconnectForTransfer() |
550 |
void NotificationServerConnection::disconnectForTransfer() |
526 |
{ |
551 |
{ |
527 |
assert(connectionStatus != NS_DISCONNECTED); |
552 |
this->assertConnectionStateIsNot(NS_DISCONNECTED); |
528 |
ext::unregisterSocket(this->sock); |
553 |
this->myNotificationServer()->externalCallbacks.unregisterSocket(this->sock); |
529 |
::close(this->sock); |
554 |
::close(this->sock); |
530 |
connectionStatus = NS_DISCONNECTED; |
555 |
this->setConnectionState(NS_DISCONNECTED); |
531 |
} |
556 |
} |
532 |
|
557 |
|
533 |
void NotificationServerConnection::handleIncomingData() |
558 |
void NotificationServerConnection::handleIncomingData() |
534 |
{ |
559 |
{ |
535 |
assert(connectionStatus >= NS_CONNECTED); |
560 |
this->assertConnectionStateIsAtLeast(NS_CONNECTED); |
536 |
while (this->isWholeLineAvailable()) |
561 |
while (this->isWholeLineAvailable()) |
537 |
{ |
562 |
{ |
538 |
std::vector<std::string> args = this->getLine(); |
563 |
std::vector<std::string> args = this->getLine(); |
539 |
if (args[0] == "MSG" || args[0] == "NOT") |
564 |
if (args[0] == "MSG" || args[0] == "NOT" || args[0] == "IPG") |
540 |
{ |
565 |
{ |
541 |
int dataLength = decimalFromString(args[3]); |
566 |
int dataLength; |
542 |
if (this->readBuffer.find("\r\n") + 2 + dataLength > this->readBuffer.size()) |
567 |
if (args[0] == "MSG") |
543 |
return; |
568 |
dataLength = decimalFromString(args[3]); |
544 |
} |
569 |
else |
545 |
this->readBuffer = this->readBuffer.substr(this->readBuffer.find("\r\n") + 2); |
570 |
dataLength = decimalFromString(args[1]); |
546 |
int trid = 0; |
571 |
|
547 |
|
572 |
if (this->readBuffer.find("\r\n") + 2 + dataLength > this->readBuffer.size()) |
548 |
if (args.size() >= 6 && args[0] == "XFR" && args[2] == "NS") |
573 |
return; |
549 |
{ |
574 |
} |
550 |
// XFR TrID NS NotificationServerIP:Port 0 ThisServerIP:Port |
575 |
this->readBuffer = this->readBuffer.substr(this->readBuffer.find("\r\n") + 2); |
551 |
// 0 1 2 3 4 5 |
576 |
int trid = 0; |
552 |
this->callbacks.clear(); // delete the callback data |
577 |
|
553 |
|
578 |
if (args.size() >= 6 && args[0] == "XFR" && args[2] == "NS") |
554 |
this->disconnectForTransfer(); |
579 |
{ |
555 |
|
580 |
// XFR TrID NS NotificationServerIP:Port 0 ThisServerIP:Port |
556 |
std::pair<std::string, int> server_address = splitServerAddress(args[3]); |
581 |
// 0 1 2 3 4 5 |
557 |
this->connect(server_address.first, server_address.second); |
582 |
this->callbacks.clear(); // delete the callback data |
558 |
return; |
583 |
|
559 |
} |
584 |
this->disconnectForTransfer(); |
560 |
|
585 |
|
561 |
if (args.size() >= 7 && args[0] == "RNG") |
586 |
std::pair<std::string, int> server_address = splitServerAddress(args[3]); |
562 |
{ |
587 |
this->connect(server_address.first, server_address.second); |
563 |
// RNG SessionID SwitchboardServerIP:Port CKI AuthString InvitingUser InvitingDisplayName |
588 |
return; |
564 |
// 0 1 2 3 4 5 6 |
589 |
} |
565 |
this->handle_RNG(args); |
590 |
|
566 |
return; |
591 |
if (args.size() >= 7 && args[0] == "RNG") |
567 |
} |
592 |
{ |
568 |
|
593 |
// RNG SessionID SwitchboardServerIP:Port CKI AuthString InvitingUser InvitingDisplayName |
569 |
if (args.size() >= 1 && args[0] == "QNG") |
594 |
// 0 1 2 3 4 5 6 |
570 |
{ |
595 |
this->handle_RNG(args); |
571 |
// QNG |
596 |
return; |
572 |
// 0 |
597 |
} |
573 |
|
598 |
|
574 |
// ping response, ignore |
599 |
if (args.size() >= 1 && args[0] == "QNG") |
575 |
return; |
600 |
{ |
576 |
} |
601 |
// QNG |
577 |
|
602 |
// 0 |
578 |
if ((args.size() >= 4 && (args[0] == "LST" || args[0] == "LSG")) || |
603 |
|
579 |
(args.size() >= 2 && (args[0] == "GTC" || args[0] == "BLP")) || |
604 |
// ping response, ignore |
580 |
(args.size() >= 3 && args[0] == "BPR") |
605 |
return; |
581 |
) |
606 |
} |
582 |
{ |
607 |
|
583 |
// LST UserName FriendlyName UserLists [GroupNumbers] |
608 |
if ((args.size() >= 4 && (args[0] == "LST" || args[0] == "LSG")) || |
584 |
// 0 1 2 3 4 |
609 |
(args.size() >= 2 && (args[0] == "GTC" || args[0] == "BLP")) || |
585 |
// |
610 |
(args.size() >= 3 && args[0] == "BPR") |
586 |
// or |
611 |
) |
587 |
// (GTC|BLP) [TrID] [ListVersion] Setting |
612 |
{ |
588 |
// 0 1 2 4 |
613 |
// LST UserName FriendlyName UserLists [GroupNumbers] |
589 |
|
614 |
// 0 1 2 3 4 |
590 |
if (this->synctrid) |
615 |
// |
591 |
{ |
616 |
// or |
592 |
trid = this->synctrid; |
617 |
// (GTC|BLP) [TrID] [ListVersion] Setting |
593 |
} |
618 |
// 0 1 2 4 |
594 |
else |
619 |
|
595 |
{ |
620 |
if (this->synctrid) |
596 |
trid = decimalFromString(args[1]); |
621 |
{ |
597 |
} |
622 |
trid = this->synctrid; |
598 |
} |
623 |
} |
599 |
else if (args.size() > 1) |
624 |
else |
600 |
{ |
625 |
{ |
601 |
try |
626 |
trid = decimalFromString(args[1]); |
602 |
{ |
627 |
} |
603 |
trid = decimalFromString(args[1]); |
628 |
} |
604 |
} |
629 |
else if (args.size() > 1) |
605 |
catch (...) |
630 |
{ |
606 |
{ |
631 |
try |
607 |
} |
632 |
{ |
608 |
} |
633 |
trid = decimalFromString(args[1]); |
609 |
|
634 |
} |
610 |
if (!this->callbacks.empty() && trid > 0) |
635 |
catch (...) |
611 |
{ |
636 |
{ |
612 |
if (this->callbacks.find(trid) != this->callbacks.end()) |
637 |
} |
613 |
{ |
638 |
} |
614 |
(this->*(this->callbacks[trid].first))(args, trid, this->callbacks[trid].second); |
639 |
|
615 |
continue; |
640 |
if (!this->callbacks.empty() && trid >= 0) |
616 |
} |
641 |
{ |
617 |
} |
642 |
if (this->callbacks.find(trid) != this->callbacks.end()) |
618 |
|
643 |
{ |
619 |
if (isdigit(args[0][0])) |
644 |
(this->*(this->callbacks[trid].first))(args, trid, this->callbacks[trid].second); |
620 |
this->showError(decimalFromString(args[0])); |
645 |
continue; |
621 |
else |
646 |
} |
622 |
this->dispatchCommand(args); |
647 |
} |
623 |
} |
648 |
|
|
|
649 |
if (isdigit(args[0][0])) |
650 |
this->showError(decimalFromString(args[0])); |
651 |
else |
652 |
this->dispatchCommand(args); |
653 |
} |
624 |
} |
654 |
} |
625 |
|
655 |
|
626 |
void NotificationServerConnection::callback_SyncData(std::vector<std::string> & args, int trid, void *data) throw (std::runtime_error) |
656 |
void NotificationServerConnection::callback_SyncData(std::vector<std::string> & args, int trid, void *data) throw (std::runtime_error) |
627 |
{ |
657 |
{ |
628 |
assert(connectionStatus == NS_SYNCHRONISING); |
658 |
this->assertConnectionStateIs(NS_SYNCHRONISING); |
629 |
ListSyncInfo *info = static_cast<ListSyncInfo *>(data); |
659 |
ListSyncInfo *info = static_cast<ListSyncInfo *>(data); |
630 |
|
660 |
|
631 |
if (args[0] == "SYN") |
661 |
if (args[0] == "SYN") |
632 |
{ |
662 |
{ |
633 |
if (info->listVersion == decimalFromString(args[2])) |
663 |
if (info->listVersion == decimalFromString(args[2])) |
634 |
{ |
664 |
{ |
635 |
delete info; |
665 |
delete info; |
636 |
info = NULL; |
666 |
info = NULL; |
637 |
this->removeCallback(trid); |
667 |
this->removeCallback(trid); |
638 |
ext::gotBuddyListInfo(this, NULL); |
668 |
this->myNotificationServer()->externalCallbacks.gotBuddyListInfo(this, NULL); |
639 |
return; |
669 |
this->setConnectionState(NS_CONNECTED); |
640 |
} |
670 |
return; |
641 |
else |
671 |
} |
642 |
{ |
672 |
else |
643 |
info->listVersion = decimalFromString(args[2]); |
673 |
{ |
644 |
info->usersRemaining = decimalFromString(args[3]); |
674 |
info->listVersion = decimalFromString(args[2]); |
645 |
info->groupsRemaining = decimalFromString(args[4]); |
675 |
info->usersRemaining = decimalFromString(args[3]); |
646 |
ext::gotLatestListSerial(this, info->listVersion); |
676 |
info->groupsRemaining = decimalFromString(args[4]); |
647 |
} |
677 |
this->myNotificationServer()->externalCallbacks.gotLatestListSerial(this, info->listVersion); |
648 |
} |
678 |
} |
649 |
else if (args[0] == "LST") |
679 |
} |
650 |
{ |
680 |
else if (args[0] == "LST") |
651 |
int list = decimalFromString(args[3]); |
681 |
{ |
652 |
if ((list & ListSyncInfo::LST_FL) == ListSyncInfo::LST_FL) |
682 |
int list = decimalFromString(args[3]); |
653 |
{ |
683 |
if ((list & ListSyncInfo::LST_FL) == ListSyncInfo::LST_FL) |
654 |
info->forwardList.push_back(Buddy(args[1], decodeURL(args[2]))); |
684 |
{ |
655 |
std::vector<std::string> groups = splitString(args[4], ","); |
685 |
info->forwardList.push_back(Buddy(args[1], decodeURL(args[2]))); |
656 |
std::vector<std::string>::iterator i = groups.begin(); |
686 |
std::vector<std::string> groups = splitString(args[4], ","); |
657 |
for (; i != groups.end(); i++) |
687 |
std::vector<std::string>::iterator i = groups.begin(); |
658 |
{ |
688 |
for (; i != groups.end(); i++) |
659 |
int group = atoi(i->c_str()); |
689 |
{ |
660 |
info->groups[group].buddies.push_back(&(info->forwardList.back())); |
690 |
int group = atoi(i->c_str()); |
661 |
info->forwardList.back().groups.push_back(&info->groups[group]); |
691 |
info->groups[group].buddies.push_back(&(info->forwardList.back())); |
662 |
} |
692 |
info->forwardList.back().groups.push_back(&info->groups[group]); |
663 |
} |
693 |
} |
664 |
if ((list & ListSyncInfo::LST_RL) == ListSyncInfo::LST_RL) |
694 |
} |
665 |
{ |
695 |
if ((list & ListSyncInfo::LST_RL) == ListSyncInfo::LST_RL) |
666 |
info->reverseList.push_back(Buddy(args[1], decodeURL(args[2]))); |
696 |
{ |
667 |
} |
697 |
info->reverseList.push_back(Buddy(args[1], decodeURL(args[2]))); |
668 |
if ((list & ListSyncInfo::LST_AL) == ListSyncInfo::LST_AL) |
698 |
} |
669 |
{ |
699 |
if ((list & ListSyncInfo::LST_AL) == ListSyncInfo::LST_AL) |
670 |
info->allowList.push_back(Buddy(args[1], decodeURL(args[2]))); |
700 |
{ |
671 |
} |
701 |
info->allowList.push_back(Buddy(args[1], decodeURL(args[2]))); |
672 |
if ((list & ListSyncInfo::LST_BL) == ListSyncInfo::LST_BL) |
702 |
} |
673 |
{ |
703 |
if ((list & ListSyncInfo::LST_BL) == ListSyncInfo::LST_BL) |
674 |
info->blockList.push_back(Buddy(args[1], decodeURL(args[2]))); |
704 |
{ |
675 |
} |
705 |
info->blockList.push_back(Buddy(args[1], decodeURL(args[2]))); |
676 |
info->usersRemaining--; |
706 |
} |
677 |
if (info->usersRemaining == 0) |
707 |
info->usersRemaining--; |
678 |
{ |
708 |
if (info->usersRemaining == 0) |
679 |
info->progress |= ListSyncInfo::LST_FL | ListSyncInfo::LST_RL | ListSyncInfo::LST_AL | ListSyncInfo::LST_BL; |
709 |
{ |
680 |
} |
710 |
info->progress |= ListSyncInfo::LST_FL | ListSyncInfo::LST_RL | ListSyncInfo::LST_AL | ListSyncInfo::LST_BL; |
681 |
} |
711 |
} |
682 |
else if (args[0] == "GTC") |
712 |
} |
683 |
{ |
713 |
else if (args[0] == "GTC") |
684 |
info->reverseListPrompting = args[1][0]; |
714 |
{ |
685 |
info->progress |= ListSyncInfo::COMPLETE_GTC; |
715 |
info->reverseListPrompting = args[1][0]; |
686 |
ext::gotGTC(this, info->reverseListPrompting); |
716 |
info->progress |= ListSyncInfo::COMPLETE_GTC; |
687 |
} |
717 |
this->myNotificationServer()->externalCallbacks.gotGTC(this, info->reverseListPrompting); |
688 |
else if (args[0] == "BLP") |
718 |
} |
689 |
{ |
719 |
else if (args[0] == "BLP") |
690 |
info->privacySetting = args[1][0]; |
720 |
{ |
691 |
info->progress |= ListSyncInfo::COMPLETE_BLP; |
721 |
info->privacySetting = args[1][0]; |
692 |
ext::gotBLP(this, info->privacySetting); |
722 |
info->progress |= ListSyncInfo::COMPLETE_BLP; |
693 |
} |
723 |
this->myNotificationServer()->externalCallbacks.gotBLP(this, info->privacySetting); |
694 |
else if (args[0] == "LSG") |
724 |
} |
695 |
{ |
725 |
else if (args[0] == "LSG") |
696 |
int groupID = decimalFromString(args[1]); |
726 |
{ |
697 |
Group g(groupID, decodeURL(args[2])); |
727 |
int groupID = decimalFromString(args[1]); |
698 |
info->groups[groupID] = g; |
728 |
Group g(groupID, decodeURL(args[2])); |
699 |
} |
729 |
info->groups[groupID] = g; |
700 |
else if (args[0] == "BPR") |
730 |
} |
701 |
{ |
731 |
else if (args[0] == "BPR") |
702 |
bool enabled; |
732 |
{ |
703 |
if (decodeURL(args[2])[0] == 'Y') |
733 |
bool enabled; |
704 |
enabled = true; |
734 |
if (decodeURL(args[2])[0] == 'Y') |
705 |
else |
735 |
enabled = true; |
706 |
enabled = false; |
736 |
else |
707 |
info->forwardList.back().phoneNumbers.push_back(Buddy::PhoneNumber(args[1], |
737 |
enabled = false; |
708 |
decodeURL(args[2]), |
738 |
info->forwardList.back().phoneNumbers.push_back(Buddy::PhoneNumber(args[1], |
709 |
enabled)); |
739 |
decodeURL(args[2]), |
710 |
} |
740 |
enabled)); |
711 |
else |
741 |
} |
712 |
throw std::runtime_error("Unexpected sync data"); |
742 |
else |
713 |
|
743 |
throw std::runtime_error("Unexpected sync data"); |
714 |
if (info->progress == (ListSyncInfo::LST_FL | ListSyncInfo::LST_RL | |
744 |
|
715 |
ListSyncInfo::LST_AL | ListSyncInfo::LST_BL | |
745 |
if (info->progress == (ListSyncInfo::LST_FL | ListSyncInfo::LST_RL | |
716 |
ListSyncInfo::COMPLETE_BLP | ListSyncInfo::COMPLETE_GTC)) |
746 |
ListSyncInfo::LST_AL | ListSyncInfo::LST_BL | |
717 |
{ |
747 |
ListSyncInfo::COMPLETE_BLP | ListSyncInfo::COMPLETE_GTC)) |
718 |
this->removeCallback(trid); |
748 |
{ |
719 |
this->checkReverseList(info); |
749 |
this->removeCallback(trid); |
720 |
ext::gotBuddyListInfo(this, info); |
750 |
this->checkReverseList(info); |
721 |
this->synctrid = 0; |
751 |
this->myNotificationServer()->externalCallbacks.gotBuddyListInfo(this, info); |
722 |
delete info; |
752 |
this->synctrid = 0; |
723 |
connectionStatus = NS_CONNECTED; |
753 |
delete info; |
724 |
} |
754 |
this->setConnectionState(NS_CONNECTED); |
725 |
else if (info->progress > 63 || info->progress < 0) |
755 |
} |
726 |
throw std::runtime_error("Corrupt sync progress!"); |
756 |
else if (info->progress > 63 || info->progress < 0) |
|
|
757 |
throw std::runtime_error("Corrupt sync progress!"); |
727 |
} |
758 |
} |
728 |
|
759 |
|
729 |
|
760 |
|
730 |
void NotificationServerConnection::callback_NegotiateCVR(std::vector<std::string> & args, int trid, void *data) |
761 |
void NotificationServerConnection::callback_NegotiateCVR(std::vector<std::string> & args, int trid, void *data) |
731 |
{ |
762 |
{ |
732 |
assert(connectionStatus >= NS_CONNECTED); |
763 |
this->assertConnectionStateIsAtLeast(NS_CONNECTED); |
733 |
connectinfo * info = (connectinfo *) data; |
764 |
connectinfo * info = (connectinfo *) data; |
734 |
this->removeCallback(trid); |
765 |
this->removeCallback(trid); |
735 |
|
766 |
|
736 |
if (args.size() >= 3) |
767 |
if (args.size() >= 3 && args[0] != "VER" || args[2] != "MSNP8") // if either *differs*... |
737 |
if (args[0] != "VER" || args[2] != "MSNP8") // if either *differs*... |
768 |
{ |
738 |
{ |
769 |
this->myNotificationServer()->externalCallbacks.showError(NULL, "Protocol negotiation failed"); |
739 |
ext::showError(NULL, "Protocol negotiation failed"); |
770 |
delete info; |
740 |
delete info; |
771 |
this->disconnect(); |
741 |
this->disconnect(); |
772 |
return; |
742 |
return; |
773 |
} |
743 |
} |
774 |
|
744 |
|
775 |
std::ostringstream buf_; |
745 |
std::ostringstream buf_; |
776 |
buf_ << "CVR " << this->trID << " 0x0409 winnt 5.2 i386 MSNMSGR 6.0.0250 MSMSGS " << info->username << "\r\n"; |
746 |
buf_ << "CVR " << trid << " 0x0409 winnt 5.2 i386 MSNMSGR 6.0.0250 MSMSGS " << info->username << "\r\n"; |
777 |
if (this->write(buf_) != buf_.str().size()) |
747 |
this->write(buf_); |
778 |
return; |
748 |
this->addCallback(&NotificationServerConnection::callback_RequestUSR, trid++, (void *) data); |
779 |
this->addCallback(&NotificationServerConnection::callback_RequestUSR, this->trID++, (void *) data); |
749 |
} |
780 |
} |
750 |
|
781 |
|
751 |
void NotificationServerConnection::callback_TransferToSwitchboard(std::vector<std::string> & args, int trid, void *data) |
782 |
void NotificationServerConnection::callback_TransferToSwitchboard(std::vector<std::string> & args, int trid, void *data) |
752 |
{ |
783 |
{ |
753 |
assert(connectionStatus >= NS_CONNECTED); |
784 |
this->assertConnectionStateIsAtLeast(NS_CONNECTED); |
754 |
SwitchboardServerConnection::AuthData *auth = static_cast<SwitchboardServerConnection::AuthData *>(data); |
785 |
SwitchboardServerConnection::AuthData *auth = static_cast<SwitchboardServerConnection::AuthData *>(data); |
755 |
this->removeCallback(trid); |
786 |
this->removeCallback(trid); |
756 |
|
787 |
|
757 |
if (args[0] != "XFR") |
788 |
if (args[0] != "XFR") |
758 |
{ |
789 |
{ |
759 |
this->showError(decimalFromString(args[0])); |
790 |
this->showError(decimalFromString(args[0])); |
760 |
this->disconnect(); |
791 |
this->disconnect(); |
761 |
delete auth; |
792 |
delete auth; |
762 |
return; |
793 |
return; |
763 |
} |
794 |
} |
764 |
|
795 |
|
765 |
auth->cookie = args[5]; |
796 |
auth->cookie = args[5]; |
766 |
auth->sessionID = ""; |
797 |
auth->sessionID = ""; |
767 |
|
798 |
|
768 |
SwitchboardServerConnection *newconn = new SwitchboardServerConnection(*auth, *this); |
799 |
SwitchboardServerConnection *newconn = new SwitchboardServerConnection(*auth, *this); |
769 |
|
800 |
|
770 |
this->addSwitchboardConnection(newconn); |
801 |
this->addSwitchboardConnection(newconn); |
771 |
std::pair<std::string, int> server_address = splitServerAddress(args[3]); |
802 |
std::pair<std::string, int> server_address = splitServerAddress(args[3]); |
772 |
newconn->connect(server_address.first, server_address.second); |
803 |
newconn->connect(server_address.first, server_address.second); |
773 |
|
804 |
|
774 |
delete auth; |
805 |
delete auth; |
775 |
} |
806 |
} |
776 |
|
807 |
|
777 |
void NotificationServerConnection::callback_RequestUSR(std::vector<std::string> & args, int trid, void *data) |
808 |
void NotificationServerConnection::callback_RequestUSR(std::vector<std::string> & args, int trid, void *data) |
778 |
{ |
809 |
{ |
779 |
assert(connectionStatus >= NS_CONNECTED); |
810 |
this->assertConnectionStateIsAtLeast(NS_CONNECTED); |
780 |
connectinfo *info = (connectinfo *)data; |
811 |
connectinfo *info = (connectinfo *)data; |
781 |
this->removeCallback(trid); |
812 |
this->removeCallback(trid); |
782 |
|
813 |
|
783 |
if (args.size() > 1 && args[0] != "CVR") // if*differs*... |
814 |
if (args.size() > 1 && args[0] != "CVR") // if*differs*... |
784 |
{ |
815 |
{ |
785 |
ext::showError(NULL, "Protocol negotiation failed"); |
816 |
this->myNotificationServer()->externalCallbacks.showError(NULL, "Protocol negotiation failed"); |
786 |
delete info; |
817 |
delete info; |
787 |
this->disconnect(); |
818 |
this->disconnect(); |
788 |
return; |
819 |
return; |
789 |
} |
820 |
} |
790 |
|
821 |
|
791 |
std::ostringstream buf_; |
822 |
std::ostringstream buf_; |
792 |
buf_ << "USR " << trid << " TWN I " << info->username << "\r\n"; |
823 |
buf_ << "USR " << this->trID << " TWN I " << info->username << "\r\n"; |
793 |
this->write(buf_); |
824 |
if (this->write(buf_) != buf_.str().size()) |
794 |
|
825 |
return; |
795 |
this->addCallback(&NotificationServerConnection::callback_PassportAuthentication, trid++, (void *) data); |
826 |
|
|
|
827 |
this->addCallback(&NotificationServerConnection::callback_PassportAuthentication, this->trID++, (void *) data); |
796 |
} |
828 |
} |
797 |
|
829 |
|
798 |
void NotificationServerConnection::callback_PassportAuthentication(std::vector<std::string> & args, int trid, void * data) |
830 |
void NotificationServerConnection::callback_PassportAuthentication(std::vector<std::string> & args, int trid, void * data) |
799 |
{ |
831 |
{ |
800 |
assert(connectionStatus >= NS_CONNECTED); |
832 |
this->assertConnectionStateIsAtLeast(NS_CONNECTED); |
801 |
connectinfo * info; |
833 |
connectinfo * info; |
802 |
|
834 |
|
803 |
CURL *curl; |
835 |
CURL *curl; |
804 |
CURLcode ret; |
836 |
CURLcode ret; |
805 |
curl_slist *slist = NULL; |
837 |
curl_slist *slist = NULL; |
806 |
std::string auth; |
838 |
std::string auth; |
807 |
char *uname, *pword; |
839 |
char *uname, *pword; |
808 |
std::string proxy; |
840 |
std::string proxy; |
809 |
|
841 |
|
810 |
info=(connectinfo *)data; |
842 |
info=(connectinfo *)data; |
811 |
this->removeCallback(trid); |
843 |
this->removeCallback(trid); |
812 |
|
844 |
|
813 |
if (isdigit(args[0][0])) |
845 |
if (isdigit(args[0][0])) |
814 |
{ |
846 |
{ |
815 |
this->showError(decimalFromString(args[0])); |
847 |
this->showError(decimalFromString(args[0])); |
816 |
delete info; |
848 |
delete info; |
817 |
this->disconnect(); |
849 |
this->disconnect(); |
818 |
return; |
850 |
return; |
819 |
} |
851 |
} |
820 |
|
852 |
|
821 |
if (args.size() >= 4 && args[4].empty()) { |
853 |
if (args.size() >= 4 && args[4].empty()) { |
822 |
this->disconnect(); |
854 |
this->disconnect(); |
823 |
delete info; |
855 |
delete info; |
824 |
return; |
856 |
return; |
825 |
} |
857 |
} |
826 |
|
858 |
|
827 |
/* Now to fire off some HTTPS login */ |
859 |
/* Now to fire off some HTTPS login */ |
828 |
/* args[4] contains the most interesting part we need to send on */ |
860 |
/* args[4] contains the most interesting part we need to send on */ |
829 |
curl = curl_easy_init(); |
861 |
curl = curl_easy_init(); |
830 |
if (curl == NULL) { |
862 |
if (curl == NULL) { |
831 |
this->disconnect(); |
863 |
this->disconnect(); |
832 |
delete info; |
864 |
delete info; |
833 |
return; |
865 |
return; |
834 |
} |
866 |
} |
835 |
|
867 |
|
836 |
proxy = ext::getSecureHTTPProxy(); |
868 |
proxy = this->myNotificationServer()->externalCallbacks.getSecureHTTPProxy(); |
837 |
if (! proxy.empty()) |
869 |
if (! proxy.empty()) |
838 |
ret = curl_easy_setopt(curl, CURLOPT_PROXY, proxy.c_str()); |
870 |
ret = curl_easy_setopt(curl, CURLOPT_PROXY, proxy.c_str()); |
839 |
else |
871 |
else |
840 |
ret = CURLE_OK; |
872 |
ret = CURLE_OK; |
841 |
|
873 |
|
842 |
if (ret == CURLE_OK) |
874 |
if (ret == CURLE_OK) |
843 |
ret = curl_easy_setopt(curl, CURLOPT_URL, "https://login.passport.com/login2.srf"); |
875 |
ret = curl_easy_setopt(curl, CURLOPT_URL, "https://login.passport.com/login2.srf"); |
844 |
|
876 |
|
845 |
uname = curl_escape(const_cast<char *>(info->username.c_str()), 0); |
877 |
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0); |
846 |
pword = curl_escape(const_cast<char *>(info->password.c_str()), 0); |
878 |
uname = curl_escape(const_cast<char *>(info->username.c_str()), 0); |
847 |
auth = std::string("Authorization: Passport1.4 OrgVerb=GET,OrgURL=http%3A%2F%2Fmessenger%2Emsn%2Ecom,sign-in=") + uname + ",pwd=" + pword + ","+ args[4]; |
879 |
pword = curl_escape(const_cast<char *>(info->password.c_str()), 0); |
848 |
free(uname); |
880 |
auth = std::string("Authorization: Passport1.4 OrgVerb=GET,OrgURL=http%3A%2F%2Fmessenger%2Emsn%2Ecom,sign-in=") + uname + ",pwd=" + pword + ","+ args[4]; |
849 |
free(pword); |
881 |
curl_free(uname); |
850 |
slist = curl_slist_append(slist, auth.c_str()); |
882 |
curl_free(pword); |
851 |
|
883 |
slist = curl_slist_append(slist, auth.c_str()); |
852 |
if (ret == CURLE_OK) |
884 |
|
853 |
ret = curl_easy_setopt(curl, CURLOPT_HTTPHEADER, slist); |
885 |
if (ret == CURLE_OK) |
854 |
if (ret == CURLE_OK) |
886 |
ret = curl_easy_setopt(curl, CURLOPT_HTTPHEADER, slist); |
855 |
ret = curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1); |
887 |
if (ret == CURLE_OK) |
856 |
if (ret == CURLE_OK) |
888 |
ret = curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1); |
857 |
ret = curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 1); |
889 |
if (ret == CURLE_OK) |
858 |
/*if (ret == CURLE_OK) |
890 |
ret = curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 1); |
859 |
ret = curl_easy_setopt(curl, CURLOPT_UNRESTRICTED_AUTH, 1);*/ |
891 |
/*if (ret == CURLE_OK) |
860 |
/* if (ret == CURLE_OK) |
892 |
ret = curl_easy_setopt(curl, CURLOPT_UNRESTRICTED_AUTH, 1);*/ |
861 |
ret = curl_easy_setopt(curl, CURLOPT_USERAGENT, "msnlib/1.0 (Proteus)");*/ |
893 |
/* if (ret == CURLE_OK) |
862 |
if (ret == CURLE_OK) |
894 |
ret = curl_easy_setopt(curl, CURLOPT_USERAGENT, "msnlib/1.0 (Proteus)");*/ |
863 |
ret = curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &msn_handle_curl_write); |
895 |
if (ret == CURLE_OK) |
864 |
/*if (ret == CURLE_OK) |
896 |
ret = curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &msn_handle_curl_write); |
865 |
ret = curl_easy_setopt(curl, CURLOPT_WRITEDATA, info);*/ |
897 |
/*if (ret == CURLE_OK) |
866 |
if (ret == CURLE_OK) |
898 |
ret = curl_easy_setopt(curl, CURLOPT_WRITEDATA, info);*/ |
867 |
ret = curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, &msn_handle_curl_header); |
899 |
if (ret == CURLE_OK) |
868 |
if (ret == CURLE_OK) |
900 |
ret = curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, &msn_handle_curl_header); |
869 |
ret = curl_easy_setopt(curl, CURLOPT_WRITEHEADER, info); |
901 |
if (ret == CURLE_OK) |
870 |
|
902 |
ret = curl_easy_setopt(curl, CURLOPT_WRITEHEADER, info); |
871 |
if (ret == CURLE_OK) |
903 |
|
872 |
ret = curl_easy_perform(curl); |
904 |
if (ret == CURLE_OK) |
873 |
|
905 |
ret = curl_easy_perform(curl); |
874 |
curl_easy_cleanup(curl); |
906 |
|
875 |
curl_slist_free_all(slist); |
907 |
curl_easy_cleanup(curl); |
876 |
|
908 |
curl_slist_free_all(slist); |
877 |
/* ok, if auth succeeded info->cookie is now the cookie to pass back */ |
909 |
|
878 |
if (info->cookie.empty()) |
910 |
/* ok, if auth succeeded info->cookie is now the cookie to pass back */ |
879 |
{ |
911 |
if (info->cookie.empty()) |
880 |
// No authentication cookie /usually/ means that authentication failed. |
912 |
{ |
881 |
this->showError(911); |
913 |
// No authentication cookie /usually/ means that authentication failed. |
882 |
|
914 |
this->showError(911); |
883 |
this->disconnect(); |
915 |
|
884 |
delete info; |
916 |
this->disconnect(); |
885 |
return; |
917 |
delete info; |
886 |
} |
918 |
return; |
887 |
|
919 |
} |
888 |
std::ostringstream buf_; |
920 |
|
889 |
buf_ << "USR " << trid << " TWN S " << info->cookie << "\r\n"; |
921 |
std::ostringstream buf_; |
890 |
this->write(buf_); |
922 |
buf_ << "USR " << this->trID << " TWN S " << info->cookie << "\r\n"; |
891 |
this->addCallback(&NotificationServerConnection::callback_AuthenticationComplete, trid++, (void *) data); |
923 |
if (this->write(buf_) != buf_.str().size()) |
|
|
924 |
return; |
925 |
this->addCallback(&NotificationServerConnection::callback_AuthenticationComplete, this->trID++, (void *) data); |
892 |
} |
926 |
} |
893 |
|
927 |
|
894 |
void NotificationServerConnection::callback_AuthenticationComplete(std::vector<std::string> & args, int trid, void * data) |
928 |
void NotificationServerConnection::callback_AuthenticationComplete(std::vector<std::string> & args, int trid, void * data) |
895 |
{ |
929 |
{ |
896 |
assert(connectionStatus >= NS_CONNECTED); |
930 |
this->assertConnectionStateIsAtLeast(NS_CONNECTED); |
897 |
connectinfo * info = (connectinfo *) data; |
931 |
connectinfo * info = (connectinfo *) data; |
898 |
this->removeCallback(trid); |
932 |
this->removeCallback(trid); |
899 |
|
933 |
|
900 |
if (isdigit(args[0][0])) |
934 |
if (isdigit(args[0][0])) |
901 |
{ |
935 |
{ |
902 |
this->showError(decimalFromString(args[0])); |
936 |
this->showError(decimalFromString(args[0])); |
903 |
delete info; |
937 |
delete info; |
904 |
this->disconnect(); |
938 |
this->disconnect(); |
905 |
return; |
939 |
return; |
906 |
} |
940 |
} |
907 |
|
941 |
|
908 |
ext::gotFriendlyName(this, decodeURL(args[4])); |
942 |
this->myNotificationServer()->externalCallbacks.gotFriendlyName(this, decodeURL(args[4])); |
909 |
|
943 |
|
910 |
delete info; |
944 |
delete info; |
911 |
|
945 |
|
912 |
trid++; |
946 |
this->myNotificationServer()->externalCallbacks.gotNewConnection(this); |
913 |
|
|
|
914 |
ext::gotNewConnection(this); |
915 |
} |
947 |
} |
916 |
|
948 |
|
917 |
|
949 |
|
918 |
static size_t msn_handle_curl_write(void *ptr, size_t size, size_t nmemb, void *stream) { |
950 |
static size_t msn_handle_curl_write(void *ptr, size_t size, size_t nmemb, void *stream) { |
919 |
return size * nmemb; |
951 |
return size * nmemb; |
920 |
} |
952 |
} |
921 |
|
953 |
|
922 |
static size_t msn_handle_curl_header(void *ptr, size_t size, size_t nmemb, void *stream) |
954 |
static size_t msn_handle_curl_header(void *ptr, size_t size, size_t nmemb, void *stream) |
923 |
{ |
955 |
{ |
924 |
connectinfo * info; |
956 |
connectinfo * info; |
925 |
std::string cookiedata; |
957 |
std::string cookiedata; |
926 |
|
958 |
|
927 |
info = (connectinfo *)stream; |
959 |
info = (connectinfo *)stream; |
928 |
|
960 |
|
929 |
if ((size * nmemb) < strlen("Authentication-Info:")) |
961 |
if ((size * nmemb) < strlen("Authentication-Info:")) |
930 |
return (size * nmemb); |
962 |
return (size * nmemb); |
931 |
|
963 |
|
932 |
std::string headers_ = std::string((char *)ptr, size * nmemb); |
964 |
std::string headers_ = std::string((char *)ptr, size * nmemb); |
933 |
Message::Headers headers = Message::Headers(headers_); |
965 |
Message::Headers headers = Message::Headers(headers_); |
934 |
cookiedata = headers["Authentication-Info:"]; |
966 |
cookiedata = headers["Authentication-Info:"]; |
935 |
|
967 |
|
936 |
if (! cookiedata.empty()) |
968 |
if (! cookiedata.empty()) |
937 |
{ |
969 |
{ |
938 |
size_t pos = cookiedata.find(",from-PP='"); |
970 |
size_t pos = cookiedata.find(",from-PP='"); |
939 |
if (pos == std::string::npos) { |
971 |
if (pos == std::string::npos) { |
940 |
info->cookie = ""; |
972 |
info->cookie = ""; |
941 |
} else { |
973 |
} else { |
942 |
info->cookie = cookiedata.substr(pos + strlen(",from-PP='")); |
974 |
info->cookie = cookiedata.substr(pos + strlen(",from-PP='")); |
943 |
pos = info->cookie.find("'"); |
975 |
pos = info->cookie.find("'"); |
944 |
if (pos != std::string::npos) |
976 |
if (pos != std::string::npos) |
945 |
info->cookie = info->cookie.substr(0, pos); |
977 |
info->cookie = info->cookie.substr(0, pos); |
946 |
} |
978 |
} |
947 |
} |
979 |
} |
948 |
|
980 |
|
949 |
return (size * nmemb); |
981 |
return (size * nmemb); |
950 |
} |
982 |
} |
951 |
} |
983 |
} |