1/* 2 Unix SMB/CIFS implementation. 3 minimal iconv implementation 4 Copyright (C) Andrew Tridgell 2001 5 Copyright (C) Jelmer Vernooij 2002,2003 6 7 This program is free software; you can redistribute it and/or modify 8 it under the terms of the GNU General Public License as published by 9 the Free Software Foundation; either version 2 of the License, or 10 (at your option) any later version. 11 12 This program is distributed in the hope that it will be useful, 13 but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 GNU General Public License for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with this program; if not, write to the Free Software 19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 20 21 From samba 3.0 beta and GNU libiconv-1.8 22 It's bad but most of the time we can't use libc iconv service: 23 - it doesn't round trip for most encoding 24 - it doesn't know about Apple extension 25*/ 26 27#ifdef HAVE_CONFIG_H 28#include "config.h" 29#endif /* HAVE_CONFIG_H */ 30#include <stdlib.h> 31#include <string.h> 32#include <errno.h> 33 34#include <netatalk/endian.h> 35#include <atalk/unicode.h> 36#include <atalk/logger.h> 37 38#include "../byteorder.h" 39#include "mac_hebrew.h" 40 41static size_t mac_hebrew_pull(void *,char **, size_t *, char **, size_t *); 42static size_t mac_hebrew_push(void *,char **, size_t *, char **, size_t *); 43 44struct charset_functions charset_mac_hebrew = 45{ 46 "MAC_HEBREW", 47 5, 48 mac_hebrew_pull, 49 mac_hebrew_push, 50 CHARSET_CLIENT | CHARSET_MULTIBYTE, 51 NULL, 52 NULL, NULL 53}; 54 55 56/* ------------------------ 57 * from unicode to mac hebrew code page 58*/ 59static int 60char_ucs2_to_mac_hebrew ( unsigned char *r, ucs2_t wc) 61{ 62 unsigned char c = 0; 63 if (wc < 0x0080) { 64 *r = wc; 65 return 1; 66 } 67 else if (wc >= 0x00a0 && wc < 0x0100) 68 c = mac_hebrew_page00[wc-0x00a0]; 69 else if (wc >= 0x05b0 && wc < 0x05f0) 70 c = mac_hebrew_page05[wc-0x05b0]; 71 else if (wc >= 0x2010 && wc < 0x2028) 72 c = mac_hebrew_page20[wc-0x2010]; 73 else if (wc == 0x20aa) 74 c = 0xa6; 75 else if (wc >= 0xfb18 && wc < 0xfb50) 76 c = mac_hebrew_pagefb[wc-0xfb18]; 77 if (c != 0) { 78 *r = c; 79 return 1; 80 } 81 return 0; 82} 83 84static size_t mac_hebrew_push( void *cd _U_, char **inbuf, size_t *inbytesleft, 85 char **outbuf, size_t *outbytesleft) 86{ 87 unsigned char c = 0; 88 int len = 0; 89 unsigned char *tmpptr = (unsigned char *) *outbuf; 90 91 while (*inbytesleft >= 2 && *outbytesleft >= 1) { 92 ucs2_t inptr = SVAL((*inbuf),0); 93 if (inptr == 0x05b8) { 94 (*inbuf) += 2; 95 (*inbytesleft) -= 2; 96 if (*inbytesleft >= 2 && SVAL((*inbuf),0) == 0xf87f ) { 97 (*inbuf) += 2; 98 (*inbytesleft) -= 2; 99 c = 0xde; 100 } 101 else { 102 c = 0xcb; 103 } 104 *tmpptr = c; 105 } 106 else if (inptr == 0x05f2 && *inbytesleft >= 4 && SVAL((*inbuf),2) == 0x05b7) { 107 (*inbuf) += 4; 108 (*inbytesleft) -= 4; 109 *tmpptr = 0x81; 110 } 111 else if (inptr == 0xf86a && *inbytesleft >= 6 && SVAL((*inbuf),2) == 0x05dc && SVAL((*inbuf),4) == 0x05b9) { 112 (*inbuf) += 6; 113 (*inbytesleft) -= 6; 114 *tmpptr = 0xc0; 115 } 116 else if (char_ucs2_to_mac_hebrew ( tmpptr, inptr)) { 117 (*inbuf) += 2; 118 (*inbytesleft) -= 2; 119 } 120 else { 121 errno = EILSEQ; 122 return (size_t) -1; 123 } 124 (*outbytesleft) -= 1; 125 tmpptr++; 126 len++; 127 } 128 129 if (*inbytesleft > 0) { 130 errno = E2BIG; 131 return -1; 132 } 133 134 return len; 135} 136 137/* ------------------------ */ 138static int 139char_mac_hebrew_to_ucs2 (ucs2_t *pwc, const unsigned char *s) 140{ 141 unsigned char c = *s; 142 if (c < 0x80) { 143 *pwc = (ucs2_t) c; 144 return 1; 145 } 146 else { 147 unsigned short wc = mac_hebrew_2uni[c-0x80]; 148 if (wc != 0xfffd) { 149 *pwc = (ucs2_t) wc; 150 return 1; 151 } 152 } 153 return 0; 154} 155 156static size_t mac_hebrew_pull ( void *cd _U_, char **inbuf, size_t *inbytesleft, 157 char **outbuf, size_t *outbytesleft) 158{ 159 ucs2_t temp; 160 unsigned char *inptr; 161 size_t len = 0; 162 163 while (*inbytesleft >= 1 && *outbytesleft >= 2) { 164 inptr = (unsigned char *) *inbuf; 165 if (char_mac_hebrew_to_ucs2 ( &temp, inptr)) { 166 if (temp == 1) { /* 0x81 --> 0x05f2+0x05b7 */ 167 if (*outbytesleft < 4) { 168 errno = E2BIG; 169 return (size_t) -1; 170 } 171 SSVAL((*outbuf),0,0x05f2); 172 SSVAL((*outbuf),2,0x05b7); 173 (*outbuf) +=4; 174 (*outbytesleft)-=4; 175 len += 2; 176 } 177 else if (temp == 2) { /* 0xc0 -> 0xf86a 0x05dc 0x05b9*/ 178 if (*outbytesleft < 6) { 179 errno = E2BIG; 180 return (size_t) -1; 181 } 182 SSVAL((*outbuf),0,0xf86a); 183 SSVAL((*outbuf),2,0x05dc); 184 SSVAL((*outbuf),4,0x05b9); 185 (*outbuf) +=6; 186 (*outbytesleft)-=6; 187 len += 3; 188 } 189 else if (temp == 3) { /* 0xde --> 0x05b8 0xf87f */ 190 if (*outbytesleft < 4) { 191 errno = E2BIG; 192 return (size_t) -1; 193 } 194 SSVAL((*outbuf),0,0x05b8); 195 SSVAL((*outbuf),2,0xf87f); 196 (*outbuf) +=4; 197 (*outbytesleft)-=4; 198 len += 2; 199 } 200 else { 201 SSVAL((*outbuf),0,temp); 202 (*outbuf) +=2; 203 (*outbytesleft)-=2; 204 len++; 205 } 206 (*inbuf) +=1; 207 (*inbytesleft) -=1; 208 } 209 else 210 { 211 errno = EILSEQ; 212 return (size_t) -1; 213 } 214 } 215 216 if (*inbytesleft > 0) { 217 errno = E2BIG; 218 return (size_t) -1; 219 } 220 return len; 221} 222 223