Mercurial > pidgin.yaz
comparison libpurple/util.c @ 17673:3d035cdd103b
Add some notes about why Yahoo! web messenger login doesn't work
(it's because they redirect us to an https page and purple_util_fetch_url()
doesn't support https), and add checks to purple_util_fetch_url()
to not allow us to be redirected more than 5 times.
author | Mark Doliner <mark@kingant.net> |
---|---|
date | Sun, 03 Jun 2007 21:42:54 +0000 |
parents | d8102e923bd1 |
children | a7a8e4245b33 |
comparison
equal
deleted
inserted
replaced
17672:df788cd53596 | 17673:3d035cdd103b |
---|---|
44 char *page; | 44 char *page; |
45 | 45 |
46 } website; | 46 } website; |
47 | 47 |
48 char *url; | 48 char *url; |
49 int num_times_redirected; | |
49 gboolean full; | 50 gboolean full; |
50 char *user_agent; | 51 char *user_agent; |
51 gboolean http11; | 52 gboolean http11; |
52 char *request; | 53 char *request; |
53 gsize request_written; | 54 gsize request_written; |
3184 g_free(cmd); | 3185 g_free(cmd); |
3185 if (params) | 3186 if (params) |
3186 g_hash_table_destroy(params); | 3187 g_hash_table_destroy(params); |
3187 } | 3188 } |
3188 | 3189 |
3190 /* | |
3191 * TODO: Should probably add a "gboolean *ret_ishttps" parameter that | |
3192 * is set to TRUE if this URL is https, otherwise it is set to | |
3193 * FALSE. But that change will break the API. | |
3194 * | |
3195 * This is important for Yahoo! web messenger login. They now | |
3196 * force https login, and if you access the web messenger login | |
3197 * page via http then it redirects you to the https version, but | |
3198 * purple_util_fetch_url() ignores the "https" and attempts to | |
3199 * fetch the URL via http again, which gets redirected again. | |
3200 */ | |
3189 gboolean | 3201 gboolean |
3190 purple_url_parse(const char *url, char **ret_host, int *ret_port, | 3202 purple_url_parse(const char *url, char **ret_host, int *ret_port, |
3191 char **ret_path, char **ret_user, char **ret_passwd) | 3203 char **ret_path, char **ret_user, char **ret_passwd) |
3192 { | 3204 { |
3193 char scan_info[255]; | 3205 char scan_info[255]; |
3204 static char user_ctrl[] = "A-Za-z0-9.~_/*!&%%?=+^-"; | 3216 static char user_ctrl[] = "A-Za-z0-9.~_/*!&%%?=+^-"; |
3205 static char passwd_ctrl[] = "A-Za-z0-9.~_/*!&%%?=+^-"; | 3217 static char passwd_ctrl[] = "A-Za-z0-9.~_/*!&%%?=+^-"; |
3206 | 3218 |
3207 g_return_val_if_fail(url != NULL, FALSE); | 3219 g_return_val_if_fail(url != NULL, FALSE); |
3208 | 3220 |
3209 if ((turl = strstr(url, "http://")) != NULL || | 3221 if ((turl = purple_strcasestr(url, "http://")) != NULL) |
3210 (turl = strstr(url, "HTTP://")) != NULL) | |
3211 { | 3222 { |
3212 turl += 7; | 3223 turl += 7; |
3224 url = turl; | |
3225 } | |
3226 else if ((turl = purple_strcasestr(url, "https://")) != NULL) | |
3227 { | |
3228 turl += 8; | |
3213 url = turl; | 3229 url = turl; |
3214 } | 3230 } |
3215 | 3231 |
3216 /* parse out authentication information if supplied */ | 3232 /* parse out authentication information if supplied */ |
3217 /* Only care about @ char BEFORE the first / */ | 3233 /* Only care about @ char BEFORE the first / */ |
3289 static gboolean | 3305 static gboolean |
3290 parse_redirect(const char *data, size_t data_len, gint sock, | 3306 parse_redirect(const char *data, size_t data_len, gint sock, |
3291 PurpleUtilFetchUrlData *gfud) | 3307 PurpleUtilFetchUrlData *gfud) |
3292 { | 3308 { |
3293 gchar *s; | 3309 gchar *s; |
3294 | 3310 gchar *new_url, *temp_url, *end; |
3295 if ((s = g_strstr_len(data, data_len, "Location: ")) != NULL) | 3311 gboolean full; |
3296 { | 3312 int len; |
3297 gchar *new_url, *temp_url, *end; | 3313 |
3298 gboolean full; | 3314 if ((s = g_strstr_len(data, data_len, "Location: ")) == NULL) |
3299 int len; | 3315 /* We're not being redirected */ |
3300 | 3316 return FALSE; |
3301 s += strlen("Location: "); | 3317 |
3302 end = strchr(s, '\r'); | 3318 s += strlen("Location: "); |
3303 | 3319 end = strchr(s, '\r'); |
3304 /* Just in case :) */ | 3320 |
3305 if (end == NULL) | 3321 /* Just in case :) */ |
3306 end = strchr(s, '\n'); | 3322 if (end == NULL) |
3307 | 3323 end = strchr(s, '\n'); |
3308 if (end == NULL) | 3324 |
3309 return FALSE; | 3325 if (end == NULL) |
3310 | 3326 return FALSE; |
3311 len = end - s; | 3327 |
3312 | 3328 len = end - s; |
3313 new_url = g_malloc(len + 1); | 3329 |
3314 strncpy(new_url, s, len); | 3330 new_url = g_malloc(len + 1); |
3315 new_url[len] = '\0'; | 3331 strncpy(new_url, s, len); |
3316 | 3332 new_url[len] = '\0'; |
3317 full = gfud->full; | 3333 |
3318 | 3334 full = gfud->full; |
3319 if (*new_url == '/' || g_strstr_len(new_url, len, "://") == NULL) | 3335 |
3320 { | 3336 if (*new_url == '/' || g_strstr_len(new_url, len, "://") == NULL) |
3321 temp_url = new_url; | 3337 { |
3322 | 3338 temp_url = new_url; |
3323 new_url = g_strdup_printf("%s:%d%s", gfud->website.address, | 3339 |
3324 gfud->website.port, temp_url); | 3340 new_url = g_strdup_printf("%s:%d%s", gfud->website.address, |
3325 | 3341 gfud->website.port, temp_url); |
3326 g_free(temp_url); | 3342 |
3327 | 3343 g_free(temp_url); |
3328 full = FALSE; | 3344 |
3329 } | 3345 full = FALSE; |
3330 | 3346 } |
3331 purple_debug_info("util", "Redirecting to %s\n", new_url); | 3347 |
3332 | 3348 purple_debug_info("util", "Redirecting to %s\n", new_url); |
3333 /* | 3349 |
3334 * Try again, with this new location. This code is somewhat | 3350 gfud->num_times_redirected++; |
3335 * ugly, but we need to reuse the gfud because whoever called | 3351 if (gfud->num_times_redirected >= 5) |
3336 * us is holding a reference to it. | 3352 { |
3337 */ | 3353 purple_util_fetch_url_error(gfud, |
3338 g_free(gfud->url); | 3354 _("Could not open %s: Redirected too many times"), |
3339 gfud->url = new_url; | 3355 gfud->url); |
3340 gfud->full = full; | |
3341 g_free(gfud->request); | |
3342 gfud->request = NULL; | |
3343 | |
3344 purple_input_remove(gfud->inpa); | |
3345 gfud->inpa = 0; | |
3346 close(gfud->fd); | |
3347 gfud->fd = -1; | |
3348 gfud->request_written = 0; | |
3349 gfud->len = 0; | |
3350 gfud->data_len = 0; | |
3351 | |
3352 g_free(gfud->website.user); | |
3353 g_free(gfud->website.passwd); | |
3354 g_free(gfud->website.address); | |
3355 g_free(gfud->website.page); | |
3356 purple_url_parse(new_url, &gfud->website.address, &gfud->website.port, | |
3357 &gfud->website.page, &gfud->website.user, &gfud->website.passwd); | |
3358 | |
3359 gfud->connect_data = purple_proxy_connect(NULL, NULL, | |
3360 gfud->website.address, gfud->website.port, | |
3361 url_fetch_connect_cb, gfud); | |
3362 | |
3363 if (gfud->connect_data == NULL) | |
3364 { | |
3365 purple_util_fetch_url_error(gfud, _("Unable to connect to %s"), | |
3366 gfud->website.address); | |
3367 } | |
3368 | |
3369 return TRUE; | 3356 return TRUE; |
3370 } | 3357 } |
3371 | 3358 |
3372 return FALSE; | 3359 /* |
3360 * Try again, with this new location. This code is somewhat | |
3361 * ugly, but we need to reuse the gfud because whoever called | |
3362 * us is holding a reference to it. | |
3363 */ | |
3364 g_free(gfud->url); | |
3365 gfud->url = new_url; | |
3366 gfud->full = full; | |
3367 g_free(gfud->request); | |
3368 gfud->request = NULL; | |
3369 | |
3370 purple_input_remove(gfud->inpa); | |
3371 gfud->inpa = 0; | |
3372 close(gfud->fd); | |
3373 gfud->fd = -1; | |
3374 gfud->request_written = 0; | |
3375 gfud->len = 0; | |
3376 gfud->data_len = 0; | |
3377 | |
3378 g_free(gfud->website.user); | |
3379 g_free(gfud->website.passwd); | |
3380 g_free(gfud->website.address); | |
3381 g_free(gfud->website.page); | |
3382 purple_url_parse(new_url, &gfud->website.address, &gfud->website.port, | |
3383 &gfud->website.page, &gfud->website.user, &gfud->website.passwd); | |
3384 | |
3385 gfud->connect_data = purple_proxy_connect(NULL, NULL, | |
3386 gfud->website.address, gfud->website.port, | |
3387 url_fetch_connect_cb, gfud); | |
3388 | |
3389 if (gfud->connect_data == NULL) | |
3390 { | |
3391 purple_util_fetch_url_error(gfud, _("Unable to connect to %s"), | |
3392 gfud->website.address); | |
3393 } | |
3394 | |
3395 return TRUE; | |
3373 } | 3396 } |
3374 | 3397 |
3375 static size_t | 3398 static size_t |
3376 parse_content_len(const char *data, size_t data_len) | 3399 parse_content_len(const char *data, size_t data_len) |
3377 { | 3400 { |