prozilla/libprozilla/src/ftpsearch.c

1113 lines
28 KiB
C
Raw Normal View History

2010-08-31 03:50:41 +02:00
/******************************************************************************
libprozilla - a download accelerator library
Copyright (C) 2001 Kalum Somaratna
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
******************************************************************************/
#include "common.h"
#include "prozilla.h"
#include "misc.h"
#include "connect.h"
#include "debug.h"
#include "http.h"
#include "ftpsearch.h"
urlinfo *prepare_lycos_url(ftps_request_t * request, char *ftps_loc,
int num_req_mirrors);
urlinfo *prepare_filesearching_url(ftps_request_t * request, char *ftps_loc,
int num_req_mirrors);
uerr_t parse_lycos_html_mirror_list(ftps_request_t * request, char *p);
uerr_t parse_filesearching_html_mirror_list(ftps_request_t * request, char *p);
uerr_t get_mirror_info(connection_t * connection, char **ret_buf);
uerr_t parse_html_mirror_list(ftps_request_t * request, char *p);
char *find_ahref(char *buf);
char *find_end(char *buf);
char *find_closed_a(char *buf);
char *get_string_ahref(char *buf, char *out, size_t out_size);
char *grow_buffer(char *buf_start, char *cur_pos, int *buf_len,
int data_len);
uerr_t get_complete_mirror_list(ftps_request_t * request);
ftp_mirror_t *reprocess_mirror_list(ftp_mirror_t * mirrors,
int *num_servers);
ftps_request_t * proz_ftps_request_init(
urlinfo * requested_url, off_t file_size,
char *ftps_loc,
ftpsearch_server_type_t server_type,
int num_req_mirrors)
{
urlinfo *url;
ftps_request_t * request;
assert(requested_url);
assert(requested_url->file);
request=kmalloc(sizeof(ftps_request_t));
memset(request, 0, sizeof(ftps_request_t));
request->file_name = strdup(requested_url->file);
request->requested_url = proz_copy_url(requested_url);
request->file_size = file_size;
request->server_type = server_type;
pthread_mutex_init(&request->access_mutex, 0);
switch (server_type)
{
case LYCOS:
url = prepare_lycos_url(request, ftps_loc, num_req_mirrors);
if (url == 0)
proz_die("Bad URl specification");
/*NOTE pasing zero as the status change mutes as we dont need it here */
request->connection=proz_connection_init(url,0);
break;
case FILESEARCH_RU:
url = prepare_filesearching_url(request, ftps_loc, num_req_mirrors);
if (url == 0)
proz_die("Bad URl specification");
/*NOTE pasing zero as the status change mutes as we dont need it here */
request->connection=proz_connection_init(url,0);
break;
default:
proz_debug("Unsupported FTP search server type");
proz_die("Unsupported FTP search server type");
}
return request;
}
urlinfo *prepare_lycos_url(ftps_request_t * request, char *ftps_loc,
int num_req_mirrors)
{
urlinfo *url;
uerr_t err;
char *lycos_url_buf;
int lycos_url_len = strlen(ftps_loc) +
strlen
("?form=advanced&query=%s&doit=Search&type=Exact+search&hits=%d&matches=&hitsprmatch=&limdom=&limpath=&limsize1=%d&limsize2=%d&limtime1=&limtime2=&f1=Host&f2=Path&f3=Size&f4=-&f5=-&f6=-&header=none&sort=none&trlen=20");
assert(request->file_name);
url = (urlinfo *) kmalloc(sizeof(urlinfo));
/* Okay lets now construct the URL we want to do lycos */
lycos_url_buf =
(char *) kmalloc(lycos_url_len + strlen(request->file_name) + 300);
sprintf(lycos_url_buf,
2010-09-01 07:45:17 +02:00
"%s?form=advanced&query=%s&doit=Search&type=Exact+search&hits=%d&matches=&hitsprmatch=&limdom=&limpath=&limsize1=%zd&limsize2=%zd&f1=Host&f2=Path&f3=Size&f4=-&f5=-&f6=-&header=none&sort=none&trlen=20",
2010-08-31 03:50:41 +02:00
ftps_loc, request->file_name, num_req_mirrors,
request->file_size, request->file_size);
/* Debugging purposes */
/*sprintf(lycos_url_buf,"localhost/search.html"); */
proz_debug("ftpsearch url= %s\n", lycos_url_buf);
err = proz_parse_url(lycos_url_buf, url, 0);
if (err != URLOK)
return 0;
else
return url;
}
urlinfo *prepare_filesearching_url(ftps_request_t * request, char *ftps_loc,
int num_req_mirrors)
{
urlinfo *url;
uerr_t err;
char *filesearching_url_buf;
int filesearching_url_len = strlen(ftps_loc) +
strlen
("?q=ddd-3.3.tar.bz2&l=en&t=f&e=on&m=20&o=n&s=on&s1=4811576&s2=4811576&d=&p=&p2=&x=10&y=14");
assert(request->file_name);
url = (urlinfo *) kmalloc(sizeof(urlinfo));
/* Okay lets now construct the URL we want to do lycos */
filesearching_url_buf =
(char *) kmalloc(filesearching_url_len + strlen(request->file_name) + 300);
sprintf(filesearching_url_buf,
2010-09-01 07:45:17 +02:00
"%s?q=%s&l=en&t=f&e=on&m=%d&o=n&s=on&s1=%zd&s2=%zd&d=&p=&p2=&x=10&y=14",
2010-08-31 03:50:41 +02:00
ftps_loc, request->file_name, num_req_mirrors,
request->file_size, request->file_size);
/* Debugging purposes */
/* sprintf(filesearching_url_buf,"localhost/fs.html"); */
proz_debug("ftpsearch url= %s\n", filesearching_url_buf);
err = proz_parse_url(filesearching_url_buf, url, 0);
if (err != URLOK)
return 0;
else
return url;
}
uerr_t parse_html_mirror_list(ftps_request_t * request, char *p)
{
switch (request->server_type)
{
case LYCOS:
return parse_lycos_html_mirror_list(request, p);
break;
case FILESEARCH_RU:
return parse_filesearching_html_mirror_list(request, p);
break;
default:
proz_debug("Unsupported FTP search server type");
proz_die("Unsupported FTP search server type");
}
return MIRPARSEFAIL;
}
uerr_t parse_lycos_html_mirror_list(ftps_request_t * request, char *p)
{
struct ftp_mirror **pmirrors = &request->mirrors;
int *num_servers = &request->num_mirrors;
char *p1, *p2, *i = 0, *j;
ftp_mirror_t *ftp_mirrors;
int k, num_ah = 0, num_pre = 0;
char buf[1024];
if (strstr(p, "No hits") != 0)
{
*num_servers = 0;
return MIRINFOK;
}
/*Check the number of PRE tags */
p1 = p;
while (((p1 = strstr(p1, "<PRE>")) != NULL) && p1)
{
num_pre++;
p1 += 5;
}
proz_debug("Number of PRE tags found = %d\n", num_pre);
if (num_pre == 1)
{
if ((i = strstr(p, "<PRE>")) == NULL)
{
proz_debug("nomatches found");
return MIRPARSEFAIL;
}
proz_debug("match at %d found", i - p);
if ((j = strstr(p, "</PRE>")) == NULL)
{
proz_debug("nomatches found");
return MIRPARSEFAIL;
}
} else
{
/*search for the reported hits text */
char *rep_hits;
int prior_pres = 0;
if ((rep_hits = strstr(p, "reported hits")) == NULL)
{
proz_debug("no reported hits found");
return MIRPARSEFAIL;
}
/* Okay so we got the position after the results, lets see how many PRE tags were there before it */
p1 = p;
while (((p1 = strstr(p1, "<PRE>")) < rep_hits) && p1)
{
prior_pres++;
p1 += 5;
}
/* now get the location of the PRE before the output */
p1 = p;
i = 0;
while (prior_pres--)
{
p1 = strstr(p1, "<PRE>");
p1 += 5;
}
i = p1 - 5;
/*now find the </PRE> tag which is after the results */
j = strstr(i, "</PRE>");
if (j == NULL)
{
proz_debug("The expected </PRE> tag was not found!\n");
return MIRPARSEFAIL;
}
}
p1 = kmalloc((j - i - 5) + 100);
strncpy(p1, i + 5, j - i - 5);
p1[j - i - 5 + 1] = 0;
proz_debug("\nstring len= %ld", strlen(p1));
p2 = p1;
while ((i = strstr(p1, "<A HREF=")) != NULL)
{
num_ah++;
p1 = i + 8;
}
proz_debug("\n%d ahrefs found\n", num_ah);
if (num_ah == 0)
{
*num_servers = 0;
return MIRINFOK;
}
*num_servers = num_ah / 3;
proz_debug("%d servers found\n", *num_servers);
/* Allocate +1 because we need to add the user specified server as well
*/
ftp_mirrors =
(ftp_mirror_t *) kmalloc(sizeof(ftp_mirror_t) *
((*num_servers) + 1));
for (k = 0; k < *num_servers; k++)
{
memset(&(ftp_mirrors[k]), 0, sizeof(ftp_mirror_t));
p2 = get_string_ahref(p2, buf, sizeof(buf)/sizeof(char));
ftp_mirrors[k].server_name = kstrdup(buf);
p2 = get_string_ahref(p2, buf, sizeof(buf)/sizeof(char));
ftp_mirrors[k].paths = kmalloc(sizeof(mirror_path_t));
// ftp_mirrors[k].paths=kmalloc (sizeof (char *));
ftp_mirrors[k].num_paths = 1;
/*Strip any leading slash in the path name if preent */
if (*buf == '/')
ftp_mirrors[k].paths[0].path = kstrdup(buf + 1);
else
ftp_mirrors[k].paths[0].path = kstrdup(buf);
p2 = get_string_ahref(p2, buf,sizeof(buf)/sizeof(char));
ftp_mirrors[k].file_name = kstrdup(buf);
}
/* add the users server to the end if it is a ftp server */
if (request->requested_url->proto == URLFTP)
{
memset(&(ftp_mirrors[k]), 0, sizeof(ftp_mirror_t));
ftp_mirrors[k].server_name = kstrdup(request->requested_url->host);
ftp_mirrors[k].paths = kmalloc(sizeof(mirror_path_t));
ftp_mirrors[k].num_paths = 1;
if (*(request->requested_url->dir))
ftp_mirrors[k].paths[0].path = kstrdup(request->requested_url->dir);
else
ftp_mirrors[k].paths[0].path = kstrdup("");
ftp_mirrors[k].file_name = kstrdup(request->requested_url->file);
*num_servers += 1;
}
proz_debug("%d servers found\n", *num_servers);
for (k = 0; k < *num_servers; k++)
{
ftp_mirrors[k].full_name =
(char *) kmalloc(strlen(ftp_mirrors[k].server_name) +
strlen(ftp_mirrors[k].paths[0].path) +
strlen(ftp_mirrors[k].file_name) + 13);
sprintf(ftp_mirrors[k].full_name, "%s%s:21/%s%s%s", "ftp://",
ftp_mirrors[k].server_name, ftp_mirrors[k].paths[0].path, "/",
ftp_mirrors[k].file_name);
proz_debug("%s\n", ftp_mirrors[k].full_name);
}
*pmirrors = reprocess_mirror_list(ftp_mirrors, num_servers);
/* *pmirrors = ftp_mirrors; */
return MIRINFOK;
}
uerr_t parse_filesearching_html_mirror_list(ftps_request_t * request, char *p)
{
struct ftp_mirror **pmirrors = &request->mirrors;
int *num_servers = &request->num_mirrors;
char *p1, *p2, *i = 0, *j;
ftp_mirror_t *ftp_mirrors;
int k, num_ah = 0, num_pre = 0;
char buf[1024];
if (strstr(p, "not found") != 0)
{
*num_servers = 0;
return MIRINFOK;
}
/*Check the number of PRE tags */
p1 = p;
while (((p1 = strstr(p1, "<pre")) != NULL) && p1)
{
num_pre++;
p1 += 4;
}
proz_debug("Number of PRE tags found = %d\n", num_pre);
if (num_pre == 1)
{
if ((i = strstr(p, "<pre class=list>")) == NULL)
{
proz_debug("nomatches found");
return MIRPARSEFAIL;
}
proz_debug("match at %d found", i - p);
if ((j = strstr(p, "</pre>")) == NULL)
{
proz_debug("nomatches found");
return MIRPARSEFAIL;
}
} else
{
/*search for the reported hits text */
char *rep_hits;
int prior_pres = 0;
if ((rep_hits = strstr(p, "reported hits")) == NULL)
{
proz_debug("no reported hits found");
return MIRPARSEFAIL;
}
/* Okay so we got the position after the results, lets see how many PRE tags were there before it */
p1 = p;
while (((p1 = strstr(p1, "<pre")) < rep_hits) && p1)
{
prior_pres++;
p1 += 5;
}
/* now get the location of the PRE before the output */
p1 = p;
i = 0;
while (prior_pres--)
{
p1 = strstr(p1, "<pre class=list>");
p1 += 5;
}
i = p1 - 5;
/*now find the </PRE> tag which is after the results */
j = strstr(i, "</pre>");
if (j == NULL)
{
proz_debug("The expected </PRE> tag was not found!\n");
return MIRPARSEFAIL;
}
}
p1 = kmalloc((j - i - 16) + 100);
strncpy(p1, i + 16, j - i - 16);
proz_debug("\nstring len= %ld", strlen(p1));
proz_debug("\nstring value= %s", p1);
p1[j - i - 16 + 1] = 0;
p2 = p1;
while ((i = strstr(p1, "<a href=")) != NULL)
{
num_ah++;
p1 = i + 8;
}
proz_debug("\n%d ahrefs found\n", num_ah);
if (num_ah == 0)
{
*num_servers = 0;
return MIRINFOK;
}
*num_servers = num_ah / 3;
proz_debug("%d servers found\n", *num_servers);
/* Allocate +1 because we need to add the user specified server as well
*/
ftp_mirrors =
(ftp_mirror_t *) kmalloc(sizeof(ftp_mirror_t) *
((*num_servers) + 1));
for (k = 0; k < *num_servers; k++)
{
memset(&(ftp_mirrors[k]), 0, sizeof(ftp_mirror_t));
p2 = get_string_ahref(p2, buf,sizeof(buf)/sizeof(char));
ftp_mirrors[k].server_name = kstrdup(buf);
p2 = get_string_ahref(p2, buf,sizeof(buf)/sizeof(char));
ftp_mirrors[k].paths = kmalloc(sizeof(mirror_path_t));
// ftp_mirrors[k].paths=kmalloc (sizeof (char *));
ftp_mirrors[k].num_paths = 1;
/*Strip any trailing slash */
if(buf[strlen(buf)-1]=='/')
buf[strlen(buf)-1]=0;
/*Strip any leading slash in the path name if preent */
if (*buf == '/')
ftp_mirrors[k].paths[0].path = kstrdup(buf + 1);
else
ftp_mirrors[k].paths[0].path = kstrdup(buf);
p2 = get_string_ahref(p2, buf,sizeof(buf)/sizeof(char));
ftp_mirrors[k].file_name = kstrdup(buf);
}
/* add the users server to the end if it is a ftp server */
if (request->requested_url->proto == URLFTP)
{
memset(&(ftp_mirrors[k]), 0, sizeof(ftp_mirror_t));
ftp_mirrors[k].server_name = kstrdup(request->requested_url->host);
ftp_mirrors[k].paths = kmalloc(sizeof(mirror_path_t));
ftp_mirrors[k].num_paths = 1;
if (*(request->requested_url->dir))
ftp_mirrors[k].paths[0].path = kstrdup(request->requested_url->dir);
else
ftp_mirrors[k].paths[0].path = kstrdup("");
ftp_mirrors[k].file_name = kstrdup(request->requested_url->file);
*num_servers += 1;
}
proz_debug("%d servers found\n", *num_servers);
for (k = 0; k < *num_servers; k++)
{
ftp_mirrors[k].full_name =
(char *) kmalloc(strlen(ftp_mirrors[k].server_name) +
strlen(ftp_mirrors[k].paths[0].path) +
strlen(ftp_mirrors[k].file_name) + 13);
sprintf(ftp_mirrors[k].full_name, "%s%s:21/%s%s%s", "ftp://",
ftp_mirrors[k].server_name, ftp_mirrors[k].paths[0].path, "/",
ftp_mirrors[k].file_name);
proz_debug("%s\n", ftp_mirrors[k].full_name);
}
*pmirrors = reprocess_mirror_list(ftp_mirrors, num_servers);
/* *pmirrors = ftp_mirrors; */
return MIRINFOK;
}
uerr_t get_mirror_info(connection_t * connection, char **ret_buf)
{
uerr_t err;
int remote_port_len;
char *user, *passwd, *www_auth = NULL, *proxy_auth = NULL, *location =
NULL, *referer = NULL, *pragma_no_cache = NULL;
char *request, *remote_port;
netrc_entry *netrc_ent;
char buffer[HTTP_BUFFER_SIZE];
/*The http stats that were returned after the call with GET */
http_stat_t hs_after_get;
char *p, *p1, *p2;
int p_len, ret, total;
/* we want it to terminate immediately */
pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
/*clear the socks */
connection->data_sock = 0;
memset(&hs_after_get, 0, sizeof(hs_after_get));
connection_change_status(connection, CONNECTING);
if (http_use_proxy(connection))
{
connection_show_message(connection, _("Connecting to %s"),
connection->http_proxy->proxy_url.host);
err = connect_to_server(&connection->data_sock,
connection->http_proxy->proxy_url.host,
connection->http_proxy->proxy_url.port,
&connection->xfer_timeout);
if (err != NOCONERROR)
{
proz_debug(_("Error connecting to %s"),
connection->http_proxy->proxy_url.host);
connection_change_status(connection, REMOTEFATAL);
return err;
}
} else
{
connection_show_message(connection, _("Connecting to %s"),
connection->u.host);
err = connect_to_server(&connection->data_sock, connection->u.host,
connection->u.port, &connection->xfer_timeout);
if (err != NOCONERROR)
{
proz_debug(_("Error connecting to %s"), connection->u.host);
connection_change_status(connection, REMOTEFATAL);
return err;
}
}
user = connection->u.user;
passwd = connection->u.passwd;
/* Use .netrc if asked to do so. */
if (connection->use_netrc == TRUE)
{
netrc_ent = search_netrc(libprozrtinfo.netrc_list, connection->u.host);
if (netrc_ent != NULL)
{
user = netrc_ent->account;
passwd = netrc_ent->password;
}
}
user = user ? user : "";
passwd = passwd ? passwd : "";
if (strlen(user) || strlen(passwd))
{
/* Construct the necessary header. */
www_auth = get_basic_auth_str(user, passwd, "Authorization");
proz_debug(_("Authenticating as user %s password %s"), user, passwd);
proz_debug(_("Authentification string=%s"), www_auth);
} else
www_auth = 0;
if (http_use_proxy(connection))
{
if (strlen(connection->http_proxy->username)
|| strlen(connection->http_proxy->passwd))
proxy_auth =
get_basic_auth_str(connection->http_proxy->username,
connection->http_proxy->passwd,
"Proxy-Authorization");
}
if (connection->u.port == 80)
{
remote_port = NULL;
remote_port_len = 0;
} else
{
remote_port = (char *) alloca(64);
remote_port_len = sprintf(remote_port, ":%d", connection->u.port);
}
if (connection->u.referer)
{
referer = (char *) alloca(13 + strlen(connection->u.referer));
sprintf(referer, "Referer: %s\r\n", connection->u.referer);
}
/* If we go through a proxy the request for the URL is different */
if (http_use_proxy(connection))
{
location = (char *) alloca(strlen(connection->u.url) + 1);
strcpy(location, connection->u.url);
} else
{
location = (char *) alloca(strlen(connection->u.path) + 1);
strcpy(location, connection->u.path);
}
/*Use no-cache directive for proxy servers, yes by default here as we dont want ftpsearch rsults which can change soon to be cached */
if (http_use_proxy(connection))
{
pragma_no_cache = (char *) alloca(21);
sprintf(pragma_no_cache, "Pragma: no-cache\r\n");
}
request = (char *) alloca(strlen(location)
+ strlen(connection->user_agent)
+ strlen(connection->u.host) + remote_port_len
+ (referer ? strlen(referer) : 0)
+ (www_auth ? strlen(www_auth) : 0)
+ (proxy_auth ? strlen(proxy_auth) : 0)
+ 64
+
(pragma_no_cache ? strlen(pragma_no_cache) :
0));
/* TODO Add referrer tag. */
sprintf(request,
"GET %s HTTP/1.0\r\nUser-Agent: %s\r\nHost: %s%s\r\nAccept: */*\r\n%s%s%s%s\r\n",
location, connection->user_agent, connection->u.host,
remote_port ? remote_port : "",
referer ? referer : "",
www_auth ? www_auth : "", proxy_auth ? proxy_auth : "",
pragma_no_cache ? pragma_no_cache : "");
proz_debug("1 HTTP request = %s", request);
connection_show_message(connection, _("Sending HTTP request"));
err = http_fetch_headers(connection, &hs_after_get, request);
/* What hapenned ? */
if (err != HOK)
{
proz_debug("1 http_fetch_headers err != HOK %d",err);
/*Check if we authenticated using any user or password and if we
were kicked out, if so return HAUTHFAIL */
if (err == HAUTHREQ && (strlen(user) || strlen(passwd)))
err = HAUTHFAIL;
/*
* a error occured druing the process
*/
close_sock(&connection->data_sock);
connection_change_status(connection, REMOTEFATAL);
return err;
}
/* Ok start fetching the data */
p1 = p = (char *) kmalloc(HTTP_BUFFER_SIZE + 1);
p_len = HTTP_BUFFER_SIZE + 1;
total = 0;
do
{
ret =
krecv(connection->data_sock, buffer, sizeof(buffer), 0,
&connection->xfer_timeout);
if (ret > 0)
{
p2 = grow_buffer(p, p1, &p_len, ret);
memcpy(p2 + (p1 - p), buffer, ret);
p1 = (p1 - p) + ret + p2;
p = p2;
}
total += ret;
}
while (ret > 0);
if (ret == -1)
{
if (errno == ETIMEDOUT)
{
close(connection->data_sock);
return READERR;
}
close(connection->data_sock);
return READERR;
}
p[total] = 0;
*ret_buf = p;
close_sock(&connection->data_sock);
return HOK;
}
char *find_ahref(char *buf)
{
return (strcasestr(buf, "<A HREF="));
}
char *find_end(char *buf)
{
return (strcasestr(buf, ">"));
}
char *find_closed_a(char *buf)
{
return (strcasestr(buf, "</A"));
}
char *get_string_ahref(char *buf, char *out, size_t out_size)
{
char *p1, *p2, *p3;
size_t to_copy;
p1 = find_ahref(buf);
assert(p1 != NULL);
p2 = find_end(p1);
assert(p2 != NULL);
p3 = find_closed_a(p2);
assert(p3 != NULL);
to_copy = p3 - p2 - 1;
if (to_copy >= out_size)
to_copy = out_size - 1;
strncpy(out, p2 + 1, to_copy);
out[to_copy] = 0;
return p3;
}
char *grow_buffer(char *buf_start, char *cur_pos, int *buf_len,
int data_len)
{
const int INIT_SIZE = 4048;
int bytes_left;
char *p;
/* find how many bytes are left */
bytes_left = *buf_len - (cur_pos - buf_start);
assert(bytes_left >= 0);
assert(data_len <= INIT_SIZE);
if (bytes_left < data_len + 1)
{
/* time to realloc the buffer buffer */
p = krealloc(buf_start, *buf_len + INIT_SIZE);
*buf_len += INIT_SIZE;
return p;
} else
{
return buf_start;
}
}
void proz_get_complete_mirror_list(ftps_request_t * request)
{
request->info_running = TRUE;
/* get_complete_mirror_list(request); */
if (pthread_create(&request->info_thread, NULL,
(void *) &get_complete_mirror_list,
(void *) request) != 0)
proz_die(_("Error: Not enough system resources"));
}
void proz_cancel_mirror_list_request(ftps_request_t * request)
{
request->info_running = FALSE;
pthread_cancel(request->info_thread);
pthread_join(request->info_thread,0);
}
uerr_t get_complete_mirror_list(ftps_request_t * request)
{
char *data_buf;
pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
do
{
pthread_mutex_lock(&request->access_mutex);
request->info_running = TRUE;
pthread_mutex_unlock(&request->access_mutex);
pthread_cleanup_push(cleanup_socks, (void *) request->connection);
request->err = get_mirror_info(request->connection, &data_buf);
pthread_cleanup_pop(0);
if (request->err == NEWLOCATION)
{
char *constructed_newloc;
/*DONE : handle relative urls too */
constructed_newloc =
uri_merge(request->connection->u.url,
request->connection->hs.newloc);
proz_debug("Redirected to %s, merged URL = %s",
request->connection->hs.newloc, constructed_newloc);
proz_free_url(&request->connection->u, 0);
request->err =
proz_parse_url(constructed_newloc, &request->connection->u, 0);
if (request->err != URLOK)
{
connection_show_message(request->connection,
_
("The server returned location is wrong: %s!"),
constructed_newloc);
pthread_mutex_lock(&request->connection->access_mutex);
request->info_running = FALSE;
pthread_mutex_unlock(&request->connection->access_mutex);
kfree(constructed_newloc);
pthread_mutex_lock(&request->access_mutex);
request->info_running = FALSE;
pthread_mutex_unlock(&request->access_mutex);
return (request->err = HERR);
} else
connection_show_message(request->connection,
_("Redirected to => %s"),
constructed_newloc);
kfree(constructed_newloc);
request->err = NEWLOCATION;
}
}
while (request->err == NEWLOCATION);
/*TODO handle and process the redirection here */
if (request->err != HOK)
{
pthread_mutex_lock(&request->access_mutex);
request->info_running = FALSE;
pthread_mutex_unlock(&request->access_mutex);
return request->err;
}
request->err = parse_html_mirror_list(request, data_buf);
/*TODO see if can give further info */
pthread_mutex_lock(&request->access_mutex);
request->info_running = FALSE;
pthread_mutex_unlock(&request->access_mutex);
return request->err;
}
boolean proz_request_info_running(ftps_request_t * request)
{
boolean ret;
pthread_mutex_lock(&request->access_mutex);
ret = request->info_running;
pthread_mutex_unlock(&request->access_mutex);
return ret;
}
boolean proz_request_mass_ping_running(ftps_request_t * request)
{
boolean ret;
pthread_mutex_lock(&request->access_mutex);
ret = request->mass_ping_running;
pthread_mutex_unlock(&request->access_mutex);
return ret;
}
ftp_mirror_t *reprocess_mirror_list(ftp_mirror_t * mirrors,
int *num_servers)
{
ftp_mirror_t *ftp_mirrors;
int i, j;
int num_new_servers = 0;
ftp_mirrors =
(ftp_mirror_t *) kmalloc(sizeof(ftp_mirror_t) * ((*num_servers)));
for (i = 0; i < *num_servers; i++)
{
if (mirrors[i].copied != 1)
{
num_new_servers++;
memset(ftp_mirrors + num_new_servers - 1, 0, sizeof(ftp_mirror_t));
memcpy(ftp_mirrors + num_new_servers - 1, mirrors + i,
sizeof(ftp_mirror_t));
/*For the moment assume that all the mirrors support resume */
ftp_mirrors[num_new_servers - 1].resume_supported=TRUE;
for (j = i + 1; j < *num_servers; j++)
{
if ((strcasecmp
(mirrors[i].server_name,
mirrors[j].server_name) == 0) && mirrors[j].copied != 1)
{
/*found a match */
ftp_mirrors[num_new_servers - 1].num_paths++;
ftp_mirrors[num_new_servers - 1].paths =
krealloc(ftp_mirrors[num_new_servers - 1].paths,
(sizeof(mirror_path_t) *
ftp_mirrors[num_new_servers - 1].num_paths));
// ftp_mirrors[num_new_servers-1].paths = krealloc(ftp_mirrors[num_new_servers-1].paths,ftp_mirrors[num_new_servers-1].num_paths );
ftp_mirrors[num_new_servers -
1].paths[ftp_mirrors[num_new_servers - 1].num_paths -
1].path = strdup(mirrors[j].paths[0].path);
ftp_mirrors[num_new_servers -
1].paths[ftp_mirrors[num_new_servers - 1].num_paths -
1].valid = TRUE;
mirrors[j].copied = 1;
}
}
}
}
*num_servers = num_new_servers;
proz_debug("Displaying the reparsed list \n");
for (i = 0; i < num_new_servers; i++)
{
proz_debug("%s\n", ftp_mirrors[i].full_name);
for (j = 0; j < ftp_mirrors[i].num_paths; j++)
proz_debug("\t%s\n", ftp_mirrors[i].paths[j].path);
}
proz_debug("End display reparsed list\n");
/*TODO free the mirros struct which we will not use now */
return ftp_mirrors;
}
/*fixme do something about this, move to a better file rather than main.c */
int compare_two_servers(const void *a, const void *b)
{
const ftp_mirror_t *ma = (const ftp_mirror_t *) a;
const ftp_mirror_t *mb = (const ftp_mirror_t *) b;
int milli_sec_a;
int milli_sec_b;
if (ma->status != RESPONSEOK && (mb->status != RESPONSEOK))
return 1000000;
milli_sec_a = ma->milli_secs;
if (ma->status != RESPONSEOK)
{
milli_sec_a = 1000000;
}
milli_sec_b = mb->milli_secs;
if (mb->status != RESPONSEOK)
{
milli_sec_b = 1000000;
}
return (milli_sec_a - milli_sec_b);
}
void proz_sort_mirror_list(ftp_mirror_t * mirrors, int num_servers)
{
int i;
qsort(mirrors, num_servers, sizeof(ftp_mirror_t), compare_two_servers);
for (i = 0; i < num_servers; i++)
proz_debug("Mirror = %s, time =%d", mirrors[i].server_name,
mirrors[i].milli_secs);
}
int ftpsearch_get_server_position(ftps_request_t * request, char *server)
{
int i;
for (i = 0; i < request->num_mirrors; i++)
{
if (strcmp(request->mirrors[i].server_name, server) == 0)
return i;
}
return -1;
}
int ftpsearch_get_path_position(ftps_request_t * request, char *server,
char *path)
{
int i, pos;
pos = ftpsearch_get_server_position(request, server);
assert(pos != -1);
proz_debug("num avail paths %d", request->mirrors[pos].num_paths);
for (i = 0; i < request->mirrors[pos].num_paths; i++)
{
proz_debug("avail path is %s", request->mirrors[pos].paths[i].path);
proz_debug("path to check is %s", path);
if (strcmp(request->mirrors[pos].paths[i].path, path) == 0)
return i;
}
return -1;
}