1/* 2 * Copyright (c) 2001 - 2010 Apple Inc. All rights reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. Please obtain a copy of the License at 10 * http://www.opensource.apple.com/apsl/ and read it before using this 11 * file. 12 * 13 * The Original Code and all software distributed under the License are 14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 * Please see the License for the specific language governing rights and 19 * limitations under the License. 20 * 21 * @APPLE_LICENSE_HEADER_END@ 22 */ 23#include <stdlib.h> 24#include <string.h> 25#include <netsmb/smb_lib.h> 26#include "charsets.h" 27 28/* 29 * We now use CFStringUppercase 30 */ 31void str_upper(char *dst, size_t maxDstLen, CFStringRef srcRef) 32{ 33 CFMutableStringRef upperRef = CFStringCreateMutableCopy(kCFAllocatorDefault, 0, srcRef); 34 if (upperRef == NULL) { 35 /* Nothing else we can do here */ 36 CFStringGetCString(srcRef, dst, maxDstLen, kCFStringEncodingUTF8); 37 return; 38 } 39 CFStringUppercase(upperRef, NULL); 40 CFStringGetCString(upperRef, dst, maxDstLen, kCFStringEncodingUTF8); 41 CFRelease(upperRef); 42} 43 44/* 45 * %%% - Change all strings to CFStringRef, once we remove the UI code. 46 */ 47char * 48convert_wincs_to_utf8(const char *windows_string, CFStringEncoding codePage) 49{ 50 CFStringRef s; 51 CFIndex maxlen; 52 char *result; 53 54 s = CFStringCreateWithCString(NULL, windows_string, codePage); 55 if (s == NULL) { 56 smb_log_info("CFStringCreateWithCString for Windows code page failed on \"%s\", syserr = %s", 57 ASL_LEVEL_DEBUG, windows_string, strerror(errno)); 58 59 /* kCFStringEncodingMacRoman should always succeed */ 60 s = CFStringCreateWithCString(NULL, windows_string, 61 kCFStringEncodingMacRoman); 62 if (s == NULL) { 63 smb_log_info("CFStringCreateWithCString for Windows code page failed on \"%s\" with kCFStringEncodingMacRoman - skipping, syserr = %s", 64 ASL_LEVEL_DEBUG, windows_string, strerror(errno)); 65 return NULL; 66 } 67 } 68 69 maxlen = CFStringGetMaximumSizeForEncoding(CFStringGetLength(s), 70 kCFStringEncodingUTF8) + 1; 71 72 result = malloc(maxlen); 73 if (result == NULL) { 74 smb_log_info("Couldn't allocate buffer for UTF-8 string for \"%s\" - skipping, syserr = %s", 75 ASL_LEVEL_DEBUG, windows_string, strerror(errno)); 76 CFRelease(s); 77 return NULL; 78 } 79 80 if (!CFStringGetCString(s, result, maxlen, kCFStringEncodingUTF8)) { 81 smb_log_info("CFStringGetCString for UTF-8 failed on \"%s\" - skipping, syserr = %s", 82 ASL_LEVEL_DEBUG, windows_string, strerror(errno)); 83 CFRelease(s); 84 free(result); 85 return NULL; 86 } 87 88 CFRelease(s); 89 return result; 90} 91 92/* 93 * This routine assumes the inbound c-style string is really a UTF8 string. 94 * We create a CFString, uppercase if the flag is set, convert it to the code 95 * page and then return a c-style string containing the new converted string. 96 */ 97char *convert_utf8_to_wincs(const char *utf8_string, CFStringEncoding codePage, int uppercase) 98{ 99 CFStringRef utfStr; 100 CFMutableStringRef utfMutableStr = NULL; 101 CFIndex maxlen; 102 char *result = NULL; 103 104 utfStr = CFStringCreateWithCString(NULL, utf8_string, kCFStringEncodingUTF8); 105 if (utfStr) { 106 utfMutableStr = CFStringCreateMutableCopy(NULL, 0, utfStr); 107 CFRelease(utfStr); 108 } 109 110 if (utfMutableStr == NULL) { 111 smb_log_info("CFStringCreateWithCString for UTF-8 failed on \"%s\", syserr = %s", 112 ASL_LEVEL_DEBUG, utf8_string, strerror(errno)); 113 goto done; 114 } 115 116 if (uppercase) { 117 CFStringUppercase(utfMutableStr, CFLocaleGetSystem()); 118 } 119 120 maxlen = CFStringGetMaximumSizeForEncoding(CFStringGetLength(utfMutableStr), codePage) + 1; 121 result = malloc(maxlen); 122 if (result == NULL) { 123 smb_log_info("Couldn't allocate buffer for Windows code page string for \"%s\" - skipping, syserr = %s", 124 ASL_LEVEL_DEBUG, utf8_string, strerror(errno)); 125 goto done; 126 } 127 if (!CFStringGetCString(utfMutableStr, result, maxlen, codePage)) { 128 smb_log_info("CFStringGetCString for Windows code page failed on \"%s\" - skipping, syserr = %s", 129 ASL_LEVEL_DEBUG, utf8_string, strerror(errno)); 130 free(result); 131 result = NULL; 132 goto done; 133 } 134 135done: 136 if (utfMutableStr) 137 CFRelease(utfMutableStr); 138 return result; 139} 140 141/* 142 * Convert little-endian Unicode string to UTF-8. 143 * Converts the Unicode string to host byte order in place. 144 * XXX - <rdar://problem/7518600> will clean this up 145 */ 146char * 147convert_leunicode_to_utf8(unsigned short *unicode_string, size_t maxLen) 148{ 149 unsigned short *unicode_charp, unicode_char; 150 151 for (unicode_charp = unicode_string; 152 (unicode_char = *unicode_charp) != 0; 153 unicode_charp++) 154 *unicode_charp = CFSwapInt16LittleToHost(unicode_char); 155 return convert_unicode_to_utf8(unicode_string, maxLen); 156} 157 158/* 159 * Convert Unicode string to UTF-8. 160 * XXX - <rdar://problem/7518600> will clean this up 161 */ 162char * 163convert_unicode_to_utf8(const uint16_t *unicode_string, size_t maxLen) 164{ 165 size_t uslen; 166 CFStringRef s; 167 char *result; 168 169 /* Number of characters not bytes */ 170 maxLen = maxLen / 2; 171 for (uslen = 0; (unicode_string[uslen] != 0) && (uslen < maxLen); uslen++) 172 ; 173 s = CFStringCreateWithCharacters(kCFAllocatorDefault, unicode_string, uslen); 174 if (s == NULL) { 175 smb_log_info("CFStringCreateWithCharacters failed, syserr = %s", 176 ASL_LEVEL_DEBUG, strerror(errno)); 177 return NULL; 178 } 179 maxLen = CFStringGetMaximumSizeForEncoding(CFStringGetLength(s), 180 kCFStringEncodingUTF8) + 1; 181 result = calloc(maxLen, 1); 182 if (result == NULL) { 183 smb_log_info("Couldn't allocate buffer for Unicode string - skipping, syserr = %s", 184 ASL_LEVEL_DEBUG, strerror(errno)); 185 CFRelease(s); 186 return NULL; 187 } 188 if (!CFStringGetCString(s, result, maxLen, kCFStringEncodingUTF8)) { 189 smb_log_info("CFStringGetCString failed on Unicode string - skipping, syserr = %s", 190 ASL_LEVEL_DEBUG, strerror(errno)); 191 CFRelease(s); 192 free(result); 193 return NULL; 194 } 195 CFRelease(s); 196 return result; 197} 198 199/* 200 * Convert UTF-8 string to little-endian Unicode. 201 * XXX - <rdar://problem/7518600> will clean this up 202*/ 203unsigned short * 204convert_utf8_to_leunicode(const char *utf8_string) 205{ 206 CFStringRef s; 207 CFIndex maxlen; 208 unsigned short *result; 209 CFRange range; 210 int i; 211 212 s = CFStringCreateWithCString(NULL, utf8_string, 213 kCFStringEncodingUTF8); 214 if (s == NULL) { 215 smb_log_info("CFStringCreateWithCString for UTF-8 failed on \"%s\", syserr = %s", 216 ASL_LEVEL_DEBUG, utf8_string, strerror(errno)); 217 return NULL; 218 } 219 220 maxlen = CFStringGetLength(s); 221 result = malloc(2*(maxlen + 1)); 222 if (result == NULL) { 223 smb_log_info("Couldn't allocate buffer for Unicode string for \"%s\" - skipping, syserr = %s", 224 ASL_LEVEL_DEBUG, utf8_string, strerror(errno)); 225 CFRelease(s); 226 return NULL; 227 } 228 range.location = 0; 229 range.length = maxlen; 230 CFStringGetCharacters(s, range, result); 231 for (i = 0; i < maxlen; i++) 232 result[i] = CFSwapInt16HostToLittle(result[i]); 233 result[maxlen] = 0; 234 CFRelease(s); 235 return result; 236} 237