1 /*****************************************************************************
2 * parser.cpp : SAP configuration file parser
3 ****************************************************************************
4 * Copyright (C) 1998-2005 VideoLAN
5 * $Id: parser.cpp 361 2010-10-09 12:14:24Z courmisch $
6 *
7 * Authors: Arnaud Schauly <gitan@via.ecp.fr>
8 * Clément Stenac <zorglub@via.ecp.fr>
9 * Damien Lucas <nitrox@videolan.org>
10 * Philippe Van Hecke <philippe.vanhecke@belnet.be>
11 * Derk-Jan Hartman <hartman at videolan dot org>
12 * Rémi Denis-Courmont <rem at videolan dot org>
13 *
14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 2 of the License, or
17 * (at your option) any later version.
18 *
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
23 *
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, write to the Free Software
26 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
27 *****************************************************************************/
28
29 #ifdef HAVE_CONFIG_H
30 # include <config.h>
31 #endif
32
33 #include <sys/types.h>
34 #include <sys/socket.h>
35 #include <netinet/in.h>
36 #include <arpa/inet.h>
37 #include <time.h>
38 #include <string.h>
39 #include <stdlib.h>
40 #include <stdio.h>
41 #include <unistd.h>
42 #include <string>
43 #include <vector>
44
45 #ifdef HAVE_ICONV
46 # include <langinfo.h>
47 # include <iconv.h>
48 #else
49 //typedef unsigned iconv_t;
50 # define iconv_open( a, b ) ((iconv_t)(-1))
51 # define iconv_close( a ) ((void)0)
52 # define iconv( a, b, c, d, e ) ((size_t)(-1))
53 #endif
54
55
56 using namespace std;
57
58 #include "sapserver.h"
59 #include "program.h"
60 #include "message.h"
61 #include "parser.h"
62
Config(string f)63 Config::Config(string f) : daemon(false), dot(false)
64 {
65 file = f;
66 ttl = DEFAULT_TTL;
67 interface = NULL;
68 delay = DEFAULT_DELAY;
69 type = TYPE_SAP;
70 reverse = false;
71 }
72
~Config()73 Config::~Config()
74 {
75 if (interface != NULL)
76 free (interface);
77 for (int i = Programs.size() - 1; i >= 0; i--)
78 delete Programs[i];
79 }
80
GetTTL()81 unsigned int Config::GetTTL()
82 {
83 return ttl;
84 }
85
SetTTL(unsigned int t)86 void Config::SetTTL(unsigned int t)
87 {
88 ttl=t;
89 }
90
GetDelay()91 unsigned int Config::GetDelay()
92 {
93 return delay;
94 }
95
SetDelay(unsigned int d)96 void Config::SetDelay(unsigned int d)
97 {
98 delay=d;
99 }
100
GetDaemonMode(void)101 bool Config::GetDaemonMode(void)
102 {
103 return daemon;
104 }
105
GetReverse(void)106 bool Config::GetReverse(void)
107 {
108 return reverse;
109 }
110
SetDaemonMode(bool d)111 void Config::SetDaemonMode(bool d)
112 {
113 daemon=d;
114 }
115
GetDotMode(void)116 bool Config::GetDotMode(void)
117 {
118 return dot;
119 }
120
SetDotMode(bool d)121 void Config::SetDotMode(bool d)
122 {
123 dot=d;
124 }
125
126
SetFile(char * s)127 void Config::SetFile(char* s)
128 {
129 file=s;
130 }
131
SetReverse(bool d)132 void Config::SetReverse(bool d)
133 {
134 reverse=d;
135 }
136
SetType(const char * s)137 void Config::SetType(const char *s)
138 {
139 if(!strcasecmp(s,"slp"))
140 {
141 type=TYPE_SLP;
142 }
143 else
144 {
145 type=TYPE_SAP;
146 }
147 }
148
GetType()149 int Config::GetType()
150 {
151 return type;
152 }
153
GetInterface()154 const char *Config::GetInterface()
155 {
156 return interface;
157 }
158
159 /**********************************************************
160 * Gets what is before delim in source. Puts it into dest *
161 **********************************************************/
strgetb(const char * source,char * dest,char delim)162 void Config::strgetb(const char *source,char *dest,char delim)
163 {
164 char *ptr = dest;
165
166 // Cut the line just before the delim char
167 while(*source != '\0' && *source != delim)
168 *(ptr++) = *(source++);
169 *(ptr--) = '\0';
170
171 // Remove the trailing blanks
172 while((ptr >= dest) && isspace(*ptr))
173 *(ptr--) = '\0';
174 }
175
176 /**********************************************************
177 * Gets what is after delim in source. Puts it into dest *
178 **********************************************************/
strgeta(const char * source,char * dest,char delim)179 void Config::strgeta(const char *source,char *dest,char delim)
180 {
181 unsigned long i=0,j=0;
182 dest[0]=0;
183 while(source[i] != delim && i < strlen(source))
184 {
185 i++;
186 }
187 i++;
188 if(i>=strlen(source))
189 {
190 return;
191 }
192 while(i < strlen(source))
193 {
194 if(source[i]!='\n') dest[j]=source[i];
195 else dest[j]=0;
196 j++;i++;
197 }
198 dest[j]=0;
199 }
200
201
202 /********************************************************************
203 Reads the configuration file and fills the program list
204 *********************************************************************/
Parse()205 int Config::Parse()
206 {
207 FILE *fd;
208 char line[1024]; //TODO line length should not be limited
209 char tline[1024];
210 bool something = false;
211 Program *pp= new Program();
212 iconv_t to_unicode, check_unicode;
213
214 check_unicode = iconv_open("UTF-8", "UTF-8");
215 to_unicode = iconv_open("UTF-8", nl_langinfo (CODESET));
216
217 fd=fopen(file.c_str(),"r");
218 if(!fd)
219 {
220 fprintf(stderr, "- Unable to open %s\n",file.c_str());
221 return(-1);
222 }
223
224 while(fgets(line,1024,fd))
225 {
226 if(!strlen(line))
227 {
228 break;
229 }
230
231 strgetb(line,line,'#'); /* Handle the comments */
232
233 /* Set SAP TTL (ttl is a member of config) */
234 if(strstr(line,"sap_ttl="))
235 {
236 strgeta(line,tline,'=');
237 ttl=atoi(tline);
238 }
239
240 /* Set SAP Delay (delay is a member of config) */
241 if(strstr(line,"sap_delay="))
242 {
243 strgeta(line,tline,'=');
244 delay=atoi(tline);
245 }
246
247 /* Set SAP Interface (interface is a member of config) */
248 if(strstr(line,"interface="))
249 {
250 strgeta(line,tline,'=');
251 interface=strdup(tline);
252 }
253
254 /* Beginning of programs parsing */
255 if(strstr(line,"[program]"))
256 {
257 if(something)
258 {
259 /* We were in a program with at least one field filled */
260 if (!pp->GetPort())
261 {
262 pp->SetPort(DEFAULT_PORT);
263 }
264 Programs.push_back(pp);
265 pp=new Program();
266 something=false;
267 }
268 }
269
270 if(strstr(line,"name="))
271 {
272 ICONV_CONST char *tptr;
273 char *uptr, uline[6139];
274 size_t tlen, ulen;
275
276 strgeta(line,tline,'=');
277 something=true;
278
279 tptr=tline;
280 uptr=uline;
281 tlen=strlen(tline) + 1;
282 ulen=sizeof(uline);
283 if(iconv(check_unicode, &tptr, &tlen, &uptr, &ulen) == (size_t)(-1))
284 {
285 tptr=tline;
286 uptr=uline;
287 tlen=strlen(tline) + 1;
288 ulen=sizeof(uline);
289 if(iconv(to_unicode, &tptr, &tlen, &uptr, &ulen) == (size_t)(-1))
290 uptr = tline;
291 else
292 uptr = uline;
293 }
294 else
295 uptr = uline;
296
297 pp->SetName(uptr);
298 }
299
300 if(strstr(line,"program_ttl="))
301 {
302 strgeta(line,tline,'=');
303 something=true;
304 pp->SetTTL(tline);
305 }
306
307 if(strstr(line,"playlist_group="))
308 {
309 ICONV_CONST char *tptr;
310 char *uptr, uline[6139];
311 size_t tlen, ulen;
312
313 strgeta(line,tline,'=');
314 something=true;
315
316 tptr=tline;
317 uptr=uline;
318 tlen=strlen(tline) + 1;
319 ulen=sizeof(uline);
320 if(iconv(check_unicode, &tptr, &tlen, &uptr, &ulen) == (size_t)(-1))
321 {
322 tptr=tline;
323 uptr=uline;
324 tlen=strlen(tline) + 1;
325 ulen=sizeof(uline);
326 if(iconv(to_unicode, &tptr, &tlen, &uptr, &ulen) == (size_t)(-1))
327 uptr = tline;
328 else
329 uptr = uline;
330 }
331 else
332 uptr = uline;
333
334 pp->SetPlGroup(uptr);
335 pp->SetHasPlGroup(true);
336 }
337
338 if(strstr(line,"type=") && strstr(line,"rtp") )
339 {
340 pp->SetRTP(true);
341 }
342
343 if(strstr(line,"user="))
344 {
345 strgeta(line,tline,'=');
346 something=true;
347 pp->SetUser(tline);
348 }
349
350 if(strstr(line,"machine="))
351 {
352 strgeta(line,tline,'=');
353 something=true;
354 pp->SetMachine(tline);
355 }
356
357 if(strstr(line,"site="))
358 {
359 strgeta(line,tline,'=');
360 something=true;
361 pp->SetSite(tline);
362 }
363
364 if(strstr(line,"address="))
365 {
366 strgeta(line,tline,'=');
367 something=true;
368 pp->SetAddress(tline);
369 }
370 if(strstr(line,"port="))
371 {
372 strgeta(line,tline,'=');
373 something=true;
374 pp->SetPort(atoi(tline));
375 }
376 if(strstr(line,"customsdp="))
377 {
378 strgeta(line,tline,'=');
379 something=true;
380 pp->SetCustomSDP(tline);
381 }
382 }
383
384 if(something)
385 {
386 if (!pp->GetPort())
387 {
388 pp->SetPort(DEFAULT_PORT);
389 }
390 Programs.push_back(pp);
391 }
392 else
393 delete pp;
394
395 fclose (fd);
396 if(check_unicode != (iconv_t)(-1))
397 iconv_close(check_unicode);
398 if(to_unicode != (iconv_t)(-1))
399 iconv_close(to_unicode);
400
401 return(0);
402 }
403