anastasis-gtk

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

anastasis-gtk_progress.c (8792B)


      1 /*
      2      This file is part of anastasis-gtk.
      3      Copyright (C) 2021 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_progress.c
     22  * @brief Functions dealing with the lists that show the user where we are in the process
     23  * @author Christian Grothoff
     24  */
     25 #include <gnunet/gnunet_util_lib.h>
     26 #include "anastasis_gtk_util.h"
     27 #include "anastasis-gtk_helper.h"
     28 #include "anastasis-gtk_rows.h"
     29 #include <gdk-pixbuf/gdk-pixbuf.h>
     30 
     31 
     32 /**
     33  * One step of one of the two processes we guide the user through.
     34  */
     35 struct Step
     36 {
     37   /**
     38    * Name of the step, as shown to the user.
     39    */
     40   const char *description;
     41 
     42   /**
     43    * Regular expression matching the reducer states this step covers.
     44    */
     45   const char *regex;
     46 
     47   /**
     48    * Long explanation of the step, shown as a tooltip.
     49    */
     50   const char *tooltip;
     51 };
     52 
     53 
     54 /**
     55  * The steps of making a backup.
     56  */
     57 static const struct Step backup_steps[] = {
     58   { .description = N_ ("1. Location & currency"),
     59     .regex = "^(CONTINENT|COUNTRY)_SELECTING$",
     60     .tooltip = N_ (
     61       "Where you live will determine which personal information can be used to identify your backup.") },
     62   { .description = N_ ("2. Personal information"),
     63     .regex = "^USER_ATTRIBUTES_COLLECTING$",
     64     .tooltip = N_ (
     65       "Your personal information will not be shared with anyone. But you must provide the same information during recovery.\\") },
     66   { .description = N_ ("3. Authorization methods"),
     67     .regex = "^AUTHENTICATIONS_EDITING$",
     68     .tooltip = N_ (
     69       "Specify which methods could be used to authenticate you during recovery.") },
     70   { .description = N_ ("4. Recovery policies"),
     71     .regex = "^POLICIES_REVIEWING$",
     72     .tooltip = N_ (
     73       "These are possible ways how the secret could be recovered. Please review and possibly edit the policies.") },
     74   { .description = N_ ("5. Enter secret"),
     75     .regex = "^SECRET_EDITING$",
     76     .tooltip = N_ ("Please specify the secret to be backed up.") },
     77   { .description = N_ ("6. Payment (optional)"),
     78     .regex = "^.*_PAYING$",
     79     .tooltip = N_ (
     80       "Some Anastasis providers require payment for their service. Please pay.") },
     81   { .description = N_ ("7. Backup completed"),
     82     .regex = "BACKUP_FINISHED",
     83     .tooltip = N_ (
     84       "Your backup is complete. Please do test the recovery on occasion.") },
     85   { .description = NULL }
     86 };
     87 
     88 
     89 /**
     90  * The steps of a recovery.
     91  */
     92 static const struct Step recovery_steps[] = {
     93   { .description = N_ ("1. Location & currency"),
     94     .regex = "^(CONTINENT|COUNTRY)_SELECTING$",
     95     .tooltip = N_ (
     96       "Where you live will determine which personal information can be used to identify your backup.") },
     97   { .description = N_ ("2. Personal information"),
     98     .regex = "^USER_ATTRIBUTES_COLLECTING$",
     99     .tooltip = N_ (
    100       "Your personal information will not be shared with anyone. But you must provide the same information during recovery.") },
    101   { .description = N_ ("3. Select secret"),
    102     .regex = "^SECRET_SELECTING$",
    103     .tooltip = N_ (
    104       "Please select which secret to recover. You may switch to a different version or provider.") },
    105   { .description = N_ ("4. Solve challenges"),
    106     /* paying for a challenge and answering it are both part of this step */
    107     .regex = "^CHALLENGE_(SELECTING|PAYING|SOLVING)$",
    108     .tooltip = N_ (
    109       "Please select an authentication challenge to pass to recover the secret.") },
    110   { .description = N_ ("5. Secret recovered"),
    111     .regex = "^RECOVERY_FINISHED$",
    112     .tooltip = N_ ("Your secret was successfully recovered.") },
    113   { .description = NULL }
    114 };
    115 
    116 
    117 /**
    118  * Fill the list called @a name with the given @a steps.
    119  *
    120  * @param name name of the model in the UI file
    121  * @param steps the steps to show
    122  */
    123 static void
    124 fill_progress (const char *name,
    125                const struct Step *steps)
    126 {
    127   GListStore *list = AG_list (name);
    128 
    129   if (NULL == list)
    130     return;
    131   for (unsigned int i = 0; NULL != steps[i].description; i++)
    132     AG_list_append (list,
    133                     GNUNET_JSON_PACK (
    134                       GNUNET_JSON_pack_string ("description",
    135                                                _ (steps[i].description)),
    136                       GNUNET_JSON_pack_string ("regex",
    137                                                steps[i].regex),
    138                       GNUNET_JSON_pack_string ("tooltip",
    139                                                _ (steps[i].tooltip))));
    140 }
    141 
    142 
    143 void
    144 AG_progress_setup (void)
    145 {
    146   fill_progress ("anastasis_gtk_backup_progress_liststore",
    147                  backup_steps);
    148   fill_progress ("anastasis_gtk_recovery_progress_liststore",
    149                  recovery_steps);
    150 }
    151 
    152 
    153 /**
    154  * The progress lists only report where we are in the process; the user must
    155  * not be able to change the selection by clicking.  The gesture runs in the
    156  * capture phase, so claiming the sequence here keeps the click from ever
    157  * reaching the list.
    158  *
    159  * @param gesture the click gesture of the list
    160  * @param n_press number of presses
    161  * @param x horizontal position of the click
    162  * @param y vertical position of the click
    163  * @param user_data NULL
    164  */
    165 void
    166 anastasis_gtk_progress_treeview_pressed_cb (GtkGestureClick *gesture,
    167                                             gint n_press,
    168                                             gdouble x,
    169                                             gdouble y,
    170                                             gpointer user_data)
    171 {
    172   (void) n_press;
    173   (void) x;
    174   (void) y;
    175   (void) user_data;
    176   gtk_gesture_set_state (GTK_GESTURE (gesture),
    177                          GTK_EVENT_SEQUENCE_CLAIMED);
    178 }
    179 
    180 
    181 /**
    182  * Function to validate an input by regular expression ("validation-regex").
    183  *
    184  * @param input text to validate
    185  * @param regexp regular expression to validate form
    186  * @return true if validation passed, else false
    187  */
    188 static bool
    189 validate_regex (const char *input,
    190                 const char *regexp)
    191 {
    192   regex_t regex;
    193 
    194   if (0 != regcomp (&regex,
    195                     regexp,
    196                     REG_EXTENDED))
    197   {
    198     GNUNET_break (0);
    199     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
    200                 "Failed to compile regular expression `%s'.",
    201                 regexp);
    202     return true;
    203   }
    204   /* check if input has correct form */
    205   if (0 != regexec (&regex,
    206                     input,
    207                     0,
    208                     NULL,
    209                     0))
    210   {
    211     regfree (&regex);
    212     return false;
    213   }
    214   regfree (&regex);
    215   return true;
    216 }
    217 
    218 
    219 void
    220 AG_progress_update (void)
    221 {
    222   const char *sel_name;
    223   GListModel *steps;
    224   const char *state;
    225   guint n;
    226 
    227   state = json_string_value (json_object_get (AG_redux_state,
    228                                               "backup_state"));
    229   if (NULL == state)
    230   {
    231     state = json_string_value (json_object_get (AG_redux_state,
    232                                                 "recovery_state"));
    233     if (NULL == state)
    234     {
    235       GNUNET_break (0);
    236       return;
    237     }
    238     sel_name = "anastasis_gtk_recovery_progress_tree_selection";
    239     steps = G_LIST_MODEL (AG_list (
    240                             "anastasis_gtk_recovery_progress_liststore"));
    241   }
    242   else
    243   {
    244     sel_name = "anastasis_gtk_backup_progress_tree_selection";
    245     steps = G_LIST_MODEL (AG_list (
    246                             "anastasis_gtk_backup_progress_liststore"));
    247   }
    248   if (NULL == steps)
    249     return;
    250   n = g_list_model_get_n_items (steps);
    251   for (guint i = 0; i < n; i++)
    252   {
    253     AGRow *row = g_list_model_get_item (steps,
    254                                         i);
    255     bool match;
    256 
    257     match = validate_regex (state,
    258                             AG_row_string (row,
    259                                            "regex"));
    260     g_object_unref (row);
    261     if (match)
    262     {
    263       /* The selection is what highlights the step the user is at.  Nothing
    264          else ever moves it: the lists are not focusable and they swallow
    265          clicks. */
    266       AG_select_row (sel_name,
    267                      i);
    268       return;
    269     }
    270   }
    271   /* the reducer is in a state none of the steps above cover */
    272   GNUNET_break (0);
    273   GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
    274               "No progress step matches state `%s'\n",
    275               state);
    276 }