1 /**********************************************************
2  *
3  * libmp3splt -- library based on mp3splt,
4  *               for mp3/ogg splitting without decoding
5  *
6  * Copyright (c) 2002-2005 M. Trotta - <mtrotta@users.sourceforge.net>
7  * Copyright (c) 2005-2014 Alexandru Munteanu - m@ioalex.net
8  *
9  * http://mp3splt.sourceforge.net
10  *
11  *********************************************************/
12 
13 /**********************************************************
14  *
15  * This program is free software; you can redistribute it and/or
16  * modify it under the terms of the GNU General Public License
17  * as published by the Free Software Foundation; either version 2
18  * of the License, or (at your option) any later version.
19  *
20  * This program is distributed in the hope that it will be useful,
21  * but WITHOUT ANY WARRANTY; without even the implied warranty of
22  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23  * GNU General Public License for more details.
24  *
25  * You should have received a copy of the GNU General Public License
26  * along with this program; if not, write to the Free Software
27  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
28  * USA.
29  *
30  *********************************************************/
31 
32 /*! \file
33 
34 Automatic generation of filenams for split files from tags.
35  */
36 #include <string.h>
37 #include <ctype.h>
38 #include <math.h>
39 
40 #include "splt.h"
41 
42 static void splt_of_trim_on_separator_characters(char *filename);
43 static const char *splt_of_goto_last_non_separator_character(const char *format);
44 
duplicate_and_clean(splt_state * state,const char * str,int * error)45 static char *duplicate_and_clean(splt_state *state, const char *str, int *error)
46 {
47   char *dup = strdup(str);
48   if (!dup)
49   {
50     *error = SPLT_ERROR_CANNOT_ALLOCATE_MEMORY;
51     return NULL;
52   }
53 
54   splt_su_clean_string(state, dup, error);
55   if (error < 0)
56   {
57     free(dup);
58     return NULL;
59   }
60 
61   return dup;
62 }
63 
64 /*! \brief Is a placeholder char valid in a filename format string?
65 
66 \param v The character that is to be tested
67 \param amb True, if the character is valid
68 \return The value that is returned in amb, as well.
69 
70 \todo Why do we need amb?
71  */
splt_of_output_variable_is_valid(char v,int * amb)72 static short splt_of_output_variable_is_valid(char v, int *amb)
73 {
74   switch (v)
75   {
76     case 's':
77     case 'S':
78     case 'm':
79     case 'M':
80     case 'h':
81     case 'H':
82     case 'a':
83     case 'A':
84     case 'b':
85     case 'f':
86     case 'd':
87     case 'g':
88     case 'p':
89       break;
90     case 't':
91     case 'l':
92     case 'L':
93     case 'u':
94     case 'U':
95     case 'n':
96     case 'N':
97       *amb = SPLT_OUTPUT_FORMAT_OK;
98       break;
99     default:
100       return SPLT_FALSE;
101   }
102 
103   return SPLT_TRUE;
104 }
105 
splt_of_parse_outformat(char * s,splt_state * state)106 int splt_of_parse_outformat(char *s, splt_state *state)
107 {
108   char *ptrs = NULL, *ptre = NULL;
109   int i=0, amb = SPLT_OUTPUT_FORMAT_AMBIGUOUS, len=0;
110 
111   size_t size = strlen(s);
112   for (i = 0; i < size; i++)
113   {
114     if (s[i]=='+')
115     {
116       s[i]=' ';
117     }
118     else
119     {
120       if (s[i] == SPLT_VARCHAR)
121       {
122         s[i]='%';
123       }
124     }
125   }
126 
127   ptrs = s;
128   i = 0;
129   ptre = strchr(ptrs+1, '%');
130   if (s[0] != '%')
131   {
132     if (ptre==NULL)
133     {
134       len = strlen(ptrs);
135     }
136     else
137     {
138       len = ptre-ptrs;
139     }
140     if (len > SPLT_MAXOLEN)
141     {
142       len = SPLT_MAXOLEN;
143     }
144     strncpy(state->oformat.format[i++], ptrs, len);
145   }
146   else
147   {
148     ptre = s;
149   }
150 
151   //if stdout, NOT ambiguous
152   if (splt_io_input_is_stdout(state))
153   {
154     return SPLT_OUTPUT_FORMAT_OK;
155   }
156 
157   char err[2] = { '\0' };
158 
159   if (ptre == NULL)
160   {
161     splt_e_set_error_data(state, err);
162     return SPLT_OUTPUT_FORMAT_AMBIGUOUS;
163   }
164   ptrs = ptre;
165 
166   char *last_ptre = NULL;
167   while (((ptre = strchr(ptrs+1, '%')) != NULL) && (i < SPLT_OUTNUM))
168   {
169     char cf = *(ptrs+1);
170 
171     len = ptre-ptrs;
172     if (len > SPLT_MAXOLEN)
173     {
174       len = SPLT_MAXOLEN;
175     }
176 
177     if (!splt_of_output_variable_is_valid(cf, &amb))
178     {
179       err[0] = cf;
180       splt_e_set_error_data(state, err);
181       return SPLT_OUTPUT_FORMAT_ERROR;
182     }
183 
184     strncpy(state->oformat.format[i++], ptrs, len);
185     ptrs = ptre;
186     last_ptre = ptre;
187   }
188 
189   if (last_ptre && *last_ptre != '\0')
190   {
191     char v = *(last_ptre+1);
192     if (!splt_of_output_variable_is_valid(v, &amb))
193     {
194       err[0] = v;
195       splt_e_set_error_data(state, err);
196       return SPLT_OUTPUT_FORMAT_ERROR;
197     }
198   }
199 
200   strncpy(state->oformat.format[i], ptrs, strlen(ptrs));
201 
202   if (ptrs[1]=='t')
203   {
204     amb = SPLT_OUTPUT_FORMAT_OK;
205   }
206 
207   if (ptrs[1]=='n')
208   {
209     amb = SPLT_OUTPUT_FORMAT_OK;
210   }
211 
212   return amb;
213 }
214 
splt_u_get_format_ptr(const char * format,char * temp,int * number_of_digits_to_output)215 static const char *splt_u_get_format_ptr(const char *format, char *temp,
216     int *number_of_digits_to_output)
217 {
218   int format_length = strlen(format);
219   const char *format_ptr = format;
220 
221   if ((format_length > 2) && isdigit(format[2]))
222   {
223     if (number_of_digits_to_output)
224     {
225       sscanf(&format[2], "%d", number_of_digits_to_output);
226     }
227 
228     temp[2] = format[2];
229     format_ptr = format + 1;
230   }
231   else
232   {
233     if (number_of_digits_to_output)
234     {
235       *number_of_digits_to_output = -1;
236     }
237   }
238 
239   return format_ptr;
240 }
241 
splt_u_get_requested_num_of_digits(splt_state * state,const char * format,int * requested_num_of_digits,int is_alpha)242 static int splt_u_get_requested_num_of_digits(splt_state *state, const char *format,
243     int *requested_num_of_digits, int is_alpha)
244 {
245   int format_length = strlen(format);
246   int number_of_digits = 0;
247   if (is_alpha)
248   {
249     number_of_digits = state->oformat.output_alpha_format_digits;
250   }
251   else
252   {
253     number_of_digits = splt_of_get_oformat_number_of_digits_as_int(state);
254   }
255   int max_number_of_digits = number_of_digits;
256   *requested_num_of_digits = number_of_digits;
257 
258   if ((format_length > 2) && isdigit(format[2]))
259   {
260     *requested_num_of_digits = format[2] - '0';
261   }
262 
263   if (*requested_num_of_digits > number_of_digits)
264   {
265     max_number_of_digits = *requested_num_of_digits;
266   }
267 
268   return max_number_of_digits;
269 }
270 
271 /*! Encode track number as 'A', 'B', ... 'Z', 'AA, 'AB', ...
272  *
273  * This is not simply "base 26"; note that the lowest 'digit' is from 'A' to
274  * 'Z' (base 26), but all higher digits are 'A' to 'Z' plus 'nothing', i.e.,
275  * base 27. In other words, since after 'Z' comes 'AA', we cannot use 'AA'
276  * as the padded version of track number 1 ('A').
277  *
278  * This means that there are two distinct work modes:
279  * - The normal encoding is as described above.
280  * - When the user has specified the number of digits (padding), we encode
281  *   the track number as simple base-26: 'AAA', 'AAB', ... 'AAZ', 'ABA',
282  *   'ABB', ...
283  */
splt_u_alpha_track(splt_state * state,int nfield,char * fm,int fm_length,int number_of_digits,int tracknumber)284 static void splt_u_alpha_track(splt_state *state, int nfield,
285     char *fm, int fm_length, int number_of_digits, int tracknumber)
286 {
287   char *format = state->oformat.format[nfield];
288   int lowercase = (toupper(format[1]) == 'L');
289   char a = lowercase ? 'a' : 'A';
290   int zerobased = tracknumber - 1;
291   int i = 1, min_digits = state->oformat.output_alpha_format_digits;
292 
293   if (number_of_digits > 1)
294   {
295     /* Padding required => simple base-26 encoding */
296     if (number_of_digits < min_digits)
297       number_of_digits = min_digits;
298     for (i = 1; i <= number_of_digits; ++ i, zerobased /= 26)
299     {
300       int digit = (zerobased % 26);
301       fm[number_of_digits - i] = a + digit;
302     }
303   }
304   else
305   {
306     /* No padding: First letter base-26, others base-27 */
307     number_of_digits = min_digits;
308 
309     /* Start with the first, base-26 'digit' */
310     fm[number_of_digits - 1] = a + (zerobased % 26);
311 
312     /* Now handle all other digits */
313     zerobased /= 26;
314     for (i = 2; i <= number_of_digits; ++ i, zerobased /= 27)
315     {
316       int digit = (zerobased % 27);
317       fm[number_of_digits - i] = a + digit - 1;
318     }
319   }
320 
321   int offset = 0;
322   if ((strlen(format) > 2) && isdigit(format[2]))
323   {
324     offset = 1;
325   }
326   snprintf(fm + number_of_digits, fm_length - number_of_digits,
327       "%s", format + 2 + offset);
328 }
329 
splt_of_get_number_of_digits_from_total_time(splt_state * state)330 char splt_of_get_number_of_digits_from_total_time(splt_state *state)
331 {
332   long total_time = splt_t_get_total_time(state);
333   if (total_time <= 0)
334   {
335     return '2';
336   }
337 
338   long minutes = total_time / 100 / 60;
339   int i = (int) (log10(minutes));
340   char number_of_digits = (char) (i + '1');
341   if (number_of_digits == '1')
342   {
343     return '2';
344   }
345 
346   return number_of_digits;
347 }
348 
349 /*! \brief Automagically set the filename for a split point
350 
351   The filename is generated from the tags and the output format
352   string.
353 
354   \param state The central structure libmp3splt keeps all its data in
355   \param current_splt The number of the split point to determine the
356   filename for.
357  */
splt_of_put_output_format_filename(splt_state * state,int current_split)358 int splt_of_put_output_format_filename(splt_state *state, int current_split)
359 {
360   int error = SPLT_OK;
361 
362   int output_filenames = splt_o_get_int_option(state, SPLT_OPT_OUTPUT_FILENAMES);
363   if (output_filenames == SPLT_OUTPUT_CUSTOM)
364   {
365     return error;
366   }
367 
368   char *temp = NULL;
369   char *fm = NULL;
370   int i = 0;
371   char *output_filename = NULL;
372   int output_filename_size = 0;
373 
374   const char *title = NULL;
375   const char *artist = NULL;
376   const char *album = NULL;
377   const char *genre = NULL;
378   const char *performer = NULL;
379   const char *artist_or_performer = NULL;
380   char *original_filename = NULL;
381 
382   int split_file_number = splt_t_get_current_split_file_number(state);
383   int tags_index = split_file_number - 1;
384 
385   if (current_split == -1)
386   {
387     current_split = splt_t_get_current_split_file_number(state) - 1;
388   }
389 
390   long mins = -1; long secs = -1; long hundr = -1;
391   long point_value = splt_sp_get_splitpoint_value(state, current_split, &error);
392   splt_co_get_mins_secs_hundr(point_value, &mins, &secs, &hundr);
393   long next_mins = -1; long next_secs = -1; long next_hundr = -1;
394   long next_point_value = -1;
395   if (splt_sp_splitpoint_exists(state, current_split + 1))
396   {
397     next_point_value = splt_sp_get_splitpoint_value(state, current_split + 1, &error);
398     long total_time = splt_t_get_total_time(state);
399     if (total_time > 0 && next_point_value > total_time)
400     {
401       next_point_value = total_time;
402     }
403     splt_co_get_mins_secs_hundr(next_point_value, &next_mins, &next_secs, &next_hundr);
404   }
405 
406   int fm_length = 0;
407 
408   //if we get the tags from the first file
409   int remaining_tags_like_x = splt_o_get_int_option(state,SPLT_OPT_ALL_REMAINING_TAGS_LIKE_X);
410   int real_tags_number = 0;
411   if (state->split.tags_group)
412   {
413     real_tags_number = state->split.tags_group->real_tagsnumber;
414   }
415 
416   if ((tags_index >= real_tags_number) &&
417       (remaining_tags_like_x != -1))
418   {
419     tags_index = remaining_tags_like_x;
420   }
421 
422   const char *output_format = splt_of_get_oformat(state);
423   short write_eof = SPLT_FALSE;
424   if ((next_point_value == LONG_MAX) &&
425       (strcmp(output_format, SPLT_DEFAULT_OUTPUT) == 0))
426   {
427     write_eof = SPLT_TRUE;
428   }
429 
430   splt_d_print_debug(state,"The output format is _%s_\n", output_format);
431 
432   long mMsShH_value = -1;
433   short eof_written = SPLT_FALSE;
434 
435   for (i = 0; i < SPLT_OUTNUM; i++)
436   {
437     if (strlen(state->oformat.format[i]) == 0)
438     {
439       break;
440     }
441 
442     //if we have some % in the format (@ has been converted to %)
443     if (state->oformat.format[i][0] == '%')
444     {
445       //we allocate memory for the temp variable
446       if (temp)
447       {
448         free(temp);
449         temp = NULL;
450       }
451 
452       int temp_len = strlen(state->oformat.format[i])+10;
453       if ((temp = malloc(temp_len * sizeof(char))) == NULL)
454       {
455         error = SPLT_ERROR_CANNOT_ALLOCATE_MEMORY;
456         goto end;
457       }
458       memset(temp, 0x0, temp_len);
459 
460       temp[0] = '%';
461       temp[1] = 's';
462       char char_variable = state->oformat.format[i][1];
463       switch (char_variable)
464       {
465         case 's':
466           mMsShH_value = secs;
467           goto put_value;
468         case 'S':
469           mMsShH_value = next_secs;
470           goto put_value;
471         case 'm':
472           mMsShH_value = mins;
473           goto put_value;
474         case 'M':
475           mMsShH_value = next_mins;
476           goto put_value;
477         case 'h':
478           mMsShH_value = hundr;
479           goto put_value;
480         case 'H':
481           mMsShH_value = next_hundr;
482 put_value:
483           if (!eof_written)
484           {
485             if (write_eof &&
486                 (char_variable == 'S' ||
487                  char_variable == 'M' ||
488                  char_variable == 'H'))
489             {
490               write_eof = SPLT_FALSE;
491               eof_written = SPLT_TRUE;
492 
493               fm_length = strlen(temp) + 4;
494               if ((fm = malloc(fm_length * sizeof(char))) == NULL)
495               {
496                 error = SPLT_ERROR_CANNOT_ALLOCATE_MEMORY;
497                 goto end;
498               }
499               snprintf(fm, fm_length, temp, "EOF");
500             }
501             else if (mMsShH_value != -1)
502             {
503               temp[1] = '0';
504               char number_of_digits = '2';
505               if (char_variable == 'M' || char_variable == 'm')
506               {
507                 number_of_digits = splt_of_get_number_of_digits_from_total_time(state);
508               }
509               temp[2] = number_of_digits;
510               temp[3] = 'l';
511               temp[4] = 'd';
512 
513               const char *format = NULL;
514               int offset = 5;
515 
516               int number_of_digits_to_output = 0;
517               const char *new_format =
518                 splt_u_get_format_ptr(state->oformat.format[i], temp, &number_of_digits_to_output);
519 
520               if (number_of_digits_to_output == 0 && mMsShH_value == 0)
521               {
522                 const char *start_format = state->oformat.format[i] + 3;
523                 format = splt_of_goto_last_non_separator_character(start_format);
524                 offset = 0;
525 
526                 splt_of_trim_on_separator_characters(output_filename);
527               }
528               else
529               {
530                 format = new_format + 2;
531               }
532 
533               int requested_num_of_digits = 0;
534               int max_number_of_digits = splt_u_get_requested_num_of_digits(state,
535                   state->oformat.format[i], &requested_num_of_digits, SPLT_FALSE);
536 
537               snprintf(temp + offset, temp_len, "%s", format);
538 
539               fm_length = strlen(temp) + 1 + max_number_of_digits;
540               if ((fm = malloc(fm_length * sizeof(char))) == NULL)
541               {
542                 error = SPLT_ERROR_CANNOT_ALLOCATE_MEMORY;
543                 goto end;
544               }
545 
546               snprintf(fm, fm_length, temp, mMsShH_value);
547             }
548           }
549           break;
550         case 'A':
551           if (splt_tu_tags_exists(state, tags_index))
552           {
553             artist_or_performer = splt_tu_get_tags_field(state,tags_index, SPLT_TAGS_PERFORMER);
554             if (artist_or_performer == NULL || artist_or_performer[0] == '\0')
555             {
556               artist_or_performer = splt_tu_get_tags_field(state, tags_index, SPLT_TAGS_ARTIST);
557             }
558           }
559           else
560           {
561             artist_or_performer = NULL;
562           }
563 
564           //
565           if (artist_or_performer != NULL)
566           {
567             snprintf(temp+2,temp_len, "%s", state->oformat.format[i]+2);
568 
569             int artist_length = 0;
570             artist_length = strlen(artist_or_performer);
571             fm_length = strlen(temp) + artist_length + 1;
572           }
573           else
574           {
575             snprintf(temp,temp_len, "%s", state->oformat.format[i]+2);
576             fm_length = strlen(temp) + 1;
577           }
578 
579           if ((fm = malloc(fm_length * sizeof(char))) == NULL)
580           {
581             error = SPLT_ERROR_CANNOT_ALLOCATE_MEMORY;
582             goto end;
583           }
584 
585           //
586           if (artist_or_performer != NULL)
587           {
588             char *dup = duplicate_and_clean(state, artist_or_performer, &error);
589             if (!dup) { goto end; }
590             snprintf(fm, fm_length, temp, dup);
591             free(dup);
592           }
593           else
594           {
595             snprintf(fm, fm_length, "%s", temp);
596           }
597 
598           break;
599         case 'a':
600           if (splt_tu_tags_exists(state, tags_index))
601           {
602             artist = splt_tu_get_tags_field(state, tags_index, SPLT_TAGS_ARTIST);
603           }
604           else
605           {
606             artist = NULL;
607           }
608 
609           //
610           if (artist != NULL)
611           {
612             snprintf(temp+2,temp_len, "%s", state->oformat.format[i]+2);
613 
614             int artist_length = 0;
615             artist_length = strlen(artist);
616             fm_length = strlen(temp) + artist_length + 1;
617           }
618           else
619           {
620             snprintf(temp,temp_len, "%s", state->oformat.format[i]+2);
621             fm_length = strlen(temp) + 1;
622           }
623 
624           if ((fm = malloc(fm_length * sizeof(char))) == NULL)
625           {
626             error = SPLT_ERROR_CANNOT_ALLOCATE_MEMORY;
627             goto end;
628           }
629 
630           //
631           if (artist != NULL)
632           {
633             char *dup = duplicate_and_clean(state, artist, &error);
634             if (!dup) { goto end; }
635             snprintf(fm, fm_length, temp, dup);
636             free(dup);
637           }
638           else
639           {
640             snprintf(fm, fm_length, "%s", temp);
641           }
642           break;
643         case 'b':
644           if (splt_tu_tags_exists(state,tags_index))
645           {
646             album = splt_tu_get_tags_field(state, tags_index, SPLT_TAGS_ALBUM);
647           }
648           else
649           {
650             album = NULL;
651           }
652 
653           //
654           if (album != NULL)
655           {
656             int album_length = 0;
657             album_length = strlen(album);
658             snprintf(temp+2, temp_len, "%s", state->oformat.format[i]+2);
659 
660             fm_length = strlen(temp) + album_length + 1;
661           }
662           else
663           {
664             snprintf(temp,temp_len, "%s", state->oformat.format[i]+2);
665             fm_length = strlen(temp) + 1;
666           }
667 
668           if ((fm = malloc(fm_length * sizeof(char))) == NULL)
669           {
670             error = SPLT_ERROR_CANNOT_ALLOCATE_MEMORY;
671             goto end;
672           }
673 
674           //
675           if (album != NULL)
676           {
677             char *dup = duplicate_and_clean(state, album, &error);
678             if (!dup) { goto end; }
679             snprintf(fm, fm_length, temp, dup);
680             free(dup);
681           }
682           else
683           {
684             snprintf(fm, fm_length, "%s", temp);
685           }
686           break;
687         case 'g':
688           if (splt_tu_tags_exists(state,tags_index))
689           {
690             genre = splt_tu_get_tags_field(state, tags_index, SPLT_TAGS_GENRE);
691           }
692           else
693           {
694             genre = NULL;
695           }
696 
697           //
698           if (genre != NULL)
699           {
700             int genre_length = 0;
701             genre_length = strlen(genre);
702             snprintf(temp+2, temp_len, "%s", state->oformat.format[i]+2);
703 
704             fm_length = strlen(temp) + genre_length + 1;
705           }
706           else
707           {
708             snprintf(temp,temp_len, "%s", state->oformat.format[i]+2);
709             fm_length = strlen(temp) + 1;
710           }
711 
712           if ((fm = malloc(fm_length * sizeof(char))) == NULL)
713           {
714             error = SPLT_ERROR_CANNOT_ALLOCATE_MEMORY;
715             goto end;
716           }
717 
718           //
719           if (genre != NULL)
720           {
721             char *dup = duplicate_and_clean(state, genre, &error);
722             if (!dup) { goto end; }
723             snprintf(fm, fm_length, temp, dup);
724             free(dup);
725           }
726           else
727           {
728             snprintf(fm, fm_length, "%s", temp);
729           }
730           break;
731         case 't':
732           if (splt_tu_tags_exists(state,tags_index))
733           {
734             title = splt_tu_get_tags_field(state, tags_index, SPLT_TAGS_TITLE);
735           }
736           else
737           {
738             title = NULL;
739           }
740 
741           //
742           if (title != NULL)
743           {
744             int title_length = 0;
745             title_length = strlen(title);
746             snprintf(temp+2, temp_len, "%s", state->oformat.format[i]+2);
747 
748             fm_length = strlen(temp) + title_length + 1;
749           }
750           else
751           {
752             snprintf(temp,temp_len, "%s", state->oformat.format[i]+2);
753             fm_length = strlen(temp) + 1;
754           }
755 
756           if ((fm = malloc(fm_length * sizeof(char))) == NULL)
757           {
758             error = SPLT_ERROR_CANNOT_ALLOCATE_MEMORY;
759             goto end;
760           }
761 
762           //
763           if (title != NULL)
764           {
765             char *dup = duplicate_and_clean(state, title, &error);
766             if (!dup) { goto end; }
767             snprintf(fm, fm_length, temp, dup);
768             free(dup);
769           }
770           else
771           {
772             snprintf(fm, fm_length, "%s", temp);
773           }
774           break;
775         case 'p':
776           if (splt_tu_tags_exists(state,tags_index))
777           {
778             performer = splt_tu_get_tags_field(state, tags_index, SPLT_TAGS_PERFORMER);
779           }
780           else
781           {
782             performer = NULL;
783           }
784 
785           //
786           if (performer != NULL)
787           {
788             int performer_length = 0;
789             performer_length = strlen(performer);
790             snprintf(temp+2, temp_len, "%s", state->oformat.format[i]+2);
791 
792             fm_length = strlen(temp) + performer_length + 1;
793           }
794           else
795           {
796             snprintf(temp,temp_len, "%s", state->oformat.format[i]+2);
797             fm_length = strlen(temp) + 1;
798           }
799 
800           if ((fm = malloc(fm_length * sizeof(char))) == NULL)
801           {
802             error = SPLT_ERROR_CANNOT_ALLOCATE_MEMORY;
803             goto end;
804           }
805 
806           if (performer != NULL)
807           {
808             char *dup = duplicate_and_clean(state, performer, &error);
809             if (!dup) { goto end; }
810             snprintf(fm, fm_length, temp, dup);
811             free(dup);
812           }
813           else
814           {
815             snprintf(fm, fm_length, "%s", temp);
816           }
817           break;
818         case 'l':
819         case 'L':
820         case 'u':
821         case 'U':
822         case 'n':
823         case 'N':
824           temp[1] = '0';
825           temp[2] = splt_of_get_oformat_number_of_digits_as_char(state);
826           temp[3] = 'd';
827 
828           int tracknumber = split_file_number;
829 
830           //if not time split, or normal split, or silence split or error,
831           //we put the track number from the tags
832           int split_mode = splt_o_get_int_option(state,SPLT_OPT_SPLIT_MODE);
833           if ((isupper(state->oformat.format[i][1])) ||
834               ((split_mode != SPLT_OPTION_TIME_MODE) &&
835                (split_mode != SPLT_OPTION_NORMAL_MODE) &&
836                (split_mode != SPLT_OPTION_SILENCE_MODE) &&
837                (split_mode != SPLT_OPTION_TRIM_SILENCE_MODE) &&
838                (split_mode != SPLT_OPTION_ERROR_MODE) &&
839                (split_mode != SPLT_OPTION_LENGTH_MODE)))
840           {
841             if (splt_tu_tags_exists(state, tags_index))
842             {
843               const int *tags_track = splt_tu_get_tags_field(state, tags_index, SPLT_TAGS_TRACK);
844               if (tags_track && *tags_track != -1)
845               {
846                 tracknumber = *tags_track;
847               }
848             }
849           }
850 
851           int requested_num_of_digits = 0;
852           int max_num_of_digits = splt_u_get_requested_num_of_digits(state,
853               state->oformat.format[i], &requested_num_of_digits, SPLT_FALSE);
854 
855           int alpha_requested_num_of_digits = 0;
856           int alpha_max_num_of_digits = splt_u_get_requested_num_of_digits(state,
857               state->oformat.format[i], &alpha_requested_num_of_digits, SPLT_TRUE);
858 
859           int is_numeric = toupper(state->oformat.format[i][1]) == 'N';
860           if (is_numeric)
861           {
862             const char *format =
863               splt_u_get_format_ptr(state->oformat.format[i], temp, NULL);
864 
865             snprintf(temp + 4, temp_len, "%s", format + 2);
866             fm_length = strlen(temp) + 1 + max_num_of_digits;
867           }
868           else
869           {
870             fm_length = strlen(state->oformat.format[i]) + 1 + alpha_max_num_of_digits;
871           }
872 
873           if ((fm = malloc(fm_length * sizeof(char))) == NULL)
874           {
875             error = SPLT_ERROR_CANNOT_ALLOCATE_MEMORY;
876             goto end;
877           }
878           memset(fm, '\0', fm_length);
879 
880           if (tracknumber == -2)
881           {
882             temp[1] = 's';
883             temp[2] = '%';
884             temp[3] = 's';
885             snprintf(fm, fm_length, temp, "", "");
886           }
887           else
888           {
889             if (is_numeric)
890             {
891               snprintf(fm, fm_length, temp, tracknumber);
892             }
893             else
894             {
895               splt_u_alpha_track(state, i, fm, fm_length,
896                   alpha_requested_num_of_digits, tracknumber);
897             }
898           }
899           break;
900         case 'f':
901           if (splt_t_get_filename_to_split(state) != NULL)
902           {
903             original_filename = strdup(splt_su_get_fname_without_path(splt_t_get_filename_to_split(state)));
904             if (original_filename)
905             {
906               snprintf(temp+2,temp_len, "%s", state->oformat.format[i]+2);
907 
908               splt_su_cut_extension(original_filename);
909 
910               int filename_length = strlen(original_filename);
911 
912               fm_length = strlen(temp) + filename_length;
913               if ((fm = malloc(fm_length * sizeof(char))) == NULL)
914               {
915                 error = SPLT_ERROR_CANNOT_ALLOCATE_MEMORY;
916                 goto end;
917               }
918 
919               snprintf(fm, fm_length, temp, original_filename);
920               free(original_filename);
921               original_filename = NULL;
922             }
923             else
924             {
925               error = SPLT_ERROR_CANNOT_ALLOCATE_MEMORY;
926               goto end;
927             }
928           }
929           break;
930         case 'd':
931           {
932             char *last_dir = splt_su_get_last_dir_of_fname(splt_t_get_filename_to_split(state), &error);
933             if (error < 0) { goto end; }
934 
935             if (last_dir)
936             {
937               snprintf(temp+2, temp_len, "%s", state->oformat.format[i]+2);
938 
939               int last_dir_length = strlen(last_dir);
940 
941               fm_length = strlen(temp) + last_dir_length;
942               if ((fm = malloc(fm_length * sizeof(char))) == NULL)
943               {
944                 error = SPLT_ERROR_CANNOT_ALLOCATE_MEMORY;
945                 goto end;
946               }
947 
948               snprintf(fm, fm_length, temp, last_dir);
949               free(last_dir);
950               last_dir = NULL;
951             }
952           }
953           break;
954       }
955     }
956     else
957     {
958       fm_length = SPLT_MAXOLEN;
959       if ((fm = malloc(fm_length * sizeof(char))) == NULL)
960       {
961         error = SPLT_ERROR_CANNOT_ALLOCATE_MEMORY;
962         goto end;
963       }
964 
965       strncpy(fm, state->oformat.format[i], SPLT_MAXOLEN);
966     }
967 
968     int fm_size = 7;
969     if (fm != NULL)
970     {
971       fm_size = strlen(fm);
972     }
973 
974     //allocate memory for the output filename
975     if (!output_filename)
976     {
977       if ((output_filename = malloc((1+fm_size)*sizeof(char))) == NULL)
978       {
979         error = SPLT_ERROR_CANNOT_ALLOCATE_MEMORY;
980         goto end;
981       }
982       output_filename_size = fm_size;
983       output_filename[0] = '\0';
984     }
985     else
986     {
987       output_filename_size += fm_size+1;
988       if ((output_filename = realloc(output_filename, output_filename_size * sizeof(char))) == NULL)
989       {
990         error = SPLT_ERROR_CANNOT_ALLOCATE_MEMORY;
991         goto end;
992       }
993     }
994 
995     if (fm != NULL)
996     {
997       strcat(output_filename, fm);
998     }
999 
1000     //we free fm
1001     if (fm)
1002     {
1003       free(fm);
1004       fm = NULL;
1005     }
1006   }
1007 
1008   splt_d_print_debug(state,"The new output filename is _%s_\n", output_filename);
1009   int cur_splt = splt_t_get_current_split(state);
1010   int name_error = splt_sp_set_splitpoint_name(state, cur_splt, output_filename);
1011   if (name_error != SPLT_OK) { error = name_error; }
1012 
1013 end:
1014   if (output_filename)
1015   {
1016     free(output_filename);
1017     output_filename = NULL;
1018   }
1019   if (fm)
1020   {
1021     free(fm);
1022     fm = NULL;
1023   }
1024   if (temp)
1025   {
1026     free(temp);
1027     temp = NULL;
1028   }
1029 
1030   return error;
1031 }
1032 
splt_of_trim_on_separator_characters(char * filename)1033 static void splt_of_trim_on_separator_characters(char *filename)
1034 {
1035   if (!filename)
1036   {
1037     return;
1038   }
1039 
1040   int last_index = strlen(filename)-1;
1041   if (last_index < 0)
1042   {
1043     return;
1044   }
1045 
1046   while (last_index >= 0)
1047   {
1048     char last_char = filename[last_index];
1049     if (last_char == ':' || last_char == '_' ||
1050         last_char == '-' || last_char == '.')
1051     {
1052       filename[last_index] = '\0';
1053     }
1054     else
1055     {
1056       return;
1057     }
1058 
1059     last_index--;
1060   }
1061 }
1062 
splt_of_goto_last_non_separator_character(const char * format)1063 static const char *splt_of_goto_last_non_separator_character(const char *format)
1064 {
1065   if (!format)
1066   {
1067     return format;
1068   }
1069 
1070   int counter = 0;
1071   int max_length = strlen(format);
1072   while (counter < max_length)
1073   {
1074     if (format[counter] == ':' || format[counter] == '_' ||
1075         format[counter] == '-' || format[counter] == '.')
1076     {
1077       break;
1078     }
1079 
1080     counter++;
1081   }
1082 
1083   return format + counter;
1084 }
1085 
1086