/**************************************************************************************************************************** cencode.c - c source to a base64 encoding algorithm implementation This is part of the libb64 project, and has been placed in the public domain. For details, see http://sourceforge.net/projects/libb64 For W5500 LwIP Ethernet in ESP32 (ESP32 + W5500) AsyncWebServer_ESP32_W5500 is a library for the LwIP Ethernet W5500 in ESP32 to run AsyncWebServer Based on and modified from ESPAsyncWebServer (https://github.com/me-no-dev/ESPAsyncWebServer) Built by Khoi Hoang https://github.com/khoih-prog/AsyncWebServer_ESP32_W5500 Licensed under GPLv3 license *****************************************************************************************************************************/ #include "cencode.h" const int CHARS_PER_LINE = 72; ///////////////////////////////////////////////// void base64_init_encodestate(base64_encodestate* state_in) { state_in->step = step_A; state_in->result = 0; state_in->stepcount = 0; } ///////////////////////////////////////////////// char base64_encode_value(char value_in) { static const char* encoding = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; if (value_in > 63) return '='; return encoding[(unsigned int)value_in]; } ///////////////////////////////////////////////// int base64_encode_block(const char* plaintext_in, int length_in, char* code_out, base64_encodestate* state_in) { const char* plainchar = plaintext_in; const char* const plaintextend = plaintext_in + length_in; char* codechar = code_out; char result; char fragment; result = state_in->result; switch (state_in->step) { while (1) { case step_A: if (plainchar == plaintextend) { state_in->result = result; state_in->step = step_A; return codechar - code_out; } fragment = *plainchar++; result = (fragment & 0x0fc) >> 2; *codechar++ = base64_encode_value(result); result = (fragment & 0x003) << 4; // fall through case step_B: if (plainchar == plaintextend) { state_in->result = result; state_in->step = step_B; return codechar - code_out; } fragment = *plainchar++; result |= (fragment & 0x0f0) >> 4; *codechar++ = base64_encode_value(result); result = (fragment & 0x00f) << 2; // fall through case step_C: if (plainchar == plaintextend) { state_in->result = result; state_in->step = step_C; return codechar - code_out; } fragment = *plainchar++; result |= (fragment & 0x0c0) >> 6; *codechar++ = base64_encode_value(result); result = (fragment & 0x03f) >> 0; *codechar++ = base64_encode_value(result); ++(state_in->stepcount); if (state_in->stepcount == CHARS_PER_LINE / 4) { *codechar++ = '\n'; state_in->stepcount = 0; } // fall through } } /* control should not reach here */ return codechar - code_out; } ///////////////////////////////////////////////// int base64_encode_blockend(char* code_out, base64_encodestate* state_in) { char* codechar = code_out; switch (state_in->step) { case step_B: *codechar++ = base64_encode_value(state_in->result); *codechar++ = '='; *codechar++ = '='; break; case step_C: *codechar++ = base64_encode_value(state_in->result); *codechar++ = '='; break; case step_A: break; } *codechar = 0x00; return codechar - code_out; } ///////////////////////////////////////////////// int base64_encode_chars(const char* plaintext_in, int length_in, char* code_out) { base64_encodestate _state; base64_init_encodestate(&_state); int len = base64_encode_block(plaintext_in, length_in, code_out, &_state); return len + base64_encode_blockend((code_out + len), &_state); }