1 /*****************************************************************************
2 * strings.c: String related functions
3 *****************************************************************************
4 * Copyright (C) 2006 the VideoLAN team
7 * Authors: Antoine Cellerier <dionoea at videolan dot org>
8 * Daniel Stranger <vlc at schmaller dot de>
9 * RĂ©mi Denis-Courmont <rem # videolan org>
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
24 *****************************************************************************/
26 /*****************************************************************************
28 *****************************************************************************/
35 /* Needed by str_format_time */
38 /* Needed by str_format_meta */
39 #include <vlc_input.h>
41 #include <vlc_playlist.h>
44 #include <vlc_strings.h>
46 #include <vlc_charset.h>
49 * Unescape URI encoded string
50 * \return decoded duplicated string
52 char *unescape_URI_duplicate( const char *psz )
54 char *psz_dup = strdup( psz );
55 unescape_URI( psz_dup );
60 * Unescape URI encoded string in place
63 void unescape_URI( char *psz )
65 unsigned char *in = (unsigned char *)psz, *out = in, c;
67 while( ( c = *in++ ) != '\0' )
73 char val[5], *pval = val;
83 if( ( *pval++ = *in++ ) == '\0' )
85 if( ( *pval++ = *in++ ) == '\0' )
91 if( ( *pval++ = *in++ ) == '\0' )
96 cp = strtoul( val, NULL, 0x10 );
102 *out++ = (( cp >> 6) | 0xc0);
103 *out++ = (( cp & 0x3f) | 0x80);
107 assert( cp < 0x10000 );
108 *out++ = (( cp >> 12) | 0xe0);
109 *out++ = (((cp >> 6) & 0x3f) | 0x80);
110 *out++ = (( cp & 0x3f) | 0x80);
115 /* + is not a special case - it means plus, not space. */
118 /* Inserting non-ASCII or non-printable characters is unsafe,
119 * and no sane browser will send these unencoded */
120 if( ( c < 32 ) || ( c > 127 ) )
130 * Decode encoded URI string
131 * \return decoded duplicated string
133 char *decode_URI_duplicate( const char *psz )
135 char *psz_dup = strdup( psz );
136 decode_URI( psz_dup );
141 * Decode encoded URI string in place
144 void decode_URI( char *psz )
146 unsigned char *in = (unsigned char *)psz, *out = in, c;
148 while( ( c = *in++ ) != '\0' )
156 if( ( ( hex[0] = *in++ ) == 0 )
157 || ( ( hex[1] = *in++ ) == 0 ) )
161 *out++ = (unsigned char)strtoul( hex, NULL, 0x10 );
170 /* Inserting non-ASCII or non-printable characters is unsafe,
171 * and no sane browser will send these unencoded */
172 if( ( c < 32 ) || ( c > 127 ) )
182 static inline int isurlsafe( int c )
184 return ( (unsigned char)( c - 'a' ) < 26 )
185 || ( (unsigned char)( c - 'A' ) < 26 )
186 || ( (unsigned char)( c - '0' ) < 10 )
187 /* Hmm, we should not encode character that are allowed in URLs
188 * (even if they are not URL-safe), nor URL-safe characters.
189 * We still encode some of them because of Microsoft's crap browser.
191 || ( strchr( "-_.", c ) != NULL );
194 static inline char url_hexchar( int c )
196 return ( c < 10 ) ? c + '0' : c + 'A' - 10;
200 * encode_URI_component
201 * Encodes an URI component.
203 * @param psz_url nul-terminated UTF-8 representation of the component.
204 * Obviously, you can't pass an URI containing a nul character, but you don't
205 * want to do that, do you?
207 * @return encoded string (must be free()'d)
209 char *encode_URI_component( const char *psz_url )
211 char psz_enc[3 * strlen( psz_url ) + 1], *out = psz_enc;
214 for( in = (const uint8_t *)psz_url; *in; in++ )
226 *out++ = url_hexchar( c >> 4 );
227 *out++ = url_hexchar( c & 0xf );
232 return strdup( psz_enc );
236 * Converts "<", ">" and "&" to "<", ">" and "&"
237 * \param string to convert
239 void resolve_xml_special_chars( char *psz_value )
241 char *p_pos = psz_value;
245 if( !strncmp( psz_value, "<", 4 ) )
250 else if( !strncmp( psz_value, ">", 4 ) )
255 else if( !strncmp( psz_value, "&", 5 ) )
260 else if( !strncmp( psz_value, """, 6 ) )
265 else if( !strncmp( psz_value, "'", 6 ) )
283 * Converts '<', '>', '\"', '\'' and '&' to their html entities
284 * \param psz_content simple element content that is to be converted
286 char *convert_xml_special_chars( const char *psz_content )
288 char *psz_temp = malloc( 6 * strlen( psz_content ) + 1 );
289 const char *p_from = psz_content;
290 char *p_to = psz_temp;
294 if ( *p_from == '<' )
296 strcpy( p_to, "<" );
299 else if ( *p_from == '>' )
301 strcpy( p_to, ">" );
304 else if ( *p_from == '&' )
306 strcpy( p_to, "&" );
309 else if( *p_from == '\"' )
311 strcpy( p_to, """ );
314 else if( *p_from == '\'' )
316 strcpy( p_to, "'" );
331 /* Base64 encoding */
332 char *vlc_b64_encode( const char *src )
334 static const char b64[] =
335 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
336 size_t len = strlen( src );
337 const uint8_t *in = (const uint8_t *)src;
340 char *dst = (char *)malloc( ( len + 4 ) * 4 / 3 );
348 /* pops (up to) 3 bytes of input, push 4 bytes */
349 uint32_t v = *in++ << 24; // 1/3
350 *dst++ = b64[v >> 26]; // 1/4
354 v |= *in++ << 22; // 2/3
355 *dst++ = b64[v >> 26]; // 2/4
359 v |= *in++ << 20; // 3/3
360 *dst++ = ( len >= 2 ) ? b64[v >> 26] : '='; // 3/4
363 *dst++ = ( len >= 3 ) ? b64[v >> 26] : '='; // 4/4
379 /****************************************************************************
380 * String formating functions
381 ****************************************************************************/
382 char *str_format_time( const char *tformat )
386 #if defined(HAVE_LOCALTIME_R)
392 /* Get the current time. */
393 curtime = time( NULL );
395 /* Convert it to local time representation. */
396 #if defined(HAVE_LOCALTIME_R)
397 localtime_r( &curtime, &loctime );
398 strftime( buffer, 255, tformat, &loctime );
400 loctime = localtime( &curtime );
401 strftime( buffer, 255, tformat, loctime );
403 return strdup( buffer );
406 #define INSERT_STRING( check, string ) \
407 if( check && string ) \
409 int len = strlen( string ); \
410 dst = realloc( dst, \
411 i_size = i_size + len + 1 ); \
412 strncpy( d, string, len+1 ); \
420 char *__str_format_meta( vlc_object_t *p_object, const char *string )
422 const char *s = string;
423 char *dst = malloc( 1000 );
427 int i_size = strlen( string );
429 playlist_t *p_playlist = pl_Yield( p_object );
430 input_thread_t *p_input = p_playlist->p_input;
431 input_item_t *p_item = NULL;
432 pl_Release( p_object );
435 vlc_object_yield( p_input );
436 p_item = input_GetItem(p_input);
438 vlc_mutex_lock( &p_item->lock );
441 sprintf( dst, string );
450 INSERT_STRING( p_item && p_item->p_meta,
451 p_item->p_meta->psz_artist );
454 INSERT_STRING( p_item && p_item->p_meta,
455 p_item->p_meta->psz_album );
458 INSERT_STRING( p_item && p_item->p_meta,
459 p_item->p_meta->psz_copyright );
462 INSERT_STRING( p_item && p_item->p_meta,
463 p_item->p_meta->psz_description );
466 INSERT_STRING( p_item && p_item->p_meta,
467 p_item->p_meta->psz_encodedby );
470 INSERT_STRING( p_item && p_item->p_meta,
471 p_item->p_meta->psz_genre );
474 INSERT_STRING( p_item && p_item->p_meta,
475 p_item->p_meta->psz_language );
478 INSERT_STRING( p_item && p_item->p_meta,
479 p_item->p_meta->psz_tracknum );
482 INSERT_STRING( p_item && p_item->p_meta,
483 p_item->p_meta->psz_nowplaying );
486 INSERT_STRING( p_item && p_item->p_meta,
487 p_item->p_meta->psz_rating );
494 lang = var_GetString( p_input, "sub-language" );
498 lang = strdup( "-" );
500 INSERT_STRING( 1, lang );
505 INSERT_STRING( p_item && p_item->p_meta,
506 p_item->p_meta->psz_title );
509 INSERT_STRING( p_item && p_item->p_meta,
510 p_item->p_meta->psz_url );
513 INSERT_STRING( p_item && p_item->p_meta,
514 p_item->p_meta->psz_date );
519 snprintf( buf, 10, "%d",
520 var_GetInteger( p_input, "bit-rate" )/1000 );
526 INSERT_STRING( 1, buf );
531 snprintf( buf, 10, "%d",
532 var_GetInteger( p_input, "chapter" ) );
538 INSERT_STRING( 1, buf );
543 sprintf( buf, "%02d:%02d:%02d",
544 (int)(p_item->i_duration/(3600000000)),
545 (int)((p_item->i_duration/(60000000))%60),
546 (int)((p_item->i_duration/1000000)%60) );
550 sprintf( buf, "--:--:--" );
552 INSERT_STRING( 1, buf );
555 INSERT_STRING( p_item, p_item->psz_uri );
560 snprintf( buf, 10, "%d",
561 var_GetInteger( p_input, "title" ) );
567 INSERT_STRING( 1, buf );
570 if( p_item && p_input )
572 sprintf( buf, "%02d:%02d:%02d",
573 (int)((p_item->i_duration-p_input->i_time)/(3600000000)),
574 (int)(((p_item->i_duration-p_input->i_time)/(60000000))%60),
575 (int)(((p_item->i_duration-p_input->i_time)/1000000)%60) );
579 sprintf( buf, "--:--:--" );
581 INSERT_STRING( 1, buf );
584 INSERT_STRING( p_item, p_item->psz_name );
591 lang = var_GetString( p_input, "audio-language" );
595 lang = strdup( "-" );
597 INSERT_STRING( 1, lang );
604 snprintf( buf, 10, "%2.1lf",
605 var_GetFloat( p_input, "position" ) * 100. );
609 sprintf( buf, "--.-%%" );
611 INSERT_STRING( 1, buf );
616 int r = var_GetInteger( p_input, "rate" );
617 snprintf( buf, 10, "%d.%d", r/1000, r%1000 );
623 INSERT_STRING( 1, buf );
628 int r = var_GetInteger( p_input, "sample-rate" );
629 snprintf( buf, 10, "%d.%d", r/1000, (r/100)%10 );
635 INSERT_STRING( 1, buf );
640 sprintf( buf, "%02d:%02d:%02d",
641 (int)(p_input->i_time/(3600000000)),
642 (int)((p_input->i_time/(60000000))%60),
643 (int)((p_input->i_time/1000000)%60) );
647 sprintf( buf, "--:--:--" );
649 INSERT_STRING( 1, buf );
652 INSERT_STRING( p_item && p_item->p_meta,
653 p_item->p_meta->psz_publisher );
657 audio_volume_t volume;
658 aout_VolumeGet( p_object, &volume );
659 snprintf( buf, 10, "%d", volume );
660 INSERT_STRING( 1, buf );
690 vlc_object_release( p_input );
692 vlc_mutex_unlock( &p_item->lock );
699 * Apply str format time and str format meta
701 char *__str_format( vlc_object_t *p_this, const char *psz_src )
703 char *psz_buf1, *psz_buf2;
704 psz_buf1 = str_format_time( psz_src );
705 psz_buf2 = str_format_meta( p_this, psz_buf1 );
711 * Remove forbidden characters from filenames (including slashes)
713 void filename_sanitize( char *str )
739 * Remove forbidden characters from full paths (leaves slashes)
741 void path_sanitize( char *str )