iconv.c 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. /*
  2. * OpenConnect (SSL + DTLS) VPN client
  3. *
  4. * Copyright © 2008-2015 Intel Corporation.
  5. *
  6. * Author: David Woodhouse <dwmw2@infradead.org>
  7. *
  8. * This program is free software; you can redistribute it and/or
  9. * modify it under the terms of the GNU Lesser General Public License
  10. * version 2.1, as published by the Free Software Foundation.
  11. *
  12. * This program is distributed in the hope that it will be useful, but
  13. * WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  15. * Lesser General Public License for more details.
  16. */
  17. #include <config.h>
  18. #include "openconnect-internal.h"
  19. #include <iconv.h>
  20. #include <errno.h>
  21. #include <string.h>
  22. static char *convert_str(struct openconnect_info *vpninfo, iconv_t ic,
  23. char *instr)
  24. {
  25. ICONV_CONST char *ic_in;
  26. char *ic_out, *outstr;
  27. size_t insize, outsize;
  28. int addq = 0;
  29. if (ic == (iconv_t)-1)
  30. return instr;
  31. iconv(ic, NULL, NULL, NULL, NULL);
  32. insize = strlen(instr) + 1;
  33. ic_in = instr;
  34. outsize = insize;
  35. ic_out = outstr = malloc(outsize);
  36. if (!outstr)
  37. return instr;
  38. while (insize) {
  39. if (iconv(ic, &ic_in, &insize, &ic_out, &outsize) == (size_t)-1) {
  40. if (errno == EILSEQ) {
  41. do {
  42. ic_in++;
  43. insize--;
  44. } while (insize && (ic_in[0] & 0xc0) == 0x80);
  45. addq = 1;
  46. }
  47. if (!outsize || errno == E2BIG) {
  48. int outlen = ic_out - outstr;
  49. realloc_inplace(outstr, outlen + 10);
  50. if (!outstr)
  51. return instr;
  52. ic_out = outstr + outlen;
  53. outsize = 10;
  54. } else if (errno != EILSEQ) {
  55. /* Should never happen */
  56. free(outstr);
  57. return instr;
  58. }
  59. if (addq) {
  60. addq = 0;
  61. *(ic_out++) = '?';
  62. outsize--;
  63. }
  64. }
  65. }
  66. return outstr;
  67. }
  68. char *openconnect_legacy_to_utf8(struct openconnect_info *vpninfo,
  69. const char *legacy)
  70. {
  71. return convert_str(vpninfo, vpninfo->ic_legacy_to_utf8, (char *)legacy);
  72. }
  73. char *openconnect_utf8_to_legacy(struct openconnect_info *vpninfo,
  74. const char *utf8)
  75. {
  76. return convert_str(vpninfo, vpninfo->ic_utf8_to_legacy, (char *)utf8);
  77. }