diff --git a/CMakeLists.txt b/CMakeLists.txt index c556ccf..ae6d489 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,6 @@ cmake_minimum_required(VERSION 3.20) -project(libprozilla VERSION 1.2.3 LANGUAGES C) +project(libprozilla VERSION 1.2.4 LANGUAGES C) include(CTest) diff --git a/README b/README index 73d70c2..3f2eb82 100644 --- a/README +++ b/README @@ -65,4 +65,4 @@ prozilla-dev: Homepage -------- -prozilla.genesys.ro +https://prozilla.disconnected-by-peer.at diff --git a/po/libprozilla.pot b/po/libprozilla.pot index f433867..4cca9b6 100644 --- a/po/libprozilla.pot +++ b/po/libprozilla.pot @@ -6,7 +6,7 @@ #, fuzzy msgid "" msgstr "" -"Project-Id-Version: libprozilla 1.2.3\n" +"Project-Id-Version: libprozilla 1.2.4\n" "Report-Msgid-Bugs-To: prozilla-dev@disconnected-by-peer.at\n" "POT-Creation-Date: 2026-07-14 19:48+0200\n" "PO-Revision-Date: 2026-07-14 19:48+0200\n" diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 3f99740..591fcb8 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -10,6 +10,7 @@ target_include_directories(prozilla PRIVATE "${PROJECT_BINARY_DIR}/generated") target_compile_definitions(prozilla PRIVATE HAVE_CONFIG_H=1 _GNU_SOURCE LOCALEDIR="${LOCALEDIR}") target_compile_options(prozilla PRIVATE $<$:-Wall;-Wextra>) +target_compile_options(prozilla PRIVATE $<$:-Wno-clobbered>) target_link_libraries(prozilla PUBLIC Threads::Threads) target_link_libraries(prozilla PRIVATE CURL::libcurl) if(Intl_FOUND) diff --git a/src/connect.c b/src/connect.c index b545ed8..563a130 100644 --- a/src/connect.c +++ b/src/connect.c @@ -199,9 +199,7 @@ int select_fd(int fd, struct timeval *timeout, int writep) int krecv(int sock, char *buffer, int size, int flags, struct timeval *timeout) { - int ret, arglen; - - arglen = sizeof(int); + int ret; assert(size >= 0); diff --git a/src/connection.c b/src/connection.c index dbc27c4..d1cfeca 100644 --- a/src/connection.c +++ b/src/connection.c @@ -160,7 +160,7 @@ uerr_t connection_retr_fsize_not_known(connection_t * connection, char *read_buffer, int read_buffer_size) { - off_t bytes_read; + int bytes_read; connection_change_status(connection, DOWNLOADING); gettimeofday(&connection->time_begin, NULL); @@ -172,7 +172,8 @@ uerr_t connection_retr_fsize_not_known(connection_t * connection, &connection->xfer_timeout); if (bytes_read > 0) { - if (write_data_with_lock(connection, read_buffer, sizeof(char), bytes_read) < bytes_read) + if (write_data_with_lock(connection, read_buffer, sizeof(char), + (size_t)bytes_read) < (size_t)bytes_read) { proz_debug(_("write failed")); connection_show_message(connection, @@ -224,7 +225,7 @@ uerr_t connection_retr_fsize_not_known(connection_t * connection, uerr_t connection_retr_fsize_known(connection_t * connection, char *read_buffer, int read_buffer_size) { - off_t bytes_read; + int bytes_read; off_t bytes_to_get; pthread_mutex_lock(&connection->access_mutex); @@ -266,7 +267,8 @@ uerr_t connection_retr_fsize_known(connection_t * connection, if (bytes_read > 0) { - if (write_data_with_lock(connection, read_buffer, sizeof(char), bytes_read) < bytes_read) + if (write_data_with_lock(connection, read_buffer, sizeof(char), + (size_t)bytes_read) < (size_t)bytes_read) { proz_debug(_("write failed")); connection_show_message(connection, @@ -329,7 +331,7 @@ dl_status proz_connection_get_status(connection_t * connection) /*This will return a textual representation of the status of a conenction. */ -char *proz_connection_get_status_string(connection_t * connection) +const char *proz_connection_get_status_string(connection_t * connection) { dl_status status; @@ -337,7 +339,7 @@ char *proz_connection_get_status_string(connection_t * connection) status = connection->status; pthread_mutex_unlock(connection->status_change_mutex); - switch (connection->status) + switch (status) { case IDLE: return(_("Idle")); diff --git a/src/ftp.c b/src/ftp.c index 34c0a85..a2843a6 100644 --- a/src/ftp.c +++ b/src/ftp.c @@ -625,7 +625,6 @@ uerr_t ftp_login(connection_t * connection, const char *username, { uerr_t err = FTPERR; int ret_code = 220; - boolean logged_in = FALSE; while (1) { @@ -688,7 +687,6 @@ uerr_t ftp_login(connection_t * connection, const char *username, case 231: /* Fallthrough. */ case 202: - logged_in = TRUE; if (!ftp_use_proxy(connection)) return FTPOK; /* Logged in succesfully. */ diff --git a/src/ftpparse.c b/src/ftpparse.c index fa1f17a..414e548 100644 --- a/src/ftpparse.c +++ b/src/ftpparse.c @@ -188,6 +188,7 @@ uerr_t ftp_parse(ftpparse *fp, char *buf, int len) if (*buf == 'l') fp->filetype = SYMBOLIC_LINK; ptr = cp = strdup(buf); + (void)ptr; for (i = 0; i < 4; i++) { @@ -235,9 +236,7 @@ uerr_t ftp_parse(ftpparse *fp, char *buf, int len) time_t parse_time(const char * str) { - char * p; - struct tm tm; - time_t t; + const char *p; if (!str) return 0; diff --git a/src/ftpsearch.c b/src/ftpsearch.c index ba90f5d..221b558 100644 --- a/src/ftpsearch.c +++ b/src/ftpsearch.c @@ -26,13 +26,18 @@ #include "ftpsearch.h" -urlinfo *prepare_lycos_url(ftps_request_t * request, char *ftps_loc, +urlinfo *prepare_lycos_url(ftps_request_t * request, const char *ftps_loc, int num_req_mirrors); -urlinfo *prepare_filesearching_url(ftps_request_t * request, char *ftps_loc, +urlinfo *prepare_filesearching_url(ftps_request_t * request, const char *ftps_loc, int num_req_mirrors); +urlinfo *prepare_archie_url(ftps_request_t * request, const char *ftps_loc, + int num_req_mirrors); +urlinfo *prepare_mamont_url(ftps_request_t * request, const char *ftps_loc); 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 parse_archie_json_mirror_list(ftps_request_t * request, char *p); +uerr_t parse_mamont_html_mirror_list(ftps_request_t * request, char *p); uerr_t get_mirror_info(connection_t * connection, char **ret_buf); @@ -52,7 +57,7 @@ ftp_mirror_t *reprocess_mirror_list(ftp_mirror_t * mirrors, ftps_request_t * proz_ftps_request_init( urlinfo * requested_url, off_t file_size, - char *ftps_loc, + const char *ftps_loc, ftpsearch_server_type_t server_type, int num_req_mirrors) { @@ -92,6 +97,20 @@ ftps_request_t * proz_ftps_request_init( request->connection = proz_connection_init(url, 0); break; + case ARCHIE_JSON: + url = prepare_archie_url(request, ftps_loc, num_req_mirrors); + if (url == 0) + proz_die("Bad URL specification"); + request->connection = proz_connection_init(url, 0); + break; + + case MAMONT_HTML: + url = prepare_mamont_url(request, ftps_loc); + if (url == 0) + proz_die("Bad URL specification"); + request->connection = proz_connection_init(url, 0); + break; + default: proz_debug("Unsupported FTP search server type"); proz_die("Unsupported FTP search server type"); @@ -101,7 +120,78 @@ ftps_request_t * proz_ftps_request_init( } -urlinfo *prepare_lycos_url(ftps_request_t * request, char *ftps_loc, +static char *url_encode_component(const char *input) +{ + static const char hex[] = "0123456789ABCDEF"; + size_t input_len = strlen(input); + char *encoded = kmalloc(input_len * 3 + 1); + char *out = encoded; + + while (*input) + { + unsigned char ch = (unsigned char)*input++; + if (isalnum(ch) || ch == '-' || ch == '_' || ch == '.' || ch == '~') + *out++ = (char)ch; + else + { + *out++ = '%'; + *out++ = hex[ch >> 4]; + *out++ = hex[ch & 15]; + } + } + *out = '\0'; + return encoded; +} + + +urlinfo *prepare_archie_url(ftps_request_t * request, const char *ftps_loc, + int num_req_mirrors) +{ + urlinfo *url = kmalloc(sizeof(*url)); + char *encoded_name = url_encode_component(request->file_name); + size_t length = strlen(ftps_loc) + strlen(encoded_name) + 80; + char *request_url = kmalloc(length); + uerr_t err; + + snprintf(request_url, length, + "%s?q=%s&type=exact&database=anonftp&limit=%d", + ftps_loc, encoded_name, num_req_mirrors); + proz_debug("ftpsearch url= %s\n", request_url); + err = proz_parse_url(request_url, url, 0); + kfree(encoded_name); + kfree(request_url); + if (err != URLOK) + { + kfree(url); + return 0; + } + return url; +} + + +urlinfo *prepare_mamont_url(ftps_request_t * request, const char *ftps_loc) +{ + urlinfo *url = kmalloc(sizeof(*url)); + char *encoded_name = url_encode_component(request->file_name); + size_t length = strlen(ftps_loc) + strlen(encoded_name) + 16; + char *request_url = kmalloc(length); + uerr_t err; + + snprintf(request_url, length, "%s?st=%s", ftps_loc, encoded_name); + proz_debug("ftpsearch url= %s\n", request_url); + err = proz_parse_url(request_url, url, 0); + kfree(encoded_name); + kfree(request_url); + if (err != URLOK) + { + kfree(url); + return 0; + } + return url; +} + + +urlinfo *prepare_lycos_url(ftps_request_t * request, const char *ftps_loc, int num_req_mirrors) { urlinfo *url; @@ -141,7 +231,7 @@ urlinfo *prepare_lycos_url(ftps_request_t * request, char *ftps_loc, -urlinfo *prepare_filesearching_url(ftps_request_t * request, char *ftps_loc, +urlinfo *prepare_filesearching_url(ftps_request_t * request, const char *ftps_loc, int num_req_mirrors) { urlinfo *url; @@ -193,6 +283,12 @@ uerr_t parse_html_mirror_list(ftps_request_t * request, char *p) return parse_filesearching_html_mirror_list(request, p); break; + case ARCHIE_JSON: + return parse_archie_json_mirror_list(request, p); + + case MAMONT_HTML: + return parse_mamont_html_mirror_list(request, p); + default: proz_debug("Unsupported FTP search server type"); proz_die("Unsupported FTP search server type"); @@ -200,6 +296,188 @@ uerr_t parse_html_mirror_list(ftps_request_t * request, char *p) return MIRPARSEFAIL; } + +static const char *json_url_value(const char *cursor, char *output, + size_t output_size) +{ + const char *key = strstr(cursor, "\"URL\""); + size_t used = 0; + + if (key == NULL) + return NULL; + cursor = key + 5; + while (isspace((unsigned char)*cursor)) + cursor++; + if (*cursor++ != ':') + return json_url_value(cursor, output, output_size); + while (isspace((unsigned char)*cursor)) + cursor++; + if (*cursor++ != '\"') + return json_url_value(cursor, output, output_size); + + while (*cursor && *cursor != '\"') + { + unsigned char ch = (unsigned char)*cursor++; + if (ch == '\\') + { + ch = (unsigned char)*cursor++; + if (ch == 'n') ch = '\n'; + else if (ch == 'r') ch = '\r'; + else if (ch == 't') ch = '\t'; + else if (ch == 'b') ch = '\b'; + else if (ch == 'f') ch = '\f'; + else if (ch == 'u') + { + /* FTP URLs are ASCII; skip a JSON Unicode escape safely. */ + for (int i = 0; i < 4 && isxdigit((unsigned char)*cursor); i++) + cursor++; + ch = '?'; + } + } + if (used + 1 < output_size) + output[used++] = (char)ch; + } + output[used] = '\0'; + return *cursor == '\"' ? cursor + 1 : cursor; +} + + +uerr_t parse_archie_json_mirror_list(ftps_request_t * request, char *p) +{ + ftp_mirror_t *mirrors; + const char *cursor = p; + int capacity = 1; + int count = 0; + char url_string[4096]; + + while ((cursor = strstr(cursor, "\"URL\"")) != NULL) + { + capacity++; + cursor += 5; + } + mirrors = kmalloc(sizeof(*mirrors) * (size_t)capacity); + cursor = p; + + while ((cursor = json_url_value(cursor, url_string, + sizeof(url_string))) != NULL) + { + urlinfo parsed; + if (proz_parse_url(url_string, &parsed, 0) != URLOK) + continue; + if (parsed.proto != URLFTP && parsed.proto != URLFTPS && + parsed.proto != URLSFTP) + { + proz_free_url(&parsed, FALSE); + continue; + } + + memset(&mirrors[count], 0, sizeof(mirrors[count])); + mirrors[count].server_name = kstrdup(parsed.host); + mirrors[count].paths = kmalloc(sizeof(mirror_path_t)); + mirrors[count].num_paths = 1; + mirrors[count].paths[0].path = kstrdup(parsed.dir ? parsed.dir : ""); + mirrors[count].paths[0].valid = TRUE; + mirrors[count].file_name = kstrdup(parsed.file); + mirrors[count].full_name = kstrdup(url_string); + count++; + proz_free_url(&parsed, FALSE); + } + + if (request->requested_url->proto == URLFTP || + request->requested_url->proto == URLFTPS || + request->requested_url->proto == URLSFTP) + { + urlinfo *original = request->requested_url; + memset(&mirrors[count], 0, sizeof(mirrors[count])); + mirrors[count].server_name = kstrdup(original->host); + mirrors[count].paths = kmalloc(sizeof(mirror_path_t)); + mirrors[count].num_paths = 1; + mirrors[count].paths[0].path = kstrdup(original->dir ? original->dir : ""); + mirrors[count].paths[0].valid = TRUE; + mirrors[count].file_name = kstrdup(original->file); + mirrors[count].full_name = str_url(original, 1); + count++; + } + + request->num_mirrors = count; + request->mirrors = reprocess_mirror_list(mirrors, &request->num_mirrors); + return MIRINFOK; +} + + +uerr_t parse_mamont_html_mirror_list(ftps_request_t * request, char *p) +{ + static const char marker[] = "href=\"ftp://"; + ftp_mirror_t *mirrors; + const char *cursor = p; + int capacity = 1; + int count = 0; + + while ((cursor = strstr(cursor, marker)) != NULL) + { + capacity++; + cursor += sizeof(marker) - 1; + } + mirrors = kmalloc(sizeof(*mirrors) * (size_t)capacity); + cursor = p; + + while ((cursor = strstr(cursor, marker)) != NULL) + { + urlinfo parsed; + const char *start = cursor + 6; + const char *end = strchr(start, '\"'); + size_t length; + char *url_string; + + if (end == NULL) + break; + cursor = end + 1; + length = (size_t)(end - start); + if (length == 0 || length >= 4096) + continue; + url_string = kmalloc(length + 1); + memcpy(url_string, start, length); + url_string[length] = '\0'; + + if (proz_parse_url(url_string, &parsed, 0) != URLOK || + parsed.proto != URLFTP) + { + kfree(url_string); + continue; + } + memset(&mirrors[count], 0, sizeof(mirrors[count])); + mirrors[count].server_name = kstrdup(parsed.host); + mirrors[count].paths = kmalloc(sizeof(mirror_path_t)); + mirrors[count].num_paths = 1; + mirrors[count].paths[0].path = kstrdup(parsed.dir ? parsed.dir : ""); + mirrors[count].paths[0].valid = TRUE; + mirrors[count].file_name = kstrdup(parsed.file); + mirrors[count].full_name = url_string; + count++; + proz_free_url(&parsed, FALSE); + } + + if (request->requested_url->proto == URLFTP || + request->requested_url->proto == URLFTPS || + request->requested_url->proto == URLSFTP) + { + urlinfo *original = request->requested_url; + memset(&mirrors[count], 0, sizeof(mirrors[count])); + mirrors[count].server_name = kstrdup(original->host); + mirrors[count].paths = kmalloc(sizeof(mirror_path_t)); + mirrors[count].num_paths = 1; + mirrors[count].paths[0].path = kstrdup(original->dir ? original->dir : ""); + mirrors[count].paths[0].valid = TRUE; + mirrors[count].file_name = kstrdup(original->file); + mirrors[count].full_name = str_url(original, 1); + count++; + } + + request->num_mirrors = count; + request->mirrors = reprocess_mirror_list(mirrors, &request->num_mirrors); + return MIRINFOK; +} + uerr_t parse_lycos_html_mirror_list(ftps_request_t * request, char *p) { struct ftp_mirror **pmirrors = &request->mirrors; diff --git a/src/http.c b/src/http.c index 908513f..72fc985 100644 --- a/src/http.c +++ b/src/http.c @@ -360,7 +360,7 @@ uerr_t http_fetch_headers(connection_t * connection, http_stat_t * hs, char *command) { uerr_t err; - int num_written, hcount, statcode, all_length; + int num_written, hcount, statcode; off_t contlen, contrange; char *hdr, *type, *all_headers; const char *error; @@ -375,14 +375,13 @@ uerr_t http_fetch_headers(connection_t * connection, http_stat_t * hs, num_written = ksend(connection->data_sock, command, strlen(command), 0, &connection->xfer_timeout); - if (num_written != strlen(command)) + if (num_written < 0 || (size_t)num_written != strlen(command)) { proz_debug(_("Failed writing HTTP request")); return WRITEERR; } all_headers = NULL; - all_length = 0; contlen = contrange = -1; statcode = -1; type = NULL; diff --git a/src/logfile.c b/src/logfile.c index ef95ae6..8d6a7f3 100644 --- a/src/logfile.c +++ b/src/logfile.c @@ -227,7 +227,7 @@ int proz_log_read_logfile(logfile * lf, download_t * download, lf->url = kmalloc(lf->url_len + 1); - if (fread(lf->url, 1, lf->url_len, fp) != lf->url_len) + if (fread(lf->url, 1, (size_t)lf->url_len, fp) != (size_t)lf->url_len) { fclose(fp); return -1; diff --git a/src/main.c b/src/main.c index 0403a50..7355dbc 100644 --- a/src/main.c +++ b/src/main.c @@ -54,8 +54,8 @@ int proz_init(int argc, char **argv) /* Gettext stuff */ setlocale(LC_ALL, ""); - bindtextdomain(PACKAGE, LOCALEDIR); - textdomain(PACKAGE); + (void)bindtextdomain(PACKAGE, LOCALEDIR); + (void)textdomain(PACKAGE); memset(&libprozrtinfo, 0, sizeof(libprozrtinfo)); libprozrtinfo.argc = argc; diff --git a/src/misc.c b/src/misc.c index 738b0a6..4a193f5 100644 --- a/src/misc.c +++ b/src/misc.c @@ -316,7 +316,7 @@ int close_sock(int *sock) /*Returns a string representation of a prozilla errror */ -char *proz_strerror(uerr_t error) +const char *proz_strerror(uerr_t error) { switch (error) { @@ -568,4 +568,3 @@ void cleanup_httpsocks(connection_t * connection) } } - diff --git a/src/prozilla.h b/src/prozilla.h index db06ddb..bcda5a9 100644 --- a/src/prozilla.h +++ b/src/prozilla.h @@ -349,7 +349,7 @@ typedef enum { } ftp_mirror_stat_t; typedef enum { - LYCOS, FILESEARCH_RU + LYCOS, FILESEARCH_RU, ARCHIE_JSON, MAMONT_HTML } ftpsearch_server_type_t; @@ -487,7 +487,7 @@ void proz_debug_delete_log(); connection_t * proz_connection_init(urlinfo * url, pthread_mutex_t * mutex); void proz_connection_set_url(connection_t * connection, urlinfo *url); -char *proz_connection_get_status_string(connection_t * connection); +const char *proz_connection_get_status_string(connection_t * connection); off_t proz_connection_get_total_bytes_got(connection_t * connection); void proz_get_url_info_loop(connection_t * connection, pthread_t *thread); off_t proz_connection_get_total_remote_bytes_got(connection_t * @@ -538,12 +538,12 @@ int proz_log_read_logfile(logfile * lf, download_t * download, boolean load_con_info); int proz_log_delete_logfile(download_t * download); int proz_log_logfile_exists(download_t * download); -char *proz_strerror(uerr_t error); +const char *proz_strerror(uerr_t error); /*Ftpsearch releated */ ftps_request_t * proz_ftps_request_init( urlinfo * requested_url, off_t file_size, - char *ftps_loc, + const char *ftps_loc, ftpsearch_server_type_t server_type, int num_req_mirrors); void proz_get_complete_mirror_list(ftps_request_t * request); diff --git a/src/url.c b/src/url.c index df9d72d..f9fedc1 100644 --- a/src/url.c +++ b/src/url.c @@ -134,7 +134,7 @@ enum { #define ARRAY_SIZE(array) (sizeof(array) / sizeof(*(array))) -const static unsigned char urlchr_table[256] = { +static const unsigned char urlchr_table[256] = { U, U, U, U, U, U, U, U, /* NUL SOH STX ETX EOT ENQ ACK BEL */ U, U, U, U, U, U, U, U, /* BS HT LF VT FF CR SO SI */ U, U, U, U, U, U, U, U, /* DLE DC1 DC2 DC3 DC4 NAK SYN ETB */ @@ -303,7 +303,7 @@ char *encode_string(const char *s) URLUNKNOWN if not. */ uerr_t urlproto(const char *url) { - int i; + size_t i; for (i = 0; i < ARRAY_SIZE(sup_protos); i++) if (!strncasecmp(url, sup_protos[i].name, strlen(sup_protos[i].name))) @@ -613,7 +613,8 @@ static uerr_t parse_uname(const char *url, char **user, char **passwd) char *str_url(const urlinfo * u, int hide) { char *res, *host, *user, *passwd, *proto_name, *dir, *file; - int i, l, ln, lu, lh, lp, lf, ld; + size_t i; + int l, ln, lu, lh, lp, lf, ld; unsigned short proto_default_port; /* Look for the protocol name. */ @@ -725,7 +726,8 @@ char *str_url(const urlinfo * u, int hide) form. */ uerr_t proz_parse_url(const char *url, urlinfo * u, int strict) { - int i, l, abs_ftp; + size_t i; + int l, abs_ftp; int recognizable; /* Recognizable URL is the one where the protocol name was explicitly named, i.e. it wasn't deduced from @@ -757,9 +759,9 @@ uerr_t proz_parse_url(const char *url, urlinfo * u, int strict) them for now). */ if (recognizable) l += skip_uname(url + l); - for (i = l; url[i] && url[i] != ':' && url[i] != '/'; i++) + for (i = (size_t)l; url[i] && url[i] != ':' && url[i] != '/'; i++) ; - if (i == l) + if (i == (size_t)l) return URLBADHOST; /* Get the hostname. */ u->host = strdupdelim(url + l, url + i); @@ -791,7 +793,7 @@ uerr_t proz_parse_url(const char *url, urlinfo * u, int strict) u->proto = type = URLHTTP; if (!u->port) { - int ind; + size_t ind; for (ind = 0; ind < ARRAY_SIZE(sup_protos); ind++) if (sup_protos[ind].ind == type) break; @@ -937,12 +939,6 @@ urlpos *add_url(urlpos * l, const char *url, const char *file) } -/*This will copy a url structure to another */ -void url_cpy(urlinfo * src, urlinfo * dest) -{ -} - - /* Find the last occurrence of character C in the range [b, e), or NULL, if none are present. This is almost completely equivalent to { *e = '\0'; return strrchr(b); }, except that it doesn't change diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 3ded262..a72663f 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -1,3 +1,7 @@ add_executable(url_parse_test url_parse_test.c) target_link_libraries(url_parse_test PRIVATE prozilla) add_test(NAME url_parse COMMAND url_parse_test) + +add_executable(ftpsearch_parse_test ftpsearch_parse_test.c) +target_link_libraries(ftpsearch_parse_test PRIVATE prozilla) +add_test(NAME ftpsearch_parse COMMAND ftpsearch_parse_test) diff --git a/tests/ftpsearch_parse_test.c b/tests/ftpsearch_parse_test.c new file mode 100644 index 0000000..8e0e2fd --- /dev/null +++ b/tests/ftpsearch_parse_test.c @@ -0,0 +1,40 @@ +#include +#include + +#include "prozilla.h" + +uerr_t parse_archie_json_mirror_list(ftps_request_t *request, char *data); +uerr_t parse_mamont_html_mirror_list(ftps_request_t *request, char *data); + +static void init_request(ftps_request_t *request, urlinfo *requested_url) +{ + memset(request, 0, sizeof(*request)); + memset(requested_url, 0, sizeof(*requested_url)); + requested_url->proto = URLHTTP; + request->requested_url = requested_url; +} + +int main(void) +{ + ftps_request_t request; + urlinfo requested_url; + char archie_json[] = + "{\"hits\":2,\"results\":[" + "{\"URL\":\"ftp://ftp.example.org/pub/file.zip\"}," + "{\"URL\":\"ftps://secure.example.org/releases/file.zip\"}]}"; + char mamont_html[] = + "file.zip"; + + init_request(&request, &requested_url); + assert(parse_archie_json_mirror_list(&request, archie_json) == MIRINFOK); + assert(request.num_mirrors == 2); + assert(strcmp(request.mirrors[0].server_name, "ftp.example.org") == 0); + assert(strcmp(request.mirrors[1].server_name, "secure.example.org") == 0); + + init_request(&request, &requested_url); + assert(parse_mamont_html_mirror_list(&request, mamont_html) == MIRINFOK); + assert(request.num_mirrors == 1); + assert(strcmp(request.mirrors[0].server_name, "mirror.example.net") == 0); + assert(strcmp(request.mirrors[0].file_name, "file.zip") == 0); + return 0; +}