libgnunetchat

library for GNUnet Messenger
Log | Files | Refs | README | LICENSE

commit cdb69d11f86721dc5d003bff5b478223b80aae0c
parent 0643c99b65df3e2ca2bf63b9b664b07c84de4f39
Author: Jacki <jacki@thejackimonster.de>
Date:   Thu, 18 Apr 2024 18:28:45 +0200

Implement function to upload file and get uri from file handle

Signed-off-by: Jacki <jacki@thejackimonster.de>

Diffstat:
Minclude/gnunet/gnunet_chat_lib.h | 27+++++++++++++++++++++++++++
Msrc/gnunet_chat_file.c | 3++-
Msrc/gnunet_chat_lib.c | 117+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 146 insertions(+), 1 deletion(-)

diff --git a/include/gnunet/gnunet_chat_lib.h b/include/gnunet/gnunet_chat_lib.h @@ -691,12 +691,29 @@ GNUNET_CHAT_lobby_join (struct GNUNET_CHAT_Handle *handle, * * @param[in,out] handle Chat handle * @param[in] uri Chat URI + * @return File handle on success, NULL on failure */ struct GNUNET_CHAT_File* GNUNET_CHAT_request_file (struct GNUNET_CHAT_Handle *handle, const struct GNUNET_CHAT_Uri *uri); /** + * Uploads a local file specified via its <i>path</i> to share its uri + * with others afterwards. + * + * @param[in,out] handle Chat handle + * @param[in] path Local file path + * @param[in] callback Callback for file uploading (optional) + * @param[in,out] cls Closure for file uploading (optional) + * @return The file handle on success, NULL on failure + */ +struct GNUNET_CHAT_File* +GNUNET_CHAT_upload_file (struct GNUNET_CHAT_Handle *handle, + const char *path, + GNUNET_CHAT_FileUploadCallback callback, + void *cls); + +/** * Sets a custom <i>user pointer</i> to a given chat <i>handle</i> so it can * be accessed in all handle related callbacks. * @@ -1433,6 +1450,16 @@ uint64_t GNUNET_CHAT_file_get_local_size (const struct GNUNET_CHAT_File *file); /** + * Returns a new allocated uri to access the content of a given + * <i>file</i> handle. + * + * @param[in] file File handle + * @return URI on success, NULL on error + */ +struct GNUNET_CHAT_Uri* +GNUNET_CHAT_file_get_uri (const struct GNUNET_CHAT_File *file); + +/** * Returns if a given <i>file</i> handle is currently uploading. * * @param[in] file File handle diff --git a/src/gnunet_chat_file.c b/src/gnunet_chat_file.c @@ -305,7 +305,8 @@ file_update_upload (struct GNUNET_CHAT_File *file, { upload = file->upload_head; - GNUNET_MESSENGER_send_message(upload->context->room, &msg, NULL); + if (upload->context) + GNUNET_MESSENGER_send_message(upload->context->room, &msg, NULL); GNUNET_CONTAINER_DLL_remove( file->upload_head, diff --git a/src/gnunet_chat_lib.c b/src/gnunet_chat_lib.c @@ -782,6 +782,111 @@ GNUNET_CHAT_request_file (struct GNUNET_CHAT_Handle *handle, } +struct GNUNET_CHAT_File* +GNUNET_CHAT_upload_file (struct GNUNET_CHAT_Handle *handle, + const char *path, + GNUNET_CHAT_FileUploadCallback callback, + void *cls) +{ + GNUNET_CHAT_VERSION_ASSERT(); + + if ((!handle) || (handle->destruction) || + (!path)) + return NULL; + + struct GNUNET_HashCode hash; + if (GNUNET_OK != util_hash_file(path, &hash)) + return NULL; + + char *filename = handle_create_file_path( + handle, &hash + ); + + if (!filename) + return NULL; + + struct GNUNET_CHAT_File *file = GNUNET_CONTAINER_multihashmap_get( + handle->files, + &hash + ); + + if (file) + goto file_binding; + + if ((GNUNET_YES == GNUNET_DISK_file_test(filename)) || + (GNUNET_OK != GNUNET_DISK_directory_create_for_file(filename)) || + (GNUNET_OK != GNUNET_DISK_file_copy(path, filename))) + { + GNUNET_free(filename); + return NULL; + } + + struct GNUNET_CRYPTO_SymmetricSessionKey key; + GNUNET_CRYPTO_symmetric_create_session_key(&key); + + if (GNUNET_OK != util_encrypt_file(filename, &hash, &key)) + { + GNUNET_free(filename); + return NULL; + } + + char* p = GNUNET_strdup(path); + + file = file_create_from_disk( + handle, + basename(p), + &hash, + &key + ); + + GNUNET_free(p); + + if (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put( + handle->files, &hash, file, + GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST)) + { + file_destroy(file); + GNUNET_free(filename); + return NULL; + } + + struct GNUNET_FS_BlockOptions bo; + + bo.anonymity_level = block_anonymity_level; + bo.content_priority = block_content_priority; + bo.replication_level = block_replication_level; + + bo.expiration_time = GNUNET_TIME_absolute_add( + GNUNET_TIME_absolute_get(), GNUNET_TIME_relative_get_hour_() + ); + + struct GNUNET_FS_FileInformation* fi = GNUNET_FS_file_information_create_from_file( + handle->fs, + file, + filename, + NULL, + file->meta, + GNUNET_YES, + &bo + ); + + file->publish = GNUNET_FS_publish_start( + handle->fs, fi, + NULL, NULL, NULL, + GNUNET_FS_PUBLISH_OPTION_NONE + ); + + if (file->publish) + file->status |= GNUNET_CHAT_FILE_STATUS_PUBLISH; + + GNUNET_free(filename); + +file_binding: + file_bind_upload(file, NULL, callback, cls); + return file; +} + + void GNUNET_CHAT_set_user_pointer (struct GNUNET_CHAT_Handle *handle, void *user_pointer) @@ -2203,6 +2308,18 @@ GNUNET_CHAT_file_get_local_size (const struct GNUNET_CHAT_File *file) } +struct GNUNET_CHAT_Uri* +GNUNET_CHAT_file_get_uri (const struct GNUNET_CHAT_File *file) +{ + GNUNET_CHAT_VERSION_ASSERT(); + + if ((!file) || (!(file->uri))) + return NULL; + + return uri_create_file(file->uri); +} + + enum GNUNET_GenericReturnValue GNUNET_CHAT_file_is_uploading (const struct GNUNET_CHAT_File *file) {