1
0
Fork 0

Update to the newest version of XEP 0363 (HTTP Upload)

Main changes:

1. Attributes instead of tags
2. Read the optional <header> tags and send them in the HTTP PUT header:

   * Authorization
   * Cookie
   * Expires

Co-authored-by: Martin Dosch <martin@mdosch.de>
This commit is contained in:
Maximilian Wuttke 2021-03-10 17:26:38 +01:00
parent 96580f917b
commit e217ed0b79
5 changed files with 65 additions and 34 deletions

View File

@ -166,6 +166,10 @@ http_file_put(void* userdata)
char* err = NULL;
char* content_type_header;
// Optional headers
char* auth_header = NULL;
char* cookie_header = NULL;
char* expires_header = NULL;
CURL* curl;
CURLcode res;
@ -196,6 +200,21 @@ http_file_put(void* userdata)
}
headers = curl_slist_append(headers, content_type_header);
headers = curl_slist_append(headers, "Expect:");
// Optional headers
if (upload->authorization) {
asprintf(&auth_header, "Authorization: %s", upload->authorization);
headers = curl_slist_append(headers, auth_header);
}
if (upload->cookie) {
asprintf(&cookie_header, "Cookie: %s", upload->cookie);
headers = curl_slist_append(headers, cookie_header);
}
if (upload->expires) {
asprintf(&expires_header, "Expires: %s", upload->expires);
headers = curl_slist_append(headers, expires_header);
}
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
#if LIBCURL_VERSION_NUM >= 0x072000
@ -225,6 +244,7 @@ http_file_put(void* userdata)
curl_easy_setopt(curl, CURLOPT_INFILESIZE_LARGE, (curl_off_t)(upload->filesize));
curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L);
if ((res = curl_easy_perform(curl)) != CURLE_OK) {
err = strdup(curl_easy_strerror(res));
} else {
@ -252,11 +272,15 @@ http_file_put(void* userdata)
curl_easy_cleanup(curl);
curl_global_cleanup();
curl_slist_free_all(headers);
if (fh) {
fclose(fh);
}
free(content_type_header);
free(output.buffer);
free(auth_header);
free(cookie_header);
free(expires_header);
pthread_mutex_lock(&lock);
g_free(cert_path);
@ -334,6 +358,9 @@ http_file_put(void* userdata)
free(upload->put_url);
free(upload->alt_scheme);
free(upload->alt_fragment);
free(upload->authorization);
free(upload->cookie);
free(upload->expires);
free(upload);
return NULL;

View File

@ -59,6 +59,11 @@ typedef struct http_upload_t
ProfWin* window;
pthread_t worker;
int cancel;
// Additional headers
// (NULL if they shouldn't be send in the PUT)
char* authorization;
char* cookie;
char* expires;
} HTTPUpload;
void* http_file_put(void* userdata);

View File

