| 19 | */ |
| 20 | |
| 21 | int b64_encode(const unsigned char* aInput, int aInputLen, unsigned char* aOutput, int aOutputLen) |
| 22 | { |
| 23 | // Work out if we've got enough space to encode the input |
| 24 | // Every 6 bits of input becomes a byte of output |
| 25 | if (aOutputLen < (aInputLen*8)/6) |
| 26 | { |
| 27 | // FIXME Should we return an error here, or just the length |
| 28 | return (aInputLen*8)/6; |
| 29 | } |
| 30 | |
| 31 | // If we get here we've got enough space to do the encoding |
| 32 | |
| 33 | const char* b64_dictionary = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; |
| 34 | if (aInputLen == 3) |
| 35 | { |
| 36 | aOutput[0] = b64_dictionary[aInput[0] >> 2]; |
| 37 | aOutput[1] = b64_dictionary[(aInput[0] & 0x3)<<4|(aInput[1]>>4)]; |
| 38 | aOutput[2] = b64_dictionary[(aInput[1]&0x0F)<<2|(aInput[2]>>6)]; |
| 39 | aOutput[3] = b64_dictionary[aInput[2]&0x3F]; |
| 40 | } |
| 41 | else if (aInputLen == 2) |
| 42 | { |
| 43 | aOutput[0] = b64_dictionary[aInput[0] >> 2]; |
| 44 | aOutput[1] = b64_dictionary[(aInput[0] & 0x3)<<4|(aInput[1]>>4)]; |
| 45 | aOutput[2] = b64_dictionary[(aInput[1]&0x0F)<<2]; |
| 46 | aOutput[3] = '='; |
| 47 | } |
| 48 | else if (aInputLen == 1) |
| 49 | { |
| 50 | aOutput[0] = b64_dictionary[aInput[0] >> 2]; |
| 51 | aOutput[1] = b64_dictionary[(aInput[0] & 0x3)<<4]; |
| 52 | aOutput[2] = '='; |
| 53 | aOutput[3] = '='; |
| 54 | } |
| 55 | else |
| 56 | { |
| 57 | // Break the input into 3-byte chunks and process each of them |
| 58 | int i; |
| 59 | for (i = 0; i < aInputLen/3; i++) |
| 60 | { |
| 61 | b64_encode(&aInput[i*3], 3, &aOutput[i*4], 4); |
| 62 | } |
| 63 | if (aInputLen % 3 > 0) |
| 64 | { |
| 65 | // It doesn't fit neatly into a 3-byte chunk, so process what's left |
| 66 | b64_encode(&aInput[i*3], aInputLen % 3, &aOutput[i*4], aOutputLen - (i*4)); |
| 67 | } |
| 68 | } |
| 69 | } |
| 70 | |