1 /** \file
2 *
3 * \author Copyright 2000 Scott Fritzinger
4 *
5 * \par License
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
10 *
11 * \par
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * \par
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the
20 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21 * Boston, MA 02110-1301 USA
22 */
23
24 #define _DEFAULT_SOURCE
25
26 #include "config.h"
27 #include <gphoto2/gphoto2-setting.h>
28
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32
33 #include <gphoto2/gphoto2-result.h>
34 #include <gphoto2/gphoto2-port-log.h>
35 #include <gphoto2/gphoto2-port-portability.h>
36
37 #ifdef WIN32
38 /* Win32 headers may use interface as a define; temporarily correct this */
39 #define interface struct
40 #include <Shlobj.h>
41 #undef interface
42 #endif
43
44 /**
45 * Internal struct to store settings.
46 */
47 typedef struct {
48 /* key = value settings */
49 char id[256];
50 char key[256];
51 char value[256];
52 } Setting;
53
54 /* Currently loaded settings */
55 static int glob_setting_count = 0;
56 static Setting glob_setting[512];
57
58 static int save_settings (void);
59
60 #define CHECK_RESULT(result) {int r = (result); if (r < 0) return (r);}
61
62 static int load_settings (void);
63
64 /**
65 * \brief Retrieve a specific gphoto setting.
66 * \param id the frontend id of the caller
67 * \param key the key the frontend queries
68 * \param value changed value
69 * \return GPhoto error code
70 *
71 * This function retrieves the setting key for a specific frontend
72 * id and copies the value into the passed value pointer.
73 */
74 int
gp_setting_get(char * id,char * key,char * value)75 gp_setting_get (char *id, char *key, char *value)
76 {
77 int x;
78
79 C_PARAMS (id && key);
80
81 if (!glob_setting_count)
82 load_settings ();
83
84 for (x=0; x<glob_setting_count; x++) {
85 if ((strcmp(glob_setting[x].id, id)==0) &&
86 (strcmp(glob_setting[x].key, key)==0)) {
87 strcpy(value, glob_setting[x].value);
88 return (GP_OK);
89 }
90 }
91 strcpy(value, "");
92 return(GP_ERROR);
93 }
94
95 /**
96 * \brief Set a specific gphoto setting.
97 *
98 * \param id the frontend id of the caller
99 * \param key the key the frontend queries
100 * \param value new value
101 * \return GPhoto error code
102 *
103 * This function sets the setting key for a specific frontend
104 * id to the value.
105 */
106 int
gp_setting_set(char * id,char * key,char * value)107 gp_setting_set (char *id, char *key, char *value)
108 {
109 int x;
110
111 C_PARAMS (id && key);
112
113 if (!glob_setting_count)
114 load_settings ();
115
116 GP_LOG_D ("Setting key '%s' to value '%s' (%s)", key, value, id);
117
118 for (x=0; x<glob_setting_count; x++) {
119 if ((strcmp(glob_setting[x].id, id)==0) &&
120 (strcmp(glob_setting[x].key, key)==0)) {
121 strcpy(glob_setting[x].value, value);
122 save_settings ();
123 return (GP_OK);
124 }
125 }
126 strcpy(glob_setting[glob_setting_count].id, id);
127 strcpy(glob_setting[glob_setting_count].key, key);
128 strcpy(glob_setting[glob_setting_count++].value, value);
129 save_settings ();
130
131 return (GP_OK);
132 }
133
134 static int
verify_settings(char * settings_file)135 verify_settings (char *settings_file)
136 {
137 FILE *f;
138 char buf[1024];
139 unsigned int x, equals;
140
141 if ((f=fopen(settings_file, "r"))==NULL) {
142 GP_LOG_D ("Can't open settings file '%s' for reading.", settings_file);
143 return(0);
144 }
145
146 rewind(f);
147 while (!feof(f)) {
148 strcpy(buf, "");
149 if (!fgets(buf, 1023, f))
150 break;
151 buf[strlen(buf)] = 0;
152 if (strlen(buf)>2) {
153 equals = 0;
154 for (x=0; x<strlen(buf); x++)
155 if (buf[x] == '=')
156 equals++;
157
158 if (equals < 2) {
159 fclose (f);
160 GP_LOG_E ("Incorrect settings format. Resetting.");
161 unlink(settings_file);
162 return (GP_ERROR);
163 }
164 }
165 }
166 fclose (f);
167
168 return (GP_OK);
169 }
170
171 static int
load_settings(void)172 load_settings (void)
173 {
174 FILE *f;
175 char buf[1024], *id, *key, *value;
176
177 /* Make sure the directories are created */
178 #ifdef WIN32
179 SHGetFolderPath(NULL, CSIDL_PROFILE, NULL, 0, buf);
180 strcat (buf, "\\.gphoto");
181 #else
182 snprintf (buf, sizeof(buf), "%s/.gphoto", getenv ("HOME"));
183 #endif
184 GP_LOG_D ("Creating gphoto config directory ('%s')", buf);
185 (void)gp_system_mkdir (buf);
186
187 glob_setting_count = 0;
188 #ifdef WIN32
189 SHGetFolderPath(NULL, CSIDL_PROFILE, NULL, 0, buf);
190 strcat(buf, "\\.gphoto\\settings");
191 #else
192 snprintf(buf, sizeof(buf), "%s/.gphoto/settings", getenv("HOME"));
193 #endif
194
195 if (verify_settings(buf) != GP_OK)
196 /* verify_settings will unlink and recreate the settings file */
197 return (GP_OK);
198 GP_LOG_D ("Loading settings from file '%s'.", buf);
199
200 if ((f=fopen(buf, "r"))==NULL) {
201 GP_LOG_D ("Can't open settings file '%s' for reading.", buf);
202 return(GP_ERROR);
203 }
204
205 rewind(f);
206 while (!feof(f)) {
207 strcpy(buf, "");
208 if (!fgets(buf, 1023, f))
209 break;
210 if (strlen(buf)>2) {
211 buf[strlen(buf)-1] = '\0';
212 id = strtok(buf, "=");
213 strcpy(glob_setting[glob_setting_count].id,id);
214 key = strtok(NULL, "=");
215 strcpy(glob_setting[glob_setting_count].key,key);
216 value = strtok(NULL, "\0");
217 if (value)
218 strcpy(glob_setting[glob_setting_count++].value, value);
219 else
220 strcpy(glob_setting[glob_setting_count++].value, "");
221 }
222 }
223 fclose (f);
224 return (GP_OK);
225 }
226
227
228 static int
save_settings(void)229 save_settings (void)
230 {
231 FILE *f;
232 char buf[1024];
233 int x=0;
234
235 #ifdef WIN32
236 SHGetFolderPath(NULL, CSIDL_PROFILE, NULL, 0, buf);
237 strcat(buf, "\\.gphoto\\settings");
238 #else
239 snprintf (buf, sizeof(buf), "%s/.gphoto/settings", getenv ("HOME"));
240 #endif
241
242
243 GP_LOG_D ("Saving %i setting(s) to file \"%s\"", glob_setting_count, buf);
244
245 if ((f=fopen(buf, "w+"))==NULL) {
246 GP_LOG_E ("Can't open settings file for writing.");
247 return(0);
248 }
249 rewind(f);
250 while (x < glob_setting_count) {
251 fwrite(glob_setting[x].id, strlen(glob_setting[x].id),1,f);
252 fputc('=', f);
253 fwrite(glob_setting[x].key, strlen(glob_setting[x].key),1,f);
254 fputc('=', f);
255 fwrite(glob_setting[x].value, strlen(glob_setting[x].value),1,f);
256 fputc('\n', f);
257 x++;
258 }
259 fclose(f);
260
261 return (GP_OK);
262 }
263
264 #if 0
265 static int dump_settings (void)
266 {
267 int x;
268
269 gp_debug_printf(GP_DEBUG_LOW, "core", "All settings:");
270 for (x=0; x<glob_setting_count; x++)
271 gp_debug_printf(GP_DEBUG_LOW, "core", "\t (%s) \"%s\" = \"%s\"", glob_setting[x].id,
272 glob_setting[x].key,glob_setting[x].value);
273 if (glob_setting_count == 0)
274 gp_debug_printf(GP_DEBUG_LOW, "core", "\tNone");
275 gp_debug_printf(GP_DEBUG_LOW, "core", "Total settings: %i", glob_setting_count);
276
277 return (GP_OK);
278 }
279 #endif
280