mirror of
				https://github.com/pbatard/rufus.git
				synced 2024-08-14 23:57:05 +00:00 
			
		
		
		
	[iso] fix UDF UNICODE support
* libcdio's unicode16_decode() was not decoding labels at all, but simply stripping the MSB of the UDF USC-16 sequences * use an actual conversion to UTF-8 * also update the rest of udf_fs.c to latest libcdio version * closes #285
This commit is contained in:
		
							parent
							
								
									167a877e9f
								
							
						
					
					
						commit
						60b68258dc
					
				
					 3 changed files with 180 additions and 146 deletions
				
			
		|  | @ -113,7 +113,6 @@ FILE* fopen_utf8(const char* filename, const char* mode) | |||
| } | ||||
| #endif | ||||
| 
 | ||||
| #ifdef HAVE_JOLIET | ||||
| #ifdef HAVE_ICONV | ||||
| #include <iconv.h> | ||||
| struct cdio_charset_coverter_s | ||||
|  | @ -344,5 +343,3 @@ bool cdio_charset_to_utf8(const char *src, size_t src_len, cdio_utf8_t **dst, | |||
|   return (*dst != NULL); | ||||
| } | ||||
| #endif /* HAVE_ICONV */ | ||||
| 
 | ||||
| #endif /* HAVE_JOLIET */ | ||||
|  |  | |||
|  | @ -1,5 +1,5 @@ | |||
| /*
 | ||||
|   Copyright (C) 2005, 2006, 2008, 2011 Rocky Bernstein <rocky@gnu.org> | ||||
|   Copyright (C) 2005-2006, 2008, 2011, 2013 Rocky Bernstein <rocky@gnu.org> | ||||
| 
 | ||||
|   This program is free software: you can redistribute it and/or modify | ||||
|   it under the terms of the GNU General Public License as published by | ||||
|  | @ -70,6 +70,9 @@ const char VSD_STD_ID_NSR03[] = {'N', 'S', 'R', '0', '3'}; | |||
| const char VSD_STD_ID_TEA01[] = {'T', 'E', 'A', '0', '1'}; | ||||
| 
 | ||||
| #include <cdio/bytesex.h> | ||||
| #include <cdio/utf8.h> | ||||
| #include <cdio/util.h> | ||||
| 
 | ||||
| #include "udf_private.h" | ||||
| #include "udf_fs.h" | ||||
| #include "cdio_assert.h" | ||||
|  | @ -134,6 +137,10 @@ udf_checktag(const udf_tag_t *p_tag, udf_Uint16_t tag_id) | |||
| 
 | ||||
|   itag = (uint8_t *)p_tag; | ||||
| 
 | ||||
| #ifdef WORDS_BIGENDIAN | ||||
|   tag_id = UINT16_SWAP_LE_BE(tag_id); | ||||
| #endif | ||||
| 
 | ||||
|   if (p_tag->id != tag_id) | ||||
|     return -1; | ||||
| 
 | ||||
|  | @ -270,23 +277,31 @@ udf_fopen(udf_dirent_t *p_udf_root, const char *psz_name) | |||
|   return p_udf_file; | ||||
| } | ||||
| 
 | ||||
| /* Convert unicode16 to 8-bit char by dripping MSB. 
 | ||||
|    Wonder if iconv can be used here | ||||
| /* Convert unicode16 to UTF-8.
 | ||||
|    The returned string is allocated and must be freed by the caller | ||||
| */ | ||||
| static int  | ||||
| unicode16_decode( const uint8_t *data, int i_len, char *target )  | ||||
| static char* | ||||
| unicode16_decode(const uint8_t *data, int i_len) | ||||
| { | ||||
|   int p = 1, i = 0; | ||||
|   int i; | ||||
|   char* r = NULL; | ||||
| 
 | ||||
|   if( ( data[ 0 ] == 8 ) || ( data[ 0 ] == 16 ) ) do { | ||||
|     if( data[ 0 ] == 16 ) p++;  /* Ignore MSB of unicode16 */ | ||||
|     if( p < i_len ) { | ||||
|       target[ i++ ] = data[ p++ ]; | ||||
|     } | ||||
|   } while( p < i_len ); | ||||
|    | ||||
|   target[ i ] = '\0'; | ||||
|   return 0; | ||||
|   switch (data[0]) | ||||
|   { | ||||
|   case 8: | ||||
|     r = (char*)malloc(i_len); | ||||
|     if (r == NULL) | ||||
|       return r; | ||||
|     for (i=0; i<i_len-1; i++) | ||||
|       r[i] = data[i+1]; | ||||
|     r[i] = 0; | ||||
|     return r; | ||||
|   case 16: | ||||
|     cdio_charset_to_utf8((char*)&data[1], i_len-1, &r, "UCS-2BE"); | ||||
|     return r; | ||||
|   default: | ||||
|     return NULL; | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
|  | @ -389,7 +404,8 @@ udf_open (const char *psz_path) | |||
|    * Then try to find a reference to a Primary Volume Descriptor. | ||||
|    */ | ||||
|   { | ||||
|     const anchor_vol_desc_ptr_t *p_avdp = &p_udf->anchor_vol_desc_ptr; | ||||
|     anchor_vol_desc_ptr_t *p_avdp = &p_udf->anchor_vol_desc_ptr; | ||||
| 
 | ||||
|     const uint32_t mvds_start = | ||||
|       uint32_from_le(p_avdp->main_vol_desc_seq_ext.loc); | ||||
|     const uint32_t mvds_end   = mvds_start + | ||||
|  | @ -398,7 +414,6 @@ udf_open (const char *psz_path) | |||
|     uint32_t i_lba; | ||||
| 
 | ||||
|     for (i_lba = mvds_start; i_lba < mvds_end; i_lba++) { | ||||
| 
 | ||||
|       udf_pvd_t *p_pvd = (udf_pvd_t *) &data; | ||||
| 
 | ||||
|       if (DRIVER_OP_SUCCESS != udf_read_sectors (p_udf, p_pvd, i_lba, 1) ) | ||||
|  | @ -427,18 +442,24 @@ udf_open (const char *psz_path) | |||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  * Gets the Volume Identifier string, in 8bit unicode (latin-1) | ||||
|  * Gets the Volume Identifier, as an UTF-8 string | ||||
|  * psz_volid, place to put the string | ||||
|  * i_volid, size of the buffer psz_volid points to | ||||
|  * returns the size of buffer needed for all data | ||||
|  * Note: this call accepts a NULL psz_volid, to retrieve the length required. | ||||
|  */ | ||||
| int  | ||||
| udf_get_volume_id(udf_t *p_udf, /*out*/ char *psz_volid,  unsigned int i_volid) | ||||
| udf_get_volume_id(udf_t *p_udf, /*out*/ char *psz_volid, unsigned int i_volid) | ||||
| { | ||||
|   uint8_t data[UDF_BLOCKSIZE]; | ||||
|   const udf_pvd_t *p_pvd = (udf_pvd_t *) &data; | ||||
|   char* r; | ||||
|   unsigned int volid_len; | ||||
| 
 | ||||
|   /* clear the output to empty string */ | ||||
|   if (psz_volid != NULL) | ||||
|     psz_volid[0] = 0; | ||||
| 
 | ||||
|   /* get primary volume descriptor */ | ||||
|   if ( DRIVER_OP_SUCCESS != udf_read_sectors(p_udf, &data, p_udf->pvd_lba, 1) ) | ||||
|     return 0; | ||||
|  | @ -448,10 +469,17 @@ udf_get_volume_id(udf_t *p_udf, /*out*/ char *psz_volid,  unsigned int i_volid) | |||
|     /* this field is only UDF_VOLID_SIZE bytes something is wrong */ | ||||
|     volid_len = UDF_VOLID_SIZE-1; | ||||
|   } | ||||
|   if(i_volid > volid_len) { | ||||
|     i_volid = volid_len; | ||||
| 
 | ||||
|   r = unicode16_decode((uint8_t *) p_pvd->vol_ident, volid_len); | ||||
|   if (r == NULL) | ||||
|     return 0; | ||||
| 
 | ||||
|   volid_len = strlen(r)+1;	/* +1 for NUL terminator */ | ||||
|   if (psz_volid != NULL) { | ||||
|     strncpy(psz_volid, r, MIN(volid_len, i_volid)); | ||||
|     psz_volid[i_volid-1] = 0;	/* strncpy does not always terminate the dest */ | ||||
|   } | ||||
|   unicode16_decode((uint8_t *) p_pvd->vol_ident, i_volid, psz_volid); | ||||
|   free(r); | ||||
| 
 | ||||
|   return volid_len; | ||||
| } | ||||
|  | @ -486,27 +514,39 @@ udf_get_volumeset_id(udf_t *p_udf, /*out*/ uint8_t *volsetid, | |||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  * Gets the Logical Volume Identifier string, in 8bit unicode (latin-1) | ||||
|  * Gets the Logical Volume Identifier string, as an UTF-8 string | ||||
|  * psz_logvolid, place to put the string (should be at least 64 bytes) | ||||
|  * i_logvolid, size of the buffer psz_logvolid points to | ||||
|  * returns the size of buffer needed for all data | ||||
|  * returns the size of buffer needed for all data, including NUL terminator | ||||
|  * A call to udf_get_root() should have been issued before this call | ||||
|  * Note: this call accepts a NULL psz_volid, to retrieve the length required. | ||||
|  */ | ||||
| int | ||||
| udf_get_logical_volume_id(udf_t *p_udf, /*out*/ char *psz_logvolid,  unsigned int i_logvolid) | ||||
| udf_get_logical_volume_id(udf_t *p_udf, /*out*/ char *psz_logvolid, unsigned int i_logvolid) | ||||
| { | ||||
|   uint8_t data[UDF_BLOCKSIZE]; | ||||
|   logical_vol_desc_t *p_logvol = (logical_vol_desc_t *) &data; | ||||
|   char* r; | ||||
|   int logvolid_len; | ||||
| 
 | ||||
|   /* clear the output to empty string */ | ||||
|   if (psz_logvolid != NULL) | ||||
|     psz_logvolid[0] = 0; | ||||
| 
 | ||||
|   if (DRIVER_OP_SUCCESS != udf_read_sectors (p_udf, p_logvol, p_udf->lvd_lba, 1) )  | ||||
|     return 0; | ||||
| 
 | ||||
|   logvolid_len = (p_logvol->logvol_id[127]+1)/2; | ||||
|   if (i_logvolid > logvolid_len) | ||||
|     i_logvolid = logvolid_len; | ||||
|   r = unicode16_decode((uint8_t *) p_logvol->logvol_id, p_logvol->logvol_id[127]); | ||||
|   if (r == NULL) | ||||
|     return 0; | ||||
| 
 | ||||
|   logvolid_len = strlen(r)+1;	/* +1 for NUL terminator */ | ||||
|   if (psz_logvolid != NULL) { | ||||
|     strncpy(psz_logvolid, r, MIN(logvolid_len, i_logvolid)); | ||||
|     psz_logvolid[i_logvolid-1] = 0;	/* strncpy does not always terminate the dest */ | ||||
|   } | ||||
|   free(r); | ||||
| 
 | ||||
|   unicode16_decode((uint8_t *) p_logvol->logvol_id, 2*i_logvolid, psz_logvolid); | ||||
|   return logvolid_len; | ||||
| } | ||||
| 
 | ||||
|  | @ -647,6 +687,7 @@ udf_dirent_t * | |||
| udf_readdir(udf_dirent_t *p_udf_dirent) | ||||
| { | ||||
|   udf_t *p_udf; | ||||
|   uint8_t* p; | ||||
| 
 | ||||
|   if (p_udf_dirent->dir_left <= 0) { | ||||
|     udf_dirent_free(p_udf_dirent); | ||||
|  | @ -706,13 +747,9 @@ udf_readdir(udf_dirent_t *p_udf_dirent) | |||
| 		return NULL; | ||||
| 	} | ||||
| 
 | ||||
| 	if (strlen(p_udf_dirent->psz_name) < i_len)  | ||||
| 	  p_udf_dirent->psz_name = (char *) | ||||
| 	    realloc(p_udf_dirent->psz_name, sizeof(char)*i_len+1); | ||||
| 	 | ||||
| 	unicode16_decode(p_udf_dirent->fid->u.imp_use.data  | ||||
| 			 + p_udf_dirent->fid->u.i_imp_use,  | ||||
| 			 i_len, p_udf_dirent->psz_name); | ||||
| 	free_and_null(p_udf_dirent->psz_name); | ||||
| 	p = (uint8_t*)p_udf_dirent->fid->u.imp_use.data + p_udf_dirent->fid->u.i_imp_use; | ||||
| 	p_udf_dirent->psz_name = unicode16_decode(p, i_len); | ||||
|       } | ||||
|       return p_udf_dirent; | ||||
|     } | ||||
|  |  | |||
							
								
								
									
										12
									
								
								src/rufus.rc
									
										
									
									
									
								
							
							
						
						
									
										12
									
								
								src/rufus.rc
									
										
									
									
									
								
							|  | @ -32,7 +32,7 @@ LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL | |||
| 
 | ||||
| IDD_DIALOG DIALOGEX 12, 12, 206, 329 | ||||
| STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU | ||||
| CAPTION "Rufus 1.4.4.412" | ||||
| CAPTION "Rufus 1.4.4.413" | ||||
| FONT 8, "MS Shell Dlg", 400, 0, 0x1 | ||||
| BEGIN | ||||
|     DEFPUSHBUTTON   "Start",IDC_START,94,291,50,14 | ||||
|  | @ -165,7 +165,7 @@ END | |||
| RTL_IDD_DIALOG DIALOGEX 12, 12, 206, 329 | ||||
| STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU | ||||
| EXSTYLE WS_EX_RTLREADING | WS_EX_APPWINDOW | WS_EX_LAYOUTRTL | ||||
| CAPTION "Rufus 1.4.4.412" | ||||
| CAPTION "Rufus 1.4.4.413" | ||||
| FONT 8, "MS Shell Dlg", 400, 0, 0x1 | ||||
| BEGIN | ||||
|     DEFPUSHBUTTON   "Start",IDC_START,94,291,50,14 | ||||
|  | @ -427,8 +427,8 @@ END | |||
| // | ||||
| 
 | ||||
| VS_VERSION_INFO VERSIONINFO | ||||
|  FILEVERSION 1,4,4,412 | ||||
|  PRODUCTVERSION 1,4,4,412 | ||||
|  FILEVERSION 1,4,4,413 | ||||
|  PRODUCTVERSION 1,4,4,413 | ||||
|  FILEFLAGSMASK 0x3fL | ||||
| #ifdef _DEBUG | ||||
|  FILEFLAGS 0x1L | ||||
|  | @ -445,13 +445,13 @@ BEGIN | |||
|         BEGIN | ||||
|             VALUE "CompanyName", "Akeo Consulting (http://akeo.ie)" | ||||
|             VALUE "FileDescription", "Rufus" | ||||
|             VALUE "FileVersion", "1.4.4.412" | ||||
|             VALUE "FileVersion", "1.4.4.413" | ||||
|             VALUE "InternalName", "Rufus" | ||||
|             VALUE "LegalCopyright", "© 2011-2014 Pete Batard (GPL v3)" | ||||
|             VALUE "LegalTrademarks", "http://www.gnu.org/copyleft/gpl.html" | ||||
|             VALUE "OriginalFilename", "rufus.exe" | ||||
|             VALUE "ProductName", "Rufus" | ||||
|             VALUE "ProductVersion", "1.4.4.412" | ||||
|             VALUE "ProductVersion", "1.4.4.413" | ||||
|         END | ||||
|     END | ||||
|     BLOCK "VarFileInfo" | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue