#include "ssb-app.h" #include "ssb-window.h" #include "ssb-scuttler.h" struct _SsbApp { GtkApplication parent_instance; gchar *ssb_dir; SsbWindow *window; SsbScuttler *scuttler; }; G_DEFINE_TYPE(SsbApp, ssb_app, GTK_TYPE_APPLICATION); static GOptionEntry entries[] = { {"noauth", 'n', 0, G_OPTION_ARG_NONE, NULL, "Noauth mode. Skip secret-handshake authentication and box-stream encryption. This option makes the -k, -K, and -c options to have no effect and output a warning if used.", NULL}, {"ipv4", '4', 0, G_OPTION_ARG_NONE, NULL, "Connect to the server over IPv4 only", NULL}, {"ipv6", '6', 0, G_OPTION_ARG_NONE, NULL, "Connect to the server over IPv6 only", NULL}, {"capkey", 'c', 0, G_OPTION_ARG_STRING, NULL, "Capability key for the secret handshake. If not set, the default SSB capability key will be used", "CAPKEY"}, {"server", 's', 0, G_OPTION_ARG_STRING, NULL, "The hostname to connect to. Defaults to localhost", "HOST"}, {"port", 'p', 0, G_OPTION_ARG_INT, NULL, "The port to connect to. Default is 8008.", "PORT"}, {"socket", 'u', 0, G_OPTION_ARG_FILENAME, NULL, "Unix socket path to connect to instead of a TCP socket. Conflicts with -s and -p", "PATH"}, {"key", 'k', 0, G_OPTION_ARG_STRING, NULL, "The key to connect to. Default is your public key as read from the private key file", "KEY"}, {"keypair-seed", 'K', 0, G_OPTION_ARG_STRING, NULL, "Private key seed to use for the secret handshake. Default is to use the private key from your privace key file.", "SEED"}, {"version", 'v', 0, G_OPTION_ARG_NONE, NULL, "Print version information and exit", NULL}, {NULL} }; static void print_version(void) { // TODO: Move these to constants or something g_print("ssb-gtk %d.%d.%d\n", 0, 0, 1); } static int local_options(GApplication *app, GVariantDict *options, gpointer user_data) { gboolean version = FALSE; g_variant_dict_lookup(options, "version", "b", &version); if (version) { print_version(); return 0; } return -1; } SsbApp * ssb_app_new(void) { SsbApp *app = g_object_new(SSB_TYPE_APP, NULL); g_application_add_main_option_entries(G_APPLICATION(app), entries); g_application_set_option_context_description(G_APPLICATION(app), "Report issues at https://gitea.polonkai.eu/gergely/ssb-gtk/issues"); g_application_set_option_context_summary(G_APPLICATION(app), "An SSB client for the GNOME desktop."); g_signal_connect(app, "handle-local-options", G_CALLBACK(local_options), NULL); return app; } static void ssb_app_finalize(GObject *gobject) { SsbApp *app = SSB_APP(gobject); app->ssb_dir = (g_free(app->ssb_dir), NULL); G_OBJECT_CLASS(ssb_app_parent_class)->finalize(gobject); } static void ssb_app_dispose(GObject *gobject) { SsbApp *app = SSB_APP(gobject); g_clear_object(&(app->window)); g_clear_object(&(app->scuttler)); G_OBJECT_CLASS(ssb_app_parent_class)->dispose(gobject); } static void whoami_finished(GObject *source, GAsyncResult *res, gpointer user_data) { } void connect_finished(GObject *source, GAsyncResult *res, gpointer user_data) { SsbScuttler *scuttler = SSB_SCUTTLER(source); SsbApp *app = user_data; GError *err = NULL; gboolean connect_successful = ssb_scuttler_connect_finish(scuttler, res, &err); ssb_scuttler_whoami_async(scuttler, NULL, whoami_finished, app); } static void ssb_app_startup(GApplication *gapp) { SsbApp *app = SSB_APP(gapp); SsbScuttler *scuttler = NULL; G_APPLICATION_CLASS(ssb_app_parent_class)->startup(gapp); if (G_UNLIKELY(!ssb_scuttler_ensure(app->ssb_dir))) { g_critical("Can not reinitialise scuttler with a new SSB directory."); return; } // Wait until the scuttler instance comes up if ((scuttler = ssb_scuttler_get()) == NULL) { g_critical("Can not get scuttler object"); } app->scuttler = g_object_ref_sink(ssb_scuttler_get()); ssb_scuttler_connect_async(app->scuttler, NULL, connect_finished, app); } static SsbWindow * ssb_app_get_or_create_window(SsbApp *app) { SsbWindow *window = ssb_window_new(app); return window; } static void ssb_app_activate(GApplication *app) { G_APPLICATION_CLASS(ssb_app_parent_class)->activate(app); SsbWindow *window = ssb_app_get_or_create_window(SSB_APP(app)); gtk_window_present(GTK_WINDOW(window)); } static void ssb_app_shutdown(GApplication *gapp) { G_APPLICATION_CLASS(ssb_app_parent_class)->shutdown(gapp); } static void ssb_app_init(SsbApp *app) { gchar **envp = g_get_environ(); const gchar *app_dir_path = g_environ_getenv(envp, "ssb_path"); app->ssb_dir = NULL; app->window = NULL; app->scuttler = NULL; if (app_dir_path != NULL) { app->ssb_dir = g_strdup(app_dir_path); } else { const gchar *home = g_environ_getenv(envp, "HOME"); const gchar *appname = g_environ_getenv(envp, "ssb_appname"); if (home == NULL) { home = "."; } if (appname == NULL) { appname = "ssb"; } app->ssb_dir = g_strdup_printf("%s/.%s", home, appname); } g_strfreev(envp); g_debug("SsbApp initialised with app dir %s", app->ssb_dir); } static void ssb_app_class_init(SsbAppClass *klass) { GObjectClass *gobject_class = G_OBJECT_CLASS(klass); GApplicationClass *app_class = G_APPLICATION_CLASS(klass); gobject_class->finalize = ssb_app_finalize; gobject_class->dispose = ssb_app_dispose; app_class->activate = ssb_app_activate; app_class->startup = ssb_app_startup; app_class->shutdown = ssb_app_shutdown; }