conn-encoding.c 4.8 KB

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