enlightenment-module-share/src/sourcedrop.c

129 lines
3.7 KiB
C

#include <ctype.h>
#include <json/json.h>
#ifdef __linux__
#include <bsd/string.h> // strlcpy, etc. found in libbsd
#else
#include <string.h>
#endif
#include "e_mod_main.h"
#include "e_share.h"
#define BUFFER_SIZE_MAX 4096
#define DROPNAME "Sourcedrop"
#define SOURCEDROP_URL "http://www.sourcedrop.net/paste"
#define RECOGNITION_STRING "Location: "
static Ecore_Event_Handler *handler = NULL;
static Eina_Bool __upload_completed_cb(void *data, int type, Ecore_Con_Event_Url_Complete *ev);
static json_object *jarray, *jparent;
/* Converts an integer value to its hex character*/
char to_hex(const char code) {
static char hex[] = "0123456789abcdef";
return hex[code & 15];
}
/* Returns a url-encoded version of str */
/* IMPORTANT: be sure to free() the returned string after use */
char *url_encode(const char *str) {
const char *pstr = str;
char *buf = malloc(strlen(str) * 3 + 1), *pbuf = buf;
while (*pstr) {
if (isalnum(*pstr) || *pstr == '-' || *pstr == '_' || *pstr == '.' || *pstr == '~')
*pbuf++ = *pstr;
else if (*pstr == ' ')
*pbuf++ = '+';
else
*pbuf++ = '%', *pbuf++ = to_hex(*pstr >> 4), *pbuf++ = to_hex(*pstr & 15);
pstr++;
}
*pbuf = '\0';
return buf;
}
const char *json_encode(const char *title, const char *content)
{
const char *encoded_string = NULL;
jarray = json_object_new_array();
jparent = json_object_new_object();
json_object_object_add(jparent, "title", json_object_new_string(title));
json_object_object_add(jparent, "content", json_object_new_string(content));
json_object_array_add(jarray, jparent);
encoded_string = json_object_to_json_string(jarray);
return encoded_string;
}
static Eina_Bool
__upload_completed_cb(void *data, int type, Ecore_Con_Event_Url_Complete *ev)
{
char buf[BUFFER_SIZE_MAX];
const Eina_List *headers = NULL, *it;
const char *header = NULL;
Share_Data *sd = NULL;
json_object_put(jarray);
jarray = NULL;
json_object_put(jparent);
jparent = NULL;
if (ev->status != 200)
{
LOG("E_SHARE/" DROPNAME ": This is not supposed to happen. The server returned status code: %d\n", ev->status);
return ECORE_CALLBACK_RENEW;
}
headers = ecore_con_url_response_headers_get(ev->url_con);
EINA_LIST_FOREACH(headers, it, header)
{
if (strncmp(header, RECOGNITION_STRING, (sizeof(RECOGNITION_STRING) - 1)) == 0)
{
sd = ecore_con_url_data_get(ev->url_con);
strlcpy(buf, (char*)(header + sizeof(RECOGNITION_STRING) - 1), sizeof(buf));
asprintf(&sd->url, "%s", buf);
e_share_upload_completed(sd);
ecore_con_url_free(ev->url_con);
break;
}
}
return ECORE_CALLBACK_CANCEL;
}
void sourcedrop_share(Share_Data *sd)
{
Ecore_Con_Url *request_url = NULL;
char post_data[BUFFER_SIZE_MAX];
const char *json_encoded = NULL;
char *url_encoded = NULL;
EINA_SAFETY_ON_NULL_RETURN(sd);
json_encoded = json_encode(sd->name, sd->content);
request_url = ecore_con_url_new(SOURCEDROP_URL);
url_encoded = url_encode(json_encoded);
snprintf(post_data, (sizeof(post_data) - 1), "data=%s", url_encoded);
free(url_encoded);
ecore_con_url_data_set(request_url, (void*)sd);
ecore_con_url_post(request_url, (void*)post_data, sizeof(post_data), "application/x-www-form-urlencoded");
}
void sourcedrop_init(void)
{
ecore_init();
ecore_con_init();
handler = ecore_event_handler_add(ECORE_CON_EVENT_URL_COMPLETE, (Ecore_Event_Handler_Cb)__upload_completed_cb, NULL);
}
void sourcedrop_shutdown(void)
{
ecore_event_handler_del(handler);
handler = NULL;
ecore_con_shutdown();
ecore_shutdown();
}