messenger-cli

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

accounts.c (4661B)


      1 /*
      2    This file is part of GNUnet.
      3    Copyright (C) 2022--2025 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 #include "../application.h"
     32 #include "../secret.h"
     33 #include "../util.h"
     34 
     35 int
     36 _accounts_iterate(void *cls,
     37                   UNUSED struct GNUNET_CHAT_Handle *handle,
     38                   struct GNUNET_CHAT_Account *account)
     39 {
     40   UI_ACCOUNTS_Handle *accounts = cls;
     41   list_input_select(accounts, 1, account);
     42   return GNUNET_YES;
     43 }
     44 
     45 void
     46 accounts_event(UI_ACCOUNTS_Handle *accounts,
     47                MESSENGER_Application *app,
     48                int key)
     49 {
     50   if (accounts->create_dialog.window)
     51   {
     52     account_create_dialog_event(&(accounts->create_dialog), app, key);
     53     return;
     54   }
     55 
     56   list_input_reset(accounts);
     57 
     58   GNUNET_CHAT_iterate_accounts(
     59     app->chat.handle,
     60     &_accounts_iterate,
     61     accounts
     62   );
     63 
     64   list_input_select(accounts, 1, NULL);
     65 
     66   switch (key)
     67   {
     68     case 27:
     69     case KEY_EXIT:
     70       app->chat.quit = TRUE;
     71       break;
     72     case '\n':
     73     case KEY_ENTER:
     74       if (accounts->selected)
     75       {
     76         char new_secret [65];
     77         uint32_t secret_len;
     78         const char *secret;
     79         char *secret_ptr;
     80 
     81         const char *name = GNUNET_CHAT_account_get_name(
     82           accounts->selected
     83         );
     84 
     85         secret_ptr = secret_lookup(name, &secret_len);
     86         secret = secret_ptr;
     87         
     88         if (!secret)
     89         {
     90           secret_len = 64;
     91           if (GNUNET_OK == GNUNET_CHAT_generate_secret(new_secret, secret_len))
     92           {
     93             new_secret[secret_len] = '\0';
     94             
     95             if (secret_store(name, new_secret, secret_len))
     96               secret = new_secret;
     97           }
     98         }
     99 
    100         if (!secret)
    101           secret_len = 0;
    102 
    103         GNUNET_CHAT_connect(
    104           app->chat.handle,
    105           accounts->selected,
    106           secret,
    107           secret_len
    108         );
    109 
    110         if (secret_ptr)
    111           secret_free(secret_ptr);
    112         else
    113           secret_wipe(new_secret);
    114       }
    115       else
    116         accounts->create_dialog.window = &(accounts->window);
    117       break;
    118     case 8:
    119     case KEY_BACKSPACE:
    120       if (accounts->selected)
    121       {
    122         const char *name = GNUNET_CHAT_account_get_name(
    123           accounts->selected
    124         );
    125 
    126         if (GNUNET_OK == GNUNET_CHAT_account_delete(app->chat.handle, name))
    127           secret_delete(name);
    128       }
    129       break;
    130     default:
    131       break;
    132   }
    133 
    134   list_input_event(accounts, key);
    135 }
    136 
    137 static int
    138 _accounts_print_entry(UI_ACCOUNTS_Handle *accounts,
    139                       char type,
    140                       const char *text,
    141                       const void *data)
    142 {
    143   list_input_print_gnunet(accounts, 1);
    144 
    145   const int attrs_select = A_BOLD;
    146 
    147   if (selected) wattron(accounts->window, attrs_select);
    148   else type = ' ';
    149 
    150   wmove(accounts->window, y, 0);
    151 
    152   util_enable_unique_color(accounts->window, data);
    153 
    154   wprintw(accounts->window, "[%c] %s", type, text);
    155 
    156   util_disable_unique_color(accounts->window, data);
    157 
    158   if (selected) wattroff(accounts->window, attrs_select);
    159 
    160   return GNUNET_YES;
    161 }
    162 
    163 int
    164 _accounts_iterate_print(void *cls,
    165                         UNUSED struct GNUNET_CHAT_Handle *handle,
    166                         struct GNUNET_CHAT_Account *account)
    167 {
    168   UI_ACCOUNTS_Handle *accounts = cls;
    169   const char *name = GNUNET_CHAT_account_get_name(account);
    170   return _accounts_print_entry(accounts, 'x', name, account);
    171 }
    172 
    173 void
    174 accounts_print(UI_ACCOUNTS_Handle *accounts,
    175                MESSENGER_Application *app)
    176 {
    177   if (accounts->create_dialog.window)
    178   {
    179     account_create_dialog_print(&(accounts->create_dialog));
    180     return;
    181   }
    182 
    183   if (!(accounts->window))
    184     return;
    185 
    186   list_input_reset(accounts);
    187   werase(accounts->window);
    188 
    189   GNUNET_CHAT_iterate_accounts(
    190       app->chat.handle,
    191       &_accounts_iterate_print,
    192       accounts
    193   );
    194 
    195   _accounts_print_entry(accounts, '+', "Add account", NULL);
    196 }