1 /* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
2 
3 /* libcroco - Library for parsing and applying CSS
4  * Copyright (C) 2006-2019 Free Software Foundation, Inc.
5  *
6  * This file is not part of the GNU gettext program, but is used with
7  * GNU gettext.
8  *
9  * The original copyright notice is as follows:
10  */
11 
12 /*
13  * This file is part of The Croco Library
14  *
15  * Copyright (C) 2002-2003 Dodji Seketeli <dodji@seketeli.org>
16  *
17  * This program is free software; you can redistribute it and/or
18  * modify it under the terms of version 2.1 of the GNU Lesser General Public
19  * License as published by the Free Software Foundation.
20  *
21  * This program is distributed in the hope that it will be useful,
22  * but WITHOUT ANY WARRANTY; without even the implied warranty of
23  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
24  * GNU General Public License for more details.
25  *
26  * You should have received a copy of the GNU Lesser General Public License
27  * along with this program; if not, write to the Free Software
28  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
29  * USA
30  */
31 
32 /*
33  *$Id$
34  */
35 
36 /**
37  *@file
38  *The definition of the #CREncHandler class.
39  */
40 
41 #include <config.h>
42 #include "cr-enc-handler.h"
43 #include "cr-utils.h"
44 
45 #include <string.h>
46 
47 struct CREncAlias {
48         const gchar *name;
49         enum CREncoding encoding;
50 };
51 
52 static struct CREncAlias gv_default_aliases[] = {
53         {"UTF-8", CR_UTF_8},
54         {"UTF_8", CR_UTF_8},
55         {"UTF8", CR_UTF_8},
56         {"UTF-16", CR_UTF_16},
57         {"UTF_16", CR_UTF_16},
58         {"UTF16", CR_UTF_16},
59         {"UCS1", CR_UCS_1},
60         {"UCS-1", CR_UCS_1},
61         {"UCS_1", CR_UCS_1},
62         {"ISO-8859-1", CR_UCS_1},
63         {"ISO_8859-1", CR_UCS_1},
64         {"UCS-1", CR_UCS_1},
65         {"UCS_1", CR_UCS_1},
66         {"UCS4", CR_UCS_4},
67         {"UCS-4", CR_UCS_4},
68         {"UCS_4", CR_UCS_4},
69         {"ASCII", CR_ASCII},
70         {0, 0}
71 };
72 
73 static CREncHandler gv_default_enc_handlers[] = {
74         {CR_UCS_1, cr_utils_ucs1_to_utf8, cr_utils_utf8_to_ucs1,
75          cr_utils_ucs1_str_len_as_utf8, cr_utils_utf8_str_len_as_ucs1},
76 
77         {CR_ISO_8859_1, cr_utils_ucs1_to_utf8, cr_utils_utf8_to_ucs1,
78          cr_utils_ucs1_str_len_as_utf8, cr_utils_utf8_str_len_as_ucs1},
79 
80         {CR_ASCII, cr_utils_ucs1_to_utf8, cr_utils_utf8_to_ucs1,
81          cr_utils_ucs1_str_len_as_utf8, cr_utils_utf8_str_len_as_ucs1},
82 
83         {0, NULL, NULL, NULL, NULL}
84 };
85 
86 /**
87  * cr_enc_handler_get_instance:
88  *@a_enc: the encoding of the Handler.
89  *
90  *Gets the instance of encoding handler.
91  *This function implements a singleton pattern.
92  *
93  *Returns the instance of #CREncHandler.
94  */
95 CREncHandler *
cr_enc_handler_get_instance(enum CREncoding a_enc)96 cr_enc_handler_get_instance (enum CREncoding a_enc)
97 {
98         gulong i = 0;
99 
100         for (i = 0; gv_default_enc_handlers[i].encoding; i++) {
101                 if (gv_default_enc_handlers[i].encoding == a_enc) {
102                         return (CREncHandler *) & gv_default_enc_handlers[i];
103                 }
104         }
105 
106         return NULL;
107 }
108 
109 /**
110  * cr_enc_handler_resolve_enc_alias:
111  *@a_alias_name: the encoding name.
112  *@a_enc: output param. The returned encoding type
113  *or 0 if the alias is not supported.
114  *
115  *Given an encoding name (called an alias name)
116  *the function returns the matching encoding type.
117  *
118  *Returns CR_OK upon successfull completion, an error code otherwise.
119  */
120 enum CRStatus
cr_enc_handler_resolve_enc_alias(const guchar * a_alias_name,enum CREncoding * a_enc)121 cr_enc_handler_resolve_enc_alias (const guchar * a_alias_name,
122                                   enum CREncoding *a_enc)
123 {
124         gulong i = 0;
125         guchar *alias_name_up = NULL;
126         enum CRStatus status = CR_ENCODING_NOT_FOUND_ERROR;
127 
128         g_return_val_if_fail (a_alias_name != NULL, CR_BAD_PARAM_ERROR);
129 
130         alias_name_up = (guchar *) g_ascii_strup ((const gchar *) a_alias_name, -1);
131 
132         for (i = 0; gv_default_aliases[i].name; i++) {
133                 if (!strcmp (gv_default_aliases[i].name, (const gchar *) alias_name_up)) {
134                         *a_enc = gv_default_aliases[i].encoding;
135                         status = CR_OK;
136                         break;
137                 }
138         }
139 
140         return status;
141 }
142 
143 /**
144  * cr_enc_handler_convert_input:
145  *@a_this: the current instance of #CREncHandler.
146  *@a_in: the input buffer to convert.
147  *@a_in_len: in/out parameter. The len of the input
148  *buffer to convert. After return, contains the number of
149  *bytes actually consumed.
150  *@a_out: output parameter. The converted output buffer.
151  *Must be freed by the buffer.
152  *@a_out_len: output parameter. The length of the output buffer.
153  *
154  *Converts a raw input buffer into an utf8 buffer.
155  *
156  *Returns CR_OK upon successfull completion, an error code otherwise.
157  */
158 enum CRStatus
cr_enc_handler_convert_input(CREncHandler * a_this,const guchar * a_in,gulong * a_in_len,guchar ** a_out,gulong * a_out_len)159 cr_enc_handler_convert_input (CREncHandler * a_this,
160                               const guchar * a_in,
161                               gulong * a_in_len,
162                               guchar ** a_out, gulong * a_out_len)
163 {
164         enum CRStatus status = CR_OK;
165 
166         g_return_val_if_fail (a_this && a_in && a_in_len && a_out,
167                               CR_BAD_PARAM_ERROR);
168 
169         if (a_this->decode_input == NULL)
170                 return CR_OK;
171 
172         if (a_this->enc_str_len_as_utf8) {
173                 status = a_this->enc_str_len_as_utf8 (a_in,
174                                                       &a_in[*a_in_len - 1],
175                                                       a_out_len);
176 
177                 g_return_val_if_fail (status == CR_OK, status);
178         } else {
179                 *a_out_len = *a_in_len;
180         }
181 
182         *a_out = g_malloc0 (*a_out_len);
183 
184         status = a_this->decode_input (a_in, a_in_len, *a_out, a_out_len);
185 
186         if (status != CR_OK) {
187                 g_free (*a_out);
188                 *a_out = NULL;
189         }
190 
191         g_return_val_if_fail (status == CR_OK, status);
192 
193         return CR_OK;
194 }
195