summaryrefslogtreecommitdiff
path: root/src/svg/base64.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/svg/base64.c')
-rw-r--r--src/svg/base64.c231
1 files changed, 231 insertions, 0 deletions
diff --git a/src/svg/base64.c b/src/svg/base64.c
new file mode 100644
index 0000000..c01b130
--- /dev/null
+++ b/src/svg/base64.c
@@ -0,0 +1,231 @@
+/***********************************************************************
+===============
+BASE64 Encoding
+===============
+Available on: http://freecode-freecode.blogspot.com/2008/02/base64c.html
+Last access in: November, 10th 2009.
+************************************************************************/
+
+#include "stdio.h"
+#include "stdlib.h"
+#include "string.h"
+#include "base64.h"
+
+/**
+ * characters used for Base64 encoding
+ */
+const char *BASE64_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+/**
+ * encode three bytes using base64 (RFC 3548)
+ *
+ * @param triple three bytes that should be encoded
+ * @param result buffer of four characters where the result is stored
+ */
+void _base64_encode_triple(unsigned char triple[3], char result[4])
+{
+ int tripleValue, i;
+
+ tripleValue = triple[0];
+ tripleValue *= 256;
+ tripleValue += triple[1];
+ tripleValue *= 256;
+ tripleValue += triple[2];
+
+ for (i=0; i<4; i++)
+ {
+ result[3-i] = BASE64_CHARS[tripleValue%64];
+ tripleValue /= 64;
+ }
+}
+
+/**
+ * encode an array of bytes using Base64 (RFC 3548)
+ *
+ * @param source the source buffer
+ * @param sourcelen the length of the source buffer
+ * @param target the target buffer
+ * @param targetlen the length of the target buffer
+ * @return 1 on success, 0 otherwise
+ */
+int base64_encode(unsigned char *source, int sourcelen, char *target, int targetlen)
+{
+ /* check if the result will fit in the target buffer */
+ if ((sourcelen+2)/3*4 > targetlen-1)
+ return 0;
+
+ /* encode all full triples */
+ while (sourcelen >= 3)
+ {
+ _base64_encode_triple(source, target);
+ sourcelen -= 3;
+ source += 3;
+ target += 4;
+ }
+
+ /* encode the last one or two characters */
+ if (sourcelen > 0)
+ {
+ unsigned char temp[3];
+ memset(temp, 0, sizeof(temp));
+ memcpy(temp, source, sourcelen);
+ _base64_encode_triple(temp, target);
+ target[3] = '=';
+
+ if (sourcelen == 1)
+ target[2] = '=';
+
+ target += 4;
+ }
+
+ /* terminate the string */
+ target[0] = 0;
+
+ return 1;
+}
+
+/**
+ * determine the value of a base64 encoding character
+ *
+ * @param base64char the character of which the value is searched
+ * @return the value in case of success (0-63), -1 on failure
+ */
+int _base64_char_value(char base64char)
+{
+ if (base64char >= 'A' && base64char <= 'Z')
+ return base64char-'A';
+
+ if (base64char >= 'a' && base64char <= 'z')
+ return base64char-'a'+26;
+
+ if (base64char >= '0' && base64char <= '9')
+ return base64char-'0'+2*26;
+
+ if (base64char == '+')
+ return 2*26+10;
+
+ if (base64char == '/')
+ return 2*26+11;
+
+ return -1;
+}
+
+/**
+ * decode a 4 char base64 encoded byte triple
+ *
+ * @param quadruple the 4 characters that should be decoded
+ * @param result the decoded data
+ * @return lenth of the result (1, 2 or 3), 0 on failure
+ */
+int _base64_decode_triple(char quadruple[4], unsigned char *result)
+{
+ int i, triple_value, bytes_to_decode = 3, only_equals_yet = 1;
+ int char_value[4];
+
+ for (i=0; i<4; i++)
+ char_value[i] = _base64_char_value(quadruple[i]);
+
+ /* check if the characters are valid */
+ for (i=3; i>=0; i--)
+ {
+ if (char_value[i]<0)
+ {
+ if (only_equals_yet && quadruple[i]=='=')
+ {
+ /* we will ignore this character anyway, make it something
+ * that does not break our calculations */
+
+ char_value[i]=0;
+ bytes_to_decode--;
+ continue;
+ }
+ return 0;
+ }
+
+ /* after we got a real character, no other '=' are allowed anymore */
+ only_equals_yet = 0;
+ }
+
+ /* if we got "====" as input, bytes_to_decode is -1 */
+ if (bytes_to_decode < 0)
+ bytes_to_decode = 0;
+
+ /* make one big value out of the partial values */
+ triple_value = char_value[0];
+ triple_value *= 64;
+ triple_value += char_value[1];
+ triple_value *= 64;
+ triple_value += char_value[2];
+ triple_value *= 64;
+ triple_value += char_value[3];
+
+ /* break the big value into bytes */
+ for (i=bytes_to_decode; i<3; i++)
+ triple_value /= 256;
+
+ for (i=bytes_to_decode-1; i>=0; i--)
+ {
+ result[i] = triple_value%256;
+ triple_value /= 256;
+ }
+
+ return bytes_to_decode;
+}
+
+/**
+ * decode base64 encoded data
+ *
+ * @param source the encoded data (zero terminated)
+ * @param target pointer to the target buffer
+ * @param targetlen length of the target buffer
+ * @return length of converted data on success, -1 otherwise
+ */
+int base64_decode(char *source, unsigned char *target, int targetlen)
+{
+ char *src, *tmpptr;
+ char quadruple[4], tmpresult[3];
+ int i, tmplen = 3;
+ int converted = 0;
+
+ /* concatenate '===' to the source to handle unpadded base64 data */
+ src = (char *)malloc(strlen(source)+5);
+ if (src == NULL)
+ return -1;
+
+ strcpy(src, source);
+ strcat(src, "====");
+ tmpptr = src;
+
+ /* convert as long as we get a full result */
+ while (tmplen == 3)
+ {
+ /* get 4 characters to convert */
+ for (i=0; i<4; i++)
+ {
+ /* skip invalid characters - we won't reach the end */
+ while (*tmpptr != '=' && _base64_char_value(*tmpptr)<0)
+ tmpptr++;
+
+ quadruple[i] = *(tmpptr++);
+ }
+
+ /* convert the characters */
+ tmplen = _base64_decode_triple(quadruple, (unsigned char*)tmpresult);
+
+ /* check if the fit in the result buffer */
+ if (targetlen < tmplen)
+ {
+ free(src);
+ return -1;
+ }
+
+ /* put the partial result in the result buffer */
+ memcpy(target, tmpresult, tmplen);
+ target += tmplen;
+ targetlen -= tmplen;
+ converted += tmplen;
+ }
+
+ free(src);
+ return converted;
+}