diff --git a/OpenRA.Launcher.Gtk/bridge.c b/OpenRA.Launcher.Gtk/bridge.c index 1f395a2e81..a5c226bbbc 100644 --- a/OpenRA.Launcher.Gtk/bridge.c +++ b/OpenRA.Launcher.Gtk/bridge.c @@ -22,11 +22,11 @@ int js_check_num_args(JSContextRef ctx, char const * func_name, int argc, int num_expected, JSValueRef * exception) { - char buf[64]; + GString * buf = g_string_new(NULL); if (argc < num_expected) { - sprintf(buf, "%s: Not enough args, expected %d got %d", func_name, num_expected, argc); - *exception = JSValueMakeString(ctx, JS_STR(buf)); + g_string_printf(buf, "%s: Not enough args, expected %d got %d", func_name, num_expected, argc); + *exception = JSValueMakeString(ctx, JS_STR(buf->str)); return 0; } return 1; @@ -101,8 +101,8 @@ JSValueRef js_exists_in_mod(JSContextRef ctx, JSObjectRef func, fclose(f); return_value = JSValueMakeNumber(ctx, 1); } - - g_message("JS ExistsInMod: Not found"); + else + g_message("JS ExistsInMod: Not found"); return return_value; } @@ -140,9 +140,8 @@ JSValueRef js_launch_mod(JSContextRef ctx, JSObjectRef func, while (strlen(mod->requires) > 0) { - char r[MOD_requires_MAX_LEN], * comma; - strcpy(r, mod->requires); - if (NULL != (comma = strchr(r, ','))) + gchar * r = g_strdup(mod->requires), * comma; + if (NULL != (comma = g_strstr_len(r, -1, ","))) { *comma = '\0'; } @@ -160,10 +159,11 @@ JSValueRef js_launch_mod(JSContextRef ctx, JSObjectRef func, mod_list = (char *)realloc(mod_list, offset + strlen(r) + 1); sprintf(mod_list + offset, ",%s", r); offset += strlen(r) + 1; + g_free(r); } { - char * launch_args[] = { "mono", "OpenRA.Game.exe", NULL, NULL }; + char * launch_args[] = { "mono", "OpenRA.Game.exe", NULL, "SupportDir=~/.openra", NULL }; char * game_mods_arg; game_mods_arg = (char *)malloc(strlen(mod_list) + strlen("Game.Mods=") + 1); diff --git a/OpenRA.Launcher.Gtk/main.c b/OpenRA.Launcher.Gtk/main.c index 20b020b4d4..21fe33e961 100644 --- a/OpenRA.Launcher.Gtk/main.c +++ b/OpenRA.Launcher.Gtk/main.c @@ -24,32 +24,43 @@ GtkTreeStore * tree_store; GtkTreeView * tree; GdkPixbuf * generic_mod_icon; +static mod_t mods[MAX_NUM_MODS]; +static int mod_count = 0; + +void free_mod(mod_t * mod) +{ + g_free(mod->key); + g_free(mod->title); + g_free(mod->version); + g_free(mod->author); + g_free(mod->description); + g_free(mod->requires); +} + gboolean window_delete(GtkWidget * widget, GdkEvent * event, gpointer user_data) { + int i; server_teardown(); + for (i = 0; i < mod_count; i++) + free_mod(mods + i); gtk_main_quit(); return FALSE; } -static mod_t mods[MAX_NUM_MODS]; -static int mod_count = 0; - -typedef void ( * lines_callback ) (char const * line, gpointer data); +typedef void ( * lines_callback ) (GString const * line, gpointer data); //Splits console output into lines and passes each one to a callback -void process_lines(char * const lines, int len, lines_callback cb, gpointer data) +void process_lines(GString * lines, lines_callback cb, gpointer data) { int prev = 0, current = 0; - while (current < len) + while (current < lines->len) { - if (lines[current] == '\n') + if (lines->str[current] == '\n') { - char * line = (char *)malloc(current - prev + 1); - memcpy(line, lines + prev, current - prev); - line[current - prev] = '\0'; + GString * line = g_string_new_len(lines->str + prev, current - prev); cb(line, data); - free(line); + g_string_free(line, TRUE); prev = current + 1; } current++; @@ -57,49 +68,46 @@ void process_lines(char * const lines, int len, lines_callback cb, gpointer data } #define ASSIGN_TO_MOD(FIELD) \ - strncpy(mod->FIELD, val_start + 2, MOD_##FIELD##_MAX_LEN - 1); \ - mod->FIELD[MOD_##FIELD##_MAX_LEN - 1] = '\0' + mod->FIELD = g_strdup(val_start) -#define min(X, Y) X < Y ? X : Y - -void mod_metadata_line(char const * line, gpointer data) +void mod_metadata_line(GString const * line, gpointer data) { mod_t * mod = (mod_t *)data; - char * val_start = strchr(line, ':'); - if (memcmp(line, "Mod:", 4) == 0) + gchar * val_start = g_strstr_len(line->str, -1, ":") + 2; + if (g_str_has_prefix(line->str, "Mod:")) { ASSIGN_TO_MOD(key); } - else if (memcmp(line, " Title:", min(strlen(line), 8)) == 0) + else if (g_str_has_prefix(line->str, " Title:")) { ASSIGN_TO_MOD(title); } - else if (memcmp(line, " Version:", min(strlen(line), 10)) == 0) + else if (g_str_has_prefix(line->str, " Version:")) { ASSIGN_TO_MOD(version); } - else if (memcmp(line, " Author:", min(strlen(line), 9)) == 0) + else if (g_str_has_prefix(line->str, " Author:")) { ASSIGN_TO_MOD(author); } - else if (memcmp(line, " Description:", min(strlen(line), 14)) == 0) + else if (g_str_has_prefix(line->str, " Description:")) { ASSIGN_TO_MOD(description); } - else if (memcmp(line, " Requires:", min(strlen(line), 11)) == 0) + else if (g_str_has_prefix(line->str, " Requires:")) { ASSIGN_TO_MOD(requires); } - else if (memcmp(line, " Standalone:", min(strlen(line), 13)) == 0) + else if (g_str_has_prefix(line->str, " Standalone:")) { - if (strcmp(val_start + 2, "True") == 0) + if (strcmp(val_start, "True") == 0) mod->standalone = TRUE; else mod->standalone = FALSE; } } -mod_t * get_mod(char const * key) +mod_t * get_mod(gchar const * key) { int i; for (i = 0; i < mod_count; i++) @@ -141,20 +149,27 @@ gboolean append_to_mod(GtkTreeModel * model, GtkTreePath * path, void mod_metadata_callback(GPid pid, gint status, gpointer data) { - int out_len, * out_fd = (int *)data; - char * msg = NULL; + int * out_fd = (int *)data; + GString * msg = NULL; mod_t * mod = mods + mod_count; GtkTreeIter iter, mod_iter; mod_count = (mod_count + 1) % MAX_NUM_MODS; + free_mod(mod); memset(mod, 0, sizeof(mod_t)); - msg = util_get_output(*out_fd, &out_len); + msg = util_get_output(*out_fd); - process_lines(msg, out_len, mod_metadata_line, mod); + close(*out_fd); + free(out_fd); - free(msg); + if (!msg) + return; + + process_lines(msg, mod_metadata_line, mod); + + g_string_free(msg, TRUE); gtk_tree_model_get_iter_first(GTK_TREE_MODEL(tree_store), &mod_iter); @@ -185,14 +200,11 @@ void mod_metadata_callback(GPid pid, gint status, gpointer data) { gtk_tree_model_foreach(GTK_TREE_MODEL(tree_store), append_to_mod, mod); } - - close(*out_fd); - free(out_fd); } typedef struct tree_node { - char const * key; + gchar const * key; gchar * node_path; } tree_node; @@ -222,23 +234,32 @@ gboolean find_mod(GtkTreeModel * model, GtkTreePath * path, void last_mod_callback(GPid pid, gint status, gpointer data) { - int out_len, * out_fd = (int *)data; - char * comma_pos = 0; - char * msg = NULL; + int * out_fd = (int *)data; + gchar * comma_pos = 0, * newline_pos = 0; + GString * msg = NULL; tree_node n; memset(&n, 0, sizeof(tree_node)); - msg = util_get_output(*out_fd, &out_len); + msg = util_get_output(*out_fd); - if (0 == memcmp(msg, "Error:", 6)) - memcpy(msg, "ra", 3); - else if (NULL != (comma_pos = strchr(msg, ','))) + close(*out_fd); + free(out_fd); + + if (!msg) + return; + + if (0 == strcmp(msg->str, "Error:")) { - *comma_pos = '\0'; + g_string_truncate(msg, 2); + g_string_overwrite(msg, 0, "ra"); } + else if (NULL != (comma_pos = g_strstr_len(msg->str, -1, ","))) + *comma_pos = '\0'; + else if (NULL != (newline_pos = g_strstr_len(msg->str, -1, "\n"))) + *newline_pos = '\0'; - n.key = msg; + n.key = msg->str; gtk_tree_model_foreach(GTK_TREE_MODEL(tree_store), find_mod, &n); @@ -254,31 +275,35 @@ void last_mod_callback(GPid pid, gint status, gpointer data) g_free(n.node_path); } - free(msg); + g_string_free(msg, TRUE); } -void mod_list_line(char const * mod, gpointer user) +void mod_list_line(GString const * mod, gpointer user) { - util_get_mod_metadata(mod, mod_metadata_callback); + util_get_mod_metadata(mod->str, mod_metadata_callback); } void mod_list_callback(GPid pid, gint status, gpointer data) { - int out_len, * out_fd = (int *)data; - char * msg = NULL; + int * out_fd = (int *)data; + GString * msg = NULL; - msg = util_get_output(*out_fd, &out_len); - - mod_count = 0; - - process_lines(msg, out_len, mod_list_line, NULL); - - util_get_setting("Game.Mods", last_mod_callback); - - free(msg); + msg = util_get_output(*out_fd); close(*out_fd); free(out_fd); + + if (!msg) + return; + + mod_count = 0; + + process_lines(msg, mod_list_line, NULL); + + util_get_setting("Game.Mods", last_mod_callback); + + g_string_free(msg, TRUE); + g_spawn_close_pid(pid); } @@ -287,7 +312,7 @@ void tree_view_selection_changed(GtkTreeView * tree_view, gpointer data) GtkTreePath * path; GtkTreeIter iter; gchar * key; - char url[256]; + GString * url; gtk_tree_view_get_cursor(tree_view, &path, NULL); @@ -306,12 +331,15 @@ void tree_view_selection_changed(GtkTreeView * tree_view, gpointer data) return; } - sprintf(url, "http://localhost:%d/mods/%s/mod.html", WEBSERVER_PORT, key); + url = g_string_new(NULL); - webkit_web_view_load_uri(browser, url); + g_string_printf(url, "http://localhost:%d/mods/%s/mod.html", WEBSERVER_PORT, key); + + webkit_web_view_load_uri(browser, url->str); g_free(key); gtk_tree_path_free(path); + g_string_free(url, TRUE); } void make_tree_view(void) diff --git a/OpenRA.Launcher.Gtk/main.h b/OpenRA.Launcher.Gtk/main.h index 067a8153c0..1111923db4 100644 --- a/OpenRA.Launcher.Gtk/main.h +++ b/OpenRA.Launcher.Gtk/main.h @@ -16,26 +16,19 @@ enum N_COLUMNS }; -#define MOD_key_MAX_LEN 16 -#define MOD_title_MAX_LEN 32 -#define MOD_version_MAX_LEN 16 -#define MOD_author_MAX_LEN 32 -#define MOD_description_MAX_LEN 128 -#define MOD_requires_MAX_LEN 32 - #define MAX_NUM_MODS 64 typedef struct mod_t { - char key[MOD_key_MAX_LEN]; - char title[MOD_title_MAX_LEN]; - char version[MOD_version_MAX_LEN]; - char author[MOD_author_MAX_LEN]; - char description[MOD_description_MAX_LEN]; - char requires[MOD_requires_MAX_LEN]; + gchar * key; + gchar * title; + gchar * version; + gchar * author; + gchar * description; + gchar * requires; int standalone; } mod_t; -mod_t * get_mod(char const * key); +mod_t * get_mod(gchar const * key); #endif diff --git a/OpenRA.Launcher.Gtk/utility.c b/OpenRA.Launcher.Gtk/utility.c index 29f55c6c4e..8dbe6ce9e4 100644 --- a/OpenRA.Launcher.Gtk/utility.c +++ b/OpenRA.Launcher.Gtk/utility.c @@ -12,11 +12,11 @@ #include #include -int util_do_command_async(char * command, GChildWatchFunc callback) +gboolean util_do_command_async(gchar * command, GChildWatchFunc callback) { GPid child_pid; gint * out_fd = (gint *)malloc(sizeof(gint)); - char * spawn_args[] = { "mono", "OpenRA.Utility.exe", command, NULL }; + gchar * spawn_args[] = { "mono", "OpenRA.Utility.exe", command, NULL }; gboolean result; result = g_spawn_async_with_pipes(NULL, spawn_args, NULL, @@ -33,17 +33,17 @@ int util_do_command_async(char * command, GChildWatchFunc callback) return TRUE; } -int util_get_mod_list (GChildWatchFunc callback) +gboolean util_get_mod_list (GChildWatchFunc callback) { return util_do_command_async("-l", callback); } -int util_do_command_blocking(char * command, GChildWatchFunc callback) +gboolean util_do_command_blocking(gchar * command, GChildWatchFunc callback) { GPid child_pid; int status; - gint * out_fd = (gint *)malloc(sizeof(gint)); - char * spawn_args[] = { "mono", "OpenRA.Utility.exe", command, NULL }; + gint * out_fd = (gint *)g_malloc(sizeof(gint)); + gchar * spawn_args[] = { "mono", "OpenRA.Utility.exe", command, NULL }; gboolean result; result = g_spawn_async_with_pipes(NULL, spawn_args, NULL, @@ -55,7 +55,6 @@ int util_do_command_blocking(char * command, GChildWatchFunc callback) return FALSE; } - //g_child_watch_add(child_pid, callback, out_fd); waitpid(child_pid, &status, 0); callback(child_pid, status, out_fd); @@ -63,47 +62,44 @@ int util_do_command_blocking(char * command, GChildWatchFunc callback) return TRUE; } -int util_get_mod_metadata(char const * mod, GChildWatchFunc callback) +gboolean util_get_mod_metadata(gchar const * mod, GChildWatchFunc callback) { - char * util_args; - int return_val; + GString * util_args = g_string_new(NULL); + gboolean return_val; - util_args = (char *)malloc(strlen(mod) + strlen("-i=") + 1); - sprintf(util_args, "-i=%s", mod); - return_val = util_do_command_blocking(util_args, callback); - free(util_args); + g_string_printf(util_args, "-i=%s", mod); + return_val = util_do_command_blocking(util_args->str, callback); + g_string_free(util_args, TRUE); return return_val; } -int util_get_setting(const char * setting, GChildWatchFunc callback) +gboolean util_get_setting(gchar const * setting, GChildWatchFunc callback) { - char * command; - int return_val; + GString * command = g_string_new(NULL); + gboolean return_val; - command = (char *)malloc(strlen(setting) + strlen("--settings-value=~/.openra,") + 1); - sprintf(command, "--settings-value=~/.openra,%s", setting); - return_val = util_do_command_blocking(command, callback); - free(command); + g_string_printf(command, "--settings-value=~/.openra,%s", setting); + return_val = util_do_command_blocking(command->str, callback); + g_string_free(command, TRUE); return return_val; } -int util_spawn_with_command(const char * command, const char * arg1, const char * arg2, GPid * pid) +gint util_spawn_with_command(gchar const * command, gchar const * arg1, gchar const * arg2, GPid * pid) { - char * complete_command; - int out_fd; + GString * complete_command = g_string_new(NULL); + gint out_fd; gboolean result; - char * launch_args[] = { "mono", "OpenRA.Utility.exe", NULL, NULL }; + gchar * launch_args[] = { "mono", "OpenRA.Utility.exe", NULL, NULL }; - complete_command = (char *)malloc(strlen(command) + strlen(arg1) + strlen(arg2) + 2); - sprintf(complete_command, "%s%s,%s", command, arg1, arg2); + g_string_printf(complete_command, "%s%s,%s", command, arg1, arg2); - launch_args[2] = complete_command; + launch_args[2] = complete_command->str; result = g_spawn_async_with_pipes(NULL, launch_args, NULL, G_SPAWN_SEARCH_PATH, NULL, NULL, pid, NULL, &out_fd, NULL, NULL); - free(complete_command); + g_string_free(complete_command, TRUE); if (!result) { @@ -113,39 +109,34 @@ int util_spawn_with_command(const char * command, const char * arg1, const char return out_fd; } -int util_do_download(const char * url, const char * dest, GPid * pid) +gint util_do_download(gchar const * url, gchar const * dest, GPid * pid) { return util_spawn_with_command("--download-url=", url, dest, pid); } -int util_do_extract(const char * target, const char * dest, GPid * pid) +gint util_do_extract(gchar const * target, gchar const * dest, GPid * pid) { return util_spawn_with_command("--extract-zip=", target, dest, pid); } -char * util_get_output(int fd, int * output_len) +GString * util_get_output(int fd) { - char buffer[1024], * msg = NULL; + char buffer[1024]; + GString * msg = g_string_new(NULL); int read_bytes = 0; - *output_len = 0; while (0 != (read_bytes = read(fd, buffer, 1024))) { if (-1 == read_bytes) { g_error("Error reading from command output"); - free(msg); - *output_len = 0; + g_string_free(msg, TRUE); return NULL; } - *output_len += read_bytes; - - msg = (char *)realloc(msg, *output_len + 1); - - memcpy(msg + (*output_len - read_bytes), buffer, read_bytes); + g_string_append_len(msg, buffer, read_bytes); } - msg[*output_len] = '\0'; + g_string_append_c(msg, '\0'); return msg; } diff --git a/OpenRA.Launcher.Gtk/utility.h b/OpenRA.Launcher.Gtk/utility.h index b1bb2a81d0..ce6d1e2684 100644 --- a/OpenRA.Launcher.Gtk/utility.h +++ b/OpenRA.Launcher.Gtk/utility.h @@ -6,9 +6,9 @@ * see LICENSE. */ -int util_get_mod_list (GChildWatchFunc); -int util_get_mod_metadata(char const *, GChildWatchFunc); -int util_get_setting(const char *, GChildWatchFunc); -int util_do_download(const char *, const char *, GPid *); -int util_do_extract(const char *, const char *, GPid *); -char * util_get_output(int, int *); +gboolean util_get_mod_list (GChildWatchFunc); +gboolean util_get_mod_metadata(gchar const *, GChildWatchFunc); +gboolean util_get_setting(gchar const *, GChildWatchFunc); +gint util_do_download(gchar const *, gchar const *, GPid *); +gint util_do_extract(gchar const *, gchar const *, GPid *); +GString * util_get_output(int);