Add secure libcurl transfer backend

This commit is contained in:
Mario Fetka
2026-07-14 17:01:03 +02:00
parent f3e6580ce5
commit 4a80e32f3e
19 changed files with 361 additions and 88 deletions
+7 -1
View File
@@ -1,6 +1,8 @@
cmake_minimum_required(VERSION 3.20)
project(libprozilla VERSION 1.1.1 LANGUAGES C)
project(libprozilla VERSION 1.2.0 LANGUAGES C)
include(CTest)
include(GNUInstallDirs)
include(CheckIncludeFile)
@@ -8,6 +10,7 @@ include(CheckFunctionExists)
include(CMakePackageConfigHelpers)
find_package(Threads REQUIRED)
find_package(CURL 8.17 REQUIRED)
find_package(Intl)
set(CMAKE_C_STANDARD 11)
@@ -39,6 +42,9 @@ configure_file(cmake/config.h.in generated/config.h)
add_subdirectory(src)
add_subdirectory(po)
add_subdirectory(docs)
if(BUILD_TESTING)
add_subdirectory(tests)
endif()
configure_package_config_file(cmake/libprozillaConfig.cmake.in
"${CMAKE_CURRENT_BINARY_DIR}/libprozillaConfig.cmake"
+1
View File
@@ -1,4 +1,5 @@
@PACKAGE_INIT@
include(CMakeFindDependencyMacro)
find_dependency(Threads)
find_dependency(CURL 8.17)
include("${CMAKE_CURRENT_LIST_DIR}/libprozillaTargets.cmake")
+3 -2
View File
@@ -1,8 +1,8 @@
add_library(prozilla
connect.c connection.c debug.c download.c ftp-retr.c ftp.c ftpparse.c
ftpsearch.c http-retr.c http.c logfile.c main.c misc.c netrc.c ping.c url.c)
ftpsearch.c http-retr.c http.c curl-retr.c logfile.c main.c misc.c netrc.c ping.c url.c)
add_library(libprozilla::prozilla ALIAS prozilla)
set_target_properties(prozilla PROPERTIES VERSION 1.0.1 SOVERSION 1)
set_target_properties(prozilla PROPERTIES VERSION ${PROJECT_VERSION} SOVERSION 1)
target_include_directories(prozilla
PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
@@ -11,6 +11,7 @@ target_include_directories(prozilla
target_compile_definitions(prozilla PRIVATE HAVE_CONFIG_H=1 _GNU_SOURCE LOCALEDIR="${LOCALEDIR}")
target_compile_options(prozilla PRIVATE $<$<COMPILE_LANG_AND_ID:C,GNU,Clang>:-Wall;-Wextra>)
target_link_libraries(prozilla PUBLIC Threads::Threads)
target_link_libraries(prozilla PRIVATE CURL::libcurl)
if(Intl_FOUND)
target_link_libraries(prozilla PRIVATE Intl::Intl)
endif()
+2
View File
@@ -25,6 +25,8 @@
#ifndef COMMON_H
#define COMMON_H
#include <inttypes.h>
#if HAVE_CONFIG_H
# include <config.h>
+17 -10
View File
@@ -25,6 +25,7 @@
#include "prozilla.h"
#include "connection.h"
#include "curl-retr.h"
#include "misc.h"
#include "connect.h"
#include "ftp.h"
@@ -208,8 +209,8 @@ uerr_t connection_retr_fsize_not_known(connection_t * connection,
connection_show_message(connection,
_("download for this connection completed"
"%s : %ld received"), connection->localfile,
connection->remote_bytes_received);
"%s : %jd received"), connection->localfile,
(intmax_t) connection->remote_bytes_received);
return FILEGETOK;
}
@@ -290,8 +291,8 @@ uerr_t connection_retr_fsize_known(connection_t * connection,
connection_show_message(connection,
_("download for this connection completed"
"%s : %ld received"), connection->localfile,
connection->remote_bytes_received);
"%s : %jd received"), connection->localfile,
(intmax_t) connection->remote_bytes_received);
return FILEGETOK;
}
@@ -305,11 +306,13 @@ int connection_load_resume_info(connection_t * connection)
{
if (connection->remote_startpos - connection->orig_remote_startpos != connection->remote_bytes_received)
{
proz_debug("connection->remote start pos before loading %ld", connection->remote_startpos);
proz_debug("connection->remote start pos before loading %jd",
(intmax_t) connection->remote_startpos);
//connection->remote_startpos +=connection->remote_bytes_received;
connection->remote_startpos += (connection->remote_bytes_received - (connection->remote_startpos - connection->orig_remote_startpos));
proz_debug("connection->remote start pos after loading %ld", connection->remote_startpos);
proz_debug("connection->remote start pos after loading %jd",
(intmax_t) connection->remote_startpos);
}
return 1;
}
@@ -455,11 +458,11 @@ void get_url_info_loop(connection_t * connection)
switch (connection->u.proto)
{
case URLHTTP:
connection->err = http_get_url_info_loop(connection);
break;
case URLFTP:
connection->err = ftp_get_url_info_loop(connection);
case URLHTTPS:
case URLFTPS:
case URLSFTP:
connection->err = curl_get_url_info(connection);
break;
default:
@@ -505,6 +508,10 @@ void get_url_info_loop(connection_t * connection)
}
} while (connection->err == NEWLOCATION);
pthread_mutex_lock(&connection->access_mutex);
connection->running = FALSE;
pthread_mutex_unlock(&connection->access_mutex);
return;
}
+210
View File
@@ -0,0 +1,210 @@
#include "common.h"
#include "prozilla.h"
#include "connection.h"
#include "curl-retr.h"
#include "debug.h"
#include <curl/curl.h>
#include <limits.h>
typedef struct {
connection_t *connection;
CURL *curl;
int write_failed;
int require_partial_response;
size_t bytes_written;
} curl_write_context;
static CURLcode configure_curl(CURL *curl, connection_t *connection)
{
char known_hosts[PATH_MAX];
proxy_info *proxy = NULL;
curl_easy_setopt(curl, CURLOPT_URL, connection->u.url);
curl_easy_setopt(curl, CURLOPT_USERAGENT, connection->user_agent);
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
curl_easy_setopt(curl, CURLOPT_MAXREDIRS, 10L);
curl_easy_setopt(curl, CURLOPT_FAILONERROR, 1L);
curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT,
(long) connection->conn_timeout.tv_sec);
curl_easy_setopt(curl, CURLOPT_TIMEOUT,
(long) connection->xfer_timeout.tv_sec);
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 1L);
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 2L);
curl_easy_setopt(curl, CURLOPT_PROTOCOLS_STR, "http,https,ftp,ftps,sftp");
curl_easy_setopt(curl, CURLOPT_REDIR_PROTOCOLS_STR,
"http,https,ftp,ftps,sftp");
if (connection->u.user)
curl_easy_setopt(curl, CURLOPT_USERNAME, connection->u.user);
if (connection->u.passwd)
curl_easy_setopt(curl, CURLOPT_PASSWORD, connection->u.passwd);
if ((connection->u.proto == URLHTTP || connection->u.proto == URLHTTPS)
&& connection->http_proxy && connection->http_proxy->use_proxy)
proxy = connection->http_proxy;
else if ((connection->u.proto == URLFTP || connection->u.proto == URLFTPS)
&& connection->ftp_proxy && connection->ftp_proxy->use_proxy
&& connection->ftp_proxy->type == HTTPPROXY)
proxy = connection->ftp_proxy;
if (proxy && proxy->proxy_url.url)
{
curl_easy_setopt(curl, CURLOPT_PROXY, proxy->proxy_url.url);
if (proxy->username)
curl_easy_setopt(curl, CURLOPT_PROXYUSERNAME, proxy->username);
if (proxy->passwd)
curl_easy_setopt(curl, CURLOPT_PROXYPASSWORD, proxy->passwd);
}
if (connection->u.proto == URLSFTP)
{
if (snprintf(known_hosts, sizeof(known_hosts), "%s/.ssh/known_hosts",
libprozrtinfo.home_dir) >= (int) sizeof(known_hosts)
|| access(known_hosts, R_OK) != 0)
return CURLE_PEER_FAILED_VERIFICATION;
curl_easy_setopt(curl, CURLOPT_SSH_KNOWNHOSTS, known_hosts);
}
return CURLE_OK;
}
static uerr_t map_curl_error(CURLcode result, long response)
{
if (result == CURLE_OK && response < 400)
return HOK;
if (response == 401 || response == 403
|| result == CURLE_LOGIN_DENIED)
return HAUTHFAIL;
if (response == 404 || result == CURLE_REMOTE_FILE_NOT_FOUND)
return HTTPNSFOD;
if (result == CURLE_WRITE_ERROR)
return FWRITEERR;
return HERR;
}
uerr_t curl_get_url_info(connection_t *connection)
{
CURL *curl = curl_easy_init();
CURLcode result;
curl_off_t length = -1;
long response = 0;
if (!curl)
return HERR;
result = configure_curl(curl, connection);
if (result == CURLE_OK)
{
curl_easy_setopt(curl, CURLOPT_NOBODY, 1L);
result = curl_easy_perform(curl);
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response);
curl_easy_getinfo(curl, CURLINFO_CONTENT_LENGTH_DOWNLOAD_T, &length);
}
curl_easy_cleanup(curl);
if (result != CURLE_OK || response >= 400)
return map_curl_error(result, response);
if (length < 0 || (curl_off_t) (off_t) length != length)
connection->main_file_size = -1;
else
connection->main_file_size = (off_t) length;
connection->hs.contlen = connection->main_file_size;
connection->hs.accept_ranges = 1;
connection->resume_support = TRUE;
return HOK;
}
static size_t curl_write(void *data, size_t size, size_t count, void *opaque)
{
curl_write_context *ctx = opaque;
size_t bytes;
long response = 0;
if (size != 0 && count > SIZE_MAX / size)
return 0;
bytes = size * count;
if (ctx->require_partial_response)
{
curl_easy_getinfo(ctx->curl, CURLINFO_RESPONSE_CODE, &response);
if (response != 206)
return 0;
}
if (write_data_with_lock(ctx->connection, data, 1, bytes) != bytes)
{
ctx->write_failed = 1;
return 0;
}
pthread_mutex_lock(&ctx->connection->access_mutex);
ctx->connection->remote_bytes_received += (off_t) bytes;
pthread_mutex_unlock(&ctx->connection->access_mutex);
ctx->bytes_written += bytes;
connection_calc_ratebps(ctx->connection);
connection_throttle_bps(ctx->connection);
return bytes;
}
static uerr_t curl_get_file(connection_t *connection)
{
CURL *curl = curl_easy_init();
CURLcode result;
curl_write_context ctx = { connection, curl, 0, 0, 0 };
char range[96];
long response = 0;
if (!curl)
return HERR;
result = configure_curl(curl, connection);
if (result == CURLE_OK)
{
if (connection->remote_endpos > connection->remote_startpos)
{
snprintf(range, sizeof(range), "%jd-%jd",
(intmax_t) connection->remote_startpos,
(intmax_t) (connection->remote_endpos - 1));
curl_easy_setopt(curl, CURLOPT_RANGE, range);
if (connection->u.proto == URLHTTP
|| connection->u.proto == URLHTTPS)
ctx.require_partial_response = 1;
}
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, curl_write);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &ctx);
connection_change_status(connection, DOWNLOADING);
gettimeofday(&connection->time_begin, NULL);
result = curl_easy_perform(curl);
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response);
}
curl_easy_cleanup(curl);
if (ctx.write_failed)
return FWRITEERR;
if (ctx.require_partial_response && response != 206)
return CANTRESUME;
if (connection->remote_endpos > connection->remote_startpos
&& (off_t) ctx.bytes_written
!= connection->remote_endpos - connection->remote_startpos)
return READERR;
if (result == CURLE_OK && response < 400)
{
connection_change_status(connection, COMPLETED);
return HOK;
}
connection_change_status(connection, REMOTEFATAL);
return map_curl_error(result, response);
}
void *curl_loop(void *opaque)
{
connection_t *connection = opaque;
boolean retry = FALSE;
do {
if (retry)
delay_ms((int) connection->retry_delay.tv_sec * 1000);
connection->err = curl_get_file(connection);
connection->attempts++;
if (connection->err == HOK || connection->err == FWRITEERR
|| connection->err == HTTPNSFOD || connection->err == HAUTHFAIL)
return (void *) (intptr_t) connection->err;
retry = TRUE;
} while (connection->max_attempts == 0
|| connection->attempts < connection->max_attempts);
return (void *) (intptr_t) connection->err;
}
+9
View File
@@ -0,0 +1,9 @@
#ifndef CURL_RETR_H
#define CURL_RETR_H
#include "prozilla.h"
uerr_t curl_get_url_info(connection_t *connection);
void *curl_loop(void *connection);
#endif
+7 -16
View File
@@ -24,6 +24,7 @@
#include "common.h"
#include "download.h"
#include "curl-retr.h"
#include "ftp-retr.h"
#include "http-retr.h"
#include "logfile.h"
@@ -305,25 +306,14 @@ void proz_download_start_downloads(download_t * download,
switch (download->pconnections[i]->u.proto)
{
case URLHTTP:
/* http_loop(&download->connections[i]); */
if (pthread_create(&download->threads[i], NULL,
(void *)&http_loop,
(void *)(download->pconnections[i])) != 0)
proz_die(_("Error: Not enough system resources"));
break;
case URLFTP:
/* ftp_loop(&download->connections[i]); */
case URLHTTPS:
case URLFTPS:
case URLSFTP:
if (pthread_create(&download->threads[i], NULL,
(void *)&ftp_loop,
curl_loop,
(void *)(download->pconnections[i])) != 0)
proz_die(_("Error: Not enough system resources"));
break;
default:
@@ -884,7 +874,8 @@ off_t proz_download_get_total_remote_bytes_got(download_t * download)
for (i = 0; i < download->num_connections; i++)
{
proz_debug("DOWNLOAD_TOTAL_BYTES_RECV=%lld for connection %d", total_bytes_recv, i);
proz_debug("DOWNLOAD_TOTAL_BYTES_RECV=%jd for connection %d",
(intmax_t) total_bytes_recv, i);
total_bytes_recv +=
proz_connection_get_total_remote_bytes_got(download->
pconnections[i]);
+1 -1
View File
@@ -123,7 +123,7 @@ uerr_t proz_ftp_get_file(connection_t * connection)
user = user ? user : libprozrtinfo.ftp_default_user;
passwd = passwd ? passwd : libprozrtinfo.ftp_default_passwd;
proz_debug(_("Logging in as user %s with password %s."), user, passwd);
proz_debug(_("Logging in as user %s."), user);
connection_change_status(connection, LOGGININ);
+23 -26
View File
@@ -31,6 +31,7 @@
#include "debug.h"
#include "ftpparse.h"
#include "ftp.h"
#include <inttypes.h>
/* #define UNIMPLEMENTED_CMD(a) ((a == 500) || (a == 502) || (a == 504)) */
@@ -188,14 +189,17 @@ uerr_t ftp_get_line(connection_t * connection, char *line)
connection->szBuffer = &ch;
while ((iBuffLen < BUFFER_SIZE)
while ((iBuffLen < BUFFER_SIZE - 1)
&& ((ret = ftp_check_msg(connection, 1)) > 0))
{
/* Now get the full string. */
iLen = ftp_read_msg(connection, 1);
if (iLen != 1)
return FTPERR;
{
connection->szBuffer = NULL;
return FTPERR;
}
iBuffLen += iLen;
*szptr = ch;
@@ -207,13 +211,14 @@ uerr_t ftp_get_line(connection_t * connection, char *line)
/* Check for error returned in ftp_check_msg(). */
if (ret == -1)
return FTPERR;
{
connection->szBuffer = NULL;
return FTPERR;
}
/* if zero bytes were found that means the server has closed the connection*/
if (ret == 0)
*(szptr) = '\0';
else
*(szptr + 1) = '\0';
*szptr = '\0';
connection->szBuffer = NULL;
proz_debug(_("Received: %s"), line);
@@ -393,7 +398,7 @@ uerr_t ftp_rest(connection_t * connection, off_t bytes)
{
uerr_t err;
err = ftp_send_msg(connection, "REST %lld\r\n", bytes);
err = ftp_send_msg(connection, "REST %jd\r\n", (intmax_t) bytes);
if (err != FTPOK)
return err;
@@ -445,7 +450,6 @@ uerr_t ftp_pwd(connection_t * connection, char *dir)
{
uerr_t err;
char *r, *l;
char szBuffer[FTP_BUFFER_SIZE];
err = ftp_send_msg(connection, "PWD\r\n");
if (err != FTPOK)
@@ -477,7 +481,7 @@ uerr_t ftp_pwd(connection_t * connection, char *dir)
if ((r = strchr(connection->serv_ret_lines->line, ' ')) != NULL)
{
*r = '\0';
strcpy(dir, szBuffer);
strcpy(dir, r + 1);
*r = ' ';
}
}
@@ -491,6 +495,8 @@ uerr_t ftp_pwd(connection_t * connection, char *dir)
uerr_t ftp_size(connection_t * connection, const char *file, off_t *size)
{
uerr_t err;
char *end;
intmax_t parsed_size;
*size = -1;
@@ -505,7 +511,12 @@ uerr_t ftp_size(connection_t * connection, const char *file, off_t *size)
/* Now lets figure out what happened. */
if (connection->serv_ret_lines->line[0] == '2')
{
sscanf(connection->serv_ret_lines->line + 3, "%lld", size);
errno = 0;
parsed_size = strtoimax(connection->serv_ret_lines->line + 3, &end, 10);
if (errno != 0 || end == connection->serv_ret_lines->line + 3
|| parsed_size < 0 || (intmax_t) (off_t) parsed_size != parsed_size)
return FTPSIZEFAIL;
*size = (off_t) parsed_size;
return FTPOK;
}
else if (connection->serv_ret_lines->line[0] == '5') /* An error occured. */
@@ -902,21 +913,7 @@ uerr_t proz_ftp_get_url_info(connection_t * connection)
user = user ? user : libprozrtinfo.ftp_default_user;
passwd = passwd ? passwd : libprozrtinfo.ftp_default_passwd;
if (strcmp(user, "anonymous") == 0)
connection_show_message(connection,
_("Logging in as user %s with password %s"),
user, passwd);
else
{
int pwd_len = strlen(passwd);
char *tmp_pwd = (char *)kmalloc(pwd_len + 1);
memset(tmp_pwd, 'x', pwd_len);
tmp_pwd[pwd_len] = 0;
connection_show_message(connection,
_("Logging in as user %s with password %s"),
user, tmp_pwd);
kfree(tmp_pwd);
}
connection_show_message(connection, _("Logging in as user %s"), user);
init_response(connection);
err = ftp_login(connection, user, passwd);
+7 -8
View File
@@ -121,9 +121,9 @@ urlinfo *prepare_lycos_url(ftps_request_t * request, char *ftps_loc,
(char *)kmalloc(lycos_url_len + strlen(request->file_name) + 300);
sprintf(lycos_url_buf,
"%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",
"%s?form=advanced&query=%s&doit=Search&type=Exact+search&hits=%d&matches=&hitsprmatch=&limdom=&limpath=&limsize1=%jd&limsize2=%jd&f1=Host&f2=Path&f3=Size&f4=-&f5=-&f6=-&header=none&sort=none&trlen=20",
ftps_loc, request->file_name, num_req_mirrors,
request->file_size, request->file_size);
(intmax_t) request->file_size, (intmax_t) request->file_size);
/* Debugging purposes */
/*sprintf(lycos_url_buf,"localhost/search.html"); */
@@ -161,9 +161,9 @@ urlinfo *prepare_filesearching_url(ftps_request_t * request, char *ftps_loc,
(char *)kmalloc(filesearching_url_len + strlen(request->file_name) + 300);
sprintf(filesearching_url_buf,
"%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",
"%s?q=%s&l=en&t=f&e=on&m=%d&o=n&s=on&s1=%jd&s2=%jd&d=&p=&p2=&x=10&y=14",
ftps_loc, request->file_name, num_req_mirrors,
request->file_size, request->file_size);
(intmax_t) request->file_size, (intmax_t) request->file_size);
/* Debugging purposes */
/* sprintf(filesearching_url_buf,"localhost/fs.html"); */
@@ -287,7 +287,7 @@ uerr_t parse_lycos_html_mirror_list(ftps_request_t * request, char *p)
strncpy(p1, i + 5, j - i - 5);
p1[j - i - 5 + 1] = 0;
proz_debug("\nstring len= %ld", strlen(p1));
proz_debug("\nstring len= %zu", strlen(p1));
p2 = p1;
@@ -464,7 +464,7 @@ uerr_t parse_filesearching_html_mirror_list(ftps_request_t * request, char *p)
p1 = kmalloc((j - i - 16) + 100);
strncpy(p1, i + 16, j - i - 16);
proz_debug("\nstring len= %ld", strlen(p1));
proz_debug("\nstring len= %zu", strlen(p1));
proz_debug("\nstring value= %s", p1);
p1[j - i - 16 + 1] = 0;
@@ -640,8 +640,7 @@ uerr_t get_mirror_info(connection_t * connection, char **ret_buf)
{
/* 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);
proz_debug(_("Authenticating as user %s"), user);
}
else
www_auth = 0;
+9 -7
View File
@@ -28,6 +28,7 @@
#include "debug.h"
#include "http.h"
#include "http-retr.h"
#include <inttypes.h>
/* Will download a portion of/or the full file from the connection->url.
*/
@@ -117,8 +118,7 @@ uerr_t proz_http_get_file(connection_t * connection)
{
/* 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);
proz_debug(_("Authenticating as user %s"), user);
}
else
www_auth = 0;
@@ -147,8 +147,10 @@ uerr_t proz_http_get_file(connection_t * connection)
if (connection->hs.accept_ranges == 1)
{
range = (char *)alloca(18 + 64);
sprintf(range, "Range: bytes=%lld-\r\n", connection->remote_startpos);
proz_debug("Range = %lld Range = %s", connection->remote_startpos, range);
snprintf(range, 18 + 64, "Range: bytes=%jd-\r\n",
(intmax_t) connection->remote_startpos);
proz_debug("Range = %jd Range = %s",
(intmax_t) connection->remote_startpos, range);
}
if (connection->u.referer)
@@ -423,8 +425,7 @@ uerr_t ftp_get_file_from_http_proxy(connection_t * connection)
{
/* 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);
proz_debug(_("Authenticating as user %s"), user);
}
else
www_auth = 0;
@@ -442,7 +443,8 @@ uerr_t ftp_get_file_from_http_proxy(connection_t * connection)
if (connection->hs.accept_ranges == 1)
{
range = (char *)alloca(18 + 64);
sprintf(range, "Range: bytes=%lld-\r\n", connection->remote_startpos);
snprintf(range, 18 + 64, "Range: bytes=%jd-\r\n",
(intmax_t) connection->remote_startpos);
}
+4 -6
View File
@@ -261,7 +261,7 @@ off_t hgetlen(const char *hdr)
for (len = 0; isdigit(*hdr); hdr++)
len = 10 * len + (*hdr - '0');
proz_debug("contenlen %s contentlen %lld", *hdr, len);
proz_debug("content length %jd", (intmax_t) len);
return len;
}
@@ -297,7 +297,7 @@ off_t hgetrange(const char *hdr)
for (len = 0; isdigit(*hdr); hdr++)
len = 10 * len + (*hdr - '0');
proz_debug("range %s range %lld", *hdr, len);
proz_debug("range %jd", (intmax_t) len);
return len;
}
@@ -614,8 +614,7 @@ uerr_t proz_http_get_url_info(connection_t * connection)
{
/* 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);
proz_debug(_("Authenticating as user %s"), user);
}
else
www_auth = 0;
@@ -829,8 +828,7 @@ uerr_t ftp_get_url_info_from_http_proxy(connection_t * connection)
{
/* 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);
proz_debug(_("Authenticating as user %s"), user);
}
else
www_auth = 0;
+5
View File
@@ -27,6 +27,7 @@
#include "misc.h"
//#include "getopt.h"
#include "debug.h"
#include <curl/curl.h>
@@ -48,6 +49,9 @@ int proz_init(int argc, char **argv)
{
// int c;
if (curl_global_init(CURL_GLOBAL_DEFAULT) != CURLE_OK)
return 0;
/* Gettext stuff */
setlocale(LC_ALL, "");
bindtextdomain(PACKAGE, LOCALEDIR);
@@ -125,6 +129,7 @@ void proz_shutdown(void)
kfree(libprozrtinfo.dl_dir);
kfree(libprozrtinfo.output_dir);
kfree(libprozrtinfo.log_dir);
curl_global_cleanup();
}
/******************************************************************************
+7 -4
View File
@@ -45,7 +45,7 @@ void *kmalloc(size_t size)
ret = malloc(size);
if (ret == NULL)
proz_die(_("Failed to malloc() %lu bytes."), size);
proz_die(_("Failed to malloc() %zu bytes."), size);
return ret;
}
@@ -60,7 +60,7 @@ void *krealloc(void *ptr, size_t new_size)
ret = realloc(ptr, new_size);
if (!ret)
proz_die(_("Failed to realloc() %lu bytes."), new_size);
proz_die(_("Failed to realloc() %zu bytes."), new_size);
return ret;
}
@@ -507,6 +507,11 @@ void cleanup_socks(void *cdata)
cleanup_ftpsocks(connection);
break;
case URLHTTPS:
case URLFTPS:
case URLSFTP:
break;
default:
proz_die(_("Error: unsupported protocol"));
}
@@ -564,5 +569,3 @@ void cleanup_httpsocks(connection_t * connection)
}
+7 -1
View File
@@ -81,7 +81,10 @@ typedef enum {
FILEISDIR,
MIRINFOK, MIRPARSEOK, MIRPARSEFAIL, FILEGETOK,
/*Related to file joining */
JOININPROGRESS, JOINDONE, JOINERR
JOININPROGRESS, JOINDONE, JOINERR,
/* Secure protocols are appended to preserve the historical ABI values. */
URLHTTPS, URLFTPS, URLSFTP
} uerr_t;
@@ -91,6 +94,9 @@ typedef enum {
#define DEFAULT_FTP_PORT 21
#define DEFAULT_HTTP_PORT 80
#define DEFAULT_HTTPS_PORT 443
#define DEFAULT_FTPS_PORT 990
#define DEFAULT_SFTP_PORT 22
/* This is used when no password is found or specified. */
#define DEFAULT_FTP_USER "anonymous"
+11 -6
View File
@@ -83,7 +83,10 @@ char *protostrings[] = {
/* Similar to former, but for supported protocols: */
proto_t sup_protos[] = {
{ "http://", URLHTTP, DEFAULT_HTTP_PORT },
{ "ftp://", URLFTP, DEFAULT_FTP_PORT }
{ "ftp://", URLFTP, DEFAULT_FTP_PORT },
{ "https://", URLHTTPS, DEFAULT_HTTPS_PORT },
{ "ftps://", URLFTPS, DEFAULT_FTPS_PORT },
{ "sftp://", URLSFTP, DEFAULT_SFTP_PORT }
/* { "file://", URLFILE, DEFAULT_FTP_PORT } */
};
@@ -637,7 +640,8 @@ char *str_url(const urlinfo * u, int hide)
else
passwd = encode_string(u->passwd);
}
if (u->proto == URLFTP && *dir == '/')
if ((u->proto == URLFTP || u->proto == URLFTPS || u->proto == URLSFTP)
&& *dir == '/')
{
char *tmp = (char *)kmalloc(strlen(dir) + 3);
/*sprintf (tmp, "%%2F%s", dir + 1); */
@@ -797,12 +801,12 @@ uerr_t proz_parse_url(const char *url, urlinfo * u, int strict)
/* Some delimiter troubles... */
if (url[i] == '/' && url[i - 1] != ':')
++i;
if (type == URLHTTP)
if (type == URLHTTP || type == URLHTTPS)
while (url[i] && url[i] == '/')
++i;
u->path = (char *)kmalloc(strlen(url + i) + 8);
strcpy(u->path, url + i);
if (type == URLFTP)
if (type == URLFTP || type == URLFTPS || type == URLSFTP)
{
u->ftp_type = process_ftp_type(u->path);
/* #### We don't handle type `d' correctly yet. */
@@ -825,14 +829,15 @@ uerr_t proz_parse_url(const char *url, urlinfo * u, int strict)
/* Simplify the directory. */
path_simplify(u->dir);
/* Remove the leading `/' in HTTP. */
if (type == URLHTTP && *u->dir == '/')
if ((type == URLHTTP || type == URLHTTPS) && *u->dir == '/')
strcpy(u->dir, u->dir + 1);
/* Strip trailing `/'. */
l = strlen(u->dir);
if (l > 1 && u->dir[l - 1] == '/')
u->dir[l - 1] = '\0';
/* Re-create the path: */
abs_ftp = (u->proto == URLFTP && *u->dir == '/');
abs_ftp = ((u->proto == URLFTP || u->proto == URLFTPS
|| u->proto == URLSFTP) && *u->dir == '/');
/* sprintf (u->path, "%s%s%s%s", abs_ftp ? "%2F": "/",
abs_ftp ? (u->dir + 1) : u->dir, *u->dir ? "/" : "", u->file); */
strcpy(u->path, abs_ftp ? "%2F" : "/");
+3
View File
@@ -0,0 +1,3 @@
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)
+28
View File
@@ -0,0 +1,28 @@
#include <prozilla.h>
#include <url.h>
#include <stdio.h>
static int check(const char *text, uerr_t protocol, unsigned short port)
{
urlinfo url;
uerr_t result = proz_parse_url(text, &url, 0);
if (result != URLOK || url.proto != protocol || url.port != port)
{
fprintf(stderr, "failed to parse %s (result=%d protocol=%d port=%u)\n",
text, result, url.proto, url.port);
return 1;
}
proz_free_url(&url, 0);
return 0;
}
int main(void)
{
return check("http://example.invalid/file", URLHTTP, 80)
|| check("https://example.invalid/file", URLHTTPS, 443)
|| check("ftp://example.invalid/file", URLFTP, 21)
|| check("ftps://example.invalid/file", URLFTPS, 990)
|| check("sftp://example.invalid/file", URLSFTP, 22);
}