source: set.c @ 12fe5ea

Last change on this file since 12fe5ea was 434ffa2, checked in by dequis <dx@…>, at 2015-01-16T19:50:24Z

set_setint: use g_strdup_printf instead of relying on a char s[24];

  • Property mode set to 100644
File size: 5.9 KB
RevLine 
[b7d3cc34]1  /********************************************************************\
2  * BitlBee -- An IRC to other IM-networks gateway                     *
3  *                                                                    *
[03886fc]4  * Copyright 2002-2013 Wilmer van der Gaast and others                *
[b7d3cc34]5  \********************************************************************/
6
7/* Some stuff to register, handle and save user preferences             */
8
9/*
10  This program is free software; you can redistribute it and/or modify
11  it under the terms of the GNU General Public License as published by
12  the Free Software Foundation; either version 2 of the License, or
13  (at your option) any later version.
14
15  This program is distributed in the hope that it will be useful,
16  but WITHOUT ANY WARRANTY; without even the implied warranty of
17  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  GNU General Public License for more details.
19
20  You should have received a copy of the GNU General Public License with
21  the Debian GNU/Linux distribution in /usr/share/common-licenses/GPL;
[6f10697]22  if not, write to the Free Software Foundation, Inc., 51 Franklin St.,
23  Fifth Floor, Boston, MA  02110-1301  USA
[b7d3cc34]24*/
[03886fc]25
[b7d3cc34]26#define BITLBEE_CORE
27#include "bitlbee.h"
28
[7125cb3]29/* Used to use NULL for this, but NULL is actually a "valid" value. */
30char *SET_INVALID = "nee";
31
[0f7ee7e5]32set_t *set_add( set_t **head, const char *key, const char *def, set_eval eval, void *data )
[b7d3cc34]33{
[5c9512f]34        set_t *s = set_find( head, key );
[b7d3cc34]35       
[5c9512f]36        /* Possibly the setting already exists. If it doesn't exist yet,
37           we create it. If it does, we'll just change the default. */
[b7d3cc34]38        if( !s )
39        {
[5c9512f]40                if( ( s = *head ) )
[b7d3cc34]41                {
[03886fc]42                        /* Sorted insertion. Special-case insertion at the start. */
43                        if( strcmp( key, s->key ) < 0 )
44                        {
45                                s = g_new0( set_t, 1 );
46                                s->next = *head;
47                                *head = s;
48                        }
49                        else
50                        {
51                                while( s->next && strcmp( key, s->next->key ) > 0 )
52                                        s = s->next;
53                                set_t *last_next = s->next;
54                                s->next = g_new0( set_t, 1 );
55                                s = s->next;
56                                s->next = last_next;
57                        }
[b7d3cc34]58                }
59                else
60                {
[5c9512f]61                        s = *head = g_new0( set_t, 1 );
[b7d3cc34]62                }
63                s->key = g_strdup( key );
64        }
65       
66        if( s->def )
67        {
68                g_free( s->def );
69                s->def = NULL;
70        }
71        if( def ) s->def = g_strdup( def );
72       
[5c9512f]73        s->eval = eval;
74        s->data = data;
[b7d3cc34]75       
[5c9512f]76        return s;
[b7d3cc34]77}
78
[b74b287]79set_t *set_find( set_t **head, const char *key )
[b7d3cc34]80{
[5c9512f]81        set_t *s = *head;
[b7d3cc34]82       
83        while( s )
84        {
[88eaf4b]85                if( g_strcasecmp( s->key, key ) == 0 ||
86                    ( s->old_key && g_strcasecmp( s->old_key, key ) == 0 ) )
[b7d3cc34]87                        break;
88                s = s->next;
89        }
90       
[5c9512f]91        return s;
[b7d3cc34]92}
93
[b74b287]94char *set_getstr( set_t **head, const char *key )
[b7d3cc34]95{
[5c9512f]96        set_t *s = set_find( head, key );
[b7d3cc34]97       
98        if( !s || ( !s->value && !s->def ) )
[5c9512f]99                return NULL;
[b7d3cc34]100       
[ce199b7]101        return set_value( s );
[b7d3cc34]102}
103
[b74b287]104int set_getint( set_t **head, const char *key )
[b7d3cc34]105{
[5c9512f]106        char *s = set_getstr( head, key );
[b7d3cc34]107        int i = 0;
108       
109        if( !s )
[5c9512f]110                return 0;
[b7d3cc34]111       
112        if( sscanf( s, "%d", &i ) != 1 )
[5c9512f]113                return 0;
[b7d3cc34]114       
[5c9512f]115        return i;
[b7d3cc34]116}
117
[b74b287]118int set_getbool( set_t **head, const char *key )
[5100caa]119{
120        char *s = set_getstr( head, key );
121       
122        if( !s )
123                return 0;
124       
125        return bool2int( s );
126}
127
[06b5893]128int set_isvisible( set_t *set )
129{
130        /* the default value is not stored in value, only in def */
131        return !( ( set->flags & SET_HIDDEN ) ||
132                  ( ( set->flags & SET_HIDDEN_DEFAULT ) &&
133                    ( set->value == NULL ) ) );
134}
135
[b74b287]136int set_setstr( set_t **head, const char *key, char *value )
[b7d3cc34]137{
[5c9512f]138        set_t *s = set_find( head, key );
[b7d3cc34]139        char *nv = value;
140       
141        if( !s )
[7125cb3]142                /*
143                Used to do this, but it never really made sense.
[5c9512f]144                s = set_add( head, key, NULL, NULL, NULL );
[7125cb3]145                */
146                return 0;
[b7d3cc34]147       
[7125cb3]148        if( value == NULL && ( s->flags & SET_NULL_OK ) == 0 )
149                return 0;
150       
151        /* Call the evaluator. For invalid values, evaluators should now
152           return SET_INVALID, but previously this was NULL. Try to handle
153           that too if NULL is not an allowed value for this setting. */
154        if( s->eval && ( ( nv = s->eval( s, value ) ) == SET_INVALID ||
155                         ( ( s->flags & SET_NULL_OK ) == 0 && nv == NULL ) ) )
[5c9512f]156                return 0;
[b7d3cc34]157       
158        if( s->value )
159        {
160                g_free( s->value );
161                s->value = NULL;
162        }
163       
[5c9512f]164        /* If there's a default setting and it's equal to what we're trying to
165           set, stick with s->value = NULL. Otherwise, remember the setting. */
[b7d3cc34]166        if( !s->def || ( strcmp( nv, s->def ) != 0 ) )
167                s->value = g_strdup( nv );
168       
169        if( nv != value )
170                g_free( nv );
171       
[5c9512f]172        return 1;
[b7d3cc34]173}
174
[b74b287]175int set_setint( set_t **head, const char *key, int value )
[b7d3cc34]176{
[434ffa2]177        char *s = g_strdup_printf( "%d", value );
178        int retval = set_setstr( head, key, s );
179        g_free( s );
180        return retval;
[b7d3cc34]181}
182
[b74b287]183void set_del( set_t **head, const char *key )
[b7d3cc34]184{
[5c9512f]185        set_t *s = *head, *t = NULL;
[b7d3cc34]186       
187        while( s )
188        {
189                if( g_strcasecmp( s->key, key ) == 0 )
190                        break;
191                s = (t=s)->next;
192        }
193        if( s )
194        {
[dd89a55]195                if( t )
196                        t->next = s->next;
197                else
[5c9512f]198                        *head = s->next;
[dd89a55]199               
[b7d3cc34]200                g_free( s->key );
[88eaf4b]201                g_free( s->old_key );
202                g_free( s->value );
203                g_free( s->def );
[b7d3cc34]204                g_free( s );
205        }
206}
207
[b74b287]208int set_reset( set_t **head, const char *key )
[cd428e4]209{
210        set_t *s;
211       
212        s = set_find( head, key );
213        if( s )
[f3579fd]214                return set_setstr( head, key, s->def );
215       
216        return 0;
[cd428e4]217}
218
[5c9512f]219char *set_eval_int( set_t *set, char *value )
[b7d3cc34]220{
[6237ded]221        char *s = value;
[b7d3cc34]222       
[5eec897]223        /* Allow a minus at the first position. */
224        if( *s == '-' )
225                s ++;
226       
[6237ded]227        for( ; *s; s ++ )
[6b13103]228                if( !g_ascii_isdigit( *s ) )
[7125cb3]229                        return SET_INVALID;
[b7d3cc34]230       
[5c9512f]231        return value;
[b7d3cc34]232}
233
[5c9512f]234char *set_eval_bool( set_t *set, char *value )
[b7d3cc34]235{
[7125cb3]236        return is_bool( value ) ? value : SET_INVALID;
[b7d3cc34]237}
238
[56244c0]239char *set_eval_list( set_t *set, char *value )
240{
241        GSList *options = set->eval_data, *opt;
242       
243        for( opt = options; opt; opt = opt->next )
244                if( strcmp( value, opt->data ) == 0 )
245                        return value;
246       
247        /* TODO: It'd be nice to show the user a list of allowed values,
248                 but we don't have enough context here to do that. May
249                 want to fix that. */
250       
251        return NULL;
252}
253
[5c9512f]254char *set_eval_to_char( set_t *set, char *value )
[b7d3cc34]255{
256        char *s = g_new( char, 3 );
257       
258        if( *value == ' ' )
259                strcpy( s, " " );
260        else
261                sprintf( s, "%c ", *value );
262       
[5c9512f]263        return s;
[b7d3cc34]264}
265
[ce199b7]266char *set_eval_oauth( set_t *set, char *value )
[b7d3cc34]267{
[ce199b7]268        account_t *acc = set->data;
[b7d3cc34]269       
[ce199b7]270        if( bool2int( value ) && strcmp( acc->pass, PASSWORD_PENDING ) == 0 )
271                *acc->pass = '\0';
272       
273        return set_eval_bool( set, value );
[b7d3cc34]274}
Note: See TracBrowser for help on using the repository browser.