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