]> arthur.barton.de Git - ngircd-alex.git/blob - src/ngircd/conn-encoding.c
Remove imp.h and exp.h header files
[ngircd-alex.git] / src / ngircd / conn-encoding.c
1 /*
2  * ngIRCd -- The Next Generation IRC Daemon
3  * Copyright (c)2001-2012 Alexander Barton (alex@barton.de) and Contributors.
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  * Please read the file COPYING, README and AUTHORS for more information.
10  */
11
12 #define __conn_encoding_c__
13
14 #define CONN_MODULE
15
16 #include "portab.h"
17
18 /**
19  * @file
20  * Functions to deal with character encodings and conversions
21  */
22
23 #include <assert.h>
24 #include <stdio.h>
25 #include <string.h>
26
27 #include "defines.h"
28 #include "conn.h"
29 #include "log.h"
30
31 #include "conn-encoding.h"
32
33 #ifdef ICONV
34
35 char Encoding_Buffer[COMMAND_LEN];
36
37 char *Convert_Message PARAMS((iconv_t Handle, char *Message));
38
39 /**
40  * Set client character encoding on a connection.
41  *
42  * @param Conn Connection identifier.
43  * @param ClientEnc Client encoding (for example "ASCII", "MacRoman", ...).
44  * @return true on success, false otherwise.
45  */
46 GLOBAL bool
47 Conn_SetEncoding(CONN_ID Conn, const char *ClientEnc)
48 {
49         char client_enc[25], server_enc[25];
50
51         assert(Conn > NONE);
52         assert(ClientEnc != NULL);
53
54         Conn_UnsetEncoding(Conn);
55
56         /* Is the client character set identical to server character set? */
57         if (strcasecmp(ClientEnc, "UTF-8") == 0)
58                 return true;
59
60         snprintf(client_enc, sizeof(client_enc), "%s//TRANSLIT", ClientEnc);
61         snprintf(server_enc, sizeof(server_enc), "%s//TRANSLIT", "UTF-8");
62
63         My_Connections[Conn].iconv_from = iconv_open(server_enc, client_enc);
64         if (My_Connections[Conn].iconv_from == (iconv_t)(-1)) {
65                 Conn_UnsetEncoding(Conn);
66                 return false;
67         }
68         My_Connections[Conn].iconv_to = iconv_open(client_enc, server_enc);
69         if (My_Connections[Conn].iconv_to == (iconv_t)(-1)) {
70                 Conn_UnsetEncoding(Conn);
71                 return false;
72         }
73
74         LogDebug("Set client character set of connection \"%d\" to \"%s\".",
75                  Conn, client_enc);
76         return true;
77 }
78
79 /**
80  * Remove client character encoding conversion on a connection.
81  *
82  * @param Conn Connection identifier.
83  */
84 GLOBAL void
85 Conn_UnsetEncoding(CONN_ID Conn)
86 {
87         assert(Conn > NONE);
88
89         if (My_Connections[Conn].iconv_from != (iconv_t)(-1))
90                 iconv_close(My_Connections[Conn].iconv_from);
91         if (My_Connections[Conn].iconv_to != (iconv_t)(-1))
92                 iconv_close(My_Connections[Conn].iconv_to);
93
94         My_Connections[Conn].iconv_from = (iconv_t)(-1);
95         My_Connections[Conn].iconv_to = (iconv_t)(-1);
96
97         LogDebug("Unset character conversion of connection %d.", Conn);
98 }
99
100 /**
101  * Convert the encoding of a given message.
102  *
103  * This function uses a static buffer for the result of the encoding
104  * conversion which is overwritten by subsequent calls to this function!
105  *
106  * @param Handle libiconv handle.
107  * @param Message The message to convert.
108  * @return Pointer to the result.
109  */
110 char *
111 Convert_Message(iconv_t Handle, char *Message)
112 {
113         size_t in_left, out_left;
114         char *out = Encoding_Buffer;
115
116         assert (Handle != (iconv_t)(-1));
117         assert (Message != NULL);
118
119         in_left = strlen(Message);
120         out_left = sizeof(Encoding_Buffer) - 1;
121
122         if (iconv(Handle, &Message, &in_left, &out, &out_left) == (size_t)(-1)) {
123                 /* An error occurred! */
124                 LogDebug("Error converting message encoding!");
125                 strlcpy(out, Message, sizeof(Encoding_Buffer));
126                 iconv(Handle, NULL, NULL, NULL, NULL);
127         } else
128                 *out = '\0';
129
130         return Encoding_Buffer;
131 }
132
133 #endif /* ICONV */
134
135 /**
136  * Convert encoding of a message received from a connection.
137  *
138  * Note 1: If no conversion is required, this function returns the original
139  * pointer to the message.
140  *
141  * Note 2: This function uses Convert_Message(), so subsequent calls to this
142  * function will overwrite the earlier results.
143  *
144  * @param Conn Connection identifier.
145  * @param Message The message to convert.
146  * @return Pointer to the result.
147  * @see Convert_Message
148  */
149 GLOBAL char *
150 Conn_EncodingFrom(UNUSED CONN_ID Conn, char *Message)
151 {
152         assert(Conn > NONE);
153         assert (Message != NULL);
154
155 #ifdef ICONV
156         if (My_Connections[Conn].iconv_from != (iconv_t)(-1))
157                 return Convert_Message(My_Connections[Conn].iconv_from, Message);
158 #endif
159         return Message;
160 }
161
162 /**
163  * Convert encoding of a message for sending on a connection.
164  *
165  * Note 1: If no conversion is required, this function returns the original
166  * pointer to the message.
167  *
168  * Note 2: This function uses Convert_Message(), so subsequent calls to this
169  * function will overwrite the earlier results.
170  *
171  * @param Conn Connection identifier.
172  * @param Message The message to convert.
173  * @return Pointer to the result.
174  * @see Convert_Message
175  */
176 GLOBAL char *
177 Conn_EncodingTo(UNUSED CONN_ID Conn, char *Message)
178 {
179         assert(Conn > NONE);
180         assert (Message != NULL);
181
182 #ifdef ICONV
183         if (My_Connections[Conn].iconv_to != (iconv_t)(-1))
184                 return Convert_Message(My_Connections[Conn].iconv_to, Message);
185 #endif
186         return Message;
187 }
188
189 /* -eof- */