1 /*
2  *  Copyright (C) 2009-2015  Christian Heckendorf <heckendorfc@gmail.com>
3  *
4  *  This program is free software: you can redistribute it and/or modify
5  *  it under the terms of the GNU General Public License as published by
6  *  the Free Software Foundation, either version 3 of the License, or
7  *  (at your option) any later version.
8  *
9  *  This program is distributed in the hope that it will be useful,
10  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  *  GNU General Public License for more details.
13  *
14  *  You should have received a copy of the GNU General Public License
15  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
16  */
17 
18 #include "harpconfig.h"
19 #include "defs.h"
20 #include "insert.h"
21 #include "util.h"
22 
23 struct lconf listconf;
24 struct iconf insertconf;
25 struct dconf debugconf;
26 
27 static const char insertflags[]={'r','a','t','y','k',0};
28 
29 extern struct option longopts[];
30 
argConfig(char * buffer)31 static void argConfig(char *buffer){
32 	char *setting=buffer;
33 	int y=0,argfound=0;
34 	while(*setting!='=' && *setting)setting++;
35 	if(*setting && *(setting+1))argfound=1;
36 	*(setting++)=0;
37 
38 	for(y=0;longopts[y].name;y++){
39 		if(strcmp(buffer,longopts[y].name)==0){
40 			if(y!=AVERBOSE || !argfound)
41 				arglist[y].active=1;
42 			else
43 				arglist[y].active=(int)strtol(setting,NULL,10);
44 
45 			if(longopts[y].has_arg>0){
46 				if(argfound){
47 					if(!(arglist[y].subarg=malloc(sizeof(char)*2)))return;
48 					arglist[y].subarg[0]=*setting;
49 					arglist[y].subarg[1]=0;
50 				}
51 				else
52 					arglist[y].active=0;
53 			}
54 
55 			return;
56 		}
57 	}
58 }
59 
listConfig(char * buffer)60 static void listConfig(char *buffer){
61 	char *setting=buffer;
62 	int argfound=0;
63 	while(*setting!='=' && *setting)setting++;
64 	if(*setting && *(setting+1))argfound=1;
65 	*(setting++)=0;
66 
67 	if(strcmp("width",buffer)==0){
68 		if(argfound)
69 			listconf.maxwidth=(int)strtol(setting,NULL,10);
70 		else // bad config. hard coded defaults
71 			listconf.maxwidth=30;
72 	}
73 	else if(strcmp("exception",buffer)==0){
74 		if(argfound)
75 			listconf.exception=(int)strtol(setting,NULL,10);
76 		else // bad config. hard coded defaults
77 			listconf.exception=0;
78 	}
79 }
80 
insertConfig(char * buffer)81 static void insertConfig(char *buffer){
82 	char *setting=buffer;
83 	static int formatsize=0;
84 	while(*setting!='=' && *setting)setting++;
85 	*(setting++)=0;
86 
87 	if(strcmp("usemetadata",buffer)==0){
88 		if(*setting!='y'){
89 			if(insertconf.second_cb==&metadataInsert)
90 				insertconf.second_cb=NULL;
91 			if(insertconf.first_cb==&metadataInsert)
92 				insertconf.first_cb=NULL;
93 			if(insertconf.second_cb && !insertconf.first_cb){
94 				insertconf.first_cb=insertconf.second_cb;
95 				insertconf.second_cb=NULL;
96 			}
97 		}
98 		else{
99 			if(insertconf.first_cb && insertconf.second_cb){
100 				insertconf.first_cb=insertconf.second_cb;
101 				insertconf.second_cb=NULL;
102 			}
103 			if(!insertconf.first_cb)
104 				insertconf.first_cb=&metadataInsert;
105 			else
106 				insertconf.second_cb=&metadataInsert;
107 		}
108 	}
109 	else if(strcmp("usefilepath",buffer)==0){
110 		if(*setting!='y'){
111 			if(insertconf.second_cb==&filepathInsert)
112 				insertconf.second_cb=NULL;
113 			if(insertconf.first_cb==&filepathInsert)
114 				insertconf.first_cb=NULL;
115 			if(insertconf.second_cb && !insertconf.first_cb){
116 				insertconf.first_cb=insertconf.second_cb;
117 				insertconf.second_cb=NULL;
118 			}
119 		}
120 		else{
121 			if(insertconf.first_cb && insertconf.second_cb){
122 				insertconf.first_cb=insertconf.second_cb;
123 				insertconf.second_cb=NULL;
124 			}
125 			if(!insertconf.first_cb)
126 				insertconf.first_cb=&filepathInsert;
127 			else
128 				insertconf.second_cb=&filepathInsert;
129 		}
130 	}
131 	else if(strcmp("format",buffer)==0){
132 		char *ptr=setting;
133 		int koi=0;
134 		const char *pflag="(.*)";
135 		char *pattern;
136 		int pi=0;
137 		int ret;
138 		int siz;
139 		if(++formatsize==ICONF_MAX_FORMAT_SIZE){
140 			fprintf(stderr,"Insert format buffer is full. Please check your config file.");
141 			return;
142 		}
143 		insertconf.keyorder[formatsize]=NULL;
144 		insertconf.keyorder[formatsize-1]=malloc(MI_NULL*sizeof(int));
145 
146 		siz=strlen(setting)+(strlen(pflag)-2)*MI_NULL;
147 		pattern=malloc(siz);
148 
149 		while(*ptr){
150 			do{
151 				pattern[pi++]=*ptr;
152 			}while(*ptr && *(++ptr)!='%');
153 
154 			if(*ptr && ptr[1] && koi<MI_NULL){
155 				int i,j,custom=0;
156 				if(ptr[1]=='['){
157 					custom=1;
158 					ptr+=2;
159 					pattern[pi++]='(';
160 					for(j=1;j>0 && *ptr;ptr++){
161 						if(*ptr=='[' && *(ptr-1)!='\\')
162 							j++;
163 						if(*ptr==']' && *(ptr-1)!='\\')
164 							j--;
165 						if(j)
166 							pattern[pi++]=*ptr;
167 					}
168 					pattern[pi++]=')';
169 					if(*ptr==0)
170 						break;
171 					ptr--;
172 				}
173 				for(i=0;insertflags[i];i++){
174 					if(insertflags[i]==ptr[1]){
175 						insertconf.keyorder[formatsize-1][koi++]=i;
176 						break;
177 					}
178 				}
179 
180 				if(!custom){
181 					for(i=0;pflag[i];i++)
182 						pattern[pi++]=pflag[i];
183 				}
184 
185 				ptr++;
186 			}
187 			else
188 				break;
189 
190 			ptr++;
191 		}
192 		insertconf.keyorder[formatsize-1][koi]=MI_NULL;
193 		pattern[pi++]=0;
194 
195 		if((ret=regcomp(insertconf.pattern+formatsize-1,pattern,REG_EXTENDED))){
196 			regerror(ret,NULL,pattern,siz);
197 			fprintf(stderr,"Compile regex failed! (%d) %s\n",ret,pattern);
198 		}
199 
200 		free(pattern);
201 	}
202 	else if(strcmp("accuratelength",buffer)==0 && *setting=='y'){
203 		insertconf.length=0;
204 	}
205 }
206 
create_logfile(char * template,char * dir,char ** dst_filename,FILE ** dst_fd)207 static void create_logfile(char *template, char *dir, char **dst_filename, FILE **dst_fd){
208 		char tmp[256];
209 		int fid;
210 
211 		sprintf(tmp,template,dir);
212 		expand(tmp);
213 
214 		if((fid=mkstemp(tmp))==-1)
215 			return;
216 
217 		if(*dst_filename){
218 			/* Debugs won't print at this point unless specified in the config file. */
219 			//char msg[350];
220 			//sprintf(msg,"Removing log: %s.\n\tPlease check config file for duplicate entries.",*dst_filename);
221 			//debug(1,msg);
222 			unlink(*dst_filename);
223 			free(*dst_filename);
224 		}
225 		*dst_filename=strdup(tmp);
226 
227 		if(*dst_fd)
228 			fclose(*dst_fd);
229 		*dst_fd=fdopen(fid,"w");
230 		//sprintf(tmp,"Logging to: %s",*dst_filename);
231 		//debug(1,tmp);
232 }
233 
debugConfig(char * buffer)234 static void debugConfig(char *buffer){
235 	char *setting=buffer;
236 	while(*setting!='=' && *setting)setting++;
237 	*(setting++)=0;
238 
239 	if(strcmp("logging",buffer)==0 && *setting=='y'){
240 		debugconf.log=1;
241 	}
242 	else if(strcmp("directory",buffer)==0){
243 		if(debugconf.dir==NULL || strcmp(debugconf.dir,setting)!=0){
244 			if(debugconf.dir)
245 				free(debugconf.dir);
246 			debugconf.dir=strdup(setting);
247 		}
248 	}
249 	else if(strcmp("playlog",buffer)==0 && *setting=='y' && debugconf.dir){
250 		create_logfile("%s/player.log.XXXXXX",debugconf.dir,&debugconf.playfilename,&debugconf.playfd);
251 	}
252 	else if(strcmp("loglevel",buffer)==0){
253 		debugconf.level=(int)strtol(setting,NULL,10);
254 		if(debugconf.level>0 && debugconf.dir){
255 			create_logfile("%s/debug.log.XXXXXX",debugconf.dir,&debugconf.msgfilename,&debugconf.msgfd);
256 		}
257 	}
258 }
259 
configInit()260 static void configInit(){
261 	if((insertconf.keyorder=malloc(sizeof(char*)*ICONF_MAX_FORMAT_SIZE)))
262 		*insertconf.keyorder=NULL;
263 	insertconf.pattern=malloc(sizeof(char*)*ICONF_MAX_FORMAT_SIZE);
264 	insertconf.length=-1;
265 	insertconf.second_cb=insertconf.first_cb=NULL;
266 
267 	debugconf.playfilename=debugconf.msgfilename=debugconf.dir=NULL;
268 	debugconf.msgfd=debugconf.playfd=NULL;
269 }
270 
parseConfig(FILE * ffd)271 static void parseConfig(FILE *ffd){
272 	char *buffer=malloc(255*sizeof(char));
273 	char *ptr=buffer;
274 	void (*dest)(char *buffer) = NULL;
275 
276 	if(!buffer)return;
277 
278 
279 	while(fgets(buffer,255,ffd)){
280 		if(*buffer=='['){ // New header
281 			switch(buffer[1]){
282 				case 'a':dest=&argConfig;break;
283 				case 'l':dest=&listConfig;break;
284 				case 'i':dest=&insertConfig;break;
285 				case 'd':dest=&debugConfig;break;
286 				default:dest=NULL;
287 			}
288 			continue;
289 		}
290 		if(dest && *buffer>64 && *buffer<123){
291 			while(*(++ptr)!='\n');
292 			while(*ptr<33 || *ptr>122)ptr--;
293 			*(ptr+1)=0;
294 			ptr=buffer;
295 
296 			dest(buffer);
297 		}
298 	}
299 	free(buffer);
300 }
301 
setDefaultConfig()302 void setDefaultConfig(){
303 	FILE *ffd;
304 	char temp[250];
305 
306 	configInit();
307 
308 	sprintf(temp,"%s/harp/defaults.conf",SHARE_PATH);
309 	if((ffd=fopen(temp,"r"))==NULL){
310 		exit(1);
311 	}
312 	parseConfig(ffd);
313 	fclose(ffd);
314 
315 	strcpy(temp,"~/.harp/defaults.conf");
316 	expand(temp);
317 	if((ffd=fopen(temp,"r"))!=NULL){
318 		parseConfig(ffd);
319 		fclose(ffd);
320 	}
321 }
322