Skip to content

Commit

Permalink
api: Allow binary data to be sent
Browse files Browse the repository at this point in the history
Allow binary data to be sent after the headers.
This data may include a NUL byte and so everything gets
more complicated.
The data is sent raw on the wire.

It's used for uploading files.

We rename matrix_api_start to matrix_api_start_full with
the extra parameters and provide a matrix_api_start for
the callers who don't need the extra binary data.

Signed-off-by: Dr. David Alan Gilbert <dave@treblig.org>
  • Loading branch information
penguin42 committed Sep 2, 2016
1 parent 2fe5a18 commit 2f14305
Showing 1 changed file with 53 additions and 17 deletions.
70 changes: 53 additions & 17 deletions matrix-api.c
Original file line number Diff line number Diff line change
Expand Up @@ -390,10 +390,11 @@ static void _parse_url(const gchar *url, const gchar **host, const gchar **path)
* - libpurple's purple_url_parse assumes that the path + querystring is
* shorter than 256 bytes.
*
* @returns a gchar* which should be freed
* @returns a GString* which should be freed
*/
static gchar *_build_request(PurpleAccount *acct, const gchar *url,
const gchar *method, const gchar *body)
static GString *_build_request(PurpleAccount *acct, const gchar *url,
const gchar *method, const gchar *body,
const gchar *extra_data, gsize extra_len)
{
PurpleProxyInfo *gpi = purple_proxy_get_setup(acct);
GString *request_str = g_string_new(NULL);
Expand Down Expand Up @@ -422,7 +423,7 @@ static gchar *_build_request(PurpleAccount *acct, const gchar *url,

g_string_append(request_str, "Connection: close\r\n");
g_string_append_printf(request_str, "Content-Length: %" G_GSIZE_FORMAT "\r\n",
body == NULL ? 0 : strlen(body));
extra_len + (body == NULL ? 0 : strlen(body)));

if(using_http_proxy)
_add_proxy_auth_headers(request_str, gpi);
Expand All @@ -431,30 +432,37 @@ static gchar *_build_request(PurpleAccount *acct, const gchar *url,
if(body != NULL)
g_string_append(request_str, body);

return g_string_free(request_str, FALSE);
if(extra_data != NULL)
g_string_append_len(request_str, extra_data, extra_len);

return request_str;
}


/**
* Start an HTTP call to the API
*
* @param method HTTP method (eg "GET")
* @param body body of request, or NULL if none
* @param max_len maximum number of bytes to return from the request. -1 for
* default (512K).
* @param method HTTP method (eg "GET")
* @param body body of request, or NULL if none
* @param extra_data raw binary data to be sent after the body
* @param extra_len The length of the raw binary data
* @param max_len maximum number of bytes to return from the request. -1 for
* default (512K).
*
* @returns handle for the request, or NULL if the request couldn't be started
* (eg, invalid hostname). In this case, the error_callback will have
* been called already.
*/
static MatrixApiRequestData *matrix_api_start(const gchar *url,
const gchar *method, const gchar *body, MatrixConnectionData *conn,
static MatrixApiRequestData *matrix_api_start_full(const gchar *url,
const gchar *method, const gchar *body,
const gchar *extra_data, gsize extra_len,
MatrixConnectionData *conn,
MatrixApiCallback callback, MatrixApiErrorCallback error_callback,
MatrixApiBadResponseCallback bad_response_callback,
gpointer user_data, gssize max_len)
{
MatrixApiRequestData *data;
gchar *request;
GString *request;
PurpleUtilFetchUrlData *purple_data;

if (error_callback == NULL)
Expand All @@ -472,10 +480,11 @@ static MatrixApiRequestData *matrix_api_start(const gchar *url,
return NULL;
}

request = _build_request(conn->pc->account, url, method, body);
request = _build_request(conn->pc->account, url, method, body,
extra_data, extra_len);

if(purple_debug_is_unsafe())
purple_debug_info("matrixprpl", "request %s\n", request);
purple_debug_info("matrixprpl", "request %s\n", request->str);


data = g_new0(MatrixApiRequestData, 1);
Expand All @@ -485,9 +494,10 @@ static MatrixApiRequestData *matrix_api_start(const gchar *url,
data->bad_response_callback = bad_response_callback;
data->user_data = user_data;

purple_data = purple_util_fetch_url_request_len_with_account(
purple_data = purple_util_fetch_url_request_data_len_with_account(
conn -> pc -> account,
url, FALSE, NULL, TRUE, request, TRUE, max_len, matrix_api_complete,
url, FALSE, NULL, TRUE, request->str, request->len,
TRUE, max_len, matrix_api_complete,
data);

if(purple_data == NULL) {
Expand All @@ -499,11 +509,37 @@ static MatrixApiRequestData *matrix_api_start(const gchar *url,
data->purple_data = purple_data;
}

g_free(request);
g_string_free(request, TRUE);
return data;
}


/**
* Start an HTTP call to the API; lighter version of matrix_api_start_full
* since most callers don't need the extras.
*
* @param method HTTP method (eg "GET")
* @param body body of request, or NULL if none
* @param max_len maximum number of bytes to return from the request. -1 for
* default (512K).
*
* @returns handle for the request, or NULL if the request couldn't be started
* (eg, invalid hostname). In this case, the error_callback will have
* been called already.
*/
static MatrixApiRequestData *matrix_api_start(const gchar *url,
const gchar *method, const gchar *body,
MatrixConnectionData *conn,
MatrixApiCallback callback, MatrixApiErrorCallback error_callback,
MatrixApiBadResponseCallback bad_response_callback,
gpointer user_data, gssize max_len)
{
return matrix_api_start_full(url, method, body, NULL, 0, conn,
callback, error_callback, bad_response_callback,
user_data, max_len);
}


void matrix_api_cancel(MatrixApiRequestData *data)
{
if(data -> purple_data != NULL)
Expand Down

0 comments on commit 2f14305

Please sign in to comment.