2016-05-03 15:23:36 -07:00
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
# include "config.h"
|
|
|
|
#endif
|
|
|
|
|
2016-12-01 21:23:40 -08:00
|
|
|
#include <sys/stat.h>
|
|
|
|
#include <fcntl.h>
|
|
|
|
|
2016-05-03 15:23:36 -07:00
|
|
|
#include "extra.h"
|
2016-12-30 05:23:48 -08:00
|
|
|
#include "jsmn/jsmn.h"
|
2016-05-03 15:23:36 -07:00
|
|
|
#include "extra_private.h"
|
|
|
|
|
|
|
|
static int _extra_init = 0;
|
2016-12-30 05:23:48 -08:00
|
|
|
static Ecore_Event_Handler *_data;
|
|
|
|
static Ecore_Event_Handler *_complete;
|
2016-05-03 15:23:36 -07:00
|
|
|
int _extra_lib_log_dom = -1;
|
|
|
|
|
2016-11-19 13:49:16 -08:00
|
|
|
Eina_List *_theme_list;
|
|
|
|
|
2016-12-30 05:23:48 -08:00
|
|
|
#define sec_strdup(v) v ? eina_strbuf_string_steal(v) : NULL
|
|
|
|
|
2016-11-19 13:49:16 -08:00
|
|
|
static void
|
2016-12-30 05:23:48 -08:00
|
|
|
_extra_theme_add(Eina_Strbuf *id, Eina_Strbuf *name,
|
|
|
|
Eina_Strbuf *author, Eina_Strbuf *description,
|
2016-11-19 13:49:16 -08:00
|
|
|
int version)
|
|
|
|
{
|
|
|
|
Extra_Theme *theme;
|
|
|
|
|
|
|
|
theme = malloc(sizeof(*theme));
|
2016-12-30 05:23:48 -08:00
|
|
|
theme->id = sec_strdup(id);
|
|
|
|
theme->name = sec_strdup(name);
|
|
|
|
theme->author = sec_strdup(author);
|
|
|
|
theme->description = sec_strdup(description);
|
2016-11-19 13:49:16 -08:00
|
|
|
theme->version = version;
|
|
|
|
|
|
|
|
_theme_list = eina_list_append(_theme_list, theme);
|
|
|
|
}
|
|
|
|
|
2016-05-03 15:23:36 -07:00
|
|
|
EAPI int
|
|
|
|
extra_init(void)
|
|
|
|
{
|
|
|
|
_extra_init++;
|
|
|
|
if (_extra_init > 1) return _extra_init;
|
|
|
|
|
|
|
|
eina_init();
|
|
|
|
|
|
|
|
_extra_lib_log_dom = eina_log_domain_register("extra", EINA_COLOR_CYAN);
|
|
|
|
if (_extra_lib_log_dom < 0)
|
|
|
|
{
|
|
|
|
EINA_LOG_ERR("extra can not create its log domain.");
|
|
|
|
goto shutdown_eina;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Put here your initialization logic of your library
|
|
|
|
|
|
|
|
eina_log_timing(_extra_lib_log_dom, EINA_LOG_STATE_STOP, EINA_LOG_STATE_INIT);
|
|
|
|
|
|
|
|
return _extra_init;
|
|
|
|
|
|
|
|
shutdown_eina:
|
|
|
|
eina_shutdown();
|
|
|
|
_extra_init--;
|
|
|
|
|
|
|
|
return _extra_init;
|
|
|
|
}
|
|
|
|
|
|
|
|
EAPI int
|
|
|
|
extra_shutdown(void)
|
|
|
|
{
|
|
|
|
_extra_init--;
|
|
|
|
if (_extra_init != 0) return _extra_init;
|
|
|
|
|
|
|
|
eina_log_timing(_extra_lib_log_dom,
|
|
|
|
EINA_LOG_STATE_START,
|
|
|
|
EINA_LOG_STATE_SHUTDOWN);
|
|
|
|
|
|
|
|
// Put here your shutdown logic
|
|
|
|
|
|
|
|
eina_log_domain_unregister(_extra_lib_log_dom);
|
|
|
|
_extra_lib_log_dom = -1;
|
|
|
|
|
|
|
|
eina_shutdown();
|
|
|
|
|
|
|
|
return _extra_init;
|
|
|
|
}
|
|
|
|
|
2016-12-30 05:23:48 -08:00
|
|
|
static Eina_Bool
|
|
|
|
_url_data_cb(void *data EINA_UNUSED, int type EINA_UNUSED, void *event_info)
|
|
|
|
{
|
|
|
|
Ecore_Con_Event_Url_Data *url_data = event_info;
|
|
|
|
Eina_Strbuf *buf = ecore_con_url_data_get(url_data->url_con);
|
|
|
|
|
|
|
|
eina_strbuf_append_n(buf, url_data->data, url_data->size);
|
|
|
|
|
|
|
|
return EINA_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
_string_tuple_get(Eina_Strbuf *c, jsmntok_t *array, int i, Eina_Strbuf **name, Eina_Strbuf **value)
|
2016-11-19 13:49:16 -08:00
|
|
|
{
|
2016-12-30 05:23:48 -08:00
|
|
|
if (array[i].type != JSMN_STRING || array[i].size != 1)
|
|
|
|
{
|
|
|
|
printf("expected string type with children\n");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
*name = eina_strbuf_substr_get(c, array[i].start, array[i].end - array[i].start);
|
|
|
|
|
|
|
|
if ((array[i + 1].type != JSMN_STRING && array[i + 1].type != JSMN_PRIMITIVE) || array[i + 1].size != 0)
|
2016-11-19 13:49:16 -08:00
|
|
|
{
|
2016-12-30 05:23:48 -08:00
|
|
|
printf("Expected string type without children\n");
|
|
|
|
return 0;
|
2016-11-19 13:49:16 -08:00
|
|
|
}
|
2016-12-30 05:23:48 -08:00
|
|
|
*value = eina_strbuf_substr_get(c, array[i + 1].start, array[i + 1].end - array[i + 1].start);
|
|
|
|
|
|
|
|
return 2;
|
2016-11-19 13:49:16 -08:00
|
|
|
}
|
|
|
|
|
2016-05-03 15:23:36 -07:00
|
|
|
static Eina_Bool
|
2016-12-30 05:23:48 -08:00
|
|
|
_fill_themes(Eina_Strbuf *buf)
|
2016-05-03 15:23:36 -07:00
|
|
|
{
|
2016-12-30 05:23:48 -08:00
|
|
|
jsmn_parser parser;
|
|
|
|
jsmntok_t parts[201];
|
|
|
|
int n, c = 0;
|
|
|
|
|
|
|
|
jsmn_init(&parser);
|
2016-05-03 15:23:36 -07:00
|
|
|
|
2016-12-30 05:23:48 -08:00
|
|
|
const char *string = eina_strbuf_string_get(buf);
|
|
|
|
n = jsmn_parse(&parser, string, strlen(string), parts, 201);
|
|
|
|
|
|
|
|
if (n == 0)
|
|
|
|
{
|
|
|
|
printf("No themes received\n");
|
|
|
|
return EINA_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (parts[0].type != JSMN_OBJECT)
|
|
|
|
{
|
|
|
|
printf("Root node should be a object\n");
|
|
|
|
return EINA_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
c += 1;
|
|
|
|
|
|
|
|
for (int i = 0; i < parts[0].size; ++i)
|
2016-08-06 15:10:27 -07:00
|
|
|
{
|
2016-12-30 05:23:48 -08:00
|
|
|
Eina_Strbuf *id = NULL, *name = NULL, *version = NULL, *description = NULL, *author = NULL;
|
|
|
|
int versionNumb;
|
|
|
|
//expect string object tuple
|
|
|
|
if (parts[c].type != JSMN_STRING || parts[c].size != 1)
|
2016-08-06 15:10:27 -07:00
|
|
|
{
|
2016-12-30 05:23:48 -08:00
|
|
|
printf("Expected String type with one child\n");
|
|
|
|
return EINA_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
c += 1;
|
2016-08-06 15:10:27 -07:00
|
|
|
|
2016-12-30 05:23:48 -08:00
|
|
|
if (parts[c].type != JSMN_OBJECT || parts[c].size <= 0)
|
|
|
|
{
|
|
|
|
printf("Expected Object type with more than 0 children\n");
|
|
|
|
return EINA_FALSE;
|
2016-08-06 15:10:27 -07:00
|
|
|
}
|
2016-12-30 05:23:48 -08:00
|
|
|
|
|
|
|
int max = parts[c].size;
|
|
|
|
c+=1;
|
|
|
|
for (int i2 = 0; i2 < max; ++i2)
|
2016-08-06 15:10:27 -07:00
|
|
|
{
|
2016-12-30 05:23:48 -08:00
|
|
|
Eina_Strbuf *value = NULL, *property = NULL;
|
|
|
|
const char *v;
|
|
|
|
int j = _string_tuple_get(buf, parts, c, &value, &property);
|
|
|
|
|
|
|
|
if (!j) return EINA_FALSE;
|
|
|
|
c += j;
|
|
|
|
|
|
|
|
v = eina_strbuf_string_steal(value);
|
|
|
|
|
|
|
|
if (!strcmp(v, "description"))
|
|
|
|
description = property;
|
|
|
|
else if (!strcmp(v, "author"))
|
|
|
|
author = property;
|
|
|
|
else if (!strcmp(v, "name"))
|
|
|
|
name = property;
|
|
|
|
else if (!strcmp(v, "version"))
|
|
|
|
version = property;
|
|
|
|
else if (!strcmp(v, "theme_id"))
|
|
|
|
id = property;
|
|
|
|
else
|
|
|
|
eina_strbuf_free(property);
|
|
|
|
eina_strbuf_free(value);
|
|
|
|
|
2016-08-06 15:10:27 -07:00
|
|
|
}
|
2016-12-30 05:23:48 -08:00
|
|
|
|
|
|
|
versionNumb = atoi(eina_strbuf_string_steal(version));
|
|
|
|
|
|
|
|
_extra_theme_add(id, name, author, description, versionNumb);
|
|
|
|
|
|
|
|
eina_strbuf_free(id);
|
|
|
|
eina_strbuf_free(name);
|
|
|
|
eina_strbuf_free(author);
|
|
|
|
eina_strbuf_free(description);
|
|
|
|
eina_strbuf_free(version);
|
2016-08-06 15:10:27 -07:00
|
|
|
}
|
2016-05-03 15:23:36 -07:00
|
|
|
|
|
|
|
return EINA_TRUE;
|
|
|
|
}
|
|
|
|
static Eina_Bool
|
2016-12-30 05:23:48 -08:00
|
|
|
_url_complete_cb(void *data, int type EINA_UNUSED, void *event_info)
|
2016-05-03 15:23:36 -07:00
|
|
|
{
|
2016-11-19 13:49:16 -08:00
|
|
|
Extra_Progress *progress = data;;
|
2016-12-30 05:23:48 -08:00
|
|
|
Ecore_Con_Event_Url_Complete *complete = event_info;
|
|
|
|
Eina_Strbuf *buf;
|
|
|
|
|
|
|
|
buf = ecore_con_url_data_get(complete->url_con);
|
|
|
|
|
|
|
|
_fill_themes(buf);
|
2016-11-19 13:49:16 -08:00
|
|
|
|
|
|
|
if (progress->done_cb)
|
|
|
|
progress->done_cb();
|
2016-05-03 15:23:36 -07:00
|
|
|
|
2016-12-30 05:23:48 -08:00
|
|
|
ecore_event_handler_del(_data);
|
|
|
|
ecore_event_handler_del(_complete);
|
|
|
|
|
2016-05-03 15:23:36 -07:00
|
|
|
return EINA_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
EAPI void
|
2016-11-19 13:49:16 -08:00
|
|
|
extra_sync(Extra_Progress *progress)
|
2016-05-03 15:23:36 -07:00
|
|
|
{
|
|
|
|
Ecore_Con_Url *url;
|
|
|
|
|
2016-11-03 16:07:17 -07:00
|
|
|
url = ecore_con_url_custom_new("http://" HOSTNAME "/v1/themes/", "GET");
|
2016-12-30 05:23:48 -08:00
|
|
|
ecore_con_url_additional_header_add(url, "Accept", "text/json");
|
|
|
|
ecore_con_url_data_set(url, eina_strbuf_new());
|
2016-05-03 15:23:36 -07:00
|
|
|
|
2016-12-30 05:23:48 -08:00
|
|
|
_data = ecore_event_handler_add(ECORE_CON_EVENT_URL_DATA, _url_data_cb, NULL);
|
|
|
|
_complete = ecore_event_handler_add(ECORE_CON_EVENT_URL_COMPLETE, _url_complete_cb, progress);
|
2016-05-03 15:23:36 -07:00
|
|
|
|
|
|
|
ecore_con_url_get(url);
|
|
|
|
}
|
2016-11-19 13:49:16 -08:00
|
|
|
|
|
|
|
EAPI Eina_List *
|
|
|
|
extra_themes_list(void)
|
|
|
|
{
|
|
|
|
return _theme_list;
|
|
|
|
}
|
|
|
|
|
2016-12-01 21:23:40 -08:00
|
|
|
EAPI Extra_Theme *extra_theme_get(const char *id)
|
|
|
|
{
|
|
|
|
Extra_Theme *theme;
|
|
|
|
Eina_List *item;
|
|
|
|
|
|
|
|
EINA_LIST_FOREACH(extra_themes_list(), item, theme)
|
|
|
|
if (!strcmp(id, theme->id))
|
|
|
|
return theme;
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
EAPI Eina_Bool
|
|
|
|
extra_theme_installed(Extra_Theme *theme)
|
|
|
|
{
|
|
|
|
char *path;
|
|
|
|
Eina_Bool exists;
|
|
|
|
|
|
|
|
path = extra_theme_install_path_get(theme);
|
|
|
|
exists = ecore_file_exists(path);
|
|
|
|
free(path);
|
|
|
|
|
|
|
|
return exists;
|
|
|
|
}
|
|
|
|
|
|
|
|
EAPI char *
|
|
|
|
extra_theme_install_path_get(Extra_Theme *theme)
|
|
|
|
{
|
|
|
|
char *path;
|
|
|
|
|
|
|
|
path = malloc(PATH_MAX * sizeof(char));
|
|
|
|
sprintf(path, "%s/.elementary/themes/%s.edj", eina_environment_home_get(), theme->id);
|
|
|
|
|
|
|
|
return path;
|
|
|
|
}
|
|
|
|
|
|
|
|
EAPI char *
|
|
|
|
extra_theme_preview_url_get(Extra_Theme *theme)
|
|
|
|
{
|
2016-12-30 07:55:44 -08:00
|
|
|
const char *pattern = "http://" HOSTNAME "/themes/preview/%s.png";
|
2016-12-01 21:23:40 -08:00
|
|
|
char *url;
|
|
|
|
|
|
|
|
if (!theme)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
url = malloc((strlen(pattern) + strlen(theme->id) - 1) * sizeof(char));
|
|
|
|
sprintf(url, pattern, theme->id);
|
|
|
|
|
|
|
|
return url;
|
|
|
|
}
|
|
|
|
|
|
|
|
EAPI char *
|
|
|
|
extra_theme_download_url_get(Extra_Theme *theme)
|
|
|
|
{
|
|
|
|
const char *pattern = "http://" HOSTNAME "/themes/%s-%d.edj";
|
|
|
|
char *url;
|
|
|
|
|
|
|
|
if (!theme)
|
|
|
|
return NULL;
|
|
|
|
|
2016-12-30 07:55:44 -08:00
|
|
|
url = malloc((strlen(pattern) + strlen(theme->id) - 1 + (int)(log10(theme->version))) * sizeof(char));
|
2016-12-01 21:23:40 -08:00
|
|
|
sprintf(url, pattern, theme->id, theme->version);
|
|
|
|
|
|
|
|
return url;
|
|
|
|
}
|
|
|
|
|
|
|
|
static Eina_Bool
|
2016-12-02 14:48:33 -08:00
|
|
|
_enlightenment_restart(void *data)
|
2016-12-01 21:23:40 -08:00
|
|
|
{
|
|
|
|
Extra_Progress *progress = data;
|
|
|
|
char *cmd = "enlightenment_remote -restart";
|
|
|
|
|
|
|
|
if (progress->done_cb)
|
|
|
|
progress->done_cb();
|
2016-12-02 14:48:33 -08:00
|
|
|
ecore_exe_run(cmd, NULL);
|
|
|
|
|
|
|
|
return EINA_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static Eina_Bool
|
|
|
|
_install_complete_cb(void *data, int type EINA_UNUSED, void *event_info EINA_UNUSED)
|
|
|
|
{
|
|
|
|
Extra_Progress *progress = data;
|
2016-12-01 21:23:40 -08:00
|
|
|
|
|
|
|
if (progress->is_theme)
|
|
|
|
{
|
|
|
|
elm_theme_set(NULL, progress->id);
|
|
|
|
elm_config_all_flush();
|
|
|
|
elm_config_save();
|
|
|
|
|
2016-12-02 14:48:33 -08:00
|
|
|
ecore_timer_add(3, _enlightenment_restart, data);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (progress->done_cb)
|
|
|
|
progress->done_cb();
|
2016-12-01 21:23:40 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
return EINA_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
EAPI void
|
|
|
|
extra_theme_install(Extra_Progress *progress)
|
|
|
|
{
|
|
|
|
Extra_Theme *theme = NULL;
|
|
|
|
char *path, *urlstr = NULL;
|
|
|
|
Ecore_Con_Url *url;
|
|
|
|
int fd;
|
|
|
|
|
|
|
|
if (progress->is_theme)
|
|
|
|
theme = extra_theme_get(progress->id);
|
|
|
|
|
|
|
|
if (theme)
|
|
|
|
urlstr = extra_theme_download_url_get(theme);
|
|
|
|
|
|
|
|
if (urlstr)
|
|
|
|
{
|
|
|
|
url = ecore_con_url_custom_new(urlstr, "GET");
|
|
|
|
ecore_event_handler_add(ECORE_CON_EVENT_URL_COMPLETE, _install_complete_cb, progress);
|
|
|
|
path = extra_theme_install_path_get(theme);
|
|
|
|
fd = creat(path, 0644);
|
|
|
|
|
|
|
|
ecore_con_url_fd_set(url, fd);
|
|
|
|
ecore_con_url_get(url);
|
|
|
|
|
|
|
|
free(path);
|
|
|
|
free(urlstr);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|