"Fossies" - the Fresh Open Source Software Archive

Member "minidlna-1.3.0/tagutils/tagutils-misc.c" (24 Nov 2020, 7430 Bytes) of package /linux/privat/minidlna-1.3.0.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "tagutils-misc.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 1.2.1_vs_1.3.0.

    1 //=========================================================================
    2 // FILENAME : tagutils-misc.c
    3 // DESCRIPTION  : Misc routines for supporting tagutils
    4 //=========================================================================
    5 // Copyright (c) 2008- NETGEAR, Inc. All Rights Reserved.
    6 //=========================================================================
    7 
    8 /* This program is free software; you can redistribute it and/or modify
    9  * it under the terms of the GNU General Public License as published by
   10  * the Free Software Foundation; either version 2 of the License, or
   11  * (at your option) any later version.
   12  *
   13  * This program is distributed in the hope that it will be useful,
   14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
   15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   16  * GNU General Public License for more details.
   17  *
   18  * You should have received a copy of the GNU General Public License
   19  * along with this program. If not, see <http://www.gnu.org/licenses/>.
   20  */
   21 
   22 /**************************************************************************
   23 * Language
   24 **************************************************************************/
   25 
   26 #define MAX_ICONV_BUF 1024
   27 
   28 typedef enum {
   29     ICONV_OK,
   30     ICONV_TRYNEXT,
   31     ICONV_FATAL
   32 } iconv_result;
   33 
   34 #ifdef HAVE_ICONV
   35 static iconv_result
   36 do_iconv(const char* to_ces, const char* from_ces,
   37      ICONV_CONST char *inbuf,  size_t inbytesleft,
   38      char *outbuf_orig, size_t outbytesleft_orig)
   39 {
   40     size_t rc;
   41     iconv_result ret = ICONV_OK;
   42 
   43     size_t outbytesleft = outbytesleft_orig - 1;
   44     char* outbuf = outbuf_orig;
   45 
   46     iconv_t cd  = iconv_open(to_ces, from_ces);
   47 
   48     if(cd == (iconv_t)-1)
   49     {
   50         return ICONV_FATAL;
   51     }
   52     rc = iconv(cd, &inbuf, &inbytesleft, &outbuf, &outbytesleft);
   53     if(rc == (size_t)-1)
   54     {
   55         if(errno == E2BIG)
   56         {
   57             ret = ICONV_FATAL;
   58         }
   59         else
   60         {
   61             ret = ICONV_TRYNEXT;
   62             memset(outbuf_orig, '\0', outbytesleft_orig);
   63         }
   64     }
   65     iconv_close(cd);
   66 
   67     return ret;
   68 }
   69 #else // HAVE_ICONV
   70 static iconv_result
   71 do_iconv(const char* to_ces, const char* from_ces,
   72      char *inbuf,  size_t inbytesleft,
   73      char *outbuf_orig, size_t outbytesleft_orig)
   74 {
   75     return ICONV_FATAL;
   76 }
   77 #endif // HAVE_ICONV
   78 
   79 #define N_LANG_ALT 8
   80 struct {
   81     char *lang;
   82     char *cpnames[N_LANG_ALT];
   83 } iconv_map[] = {
   84     { "ja_JP",     { "CP932", "CP950", "CP936", "ISO-8859-1", 0 } },
   85     { "zh_CN",  { "CP936", "CP950", "CP932", "ISO-8859-1", 0 } },
   86     { "zh_TW",  { "CP950", "CP936", "CP932", "ISO-8859-1", 0 } },
   87     { "ko_KR",  { "CP949", "ISO-8859-1", 0 } },
   88     { 0,        { 0 } }
   89 };
   90 static int lang_index = -1;
   91 
   92 static int
   93 _lang2cp(char *lang)
   94 {
   95     int cp;
   96 
   97     if(!lang || lang[0] == '\0')
   98         return -1;
   99     for(cp = 0; iconv_map[cp].lang; cp++)
  100     {
  101         if(!strcasecmp(iconv_map[cp].lang, lang))
  102             return cp;
  103     }
  104     return -2;
  105 }
  106 
  107 static unsigned char*
  108 _get_utf8_text(const id3_ucs4_t* native_text)
  109 {
  110     unsigned char *utf8_text = NULL;
  111     char *in, *in8, *iconv_buf;
  112     iconv_result rc;
  113     int i, n;
  114 
  115     in = (char*)id3_ucs4_latin1duplicate(native_text);
  116     if(!in)
  117     {
  118         goto out;
  119     }
  120 
  121     in8 = (char*)id3_ucs4_utf8duplicate(native_text);
  122     if(!in8)
  123     {
  124         free(in);
  125         goto out;
  126     }
  127 
  128     iconv_buf = (char*)calloc(MAX_ICONV_BUF, sizeof(char));
  129     if(!iconv_buf)
  130     {
  131         free(in); free(in8);
  132         goto out;
  133     }
  134 
  135     i = lang_index;
  136     // (1) try utf8 -> default
  137     rc = do_iconv(iconv_map[i].cpnames[0], "UTF-8", in8, strlen(in8), iconv_buf, MAX_ICONV_BUF);
  138     if(rc == ICONV_OK)
  139     {
  140         utf8_text = (unsigned char*)in8;
  141         free(iconv_buf);
  142     }
  143     else if(rc == ICONV_TRYNEXT)
  144     {
  145         // (2) try default -> utf8
  146         rc = do_iconv("UTF-8", iconv_map[i].cpnames[0], in, strlen(in), iconv_buf, MAX_ICONV_BUF);
  147         if(rc == ICONV_OK)
  148         {
  149             utf8_text = (unsigned char*)iconv_buf;
  150         }
  151         else if(rc == ICONV_TRYNEXT)
  152         {
  153             // (3) try other encodes
  154             for(n = 1; n < N_LANG_ALT && iconv_map[i].cpnames[n]; n++)
  155             {
  156                 rc = do_iconv("UTF-8", iconv_map[i].cpnames[n], in, strlen(in), iconv_buf, MAX_ICONV_BUF);
  157                 if(rc == ICONV_OK)
  158                 {
  159                     utf8_text = (unsigned char*)iconv_buf;
  160                     break;
  161                 }
  162             }
  163             if(!utf8_text)
  164             {
  165                 // cannot iconv
  166                 utf8_text = (unsigned char*)id3_ucs4_utf8duplicate(native_text);
  167                 free(iconv_buf);
  168             }
  169         }
  170         free(in8);
  171     }
  172     free(in);
  173 
  174  out:
  175     if(!utf8_text)
  176     {
  177         utf8_text = (unsigned char*)strdup("UNKNOWN");
  178     }
  179 
  180     return utf8_text;
  181 }
  182 
  183 
  184 static void
  185 vc_scan(struct song_metadata *psong, const char *comment, const size_t length)
  186 {
  187     char strbuf[1024];
  188 
  189     if(length > (sizeof(strbuf) - 1))
  190     {
  191         if( strncasecmp(comment, "LYRICS=", 7) != 0 &&
  192             strncasecmp(comment, "coverart=", 9) != 0 &&
  193             strncasecmp(comment, "METADATA_BLOCK_PICTURE=", 23) != 0 )
  194         {
  195             const char *eq = strchr(comment, '=');
  196             int len = 8;
  197             if (eq)
  198                 len = eq - comment;
  199             DPRINTF(E_WARN, L_SCANNER, "Vorbis %.*s too long [%s]\n",
  200                 len, comment, psong->path);
  201         }
  202         return;
  203     }
  204     strncpy(strbuf, comment, length);
  205     strbuf[length] = '\0';
  206 
  207     // ALBUM, ARTIST, PUBLISHER, COPYRIGHT, DISCNUMBER, ISRC, EAN/UPN, LABEL, LABELNO,
  208     // LICENSE, OPUS, SOURCEMEDIA, TITLE, TRACKNUMBER, VERSION, ENCODED-BY, ENCODING,
  209     // -- following tags are muliples
  210     // COMPOSER, ARRANGER, LYRICIST, AUTHOR, CONDUCTOR, PERFORMER, ENSEMBLE, PART
  211     // PARTNUMBER, GENRE, DATE, LOCATION, COMMENT
  212     if(!strncasecmp(strbuf, "ALBUM=", 6))
  213     {
  214         if( *(strbuf+6) )
  215             psong->album = strdup(strbuf + 6);
  216     }
  217     else if(!strncasecmp(strbuf, "ARTIST=", 7))
  218     {
  219         if( *(strbuf+7) )
  220             psong->contributor[ROLE_ARTIST] = strdup(strbuf + 7);
  221     }
  222     else if(!strncasecmp(strbuf, "ARTISTSORT=", 11))
  223     {
  224         psong->contributor_sort[ROLE_ARTIST] = strdup(strbuf + 11);
  225     }
  226     else if(!strncasecmp(strbuf, "ALBUMARTIST=", 12))
  227     {
  228         if( *(strbuf+12) )
  229             psong->contributor[ROLE_BAND] = strdup(strbuf + 12);
  230     }
  231     else if(!strncasecmp(strbuf, "ALBUMARTISTSORT=", 16))
  232     {
  233         psong->contributor_sort[ROLE_BAND] = strdup(strbuf + 16);
  234     }
  235     else if(!strncasecmp(strbuf, "TITLE=", 6))
  236     {
  237         if( *(strbuf+6) )
  238             psong->title = strdup(strbuf + 6);
  239     }
  240     else if(!strncasecmp(strbuf, "TRACKNUMBER=", 12))
  241     {
  242         psong->track = atoi(strbuf + 12);
  243     }
  244     else if(!strncasecmp(strbuf, "DISCNUMBER=", 11))
  245     {
  246         psong->disc = atoi(strbuf + 11);
  247     }
  248     else if(!strncasecmp(strbuf, "GENRE=", 6))
  249     {
  250         if( *(strbuf+6) )
  251             psong->genre = strdup(strbuf + 6);
  252     }
  253     else if(!strncasecmp(strbuf, "DATE=", 5))
  254     {
  255         if(length >= (5 + 10) &&
  256            isdigit(strbuf[5 + 0]) && isdigit(strbuf[5 + 1]) && ispunct(strbuf[5 + 2]) &&
  257            isdigit(strbuf[5 + 3]) && isdigit(strbuf[5 + 4]) && ispunct(strbuf[5 + 5]) &&
  258            isdigit(strbuf[5 + 6]) && isdigit(strbuf[5 + 7]) && isdigit(strbuf[5 + 8]) && isdigit(strbuf[5 + 9]))
  259         {
  260             // nn-nn-yyyy
  261             strbuf[5 + 10] = '\0';
  262             psong->year = atoi(strbuf + 5 + 6);
  263         }
  264         else
  265         {
  266             // year first. year is at most 4 digit.
  267             strbuf[5 + 4] = '\0';
  268             psong->year = atoi(strbuf + 5);
  269         }
  270     }
  271     else if(!strncasecmp(strbuf, "COMMENT=", 8))
  272     {
  273         if( *(strbuf+8) )
  274             psong->comment = strdup(strbuf + 8);
  275     }
  276     else if(!strncasecmp(strbuf, "MUSICBRAINZ_ALBUMID=", 20))
  277     {
  278         psong->musicbrainz_albumid = strdup(strbuf + 20);
  279     }
  280     else if(!strncasecmp(strbuf, "MUSICBRAINZ_TRACKID=", 20))
  281     {
  282         psong->musicbrainz_trackid = strdup(strbuf + 20);
  283     }
  284     else if(!strncasecmp(strbuf, "MUSICBRAINZ_TRACKID=", 20))
  285     {
  286         psong->musicbrainz_trackid = strdup(strbuf + 20);
  287     }
  288     else if(!strncasecmp(strbuf, "MUSICBRAINZ_ARTISTID=", 21))
  289     {
  290         psong->musicbrainz_artistid = strdup(strbuf + 21);
  291     }
  292     else if(!strncasecmp(strbuf, "MUSICBRAINZ_ALBUMARTISTID=", 26))
  293     {
  294         psong->musicbrainz_albumartistid = strdup(strbuf + 26);
  295     }
  296 }