X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=src%2Ftext%2Fstrings.c;h=be02bc034aa1291112f77e8e3468c95b50f449e0;hb=21724f580a769fdb2205218bb2e1e1acb8f645b6;hp=1de2ab047d09638ebdf47250ec7d94a114be7c37;hpb=7f8cab90a9d1d553a2d1bd8679eae77b43b95455;p=vlc diff --git a/src/text/strings.c b/src/text/strings.c index 1de2ab047d..be02bc034a 100644 --- a/src/text/strings.c +++ b/src/text/strings.c @@ -27,9 +27,6 @@ * Preamble *****************************************************************************/ #include -#include -#include -#include #include /* Needed by str_format_time */ @@ -63,6 +60,8 @@ char *unescape_URI_duplicate( const char *psz ) void unescape_URI( char *psz ) { unsigned char *in = (unsigned char *)psz, *out = in, c; + if( psz == NULL ) + return; while( ( c = *in++ ) != '\0' ) { @@ -144,6 +143,8 @@ char *decode_URI_duplicate( const char *psz ) void decode_URI( char *psz ) { unsigned char *in = (unsigned char *)psz, *out = in, c; + if( psz == NULL ) + return; while( ( c = *in++ ) != '\0' ) { @@ -242,30 +243,174 @@ void resolve_xml_special_chars( char *psz_value ) while ( *psz_value ) { - if( !strncmp( psz_value, "<", 4 ) ) + if( *psz_value == '&' ) { - *p_pos = '<'; - psz_value += 4; - } - else if( !strncmp( psz_value, ">", 4 ) ) - { - *p_pos = '>'; - psz_value += 4; - } - else if( !strncmp( psz_value, "&", 5 ) ) - { - *p_pos = '&'; - psz_value += 5; - } - else if( !strncmp( psz_value, """, 6 ) ) - { - *p_pos = '\"'; - psz_value += 6; - } - else if( !strncmp( psz_value, "'", 6 ) ) - { - *p_pos = '\''; - psz_value += 6; +#define TRY_CHAR( src, len, dst ) \ + if( !strncmp( psz_value, src, len ) ) \ + { \ + *p_pos = dst; \ + psz_value += len; \ + } +#define TRY_LONGCHAR( src, len, dst ) \ + if( !strncmp( psz_value, src, len ) ) \ + { \ + strncpy( p_pos, dst, strlen( dst ) ); \ + p_pos += strlen( dst ) - 1; \ + psz_value += len; \ + } + TRY_CHAR( "<", 4, '<' ) + else TRY_CHAR( ">", 4, '>' ) + else TRY_CHAR( "&", 5, '&' ) + else TRY_CHAR( """, 6, '"' ) + else TRY_CHAR( "'", 6, '\'' ) + else if( psz_value[1] == '#' ) + { + char *psz_end; + int i = strtol( psz_value+2, &psz_end, 10 ); + if( *psz_end == ';' ) + { + if( i >= 32 && i <= 126 ) + { + *p_pos = (char)i; + psz_value = psz_end+1; + } + else + { + /* Unhandled code, FIXME */ + *p_pos = *psz_value; + psz_value++; + } + } + else + { + /* Invalid entity number */ + *p_pos = *psz_value; + psz_value++; + } + } + else TRY_LONGCHAR( "À", 8, "À" ) + else TRY_LONGCHAR( "Á", 8, "Á" ) + else TRY_LONGCHAR( "Â", 7, "Â" ) + else TRY_LONGCHAR( "Ã", 8, "Ã" ) + else TRY_LONGCHAR( "Ä", 6, "Ä" ) + else TRY_LONGCHAR( "Å", 7, "Å" ) + else TRY_LONGCHAR( "Æ", 7, "Æ" ) + else TRY_LONGCHAR( "Ç", 8, "Ç" ) + else TRY_LONGCHAR( "È", 8, "È" ) + else TRY_LONGCHAR( "É", 8, "É" ) + else TRY_LONGCHAR( "Ê", 7, "Ê" ) + else TRY_LONGCHAR( "Ë", 6, "Ë" ) + else TRY_LONGCHAR( "Ì", 8, "Ì" ) + else TRY_LONGCHAR( "Í", 8, "Í" ) + else TRY_LONGCHAR( "Î", 7, "Î" ) + else TRY_LONGCHAR( "Ï", 6, "Ï" ) + else TRY_LONGCHAR( "Ð", 5, "Ð" ) + else TRY_LONGCHAR( "Ñ", 8, "Ñ" ) + else TRY_LONGCHAR( "Ò", 8, "Ò" ) + else TRY_LONGCHAR( "Ó", 8, "Ó" ) + else TRY_LONGCHAR( "Ô", 7, "Ô" ) + else TRY_LONGCHAR( "Õ", 8, "Õ" ) + else TRY_LONGCHAR( "Ö", 6, "Ö" ) + else TRY_LONGCHAR( "Ø", 8, "Ø" ) + else TRY_LONGCHAR( "Ù", 8, "Ù" ) + else TRY_LONGCHAR( "Ú", 8, "Ú" ) + else TRY_LONGCHAR( "Û", 7, "Û" ) + else TRY_LONGCHAR( "Ü", 6, "Ü" ) + else TRY_LONGCHAR( "Ý", 8, "Ý" ) + else TRY_LONGCHAR( "Þ", 7, "Þ" ) + else TRY_LONGCHAR( "ß", 7, "ß" ) + else TRY_LONGCHAR( "à", 8, "à" ) + else TRY_LONGCHAR( "á", 8, "á" ) + else TRY_LONGCHAR( "â", 7, "â" ) + else TRY_LONGCHAR( "ã", 8, "ã" ) + else TRY_LONGCHAR( "ä", 6, "ä" ) + else TRY_LONGCHAR( "å", 7, "Ã¥" ) + else TRY_LONGCHAR( "æ", 7, "æ" ) + else TRY_LONGCHAR( "ç", 8, "ç" ) + else TRY_LONGCHAR( "è", 8, "è" ) + else TRY_LONGCHAR( "é", 8, "é" ) + else TRY_LONGCHAR( "ê", 7, "ê" ) + else TRY_LONGCHAR( "ë", 6, "ë" ) + else TRY_LONGCHAR( "ì", 8, "ì" ) + else TRY_LONGCHAR( "í", 8, "í" ) + else TRY_LONGCHAR( "î", 7, "î" ) + else TRY_LONGCHAR( "ï", 6, "ï" ) + else TRY_LONGCHAR( "ð", 5, "ð" ) + else TRY_LONGCHAR( "ñ", 8, "ñ" ) + else TRY_LONGCHAR( "ò", 8, "ò" ) + else TRY_LONGCHAR( "ó", 8, "ó" ) + else TRY_LONGCHAR( "ô", 7, "ô" ) + else TRY_LONGCHAR( "õ", 8, "õ" ) + else TRY_LONGCHAR( "ö", 6, "ö" ) + else TRY_LONGCHAR( "ø", 8, "ø" ) + else TRY_LONGCHAR( "ù", 8, "ù" ) + else TRY_LONGCHAR( "ú", 8, "ú" ) + else TRY_LONGCHAR( "û", 7, "û" ) + else TRY_LONGCHAR( "ü", 6, "ü" ) + else TRY_LONGCHAR( "ý", 8, "ý" ) + else TRY_LONGCHAR( "þ", 7, "þ" ) + else TRY_LONGCHAR( "ÿ", 6, "ÿ" ) + else TRY_LONGCHAR( "¡", 7, "¡" ) + else TRY_LONGCHAR( "¤", 8, "¤" ) + else TRY_LONGCHAR( "¢", 6, "¢" ) + else TRY_LONGCHAR( "£", 7, "£" ) + else TRY_LONGCHAR( "¥", 5, "Â¥" ) + else TRY_LONGCHAR( "¦", 8, "¦" ) + else TRY_LONGCHAR( "§", 6, "§" ) + else TRY_LONGCHAR( "¨", 5, "¨" ) + else TRY_LONGCHAR( "©", 6, "©" ) + else TRY_LONGCHAR( "ª", 6, "ª" ) + else TRY_LONGCHAR( "«", 7, "«" ) + else TRY_LONGCHAR( "¬", 5, "¬" ) + else TRY_LONGCHAR( "­", 5, "­" ) + else TRY_LONGCHAR( "®", 5, "®" ) + else TRY_LONGCHAR( "™", 7, "™" ) + else TRY_LONGCHAR( "¯", 6, "¯" ) + else TRY_LONGCHAR( "°", 5, "°" ) + else TRY_LONGCHAR( "±", 8, "±" ) + else TRY_LONGCHAR( "²", 6, "²" ) + else TRY_LONGCHAR( "³", 6, "³" ) + else TRY_LONGCHAR( "´", 7, "´" ) + else TRY_LONGCHAR( "µ", 7, "µ" ) + else TRY_LONGCHAR( "¶", 6, "¶" ) + else TRY_LONGCHAR( "·", 8, "·" ) + else TRY_LONGCHAR( "¸", 7, "¸" ) + else TRY_LONGCHAR( "¹", 6, "¹" ) + else TRY_LONGCHAR( "º", 6, "º" ) + else TRY_LONGCHAR( "»", 7, "»" ) + else TRY_LONGCHAR( "¼", 8, "¼" ) + else TRY_LONGCHAR( "½", 8, "½" ) + else TRY_LONGCHAR( "¾", 8, "¾" ) + else TRY_LONGCHAR( "¿", 8, "¿" ) + else TRY_LONGCHAR( "×", 7, "×" ) + else TRY_LONGCHAR( "÷", 8, "÷" ) + else TRY_LONGCHAR( "Œ", 7, "Œ" ) + else TRY_LONGCHAR( "œ", 7, "œ" ) + else TRY_LONGCHAR( "Š", 8, "Å " ) + else TRY_LONGCHAR( "š", 8, "Å¡" ) + else TRY_LONGCHAR( "Ÿ", 6, "Ÿ" ) + else TRY_LONGCHAR( "ˆ", 6, "ˆ" ) + else TRY_LONGCHAR( "˜", 7, "˜" ) + else TRY_LONGCHAR( "–", 7, "–" ) + else TRY_LONGCHAR( "—", 7, "—" ) + else TRY_LONGCHAR( "‘", 7, "‘" ) + else TRY_LONGCHAR( "’", 7, "’" ) + else TRY_LONGCHAR( "‚", 7, "‚" ) + else TRY_LONGCHAR( "“", 7, "“" ) + else TRY_LONGCHAR( "”", 7, "”" ) + else TRY_LONGCHAR( "„", 7, "„" ) + else TRY_LONGCHAR( "†", 8, "†" ) + else TRY_LONGCHAR( "‡", 8, "‡" ) + else TRY_LONGCHAR( "…", 8, "…" ) + else TRY_LONGCHAR( "‰", 8, "‰" ) + else TRY_LONGCHAR( "‹", 8, "‹" ) + else TRY_LONGCHAR( "›", 8, "›" ) + else TRY_LONGCHAR( "€", 6, "€" ) + else + { + *p_pos = *psz_value; + psz_value++; + } } else { @@ -490,25 +635,41 @@ char *str_format_time( const char *tformat ) } #define INSERT_STRING( check, string ) \ - if( check && string ) \ + if( check ) \ { \ - int len = strlen( string ); \ - dst = realloc( dst, \ - i_size = i_size + len + 1 ); \ - strncpy( d, string, len+1 ); \ - d += len; \ - } \ - else \ - { \ - *d = '-'; \ - d++; \ + psz_meta = string; \ + if( psz_meta != NULL ) \ + { \ + int len = strlen( string ); \ + dst = realloc( dst, \ + i_size = i_size + len + 1 ); \ + strncpy( d, psz_meta, len+1 ); \ + d += len; \ + } \ + else \ + { \ + *d = '-'; \ + d++; \ + } \ } + +/* same than INSERT_STRING, except that string won't be freed */ +#define INSERT_STRING_NO_FREE( string ) \ + { \ + int len = strlen( string ); \ + dst = realloc( dst, \ + i_size = i_size + len + 1 ); \ + strncpy( d, string, len+1 ); \ + d += len; \ + free( string ); \ + } char *__str_format_meta( vlc_object_t *p_object, const char *string ) { const char *s = string; char *dst = malloc( 1000 ); char *d = dst; int b_is_format = 0; + int b_empty_if_na = 0; char buf[10]; int i_size = strlen( string ); @@ -520,8 +681,6 @@ char *__str_format_meta( vlc_object_t *p_object, const char *string ) { vlc_object_yield( p_input ); p_item = input_GetItem(p_input); - if( p_item ) - vlc_mutex_lock( &p_item->lock ); } sprintf( dst, string ); @@ -532,72 +691,55 @@ char *__str_format_meta( vlc_object_t *p_object, const char *string ) { switch( *s ) { + char *psz_meta; /* used by INSERT_STRING */ case 'a': - INSERT_STRING( p_item && p_item->p_meta, - p_item->p_meta->psz_artist ); + INSERT_STRING( p_item, input_item_GetArtist(p_item) ); break; case 'b': - INSERT_STRING( p_item && p_item->p_meta, - p_item->p_meta->psz_album ); + INSERT_STRING( p_item, input_item_GetAlbum(p_item) ); break; case 'c': - INSERT_STRING( p_item && p_item->p_meta, - p_item->p_meta->psz_copyright ); + INSERT_STRING( p_item, input_item_GetCopyright(p_item) ); break; case 'd': - INSERT_STRING( p_item && p_item->p_meta, - p_item->p_meta->psz_description ); + INSERT_STRING( p_item, input_item_GetDescription(p_item) ); break; case 'e': - INSERT_STRING( p_item && p_item->p_meta, - p_item->p_meta->psz_encodedby ); + INSERT_STRING( p_item, input_item_GetEncodedBy(p_item) ); break; case 'g': - INSERT_STRING( p_item && p_item->p_meta, - p_item->p_meta->psz_genre ); + INSERT_STRING( p_item, input_item_GetGenre(p_item) ); break; case 'l': - INSERT_STRING( p_item && p_item->p_meta, - p_item->p_meta->psz_language ); + INSERT_STRING( p_item, input_item_GetLanguage(p_item) ); break; case 'n': - INSERT_STRING( p_item && p_item->p_meta, - p_item->p_meta->psz_tracknum ); + INSERT_STRING( p_item, input_item_GetTrackNum(p_item) ); break; case 'p': - INSERT_STRING( p_item && p_item->p_meta, - p_item->p_meta->psz_nowplaying ); + INSERT_STRING( p_item, input_item_GetNowPlaying(p_item) ); break; case 'r': - INSERT_STRING( p_item && p_item->p_meta, - p_item->p_meta->psz_rating ); + INSERT_STRING( p_item, input_item_GetRating(p_item) ); break; case 's': { - char *lang; + char *lang = NULL; if( p_input ) - { - lang = var_GetString( p_input, "sub-language" ); - } - else - { - lang = strdup( "-" ); - } + lang = var_GetNonEmptyString( p_input, "sub-language" ); + if( lang == NULL ) + lang = strdup( b_empty_if_na ? "" : "-" ); INSERT_STRING( 1, lang ); - free( lang ); break; } case 't': - INSERT_STRING( p_item && p_item->p_meta, - p_item->p_meta->psz_title ); + INSERT_STRING( p_item, input_item_GetTitle(p_item) ); break; case 'u': - INSERT_STRING( p_item && p_item->p_meta, - p_item->p_meta->psz_url ); + INSERT_STRING( p_item, input_item_GetURL(p_item) ); break; case 'A': - INSERT_STRING( p_item && p_item->p_meta, - p_item->p_meta->psz_date ); + INSERT_STRING( p_item, input_item_GetDate(p_item) ); break; case 'B': if( p_input ) @@ -607,9 +749,9 @@ char *__str_format_meta( vlc_object_t *p_object, const char *string ) } else { - sprintf( buf, "-" ); + sprintf( buf, b_empty_if_na ? "" : "-" ); } - INSERT_STRING( 1, buf ); + INSERT_STRING_NO_FREE( buf ); break; case 'C': if( p_input ) @@ -619,26 +761,27 @@ char *__str_format_meta( vlc_object_t *p_object, const char *string ) } else { - sprintf( buf, "-" ); + sprintf( buf, b_empty_if_na ? "" : "-" ); } - INSERT_STRING( 1, buf ); + INSERT_STRING_NO_FREE( buf ); break; case 'D': if( p_item ) { + mtime_t i_duration = input_item_GetDuration( p_item ); sprintf( buf, "%02d:%02d:%02d", - (int)(p_item->i_duration/(3600000000)), - (int)((p_item->i_duration/(60000000))%60), - (int)((p_item->i_duration/1000000)%60) ); + (int)(i_duration/(3600000000)), + (int)((i_duration/(60000000))%60), + (int)((i_duration/1000000)%60) ); } else { - sprintf( buf, "--:--:--" ); + sprintf( buf, b_empty_if_na ? "" : "--:--:--" ); } - INSERT_STRING( 1, buf ); + INSERT_STRING_NO_FREE( buf ); break; case 'F': - INSERT_STRING( p_item, p_item->psz_uri ); + INSERT_STRING( p_item, input_item_GetURI( p_item ) ); break; case 'I': if( p_input ) @@ -648,40 +791,38 @@ char *__str_format_meta( vlc_object_t *p_object, const char *string ) } else { - sprintf( buf, "-" ); + sprintf( buf, b_empty_if_na ? "" : "-" ); } - INSERT_STRING( 1, buf ); + INSERT_STRING_NO_FREE( buf ); break; case 'L': if( p_item && p_input ) { + mtime_t i_duration = input_item_GetDuration( p_item ); + int64_t i_time = p_input->i_time; sprintf( buf, "%02d:%02d:%02d", - (int)((p_item->i_duration-p_input->i_time)/(3600000000)), - (int)(((p_item->i_duration-p_input->i_time)/(60000000))%60), - (int)(((p_item->i_duration-p_input->i_time)/1000000)%60) ); + (int)( ( i_duration - i_time ) / 3600000000 ), + (int)( ( ( i_duration - i_time ) / 60000000 ) % 60 ), + (int)( ( ( i_duration - i_time ) / 1000000 ) % 60 ) ); } else { - sprintf( buf, "--:--:--" ); + sprintf( buf, b_empty_if_na ? "" : "--:--:--" ); } - INSERT_STRING( 1, buf ); + INSERT_STRING_NO_FREE( buf ); break; case 'N': - INSERT_STRING( p_item, p_item->psz_name ); + INSERT_STRING( p_item, input_item_GetName( p_item ) ); break; case 'O': { - char *lang; + char *lang = NULL; if( p_input ) - { - lang = var_GetString( p_input, "audio-language" ); - } - else - { - lang = strdup( "-" ); - } + lang = var_GetNonEmptyString( p_input, + "audio-language" ); + if( lang == NULL ) + lang = strdup( b_empty_if_na ? "" : "-" ); INSERT_STRING( 1, lang ); - free( lang ); break; } case 'P': @@ -692,9 +833,9 @@ char *__str_format_meta( vlc_object_t *p_object, const char *string ) } else { - sprintf( buf, "--.-%%" ); + sprintf( buf, b_empty_if_na ? "" : "--.-%%" ); } - INSERT_STRING( 1, buf ); + INSERT_STRING_NO_FREE( buf ); break; case 'R': if( p_input ) @@ -704,9 +845,9 @@ char *__str_format_meta( vlc_object_t *p_object, const char *string ) } else { - sprintf( buf, "-" ); + sprintf( buf, b_empty_if_na ? "" : "-" ); } - INSERT_STRING( 1, buf ); + INSERT_STRING_NO_FREE( buf ); break; case 'S': if( p_input ) @@ -716,34 +857,33 @@ char *__str_format_meta( vlc_object_t *p_object, const char *string ) } else { - sprintf( buf, "-" ); + sprintf( buf, b_empty_if_na ? "" : "-" ); } - INSERT_STRING( 1, buf ); + INSERT_STRING_NO_FREE( buf ); break; case 'T': if( p_input ) { sprintf( buf, "%02d:%02d:%02d", - (int)(p_input->i_time/(3600000000)), - (int)((p_input->i_time/(60000000))%60), - (int)((p_input->i_time/1000000)%60) ); + (int)( p_input->i_time / ( 3600000000 ) ), + (int)( ( p_input->i_time / ( 60000000 ) ) % 60 ), + (int)( ( p_input->i_time / 1000000 ) % 60 ) ); } else { - sprintf( buf, "--:--:--" ); + sprintf( buf, b_empty_if_na ? "" : "--:--:--" ); } - INSERT_STRING( 1, buf ); + INSERT_STRING_NO_FREE( buf ); break; case 'U': - INSERT_STRING( p_item && p_item->p_meta, - p_item->p_meta->psz_publisher ); + INSERT_STRING( p_item, input_item_GetPublisher(p_item) ); break; case 'V': { audio_volume_t volume; aout_VolumeGet( p_object, &volume ); snprintf( buf, 10, "%d", volume ); - INSERT_STRING( 1, buf ); + INSERT_STRING_NO_FREE( buf ); break; } case '_': @@ -751,16 +891,22 @@ char *__str_format_meta( vlc_object_t *p_object, const char *string ) d++; break; + case ' ': + b_empty_if_na = 1; + break; + default: *d = *s; d++; break; } - b_is_format = 0; + if( *s != ' ' ) + b_is_format = 0; } else if( *s == '$' ) { b_is_format = 1; + b_empty_if_na = 0; } else { @@ -772,11 +918,7 @@ char *__str_format_meta( vlc_object_t *p_object, const char *string ) *d = '\0'; if( p_input ) - { vlc_object_release( p_input ); - if( p_item ) - vlc_mutex_unlock( &p_item->lock ); - } return dst; } @@ -798,22 +940,30 @@ char *__str_format( vlc_object_t *p_this, const char *psz_src ) */ void filename_sanitize( char *str ) { + if( *str == '.' && (str[1] == '\0' || (str[1] == '.' && str[2] == '\0' ) ) ) + { + while( *str ) + { + *str = '_'; + str++; + } + return; + } + while( *str ) { switch( *str ) { case '/': #ifdef WIN32 + case '\\': case '*': - case '.': case '"': - case '\\': - case '[': - case ']': + case '?': case ':': - case ';': case '|': - case '=': + case '<': + case '>': #endif *str = '_'; } @@ -826,23 +976,52 @@ void filename_sanitize( char *str ) */ void path_sanitize( char *str ) { +#if 0 + /* + * Uncomment the two blocks to prevent /../ or /./, i'm not sure that we + * want to. + */ + char *prev = str - 1; +#endif +#ifdef WIN32 + /* check drive prefix if path is absolute */ + if( isalpha(*str) && (':' == *(str+1)) ) + str += 2; +#endif while( *str ) { +#ifdef WIN32 switch( *str ) { -#ifdef WIN32 case '*': - case '.': case '"': - case '[': - case ']': + case '?': case ':': - case ';': case '|': - case '=': -#endif + case '<': + case '>': *str = '_'; } +#endif +#if 0 + if( *str == '/' +#ifdef WIN32 + || *str == '\\' +#endif + ) + { + if( str - prev == 2 && prev[1] == '.' ) + { + prev[1] = '.'; + } + else if( str - prev == 3 && prev[1] == '.' && prev[2] == '.' ) + { + prev[1] = '_'; + prev[2] = '_'; + } + prev = str; + } +#endif str++; } }