|
| 1 | +/* |
| 2 | +cdecoder.c - c source to a base64 decoding algorithm implementation |
| 3 | +
|
| 4 | +This is part of the libb64 project, and has been placed in the public domain. |
| 5 | +For details, see http://sourceforge.net/projects/libb64 |
| 6 | +*/ |
| 7 | + |
| 8 | +#include "cdecode.h" |
| 9 | + |
| 10 | +int base64_decode_value(char value_in){ |
| 11 | + 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}; |
| 12 | + static const char decoding_size = sizeof(decoding); |
| 13 | + value_in -= 43; |
| 14 | + if (value_in < 0 || value_in > decoding_size) return -1; |
| 15 | + return decoding[(int)value_in]; |
| 16 | +} |
| 17 | + |
| 18 | +void base64_init_decodestate(base64_decodestate* state_in){ |
| 19 | + state_in->step = step_a; |
| 20 | + state_in->plainchar = 0; |
| 21 | +} |
| 22 | + |
| 23 | +int base64_decode_block(const char* code_in, const int length_in, char* plaintext_out, base64_decodestate* state_in){ |
| 24 | + const char* codechar = code_in; |
| 25 | + char* plainchar = plaintext_out; |
| 26 | + char fragment; |
| 27 | + |
| 28 | + *plainchar = state_in->plainchar; |
| 29 | + |
| 30 | + switch (state_in->step){ |
| 31 | + while (1){ |
| 32 | + case step_a: |
| 33 | + do { |
| 34 | + if (codechar == code_in+length_in){ |
| 35 | + state_in->step = step_a; |
| 36 | + state_in->plainchar = *plainchar; |
| 37 | + return plainchar - plaintext_out; |
| 38 | + } |
| 39 | + fragment = (char)base64_decode_value(*codechar++); |
| 40 | + } while (fragment < 0); |
| 41 | + *plainchar = (fragment & 0x03f) << 2; |
| 42 | + case step_b: |
| 43 | + do { |
| 44 | + if (codechar == code_in+length_in){ |
| 45 | + state_in->step = step_b; |
| 46 | + state_in->plainchar = *plainchar; |
| 47 | + return plainchar - plaintext_out; |
| 48 | + } |
| 49 | + fragment = (char)base64_decode_value(*codechar++); |
| 50 | + } while (fragment < 0); |
| 51 | + *plainchar++ |= (fragment & 0x030) >> 4; |
| 52 | + *plainchar = (fragment & 0x00f) << 4; |
| 53 | + case step_c: |
| 54 | + do { |
| 55 | + if (codechar == code_in+length_in){ |
| 56 | + state_in->step = step_c; |
| 57 | + state_in->plainchar = *plainchar; |
| 58 | + return plainchar - plaintext_out; |
| 59 | + } |
| 60 | + fragment = (char)base64_decode_value(*codechar++); |
| 61 | + } while (fragment < 0); |
| 62 | + *plainchar++ |= (fragment & 0x03c) >> 2; |
| 63 | + *plainchar = (fragment & 0x003) << 6; |
| 64 | + case step_d: |
| 65 | + do { |
| 66 | + if (codechar == code_in+length_in){ |
| 67 | + state_in->step = step_d; |
| 68 | + state_in->plainchar = *plainchar; |
| 69 | + return plainchar - plaintext_out; |
| 70 | + } |
| 71 | + fragment = (char)base64_decode_value(*codechar++); |
| 72 | + } while (fragment < 0); |
| 73 | + *plainchar++ |= (fragment & 0x03f); |
| 74 | + } |
| 75 | + } |
| 76 | + /* control should not reach here */ |
| 77 | + return plainchar - plaintext_out; |
| 78 | +} |
| 79 | + |
| 80 | +int base64_decode_chars(const char* code_in, const int length_in, char* plaintext_out){ |
| 81 | + base64_decodestate _state; |
| 82 | + base64_init_decodestate(&_state); |
| 83 | + int len = base64_decode_block(code_in, length_in, plaintext_out, &_state); |
| 84 | + if(len > 0) plaintext_out[len] = 0; |
| 85 | + return len; |
| 86 | +} |
0 commit comments