root/trunk/src/encoding.c

Revision 694, 3.8 kB (checked in by jajcus, 2 years ago)

- buffer overflow bug fixed, thanks Michal

Line 
1 /* $Id: encoding.c,v 1.16 2003/08/08 16:08:10 jajcus Exp $ */
2
3 /*
4  *  (C) Copyright 2002-2006 Jacek Konieczny [jajcus(a)jajcus,net]
5  *
6  *  This program is free software; you can redistribute it and/or modify
7  *  it under the terms of the GNU General Public License Version 2 as
8  *  published by the Free Software Foundation.
9  *
10  *  This program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  *  GNU General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License
16  *  along with this program; if not, write to the Free Software
17  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18  */
19
20 #include "ggtrans.h"
21 #include <errno.h>
22 #include <assert.h>
23 #include "encoding.h"
24 #include "enc_win2uni.h"
25 #include "enc_uni2win.h"
26
27 static unsigned char *buf;
28 static int buf_len;
29
30 int encoding_init(){
31
32         buf_len=16;
33         buf=g_new(char,buf_len);
34         return 0;
35 }
36
37 void encoding_done(){
38
39         g_free(buf);
40 }
41
42 char *to_utf8(const char *str){
43 int o=0;
44 int i;
45 unsigned char c;
46 unsigned u;
47
48         if (str==NULL) return NULL;
49         if (buf_len<(3*strlen(str)+1)){
50                 buf_len=3*strlen(str)+1; /* this should always be enough */
51                 buf=(char *)g_realloc(buf,buf_len);
52                 assert(buf!=NULL);
53         }
54         for(i=0;str[i];i++){
55                 c=(unsigned char)str[i];
56                 if (c=='\r'){
57                         continue;
58                 }
59                 if (c=='\t' || c=='\n'){
60                         buf[o++]=c;
61                         continue;
62                 }
63                 if (c<32){
64                         buf[o++]='\xef';
65                         buf[o++]='\xbf';
66                         buf[o++]='\xbd';
67                         continue;
68                 }
69                 if (c<128){
70                         buf[o++]=c;
71                         continue;
72                 }
73                 u=win1250_to_unicode[c-128];
74                 if (u==0||u>0x10000){ /* we don't need character > U+0x10000 */
75                         buf[o++]='\xef';
76                         buf[o++]='\xbf';
77                         buf[o++]='\xbd';
78                 }
79                 else if (u<0x800){
80                         buf[o++]=0xc0|(u>>6);
81                         buf[o++]=0x80|(u&0x3f);
82                 }
83                 else{
84                         buf[o++]=0xe0|(u>>12);
85                         buf[o++]=0x80|((u>>6)&0x3f);
86                         buf[o++]=0x80|(u&0x3f);
87                 }
88         }
89         buf[o]=0;
90         return (char *)buf;
91 }
92
93 char *from_utf8(const char *str){
94 unsigned char b;
95 unsigned u;
96 int o=0;
97 int i;
98
99         if (str==NULL) return NULL;
100         if (buf_len<(strlen(str)*2+1)){
101                 buf_len=strlen(str)*2+1; /* this should always be enough */
102                 buf=(char *)g_realloc(buf,buf_len);
103                 assert(buf!=NULL);
104         }
105         for(i=0;str[i];i++){
106                 b=(unsigned char)str[i];
107                 if (b=='\n'){
108                         buf[o++]='\r';
109                         buf[o++]='\n';
110                         continue;
111                 }
112                 if ((b&0x80)==0){ /* ASCII */
113                         buf[o++]=b;
114                         continue;
115                 }
116                 if ((b&0xc0)==0x80){ /* middle of UTF-8 char */
117                         continue;
118                 }
119                 if ((b&0xe0)==0xc0){
120                         u=b&0x1f;
121                         i++;
122                         b=(unsigned char)str[i];
123                         if (b==0){
124                                 buf[o++]='?';
125                                 break;
126                         }
127                         if ((b&0xc0)!=0x80){
128                                 buf[o++]='?';
129                                 continue;
130                         }
131                         u=(u<<6)|(b&0x3f);
132                 }
133                 else if ((b&0xf0)==0xe0){
134                         u=b&0x0f;
135                         b=(unsigned char)str[++i];
136                         if (b==0){
137                                 buf[o++]='?';
138                                 break;
139                         }
140                         if ((b&0xc0)!=0x80){
141                                 buf[o++]='?';
142                                 continue;
143                         }
144                         u=(u<<6)|(b&0x3f);
145                         b=(unsigned char)str[++i];
146                         if (b==0){
147                                 buf[o++]='?';
148                                 break;
149                         }
150                         if ((b&0xc0)!=0x80){
151                                 buf[o++]='?';
152                                 continue;
153                         }
154                         u=(u<<6)|(b&0x3f);
155                 }
156                 else{
157                         buf[o++]='?';
158                         continue;
159                 }
160                 if (u<0x00a0)
161                         buf[o++]='?';
162                 else if (u<0x0180)
163                         buf[o++]=unicode_to_win1250_a0_17f[u-0x00a0];
164                 else if (u==0x02c7)
165                         buf[o++]=0xa1;
166                 else if (u<0x02d8)
167                         buf[o++]='?';
168                 else if (u<0x02de)
169                         buf[o++]=unicode_to_win1250_2d8_2dd[u-0x02d8];
170                 else if (u<0x2013)
171                         buf[o++]='?';
172                 else if (u<0x203b)
173                         buf[o++]=unicode_to_win1250_2013_203a[u-0x2013];
174                 else if (u==0x20ac)
175                         buf[o++]=0x80;
176                 else if (u==0x2122)
177                         buf[o++]=0x99;
178                 else
179                         buf[o++]='?';
180         }
181         buf[o]=0;
182         return buf;
183 }
184
185 #ifdef ENCODINGTEST
186 #include <stdio.h>
187
188 int main(int argc,char *argv[]){
189 char buf[1024],*p;
190
191         encoding_init();
192         while(1){
193                 p=fgets(buf,1024,stdin);
194                 if (p==NULL || buf[0]=='\n') break;
195                 printf("To UTF8: %s",to_utf8(buf));
196                 printf("From UTF8: %s",from_utf8(buf));
197         }
198         encoding_done();
199         return 0;
200 }
201
202 #endif
Note: See TracBrowser for help on using the browser.