base64_encode.c 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. /*
  2. * Copyright (C) 2009 by Thermotemp GmbH. All rights reserved.
  3. *
  4. * Redistribution and use in source and binary forms, with or without
  5. * modification, are permitted provided that the following conditions
  6. * are met:
  7. *
  8. * 1. Redistributions of source code must retain the above copyright
  9. * notice, this list of conditions and the following disclaimer.
  10. * 2. Redistributions in binary form must reproduce the above copyright
  11. * notice, this list of conditions and the following disclaimer in the
  12. * documentation and/or other materials provided with the distribution.
  13. * 3. Neither the name of the copyright holders nor the names of
  14. * contributors may be used to endorse or promote products derived
  15. * from this software without specific prior written permission.
  16. *
  17. * THIS SOFTWARE IS PROVIDED BY THERMOTEMP GMBH AND CONTRIBUTORS
  18. * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  19. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  20. * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THERMOTEMP
  21. * GMBH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  22. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  23. * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
  24. * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
  25. * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  26. * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
  27. * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  28. * SUCH DAMAGE.
  29. *
  30. * For additional information see http://www.ethernut.de/
  31. */
  32. /*!
  33. * \file gorp/base64/base64_encode.c
  34. * \brief Base64 encoder.
  35. *
  36. * \verbatim
  37. *
  38. * $Log$
  39. * Revision 1.3 2009/03/08 20:18:37 haraldkipp
  40. * Replaced inttypes.h by stdint.h.
  41. *
  42. * Revision 1.2 2009/03/06 23:51:37 olereinhardt
  43. * Fixed minor compile bugs
  44. *
  45. * Revision 1.1 2009/03/06 17:46:21 olereinhardt
  46. * Initial checkin, base64 encoding and decoding routines
  47. *
  48. *
  49. * \endverbatim
  50. */
  51. #include <stdint.h>
  52. #include <string.h>
  53. #include <sys/heap.h>
  54. #include <sys/types.h>
  55. /*!
  56. * \addtogroup xgBase64
  57. */
  58. /*@{*/
  59. static const char base64etab[65] PROGMEM = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
  60. /*!
  61. * \brief Do base-64 encoding on a string.
  62. *
  63. * Return newly allocated string filled with the bytes generated.
  64. * The encoded size will be at least 4/3 the size of the text, and
  65. * may be smaller larger if there needs to be some padding characters
  66. * (blanks, newlines).
  67. *
  68. * \param str Points to the string to be encoded.
  69. * \return Newly allocated string containing the encoded data. Must be freed later
  70. */
  71. char *NutEncodeBase64(const char* str)
  72. {
  73. char *encoded;
  74. size_t length;
  75. size_t encoded_length;
  76. int idx, enc_pos;
  77. int32_t bits;
  78. int cols;
  79. int char_count;
  80. /* Calculate buffer size for encoded data
  81. * 8 Bit code converted into 6 Bit code ==> encoded code will be 4/3 larger
  82. * The algorithm will padd the encoded data with == so that the resulting
  83. * length can be exactly deviced by 3
  84. * Also every 72 chars a <cr><lf> will be added
  85. */
  86. length = strlen(str);
  87. /* Calc the base code length, add one to the inital length to have space for rounding errors */
  88. encoded_length = ((length + 1) * 4) / 3;
  89. /* Add the size for the padding characters */
  90. encoded_length += encoded_length % 3;
  91. /* Now add the space for the inserted <cr><lf> characters and add one byte for the end of string NUL character*/
  92. encoded_length += (encoded_length / 72) * 2 + 3;
  93. /* Allocate the memory. */;
  94. encoded = NutHeapAlloc(encoded_length);
  95. if (encoded == NULL) return NULL;
  96. enc_pos = 0;
  97. char_count = 0;
  98. bits = 0;
  99. cols = 0;
  100. for (idx = 0; idx < length; idx ++) {
  101. bits += (int32_t)str[idx];
  102. char_count ++;
  103. if (char_count == 3) {
  104. encoded[enc_pos++] = PRG_RDB(&base64etab[(bits >> 18) & 0x3f]);
  105. encoded[enc_pos++] = PRG_RDB(&base64etab[(bits >> 12) & 0x3f]);
  106. encoded[enc_pos++] = PRG_RDB(&base64etab[(bits >> 6) & 0x3f]);
  107. encoded[enc_pos++] = PRG_RDB(&base64etab[bits & 0x3f]);
  108. cols += 4;
  109. if (cols == 72) {
  110. encoded[enc_pos++] = '\r';
  111. encoded[enc_pos++] = '\n';
  112. cols =0;
  113. }
  114. bits = 0;
  115. char_count = 0;
  116. } else {
  117. bits <<= 8;
  118. }
  119. }
  120. if (char_count != 0) {
  121. bits <<= 16 - (8 * char_count);
  122. encoded[enc_pos++] = PRG_RDB(&base64etab[bits >> 18]);
  123. encoded[enc_pos++] = PRG_RDB(&base64etab[(bits >> 12) & 0x3f]);
  124. if (char_count == 1) {
  125. encoded[enc_pos++] = '=';
  126. encoded[enc_pos++] = '=';
  127. } else {
  128. encoded[enc_pos++] = PRG_RDB(&base64etab[(bits >> 6) & 0x3f]);
  129. encoded[enc_pos++] = '=';
  130. }
  131. }
  132. encoded[enc_pos] = '\0';
  133. return encoded;
  134. }
  135. /*@}*/