1 /***  Extension-formats
2  *
3  *    This file adds the following file format support to SQLite.
4  *
5  *    Plist      - An XML like encoding
6  *    Base64     - Standard binary to text conversion
7  *
8  *    Compile using:
9  *
10  *       gcc -g -fPIC -shared extension-formats.c -o libsqlite-formats.so
11  */
12 
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <string.h>
16 #include <ctype.h>
17 #include <stdint.h>
18 #include <time.h>
19 #include <assert.h>
20 
21 #define COMPILE_SQLITE_EXTENSIONS_AS_LOADABLE_MODULE 1
22 #include "sqlite3ext.h"
23 SQLITE_EXTENSION_INIT1
24 
25 #define INDENT_INCREMENT 4
26 
27 #define ERROR_NONE                   0
28 #define ERROR_INSUFFICIENT_MEMORY    1
29 #define ERROR_INVALID_HEADER         2
30 #define ERROR_INVALID_TRAILER        3
31 #define ERROR_INVALID_OFFSET         4
32 #define ERROR_INVALID_OBJECT_LENGTH  5
33 #define ERROR_INVALID_REFERENCE      6
34 #define ERROR_INVALID_CHARACTER      7
35 
36 typedef struct KEY {
37   struct OBJECT *key;
38   struct OBJECT *value;
39 } KEY;
40 
41 typedef struct OBJECT {
42   int type;
43   int length;
44   union {
45     time_t date;
46     double real;
47     long integer;
48     unsigned long uid;
49     unsigned char binary[1];
50     char text[1];
51     short int utf16[1];
52     int refs[1];
53     KEY keys[1];
54     struct OBJECT *objects[1];
55   } data;
56 } OBJECT;
57 
58 typedef struct CONFIG {
59   int bytesPerOffset;
60   int bytesPerReference;
61   int objectCount;
62   int rootObjectReference;
63   int offsetTableOffset;
64   size_t bufferLength;
65   size_t outputBufferLength;
66   size_t outputBufferIn;
67   long *offsetTable;
68   unsigned char *buffer;
69   unsigned char *outputBuffer;
70 } CONFIG;
71 
72 int createObject(int type, int length, int extra, OBJECT **ptr2);
73 int readObject(CONFIG *cfg, long offset, OBJECT **ptr2);
74 
75 static int indent = 2;
76 
outputText(CONFIG * cfg,const char * text)77 int outputText(CONFIG *cfg, const char *text)
78 {
79   size_t textLength = strlen(text);
80   size_t availableSpace = cfg->outputBufferLength - cfg->outputBufferIn;
81   while (textLength >= availableSpace) {
82     unsigned char *tmp = cfg->outputBuffer;
83     cfg->outputBufferLength += textLength + 1024;
84     cfg->outputBuffer = (unsigned char *)realloc(cfg->outputBuffer, cfg->outputBufferLength);
85     if (cfg->outputBuffer == NULL) {
86       if (tmp != NULL)
87         free(tmp);
88       return ERROR_INSUFFICIENT_MEMORY;
89     }
90     availableSpace = cfg->outputBufferLength - cfg->outputBufferIn;
91   }
92   strcpy((char *)(cfg->outputBuffer+cfg->outputBufferIn), text);
93   cfg->outputBufferIn += textLength;
94   return ERROR_NONE;
95 }
96 
printWithIndent(CONFIG * cfg,const char * text,int newline)97 int printWithIndent(CONFIG *cfg, const char *text, int newline)
98 {
99   int err = ERROR_NONE;
100   char spaces[9] = "        ";
101   int n = indent;
102   while ((n > 8) && (err == ERROR_NONE)) {
103     err = outputText(cfg, spaces);
104     n -= 8;
105   }
106   if ((n > 0) && (err == ERROR_NONE))
107     err = outputText(cfg, spaces + 8 - n);
108   if (err == ERROR_NONE)
109     err = outputText(cfg, text);
110   if (newline && (err == ERROR_NONE))
111     err = outputText(cfg, "\n");
112   return err;
113 }
114 
readHeader(CONFIG * cfg)115 int readHeader(CONFIG *cfg)
116 {
117   if ((cfg->bufferLength < 40) ||
118       (strncmp((const char *)(cfg->buffer), "bplist0", 7) != 0) ||
119       ((cfg->buffer[7] != '0') && (cfg->buffer[7] != '1')))
120     return ERROR_INVALID_HEADER;
121   return ERROR_NONE;
122 }
123 
readTrailer(CONFIG * cfg)124 int readTrailer(CONFIG *cfg)
125 {
126   int i, j;
127   int objectCount = 0;
128   int rootObjectReference = 0;
129   int offsetTableOffset = 0;
130   unsigned char *ptr;
131   unsigned char *buffer = cfg->buffer + cfg->bufferLength - 32;
132 
133   //  Extract the relevant fields
134   for (i=12; i < 16; i++)
135     objectCount = (objectCount << 8) + buffer[i];
136   for (i=20; i < 24; i++)
137     rootObjectReference = (rootObjectReference << 8) + buffer[i];
138   for (i=28; i < 32; i++)
139     offsetTableOffset = (offsetTableOffset << 8) + buffer[i];
140 
141   //  Populate the configurartion structure
142   cfg->bytesPerOffset = buffer[6];
143   cfg->bytesPerReference = buffer[7];
144   cfg->objectCount = objectCount;
145   cfg->rootObjectReference = rootObjectReference;
146   cfg->offsetTableOffset = offsetTableOffset;
147   cfg->offsetTable = (long *)malloc((size_t)objectCount * sizeof(long));
148   if (cfg->offsetTable == NULL)
149     return ERROR_INSUFFICIENT_MEMORY;
150   ptr = cfg->buffer + offsetTableOffset;
151   for (i=0; i < objectCount; i++) {
152     long n = 0;
153     for (j=0; j < cfg->bytesPerOffset; j++)
154        n = (n << 8) | *(ptr++);
155     cfg->offsetTable[i] = n;
156   }
157   return ERROR_NONE;
158 }
159 
createObject(int type,int length,int extra,OBJECT ** ptr2)160 int createObject(int type, int length, int extra, OBJECT **ptr2)
161 {
162   *ptr2 = NULL;
163   OBJECT *ptr = (OBJECT *)malloc(sizeof(OBJECT) + (size_t)extra);
164   if (ptr == NULL)
165     return ERROR_INSUFFICIENT_MEMORY;
166   ptr->type = type;
167   ptr->length = length;
168   *ptr2 = ptr;
169   return ERROR_NONE;
170 }
171 
readInteger(unsigned char * ptr,int desc)172 long readInteger(unsigned char *ptr, int desc)
173 {
174   long value = 0L;
175   int n = 1 << (desc & 0x03);
176   while (n--)
177     value = (value << 8) | (long)(*(ptr++));
178   return value;
179 }
180 
readUid(unsigned char * ptr,int desc)181 unsigned long readUid(unsigned char *ptr, int desc)
182 {
183   unsigned long value = 0L;
184   int n = 1 << (desc & 0x03);
185   while (n--)
186     value = (value << 8) | (unsigned long)(*(ptr++));
187   return value;
188 }
189 
readDouble(unsigned char * ptr,int desc)190 double readDouble(unsigned char *ptr, int desc)
191 {
192   union {
193     double v;
194     float f[2];
195     unsigned char b[8];
196   } value;
197   int n = 1 << (desc & 0x03);
198   for (int i=0; i < n; i++)
199     value.b[7-i] = *(ptr++);
200   if (n == 4)
201     value.v = (double)(value.f[1]);
202   return value.v;
203 }
204 
readArray(CONFIG * cfg,unsigned char * ptr,int type,int length,OBJECT ** array2)205 int readArray(CONFIG *cfg, unsigned char *ptr, int type, int length, OBJECT **array2)
206 {
207   int i;
208   long offset;
209   OBJECT *array;
210   int err = createObject(type, length, ((length-1) * (int)sizeof(OBJECT)), &array);
211   *array2 = NULL;
212   for (i=0; (i < length) && (err == ERROR_NONE); i++) {
213     offset = 0L;
214     for (int j=0; j < cfg->bytesPerReference; j++)
215       offset = (offset << 8) | (long)(*(ptr++));
216     if (offset >= cfg->objectCount)
217       return ERROR_INVALID_REFERENCE;
218     offset = cfg->offsetTable[offset];
219     err = readObject(cfg, offset, &(array->data.objects[i]));
220   }
221   if (err == ERROR_NONE)
222     *array2 = array;
223   return err;
224 }
225 
readDictionary(CONFIG * cfg,unsigned char * ptr,int type,int length,OBJECT ** dict2)226 int readDictionary(CONFIG *cfg, unsigned char *ptr, int type, int length, OBJECT **dict2)
227 {
228   int i;
229   long offset;
230   OBJECT *dict;
231   int err  = createObject(type, length, ((length-1) * (int)sizeof(KEY)), &dict);
232   *dict2 = NULL;
233   if (err != ERROR_NONE)
234     return err;
235   for (i=0; (i < length) && (err == ERROR_NONE); i++) {
236     offset = 0L;
237     for (int j=0; j < cfg->bytesPerReference; j++)
238       offset = (offset << 8) | (long)(*(ptr++));
239     if (offset >= cfg->objectCount)
240       return ERROR_INVALID_REFERENCE;
241     offset = cfg->offsetTable[offset];
242     err = readObject(cfg, offset, &(dict->data.keys[i].key));
243   }
244   for (i=0; (i < length) && (err == ERROR_NONE); i++) {
245     offset = 0L;
246     for (int j=0; j < cfg->bytesPerReference; j++)
247       offset = (offset << 8) | (long)(*(ptr++));
248     if (offset >= cfg->objectCount)
249       return ERROR_INVALID_REFERENCE;
250     offset = cfg->offsetTable[offset];
251     err = readObject(cfg, offset, &(dict->data.keys[i].value));
252   }
253   if (err == ERROR_NONE)
254     *dict2 = dict;
255   return err;
256 }
257 
readObject(CONFIG * cfg,long offset,OBJECT ** ptr2)258 int readObject(CONFIG *cfg, long offset, OBJECT **ptr2)
259 {
260   int i;
261   int length;
262   int type;
263   int err = ERROR_NONE;
264   OBJECT *obj;
265   unsigned char *ptr;
266 
267   *ptr2 = NULL;
268   if ((size_t)offset >= cfg->bufferLength)
269     return ERROR_INVALID_OFFSET;
270   ptr = cfg->buffer + offset;
271   type = *(ptr++);
272   length = (type & 0x0F);
273   type >>= 4;
274   if ((type != 0) && (length == 0x0F)) {
275     length = *(ptr++);
276     if ((length >> 4) != 0x01)
277       return ERROR_INVALID_OBJECT_LENGTH;
278     i = (int)readInteger(ptr, length);
279     ptr += (1 << (length & 0x03));
280     length = i;
281   }
282   switch (type) {
283     case 0x00:               //  Singleton
284               err = createObject(type, length, 5, &obj);
285               if (err != ERROR_NONE)
286                 return err;
287               switch(length) {
288                 case 0:             //  NULL
289                        strcpy(obj->data.text, "<Null/>");
290                        break;
291                 case 8:             //  False
292                        strcpy(obj->data.text, "<False/>");
293                        break;
294                 case 9:             //  True
295                        strcpy(obj->data.text, "<True/>");
296                        break;
297                 case 15:             //  Fill
298                        strcpy(obj->data.text, "<Fill/>");
299                        break;
300                 default:             //  Illegal
301                        strcpy(obj->data.text, "***Error***");
302                        break;
303               }
304               break;
305     case 0x01:               //  Integer
306               err = createObject(type, length, 0, &obj);
307               if (err != ERROR_NONE)
308                 return err;
309               obj->data.integer = readInteger(ptr, length);
310               break;
311     case 0x02:               //  Float
312               err = createObject(type, length, 0, &obj);
313               if (err != ERROR_NONE)
314                 return err;
315               obj->data.real = readDouble(ptr, length);
316               break;
317     case 0x03:               //  Date in Elapsed seconds
318               err = createObject(type, length, 0, &obj);
319               if (err != ERROR_NONE)
320                 return err;
321               obj->data.date = (time_t)readDouble(ptr, length);
322               break;
323     case 0x04:               //  binary data
324               err = createObject(type, length, length, &obj);
325               if (err != ERROR_NONE)
326                 return err;
327               for (i=0; i < length; i++)
328                 obj->data.binary[i] = *(ptr++);
329               break;
330     case 0x05:               //  ASCII string
331               err = createObject(type, length, length, &obj);
332               if (err != ERROR_NONE)
333                 return err;
334               for (i=0; i < length; i++)
335                 obj->data.text[i] = (char)*(ptr++);
336               obj->data.text[length] = '\0';
337               break;
338     case 0x06:               //  UTF16 string
339               err = createObject(type, length, 2 * length, &obj);
340               if (err != ERROR_NONE)
341                 return err;
342               for (i=0; i < length; i++) {
343                 short int d = *(ptr++);
344                 obj->data.utf16[i] = (short int)((d << 8) | *(ptr++));
345               }
346               obj->data.utf16[length] = '\0';
347               break;
348     case 0x08:               //  UID
349               err = createObject(type, length, 0, &obj);
350               if (err != ERROR_NONE)
351                 return err;
352               obj->data.uid = readUid(ptr, length);
353               break;
354     case 0x0A:               //  Array
355               err = readArray(cfg, ptr, type, length, &obj);
356               break;
357     case 0x0D:               //  Dictionary
358               err = readDictionary(cfg, ptr, type, length, &obj);
359               break;
360     default:
361               fprintf(stderr, "Unknown object type: %d\n", type);
362               err = createObject(type, length, 0, &obj);
363               break;
364   }
365   if (err == ERROR_NONE)
366     *ptr2 = obj;
367   return err;
368 }
369 
displayHex(CONFIG * cfg,int data)370 void displayHex(CONFIG *cfg, int data)
371 {
372   static int in = 0;
373   static char buffer[76];
374   static long offset = 0L;
375   static char hex[] = "0123456789ABCDEF";
376   char *tmp;
377 
378   //  If -ve then flush buffer
379   if (data < 0) {
380     if (in > 0) {
381       tmp = buffer + in * 3 + 8 + 2 * (in / 8);
382       while (tmp < buffer+59)
383         *(tmp++) = ' ';
384       buffer[in+59] = '\0';
385       printWithIndent(cfg, buffer, 1);
386     }
387     offset = 0L;
388     in = 0;
389     return;
390   }
391 
392   //  If start of line add offset
393   if (in == 0) {
394     sprintf((char *)buffer, "%06lX  ", offset);
395     offset += 16;
396     buffer[8] = '\0';
397   }
398 
399   //  Add Byte in hex
400   tmp = buffer + in * 3 + 8 + 2 * (in / 8);
401   *(tmp++) = hex[(data >> 4) & 0x0F];
402   *(tmp++) = hex[data & 0x0F];
403   *(tmp++) = ' ';
404 
405   //  Add to character buffer
406   buffer[in+59] = (char)data;
407 
408   //  Check if midpoint of buffer
409   if (++in == 8) {
410     *(tmp++) = '-';
411     *(tmp++) = ' ';
412   }
413 
414   //  Check if buffer full
415   if (in == 16) {
416     buffer[75] = '\0';
417     printWithIndent(cfg, buffer, 1);
418     in = 0;
419   }
420   return;
421 }
422 
displayObject(CONFIG * cfg,OBJECT * obj,int raw)423 int displayObject(CONFIG *cfg, OBJECT *obj, int raw)
424 {
425   char text[32];
426   switch (obj->type) {
427     case 0x00:                 //  Singleton
428               printWithIndent(cfg, obj->data.text, 1);
429               break;
430     case 0x01:                 //  Integer
431               if (raw == 0)
432                 printWithIndent(cfg, "<number>", 0);
433               sprintf(text, "%ld", obj->data.integer);
434               outputText(cfg, text);
435               if (raw == 0)
436                 outputText(cfg, "</number>\n");
437               break;
438     case 0x02:                 //  Float
439               if (raw == 0)
440                 printWithIndent(cfg, "<float>", 0);
441               sprintf(text, "%f", obj->data.real);
442               outputText(cfg, text);
443               if (raw == 0)
444                 outputText(cfg, "</float>\n");
445               break;
446     case 0x03:                 //  Date
447               if (raw == 0)
448                 printWithIndent(cfg, "<date>", 0);
449               outputText(cfg, ctime(&(obj->data.date)));
450               if (raw == 0)
451                 outputText(cfg, "</date>\n");
452               break;
453     case 0x04:                 //  Binary data
454               if (raw == 0)
455                 printWithIndent(cfg, "<data>", 1);
456               indent += INDENT_INCREMENT;
457               for (int i=0; i < obj->length; i++)
458                 displayHex(cfg, obj->data.binary[i]);
459               displayHex(cfg, -1);
460               indent -= INDENT_INCREMENT;
461               if (raw == 0)
462                 printWithIndent(cfg, "</data>", 1);
463               break;
464     case 0x05:                 //  String
465               if (raw == 0)
466                 printWithIndent(cfg, "<string>", 0);
467               outputText(cfg, (obj->data.text));
468               if (raw == 0)
469                 outputText(cfg, "</string>\n");
470               break;
471     case 0x06:                 //  UTF16 string
472               if (raw == 0)
473                 printWithIndent(cfg, "<utf16>", 1);
474               indent += INDENT_INCREMENT;
475               for (int i=0; i < obj->length; i++)
476                 displayHex(cfg, obj->data.binary[i]);
477               displayHex(cfg, -1);
478               indent -= INDENT_INCREMENT;
479               if (raw == 0)
480                 printWithIndent(cfg, "</utf16>", 1);
481               break;
482     case 0x08:                 //  UID
483               if (raw == 0)
484                 printWithIndent(cfg, "<uid>", 0);
485               sprintf(text, "%lu", obj->data.uid);
486               outputText(cfg, text);
487               if (raw == 0)
488                 outputText(cfg, "</uid>\n");
489               break;
490     case 0x0A:                 //  Array
491               printWithIndent(cfg, "<array>", 1);
492               indent += INDENT_INCREMENT;
493               for (int i=0; i < obj->length; i++)
494                 displayObject(cfg, obj->data.objects[i], 0);
495               indent -= INDENT_INCREMENT;
496               printWithIndent(cfg, "</array>", 1);
497               break;
498     case 0x0D:                 //  Dictionary
499               printWithIndent(cfg, "<dict>", 1);
500               indent += INDENT_INCREMENT;
501               for (int i=0; i < obj->length; i++) {
502                 printWithIndent(cfg, "<key>", 0);
503                 displayObject(cfg, obj->data.keys[i].key, 1);
504                 outputText(cfg, "</key>\n");
505                 displayObject(cfg, obj->data.keys[i].value, 0);
506               }
507               indent -= INDENT_INCREMENT;
508               printWithIndent(cfg, "</dict>", 1);
509               break;
510     default:
511               sprintf(text, "Cannot display type: %d\n", obj->type);
512               outputText(cfg, text);
513               break;
514   }
515   return ERROR_NONE;
516 }
517 
releaseObject(OBJECT * obj)518 int releaseObject(OBJECT *obj)
519 {
520   int i;
521   switch (obj->type) {
522     case 0x00:                        //  Singleton
523     case 0x01:                        //  Int
524     case 0x02:                        //  Float
525     case 0x03:                        //  Date
526     case 0x04:                        //  Binary
527     case 0x05:                        //  ASCII
528     case 0x06:                        //  UTF16
529     case 0x08:                        //  UID
530               break;
531     case 0x0A:                        //  Array
532               for (i=0; i < obj->length; i++)
533                 releaseObject(obj->data.objects[i]);
534               break;
535     case 0x0D:                        //  Dictionary
536               for (i=0; i < obj->length; i++) {
537                 releaseObject(obj->data.keys[i].key);
538                 releaseObject(obj->data.keys[i].value);
539               }
540               break;
541   }
542   free(obj);
543   return ERROR_NONE;
544 }
545 
parsePlist(char ** result,const char * data,int dataLength)546 int parsePlist(char **result, const char *data, int dataLength)
547 {
548   CONFIG cfg;
549   char   *ptr;
550   OBJECT *obj;
551   int err = ERROR_NONE;
552   int version;
553   long offset;
554   long length;
555   char text[32];
556 
557   //  Determine the file size and save
558   cfg.buffer = (unsigned char *)data;
559   cfg.bufferLength = dataLength;
560 
561   //  Preset the output buffer
562   cfg.outputBufferLength = 0;
563   cfg.outputBufferIn  = 0;
564   cfg.outputBuffer = NULL;
565 
566   //  Read the header
567   err = readHeader(&cfg);
568   if (err != ERROR_NONE)
569     return err;
570   version = (int)(cfg.buffer[7] - '0');
571 
572   //  Read the trailer
573   err = readTrailer(&cfg);
574   if (err != ERROR_NONE)
575     return err; //  ERROR_INVALID_TRAILER;
576 
577   //  Locate and read the root object
578   offset = cfg.offsetTable[cfg.rootObjectReference];
579   err = readObject(&cfg, offset, &obj);
580 
581   //  If no error display the root object and hence the whole object tree
582   if (err != ERROR_NONE)
583     return err;
584 
585   sprintf(text, "<plist version = \"1.%d\">\n", version);
586   outputText(&cfg, text);
587   displayObject(&cfg, obj, 0);
588   outputText(&cfg, "</plist>\n");
589 
590   //  Create return data
591   length = strlen((const char *)(cfg.outputBuffer));
592   ptr = malloc(length + 1);
593   *result = ptr;
594   if (ptr != NULL) {
595     for (int i=0; i < length; i++)
596       *(ptr++) = cfg.outputBuffer[i];
597     *ptr = '\0';
598   }
599   else
600     err = ERROR_INSUFFICIENT_MEMORY;
601 
602   //  Release assigned memory
603   releaseObject(obj);
604   free(cfg.offsetTable);
605   free(cfg.outputBuffer);
606   return err;
607 }
608 
609 static char map[64] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
610 
611 /**  Encode Base64
612  *
613  */
614 
encodeBase64(char ** result,const unsigned char * data,int dataLength)615 int encodeBase64(char **result, const unsigned char *data, int dataLength)
616 {
617   unsigned char d;
618   int b;
619   int bitsLeft = 0;
620   int in = 0;
621   int out = 0;
622   int encodedLength = dataLength * 4 / 3 + 4;
623   char *encoded = malloc(encodedLength);
624   *result = encoded;
625   if (encoded == NULL)
626     return ERROR_INSUFFICIENT_MEMORY;
627 
628   while (out < dataLength) {
629     d = data[out++];
630     switch (bitsLeft) {
631       case 0:
632              encoded[in++] = map[d >> 2];
633              b = d & 0x03;
634              bitsLeft = 2;
635              break;
636       case 2:
637              b = (b << 8) | d;
638              encoded[in++] = map[b >> 4];
639              b &= 0x0F;
640              bitsLeft = 4;
641              break;
642       case 4:
643              b = (b << 8) | d;
644              encoded[in++] = map[b >> 6];
645              encoded[in++] = map[b & 0x03F];
646              bitsLeft = 0;
647              break;
648     }
649   }
650 
651   /*  Flush remaining bits  */
652   switch (bitsLeft) {
653     case 2:
654            encoded[in++] = map[b << 4];
655            encoded[in++] = '=';
656            encoded[in++] = '=';
657            break;
658     case 4:
659            encoded[in++] = map[b << 2];
660            encoded[in++] = '=';
661            break;
662     default:
663            break;
664   }
665 
666   /*  Terminate as string  */
667   encoded[in] = '\0';
668   return ERROR_NONE;
669 }
670 
671 static unsigned char unmap[256] = { 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 00 - 07
672                                     0x81, 0x80, 0x81, 0x80, 0x80, 0x81, 0x80, 0x80, // 08 - 0F
673                                     0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 10 - 17
674                                     0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 18 - 1F
675                                     0x80, 0x81, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 20 - 27
676                                     0x80, 0x80, 0x80, 0x3E, 0x80, 0x80, 0x80, 0x3F, // 28 - 2F
677                                     0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, // 30 - 37
678                                     0x3C, 0x3D, 0x80, 0x80, 0x80, 0x40, 0x80, 0x80, // 38 - 3F
679                                     0x80, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, // 40 - 47
680                                     0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, // 48 - 4F
681                                     0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, // 50 - 57
682                                     0x17, 0x18, 0x19, 0x80, 0x80, 0x80, 0x80, 0x80, // 58 - 5F
683                                     0x80, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, // 60 - 67
684                                     0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, // 68 - 6F
685                                     0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, // 70 - 77
686                                     0x31, 0x32, 0x33, 0x80, 0x80, 0x80, 0x80, 0x80, // 78 - 7F
687                                     0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 80 - 87
688                                     0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 88 - 8F
689                                     0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 90 - 97
690                                     0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 98 - 9F
691                                     0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // A0 - A7
692                                     0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // A8 - AF
693                                     0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // B0 - B7
694                                     0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // B8 - BF
695                                     0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // C0 - C7
696                                     0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // C8 - CF
697                                     0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // D0 - D7
698                                     0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // D8 - DF
699                                     0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // E0 - E7
700                                     0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // E8 - EF
701                                     0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // F0 - F7
702                                     0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // F8 - FF
703 };
704 
705 /***  decodeBase64
706  *
707  *    Returns decoded data and length.
708  */
709 
decodeBase64(unsigned char ** result,int * resultLength,const char * data,int dataLength)710 int decodeBase64(unsigned char **result, int *resultLength, const char *data, int dataLength)
711 {
712   int bitsLeft = 8;
713   int in = 0;
714   unsigned char b;
715   unsigned char d;
716   unsigned char *decoded = malloc(dataLength * 3 / 4 + 3);
717   *result = decoded;
718   *resultLength = 0;
719   if (decoded == NULL)
720     return ERROR_INSUFFICIENT_MEMORY;
721 
722   while (*data != '\0') {
723     //  Get character and check valid
724     d = unmap[*(data++)];
725     if (d > 0x3F) {
726       if (d == 0x80) {
727         free(decoded);
728         return ERROR_INVALID_CHARACTER;
729       }
730       break;                  //  padding space
731     }
732 
733     switch (bitsLeft) {
734       case 8:
735              decoded[in] = d;
736              bitsLeft = 2;
737              break;
738       case 2:
739              decoded[in] = (decoded[in] << 2) | (d >> 4);
740              decoded[++in] = d & 0x0F;
741              bitsLeft = 4;
742              break;
743       case 4:
744              decoded[in] = (decoded[in] << 4) | (d >> 2);
745              decoded[++in] = d & 0x03;
746              bitsLeft = 6;
747              break;
748       case 6:
749              decoded[in] = (decoded[in] << 6) | d;
750              in++;
751              bitsLeft = 8;
752              break;
753     }
754   }
755   *resultLength = in;
756   return ERROR_NONE;
757 }
758 
759 /**  Wrapper functions
760  *
761  */
762 
freeResult(void * ptr)763 void freeResult(void *ptr)
764 {
765   if (ptr != NULL)
766     free(ptr);
767   return;
768 }
769 
plistFunc(sqlite3_context * context,int argc,sqlite3_value ** argv)770 static void plistFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
771   int resultLength;
772   int errorCode = 0;
773   char *result = NULL;
774   assert( argc==1 );
775   switch( sqlite3_value_type(argv[0]) ){
776     case SQLITE_TEXT:
777     case SQLITE_BLOB: {
778       const char *data = sqlite3_value_text(argv[0]);
779       const int dataLength = sqlite3_value_bytes(argv[0]);
780       errorCode = parsePlist(&result, data, dataLength);
781       if (errorCode == ERROR_NONE) {
782         resultLength = strlen(result);
783         sqlite3_result_text(context, result, resultLength, &freeResult);
784       } else {
785         if (sqlite3_value_type(argv[0]) == SQLITE_TEXT)
786           sqlite3_result_text(context, data, dataLength, NULL);
787         else
788           sqlite3_result_blob(context, data, dataLength, NULL);
789       }
790       break;
791     }
792     default: {
793       sqlite3_result_null(context);
794       break;
795     }
796   }
797 }
798 
encodeBase64Func(sqlite3_context * context,int argc,sqlite3_value ** argv)799 static void encodeBase64Func(sqlite3_context *context, int argc, sqlite3_value **argv){
800   int resultLength;
801   int errorCode = 0;
802   int dataLength;
803   const unsigned char *data;
804   char *result = NULL;
805   assert( argc==1 );
806   switch( sqlite3_value_type(argv[0]) ){
807     case SQLITE_BLOB:
808       data = sqlite3_value_blob(argv[0]);
809       dataLength = sqlite3_value_bytes(argv[0]);
810       errorCode = encodeBase64(&result, data, dataLength);
811       if (errorCode == ERROR_NONE) {
812         resultLength = strlen(result);
813         sqlite3_result_text(context, result, resultLength, &freeResult);
814       } else {
815         sqlite3_result_blob(context, data, dataLength, NULL);
816       }
817       break;
818     case SQLITE_TEXT: {
819       data = sqlite3_value_text(argv[0]);
820       dataLength = sqlite3_value_bytes(argv[0]);
821       sqlite3_result_text(context, data, dataLength, NULL);
822       errorCode = encodeBase64(&result, data, dataLength);
823       if (errorCode == ERROR_NONE) {
824         resultLength = strlen(result);
825         sqlite3_result_text(context, result, resultLength, &freeResult);
826       } else {
827         sqlite3_result_text(context, data, dataLength, NULL);
828       }
829       break;
830     }
831     default: {
832       sqlite3_result_null(context);
833       break;
834     }
835   }
836 }
837 
838 
839 /***  isText
840  *
841  *    Returns zero if supplied data is entirely
842  *    ASCII printable characters or white space.
843  */
844 
isText(unsigned char * data,int dataLength)845 int isText(unsigned char *data, int dataLength)
846 {
847   static unsigned char map[256] = {
848     1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1,
849     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
850     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
851     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
852     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
853     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
854     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
855     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
856     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
857     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
858     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
859     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
860     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
861     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
862     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
863     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
864   };
865   int result = 0;
866   for (int i=0; i < dataLength; i++)
867     result |= map[*(data++)];
868   return result;
869 }
870 
871 /**  isUTF8
872  *
873  *   Returns one if the characters conform to UTF8 format in so
874  *   far as all the byte lengths are consistent. It does not
875  *   check for overlong encodings or invalid characters. A zero
876  *   is returned if the format is not consistent.
877  *   Note that a file of all zeros will be returned as UTF8.
878  */
879 
isUTF8(unsigned char * data,int length)880 int isUTF8(unsigned char *data, int length)
881 {
882   int count = 0;
883   while (length-- > 0) {
884     unsigned char d = *(data++);
885     switch (count) {
886       case 0:                           /*  First character  */
887              if ((d & 0x80) == 0)
888                continue;                   /*  7 bit ASCII  */
889              if ((d & 0xE0) == 0xC0) {
890                count = 1;                  /*  2 byte code  */
891                break;
892              }
893              if ((d & 0xF0) == 0xE0) {
894                count = 2;                  /*  3 byte code  */
895                break;
896              }
897              if ((d & 0xF8) == 0xF0) {
898                count = 3;                  /*  4 byte code  */
899                break;
900              }
901              return 0;
902        default:
903              count--;
904              if ((d & 0xC0) != 0x80)
905                return 0;
906              break;
907     }
908   }
909   return (count == 0) ? 1 : 0;
910 }
911 
decodeBase64Func(sqlite3_context * context,int argc,sqlite3_value ** argv)912 static void decodeBase64Func(sqlite3_context *context, int argc, sqlite3_value **argv){
913   int resultLength;
914   int errorCode = 0;
915   unsigned char *result = NULL;
916   assert( argc==1 );
917   switch( sqlite3_value_type(argv[0]) ){
918     case SQLITE_BLOB:
919     case SQLITE_TEXT: {
920       const char *data = sqlite3_value_text(argv[0]);
921       int dataLength = sqlite3_value_bytes(argv[0]);
922       errorCode = decodeBase64(&result, &resultLength, data, dataLength);
923       if (errorCode == ERROR_NONE) {
924         if (isUTF8(result, resultLength))
925           sqlite3_result_text(context,  result, resultLength, &freeResult);
926         else
927           sqlite3_result_blob(context,  result, resultLength, &freeResult);
928       } else {
929         if (sqlite3_value_type(argv[0]) == SQLITE_TEXT)
930           sqlite3_result_text(context, data, dataLength, NULL);
931         else
932           sqlite3_result_blob(context, data, dataLength, NULL);
933       }
934       break;
935     }
936     default: {
937       sqlite3_result_null(context);
938       break;
939     }
940   }
941 }
942 
943 /**  RegisterExtensionFormats
944  *
945  *   Register the parsing functions with sqlite
946  */
947 
RegisterExtensionFormats(sqlite3 * db)948 int RegisterExtensionFormats(sqlite3 *db)
949 {
950   sqlite3_create_function(db, "plist", 1, 0, db, plistFunc, 0, 0);
951   sqlite3_create_function(db, "unBase64", 1, 0, db, decodeBase64Func, 0, 0);
952   sqlite3_create_function(db, "toBase64", 1, 0, db, encodeBase64Func, 0, 0);
953 }
954 
955 #ifdef COMPILE_SQLITE_EXTENSIONS_AS_LOADABLE_MODULE
956 
957 #ifdef _WIN32
958 __declspec(dllexport)
959 #endif
960 
sqlite3_extension_init(sqlite3 * db,char ** pzErrMsg,const sqlite3_api_routines * pApi)961 int sqlite3_extension_init(sqlite3 *db, char **pzErrMsg, const sqlite3_api_routines *pApi)
962 {
963   int rc = SQLITE_OK;
964   SQLITE_EXTENSION_INIT2(pApi);
965   RegisterExtensionFormats(db);
966   return rc;
967 }
968 
969 #endif
970 
971 
972