1 /*
2  * Mp3Splt -- Utility for mp3/ogg splitting without decoding
3  *
4  * Copyright (c) 2002-2005 M. Trotta - <mtrotta@users.sourceforge.net>
5  * Copyright (c) 2005-2014 Alexandru Munteanu - <m@ioalex.net>
6  *
7  * http://mp3splt.sourceforge.net
8  *
9  *  This program is free software; you can redistribute it and/or modify
10  *  it under the terms of the GNU General Public License as published by
11  *  the Free Software Foundation; either version 2 of the License, or
12  *  (at your option) any later version.
13  *
14  *  This program is distributed in the hope that it will be useful,
15  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  *  GNU General Public License for more details.
18  *
19  *  You should have received a copy of the GNU General Public License
20  *  along with this program; if not, write to the Free Software
21  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
22  */
23 
24 #include <unistd.h>
25 
26 #ifdef __WIN32__
27 #include <conio.h>
28 #endif
29 
30 #include "common.h"
31 #include "utils.h"
32 #include "print_utils.h"
33 
34 #include "freedb.h"
35 
36 static void handle_proxy(main_data *data);
37 static void query_for_proxy_and_write_configuration_file(main_data *data);
38 static void read_proxy_settings_from_configuration_file(main_data *data);
39 static char *get_configuration_filename();
40 static char *query_for_proxy_login();
41 static char *get_input_line(FILE *input_file, char *key);
42 
43 extern FILE *console_out;
44 
45 #if defined(__BEOS__) && !defined (HAS_GETPASS)
46 #warning Faking getpass() !!!
getpass(char * p)47 char *getpass(char *p)
48 {
49   char *ret = malloc(30);
50   if (!ret)
51     return NULL;
52   puts(p);
53   fgets(ret, 30, stdin);
54   return ret;
55 }
56 #endif
57 
58 #ifdef __WIN32__
getpass(char * s)59 char *getpass(char *s)
60 {
61   char *pass, c;
62   int i=0;
63   fputs(s, stdout);
64   pass = malloc(100);
65   do {
66     c = _getch();
67     if (c!='\r') {
68       if (c=='\b') {
69         if (i>0) {
70           printf ("\b \b");
71           i--;
72         }
73       }
74       else {
75         printf ("*");
76         pass[i++] = c;
77       }
78     }
79     else break;
80   } while (i<100);
81 
82   pass[i]='\0';
83 
84   printf("\n");
85 
86   return pass;
87 }
88 #endif
89 
do_freedb_search(main_data * data)90 void do_freedb_search(main_data *data)
91 {
92   handle_proxy(data);
93 
94   int err = SPLT_OK;
95   options *opt = data->opt;
96   splt_state *state = data->state;
97 
98   char search_type[30] = "";
99   char get_type[30] = "";
100   if (opt->freedb_search_type == SPLT_FREEDB_SEARCH_TYPE_CDDB_CGI)
101   {
102     snprintf(search_type, 30, "%s", "cddb_cgi");
103   }
104   else
105   {
106     snprintf(search_type, 30 ,"%s", "web_search");
107   }
108   if (opt->freedb_get_type == SPLT_FREEDB_GET_FILE_TYPE_CDDB_CGI)
109   {
110     snprintf(get_type, 30, "%s", "cddb_cgi");
111   }
112   else
113   {
114     snprintf(get_type, 30, "%s", "cddb_protocol");
115   }
116 
117   //print out infos about the servers
118   fprintf(console_out,_(" Freedb search type: %s , Site: %s , Port: %d\n"),
119       search_type,opt->freedb_search_server,opt->freedb_search_port);
120   fflush(console_out);
121   fprintf(console_out,_(" Freedb get type: %s , Site: %s , Port: %d\n"),
122       get_type,opt->freedb_get_server,opt->freedb_get_port);
123   fflush(console_out);
124 
125   char *freedb_search_string = NULL;
126   char freedb_input[2048] = { '\0' };
127   //if we haven't chosen to search from the arguments, interactive search
128   if (opt->freedb_arg_search_string[0] == '\0')
129   {
130     print_message(_("CDDB QUERY. Insert album and artist informations to find cd."));
131 
132     short first_time = SPLT_TRUE;
133     do {
134       if (!first_time)
135       {
136         print_message(_("\nPlease search something ..."));
137       }
138 
139       memset(freedb_input, '\0', sizeof(freedb_input));
140 
141       fprintf(console_out, "\n\t____________________________________________________________]");
142       fprintf(console_out, _("\r Search: ["));
143 
144       fgets(freedb_input, 2046, stdin);
145 
146       first_time = SPLT_FALSE;
147 
148       freedb_input[strlen(freedb_input)-1] = '\0';
149     } while (strlen(freedb_input)==0);
150 
151     freedb_search_string = freedb_input;
152   }
153   else
154   {
155     freedb_search_string = opt->freedb_arg_search_string;
156   }
157 
158   fprintf(console_out, _("\n  Search string: %s\n"),freedb_search_string);
159   fprintf(console_out, _("\nSearching from %s on port %d using %s ...\n"),
160       opt->freedb_search_server,opt->freedb_search_port, search_type);
161   fflush(console_out);
162 
163   splt_freedb_results *f_results =
164     mp3splt_get_freedb_search(state, freedb_search_string,
165         &err, opt->freedb_search_type,
166         opt->freedb_search_server,
167         opt->freedb_search_port);
168 
169   process_confirmation_error(err, data);
170   if (!f_results)
171   {
172     print_message_exit(_("No results found"), data);
173   }
174 
175   //if we don't have an auto-select the result X from the arguments:
176   // (query{artist}(resultX)
177   //, then interactive user ask
178   int selected_cd = 0;
179   if (opt->freedb_arg_result_option < 0)
180   {
181     //print the searched informations
182     print_message(_("List of found cd:"));
183 
184     int cd_number = 0;
185     short end = SPLT_FALSE;
186 
187     mp3splt_freedb_init_iterator(f_results);
188     const splt_freedb_one_result *f_result = NULL;
189     while ((f_result = mp3splt_freedb_next(f_results))) {
190       int cd_id = mp3splt_freedb_get_id(f_result);
191 
192       const char *cd_name = mp3splt_freedb_get_name(f_result);
193       fprintf(console_out,"%3d) %s\n", cd_id, cd_name);
194 
195       int i = 0;
196       int number_of_revisions = mp3splt_freedb_get_number_of_revisions(f_result);
197       for(i = 0; i < number_of_revisions; i++)
198       {
199         fprintf(console_out, "  |\\=>");
200         fprintf(console_out, "%3d) ", cd_id+i+1);
201         fprintf(console_out, _("Revision: %d\n"), i+2);
202 
203         //break at 22
204         if (((cd_id+i+2) % 22) == 0)
205         {
206           //duplicate, see below
207           char junk[18];
208           fprintf(console_out, _("-- 'q' to select cd, Enter for more:"));
209           fflush(console_out);
210 
211           fgets(junk, 16, stdin);
212           if (junk[0]=='q')
213           {
214             end = SPLT_TRUE;
215             goto end;
216           }
217         }
218       }
219 
220       //we read result from the char, q tu select cd or
221       //enter to show more results
222       if (((cd_id + 1) % 22) == 0)
223       {
224         //duplicate, see ^^
225         char junk[18];
226         fprintf(console_out, _("-- 'q' to select cd, Enter for more: "));
227         fflush(console_out);
228 
229         fgets(junk, 16, stdin);
230         if (junk[0]=='q')
231         {
232           end = SPLT_TRUE;
233           goto end;
234         }
235       }
236 
237 end:
238       if (end)
239       {
240         end = SPLT_FALSE;
241         break;
242       }
243 
244       cd_number++;
245     };
246 
247     //select the CD
248     //input of the selected cd
249     char sel_cd_input[1024];
250     int tot = 0;
251     do {
252       selected_cd = 0;
253       fprintf(console_out, _("Select cd #: "));
254       fflush(console_out);
255       fgets(sel_cd_input, 254, stdin);
256       sel_cd_input[strlen(sel_cd_input)-1]='\0';
257       tot = 0;
258 
259       if (sel_cd_input[tot] == '\0')
260       {
261         selected_cd = -1;
262       }
263 
264       while(sel_cd_input[tot] != '\0')
265       {
266         if (isdigit(sel_cd_input[tot++])==0)
267         {
268           fprintf(console_out, _("Please "));
269           fflush(console_out);
270 
271           selected_cd = -1;
272           break;
273         }
274       }
275 
276       if (selected_cd != -1)
277       {
278         selected_cd = atoi(sel_cd_input);
279       }
280 
281     } while ((selected_cd < 0) || (selected_cd >= cd_number));
282   }
283   else
284   {
285     selected_cd = opt->freedb_arg_result_option;
286   }
287 
288   fprintf(console_out, _("\nGetting file from %s on port %d using %s ...\n"),
289       opt->freedb_get_server,opt->freedb_get_port, get_type);
290   fflush(console_out);
291 
292   err = mp3splt_write_freedb_file_result(state, selected_cd,
293       MP3SPLT_CDDBFILE, opt->freedb_get_type,
294       opt->freedb_get_server, opt->freedb_get_port);
295   process_confirmation_error(err, data);
296 
297   mp3splt_clear_proxy(data->state);
298 }
299 
handle_proxy(main_data * data)300 static void handle_proxy(main_data *data)
301 {
302   mp3splt_clear_proxy(data->state);
303   query_for_proxy_and_write_configuration_file(data);
304   read_proxy_settings_from_configuration_file(data);
305 }
306 
read_proxy_settings_from_configuration_file(main_data * data)307 static void read_proxy_settings_from_configuration_file(main_data *data)
308 {
309   char *config_file = get_configuration_filename();
310 
311   FILE *input_file = fopen(config_file, "r");
312   if (!input_file)
313   {
314     free(config_file);
315     return;
316   }
317   free(config_file);
318 
319   fseek(input_file, 0, SEEK_SET);
320 
321   char *proxy_address = get_input_line(input_file, "PROXYADDR");
322   if (!proxy_address) { goto end; }
323 
324   char *proxy_port = get_input_line(input_file, "PROXYPORT");
325   if (!proxy_port) { free(proxy_address); goto end; }
326   int port = atoi(proxy_port);
327 
328   fprintf(stderr, " Using proxy %s on port %d\n", proxy_address, port);
329 
330   mp3splt_use_proxy(data->state, proxy_address, port);
331 
332   if (proxy_address != NULL)
333   {
334     free(proxy_address);
335   }
336   if (proxy_port != NULL)
337   {
338     free(proxy_port);
339   }
340 
341   char *use_proxy_auth = get_input_line(input_file, "PROXYAUTH");
342   if (!use_proxy_auth) { goto end; }
343   if (use_proxy_auth[0] != '1')
344   {
345     free(use_proxy_auth);
346     goto end;
347   }
348   free(use_proxy_auth);
349 
350   char *authentification = get_input_line(input_file, NULL);
351   if (authentification)
352   {
353     mp3splt_use_base64_authentification(data->state, authentification);
354     free(authentification);
355   }
356   else
357   {
358     splt_code error = SPLT_OK;
359 
360     char *proxy_authentification = query_for_proxy_login();
361     char *authentification_as_base64 =
362       mp3splt_encode_in_base64(data->state, proxy_authentification, &error);
363     process_confirmation_error(error, data);
364 
365     memset(proxy_authentification, 0x00, strlen(proxy_authentification));
366     free(proxy_authentification);
367 
368     mp3splt_use_base64_authentification(data->state, authentification_as_base64);
369 
370     memset(authentification_as_base64, 0x00, strlen(authentification_as_base64));
371     free(authentification_as_base64);
372   }
373 
374 end:
375   fclose(input_file);
376 }
377 
get_input_line(FILE * input_file,char * key)378 static char *get_input_line(FILE *input_file, char *key)
379 {
380   char *line = NULL;
381   size_t length = 0;
382 
383 #ifndef HAVE_GETLINE
384   char junk[512];
385   fgets(junk, 511, input_file);
386   junk[strlen(junk)] = '\0';
387 
388   length = strlen(junk) + 1;
389   line = my_malloc(sizeof(char) * length);
390   snprintf(line, length, junk);
391 #else
392   if (getline(&line, &length, input_file) == -1)
393   {
394     if (line) { free(line); }
395     return NULL;
396   }
397 #endif
398 
399   if (!line) { return NULL; }
400 
401   int line_length = strlen(line);
402   if (line_length < 3)
403   {
404     free(line);
405     return NULL;
406   }
407 
408   line[line_length-1] = '\0';
409   if (line[line_length-2] == '\r')
410   {
411     line[line_length-2] = '\0';
412   }
413 
414   if (key == NULL)
415   {
416     return line;
417   }
418 
419   if (strstr(line, key) == NULL) {
420     free(line);
421     return NULL;
422   }
423 
424   char *value_start = NULL;
425   if ((value_start = strchr(line, '=')) == NULL) {
426     print_warning(_("the configuration file is malformed !"));
427     free(line);
428     return NULL;
429   }
430 
431   char *value = strdup(value_start + 1);
432   if (!value)
433   {
434     print_warning(_("cannot allocate memory !"));
435   }
436 
437   free(line);
438 
439   return value;
440 }
441 
query_for_proxy_and_write_configuration_file(main_data * data)442 static void query_for_proxy_and_write_configuration_file(main_data *data)
443 {
444   char *config_file = get_configuration_filename();
445 
446   FILE *output_file = NULL;
447   if ((output_file = fopen(config_file, "r")))
448   {
449     free(config_file);
450     fclose(output_file);
451     return;
452   }
453 
454   if (data->opt->q_option)
455   {
456     return;
457   }
458 
459   if (!(output_file = fopen(config_file, "w+")))
460   {
461     free(config_file);
462     print_warning(_("can't open the configuration file !"));
463     return;
464   }
465   free(config_file);
466 
467   int user_input_length = 1024;
468   char user_input[1024] = { '\0' };
469 
470   fprintf(stderr, _("Will you use a proxy ? (y/n): "));
471   fgets(user_input, user_input_length, stdin);
472   if (user_input[0] != 'y')
473   {
474     goto close_file;
475   }
476 
477   fprintf(stderr, _("Proxy Address: "));
478   fgets(user_input, user_input_length, stdin);
479   fprintf(output_file, "PROXYADDR=%s", user_input);
480 
481   fprintf(stderr, _("Proxy Port: "));
482   fgets(user_input, user_input_length, stdin);
483   fprintf(output_file, "PROXYPORT=%s", user_input);
484 
485   fprintf(stderr, _("Need authentication ? (y/n): "));
486   fgets(user_input, user_input_length, stdin);
487   if (user_input[0] != 'y')
488   {
489     goto close_file;
490   }
491 
492   fprintf(output_file, "PROXYAUTH=1\n");
493   fprintf(stderr, _("Would you like to save the password (insecure) ? (y/n): "));
494   fgets(user_input, user_input_length, stdin);
495   if (user_input[0] != 'y')
496   {
497     goto close_file;
498   }
499 
500   char *authentification = query_for_proxy_login();
501 
502   splt_code error = SPLT_OK;
503   char *authentification_as_base64 =
504     mp3splt_encode_in_base64(data->state, authentification, &error);
505   process_confirmation_error(error, data);
506 
507   memset(authentification, 0x00, strlen(authentification));
508   free(authentification);
509 
510   fprintf(output_file, "%s\n", authentification_as_base64);
511 
512   memset(authentification_as_base64, 0x00, strlen(authentification_as_base64));
513   free(authentification_as_base64);
514 
515 close_file:
516   fclose(output_file);
517 }
518 
query_for_proxy_login()519 static char *query_for_proxy_login()
520 {
521   char user_input[130];
522   fprintf(console_out, _("Username: "));
523   fgets(user_input, 128, stdin);
524   user_input[strlen(user_input)-1] = '\0';
525 
526   char *pass = getpass(_("Password: "));
527 
528   size_t login_size = strlen(user_input) + strlen(pass) + 2;
529   char *login = my_malloc(sizeof(char) * login_size);
530   snprintf(login, login_size, "%s:%s", user_input, pass);
531 
532   memset(pass, 0x00, strlen(pass));
533   free(pass);
534 
535   return login;
536 }
537 
get_configuration_filename()538 static char *get_configuration_filename()
539 {
540   char *home_directory = getenv("HOME");
541 
542   size_t home_directory_length = 0;
543   if (home_directory)
544   {
545     home_directory_length = strlen(home_directory);
546   }
547 
548   size_t maximum_length = home_directory_length + strlen(PROXY_CONFIG_FILE) + 2;
549   char *config_file = my_malloc(sizeof(char) * maximum_length);
550 
551   if (home_directory != NULL)
552   {
553     snprintf(config_file, maximum_length, "%s%c"PROXY_CONFIG_FILE, home_directory, SPLT_DIRCHAR);
554   }
555   else
556   {
557     snprintf(config_file, maximum_length, PROXY_CONFIG_FILE);
558   }
559 
560   return config_file;
561 }
562 
563