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