mirror of
https://github.com/profanity-im/profanity.git
synced 2024-11-03 19:37:16 -05:00
Refactor to use file stream
This commit is contained in:
parent
3370418d71
commit
39c3290613
@ -4811,7 +4811,6 @@ cmd_sendfile(ProfWin* window, const char* const command, gchar** args)
|
|||||||
{
|
{
|
||||||
jabber_conn_status_t conn_status = connection_get_status();
|
jabber_conn_status_t conn_status = connection_get_status();
|
||||||
char *filename = args[0];
|
char *filename = args[0];
|
||||||
char *filepath = NULL;
|
|
||||||
unsigned char *key = NULL;
|
unsigned char *key = NULL;
|
||||||
|
|
||||||
// expand ~ to $HOME
|
// expand ~ to $HOME
|
||||||
@ -4823,7 +4822,15 @@ cmd_sendfile(ProfWin* window, const char* const command, gchar** args)
|
|||||||
filename = strdup(filename);
|
filename = strdup(filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
filepath = strdup(filename);
|
if (access(filename, R_OK) != 0) {
|
||||||
|
cons_show_error("Uploading '%s' failed: File not found!", filename);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!is_regular_file(filename)) {
|
||||||
|
cons_show_error("Uploading '%s' failed: Not a file!", filename);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
if (conn_status != JABBER_CONNECTED) {
|
if (conn_status != JABBER_CONNECTED) {
|
||||||
cons_show("You are not currently connected.");
|
cons_show("You are not currently connected.");
|
||||||
@ -4835,6 +4842,14 @@ cmd_sendfile(ProfWin* window, const char* const command, gchar** args)
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int fd;
|
||||||
|
if ((fd = open(filename, O_RDONLY)) == -1) {
|
||||||
|
cons_show_error("Unable to open file descriptor for '%s'.", filename);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
FILE *fh = fdopen(fd, "rb");
|
||||||
|
|
||||||
switch (window->type) {
|
switch (window->type) {
|
||||||
case WIN_MUC:
|
case WIN_MUC:
|
||||||
case WIN_CHAT:
|
case WIN_CHAT:
|
||||||
@ -4844,37 +4859,14 @@ cmd_sendfile(ProfWin* window, const char* const command, gchar** args)
|
|||||||
|
|
||||||
if (chatwin->is_omemo && !prefs_get_boolean(PREF_OMEMO_SENDFILE)) {
|
if (chatwin->is_omemo && !prefs_get_boolean(PREF_OMEMO_SENDFILE)) {
|
||||||
int tmpfd;
|
int tmpfd;
|
||||||
GError *err = NULL;
|
if ((tmpfd = g_file_open_tmp("profanity.XXXXXX", NULL, NULL)) == -1) {
|
||||||
char *tmppath = NULL;
|
|
||||||
|
|
||||||
tmpfd = g_file_open_tmp("profanity.XXXXXX", &tmppath, &err);
|
|
||||||
if (err != NULL) {
|
|
||||||
cons_show_error("Unable to create temporary file for encrypted transfer.");
|
cons_show_error("Unable to create temporary file for encrypted transfer.");
|
||||||
win_println(window, THEME_ERROR, "-", "Unable to create temporary file for encrypted transfer.");
|
win_println(window, THEME_ERROR, "-", "Unable to create temporary file for encrypted transfer.");
|
||||||
|
fclose(fh);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct stat tmpst;
|
FILE *tmpfh = fdopen(tmpfd, "wb");
|
||||||
if (fstat(tmpfd, &tmpst)) {
|
|
||||||
cons_show_error("Cannot determine file size.");
|
|
||||||
win_println(window, THEME_ERROR, "-", "Cannot determine file size.");
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
FILE *tmpfile = fdopen(tmpfd, "wb");
|
|
||||||
if (tmpfile == NULL) {
|
|
||||||
cons_show_error("Unable to open temporary file.");
|
|
||||||
win_println(window, THEME_ERROR, "-", "Unable to open temporary file.");
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
FILE *infile = fopen(filepath, "rb");
|
|
||||||
if (infile == NULL) {
|
|
||||||
cons_show_error("Unable to open file.");
|
|
||||||
win_println(window, THEME_ERROR, "-", "Unable to open file.");
|
|
||||||
close(tmpfd);
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
int crypt_res = GPG_ERR_NO_ERROR;
|
int crypt_res = GPG_ERR_NO_ERROR;
|
||||||
|
|
||||||
@ -4884,22 +4876,33 @@ cmd_sendfile(ProfWin* window, const char* const command, gchar** args)
|
|||||||
if (key == NULL) {
|
if (key == NULL) {
|
||||||
cons_show_error("Cannot allocate secure memory for encryption.");
|
cons_show_error("Cannot allocate secure memory for encryption.");
|
||||||
win_println(window, THEME_ERROR, "-", "Cannot allocate secure memory for encryption.");
|
win_println(window, THEME_ERROR, "-", "Cannot allocate secure memory for encryption.");
|
||||||
|
fclose(fh);
|
||||||
|
fclose(tmpfh);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
key = gcry_random_bytes_secure(AES256_GCM_KEY_LENGTH, GCRY_VERY_STRONG_RANDOM);
|
key = gcry_random_bytes_secure(AES256_GCM_KEY_LENGTH, GCRY_VERY_STRONG_RANDOM);
|
||||||
gcry_create_nonce(nonce, AES256_GCM_NONCE_LENGTH);
|
gcry_create_nonce(nonce, AES256_GCM_NONCE_LENGTH);
|
||||||
|
|
||||||
crypt_res = aes256gcm_encrypt_file(infile, tmpfile, tmpst.st_size, key, nonce);
|
crypt_res = aes256gcm_encrypt_file(fh, tmpfh, file_size(fd), key, nonce);
|
||||||
|
|
||||||
if (crypt_res != 0) {
|
if (crypt_res != 0) {
|
||||||
cons_show_error("Failed to encrypt file.");
|
cons_show_error("Failed to encrypt file.");
|
||||||
win_println(window, THEME_ERROR, "-", "Failed to encrypt file.");
|
win_println(window, THEME_ERROR, "-", "Failed to encrypt file.");
|
||||||
|
fclose(fh);
|
||||||
|
fclose(tmpfh);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
free(filepath);
|
// Force flush as the upload will read from the same stream.
|
||||||
filepath = tmppath;
|
fflush(tmpfh);
|
||||||
|
rewind(tmpfh);
|
||||||
|
|
||||||
|
fclose(fh);
|
||||||
|
|
||||||
|
// Switch original stream with temporary encrypted stream.
|
||||||
|
fd = tmpfd;
|
||||||
|
fh = tmpfh;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -4934,21 +4937,12 @@ cmd_sendfile(ProfWin* window, const char* const command, gchar** args)
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (access(filename, R_OK) != 0) {
|
HTTPUpload *upload = malloc(sizeof(HTTPUpload));
|
||||||
cons_show_error("Uploading '%s' failed: File not found!", filename);
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!is_regular_file(filename)) {
|
|
||||||
cons_show_error("Uploading '%s' failed: Not a file!", filename);
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
HTTPUpload* upload = malloc(sizeof(HTTPUpload));
|
|
||||||
upload->window = window;
|
upload->window = window;
|
||||||
|
|
||||||
upload->filename = filename;
|
upload->filename = strdup(filename);
|
||||||
upload->filesize = file_size(filename);
|
upload->filehandle = fh;
|
||||||
|
upload->filesize = file_size(fd);
|
||||||
upload->mime_type = file_mime_type(filename);
|
upload->mime_type = file_mime_type(filename);
|
||||||
|
|
||||||
iq_http_upload_request(upload);
|
iq_http_upload_request(upload);
|
||||||
@ -4958,8 +4952,6 @@ out:
|
|||||||
gcry_free(key);
|
gcry_free(key);
|
||||||
if (filename != NULL)
|
if (filename != NULL)
|
||||||
free(filename);
|
free(filename);
|
||||||
if (filepath != NULL)
|
|
||||||
free(filepath);
|
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
@ -133,7 +133,7 @@ http_file_put(void* userdata)
|
|||||||
{
|
{
|
||||||
HTTPUpload* upload = (HTTPUpload*)userdata;
|
HTTPUpload* upload = (HTTPUpload*)userdata;
|
||||||
|
|
||||||
FILE* fd = NULL;
|
FILE *fh = NULL;
|
||||||
|
|
||||||
char* err = NULL;
|
char* err = NULL;
|
||||||
char* content_type_header;
|
char* content_type_header;
|
||||||
@ -146,7 +146,7 @@ http_file_put(void* userdata)
|
|||||||
|
|
||||||
pthread_mutex_lock(&lock);
|
pthread_mutex_lock(&lock);
|
||||||
char* msg;
|
char* msg;
|
||||||
if (asprintf(&msg, "Uploading '%s': 0%%", upload->filepath) == -1) {
|
if (asprintf(&msg, "Uploading '%s': 0%%", upload->filename) == -1) {
|
||||||
msg = strdup(FALLBACK_MSG);
|
msg = strdup(FALLBACK_MSG);
|
||||||
}
|
}
|
||||||
win_print_http_upload(upload->window, msg, upload->put_url);
|
win_print_http_upload(upload->window, msg, upload->put_url);
|
||||||
@ -186,18 +186,13 @@ http_file_put(void* userdata)
|
|||||||
|
|
||||||
curl_easy_setopt(curl, CURLOPT_USERAGENT, "profanity");
|
curl_easy_setopt(curl, CURLOPT_USERAGENT, "profanity");
|
||||||
|
|
||||||
if (!(fd = fopen(upload->filepath, "rb"))) {
|
fh = upload->filehandle;
|
||||||
if (asprintf(&err, "failed to open '%s'", upload->filepath) == -1) {
|
|
||||||
err = NULL;
|
|
||||||
}
|
|
||||||
goto end;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cert_path) {
|
if (cert_path) {
|
||||||
curl_easy_setopt(curl, CURLOPT_CAPATH, cert_path);
|
curl_easy_setopt(curl, CURLOPT_CAPATH, cert_path);
|
||||||
}
|
}
|
||||||
|
|
||||||
curl_easy_setopt(curl, CURLOPT_READDATA, fd);
|
curl_easy_setopt(curl, CURLOPT_READDATA, fh);
|
||||||
curl_easy_setopt(curl, CURLOPT_INFILESIZE_LARGE, (curl_off_t)(upload->filesize));
|
curl_easy_setopt(curl, CURLOPT_INFILESIZE_LARGE, (curl_off_t)(upload->filesize));
|
||||||
curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L);
|
curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L);
|
||||||
|
|
||||||
@ -225,12 +220,11 @@ http_file_put(void* userdata)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
end:
|
|
||||||
curl_easy_cleanup(curl);
|
curl_easy_cleanup(curl);
|
||||||
curl_global_cleanup();
|
curl_global_cleanup();
|
||||||
curl_slist_free_all(headers);
|
curl_slist_free_all(headers);
|
||||||
if (fd) {
|
if (fh) {
|
||||||
fclose(fd);
|
fclose(fh);
|
||||||
}
|
}
|
||||||
free(content_type_header);
|
free(content_type_header);
|
||||||
free(output.buffer);
|
free(output.buffer);
|
||||||
@ -294,7 +288,6 @@ end:
|
|||||||
pthread_mutex_unlock(&lock);
|
pthread_mutex_unlock(&lock);
|
||||||
|
|
||||||
free(upload->filename);
|
free(upload->filename);
|
||||||
free(upload->filepath);
|
|
||||||
free(upload->mime_type);
|
free(upload->mime_type);
|
||||||
free(upload->get_url);
|
free(upload->get_url);
|
||||||
free(upload->put_url);
|
free(upload->put_url);
|
||||||
@ -304,18 +297,18 @@ end:
|
|||||||
}
|
}
|
||||||
|
|
||||||
char*
|
char*
|
||||||
file_mime_type(const char* const filepath)
|
file_mime_type(const char* const filename)
|
||||||
{
|
{
|
||||||
char* out_mime_type;
|
char* out_mime_type;
|
||||||
char file_header[FILE_HEADER_BYTES];
|
char file_header[FILE_HEADER_BYTES];
|
||||||
FILE *fd;
|
FILE *fh;
|
||||||
if (!(fd = fopen(filepath, "rb"))) {
|
if (!(fh = fopen(filename, "rb"))) {
|
||||||
return strdup(FALLBACK_MIMETYPE);
|
return strdup(FALLBACK_MIMETYPE);
|
||||||
}
|
}
|
||||||
size_t file_header_size = fread(file_header, 1, FILE_HEADER_BYTES, fd);
|
size_t file_header_size = fread(file_header, 1, FILE_HEADER_BYTES, fh);
|
||||||
fclose(fd);
|
fclose(fh);
|
||||||
|
|
||||||
char *content_type = g_content_type_guess(filepath, (unsigned char*)file_header, file_header_size, NULL);
|
char *content_type = g_content_type_guess(filename, (unsigned char*)file_header, file_header_size, NULL);
|
||||||
if (content_type != NULL) {
|
if (content_type != NULL) {
|
||||||
char* mime_type = g_content_type_get_mime_type(content_type);
|
char* mime_type = g_content_type_get_mime_type(content_type);
|
||||||
out_mime_type = strdup(mime_type);
|
out_mime_type = strdup(mime_type);
|
||||||
@ -327,10 +320,10 @@ file_mime_type(const char* const filepath)
|
|||||||
return out_mime_type;
|
return out_mime_type;
|
||||||
}
|
}
|
||||||
|
|
||||||
off_t file_size(const char* const filepath)
|
off_t file_size(int filedes)
|
||||||
{
|
{
|
||||||
struct stat st;
|
struct stat st;
|
||||||
stat(filepath, &st);
|
fstat(filedes, &st);
|
||||||
return st.st_size;
|
return st.st_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -47,7 +47,7 @@
|
|||||||
|
|
||||||
typedef struct http_upload_t {
|
typedef struct http_upload_t {
|
||||||
char *filename;
|
char *filename;
|
||||||
char *filepath;
|
FILE *filehandle;
|
||||||
off_t filesize;
|
off_t filesize;
|
||||||
curl_off_t bytes_sent;
|
curl_off_t bytes_sent;
|
||||||
char* mime_type;
|
char* mime_type;
|
||||||
@ -60,8 +60,8 @@ typedef struct http_upload_t {
|
|||||||
|
|
||||||
void* http_file_put(void* userdata);
|
void* http_file_put(void* userdata);
|
||||||
|
|
||||||
char* file_mime_type(const char* const filepath);
|
char* file_mime_type(const char* const filename);
|
||||||
off_t file_size(const char* const filepath);
|
off_t file_size(int filedes);
|
||||||
|
|
||||||
void http_upload_cancel_processes(ProfWin* window);
|
void http_upload_cancel_processes(ProfWin* window);
|
||||||
void http_upload_add_upload(HTTPUpload* upload);
|
void http_upload_add_upload(HTTPUpload* upload);
|
||||||
|
@ -2401,9 +2401,9 @@ _http_upload_response_id_handler(xmpp_stanza_t* const stanza, void* const userda
|
|||||||
if (g_strcmp0(type, STANZA_TYPE_ERROR) == 0) {
|
if (g_strcmp0(type, STANZA_TYPE_ERROR) == 0) {
|
||||||
char* error_message = stanza_get_error_message(stanza);
|
char* error_message = stanza_get_error_message(stanza);
|
||||||
if (from) {
|
if (from) {
|
||||||
cons_show_error("Uploading '%s' failed for %s: %s", upload->filepath, from, error_message);
|
cons_show_error("Uploading '%s' failed for %s: %s", upload->filename, from, error_message);
|
||||||
} else {
|
} else {
|
||||||
cons_show_error("Uploading '%s' failed: %s", upload->filepath, error_message);
|
cons_show_error("Uploading '%s' failed: %s", upload->filename, error_message);
|
||||||
}
|
}
|
||||||
free(error_message);
|
free(error_message);
|
||||||
return 0;
|
return 0;
|
||||||
|
Loading…
Reference in New Issue
Block a user