]> arthur.barton.de Git - netatalk.git/blobdiff - etc/afpd/spotlight_marshalling.c
Don't use fixed tag when marshalling the CNID structure
[netatalk.git] / etc / afpd / spotlight_marshalling.c
index 29bd234c5dae44b1999bbb32d3d15e4b82dcc608..69733f4943676c58ec4baf7e1d20105a17d97503 100644 (file)
@@ -100,21 +100,16 @@ static int slvalc(char *buf, off_t off, off_t maxoff, uint64_t val)
 static uint spotlight_get_utf16_string_encoding(const char *buf, int offset, int query_length, uint encoding) {
     uint utf16_encoding;
 
-    /* check for byte order mark */
-    utf16_encoding = SL_ENC_BIG_ENDIAN;
-    if (query_length >= 2) {
-        uint16_t byte_order_mark;
-        if (encoding == SL_ENC_LITTLE_ENDIAN)
-            byte_order_mark = SVAL(buf, offset);
-        else
-            byte_order_mark = RSVAL(buf, offset);
+    /* Assumed encoding in absence of a bom is little endian */
+    utf16_encoding = SL_ENC_LITTLE_ENDIAN;
 
-        if (byte_order_mark == 0xFFFE) {
-            utf16_encoding = SL_ENC_BIG_ENDIAN | SL_ENC_UTF_16;
-        }
-        else if (byte_order_mark == 0xFEFF) {
+    if (query_length >= 2) {
+        uint8_t le_bom[] = {0xff, 0xfe};
+        uint8_t be_bom[] = {0xfe, 0xff};
+        if (memcmp(le_bom, buf + offset, sizeof(uint16_t)) == 0)
             utf16_encoding = SL_ENC_LITTLE_ENDIAN | SL_ENC_UTF_16;
-        }
+        else if (memcmp(be_bom, buf + offset, sizeof(uint16_t)) == 0)
+            utf16_encoding = SL_ENC_BIG_ENDIAN | SL_ENC_UTF_16;
     }
 
     return utf16_encoding;
@@ -238,7 +233,7 @@ static int sl_pack_CNID(sl_cnids_t *cnids, char *buf, int offset, char *toc_buf,
     offset += 8;
 
     if (cnid_count > 0) {
-        EC_ZERO( slvalc(buf, offset, MAX_SLQ_DAT, sl_pack_tag(0x0add, cnid_count, cnids->ca_context)) );
+        EC_ZERO( slvalc(buf, offset, MAX_SLQ_DAT, sl_pack_tag(cnids->ca_unkn1, cnid_count, cnids->ca_context)) );
         offset += 8;
 
         for (int i = 0; i < cnid_count; i++) {
@@ -603,7 +598,7 @@ static int sl_unpack_cpx(DALLOC_CTX *query,
     uint64_t query_data64;
     uint unicode_encoding;
     uint8_t mark_exists;
-    char *p;
+    char *p, *tmp;
     int qlen, used_in_last_block, slen;
     sl_array_t *sl_array;
     sl_dict_t *sl_dict;
@@ -627,15 +622,23 @@ static int sl_unpack_cpx(DALLOC_CTX *query,
         query_data64 = sl_unpack_uint64(buf, offset, encoding);
         qlen = (query_data64 & 0xffff) * 8;
         used_in_last_block = query_data64 >> 32;
-        slen = qlen - 8 + used_in_last_block;
+        slen = qlen - 16 + used_in_last_block;
 
         if (cpx_query_type == SQ_CPX_TYPE_STRING) {
             p = dalloc_strndup(query, buf + offset + 8, slen);
         } else {
             unicode_encoding = spotlight_get_utf16_string_encoding(buf, offset + 8, slen, encoding);
             mark_exists = (unicode_encoding & SL_ENC_UTF_16);
-            unicode_encoding &= ~SL_ENC_UTF_16;
-            EC_NEG1( convert_string_allocate(CH_UCS2, CH_UTF8, buf + offset + (mark_exists ? 18 : 16), slen, &p) );
+            if (unicode_encoding & SL_ENC_BIG_ENDIAN)
+                EC_FAIL_LOG("Unsupported big endian UTF16 string");
+            slen -= mark_exists ? 2 : 0;
+            EC_NEG1( convert_string_allocate(CH_UCS2,
+                                             CH_UTF8,
+                                             buf + offset + (mark_exists ? 10 : 8),
+                                             slen,
+                                             &tmp) );
+            p = dalloc_strndup(query, tmp, strlen(tmp));
+            free(tmp);
         }
 
         dalloc_add(query, p, char *);