Home | History | Annotate | Line # | Download | only in udf
udf_osta.c revision 1.3.4.2
      1  1.3.4.2  rpaulo /* $NetBSD: udf_osta.c,v 1.3.4.2 2006/09/09 02:57:06 rpaulo Exp $ */
      2  1.3.4.2  rpaulo 
      3  1.3.4.2  rpaulo /*
      4  1.3.4.2  rpaulo  * Various routines from the OSTA 2.01 specs.  Copyrights are included with
      5  1.3.4.2  rpaulo  * each code segment.  Slight whitespace modifications have been made for
      6  1.3.4.2  rpaulo  * formatting purposes.  Typos/bugs have been fixed.
      7  1.3.4.2  rpaulo  *
      8  1.3.4.2  rpaulo  */
      9  1.3.4.2  rpaulo 
     10  1.3.4.2  rpaulo #include "udf_osta.h"
     11  1.3.4.2  rpaulo 
     12  1.3.4.2  rpaulo 
     13  1.3.4.2  rpaulo /*****************************************************************************/
     14  1.3.4.2  rpaulo /***********************************************************************
     15  1.3.4.2  rpaulo  * OSTA compliant Unicode compression, uncompression routines.
     16  1.3.4.2  rpaulo  * Copyright 1995 Micro Design International, Inc.
     17  1.3.4.2  rpaulo  * Written by Jason M. Rinn.
     18  1.3.4.2  rpaulo  * Micro Design International gives permission for the free use of the
     19  1.3.4.2  rpaulo  * following source code.
     20  1.3.4.2  rpaulo  */
     21  1.3.4.2  rpaulo 
     22  1.3.4.2  rpaulo /***********************************************************************
     23  1.3.4.2  rpaulo  * Takes an OSTA CS0 compressed unicode name, and converts
     24  1.3.4.2  rpaulo  * it to Unicode.
     25  1.3.4.2  rpaulo  * The Unicode output will be in the byte order
     26  1.3.4.2  rpaulo  * that the local compiler uses for 16-bit values.
     27  1.3.4.2  rpaulo  * NOTE: This routine only performs error checking on the compID.
     28  1.3.4.2  rpaulo  * It is up to the user to ensure that the unicode buffer is large
     29  1.3.4.2  rpaulo  * enough, and that the compressed unicode name is correct.
     30  1.3.4.2  rpaulo  *
     31  1.3.4.2  rpaulo  * RETURN VALUE
     32  1.3.4.2  rpaulo  *
     33  1.3.4.2  rpaulo  * The number of unicode characters which were uncompressed.
     34  1.3.4.2  rpaulo  * A -1 is returned if the compression ID is invalid.
     35  1.3.4.2  rpaulo  */
     36  1.3.4.2  rpaulo int
     37  1.3.4.2  rpaulo udf_UncompressUnicode(
     38  1.3.4.2  rpaulo 	int numberOfBytes,	/* (Input) number of bytes read from media. */
     39  1.3.4.2  rpaulo 	byte *UDFCompressed,	/* (Input) bytes read from media. */
     40  1.3.4.2  rpaulo 	unicode_t *unicode)	/* (Output) uncompressed unicode characters. */
     41  1.3.4.2  rpaulo {
     42  1.3.4.2  rpaulo 	unsigned int compID;
     43  1.3.4.2  rpaulo 	int returnValue, unicodeIndex, byteIndex;
     44  1.3.4.2  rpaulo 
     45  1.3.4.2  rpaulo 	/* Use UDFCompressed to store current byte being read. */
     46  1.3.4.2  rpaulo 	compID = UDFCompressed[0];
     47  1.3.4.2  rpaulo 
     48  1.3.4.2  rpaulo 	/* First check for valid compID. */
     49  1.3.4.2  rpaulo 	if (compID != 8 && compID != 16) {
     50  1.3.4.2  rpaulo 		returnValue = -1;
     51  1.3.4.2  rpaulo 	} else {
     52  1.3.4.2  rpaulo 		unicodeIndex = 0;
     53  1.3.4.2  rpaulo 		byteIndex = 1;
     54  1.3.4.2  rpaulo 
     55  1.3.4.2  rpaulo 		/* Loop through all the bytes. */
     56  1.3.4.2  rpaulo 		while (byteIndex < numberOfBytes) {
     57  1.3.4.2  rpaulo 			if (compID == 16) {
     58  1.3.4.2  rpaulo 				/* Move the first byte to the high bits of the
     59  1.3.4.2  rpaulo 				 * unicode char.
     60  1.3.4.2  rpaulo 				 */
     61  1.3.4.2  rpaulo 				unicode[unicodeIndex] =
     62  1.3.4.2  rpaulo 				    UDFCompressed[byteIndex++] << 8;
     63  1.3.4.2  rpaulo 			} else {
     64  1.3.4.2  rpaulo 				unicode[unicodeIndex] = 0;
     65  1.3.4.2  rpaulo 			}
     66  1.3.4.2  rpaulo 			if (byteIndex < numberOfBytes) {
     67  1.3.4.2  rpaulo 				/*Then the next byte to the low bits. */
     68  1.3.4.2  rpaulo 				unicode[unicodeIndex] |=
     69  1.3.4.2  rpaulo 				    UDFCompressed[byteIndex++];
     70  1.3.4.2  rpaulo 			}
     71  1.3.4.2  rpaulo 			unicodeIndex++;
     72  1.3.4.2  rpaulo 		}
     73  1.3.4.2  rpaulo 		returnValue = unicodeIndex;
     74  1.3.4.2  rpaulo 	}
     75  1.3.4.2  rpaulo 	return(returnValue);
     76  1.3.4.2  rpaulo }
     77  1.3.4.2  rpaulo 
     78  1.3.4.2  rpaulo /***********************************************************************
     79  1.3.4.2  rpaulo  * DESCRIPTION:
     80  1.3.4.2  rpaulo  * Takes a string of unicode wide characters and returns an OSTA CS0
     81  1.3.4.2  rpaulo  * compressed unicode string. The unicode MUST be in the byte order of
     82  1.3.4.2  rpaulo  * the compiler in order to obtain correct results. Returns an error
     83  1.3.4.2  rpaulo  * if the compression ID is invalid.
     84  1.3.4.2  rpaulo  *
     85  1.3.4.2  rpaulo  * NOTE: This routine assumes the implementation already knows, by
     86  1.3.4.2  rpaulo  * the local environment, how many bits are appropriate and
     87  1.3.4.2  rpaulo  * therefore does no checking to test if the input characters fit
     88  1.3.4.2  rpaulo  * into that number of bits or not.
     89  1.3.4.2  rpaulo  *
     90  1.3.4.2  rpaulo  * RETURN VALUE
     91  1.3.4.2  rpaulo  *
     92  1.3.4.2  rpaulo  * The total number of bytes in the compressed OSTA CS0 string,
     93  1.3.4.2  rpaulo  * including the compression ID.
     94  1.3.4.2  rpaulo  * A -1 is returned if the compression ID is invalid.
     95  1.3.4.2  rpaulo  */
     96  1.3.4.2  rpaulo int
     97  1.3.4.2  rpaulo udf_CompressUnicode(
     98  1.3.4.2  rpaulo 	int numberOfChars,	/* (Input) number of unicode characters. */
     99  1.3.4.2  rpaulo 	int compID,		/* (Input) compression ID to be used. */
    100  1.3.4.2  rpaulo 	unicode_t *unicode,	/* (Input) unicode characters to compress. */
    101  1.3.4.2  rpaulo 	byte *UDFCompressed)	/* (Output) compressed string, as bytes. */
    102  1.3.4.2  rpaulo {
    103  1.3.4.2  rpaulo 	int byteIndex, unicodeIndex;
    104  1.3.4.2  rpaulo 
    105  1.3.4.2  rpaulo 	if (compID != 8 && compID != 16) {
    106  1.3.4.2  rpaulo 		byteIndex = -1; /* Unsupported compression ID ! */
    107  1.3.4.2  rpaulo 	} else {
    108  1.3.4.2  rpaulo 		/* Place compression code in first byte. */
    109  1.3.4.2  rpaulo 		UDFCompressed[0] = compID;
    110  1.3.4.2  rpaulo 
    111  1.3.4.2  rpaulo 		byteIndex = 1;
    112  1.3.4.2  rpaulo 		unicodeIndex = 0;
    113  1.3.4.2  rpaulo 		while (unicodeIndex < numberOfChars) {
    114  1.3.4.2  rpaulo 			if (compID == 16) {
    115  1.3.4.2  rpaulo 				/* First, place the high bits of the char
    116  1.3.4.2  rpaulo 				 * into the byte stream.
    117  1.3.4.2  rpaulo 				 */
    118  1.3.4.2  rpaulo 				UDFCompressed[byteIndex++] =
    119  1.3.4.2  rpaulo 				    (unicode[unicodeIndex] & 0xFF00) >> 8;
    120  1.3.4.2  rpaulo 			}
    121  1.3.4.2  rpaulo 			/*Then place the low bits into the stream. */
    122  1.3.4.2  rpaulo 			UDFCompressed[byteIndex++] =
    123  1.3.4.2  rpaulo 			    unicode[unicodeIndex] & 0x00FF;
    124  1.3.4.2  rpaulo 			unicodeIndex++;
    125  1.3.4.2  rpaulo 		}
    126  1.3.4.2  rpaulo 	}
    127  1.3.4.2  rpaulo 	return(byteIndex);
    128  1.3.4.2  rpaulo }
    129  1.3.4.2  rpaulo 
    130  1.3.4.2  rpaulo /*****************************************************************************/
    131  1.3.4.2  rpaulo /*
    132  1.3.4.2  rpaulo  * CRC 010041
    133  1.3.4.2  rpaulo  */
    134  1.3.4.2  rpaulo static unsigned short crc_table[256] = {
    135  1.3.4.2  rpaulo 	0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7,
    136  1.3.4.2  rpaulo 	0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF,
    137  1.3.4.2  rpaulo 	0x1231, 0x0210, 0x3273, 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6,
    138  1.3.4.2  rpaulo 	0x9339, 0x8318, 0xB37B, 0xA35A, 0xD3BD, 0xC39C, 0xF3FF, 0xE3DE,
    139  1.3.4.2  rpaulo 	0x2462, 0x3443, 0x0420, 0x1401, 0x64E6, 0x74C7, 0x44A4, 0x5485,
    140  1.3.4.2  rpaulo 	0xA56A, 0xB54B, 0x8528, 0x9509, 0xE5EE, 0xF5CF, 0xC5AC, 0xD58D,
    141  1.3.4.2  rpaulo 	0x3653, 0x2672, 0x1611, 0x0630, 0x76D7, 0x66F6, 0x5695, 0x46B4,
    142  1.3.4.2  rpaulo 	0xB75B, 0xA77A, 0x9719, 0x8738, 0xF7DF, 0xE7FE, 0xD79D, 0xC7BC,
    143  1.3.4.2  rpaulo 	0x48C4, 0x58E5, 0x6886, 0x78A7, 0x0840, 0x1861, 0x2802, 0x3823,
    144  1.3.4.2  rpaulo 	0xC9CC, 0xD9ED, 0xE98E, 0xF9AF, 0x8948, 0x9969, 0xA90A, 0xB92B,
    145  1.3.4.2  rpaulo 	0x5AF5, 0x4AD4, 0x7AB7, 0x6A96, 0x1A71, 0x0A50, 0x3A33, 0x2A12,
    146  1.3.4.2  rpaulo 	0xDBFD, 0xCBDC, 0xFBBF, 0xEB9E, 0x9B79, 0x8B58, 0xBB3B, 0xAB1A,
    147  1.3.4.2  rpaulo 	0x6CA6, 0x7C87, 0x4CE4, 0x5CC5, 0x2C22, 0x3C03, 0x0C60, 0x1C41,
    148  1.3.4.2  rpaulo 	0xEDAE, 0xFD8F, 0xCDEC, 0xDDCD, 0xAD2A, 0xBD0B, 0x8D68, 0x9D49,
    149  1.3.4.2  rpaulo 	0x7E97, 0x6EB6, 0x5ED5, 0x4EF4, 0x3E13, 0x2E32, 0x1E51, 0x0E70,
    150  1.3.4.2  rpaulo 	0xFF9F, 0xEFBE, 0xDFDD, 0xCFFC, 0xBF1B, 0xAF3A, 0x9F59, 0x8F78,
    151  1.3.4.2  rpaulo 	0x9188, 0x81A9, 0xB1CA, 0xA1EB, 0xD10C, 0xC12D, 0xF14E, 0xE16F,
    152  1.3.4.2  rpaulo 	0x1080, 0x00A1, 0x30C2, 0x20E3, 0x5004, 0x4025, 0x7046, 0x6067,
    153  1.3.4.2  rpaulo 	0x83B9, 0x9398, 0xA3FB, 0xB3DA, 0xC33D, 0xD31C, 0xE37F, 0xF35E,
    154  1.3.4.2  rpaulo 	0x02B1, 0x1290, 0x22F3, 0x32D2, 0x4235, 0x5214, 0x6277, 0x7256,
    155  1.3.4.2  rpaulo 	0xB5EA, 0xA5CB, 0x95A8, 0x8589, 0xF56E, 0xE54F, 0xD52C, 0xC50D,
    156  1.3.4.2  rpaulo 	0x34E2, 0x24C3, 0x14A0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
    157  1.3.4.2  rpaulo 	0xA7DB, 0xB7FA, 0x8799, 0x97B8, 0xE75F, 0xF77E, 0xC71D, 0xD73C,
    158  1.3.4.2  rpaulo 	0x26D3, 0x36F2, 0x0691, 0x16B0, 0x6657, 0x7676, 0x4615, 0x5634,
    159  1.3.4.2  rpaulo 	0xD94C, 0xC96D, 0xF90E, 0xE92F, 0x99C8, 0x89E9, 0xB98A, 0xA9AB,
    160  1.3.4.2  rpaulo 	0x5844, 0x4865, 0x7806, 0x6827, 0x18C0, 0x08E1, 0x3882, 0x28A3,
    161  1.3.4.2  rpaulo 	0xCB7D, 0xDB5C, 0xEB3F, 0xFB1E, 0x8BF9, 0x9BD8, 0xABBB, 0xBB9A,
    162  1.3.4.2  rpaulo 	0x4A75, 0x5A54, 0x6A37, 0x7A16, 0x0AF1, 0x1AD0, 0x2AB3, 0x3A92,
    163  1.3.4.2  rpaulo 	0xFD2E, 0xED0F, 0xDD6C, 0xCD4D, 0xBDAA, 0xAD8B, 0x9DE8, 0x8DC9,
    164  1.3.4.2  rpaulo 	0x7C26, 0x6C07, 0x5C64, 0x4C45, 0x3CA2, 0x2C83, 0x1CE0, 0x0CC1,
    165  1.3.4.2  rpaulo 	0xEF1F, 0xFF3E, 0xCF5D, 0xDF7C, 0xAF9B, 0xBFBA, 0x8FD9, 0x9FF8,
    166  1.3.4.2  rpaulo 	0x6E17, 0x7E36, 0x4E55, 0x5E74, 0x2E93, 0x3EB2, 0x0ED1, 0x1EF0
    167  1.3.4.2  rpaulo };
    168  1.3.4.2  rpaulo 
    169  1.3.4.2  rpaulo unsigned short
    170  1.3.4.2  rpaulo udf_cksum(s, n)
    171  1.3.4.2  rpaulo 	unsigned char *s;
    172  1.3.4.2  rpaulo 	int n;
    173  1.3.4.2  rpaulo {
    174  1.3.4.2  rpaulo 	unsigned short crc=0;
    175  1.3.4.2  rpaulo 
    176  1.3.4.2  rpaulo 	while (n-- > 0)
    177  1.3.4.2  rpaulo 		crc = crc_table[(crc>>8 ^ *s++) & 0xff] ^ (crc<<8);
    178  1.3.4.2  rpaulo 	return crc;
    179  1.3.4.2  rpaulo }
    180  1.3.4.2  rpaulo 
    181  1.3.4.2  rpaulo /* UNICODE Checksum */
    182  1.3.4.2  rpaulo unsigned short
    183  1.3.4.2  rpaulo udf_unicode_cksum(s, n)
    184  1.3.4.2  rpaulo 	unsigned short *s;
    185  1.3.4.2  rpaulo 	int n;
    186  1.3.4.2  rpaulo {
    187  1.3.4.2  rpaulo 	unsigned short crc=0;
    188  1.3.4.2  rpaulo 
    189  1.3.4.2  rpaulo 	while (n-- > 0) {
    190  1.3.4.2  rpaulo 		/* Take high order byte first--corresponds to a big endian
    191  1.3.4.2  rpaulo 		 * byte stream.
    192  1.3.4.2  rpaulo 		 */
    193  1.3.4.2  rpaulo 		crc = crc_table[(crc>>8 ^ (*s>>8)) & 0xff] ^ (crc<<8);
    194  1.3.4.2  rpaulo 		crc = crc_table[(crc>>8 ^ (*s++ & 0xff)) & 0xff] ^ (crc<<8);
    195  1.3.4.2  rpaulo 	}
    196  1.3.4.2  rpaulo 	return crc;
    197  1.3.4.2  rpaulo }
    198  1.3.4.2  rpaulo 
    199  1.3.4.2  rpaulo #ifdef MAIN
    200  1.3.4.2  rpaulo unsigned char bytes[] = { 0x70, 0x6A, 0x77 };
    201  1.3.4.2  rpaulo 
    202  1.3.4.2  rpaulo main()
    203  1.3.4.2  rpaulo {
    204  1.3.4.2  rpaulo 	unsigned short x;
    205  1.3.4.2  rpaulo 	x = cksum(bytes, sizeof bytes);
    206  1.3.4.2  rpaulo 	printf("checksum: calculated=%4.4x, correct=%4.4x\en", x, 0x3299);
    207  1.3.4.2  rpaulo 	exit(0);
    208  1.3.4.2  rpaulo }
    209  1.3.4.2  rpaulo #endif
    210  1.3.4.2  rpaulo 
    211  1.3.4.2  rpaulo /*****************************************************************************/
    212  1.3.4.2  rpaulo /* #ifdef NEEDS_ISPRINT */
    213  1.3.4.2  rpaulo /***********************************************************************
    214  1.3.4.2  rpaulo  * OSTA UDF compliant file name translation routine for OS/2,
    215  1.3.4.2  rpaulo  * Windows 95, Windows NT, Macintosh and UNIX.
    216  1.3.4.2  rpaulo  * Copyright 1995 Micro Design International, Inc.
    217  1.3.4.2  rpaulo  * Written by Jason M. Rinn.
    218  1.3.4.2  rpaulo  * Micro Design International gives permission for the free use of the
    219  1.3.4.2  rpaulo  * following source code.
    220  1.3.4.2  rpaulo  */
    221  1.3.4.2  rpaulo 
    222  1.3.4.2  rpaulo /***********************************************************************
    223  1.3.4.2  rpaulo  * To use these routines with different operating systems.
    224  1.3.4.2  rpaulo  *
    225  1.3.4.2  rpaulo  * OS/2
    226  1.3.4.2  rpaulo  * Define OS2
    227  1.3.4.2  rpaulo  * Define MAXLEN = 254
    228  1.3.4.2  rpaulo  *
    229  1.3.4.2  rpaulo  * Windows 95
    230  1.3.4.2  rpaulo  * Define WIN_95
    231  1.3.4.2  rpaulo  * Define MAXLEN = 255
    232  1.3.4.2  rpaulo  *
    233  1.3.4.2  rpaulo  * Windows NT
    234  1.3.4.2  rpaulo  * Define WIN_NT
    235  1.3.4.2  rpaulo  * Define MAXLEN = 255
    236  1.3.4.2  rpaulo  *
    237  1.3.4.2  rpaulo  * Macintosh:
    238  1.3.4.2  rpaulo  * Define MAC.
    239  1.3.4.2  rpaulo  * Define MAXLEN = 31.
    240  1.3.4.2  rpaulo  *
    241  1.3.4.2  rpaulo  * UNIX
    242  1.3.4.2  rpaulo  * Define UNIX.
    243  1.3.4.2  rpaulo  * Define MAXLEN as specified by unix version.
    244  1.3.4.2  rpaulo  */
    245  1.3.4.2  rpaulo 
    246  1.3.4.2  rpaulo #define	ILLEGAL_CHAR_MARK	0x005F
    247  1.3.4.2  rpaulo #define	CRC_MARK	0x0023
    248  1.3.4.2  rpaulo #define	EXT_SIZE	5
    249  1.3.4.2  rpaulo #define	TRUE	1
    250  1.3.4.2  rpaulo #define	FALSE	0
    251  1.3.4.2  rpaulo #define	PERIOD	0x002E
    252  1.3.4.2  rpaulo #define	SPACE	0x0020
    253  1.3.4.2  rpaulo 
    254  1.3.4.2  rpaulo /*** PROTOTYPES ***/
    255  1.3.4.2  rpaulo int IsIllegal(unicode_t ch);
    256  1.3.4.2  rpaulo 
    257  1.3.4.2  rpaulo /* Define a function or macro which determines if a Unicode character is
    258  1.3.4.2  rpaulo  * printable under your implementation.
    259  1.3.4.2  rpaulo  */
    260  1.3.4.2  rpaulo 
    261  1.3.4.2  rpaulo 
    262  1.3.4.2  rpaulo /* #include <stdio.h> */
    263  1.3.4.2  rpaulo static int UnicodeIsPrint(unicode_t ch) {
    264  1.3.4.2  rpaulo 	return (ch >=' ') && (ch < 127);
    265  1.3.4.2  rpaulo }
    266  1.3.4.2  rpaulo 
    267  1.3.4.2  rpaulo 
    268  1.3.4.2  rpaulo int UnicodeLength(unicode_t *string) {
    269  1.3.4.2  rpaulo 	int length;
    270  1.3.4.2  rpaulo 	length = 0;
    271  1.3.4.2  rpaulo 	while (*string++) length++;
    272  1.3.4.2  rpaulo 
    273  1.3.4.2  rpaulo 	return length;
    274  1.3.4.2  rpaulo }
    275  1.3.4.2  rpaulo 
    276  1.3.4.2  rpaulo 
    277  1.3.4.2  rpaulo static int isprint(unsigned char c) {
    278  1.3.4.2  rpaulo 	return (c >= ' ') && (c != 127);
    279  1.3.4.2  rpaulo }
    280  1.3.4.2  rpaulo 
    281  1.3.4.2  rpaulo 
    282  1.3.4.2  rpaulo /***********************************************************************
    283  1.3.4.2  rpaulo  * Translates a long file name to one using a MAXLEN and an illegal
    284  1.3.4.2  rpaulo  * char set in accord with the OSTA requirements. Assumes the name has
    285  1.3.4.2  rpaulo  * already been translated to Unicode.
    286  1.3.4.2  rpaulo  *
    287  1.3.4.2  rpaulo  * RETURN VALUE
    288  1.3.4.2  rpaulo  *
    289  1.3.4.2  rpaulo  * Number of unicode characters in translated name.
    290  1.3.4.2  rpaulo  */
    291  1.3.4.2  rpaulo int UDFTransName(
    292  1.3.4.2  rpaulo 	unicode_t *newName,	/* (Output)Translated name. Must be of length
    293  1.3.4.2  rpaulo 				 * MAXLEN */
    294  1.3.4.2  rpaulo 	unicode_t *udfName,	/* (Input) Name from UDF volume.*/
    295  1.3.4.2  rpaulo 	int udfLen)		/* (Input) Length of UDF Name. */
    296  1.3.4.2  rpaulo {
    297  1.3.4.2  rpaulo 	int Index, newIndex = 0, needsCRC = FALSE;	/* index is shadowed */
    298  1.3.4.2  rpaulo 	int extIndex = 0, newExtIndex = 0, hasExt = FALSE;
    299  1.3.4.2  rpaulo #if defined OS2 || defined WIN_95 || defined WIN_NT
    300  1.3.4.2  rpaulo 	int trailIndex = 0;
    301  1.3.4.2  rpaulo #endif
    302  1.3.4.2  rpaulo 	unsigned short valueCRC;
    303  1.3.4.2  rpaulo 	unicode_t current;
    304  1.3.4.2  rpaulo 	const char hexChar[] = "0123456789ABCDEF";
    305  1.3.4.2  rpaulo 
    306  1.3.4.2  rpaulo 	for (Index = 0; Index < udfLen; Index++) {
    307  1.3.4.2  rpaulo 		current = udfName[Index];
    308  1.3.4.2  rpaulo 
    309  1.3.4.2  rpaulo 		if (IsIllegal(current) || !UnicodeIsPrint(current)) {
    310  1.3.4.2  rpaulo 			needsCRC = TRUE;
    311  1.3.4.2  rpaulo 			/* Replace Illegal and non-displayable chars with
    312  1.3.4.2  rpaulo 			 * underscore.
    313  1.3.4.2  rpaulo 			 */
    314  1.3.4.2  rpaulo 			current = ILLEGAL_CHAR_MARK;
    315  1.3.4.2  rpaulo 			/* Skip any other illegal or non-displayable
    316  1.3.4.2  rpaulo 			 * characters.
    317  1.3.4.2  rpaulo 			 */
    318  1.3.4.2  rpaulo 			while(Index+1 < udfLen && (IsIllegal(udfName[Index+1])
    319  1.3.4.2  rpaulo 			    || !UnicodeIsPrint(udfName[Index+1]))) {
    320  1.3.4.2  rpaulo 				Index++;
    321  1.3.4.2  rpaulo 			}
    322  1.3.4.2  rpaulo 		}
    323  1.3.4.2  rpaulo 
    324  1.3.4.2  rpaulo 		/* Record position of extension, if one is found. */
    325  1.3.4.2  rpaulo 		if (current == PERIOD && (udfLen - Index -1) <= EXT_SIZE) {
    326  1.3.4.2  rpaulo 			if (udfLen == Index + 1) {
    327  1.3.4.2  rpaulo 				/* A trailing period is NOT an extension. */
    328  1.3.4.2  rpaulo 				hasExt = FALSE;
    329  1.3.4.2  rpaulo 			} else {
    330  1.3.4.2  rpaulo 				hasExt = TRUE;
    331  1.3.4.2  rpaulo 				extIndex = Index;
    332  1.3.4.2  rpaulo 				newExtIndex = newIndex;
    333  1.3.4.2  rpaulo 			}
    334  1.3.4.2  rpaulo 		}
    335  1.3.4.2  rpaulo 
    336  1.3.4.2  rpaulo #if defined OS2 || defined WIN_95 || defined WIN_NT
    337  1.3.4.2  rpaulo 		/* Record position of last char which is NOT period or space. */
    338  1.3.4.2  rpaulo 		else if (current != PERIOD && current != SPACE) {
    339  1.3.4.2  rpaulo 			trailIndex = newIndex;
    340  1.3.4.2  rpaulo 		}
    341  1.3.4.2  rpaulo #endif
    342  1.3.4.2  rpaulo 
    343  1.3.4.2  rpaulo 		if (newIndex < MAXLEN) {
    344  1.3.4.2  rpaulo 			newName[newIndex++] = current;
    345  1.3.4.2  rpaulo 		} else {
    346  1.3.4.2  rpaulo 			needsCRC = TRUE;
    347  1.3.4.2  rpaulo 		}
    348  1.3.4.2  rpaulo 	}
    349  1.3.4.2  rpaulo 
    350  1.3.4.2  rpaulo #if defined OS2 || defined WIN_95 || defined WIN_NT
    351  1.3.4.2  rpaulo 	/* For OS2, 95 & NT, truncate any trailing periods and\or spaces. */
    352  1.3.4.2  rpaulo 	if (trailIndex != newIndex - 1) {
    353  1.3.4.2  rpaulo 		newIndex = trailIndex + 1;
    354  1.3.4.2  rpaulo 		needsCRC = TRUE;
    355  1.3.4.2  rpaulo 		hasExt = FALSE; /* Trailing period does not make an
    356  1.3.4.2  rpaulo 				 * extension. */
    357  1.3.4.2  rpaulo 	}
    358  1.3.4.2  rpaulo #endif
    359  1.3.4.2  rpaulo 
    360  1.3.4.2  rpaulo 	if (needsCRC) {
    361  1.3.4.2  rpaulo 		unicode_t ext[EXT_SIZE];
    362  1.3.4.2  rpaulo 		int localExtIndex = 0;
    363  1.3.4.2  rpaulo 		if (hasExt) {
    364  1.3.4.2  rpaulo 			int maxFilenameLen;
    365  1.3.4.2  rpaulo 			/* Translate extension, and store it in ext. */
    366  1.3.4.2  rpaulo 			for(Index = 0; Index<EXT_SIZE &&
    367  1.3.4.2  rpaulo 			    extIndex + Index +1 < udfLen; Index++ ) {
    368  1.3.4.2  rpaulo 				current = udfName[extIndex + Index + 1];
    369  1.3.4.2  rpaulo 				if (IsIllegal(current) ||
    370  1.3.4.2  rpaulo 				    !UnicodeIsPrint(current)) {
    371  1.3.4.2  rpaulo 					needsCRC = 1;
    372  1.3.4.2  rpaulo 					/* Replace Illegal and non-displayable
    373  1.3.4.2  rpaulo 					 * chars with underscore.
    374  1.3.4.2  rpaulo 					 */
    375  1.3.4.2  rpaulo 					current = ILLEGAL_CHAR_MARK;
    376  1.3.4.2  rpaulo 					/* Skip any other illegal or
    377  1.3.4.2  rpaulo 					 * non-displayable characters.
    378  1.3.4.2  rpaulo 					 */
    379  1.3.4.2  rpaulo 					while(Index + 1 < EXT_SIZE
    380  1.3.4.2  rpaulo 					    && (IsIllegal(udfName[extIndex +
    381  1.3.4.2  rpaulo 					    Index + 2]) ||
    382  1.3.4.2  rpaulo 					    !isprint(udfName[extIndex +
    383  1.3.4.2  rpaulo 					    Index + 2]))) {
    384  1.3.4.2  rpaulo 						Index++;
    385  1.3.4.2  rpaulo 					}
    386  1.3.4.2  rpaulo 				}
    387  1.3.4.2  rpaulo 				ext[localExtIndex++] = current;
    388  1.3.4.2  rpaulo 			}
    389  1.3.4.2  rpaulo 
    390  1.3.4.2  rpaulo 			/* Truncate filename to leave room for extension and
    391  1.3.4.2  rpaulo 			 * CRC.
    392  1.3.4.2  rpaulo 			 */
    393  1.3.4.2  rpaulo 			maxFilenameLen = ((MAXLEN - 5) - localExtIndex - 1);
    394  1.3.4.2  rpaulo 			if (newIndex > maxFilenameLen) {
    395  1.3.4.2  rpaulo 				newIndex = maxFilenameLen;
    396  1.3.4.2  rpaulo 			} else {
    397  1.3.4.2  rpaulo 				newIndex = newExtIndex;
    398  1.3.4.2  rpaulo 			}
    399  1.3.4.2  rpaulo 		} else if (newIndex > MAXLEN - 5) {
    400  1.3.4.2  rpaulo 			/*If no extension, make sure to leave room for CRC. */
    401  1.3.4.2  rpaulo 			newIndex = MAXLEN - 5;
    402  1.3.4.2  rpaulo 		}
    403  1.3.4.2  rpaulo 		newName[newIndex++] = CRC_MARK; /* Add mark for CRC. */
    404  1.3.4.2  rpaulo 
    405  1.3.4.2  rpaulo 		/*Calculate CRC from original filename from FileIdentifier. */
    406  1.3.4.2  rpaulo 		valueCRC = udf_unicode_cksum(udfName, udfLen);
    407  1.3.4.2  rpaulo 		/* Convert 16-bits of CRC to hex characters. */
    408  1.3.4.2  rpaulo 		newName[newIndex++] = hexChar[(valueCRC & 0xf000) >> 12];
    409  1.3.4.2  rpaulo 		newName[newIndex++] = hexChar[(valueCRC & 0x0f00) >> 8];
    410  1.3.4.2  rpaulo 		newName[newIndex++] = hexChar[(valueCRC & 0x00f0) >> 4];
    411  1.3.4.2  rpaulo 		newName[newIndex++] = hexChar[(valueCRC & 0x000f)];
    412  1.3.4.2  rpaulo 
    413  1.3.4.2  rpaulo 		/* Place a translated extension at end, if found. */
    414  1.3.4.2  rpaulo 		if (hasExt) {
    415  1.3.4.2  rpaulo 			newName[newIndex++] = PERIOD;
    416  1.3.4.2  rpaulo 			for (Index = 0;Index < localExtIndex ;Index++ ) {
    417  1.3.4.2  rpaulo 				newName[newIndex++] = ext[Index];
    418  1.3.4.2  rpaulo 			}
    419  1.3.4.2  rpaulo 		}
    420  1.3.4.2  rpaulo 	}
    421  1.3.4.2  rpaulo 	return(newIndex);
    422  1.3.4.2  rpaulo }
    423  1.3.4.2  rpaulo 
    424  1.3.4.2  rpaulo #if defined OS2 || defined WIN_95 || defined WIN_NT
    425  1.3.4.2  rpaulo /***********************************************************************
    426  1.3.4.2  rpaulo  * Decides if a Unicode character matches one of a list
    427  1.3.4.2  rpaulo  * of ASCII characters.
    428  1.3.4.2  rpaulo  * Used by OS2 version of IsIllegal for readability, since all of the
    429  1.3.4.2  rpaulo  * illegal characters above 0x0020 are in the ASCII subset of Unicode.
    430  1.3.4.2  rpaulo  * Works very similarly to the standard C function strchr().
    431  1.3.4.2  rpaulo  *
    432  1.3.4.2  rpaulo  * RETURN VALUE
    433  1.3.4.2  rpaulo  *
    434  1.3.4.2  rpaulo  * Non-zero if the Unicode character is in the given ASCII string.
    435  1.3.4.2  rpaulo  */
    436  1.3.4.2  rpaulo int UnicodeInString(
    437  1.3.4.2  rpaulo 	unsigned char *string,	/* (Input) String to search through. */
    438  1.3.4.2  rpaulo 	unicode_t ch)		/* (Input) Unicode char to search for. */
    439  1.3.4.2  rpaulo {
    440  1.3.4.2  rpaulo 	int found = FALSE;
    441  1.3.4.2  rpaulo 	while (*string != '\0' && found == FALSE) {
    442  1.3.4.2  rpaulo 		/* These types should compare, since both are unsigned
    443  1.3.4.2  rpaulo 		 * numbers. */
    444  1.3.4.2  rpaulo 		if (*string == ch) {
    445  1.3.4.2  rpaulo 			found = TRUE;
    446  1.3.4.2  rpaulo 		}
    447  1.3.4.2  rpaulo 		string++;
    448  1.3.4.2  rpaulo 	}
    449  1.3.4.2  rpaulo 	return(found);
    450  1.3.4.2  rpaulo }
    451  1.3.4.2  rpaulo #endif /* OS2 */
    452  1.3.4.2  rpaulo 
    453  1.3.4.2  rpaulo /***********************************************************************
    454  1.3.4.2  rpaulo  * Decides whether the given character is illegal for a given OS.
    455  1.3.4.2  rpaulo  *
    456  1.3.4.2  rpaulo  * RETURN VALUE
    457  1.3.4.2  rpaulo  *
    458  1.3.4.2  rpaulo  * Non-zero if char is illegal.
    459  1.3.4.2  rpaulo  */
    460  1.3.4.2  rpaulo int IsIllegal(unicode_t ch)
    461  1.3.4.2  rpaulo {
    462  1.3.4.2  rpaulo #ifdef MAC
    463  1.3.4.2  rpaulo 	/* Only illegal character on the MAC is the colon. */
    464  1.3.4.2  rpaulo 	if (ch == 0x003A) {
    465  1.3.4.2  rpaulo 		return(1);
    466  1.3.4.2  rpaulo 	} else {
    467  1.3.4.2  rpaulo 		return(0);
    468  1.3.4.2  rpaulo 	}
    469  1.3.4.2  rpaulo 
    470  1.3.4.2  rpaulo #elif defined UNIX
    471  1.3.4.2  rpaulo 	/* Illegal UNIX characters are NULL and slash. */
    472  1.3.4.2  rpaulo 	if (ch == 0x0000 || ch == 0x002F) {
    473  1.3.4.2  rpaulo 		return(1);
    474  1.3.4.2  rpaulo 	} else {
    475  1.3.4.2  rpaulo 		return(0);
    476  1.3.4.2  rpaulo 	}
    477  1.3.4.2  rpaulo 
    478  1.3.4.2  rpaulo #elif defined OS2 || defined WIN_95 || defined WIN_NT
    479  1.3.4.2  rpaulo 	/* Illegal char's for OS/2 according to WARP toolkit. */
    480  1.3.4.2  rpaulo 	if (ch < 0x0020 || UnicodeInString("\\/:*?\"<>|", ch)) {
    481  1.3.4.2  rpaulo 		return(1);
    482  1.3.4.2  rpaulo 	} else {
    483  1.3.4.2  rpaulo 		return(0);
    484  1.3.4.2  rpaulo 	}
    485  1.3.4.2  rpaulo #endif
    486  1.3.4.2  rpaulo }
    487  1.3.4.2  rpaulo /* #endif*/	/* NEEDS_ISPRINT */
    488  1.3.4.2  rpaulo 
    489