[xml] Patch for base64Binary datatype.



This is my first time playing with the libxml2 codebase, so I hope I
didn't violate any rules or overlook something obvious. Here is a
patch to support base64Binary datatypes:

$ cvs diff -u xmlschemastypes.c
Index: xmlschemastypes.c
===================================================================
RCS file: /cvs/gnome/gnome-xml/xmlschemastypes.c,v
retrieving revision 1.43
diff -u -r1.43 xmlschemastypes.c
--- xmlschemastypes.c   8 Aug 2003 14:00:27 -0000       1.43
+++ xmlschemastypes.c   27 Aug 2003 04:13:35 -0000
@@ -83,7 +83,8 @@
     XML_SCHEMAS_USHORT,
     XML_SCHEMAS_BYTE,
     XML_SCHEMAS_UBYTE,
-    XML_SCHEMAS_HEXBINARY
+    XML_SCHEMAS_HEXBINARY,
+    XML_SCHEMAS_BASE64BINARY
 } xmlSchemaValType;
 
 static unsigned long powten[10] = {
@@ -141,6 +142,13 @@
     unsigned int total;
 };
 
+typedef struct _xmlSchemaValBase64 xmlSchemaValBase64;
+typedef xmlSchemaValBase64 *xmlSchemaValBase64Ptr;
+struct _xmlSchemaValBase64 {
+    xmlChar     *str;
+    unsigned int total;
+};
+
 struct _xmlSchemaVal {
     xmlSchemaValType type;
     union {
@@ -149,6 +157,7 @@
         xmlSchemaValDuration    dur;
        xmlSchemaValQName       qname;
        xmlSchemaValHex         hex;
+       xmlSchemaValBase64      base64;
        float                   f;
        double                  d;
        int                     b;
@@ -179,6 +188,7 @@
 static xmlSchemaTypePtr xmlSchemaTypeBooleanDef = NULL;
 static xmlSchemaTypePtr xmlSchemaTypeDoubleDef = NULL;
 static xmlSchemaTypePtr xmlSchemaTypeHexBinaryDef = NULL;
+static xmlSchemaTypePtr xmlSchemaTypeBase64BinaryDef = NULL;
 static xmlSchemaTypePtr xmlSchemaTypeAnyURIDef = NULL;
 
 /*
@@ -290,6 +300,8 @@
                                                     XML_SCHEMAS_ANYURI);
     xmlSchemaTypeHexBinaryDef = xmlSchemaInitBasicType("hexBinary",
                                                      XML_SCHEMAS_HEXBINARY);
+    xmlSchemaTypeBase64BinaryDef
+        = xmlSchemaInitBasicType("base64Binary", XML_SCHEMAS_BASE64BINARY);
 
     /*
      * derived datatypes
@@ -425,6 +437,10 @@
            if (value->value.hex.str != NULL)
                xmlFree(value->value.hex.str);
            break;
+        case XML_SCHEMAS_BASE64BINARY:
+           if (value->value.base64.str != NULL)
+               xmlFree(value->value.base64.str);
+           break;
        default:
            break;
     }
@@ -795,6 +811,25 @@
     return 0;
 }
 
+/**
+ * _xmlSchemaBase64Decode:
+ * @ch: a character
+ *
+ * Converts a base64 encoded character to its base 64 value.
+ *
+ * Returns 0-63 (value), 64 (pad), or -1 (not recognized)
+ */
+static int
+_xmlSchemaBase64Decode (const xmlChar ch) {
+    if (('A' <= ch) && (ch <= 'Z')) return ch - 'A';
+    if (('a' <= ch) && (ch <= 'z')) return ch - 'a' + 26;
+    if (('0' <= ch) && (ch <= '9')) return ch - '0' + 52;
+    if ('+' == ch) return 62;
+    if ('/' == ch) return 63;
+    if ('=' == ch) return 64;
+    return -1;
+}
+
 /****************************************************************
  *                                                             *
  *     XML Schema Dates/Times Datatypes Handling               *
@@ -1976,6 +2011,127 @@
             }
            goto return0;
         }
+        case XML_SCHEMAS_BASE64BINARY: {
+        /* ISSUE:
+
+           Ignore all stray characters? (yes, currently)
+           Worry about long lines? (no, currently)
+
+           rfc2045.txt:
+
+           "The encoded output stream must be represented in lines of
+           no more than 76 characters each.  All line breaks or other
+           characters not found in Table 1 must be ignored by decoding
+           software.  In base64 data, characters other than those in
+           Table 1, line breaks, and other white space probably
+           indicate a transmission error, about which a warning
+           message or even a message rejection might be appropriate
+           under some circumstances." */
+        const xmlChar *cur=value;
+           xmlChar *base;
+        int total, i=0, pad=0;
+
+        if (cur == NULL)
+            goto return1;
+            
+        for (; *cur; ++cur) {
+            int val=_xmlSchemaBase64Decode (*cur);
+            if (val<0)
+                ;
+            else if (val<64)
+                i++;
+            else
+                break;
+        }
+        for (; *cur; ++cur) {
+            int val=_xmlSchemaBase64Decode (*cur);
+            if (val<0)
+                ;
+            else if (val<64)
+                goto return1;
+            if (val==64)
+                pad++;
+        }
+
+        /* rfc2045.txt: "Special processing is performed if fewer than
+           24 bits are available at the end of the data being encoded.
+           A full encoding quantum is always completed at the end of a
+           body.  When fewer than 24 input bits are available in an
+           input group, zero bits are added (on the right) to form an
+           integral number of 6-bit groups.  Padding at the end of the
+           data is performed using the "=" character.  Since all
+           base64 input is an integral number of octets, only the
+           following cases can arise: (1) the final quantum of
+           encoding input is an integral multiple of 24 bits; here,
+           the final unit of encoded output will be an integral
+           multiple of 4 characters with no "=" padding, (2) the final
+           quantum of encoding input is exactly 8 bits; here, the
+           final unit of encoded output will be two characters
+           followed by two "=" padding characters, or (3) the final
+           quantum of encoding input is exactly 16 bits; here, the
+           final unit of encoded output will be three characters
+           followed by one "=" padding character." */
+        
+        total = 3*(i/4);
+        if (pad==0) {
+            if (i%4!=0)
+                goto return1;
+        }
+        else if (pad==1) {
+            int val;
+            if (i%4!=3)
+                goto return1;
+            for (val=_xmlSchemaBase64Decode(*cur);
+                 (val<0) || (val>63);
+                 val=_xmlSchemaBase64Decode(*cur))
+                --cur;
+            /* 16bits in 24bits means 2 pad bits: nnnnnn nnmmmm mmmm00 */
+            /* 00111100 -> 0x3c */
+            if (val & ~0x3c)
+                goto return1;
+            total+=2;
+        }
+        else if (pad==2) {
+            int val;
+            if (i%4!=2)
+                goto return1;
+            for (val=_xmlSchemaBase64Decode(*cur);
+                 (val<0) || (val>63);
+                 val=_xmlSchemaBase64Decode(*cur))
+                --cur;
+            /* 8bits in 12bits means 4 pad bits: nnnnnn nn0000 */
+            /* 00110000 -> 0x30 */
+            if (val & ~0x30)
+                goto return1;
+            total+=1;
+        }
+        else
+            goto return1;
+
+           if (val != NULL) {
+               v = xmlSchemaNewValue(XML_SCHEMAS_BASE64BINARY);
+               if (v == NULL)
+                goto error;
+            base = (xmlChar *) xmlMallocAtomic((i + pad +1) * sizeof(xmlChar));
+            if (base == NULL) {
+                xmlGenericError(xmlGenericErrorContext,
+                                "malloc of %ld byte failed\n",
+                                (i + pad + 1) * (long)sizeof(xmlChar));
+                xmlFree(v);
+                goto return1;
+               }
+               v->value.base64.str = base;
+            for (cur=value; *cur; ++cur)
+                if (_xmlSchemaBase64Decode(*cur) >= 0) {
+                    *base=*cur;
+                    ++base;
+                }
+            *base=0;
+            v->value.base64.total = total;
+            *val = v;
+        }
+           goto return0;
+        }
         case XML_SCHEMAS_INTEGER:
         case XML_SCHEMAS_PINTEGER:
         case XML_SCHEMAS_NPINTEGER:
@@ -3138,6 +3294,21 @@
                return(-1);
             }
             return (-2);
+        case XML_SCHEMAS_BASE64BINARY:
+            if (y->type == XML_SCHEMAS_BASE64BINARY) {
+                if (x->value.base64.total == y->value.base64.total) {
+                    int ret = xmlStrcmp(x->value.base64.str, y->value.base64.str);
+                    if (ret > 0)
+                        return(1);
+                    else if (ret == 0)
+                        return(0);
+                }
+                else if (x->value.base64.total > y->value.base64.total)
+                    return(1);
+                else
+                    return(-1);
+            }
+            return (-2);
         case XML_SCHEMAS_STRING:
         case XML_SCHEMAS_IDREFS:
         case XML_SCHEMAS_ENTITIES:
@@ -3284,7 +3455,9 @@
            }
            if ((val != NULL) && (val->type == XML_SCHEMAS_HEXBINARY))
                len = val->value.hex.total;
-           else { 
+           else if ((val != NULL) && (val->type == XML_SCHEMAS_BASE64BINARY))
+            len = val->value.base64.total;
+           else {
                switch (base->flags) {
                    case XML_SCHEMAS_IDREF:
                    case XML_SCHEMAS_NORMSTRING:

-- 
Anthony Carrico



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]