source: trunk/gtk/conf.c @ 10031

Last change on this file since 10031 was 10031, checked in by charles, 12 years ago

(trunk) remove unnecessary #includes

  • Property svn:keywords set to Date Rev Author Id
File size: 12.0 KB
Line 
1/******************************************************************************
2 * $Id: conf.c 10031 2010-01-28 13:33:40Z charles $
3 *
4 * Copyright (c) 2005-2008 Transmission authors and contributors
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
23 *****************************************************************************/
24
25#include <errno.h>
26#include <stdio.h>
27#include <stdlib.h>
28#include <string.h>
29
30#include <unistd.h>
31
32#include <glib.h>
33#include <glib/gi18n.h>
34#include <glib/gstdio.h>
35
36#include <libtransmission/transmission.h>
37#include <libtransmission/bencode.h>
38
39#include "conf.h"
40#include "tr-prefs.h"
41#include "util.h"
42
43#define MY_NAME "transmission"
44
45static char * gl_confdir = NULL;
46static char * gl_lockpath = NULL;
47
48/* errstr may be NULL, this might be called before GTK is initialized */
49gboolean
50cf_init( const char   * configDir,
51         char        ** errstr )
52{
53    if( errstr != NULL )
54        *errstr = NULL;
55
56    gl_confdir = g_strdup( configDir );
57
58    if( gtr_mkdir_with_parents( gl_confdir, 0755 ) )
59        return TRUE;
60
61    if( errstr != NULL )
62        *errstr = g_strdup_printf( _( "Couldn't create \"%1$s\": %2$s" ),
63                                  gl_confdir, g_strerror( errno ) );
64
65    return FALSE;
66}
67
68/***
69****
70****  Lockfile
71****
72***/
73
74/* errstr may be NULL, this might be called before GTK is initialized */
75static gboolean
76lockfile( const char             * filename,
77          gtr_lockfile_state_t   * tr_state,
78          char                  ** errstr )
79{
80    const gtr_lockfile_state_t state = gtr_lockfile( filename );
81    const gboolean success = state == GTR_LOCKFILE_SUCCESS;
82
83    if( errstr ) switch( state )
84        {
85            case GTR_LOCKFILE_EOPEN:
86                *errstr =
87                    g_strdup_printf( _( "Couldn't open \"%1$s\": %2$s" ),
88                                    filename, g_strerror( errno ) );
89                break;
90
91            case GTR_LOCKFILE_ELOCK:
92                *errstr = g_strdup_printf( _( "%s is already running." ),
93                                          g_get_application_name( ) );
94                break;
95
96            case GTR_LOCKFILE_SUCCESS:
97                *errstr = NULL;
98                break;
99        }
100
101    if( tr_state != NULL )
102        *tr_state = state;
103
104    return success;
105}
106
107static char*
108getLockFilename( void )
109{
110    g_assert( gl_confdir != NULL );
111    return g_build_filename( gl_confdir, "lock", NULL );
112}
113
114static void
115cf_removelocks( void )
116{
117    if( gl_lockpath )
118    {
119        g_unlink( gl_lockpath );
120        g_free( gl_lockpath );
121    }
122}
123
124/* errstr may be NULL, this might be called before GTK is initialized */
125gboolean
126cf_lock( gtr_lockfile_state_t * tr_state, char ** errstr )
127{
128    char *         path = getLockFilename( );
129    const gboolean didLock = lockfile( path, tr_state, errstr );
130
131    if( didLock )
132        gl_lockpath = g_strdup( path );
133    g_atexit( cf_removelocks );
134    g_free( path );
135    return didLock;
136}
137
138/***
139****
140****  Preferences
141****
142***/
143
144static void cf_check_older_configs( void );
145
146/**
147 * This is where we initialize the preferences file with the default values.
148 * If you add a new preferences key, you /must/ add a default value here.
149 */
150static void
151tr_prefs_init_defaults( tr_benc * d )
152{
153    const char * str;
154
155    cf_check_older_configs( );
156
157#ifdef HAVE_GIO
158    str = NULL;
159    if( !str ) str = g_get_user_special_dir( G_USER_DIRECTORY_DOWNLOAD );
160    if( !str ) str = g_get_user_special_dir( G_USER_DIRECTORY_DESKTOP );
161    if( !str ) str = tr_getDefaultDownloadDir( );
162    tr_bencDictAddStr( d, PREF_KEY_DIR_WATCH, str );
163    tr_bencDictAddBool( d, PREF_KEY_DIR_WATCH_ENABLED, FALSE );
164#endif
165
166    tr_bencDictAddBool( d, PREF_KEY_USER_HAS_GIVEN_INFORMED_CONSENT, FALSE );
167    tr_bencDictAddBool( d, PREF_KEY_INHIBIT_HIBERNATION, FALSE );
168    tr_bencDictAddBool( d, PREF_KEY_BLOCKLIST_UPDATES_ENABLED, TRUE );
169
170    tr_bencDictAddStr( d, PREF_KEY_OPEN_DIALOG_FOLDER, g_get_home_dir( ) );
171
172    tr_bencDictAddBool( d, PREF_KEY_TOOLBAR, TRUE );
173    tr_bencDictAddBool( d, PREF_KEY_FILTERBAR, TRUE );
174    tr_bencDictAddBool( d, PREF_KEY_STATUSBAR, TRUE );
175    tr_bencDictAddBool( d, PREF_KEY_SHOW_TRAY_ICON, FALSE );
176    tr_bencDictAddBool( d, PREF_KEY_PLAY_DOWNLOAD_COMPLETE_SOUND, TRUE );
177    tr_bencDictAddBool( d, PREF_KEY_SHOW_DESKTOP_NOTIFICATION, TRUE );
178    tr_bencDictAddBool( d, PREF_KEY_SHOW_MORE_TRACKER_INFO, FALSE );
179    tr_bencDictAddBool( d, PREF_KEY_SHOW_MORE_PEER_INFO, FALSE );
180    tr_bencDictAddBool( d, PREF_KEY_SHOW_BACKUP_TRACKERS, FALSE );
181    tr_bencDictAddStr( d, PREF_KEY_STATUSBAR_STATS, "total-ratio" );
182
183    tr_bencDictAddBool( d, PREF_KEY_OPTIONS_PROMPT, TRUE );
184
185    tr_bencDictAddBool( d, PREF_KEY_MAIN_WINDOW_IS_MAXIMIZED, FALSE );
186    tr_bencDictAddInt( d, PREF_KEY_MAIN_WINDOW_HEIGHT, 500 );
187    tr_bencDictAddInt( d, PREF_KEY_MAIN_WINDOW_WIDTH, 300 );
188    tr_bencDictAddInt( d, PREF_KEY_MAIN_WINDOW_X, 50 );
189    tr_bencDictAddInt( d, PREF_KEY_MAIN_WINDOW_Y, 50 );
190    tr_bencDictAddStr( d, PREF_KEY_MAIN_WINDOW_LAYOUT_ORDER, "menu,toolbar,filter,list,statusbar" );
191
192    str = NULL;
193#if GLIB_CHECK_VERSION( 2, 14, 0 )
194    if( !str ) str = g_get_user_special_dir( G_USER_DIRECTORY_DOWNLOAD );
195#endif
196    if( !str ) str = tr_getDefaultDownloadDir( );
197    tr_bencDictAddStr( d, TR_PREFS_KEY_DOWNLOAD_DIR, str );
198
199    tr_bencDictAddBool( d, PREF_KEY_ASKQUIT, TRUE );
200
201    tr_bencDictAddStr( d, PREF_KEY_FILTER_MODE, "show-all" );
202    tr_bencDictAddStr( d, PREF_KEY_SORT_MODE, "sort-by-name" );
203    tr_bencDictAddBool( d, PREF_KEY_SORT_REVERSED, FALSE );
204    tr_bencDictAddBool( d, PREF_KEY_MINIMAL_VIEW, FALSE );
205
206    tr_bencDictAddBool( d, PREF_KEY_START, TRUE );
207    tr_bencDictAddBool( d, PREF_KEY_TRASH_ORIGINAL, FALSE );
208}
209
210static char*
211getPrefsFilename( void )
212{
213    g_assert( gl_confdir != NULL );
214    return g_build_filename( gl_confdir, "settings.json", NULL );
215}
216
217static tr_benc*
218getPrefs( void )
219{
220    static tr_benc settings;
221    static gboolean loaded = FALSE;
222
223    if( !loaded )
224    {
225        tr_bencInitDict( &settings, 0 );
226        tr_prefs_init_defaults( &settings );
227        tr_sessionLoadSettings( &settings, gl_confdir, MY_NAME );
228        loaded = TRUE;
229    }
230
231    return &settings;
232}
233
234/***
235****
236***/
237
238tr_benc*
239pref_get_all( void )
240{
241    return getPrefs( );
242}
243
244int64_t
245pref_int_get( const char * key )
246{
247    int64_t i = 0;
248
249    tr_bencDictFindInt( getPrefs( ), key, &i );
250    return i;
251}
252
253void
254pref_int_set( const char * key,
255              int64_t      value )
256{
257    tr_bencDictAddInt( getPrefs( ), key, value );
258}
259
260double
261pref_double_get( const char * key )
262{
263    double d = 0.0;
264    tr_bencDictFindReal( getPrefs( ), key, &d );
265    return d;
266}
267
268void
269pref_double_set( const char * key,
270                 double       value )
271{
272    tr_bencDictAddReal( getPrefs( ), key, value );
273}
274
275/***
276****
277***/
278
279gboolean
280pref_flag_get( const char * key )
281{
282    tr_bool boolVal;
283    tr_bencDictFindBool( getPrefs( ), key, &boolVal );
284    return boolVal != 0;
285}
286
287gboolean
288pref_flag_eval( pref_flag_t  val,
289                const char * key )
290{
291    switch( val )
292    {
293        case PREF_FLAG_TRUE:
294            return TRUE;
295
296        case PREF_FLAG_FALSE:
297            return FALSE;
298
299        default:
300            return pref_flag_get( key );
301    }
302}
303
304void
305pref_flag_set( const char * key,
306               gboolean     value )
307{
308    tr_bencDictAddBool( getPrefs( ), key, value );
309}
310
311/***
312****
313***/
314
315const char*
316pref_string_get( const char * key )
317{
318    const char * str = NULL;
319    tr_bencDictFindStr( getPrefs( ), key, &str );
320    return str;
321}
322
323void
324pref_string_set( const char * key, const char * value )
325{
326    tr_bencDictAddStr( getPrefs( ), key, value );
327}
328
329/***
330****
331***/
332
333void
334pref_save( tr_session * session )
335{
336    tr_sessionSaveSettings( session, gl_confdir, getPrefs( ) );
337}
338
339/***
340****
341***/
342
343#if !GLIB_CHECK_VERSION( 2, 8, 0 )
344static void
345tr_file_set_contents( const char *   filename,
346                      const void *   out,
347                      size_t         len,
348                      GError* unused UNUSED )
349{
350    FILE * fp = fopen( filename, "wb+" );
351
352    if( fp != NULL )
353    {
354        fwrite( out, 1, len, fp );
355        fclose( fp );
356    }
357}
358
359 #define g_file_set_contents tr_file_set_contents
360#endif
361
362static char*
363getCompat090PrefsFilename( void )
364{
365    g_assert( gl_confdir != NULL );
366
367    return g_build_filename( g_get_home_dir( ), ".transmission", "gtk", "prefs.ini", NULL );
368}
369
370static char*
371getCompat121PrefsFilename( void )
372{
373    return g_build_filename( g_get_user_config_dir( ), "transmission", "gtk", "prefs.ini", NULL );
374}
375
376static void
377translate_keyfile_to_json( const char * old_file,
378                           const char * new_file )
379{
380    tr_benc    dict;
381    GKeyFile * keyfile;
382    gchar **   keys;
383    gsize      i;
384    gsize      length;
385
386    static struct pref_entry {
387        const char*   oldkey;
388        const char*   newkey;
389    } renamed[] = {
390        { "default-download-directory", "download-dir"             },
391        { "encrypted-connections-only", "encryption"               },
392        { "listening-port",             "peer-port"                },
393        { "nat-traversal-enabled",      "port-forwarding-enabled"  },
394        { "open-dialog-folder",         "open-dialog-dir"          },
395        { "watch-folder",               "watch-dir"                },
396        { "watch-folder-enabled",       "watch-dir-enabled"        }
397    };
398
399    keyfile = g_key_file_new( );
400    g_key_file_load_from_file( keyfile, old_file, 0, NULL );
401    length = 0;
402    keys = g_key_file_get_keys( keyfile, "general", &length, NULL );
403
404    tr_bencInitDict( &dict, length );
405    for( i = 0; i < length; ++i )
406    {
407        guint        j;
408        const char * key = keys[i];
409        gchar *      val = g_key_file_get_value( keyfile, "general", key,
410                                                 NULL );
411
412        for( j = 0; j < G_N_ELEMENTS( renamed ); ++j )
413            if( !strcmp( renamed[j].oldkey, key ) )
414                key = renamed[j].newkey;
415
416        if( !strcmp( val, "true" ) || !strcmp( val, "false" ) )
417            tr_bencDictAddInt( &dict, key, !strcmp( val, "true" ) );
418        else
419        {
420            char * end;
421            long   l;
422            errno = 0;
423            l = strtol( val, &end, 10 );
424            if( !errno && end && !*end )
425                tr_bencDictAddInt( &dict, key, l );
426            else
427                tr_bencDictAddStr( &dict, key, val );
428        }
429
430        g_free( val );
431    }
432
433    g_key_file_free( keyfile );
434    tr_bencToFile( &dict, TR_FMT_JSON, new_file );
435    tr_bencFree( &dict );
436}
437
438static void
439cf_check_older_configs( void )
440{
441    char * filename = getPrefsFilename( );
442
443    if( !g_file_test( filename, G_FILE_TEST_IS_REGULAR ) )
444    {
445        char * key1 = getCompat121PrefsFilename( );
446        char * key2 = getCompat090PrefsFilename( );
447
448        if( g_file_test( key1, G_FILE_TEST_IS_REGULAR ) )
449        {
450            g_message( _( "Importing \"%s\"" ), key1 );
451            translate_keyfile_to_json( key1, filename );
452        }
453        else if( g_file_test( key2, G_FILE_TEST_IS_REGULAR ) )
454        {
455            g_message( _( "Importing \"%s\"" ), key2 );
456            translate_keyfile_to_json( key2, filename );
457        }
458
459        g_free( key2 );
460        g_free( key1 );
461    }
462
463    g_free( filename );
464}
Note: See TracBrowser for help on using the repository browser.