1/* MiniUPnP project
2 * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
3 * author: Ryan Wagoner
4 *
5 * Copyright (c) 2006, Thomas Bernard
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions are met:
10 *     * Redistributions of source code must retain the above copyright
11 *       notice, this list of conditions and the following disclaimer.
12 *     * Redistributions in binary form must reproduce the above copyright
13 *       notice, this list of conditions and the following disclaimer in the
14 *       documentation and/or other materials provided with the distribution.
15 *     * The name of the author may not be used to endorse or promote products
16 *       derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
22 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 * POSSIBILITY OF SUCH DAMAGE.
29 */
30#include <stdio.h>
31#include <string.h>
32#include <stdlib.h>
33#include <ctype.h>
34#include "options.h"
35#include "utils.h"
36#include "upnpglobalvars.h"
37
38struct option * ary_options = NULL;
39int num_options = 0;
40
41static const struct {
42	enum upnpconfigoptions id;
43	const char * name;
44} optionids[] = {
45	{ UPNPIFNAME, "network_interface" },
46	{ UPNPPORT, "port" },
47	{ UPNPPRESENTATIONURL, "presentation_url" },
48	{ UPNPNOTIFY_INTERVAL, "notify_interval" },
49	{ UPNPUUID, "uuid"},
50	{ UPNPSERIAL, "serial"},
51	{ UPNPMODEL_NAME, "model_name"},
52	{ UPNPMODEL_NUMBER, "model_number"},
53	{ UPNPFRIENDLYNAME, "friendly_name"},
54	{ UPNPMEDIADIR, "media_dir"},
55	{ UPNPALBUMART_NAMES, "album_art_names"},
56	{ UPNPINOTIFY, "inotify" },
57	{ UPNPDBDIR, "db_dir" },
58	{ UPNPLOGDIR, "log_dir" },
59	{ UPNPLOGLEVEL, "log_level" },
60	{ UPNPMINISSDPDSOCKET, "minissdpdsocket"},
61	{ ENABLE_TIVO, "enable_tivo" },
62	{ ENABLE_DLNA_STRICT, "strict_dlna" },
63	{ ROOT_CONTAINER, "root_container" },
64	{ USER_ACCOUNT, "user" },
65	{ FORCE_SORT_CRITERIA, "force_sort_criteria" },
66	{ MAX_CONNECTIONS, "max_connections" },
67	{ MERGE_MEDIA_DIRS, "merge_media_dirs" }
68};
69
70int
71readoptionsfile(const char * fname)
72{
73	FILE *hfile = NULL;
74	char buffer[1024];
75	char *equals;
76	char *name;
77	char *value;
78	char *t;
79	int linenum = 0;
80	int i;
81	enum upnpconfigoptions id;
82
83	if(!fname || *fname == '\0')
84		return -1;
85
86	memset(buffer, 0, sizeof(buffer));
87
88#ifdef DEBUG
89	printf("Reading configuration from file %s\n", fname);
90#endif
91
92	if(!(hfile = fopen(fname, "r")))
93		return -1;
94
95	while(fgets(buffer, sizeof(buffer), hfile))
96	{
97		linenum++;
98		t = strchr(buffer, '\n');
99		if(t)
100		{
101			*t = '\0';
102			t--;
103			while((t >= buffer) && isspace(*t))
104			{
105				*t = '\0';
106				t--;
107			}
108		}
109
110		/* skip leading whitespaces */
111		name = buffer;
112		while(isspace(*name))
113			name++;
114
115		/* check for comments or empty lines */
116		if(name[0] == '#' || name[0] == '\0') continue;
117
118		if(!(equals = strchr(name, '=')))
119		{
120			fprintf(stderr, "parsing error file %s line %d : %s\n",
121			        fname, linenum, name);
122			continue;
123		}
124
125		/* remove ending whitespaces */
126		for(t=equals-1; t>name && isspace(*t); t--)
127			*t = '\0';
128
129		*equals = '\0';
130		value = equals+1;
131
132		/* skip leading whitespaces */
133		while(isspace(*value))
134			value++;
135
136		id = UPNP_INVALID;
137		for(i=0; i<sizeof(optionids)/sizeof(optionids[0]); i++)
138		{
139			/*printf("%2d %2d %s %s\n", i, optionids[i].id, name,
140			       optionids[i].name); */
141
142			if(0 == strcmp(name, optionids[i].name))
143			{
144				id = optionids[i].id;
145				break;
146			}
147		}
148
149		if(id == UPNP_INVALID)
150		{
151			if (strcmp(name, "include") == 0)
152				readoptionsfile(value);
153			else
154				fprintf(stderr, "parsing error file %s line %d : %s=%s\n",
155				        fname, linenum, name, value);
156		}
157		else
158		{
159			num_options++;
160			t = realloc(ary_options, num_options * sizeof(struct option));
161			if(!t)
162			{
163				fprintf(stderr, "memory allocation error: %s=%s\n",
164					name, value);
165				num_options--;
166				continue;
167			}
168			else
169				ary_options = (struct option *)t;
170
171			ary_options[num_options-1].id = id;
172			strncpyt(ary_options[num_options-1].value, value, MAX_OPTION_VALUE_LEN);
173		}
174
175	}
176
177	fclose(hfile);
178
179	return 0;
180}
181
182void
183freeoptions(void)
184{
185	struct media_dir_s *media_path, *last_path;
186	struct album_art_name_s *art_names, *last_name;
187
188	media_path = media_dirs;
189	while (media_path)
190	{
191		free(media_path->path);
192		last_path = media_path;
193		media_path = media_path->next;
194		free(last_path);
195	}
196
197	art_names = album_art_names;
198	while (art_names)
199	{
200		free(art_names->name);
201		last_name = art_names;
202		art_names = art_names->next;
203		free(last_name);
204	}
205
206	if(ary_options)
207	{
208		free(ary_options);
209		ary_options = NULL;
210		num_options = 0;
211	}
212}
213
214