anastasis-gtk

Demonstrator GUI for Anastasis
Log | Files | Refs | README | LICENSE

anastasis-gtk_io.c (8435B)


      1 /*
      2      This file is part of anastasis-gtk.
      3      Copyright (C) 2020 Anastasis SARL
      4 
      5      Anastasis is free software; you can redistribute it and/or modify
      6      it under the terms of the GNU General Public License as published
      7      by the Free Software Foundation; either version 3, or (at your
      8      option) any later version.
      9 
     10      Anastasis is distributed in the hope that it will be useful, but
     11      WITHOUT ANY WARRANTY; without even the implied warranty of
     12      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     13      General Public License for more details.
     14 
     15      You should have received a copy of the GNU General Public License
     16      along with Anastasis; see the file COPYING.  If not, write to the
     17      Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
     18      Boston, MA 02110-1301, USA.
     19 */
     20 /**
     21  * @file src/anastasis/anastasis-gtk_io.c
     22  * @brief
     23  * @author Christian Grothoff
     24  */
     25 #include <gnunet/gnunet_util_lib.h>
     26 #include "anastasis_gtk_util.h"
     27 #include "anastasis-gtk_attributes.h"
     28 #include "anastasis-gtk_dispatch.h"
     29 #include "anastasis-gtk_helper.h"
     30 #include <jansson.h>
     31 
     32 
     33 /**
     34  * Return a file filter matching the files we store states in.
     35  *
     36  * @return the filter, ownership is passed to the caller
     37  */
     38 static GListModel *
     39 state_filters (void)
     40 {
     41   GtkFileFilter *filter;
     42   GListStore *filters;
     43 
     44   filter = gtk_file_filter_new ();
     45   gtk_file_filter_set_name (filter,
     46                             _ ("Anastasis state files"));
     47   gtk_file_filter_add_pattern (filter,
     48                                "*.ana");
     49   filters = g_list_store_new (GTK_TYPE_FILE_FILTER);
     50   g_list_store_append (filters,
     51                        filter);
     52   g_object_unref (filter);
     53   return G_LIST_MODEL (filters);
     54 }
     55 
     56 
     57 /**
     58  * Function called once the user picked the state file to open.
     59  *
     60  * @param source the file dialog
     61  * @param res the result of the user's choice
     62  * @param user_data unused
     63  */
     64 static void
     65 open_state_ready_cb (GObject *source,
     66                      GAsyncResult *res,
     67                      gpointer user_data)
     68 {
     69   GFile *file;
     70   char *filename;
     71 
     72   (void) user_data;
     73   file = gtk_file_dialog_open_finish (GTK_FILE_DIALOG (source),
     74                                       res,
     75                                       NULL);
     76   if (NULL == file)
     77     return; /* user aborted */
     78   filename = ANASTASIS_GTK_file_get_path_utf8 (file);
     79   g_object_unref (file);
     80   if (NULL == filename)
     81     return;
     82   AG_load (filename);
     83   GNUNET_free (filename);
     84 }
     85 
     86 
     87 /**
     88  * User clicked the "open" button.
     89  *
     90  * @param button the button
     91  * @param user_data unused
     92  */
     93 void
     94 anastasis_gtk_open_state_clicked_cb (GtkButton *button,
     95                                      gpointer user_data)
     96 {
     97   GtkFileDialog *dialog;
     98   GListModel *filters;
     99 
    100   (void) user_data;
    101   dialog = gtk_file_dialog_new ();
    102   gtk_file_dialog_set_title (dialog,
    103                              _ ("Open saved Anastasis state"));
    104   filters = state_filters ();
    105   gtk_file_dialog_set_filters (dialog,
    106                                filters);
    107   g_object_unref (filters);
    108   gtk_file_dialog_open (dialog,
    109                         GTK_WINDOW (gtk_widget_get_root (GTK_WIDGET (button))),
    110                         NULL,
    111                         &open_state_ready_cb,
    112                         NULL);
    113   g_object_unref (dialog);
    114 }
    115 
    116 
    117 /**
    118  * Serialize state of currently shown use attribute editing frame to JSON.
    119  */
    120 static void
    121 save_user_attributes_collecting (void)
    122 {
    123   json_t *ia;
    124 
    125   ia = AG_collect_attributes (true);
    126   if (NULL == ia)
    127   {
    128     GNUNET_break (0);
    129     return;
    130   }
    131   GNUNET_break (0 ==
    132                 json_object_set (AG_redux_state,
    133                                  "identity_attributes",
    134                                  json_object_get (ia,
    135                                                   "identity_attributes")));
    136   json_decref (ia);
    137 }
    138 
    139 
    140 /**
    141  * Write the current state to @a filename, appending the ".ana" suffix if the
    142  * user did not provide it.
    143  *
    144  * @param filename where to write the state to, freed by this function
    145  */
    146 static void
    147 write_state (char *filename)
    148 {
    149   {
    150     const char *ana;
    151 
    152     ana = strstr (filename,
    153                   ".ana");
    154     if ( (NULL == ana) ||
    155          (4 != strlen (ana)) )
    156     {
    157       char *tmp;
    158 
    159       GNUNET_asprintf (&tmp,
    160                        "%s.ana",
    161                        filename);
    162       GNUNET_free (filename);
    163       filename = tmp;
    164     }
    165   }
    166   if (0 !=
    167       json_dump_file (AG_redux_state,
    168                       filename,
    169                       JSON_COMPACT))
    170   {
    171     AG_error ("Failed to write state to `%s'\n",
    172               filename);
    173   }
    174   GNUNET_free (filename);
    175 }
    176 
    177 
    178 /**
    179  * The user answered the question whether they really want their secret written
    180  * to disk in cleartext.
    181  *
    182  * @param source the warning dialog
    183  * @param res the result of the user's choice
    184  * @param user_data the file name to write to
    185  */
    186 static void
    187 cleartext_warning_response_cb (GObject *source,
    188                               GAsyncResult *res,
    189                               gpointer user_data)
    190 {
    191   char *filename = user_data;
    192 
    193   if (0 !=
    194       gtk_alert_dialog_choose_finish (GTK_ALERT_DIALOG (source),
    195                                       res,
    196                                       NULL))
    197   {
    198     /* user aborted */
    199     GNUNET_free (filename);
    200     return;
    201   }
    202   write_state (filename);
    203 }
    204 
    205 
    206 /**
    207  * Function called once the user picked the file to save the state in.
    208  *
    209  * @param source the file dialog
    210  * @param res the result of the user's choice
    211  * @param user_data unused
    212  */
    213 static void
    214 save_state_ready_cb (GObject *source,
    215                      GAsyncResult *res,
    216                      gpointer user_data)
    217 {
    218   static const struct DispatchItem save_state[] = {
    219     { .state = "USER_ATTRIBUTES_COLLECTING",
    220       .action = &save_user_attributes_collecting },
    221     { .state = NULL,
    222       .action = NULL }
    223   };
    224   GFile *file;
    225   char *filename;
    226 
    227   (void) user_data;
    228   file = gtk_file_dialog_save_finish (GTK_FILE_DIALOG (source),
    229                                       res,
    230                                       NULL);
    231   if (NULL == file)
    232     return; /* user aborted */
    233   filename = ANASTASIS_GTK_file_get_path_utf8 (file);
    234   g_object_unref (file);
    235   if (NULL == filename)
    236     return;
    237   (void) AG_dispatch (save_state);
    238 
    239   /* check if we should warn the user about writing 'core_secret' to disk */
    240   {
    241     json_t *cs;
    242 
    243     cs = json_object_get (AG_redux_state,
    244                           "core_secret");
    245     if ( (NULL != cs) &&
    246          (! json_is_null (cs)) )
    247     {
    248       GtkAlertDialog *diag;
    249       GtkRoot *toplevel;
    250       const char *buttons[] = {
    251         _ ("_OK"),
    252         _ ("_Cancel"),
    253         NULL
    254       };
    255 
    256       toplevel = gtk_widget_get_root (
    257         GTK_WIDGET (GCG_get_main_window_object (
    258                       "anastasis_gtk_main_window")));
    259       diag = gtk_alert_dialog_new (
    260         "%s",
    261         _ ("This will write your secret to disk in cleartext!"));
    262       gtk_alert_dialog_set_buttons (diag,
    263                                     buttons);
    264       gtk_alert_dialog_set_cancel_button (diag,
    265                                           1);
    266       gtk_alert_dialog_set_default_button (diag,
    267                                            0);
    268       gtk_alert_dialog_choose (diag,
    269                                GTK_WINDOW (toplevel),
    270                                NULL,
    271                                &cleartext_warning_response_cb,
    272                                filename);
    273       g_object_unref (diag);
    274       return;
    275     }
    276   }
    277 
    278   /* all good, do writing! */
    279   write_state (filename);
    280 }
    281 
    282 
    283 /**
    284  * User clicked the "save as" button.
    285  *
    286  * @param button the button
    287  * @param user_data unused
    288  */
    289 void
    290 anastasis_gtk_main_window_save_as_button_clicked_cb (GtkButton *button,
    291                                                      gpointer user_data)
    292 {
    293   GtkFileDialog *dialog;
    294   GListModel *filters;
    295 
    296   (void) user_data;
    297   dialog = gtk_file_dialog_new ();
    298   gtk_file_dialog_set_title (dialog,
    299                              _ ("Save Anastasis state"));
    300   filters = state_filters ();
    301   gtk_file_dialog_set_filters (dialog,
    302                                filters);
    303   g_object_unref (filters);
    304   gtk_file_dialog_set_initial_name (dialog,
    305                                     "untitled.ana");
    306   gtk_file_dialog_save (dialog,
    307                         GTK_WINDOW (gtk_widget_get_root (GTK_WIDGET (button))),
    308                         NULL,
    309                         &save_state_ready_cb,
    310                         NULL);
    311   g_object_unref (dialog);
    312 }