ua_base64.c 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. /*
  2. begin library headers
  3. */
  4. /*
  5. cdecode.h - c header for a base64 decoding algorithm
  6. This is part of the libb64 project, and has been placed in the public domain.
  7. For details, see http://sourceforge.net/projects/libb64
  8. */
  9. #ifndef BASE64_CDECODE_H
  10. #define BASE64_CDECODE_H
  11. typedef enum
  12. {
  13. step_a, step_b, step_c, step_d
  14. } base64_decodestep;
  15. typedef struct
  16. {
  17. base64_decodestep step;
  18. char plainchar;
  19. } base64_decodestate;
  20. void base64_init_decodestate(base64_decodestate* state_in);
  21. int base64_decode_value(char value_in);
  22. int base64_decode_block(const char* code_in, const int length_in, char* plaintext_out, base64_decodestate* state_in);
  23. #endif /* BASE64_CDECODE_H */
  24. /*
  25. end library headers
  26. */
  27. #include "ua_base64.h"
  28. UA_Int32 UA_base64_getDecodedSize(UA_String* const base64EncodedData){
  29. //note that base64-encoded data length is always divisible by 4
  30. UA_Int32 temp = base64EncodedData->length * 3 / 4;
  31. //subtract padding
  32. if(base64EncodedData->data[base64EncodedData->length-1] == '=') {
  33. temp--;
  34. if(base64EncodedData->data[base64EncodedData->length-2] == '=') {
  35. temp--;
  36. }
  37. }
  38. return temp;
  39. }
  40. UA_Int32 UA_base64_decode(UA_String* const base64EncodedData, UA_Byte* target){
  41. if(target == UA_NULL){
  42. return UA_ERROR;
  43. }
  44. base64_decodestate state;
  45. base64_init_decodestate(&state);
  46. base64_decode_block((char*)(base64EncodedData->data), base64EncodedData->length, (char*)target, &state);
  47. return UA_NO_ERROR;
  48. }
  49. /*
  50. begin library code
  51. */
  52. /*
  53. cdecoder.c - c source to a base64 decoding algorithm implementation
  54. This is part of the libb64 project, and has been placed in the public domain.
  55. For details, see http://sourceforge.net/projects/libb64
  56. */
  57. int base64_decode_value(char value_in)
  58. {
  59. static const char decoding[] = {62,-1,-1,-1,63,52,53,54,55,56,57,58,59,60,61,-1,-1,-1,-2,-1,-1,-1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,-1,-1,-1,-1,-1,-1,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51};
  60. static const char decoding_size = sizeof(decoding);
  61. value_in -= 43;
  62. if (value_in > decoding_size) return -1;
  63. return decoding[(int)value_in];
  64. }
  65. void base64_init_decodestate(base64_decodestate* state_in)
  66. {
  67. state_in->step = step_a;
  68. state_in->plainchar = 0;
  69. }
  70. int base64_decode_block(const char* code_in, const int length_in, char* plaintext_out, base64_decodestate* state_in)
  71. {
  72. const char* codechar = code_in;
  73. char* plainchar = plaintext_out;
  74. signed char fragment;
  75. *plainchar = state_in->plainchar;
  76. switch (state_in->step)
  77. {
  78. while (1)
  79. {
  80. case step_a:
  81. do {
  82. if (codechar == code_in+length_in)
  83. {
  84. state_in->step = step_a;
  85. state_in->plainchar = *plainchar;
  86. return plainchar - plaintext_out;
  87. }
  88. fragment = (char)base64_decode_value(*codechar++);
  89. } while (fragment < 0);
  90. *plainchar = (fragment & 0x03f) << 2;
  91. case step_b:
  92. do {
  93. if (codechar == code_in+length_in)
  94. {
  95. state_in->step = step_b;
  96. state_in->plainchar = *plainchar;
  97. return plainchar - plaintext_out;
  98. }
  99. fragment = (char)base64_decode_value(*codechar++);
  100. } while (fragment < 0);
  101. *plainchar++ |= (fragment & 0x030) >> 4;
  102. *plainchar = (fragment & 0x00f) << 4;
  103. case step_c:
  104. do {
  105. if (codechar == code_in+length_in)
  106. {
  107. state_in->step = step_c;
  108. state_in->plainchar = *plainchar;
  109. return plainchar - plaintext_out;
  110. }
  111. fragment = (char)base64_decode_value(*codechar++);
  112. } while (fragment < 0);
  113. *plainchar++ |= (fragment & 0x03c) >> 2;
  114. *plainchar = (fragment & 0x003) << 6;
  115. case step_d:
  116. do {
  117. if (codechar == code_in+length_in)
  118. {
  119. state_in->step = step_d;
  120. state_in->plainchar = *plainchar;
  121. return plainchar - plaintext_out;
  122. }
  123. fragment = (char)base64_decode_value(*codechar++);
  124. } while (fragment < 0);
  125. *plainchar++ |= (fragment & 0x03f);
  126. }
  127. }
  128. /* control should not reach here */
  129. return plainchar - plaintext_out;
  130. }