5 * Copyright (C) 2010-2011 Nokia Corporation
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
41 /* NOTE: ap_defs array has to be kept in sync with map_ap_tag. */
42 static const struct ap_def {
46 { "MAXLISTCOUNT", APT_UINT16 },
47 { "STARTOFFSET", APT_UINT16 },
48 { "FILTERMESSAGETYPE", APT_UINT8 },
49 { "FILTERPERIODBEGIN", APT_STR },
50 { "FILTERPERIODEND", APT_STR },
51 { "FILTERREADSTATUS", APT_UINT8 },
52 { "FILTERRECIPIENT", APT_STR },
53 { "FILTERORIGINATOR", APT_STR },
54 { "FILTERPRIORITY", APT_UINT8 },
55 { "ATTACHMENT", APT_UINT8 },
56 { "TRANSPARENT", APT_UINT8 },
57 { "RETRY", APT_UINT8 },
58 { "NEWMESSAGE", APT_UINT8 },
59 { "NOTIFICATIONSTATUS", APT_UINT8 },
60 { "MASINSTANCEID", APT_UINT8 },
61 { "PARAMETERMASK", APT_UINT32 },
62 { "FOLDERLISTINGSIZE", APT_UINT16 },
63 { "MESSAGESLISTINGSIZE", APT_UINT16 },
64 { "SUBJECTLENGTH", APT_UINT8 },
65 { "CHARSET", APT_UINT8 },
66 { "FRACTIONREQUEST", APT_UINT8 },
67 { "FRACTIONDELIVER", APT_UINT8 },
68 { "STATUSINDICATOR", APT_UINT8 },
69 { "STATUSVALUE", APT_UINT8 },
70 { "MSETIME", APT_STR },
83 /* This comes from OBEX specs */
84 struct obex_ap_header {
88 } __attribute__ ((packed));
90 static int find_ap_def_offset(uint8_t tag)
92 if (tag == 0 || tag > G_N_ELEMENTS(ap_defs))
98 static void ap_entry_dump(gpointer tag, gpointer val, gpointer user_data)
100 struct ap_entry *entry = val;
103 offset = find_ap_def_offset(GPOINTER_TO_INT(tag));
105 switch (ap_defs[offset].type) {
107 DBG("%-30s %08x", ap_defs[offset].name, entry->val.u8);
110 DBG("%-30s %08x", ap_defs[offset].name, entry->val.u16);
113 DBG("%-30s %08x", ap_defs[offset].name, entry->val.u32);
116 DBG("%-30s %s", ap_defs[offset].name, entry->val.str);
121 static void ap_entry_free(gpointer val)
123 struct ap_entry *entry = val;
126 offset = find_ap_def_offset(entry->tag);
128 if (offset >= 0 && ap_defs[offset].type == APT_STR)
129 g_free(entry->val.str);
134 map_ap_t *map_ap_new(void)
136 return g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL,
140 void map_ap_free(map_ap_t *ap)
145 g_hash_table_destroy(ap);
148 static void ap_decode_u8(map_ap_t *ap, const struct obex_ap_header *hdr)
151 DBG("Value of tag %u is %u byte(s) long instead of expected "
152 "1 byte - skipped!", hdr->tag, hdr->len);
156 map_ap_set_u8(ap, hdr->tag, hdr->val[0]);
159 static void ap_decode_u16(map_ap_t *ap, const struct obex_ap_header *hdr)
164 DBG("Value of tag %u is %u byte(s) long instead of expected "
165 "2 bytes - skipped!", hdr->tag, hdr->len);
169 memcpy(&val, hdr->val, sizeof(val));
170 map_ap_set_u16(ap, hdr->tag, GUINT16_FROM_BE(val));
173 static void ap_decode_u32(map_ap_t *ap, const struct obex_ap_header *hdr)
178 DBG("Value of tag %u is %u byte(s) long instead of expected "
179 "4 bytes - skipped!", hdr->tag, hdr->len);
183 memcpy(&val, hdr->val, sizeof(val));
184 map_ap_set_u32(ap, hdr->tag, GUINT32_FROM_BE(val));
187 static void ap_decode_str(map_ap_t *ap, const struct obex_ap_header *hdr)
189 char *val = g_malloc0(hdr->len + 1);
191 memcpy(val, hdr->val, hdr->len);
192 map_ap_set_string(ap, hdr->tag, val);
197 map_ap_t *map_ap_decode(const uint8_t *buffer, size_t length)
200 struct obex_ap_header *hdr;
208 for (done = 0; done < length; done += hdr->len + sizeof(*hdr)) {
209 hdr = (struct obex_ap_header *)(buffer + done);
211 offset = find_ap_def_offset(hdr->tag);
214 DBG("Unknown tag %u (length %u) - skipped.",
219 switch (ap_defs[offset].type) {
221 ap_decode_u8(ap, hdr);
224 ap_decode_u16(ap, hdr);
227 ap_decode_u32(ap, hdr);
230 ap_decode_str(ap, hdr);
235 g_hash_table_foreach(ap, ap_entry_dump, NULL);
240 static void ap_encode_u8(GByteArray *buf, struct ap_entry *entry)
242 struct obex_ap_header *hdr;
244 hdr = (struct obex_ap_header *) buf->data + buf->len;
245 g_byte_array_set_size(buf, buf->len + sizeof(*hdr) + 1);
247 hdr->tag = entry->tag;
249 hdr->val[0] = entry->val.u8;
252 static void ap_encode_u16(GByteArray *buf, struct ap_entry *entry)
254 struct obex_ap_header *hdr;
257 hdr = (struct obex_ap_header *) buf->data + buf->len;
259 g_byte_array_set_size(buf, buf->len + sizeof(*hdr) + 2);
261 hdr->tag = entry->tag;
264 val = GUINT16_TO_BE(entry->val.u16);
265 memcpy(hdr->val, &val, sizeof(val));
268 static void ap_encode_u32(GByteArray *buf, struct ap_entry *entry)
271 struct obex_ap_header *hdr;
273 hdr = (struct obex_ap_header *) buf->data + buf->len;
274 g_byte_array_set_size(buf, buf->len + sizeof(*hdr) + 4);
276 hdr->tag = entry->tag;
279 val = GUINT32_TO_BE(entry->val.u16);
280 memcpy(hdr->val, &val, sizeof(val));
283 static void ap_encode_str(GByteArray *buf, struct ap_entry *entry)
286 struct obex_ap_header *hdr;
288 hdr = (struct obex_ap_header *) buf->data + buf->len;
289 len = strlen(entry->val.str);
290 g_byte_array_set_size(buf, buf->len + sizeof(*hdr) + len);
292 hdr->tag = entry->tag;
295 memcpy(hdr->val, entry->val.str, len);
298 uint8_t *map_ap_encode(map_ap_t *ap, size_t *length)
303 struct ap_entry *entry;
306 buf = g_byte_array_new();
307 g_hash_table_iter_init(&iter, ap);
309 while (g_hash_table_iter_next(&iter, &key, &value)) {
310 entry = (struct ap_entry *) value;
311 offset = find_ap_def_offset(entry->tag);
313 switch (ap_defs[offset].type) {
315 ap_encode_u8(buf, entry);
318 ap_encode_u16(buf, entry);
321 ap_encode_u32(buf, entry);
324 ap_encode_str(buf, entry);
331 return g_byte_array_free(buf, FALSE);
334 gboolean map_ap_get_u8(map_ap_t *ap, enum map_ap_tag tag, uint8_t *val)
336 struct ap_entry *entry;
337 int offset = find_ap_def_offset(tag);
339 if (offset < 0 || ap_defs[offset].type != APT_UINT8)
342 entry = g_hash_table_lookup(ap, GINT_TO_POINTER(tag));
346 *val = entry->val.u8;
351 gboolean map_ap_get_u16(map_ap_t *ap, enum map_ap_tag tag, uint16_t *val)
353 struct ap_entry *entry;
354 int offset = find_ap_def_offset(tag);
356 if (offset < 0 || ap_defs[offset].type != APT_UINT16)
359 entry = g_hash_table_lookup(ap, GINT_TO_POINTER(tag));
363 *val = entry->val.u16;
368 gboolean map_ap_get_u32(map_ap_t *ap, enum map_ap_tag tag, uint32_t *val)
370 struct ap_entry *entry;
371 int offset = find_ap_def_offset(tag);
373 if (offset < 0 || ap_defs[offset].type != APT_UINT32)
376 entry = g_hash_table_lookup(ap, GINT_TO_POINTER(tag));
380 *val = entry->val.u32;
385 const char *map_ap_get_string(map_ap_t *ap, enum map_ap_tag tag)
387 struct ap_entry *entry;
388 int offset = find_ap_def_offset(tag);
390 if (offset < 0 || ap_defs[offset].type != APT_STR)
393 entry = g_hash_table_lookup(ap, GINT_TO_POINTER(tag));
397 return entry->val.str;
400 gboolean map_ap_set_u8(map_ap_t *ap, enum map_ap_tag tag, uint8_t val)
402 struct ap_entry *entry;
403 int offset = find_ap_def_offset(tag);
405 if (offset < 0 || ap_defs[offset].type != APT_UINT8)
408 entry = g_new0(struct ap_entry, 1);
412 g_hash_table_insert(ap, GINT_TO_POINTER(tag), entry);
417 gboolean map_ap_set_u16(map_ap_t *ap, enum map_ap_tag tag, uint16_t val)
419 struct ap_entry *entry;
420 int offset = find_ap_def_offset(tag);
422 if (offset < 0 || ap_defs[offset].type != APT_UINT16)
425 entry = g_new0(struct ap_entry, 1);
427 entry->val.u16 = val;
429 g_hash_table_insert(ap, GINT_TO_POINTER(tag), entry);
434 gboolean map_ap_set_u32(map_ap_t *ap, enum map_ap_tag tag, uint32_t val)
436 struct ap_entry *entry;
437 int offset = find_ap_def_offset(tag);
439 if (offset < 0 || ap_defs[offset].type != APT_UINT32)
442 entry = g_new0(struct ap_entry, 1);
444 entry->val.u32 = val;
446 g_hash_table_insert(ap, GINT_TO_POINTER(tag), entry);
451 gboolean map_ap_set_string(map_ap_t *ap, enum map_ap_tag tag, const char *val)
453 struct ap_entry *entry;
454 int offset = find_ap_def_offset(tag);
456 if (offset < 0 || ap_defs[offset].type != APT_STR)
459 entry = g_new0(struct ap_entry, 1);
461 entry->val.str = g_strdup(val);
463 g_hash_table_insert(ap, GINT_TO_POINTER(tag), entry);