Eliminate MAX_CONFIGS limit using a dynamic array

The number of configs is now unlimited. But there is a limit
of 2^16 menu items which permits only about 2^12 configs to be
displayed in the menu. A warning is shown if the number of
configs exceeds this value.

For a responsive menu keep the number of configs under ~1000.

Signed-off-by: Selva Nair <selva.nair@gmail.com>
pull/298/head
Selva Nair 2018-04-19 22:19:10 -04:00
parent a9898d3819
commit f55eeb1da8
5 changed files with 38 additions and 21 deletions

View File

@ -49,12 +49,6 @@ AC_ARG_ENABLE(
[enable_password_change="yes"] [enable_password_change="yes"]
) )
AC_ARG_VAR([MAX_CONFIGS], [specify the maximum number of configs @<:@default=50@:>@])
if test -z "$MAX_CONFIGS"; then
MAX_CONFIGS=50
fi
AC_DEFINE_UNQUOTED([MAX_CONFIGS], [$MAX_CONFIGS], [Maximum number of config files supported.])
case "$host" in case "$host" in
*-mingw*) *-mingw*)
CPPFLAGS="${CPPFLAGS} -DWIN32_LEAN_AND_MEAN" CPPFLAGS="${CPPFLAGS} -DWIN32_LEAN_AND_MEAN"

2
main.c
View File

@ -80,7 +80,7 @@ VerifyAutoConnections()
{ {
int i; int i;
for (i = 0; i < MAX_CONFIGS && o.auto_connect[i] != 0; i++) for (i = 0; i < o.num_auto_connect; i++)
{ {
if (GetConnByName(o.auto_connect[i]) == NULL) if (GetConnByName(o.auto_connect[i]) == NULL)
{ {

View File

@ -112,7 +112,7 @@ AddConfigFileToList(int config, const TCHAR *filename, const TCHAR *config_dir)
#endif #endif
/* Check if connection should be autostarted */ /* Check if connection should be autostarted */
for (i = 0; i < MAX_CONFIGS && o.auto_connect[i]; ++i) for (i = 0; i < o.num_auto_connect; ++i)
{ {
if (_tcsicmp(c->config_file, o.auto_connect[i]) == 0 if (_tcsicmp(c->config_file, o.auto_connect[i]) == 0
|| _tcsicmp(c->config_name, o.auto_connect[i]) == 0) || _tcsicmp(c->config_name, o.auto_connect[i]) == 0)
@ -265,10 +265,17 @@ BuildFileList0(const TCHAR *config_dir, int recurse_depth, config_group_t *group
/* Loop over each config file in config dir */ /* Loop over each config file in config dir */
do do
{ {
if (o.num_configs >= MAX_CONFIGS) if (!o.conn || o.num_configs == o.max_configs)
{ {
ShowLocalizedMsg(IDS_ERR_MANY_CONFIGS, MAX_CONFIGS); o.max_configs += 50;
break; void *tmp = realloc(o.conn, sizeof(*o.conn)*o.max_configs);
if (!tmp)
{
o.max_configs -= 50;
FindClose(find_handle);
ErrorExit(1, L"Out of memory while scanning configs");
}
o.conn = tmp;
} }
match_t match_type = match(&find_obj, o.ext_string); match_t match_type = match(&find_obj, o.ext_string);
@ -360,6 +367,14 @@ BuildFileList()
if (o.num_configs == 0 && issue_warnings) if (o.num_configs == 0 && issue_warnings)
ShowLocalizedMsg(IDS_NFO_NO_CONFIGS, o.config_dir, o.global_config_dir); ShowLocalizedMsg(IDS_NFO_NO_CONFIGS, o.config_dir, o.global_config_dir);
/* More than MAX_CONFIGS are ignored in the menu listing */
if (o.num_configs > MAX_CONFIGS)
{
if (issue_warnings)
ShowLocalizedMsg(IDS_ERR_MANY_CONFIGS, o.num_configs);
o.num_configs = MAX_CONFIGS; /* menus don't work with more -- ignore the rest */
}
ActivateConfigGroups(); ActivateConfigGroups();
issue_warnings = false; issue_warnings = false;

View File

@ -97,18 +97,22 @@ add_option(options_t *options, int i, TCHAR **p)
else if (streq(p[0], _T("connect")) && p[1]) else if (streq(p[0], _T("connect")) && p[1])
{ {
++i; ++i;
static int auto_connect_nr = 0; if (!options->auto_connect || options->num_auto_connect == options->max_auto_connect)
if (auto_connect_nr == MAX_CONFIGS)
{ {
/* Too many configs */ options->max_auto_connect += 10;
ShowLocalizedMsg(IDS_ERR_MANY_CONFIGS, MAX_CONFIGS); void *tmp = realloc(options->auto_connect, sizeof(wchar_t *)*options->max_auto_connect);
exit(1); if (!tmp)
{
options->max_auto_connect -= 10;
ErrorExit(1, L"Out of memory while parsing command line");
}
options->auto_connect = tmp;
} }
options->auto_connect[auto_connect_nr++] = p[1]; options->auto_connect[options->num_auto_connect++] = p[1];
/* Treat the first connect option to also mean --command connect profile. /* Treat the first connect option to also mean --command connect profile.
* This gets used if we are not the first instance. * This gets used if we are not the first instance.
*/ */
if (auto_connect_nr == 1) if (options->num_auto_connect == 1)
{ {
options->action = WM_OVPN_START; options->action = WM_OVPN_START;
options->action_arg = p[1]; options->action_arg = p[1];

View File

@ -41,7 +41,8 @@ typedef struct connection connection_t;
* including the option name itself. * including the option name itself.
*/ */
#define MAX_PARMS 5 /* Max number of parameters per option */ #define MAX_PARMS 5 /* Max number of parameters per option */
/* Menu ids are constructed as 12 bits for config number, 4 bits for action */
#define MAX_CONFIGS (1<<12)
typedef enum { typedef enum {
service_noaccess = -1, service_noaccess = -1,
@ -155,13 +156,16 @@ struct connection {
/* All options used within OpenVPN GUI */ /* All options used within OpenVPN GUI */
typedef struct { typedef struct {
/* Array of configs to autostart */ /* Array of configs to autostart */
const TCHAR *auto_connect[MAX_CONFIGS]; const TCHAR **auto_connect;
/* Connection parameters */ /* Connection parameters */
connection_t conn[MAX_CONFIGS]; /* Connection structure */ connection_t *conn; /* Array of connection structure */
config_group_t *groups; /* Array of nodes defining the config groups tree */ config_group_t *groups; /* Array of nodes defining the config groups tree */
int num_configs; /* Number of configs */ int num_configs; /* Number of configs */
int num_auto_connect; /* Number of auto-connect configs */
int num_groups; /* Number of config groups */ int num_groups; /* Number of config groups */
int max_configs; /* Current capacity of conn array */
int max_auto_connect; /* Current capacity of auto_connect array */
int max_groups; /* Current capacity of groups array */ int max_groups; /* Current capacity of groups array */
service_state_t service_state; /* State of the OpenVPN Service */ service_state_t service_state; /* State of the OpenVPN Service */