Mercurial > pidgin
annotate src/protocols/msn/nexus.c @ 8808:bbd8cdaf0ad5
[gaim-migrate @ 9570]
A massive patch by shx to reorganize MSN some more and add command
processor support. This allows us to do cool things like produce more
detailed error messages. For example, the Invalid Username dialog now
shows the username of the invalid user.
I modified the aforementioned dialog so it'll look a little nicer looking,
and also mention the account this happened on. It also removes the user
from your blist, as there's no point to keeping the user on there.
committer: Tailor Script <tailor@pidgin.im>
| author | Christian Hammond <chipx86@chipx86.com> |
|---|---|
| date | Sun, 25 Apr 2004 22:02:06 +0000 |
| parents | d0ba2f7b40e7 |
| children | 577c76e1442d |
| rev | line source |
|---|---|
| 8171 | 1 #include "msn.h" |
| 2 #include "nexus.h" | |
| 3 #include "notification.h" | |
| 4 | |
| 5 /************************************************************************** | |
| 6 * Util | |
| 7 **************************************************************************/ | |
| 8 | |
| 9 static size_t | |
| 10 msn_ssl_read(GaimSslConnection *gsc, char **dest_buffer) | |
| 11 { | |
| 12 size_t size = 0, s; | |
| 13 char *buffer = NULL; | |
| 14 char temp_buf[4096]; | |
| 15 | |
| 16 while ((s = gaim_ssl_read(gsc, temp_buf, sizeof(temp_buf))) > 0) | |
| 17 { | |
| 18 buffer = g_realloc(buffer, size + s + 1); | |
| 19 | |
| 20 strncpy(buffer + size, temp_buf, s); | |
| 21 | |
| 22 buffer[size + s] = '\0'; | |
| 23 | |
| 24 size += s; | |
| 25 } | |
| 26 | |
| 27 *dest_buffer = buffer; | |
| 28 | |
| 29 return size; | |
| 30 } | |
| 31 | |
| 32 /************************************************************************** | |
| 33 * Login | |
| 34 **************************************************************************/ | |
| 35 | |
| 36 static void | |
| 37 login_error_cb(GaimSslConnection *gsc, GaimSslErrorType error, void *data) | |
| 38 { | |
| 39 MsnNexus *nexus; | |
| 40 MsnSession *session; | |
| 41 GaimAccount *account; | |
| 42 GaimConnection *gc; | |
| 43 | |
| 44 nexus = data; | |
| 45 g_return_if_fail(nexus != NULL); | |
| 46 | |
| 47 session = nexus->session; | |
| 48 g_return_if_fail(session != NULL); | |
| 49 | |
| 50 account = session->account; | |
| 51 g_return_if_fail(account != NULL); | |
| 52 | |
| 53 gc = gaim_account_get_connection(account); | |
| 54 g_return_if_fail(gc != NULL); | |
| 55 | |
| 56 gaim_connection_error(gc, _("Unable to connect to server")); | |
| 57 | |
| 58 msn_nexus_destroy(nexus); | |
| 59 session->nexus = NULL; | |
| 60 } | |
| 61 | |
| 62 static void | |
| 63 login_connect_cb(gpointer data, GaimSslConnection *gsc, | |
| 64 GaimInputCondition cond) | |
| 65 { | |
| 66 MsnNexus *nexus; | |
| 67 MsnSession *session; | |
| 68 GaimConnection *gc; | |
| 69 char *username, *password; | |
| 70 char *request_str; | |
| 71 char *buffer = NULL; | |
| 72 size_t s; | |
| 73 | |
| 74 nexus = data; | |
| 75 g_return_if_fail(nexus != NULL); | |
| 76 | |
| 77 session = nexus->session; | |
| 78 g_return_if_fail(session != NULL); | |
| 79 | |
| 80 gc = gaim_account_get_connection(session->account); | |
| 81 g_return_if_fail(gc != NULL); | |
| 82 | |
| 83 username = | |
| 84 g_strdup(gaim_url_encode(gaim_account_get_username(session->account))); | |
| 85 | |
| 86 password = | |
| 87 g_strdup(gaim_url_encode(gaim_account_get_password(session->account))); | |
| 88 | |
| 89 request_str = g_strdup_printf( | |
| 90 "GET %s HTTP/1.1\r\n" | |
| 91 "Authorization: Passport1.4 OrgVerb=GET,OrgURL=%s,sign-in=%s,pwd=%s," | |
| 92 "lc=%s,id=%s,tw=%s,fs=%s,ru=%s,ct=%s,kpp=%s,kv=%s,ver=%s,tpf=%s\r\n" | |
| 93 "User-Agent: MSMSGS\r\n" | |
| 94 "Host: %s\r\n" | |
| 95 "Connection: Keep-Alive\r\n" | |
| 96 "Cache-Control: no-cache\r\n" | |
| 97 "\r\n", | |
| 98 nexus->login_path, | |
| 99 (char *)g_hash_table_lookup(nexus->challenge_data, "ru"), | |
| 100 username, password, | |
| 101 (char *)g_hash_table_lookup(nexus->challenge_data, "lc"), | |
| 102 (char *)g_hash_table_lookup(nexus->challenge_data, "id"), | |
| 103 (char *)g_hash_table_lookup(nexus->challenge_data, "tw"), | |
| 104 (char *)g_hash_table_lookup(nexus->challenge_data, "fs"), | |
| 105 (char *)g_hash_table_lookup(nexus->challenge_data, "ru"), | |
| 106 (char *)g_hash_table_lookup(nexus->challenge_data, "ct"), | |
| 107 (char *)g_hash_table_lookup(nexus->challenge_data, "kpp"), | |
| 108 (char *)g_hash_table_lookup(nexus->challenge_data, "kv"), | |
| 109 (char *)g_hash_table_lookup(nexus->challenge_data, "ver"), | |
| 110 (char *)g_hash_table_lookup(nexus->challenge_data, "tpf"), | |
| 111 nexus->login_host); | |
| 112 | |
| 113 gaim_debug(GAIM_DEBUG_MISC, "msn", "Sending: {%s}\n", request_str); | |
| 114 | |
| 115 g_free(username); | |
| 116 g_free(password); | |
| 117 | |
| 118 if ((s = gaim_ssl_write(gsc, request_str, strlen(request_str))) <= 0) | |
| 119 { | |
| 120 g_free(request_str); | |
| 121 gaim_connection_error(gc, _("Unable to write to MSN Nexus server.")); | |
| 122 | |
| 123 return; | |
| 124 } | |
| 125 | |
| 126 g_free(request_str); | |
| 127 | |
| 128 if ((s = msn_ssl_read(gsc, &buffer)) <= 0) | |
| 129 { | |
| 130 gaim_connection_error(gc, _("Unable to write to MSN Nexus server.")); | |
| 131 return; | |
| 132 } | |
| 133 | |
| 134 gaim_ssl_close(gsc); | |
| 135 | |
| 136 gaim_debug(GAIM_DEBUG_MISC, "msn", "ssl buffer: {%s}", buffer); | |
| 137 | |
| 138 if (strstr(buffer, "HTTP/1.1 302") != NULL) | |
| 139 { | |
| 140 /* Redirect. */ | |
| 141 char *location, *c; | |
| 142 | |
| 143 location = strstr(buffer, "Location: "); | |
| 144 if (location == NULL) | |
| 145 { | |
| 146 gaim_connection_error(gc, | |
| 147 _("MSN Nexus server returned invalid redirect information.")); | |
| 148 | |
| 149 g_free(buffer); | |
| 150 | |
| 151 return; | |
| 152 } | |
| 153 | |
| 154 location = strchr(location, ' ') + 1; | |
| 155 | |
| 156 if ((c = strchr(location, '\r')) != NULL) | |
| 157 *c = '\0'; | |
| 158 | |
| 159 /* Skip the http:// */ | |
| 160 if ((c = strchr(location, '/')) != NULL) | |
| 161 location = c + 2; | |
| 162 | |
| 163 if ((c = strchr(location, '/')) != NULL) | |
| 164 { | |
| 165 g_free(nexus->login_path); | |
| 166 nexus->login_path = g_strdup(c); | |
| 167 | |
| 168 *c = '\0'; | |
| 169 } | |
| 170 | |
| 171 g_free(nexus->login_host); | |
| 172 nexus->login_host = g_strdup(location); | |
| 173 | |
| 174 gaim_ssl_connect(session->account, nexus->login_host, | |
| 175 GAIM_SSL_DEFAULT_PORT, login_connect_cb, | |
| 176 login_error_cb, nexus); | |
| 177 } | |
| 178 else if (strstr(buffer, "HTTP/1.1 401 Unauthorized") != NULL) | |
| 179 { | |
| 180 GaimConnection *gc; | |
| 181 const char *error, *c; | |
| 182 char *temp; | |
| 183 | |
| 184 if ((error = strstr(buffer, "WWW-Authenticate")) != NULL) | |
| 185 { | |
| 186 if ((error = strstr(error, "cbtxt=")) != NULL) | |
| 187 { | |
| 188 error += strlen("cbtxt="); | |
| 189 | |
| 190 if ((c = strchr(error, '\n')) == NULL) | |
| 191 c = error + strlen(error); | |
| 192 | |
| 193 temp = g_strndup(error, c - error); | |
| 194 error = gaim_url_decode(temp); | |
| 195 g_free(temp); | |
| 196 } | |
| 197 } | |
| 198 | |
| 199 gc = gaim_account_get_connection(session->account); | |
| 200 | |
| 201 if (error == NULL) | |
| 202 { | |
| 203 gaim_connection_error(gc, | |
| 204 _("Unknown error when attempting to authorize with " | |
| 205 "MSN login server.")); | |
| 206 } | |
| 207 else | |
| 208 gaim_connection_error(gc, error); | |
| 209 } | |
| 210 else if (strstr(buffer, "HTTP/1.1 200 OK")) | |
| 211 { | |
|
8808
bbd8cdaf0ad5
[gaim-migrate @ 9570]
Christian Hammond <chipx86@chipx86.com>
parents:
8171
diff
changeset
|
212 MsnCmdProc *cmdproc; |
| 8171 | 213 char *base, *c; |
| 214 char *login_params; | |
| 215 | |
| 216 #if 0 | |
| 217 /* All your base are belong to us. */ | |
| 218 base = buffer; | |
| 219 | |
| 220 /* For great cookie! */ | |
| 221 while ((base = strstr(base, "Set-Cookie: ")) != NULL) | |
| 222 { | |
| 223 base += strlen("Set-Cookie: "); | |
| 224 | |
| 225 c = strchr(base, ';'); | |
| 226 | |
| 227 session->login_cookies = | |
| 228 g_list_append(session->login_cookies, | |
| 229 g_strndup(base, c - base)); | |
| 230 } | |
| 231 #endif | |
| 232 | |
|
8808
bbd8cdaf0ad5
[gaim-migrate @ 9570]
Christian Hammond <chipx86@chipx86.com>
parents:
8171
diff
changeset
|
233 cmdproc = session->notification_conn->cmdproc; |
| 8171 | 234 base = strstr(buffer, "Authentication-Info: "); |
| 235 | |
|
8808
bbd8cdaf0ad5
[gaim-migrate @ 9570]
Christian Hammond <chipx86@chipx86.com>
parents:
8171
diff
changeset
|
236 if (base == NULL) |
| 8171 | 237 { |
| 238 gaim_debug(GAIM_DEBUG_ERROR, "msn", | |
| 239 "Authentication information was not found. This did " | |
| 240 "not just happen, but if it did, you're screwed. " | |
| 241 "Report this.\n"); | |
| 242 | |
| 243 return; | |
| 244 } | |
| 245 | |
| 246 base = strstr(base, "from-PP='"); | |
| 247 base += strlen("from-PP='"); | |
| 248 c = strchr(base, '\''); | |
| 249 | |
| 250 login_params = g_strndup(base, c - base); | |
| 251 | |
|
8808
bbd8cdaf0ad5
[gaim-migrate @ 9570]
Christian Hammond <chipx86@chipx86.com>
parents:
8171
diff
changeset
|
252 msn_cmdproc_send(cmdproc, "USR", "TWN S %s", login_params); |
| 8171 | 253 |
| 254 g_free(login_params); | |
| 255 | |
| 256 msn_nexus_destroy(nexus); | |
| 257 session->nexus = NULL; | |
| 258 } | |
| 259 | |
| 260 g_free(buffer); | |
| 261 } | |
| 262 | |
| 263 static void | |
| 264 nexus_connect_cb(gpointer data, GaimSslConnection *gsc, | |
| 265 GaimInputCondition cond) | |
| 266 { | |
| 267 MsnNexus *nexus; | |
| 268 MsnSession *session; | |
| 269 char *request_str; | |
| 270 char *da_login; | |
| 271 char *base, *c; | |
| 272 char *buffer = NULL; | |
| 273 size_t s; | |
| 274 | |
| 275 nexus = data; | |
| 276 g_return_if_fail(nexus != NULL); | |
| 277 | |
| 278 session = nexus->session; | |
| 279 g_return_if_fail(session != NULL); | |
| 280 | |
| 281 request_str = g_strdup_printf("GET /rdr/pprdr.asp\r\n\r\n"); | |
| 282 | |
| 283 if ((s = gaim_ssl_write(gsc, request_str, strlen(request_str))) <= 0) | |
| 284 { | |
| 285 g_free(request_str); | |
| 286 return; | |
| 287 } | |
| 288 | |
| 289 g_free(request_str); | |
| 290 | |
| 291 /* Get the PassportURLs line. */ | |
| 292 if ((s = msn_ssl_read(gsc, &buffer)) <= 0) | |
| 293 return; | |
| 294 | |
| 295 base = strstr(buffer, "PassportURLs"); | |
| 296 | |
| 297 if (base == NULL) | |
| 298 { | |
| 299 g_free(buffer); | |
| 300 return; | |
| 301 } | |
| 302 | |
| 303 if ((da_login = strstr(base, "DALogin=")) != NULL) | |
| 304 { | |
| 305 if ((da_login = strchr(da_login, '=')) != NULL) | |
| 306 da_login++; | |
| 307 | |
| 308 if ((c = strchr(da_login, ',')) != NULL) | |
| 309 *c = '\0'; | |
| 310 | |
| 311 if ((c = strchr(da_login, '/')) != NULL) | |
| 312 { | |
| 313 nexus->login_path = g_strdup(c); | |
| 314 | |
| 315 *c = '\0'; | |
| 316 } | |
| 317 | |
| 318 nexus->login_host = g_strdup(da_login); | |
| 319 } | |
| 320 | |
| 321 g_free(buffer); | |
| 322 | |
| 323 gaim_ssl_close(gsc); | |
| 324 | |
| 325 /* Now begin the connection to the login server. */ | |
| 326 gaim_ssl_connect(session->account, nexus->login_host, | |
| 327 GAIM_SSL_DEFAULT_PORT, login_connect_cb, | |
| 328 login_error_cb, nexus); | |
| 329 } | |
| 330 | |
| 331 /************************************************************************** | |
| 332 * Nexus | |
| 333 **************************************************************************/ | |
| 334 | |
| 335 MsnNexus * | |
| 336 msn_nexus_new(MsnSession *session) | |
| 337 { | |
| 338 MsnNexus *nexus; | |
| 339 | |
| 340 nexus = g_new0(MsnNexus, 1); | |
| 341 nexus->session = session; | |
| 342 nexus->challenge_data = g_hash_table_new_full(g_str_hash, g_str_equal, | |
| 343 g_free, g_free); | |
| 344 | |
| 345 return nexus; | |
| 346 } | |
| 347 | |
| 348 void | |
| 349 msn_nexus_destroy(MsnNexus *nexus) | |
| 350 { | |
| 351 if (nexus->login_host != NULL) | |
| 352 g_free(nexus->login_host); | |
| 353 | |
| 354 if (nexus->login_path != NULL) | |
| 355 g_free(nexus->login_path); | |
| 356 | |
| 357 if (nexus->challenge_data != NULL) | |
| 358 g_hash_table_destroy(nexus->challenge_data); | |
| 359 | |
| 360 g_free(nexus); | |
| 361 } | |
| 362 | |
| 363 void | |
| 364 msn_nexus_connect(MsnNexus *nexus) | |
| 365 { | |
| 366 gaim_ssl_connect(nexus->session->account, "nexus.passport.com", | |
| 367 GAIM_SSL_DEFAULT_PORT, nexus_connect_cb, | |
| 368 login_error_cb, nexus); | |
| 369 } |