@ -2423,18 +2423,31 @@ _http_upload_response_id_handler(xmpp_stanza_t* const stanza, void* const userda
xmpp_stanza_t* get = xmpp_stanza_get_child_by_name(slot, STANZA_NAME_GET);
if (put && get) {
char* put_url = xmpp_stanza_get_text(put);
char* get_url = xmpp_stanza_get_text(get);
const char* put_url = xmpp_stanza_get_attribute(put, "url");
upload->put_url = strdup(put_url);
const char* get_url = xmpp_stanza_get_attribute(get, "url");
upload->get_url = strdup(get_url);
xmpp_conn_t* conn = connection_get_conn();
xmpp_ctx_t* ctx = xmpp_conn_get_context(conn);
if (put_url)
xmpp_free(ctx, put_url);
if (get_url)
xmpp_free(ctx, get_url);
// Optional "authorization", "cookie", "expires" headers
upload->authorization = upload->cookie = upload->expires = NULL;
xmpp_stanza_t* header = xmpp_stanza_get_children(put);
for (; header; header = xmpp_stanza_get_next(header)) {
if (g_strcmp0(xmpp_stanza_get_name(header), STANZA_NAME_HEADER) == 0) {
const char* header_name = xmpp_stanza_get_attribute(header, STANZA_ATTR_NAME);
if (g_strcmp0(header_name, STANZA_HEADER_AUTHORIZATION) == 0) {
upload->authorization = xmpp_stanza_get_text(header);
}
else if (g_strcmp0(header_name, STANZA_HEADER_COOKIE) == 0) {
upload->cookie = xmpp_stanza_get_text(header);
}
else if (g_strcmp0(header_name, STANZA_HEADER_EXPIRES) == 0) {
upload->expires = xmpp_stanza_get_text(header);
}
else {
log_warning("[HTTP upload] unknown header: %s", header_name);
}
}
}
pthread_create(&(upload->worker), NULL, &http_file_put, upload);
http_upload_add_upload(upload);

View File

@ -232,9 +232,6 @@ stanza_create_http_upload_request(xmpp_ctx_t* ctx, const char* const id,
xmpp_stanza_set_name(request, STANZA_NAME_REQUEST);
xmpp_stanza_set_ns(request, STANZA_NS_HTTP_UPLOAD);
xmpp_stanza_t* filename = xmpp_stanza_new(ctx);
xmpp_stanza_set_name(filename, STANZA_NAME_FILENAME);
xmpp_stanza_t* filename_txt = xmpp_stanza_new(ctx);
char* filename_cpy = strdup(upload->filename);
// strip spaces from filename (servers don't spaces)
for (int i = 0; i < strlen(filename_cpy); i++) {
@ -242,34 +239,16 @@ stanza_create_http_upload_request(xmpp_ctx_t* ctx, const char* const id,
filename_cpy[i] = '_';
}
}
xmpp_stanza_set_text(filename_txt, basename(filename_cpy));
xmpp_stanza_set_attribute(request, STANZA_ATTR_FILENAME, basename(filename_cpy));
free(filename_cpy);
xmpp_stanza_add_child(filename, filename_txt);
xmpp_stanza_add_child(request, filename);
xmpp_stanza_release(filename_txt);
xmpp_stanza_release(filename);
xmpp_stanza_t* size = xmpp_stanza_new(ctx);
xmpp_stanza_set_name(size, STANZA_NAME_SIZE);
xmpp_stanza_t* size_txt = xmpp_stanza_new(ctx);
char* filesize = NULL;
if (asprintf(&filesize, "%jd", (intmax_t)(upload->filesize)) != -1) {
xmpp_stanza_set_text(size_txt, filesize);
xmpp_stanza_set_attribute(request, STANZA_ATTR_SIZE, filesize);
free(filesize);
}
xmpp_stanza_add_child(size, size_txt);
xmpp_stanza_add_child(request, size);
xmpp_stanza_release(size_txt);
xmpp_stanza_release(size);
xmpp_stanza_t* content_type = xmpp_stanza_new(ctx);
xmpp_stanza_set_name(content_type, STANZA_NAME_CONTENT_TYPE);
xmpp_stanza_t* content_type_txt = xmpp_stanza_new(ctx);
xmpp_stanza_set_text(content_type_txt, upload->mime_type);
xmpp_stanza_add_child(content_type, content_type_txt);
xmpp_stanza_add_child(request, content_type);
xmpp_stanza_release(content_type_txt);
xmpp_stanza_release(content_type);
xmpp_stanza_set_attribute(request, STANZA_ATTR_CONTENTTYPE, upload->mime_type);
xmpp_stanza_add_child(iq, request);
xmpp_stanza_release(request);

View File

@ -106,6 +106,10 @@
#define STANZA_NAME_SLOT "slot"
#define STANZA_NAME_PUT "put"
#define STANZA_NAME_GET "get"
#define STANZA_NAME_HEADER "header"
#define STANZA_HEADER_AUTHORIZATION "Authorization"
#define STANZA_HEADER_COOKIE "Cookie"
#define STANZA_HEADER_EXPIRES "Expires"
#define STANZA_NAME_URL "url"
#define STANZA_NAME_COMMAND "command"
#define STANZA_NAME_CONFIGURE "configure"
@ -178,6 +182,9 @@
#define STANZA_ATTR_STATUS "status"
#define STANZA_ATTR_DATE "date"
#define STANZA_ATTR_V4_FINGERPRINT "v4-fingerprint"
#define STANZA_ATTR_FILENAME "filename"
#define STANZA_ATTR_SIZE "size"
#define STANZA_ATTR_CONTENTTYPE "content-type"
#define STANZA_TEXT_AWAY "away"
#define STANZA_TEXT_DND "dnd"
@ -210,7 +217,7 @@
// XEP-0373: OpenPGP for XMPP
#define STANZA_NS_OPENPGP_0 "urn:xmpp:openpgp:0"
#define STANZA_NS_OPENPGP_0_PUBLIC_KEYS "urn:xmpp:openpgp:0:public-keys"
#define STANZA_NS_HTTP_UPLOAD "urn:xmpp:http:upload"
#define STANZA_NS_HTTP_UPLOAD "urn:xmpp:http:upload:0"
#define STANZA_NS_X_OOB "jabber:x:oob"
#define STANZA_NS_BLOCKING "urn:xmpp:blocking"
#define STANZA_NS_COMMAND "http://jabber.org/protocol/commands"