messenger-cli

Command-line user interface for GNUnet Messenger
Log | Files | Refs | README | LICENSE

accounts.c (4642B)


      1 /*
      2    This file is part of GNUnet.
      3    Copyright (C) 2022--2026 GNUnet e.V.
      4 
      5    GNUnet is free software: you can redistribute it and/or modify it
      6    under the terms of the GNU Affero General Public License as published
      7    by the Free Software Foundation, either version 3 of the License,
      8    or (at your option) any later version.
      9 
     10    GNUnet 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    Affero General Public License for more details.
     14 
     15    You should have received a copy of the GNU Affero General Public License
     16    along with this program.  If not, see <http://www.gnu.org/licenses/>.
     17 
     18    SPDX-License-Identifier: AGPL3.0-or-later
     19  */
     20 /*
     21  * @author Tobias Frisch
     22  * @file ui/accounts.c
     23  */
     24 
     25 #include "accounts.h"
     26 
     27 #include <curses.h>
     28 #include <gnunet/gnunet_chat_lib.h>
     29 
     30 #include "list_input.h"
     31 
     32 #include "../application.h"
     33 #include "../secret.h"
     34 #include "../util.h"
     35 
     36 int
     37 _accounts_iterate(void *cls,
     38                   UNUSED struct GNUNET_CHAT_Handle *handle,
     39                   struct GNUNET_CHAT_Account *account)
     40 {
     41   UI_ACCOUNTS_Handle *accounts = cls;
     42   list_input_select(accounts, 1, account);
     43   return GNUNET_YES;
     44 }
     45 
     46 void
     47 accounts_event(UI_ACCOUNTS_Handle *accounts,
     48                MESSENGER_Application *app,
     49                int key)
     50 {
     51   if (accounts->create_dialog.window)
     52   {
     53     account_create_dialog_event(&(accounts->create_dialog), app, key);
     54     return;
     55   }
     56 
     57   list_input_reset(accounts);
     58 
     59   GNUNET_CHAT_iterate_accounts(
     60     app->chat.handle,
     61     &_accounts_iterate,
     62     accounts
     63   );
     64 
     65   list_input_select(accounts, 1, NULL);
     66 
     67   switch (key)
     68   {
     69     case 27:
     70     case KEY_EXIT:
     71       app->chat.quit = TRUE;
     72       break;
     73     case '\n':
     74     case KEY_ENTER:
     75       if (accounts->selected)
     76       {
     77         char new_secret [65];
     78         uint32_t secret_len;
     79         const char *secret;
     80         char *secret_ptr;
     81 
     82         const char *name = GNUNET_CHAT_account_get_name(
     83           accounts->selected
     84         );
     85 
     86         secret_ptr = secret_lookup(name, &secret_len);
     87         secret = secret_ptr;
     88 
     89         if (!secret)
     90         {
     91           secret_len = 64;
     92           if (GNUNET_OK == GNUNET_CHAT_generate_secret(new_secret, secret_len))
     93           {
     94             new_secret[secret_len] = '\0';
     95 
     96             if (secret_store(name, new_secret, secret_len))
     97               secret = new_secret;
     98           }
     99         }
    100 
    101         if (!secret)
    102           secret_len = 0;
    103 
    104         GNUNET_CHAT_connect(
    105           app->chat.handle,
    106           accounts->selected,
    107           secret,
    108           secret_len
    109         );
    110 
    111         if (secret_ptr)
    112           secret_free(secret_ptr);
    113         else
    114           secret_wipe(new_secret);
    115       }
    116       else
    117         accounts->create_dialog.window = &(accounts->window);
    118       break;
    119     case 8:
    120     case KEY_BACKSPACE:
    121       if (accounts->selected)
    122       {
    123         const char *name = GNUNET_CHAT_account_get_name(
    124           accounts->selected
    125         );
    126 
    127         if (GNUNET_OK == GNUNET_CHAT_account_delete(app->chat.handle, name))
    128           secret_delete(name);
    129       }
    130       break;
    131     default:
    132       break;
    133   }
    134 
    135   list_input_event(accounts, key);
    136 }
    137 
    138 static int
    139 _accounts_print_entry(UI_ACCOUNTS_Handle *accounts,
    140                       char type,
    141                       const char *text,
    142                       const void *data)
    143 {
    144   list_input_print_gnunet(accounts, 1);
    145 
    146   const int attrs_select = A_BOLD;
    147 
    148   if (selected) wattron(accounts->window, attrs_select);
    149   else type = ' ';
    150 
    151   wmove(accounts->window, y, 0);
    152 
    153   util_enable_unique_color(accounts->window, data);
    154 
    155   wprintw(accounts->window, "[%c] %s", type, text);
    156 
    157   util_disable_unique_color(accounts->window, data);
    158 
    159   if (selected) wattroff(accounts->window, attrs_select);
    160 
    161   return GNUNET_YES;
    162 }
    163 
    164 int
    165 _accounts_iterate_print(void *cls,
    166                         UNUSED struct GNUNET_CHAT_Handle *handle,
    167                         struct GNUNET_CHAT_Account *account)
    168 {
    169   UI_ACCOUNTS_Handle *accounts = cls;
    170   const char *name = GNUNET_CHAT_account_get_name(account);
    171   return _accounts_print_entry(accounts, 'x', name, account);
    172 }
    173 
    174 void
    175 accounts_print(UI_ACCOUNTS_Handle *accounts,
    176                MESSENGER_Application *app)
    177 {
    178   if (accounts->create_dialog.window)
    179   {
    180     account_create_dialog_print(&(accounts->create_dialog));
    181     return;
    182   }
    183 
    184   if (!(accounts->window))
    185     return;
    186 
    187   list_input_reset(accounts);
    188   werase(accounts->window);
    189 
    190   GNUNET_CHAT_iterate_accounts(
    191       app->chat.handle,
    192       &_accounts_iterate_print,
    193       accounts
    194   );
    195 
    196   _accounts_print_entry(accounts, '+', "Add account", NULL);
    197 }