comparison libpurple/protocols/myspace/message.c @ 18895:f732d072b118

Change all code to better match the style of libpurple - use 8-space tabs for indentation everywhere. Spaces are still used for alignment when needed, as described on http://derkarl.org/why_to_tabs.html (ack for [^\t]\t to ensure tabs are only being used for indentation). Lots of vim regexes made this transformation possible. Also cuddled a few braces that I missed before. This is a big commit, but there are no actual code changes.
author Jeffrey Connelly <jaconnel@calpoly.edu>
date Sat, 11 Aug 2007 05:53:11 +0000
parents 7db556e97dd1
children d0be4366e876
comparison
equal deleted inserted replaced
18894:daedc9647341 18895:f732d072b118
30 static MsimMessage *msim_msg_new_v(va_list argp); 30 static MsimMessage *msim_msg_new_v(va_list argp);
31 31
32 /* Escape codes and associated replacement text, used for protocol message 32 /* Escape codes and associated replacement text, used for protocol message
33 * escaping and unescaping. */ 33 * escaping and unescaping. */
34 static struct MSIM_ESCAPE_REPLACEMENT { 34 static struct MSIM_ESCAPE_REPLACEMENT {
35 gchar *code; 35 gchar *code;
36 gchar *text; 36 gchar *text;
37 } msim_escape_replacements[] = { 37 } msim_escape_replacements[] = {
38 { "/1", "/" }, 38 { "/1", "/" },
39 { "/2", "\\" }, 39 { "/2", "\\" },
40 /* { "/3", "|" }, */ /* Not used here -- only for within arrays */ 40 /* { "/3", "|" }, */ /* Not used here -- only for within arrays */
41 { NULL, NULL } 41 { NULL, NULL }
42 }; 42 };
43 43
44 /** 44 /**
45 * Unescape or escape a protocol message. 45 * Unescape or escape a protocol message.
46 * 46 *
52 static gchar * 52 static gchar *
53 msim_unescape_or_escape(const gchar *original_msg, gboolean escape) 53 msim_unescape_or_escape(const gchar *original_msg, gboolean escape)
54 { 54 {
55 gchar *tmp, *msg; 55 gchar *tmp, *msg;
56 guint i; 56 guint i;
57 struct MSIM_ESCAPE_REPLACEMENT* replacement; 57 struct MSIM_ESCAPE_REPLACEMENT* replacement;
58 58
59 /* Freed in loop below. */ 59 /* Freed in loop below. */
60 msg = g_strdup(original_msg); 60 msg = g_strdup(original_msg);
61 61
62 /* Replace each code in msim_replacement_code with 62 /* Replace each code in msim_replacement_code with
63 * corresponding entry in msim_replacement_text. */ 63 * corresponding entry in msim_replacement_text. */
64 for (i = 0; (replacement = &msim_escape_replacements[i]); ++i) { 64 for (i = 0; (replacement = &msim_escape_replacements[i]); ++i) {
65 gchar *code, *text; 65 gchar *code, *text;
66 66
67 code = replacement->code; 67 code = replacement->code;
68 text = replacement->text; 68 text = replacement->text;
69 69
70 if (!code || !text) 70 if (!code || !text)
71 break; 71 break;
72 72
73 if (escape) { 73 if (escape) {
74 tmp = str_replace(msg, text, code); 74 tmp = str_replace(msg, text, code);
75 } else { 75 } else {
76 tmp = str_replace(msg, code, text); 76 tmp = str_replace(msg, code, text);
113 113
114 va_start(argp, not_empty); 114 va_start(argp, not_empty);
115 115
116 if (not_empty) { 116 if (not_empty) {
117 return msim_msg_new_v(argp); 117 return msim_msg_new_v(argp);
118 } else { 118 } else {
119 return NULL; 119 return NULL;
120 } 120 }
121 } 121 }
122 122
123 /** Create a new message from va_list and its first argument. 123 /** Create a new message from va_list and its first argument.
124 * 124 *
125 * @param argp A va_list of variadic arguments, already started with va_start(). Will be va_end()'d. 125 * @param argp A va_list of variadic arguments, already started with va_start(). Will be va_end()'d.
132 { 132 {
133 gchar *key, *value; 133 gchar *key, *value;
134 MsimMessageType type; 134 MsimMessageType type;
135 MsimMessage *msg; 135 MsimMessage *msg;
136 136
137 GString *gs; 137 GString *gs;
138 GList *gl; 138 GList *gl;
139 MsimMessage *dict; 139 MsimMessage *dict;
140 140
141 141
142 /* Begin with an empty message. */ 142 /* Begin with an empty message. */
143 msg = NULL; 143 msg = NULL;
144 144
165 165
166 msg = msim_msg_append(msg, key, type, value); 166 msg = msim_msg_append(msg, key, type, value);
167 break; 167 break;
168 168
169 case MSIM_TYPE_BINARY: 169 case MSIM_TYPE_BINARY:
170 gs = va_arg(argp, GString *); 170 gs = va_arg(argp, GString *);
171 171
172 g_return_val_if_fail(gs != NULL, FALSE); 172 g_return_val_if_fail(gs != NULL, FALSE);
173 173
174 /* msim_msg_free() will free this GString the caller created. */ 174 /* msim_msg_free() will free this GString the caller created. */
175 msg = msim_msg_append(msg, key, type, gs); 175 msg = msim_msg_append(msg, key, type, gs);
176 break; 176 break;
177 177
178 case MSIM_TYPE_LIST: 178 case MSIM_TYPE_LIST:
179 gl = va_arg(argp, GList *); 179 gl = va_arg(argp, GList *);
180 180
181 g_return_val_if_fail(gl != NULL, FALSE); 181 g_return_val_if_fail(gl != NULL, FALSE);
182 182
183 msg = msim_msg_append(msg, key, type, gl); 183 msg = msim_msg_append(msg, key, type, gl);
184 break; 184 break;
185 185
186 case MSIM_TYPE_DICTIONARY: 186 case MSIM_TYPE_DICTIONARY:
187 dict = va_arg(argp, MsimMessage *); 187 dict = va_arg(argp, MsimMessage *);
188 188
189 g_return_val_if_fail(dict != NULL, FALSE); 189 g_return_val_if_fail(dict != NULL, FALSE);
190 190
191 msg = msim_msg_append(msg, key, type, dict); 191 msg = msim_msg_append(msg, key, type, dict);
192 break; 192 break;
193 193
194 default: 194 default:
195 purple_debug_info("msim", "msim_send: unknown type %d\n", type); 195 purple_debug_info("msim", "msim_send: unknown type %d\n", type);
196 break; 196 break;
197 } 197 }
198 } while(key); 198 } while(key);
199 va_end(argp); 199 va_end(argp);
200 200
201 return msg; 201 return msg;
202 } 202 }
203 203
204 /** Perform a deep copy on a GList * of gchar * strings. Free with msim_msg_list_free(). */ 204 /** Perform a deep copy on a GList * of gchar * strings. Free with msim_msg_list_free(). */
205 GList * 205 GList *
206 msim_msg_list_copy(GList *old) 206 msim_msg_list_copy(GList *old)
207 { 207 {
208 GList *new_list; 208 GList *new_list;
209 209
210 new_list = NULL; 210 new_list = NULL;
211 211
212 /* Deep copy (g_list_copy is shallow). Copy each string. */ 212 /* Deep copy (g_list_copy is shallow). Copy each string. */
213 for (; old != NULL; old = g_list_next(old)) { 213 for (; old != NULL; old = g_list_next(old)) {
214 new_list = g_list_append(new_list, g_strdup(old->data)); 214 new_list = g_list_append(new_list, g_strdup(old->data));
215 } 215 }
216 216
217 return new_list; 217 return new_list;
218 } 218 }
219 219
220 /** Free a GList * of gchar * strings. */ 220 /** Free a GList * of gchar * strings. */
221 void 221 void
222 msim_msg_list_free(GList *l) 222 msim_msg_list_free(GList *l)
223 { 223 {
224 224
225 for (; l != NULL; l = g_list_next(l)) { 225 for (; l != NULL; l = g_list_next(l)) {
226 g_free((gchar *)(l->data)); 226 g_free((gchar *)(l->data));
227 } 227 }
228 g_list_free(l); 228 g_list_free(l);
229 } 229 }
230 230
231 /** Parse a |-separated string into a new GList. Free with msim_msg_list_free(). */ 231 /** Parse a |-separated string into a new GList. Free with msim_msg_list_free(). */
232 GList * 232 GList *
233 msim_msg_list_parse(const gchar *raw) 233 msim_msg_list_parse(const gchar *raw)
234 { 234 {
235 gchar **array; 235 gchar **array;
236 GList *list; 236 GList *list;
237 guint i; 237 guint i;
238 238
239 array = g_strsplit(raw, "|", 0); 239 array = g_strsplit(raw, "|", 0);
240 list = NULL; 240 list = NULL;
241 241
242 /* TODO: escape/unescape /3 <-> | within list elements */ 242 /* TODO: escape/unescape /3 <-> | within list elements */
243 243
244 for (i = 0; array[i] != NULL; ++i) { 244 for (i = 0; array[i] != NULL; ++i) {
245 list = g_list_append(list, g_strdup(array[i])); 245 list = g_list_append(list, g_strdup(array[i]));
246 } 246 }
247 247
248 g_strfreev(array); 248 g_strfreev(array);
249 249
250 return list; 250 return list;
251 } 251 }
252 252
253 /** Clone an individual element. 253 /** Clone an individual element.
254 * 254 *
255 * @param data MsimMessageElement * to clone. 255 * @param data MsimMessageElement * to clone.
260 { 260 {
261 MsimMessageElement *elem; 261 MsimMessageElement *elem;
262 MsimMessage **new; 262 MsimMessage **new;
263 gpointer new_data; 263 gpointer new_data;
264 264
265 GString *gs; 265 GString *gs;
266 MsimMessage *dict; 266 MsimMessage *dict;
267 267
268 elem = (MsimMessageElement *)data; 268 elem = (MsimMessageElement *)data;
269 new = (MsimMessage **)user_data; 269 new = (MsimMessage **)user_data;
270 270
271 switch (elem->type) { 271 switch (elem->type) {
277 case MSIM_TYPE_RAW: 277 case MSIM_TYPE_RAW:
278 case MSIM_TYPE_STRING: 278 case MSIM_TYPE_STRING:
279 new_data = g_strdup((gchar *)elem->data); 279 new_data = g_strdup((gchar *)elem->data);
280 break; 280 break;
281 281
282 case MSIM_TYPE_LIST: 282 case MSIM_TYPE_LIST:
283 new_data = (gpointer)msim_msg_list_copy((GList *)(elem->data)); 283 new_data = (gpointer)msim_msg_list_copy((GList *)(elem->data));
284 break; 284 break;
285 285
286 case MSIM_TYPE_BINARY: 286 case MSIM_TYPE_BINARY:
287 gs = (GString *)elem->data; 287 gs = (GString *)elem->data;
288 288
289 new_data = g_string_new_len(gs->str, gs->len); 289 new_data = g_string_new_len(gs->str, gs->len);
290 break; 290 break;
291 case MSIM_TYPE_DICTIONARY: 291 case MSIM_TYPE_DICTIONARY:
292 dict = (MsimMessage *)elem->data; 292 dict = (MsimMessage *)elem->data;
293 293
294 new_data = msim_msg_clone(dict); 294 new_data = msim_msg_clone(dict);
295 break; 295 break;
296 296
297 default: 297 default:
298 purple_debug_info("msim", "msim_msg_clone_element: unknown type %d\n", elem->type); 298 purple_debug_info("msim", "msim_msg_clone_element: unknown type %d\n", elem->type);
299 g_return_if_fail(NULL); 299 g_return_if_fail(NULL);
300 } 300 }
313 { 313 {
314 MsimMessage *new; 314 MsimMessage *new;
315 315
316 if (old == NULL) { 316 if (old == NULL) {
317 return NULL; 317 return NULL;
318 } 318 }
319 319
320 new = msim_msg_new(FALSE); 320 new = msim_msg_new(FALSE);
321 321
322 g_list_foreach(old, msim_msg_clone_element, &new); 322 g_list_foreach(old, msim_msg_clone_element, &new);
323 323
332 * element itself with g_free() (see msim_msg_free_element()). 332 * element itself with g_free() (see msim_msg_free_element()).
333 */ 333 */
334 void 334 void
335 msim_msg_free_element_data(MsimMessageElement *elem) 335 msim_msg_free_element_data(MsimMessageElement *elem)
336 { 336 {
337 switch (elem->type) { 337 switch (elem->type) {
338 case MSIM_TYPE_BOOLEAN: 338 case MSIM_TYPE_BOOLEAN:
339 case MSIM_TYPE_INTEGER: 339 case MSIM_TYPE_INTEGER:
340 /* Integer value stored in gpointer - no need to free(). */ 340 /* Integer value stored in gpointer - no need to free(). */
341 break; 341 break;
342 342
351 /* Free the GString itself and the binary data. */ 351 /* Free the GString itself and the binary data. */
352 g_string_free((GString *)elem->data, TRUE); 352 g_string_free((GString *)elem->data, TRUE);
353 break; 353 break;
354 354
355 case MSIM_TYPE_DICTIONARY: 355 case MSIM_TYPE_DICTIONARY:
356 msim_msg_free((MsimMessage *)elem->data); 356 msim_msg_free((MsimMessage *)elem->data);
357 break; 357 break;
358 358
359 case MSIM_TYPE_LIST: 359 case MSIM_TYPE_LIST:
360 g_list_free((GList *)elem->data); 360 g_list_free((GList *)elem->data);
361 break; 361 break;
362 362
363 default: 363 default:
364 purple_debug_info("msim", "msim_msg_free_element_data: " 364 purple_debug_info("msim", "msim_msg_free_element_data: "
365 "not freeing unknown type %d\n", elem->type); 365 "not freeing unknown type %d\n", elem->type);
366 break; 366 break;
367 } 367 }
368 } 368 }
369 369
370 /** Free an individual message element. 370 /** Free an individual message element.
379 { 379 {
380 MsimMessageElement *elem; 380 MsimMessageElement *elem;
381 381
382 elem = (MsimMessageElement *)data; 382 elem = (MsimMessageElement *)data;
383 383
384 msim_msg_free_element_data(elem); 384 msim_msg_free_element_data(elem);
385 385
386 g_free(elem); 386 g_free(elem);
387 } 387 }
388 388
389 /** Free a complete message. */ 389 /** Free a complete message. */
393 if (!msg) { 393 if (!msg) {
394 /* already free as can be */ 394 /* already free as can be */
395 return; 395 return;
396 } 396 }
397 397
398 msim_msg_dump("msim_msg_free: freeing %s", msg); 398 msim_msg_dump("msim_msg_free: freeing %s", msg);
399 399
400 g_list_foreach(msg, msim_msg_free_element, NULL); 400 g_list_foreach(msg, msim_msg_free_element, NULL);
401 g_list_free(msg); 401 g_list_free(msg);
402 } 402 }
403 403
407 { 407 {
408 gchar *raw; 408 gchar *raw;
409 gboolean success; 409 gboolean success;
410 410
411 raw = msim_msg_pack(msg); 411 raw = msim_msg_pack(msg);
412 g_return_val_if_fail(raw != NULL, FALSE); 412 g_return_val_if_fail(raw != NULL, FALSE);
413 success = msim_send_raw(session, raw); 413 success = msim_send_raw(session, raw);
414 g_free(raw); 414 g_free(raw);
415 415
416 msim_msg_dump("msim_msg_send()ing %s\n", msg); 416 msim_msg_dump("msim_msg_send()ing %s\n", msg);
417 417
436 msim_send(MsimSession *session, ...) 436 msim_send(MsimSession *session, ...)
437 { 437 {
438 gboolean success; 438 gboolean success;
439 MsimMessage *msg; 439 MsimMessage *msg;
440 va_list argp; 440 va_list argp;
441 441
442 va_start(argp, session); 442 va_start(argp, session);
443 msg = msim_msg_new_v(argp); 443 msg = msim_msg_new_v(argp);
444 444
445 /* Actually send the message. */ 445 /* Actually send the message. */
446 success = msim_msg_send(session, msg); 446 success = msim_msg_send(session, msg);
476 * @param type An MSIM_TYPE_* code. 476 * @param type An MSIM_TYPE_* code.
477 * @param data Pointer to data, see below. 477 * @param data Pointer to data, see below.
478 * 478 *
479 * @return The new message - must be assigned to as with GList*. For example: 479 * @return The new message - must be assigned to as with GList*. For example:
480 * 480 *
481 * msg = msim_msg_append(msg, ...) 481 * msg = msim_msg_append(msg, ...)
482 * 482 *
483 * The data parameter depends on the type given: 483 * The data parameter depends on the type given:
484 * 484 *
485 * * MSIM_TYPE_INTEGER: Use GUINT_TO_POINTER(x). 485 * * MSIM_TYPE_INTEGER: Use GUINT_TO_POINTER(x).
486 * 486 *
505 } 505 }
506 506
507 /** Insert a new element into a message, before the given element name. 507 /** Insert a new element into a message, before the given element name.
508 * 508 *
509 * @param name_before Name of the element to insert the new element before. If 509 * @param name_before Name of the element to insert the new element before. If
510 * could not be found or NULL, new element will be inserted at end. 510 * could not be found or NULL, new element will be inserted at end.
511 * 511 *
512 * See msim_msg_append() for usage of other parameters, and an important note about return value. 512 * See msim_msg_append() for usage of other parameters, and an important note about return value.
513 */ 513 */
514 MsimMessage * 514 MsimMessage *
515 msim_msg_insert_before(MsimMessage *msg, const gchar *name_before, 515 msim_msg_insert_before(MsimMessage *msg, const gchar *name_before,
516 const gchar *name, MsimMessageType type, gpointer data) 516 const gchar *name, MsimMessageType type, gpointer data)
517 { 517 {
518 MsimMessageElement *new_elem; 518 MsimMessageElement *new_elem;
519 GList *node_before; 519 GList *node_before;
520 520
521 new_elem = msim_msg_element_new(name, type, data); 521 new_elem = msim_msg_element_new(name, type, data);
522 522
523 node_before = msim_msg_get_node(msg, name_before); 523 node_before = msim_msg_get_node(msg, name_before);
524 524
525 return g_list_insert_before(msg, node_before, new_elem); 525 return g_list_insert_before(msg, node_before, new_elem);
526 } 526 }
528 /** Pack a string using the given GFunc and seperator. 528 /** Pack a string using the given GFunc and seperator.
529 * Used by msim_msg_dump() and msim_msg_pack(). 529 * Used by msim_msg_dump() and msim_msg_pack().
530 */ 530 */
531 gchar * 531 gchar *
532 msim_msg_pack_using(MsimMessage *msg, 532 msim_msg_pack_using(MsimMessage *msg,
533 GFunc gf, 533 GFunc gf,
534 const gchar *sep, 534 const gchar *sep,
535 const gchar *begin, const gchar *end) 535 const gchar *begin, const gchar *end)
536 { 536 {
537 gchar **strings; 537 gchar **strings;
538 gchar **strings_tmp; 538 gchar **strings_tmp;
539 gchar *joined; 539 gchar *joined;
571 { 571 {
572 MsimMessageElement *elem; 572 MsimMessageElement *elem;
573 gchar *string; 573 gchar *string;
574 GString *gs; 574 GString *gs;
575 gchar *binary; 575 gchar *binary;
576 gchar ***items; /* wow, a pointer to a pointer to a pointer */ 576 gchar ***items; /* wow, a pointer to a pointer to a pointer */
577 577
578 gchar *s; 578 gchar *s;
579 GList *gl; 579 GList *gl;
580 guint i; 580 guint i;
581 581
582 elem = (MsimMessageElement *)data; 582 elem = (MsimMessageElement *)data;
583 items = user_data; 583 items = user_data;
584 584
585 switch (elem->type) { 585 switch (elem->type) {
586 case MSIM_TYPE_INTEGER: 586 case MSIM_TYPE_INTEGER:
587 string = g_strdup_printf("%s(integer): %d", elem->name, 587 string = g_strdup_printf("%s(integer): %d", elem->name,
588 GPOINTER_TO_UINT(elem->data)); 588 GPOINTER_TO_UINT(elem->data));
589 break; 589 break;
590 590
591 case MSIM_TYPE_RAW: 591 case MSIM_TYPE_RAW:
592 string = g_strdup_printf("%s(raw): %s", elem->name, 592 string = g_strdup_printf("%s(raw): %s", elem->name,
593 elem->data ? (gchar *)elem->data : "(NULL)"); 593 elem->data ? (gchar *)elem->data : "(NULL)");
594 break; 594 break;
595 595
596 case MSIM_TYPE_STRING: 596 case MSIM_TYPE_STRING:
597 string = g_strdup_printf("%s(string): %s", elem->name, 597 string = g_strdup_printf("%s(string): %s", elem->name,
598 elem->data ? (gchar *)elem->data : "(NULL)"); 598 elem->data ? (gchar *)elem->data : "(NULL)");
599 break; 599 break;
600 600
601 case MSIM_TYPE_BINARY: 601 case MSIM_TYPE_BINARY:
602 gs = (GString *)elem->data; 602 gs = (GString *)elem->data;
603 binary = purple_base64_encode((guchar*)gs->str, gs->len); 603 binary = purple_base64_encode((guchar*)gs->str, gs->len);
609 string = g_strdup_printf("%s(boolean): %s", elem->name, 609 string = g_strdup_printf("%s(boolean): %s", elem->name,
610 elem->data ? "TRUE" : "FALSE"); 610 elem->data ? "TRUE" : "FALSE");
611 break; 611 break;
612 612
613 case MSIM_TYPE_DICTIONARY: 613 case MSIM_TYPE_DICTIONARY:
614 if (!elem->data) 614 if (!elem->data) {
615 s = g_strdup("(NULL)"); 615 s = g_strdup("(NULL)");
616 else 616 } else {
617 s = msim_msg_dump_to_str((MsimMessage *)elem->data); 617 s = msim_msg_dump_to_str((MsimMessage *)elem->data);
618 618 }
619 if (!s) 619
620 s = g_strdup("(NULL, couldn't msim_msg_dump_to_str)"); 620 if (!s) {
621 621 s = g_strdup("(NULL, couldn't msim_msg_dump_to_str)");
622 string = g_strdup_printf("%s(dict): %s", elem->name, s); 622 }
623 623
624 g_free(s); 624 string = g_strdup_printf("%s(dict): %s", elem->name, s);
625
626 g_free(s);
625 break; 627 break;
626 628
627 case MSIM_TYPE_LIST: 629 case MSIM_TYPE_LIST:
628 gs = g_string_new(""); 630 gs = g_string_new("");
629 g_string_append_printf(gs, "%s(list): \n", elem->name); 631 g_string_append_printf(gs, "%s(list): \n", elem->name);
630 632
631 i = 0; 633 i = 0;
632 for (gl = (GList *)elem->data; gl != NULL; gl = g_list_next(gl)) 634 for (gl = (GList *)elem->data; gl != NULL; gl = g_list_next(gl)) {
633 { 635 g_string_append_printf(gs, " %d. %s\n", i, (gchar *)(gl->data));
634 g_string_append_printf(gs, " %d. %s\n", i, (gchar *)(gl->data)); 636 ++i;
635 ++i; 637 }
636 } 638
637 639 string = gs->str;
638 string = gs->str;
639 break; 640 break;
640 641
641 default: 642 default:
642 string = g_strdup_printf("%s(unknown type %d", 643 string = g_strdup_printf("%s(unknown type %d",
643 elem->name ? elem->name : "(NULL)", elem->type); 644 elem->name ? elem->name : "(NULL)", elem->type);
644 break; 645 break;
645 } 646 }
646 647
647 **items = string; 648 **items = string;
648 ++(*items); 649 ++(*items);
653 * @param fmt_string A static string, in which '%s' will be replaced. 654 * @param fmt_string A static string, in which '%s' will be replaced.
654 */ 655 */
655 void 656 void
656 msim_msg_dump(const gchar *fmt_string, MsimMessage *msg) 657 msim_msg_dump(const gchar *fmt_string, MsimMessage *msg)
657 { 658 {
658 gchar *debug_str; 659 gchar *debug_str;
659 660
660 g_return_if_fail(fmt_string != NULL); 661 g_return_if_fail(fmt_string != NULL);
661 662
662 debug_str = msim_msg_dump_to_str(msg); 663 debug_str = msim_msg_dump_to_str(msg);
663 664
664 g_return_if_fail(debug_str != NULL); 665 g_return_if_fail(debug_str != NULL);
665 666
666 purple_debug_info("msim_msg_dump", "debug_str=%s\n", debug_str); 667 purple_debug_info("msim_msg_dump", "debug_str=%s\n", debug_str);
667 668
668 669
669 purple_debug_info("msim", fmt_string, debug_str); 670 purple_debug_info("msim", fmt_string, debug_str);
670 671
671 g_free(debug_str); 672 g_free(debug_str);
685 } else { 686 } else {
686 debug_str = msim_msg_pack_using(msg, msim_msg_debug_string_element, 687 debug_str = msim_msg_pack_using(msg, msim_msg_debug_string_element,
687 "\n", "<MsimMessage: \n", "\n/MsimMessage>"); 688 "\n", "<MsimMessage: \n", "\n/MsimMessage>");
688 } 689 }
689 690
690 return debug_str; 691 return debug_str;
691 } 692 }
692 693
693 /** Return a message element data as a new string for a raw protocol message, converting from other types (integer, etc.) if necessary. 694 /** Return a message element data as a new string for a raw protocol message, converting from other types (integer, etc.) if necessary.
694 * 695 *
695 * @return const gchar * The data as a string, or NULL. Caller must g_free(). 696 * @return const gchar * The data as a string, or NULL. Caller must g_free().
699 * msim_msg_get_string() if you want a string, which in some cases is same as this. 700 * msim_msg_get_string() if you want a string, which in some cases is same as this.
700 */ 701 */
701 gchar * 702 gchar *
702 msim_msg_pack_element_data(MsimMessageElement *elem) 703 msim_msg_pack_element_data(MsimMessageElement *elem)
703 { 704 {
704 GString *gs; 705 GString *gs;
705 GList *gl; 706 GList *gl;
706 707
707 g_return_val_if_fail(elem != NULL, NULL); 708 g_return_val_if_fail(elem != NULL, NULL);
708 709
709 switch (elem->type) { 710 switch (elem->type) {
710 case MSIM_TYPE_INTEGER: 711 case MSIM_TYPE_INTEGER:
711 return g_strdup_printf("%d", GPOINTER_TO_UINT(elem->data)); 712 return g_strdup_printf("%d", GPOINTER_TO_UINT(elem->data));
712 713
714 /* Not un-escaped - this is a raw element, already escaped if necessary. */ 715 /* Not un-escaped - this is a raw element, already escaped if necessary. */
715 return (gchar *)g_strdup((gchar *)elem->data); 716 return (gchar *)g_strdup((gchar *)elem->data);
716 717
717 case MSIM_TYPE_STRING: 718 case MSIM_TYPE_STRING:
718 /* Strings get escaped. msim_escape() creates a new string. */ 719 /* Strings get escaped. msim_escape() creates a new string. */
719 g_return_val_if_fail(elem->data != NULL, NULL); 720 g_return_val_if_fail(elem->data != NULL, NULL);
720 return elem->data ? msim_escape((gchar *)elem->data) : 721 return elem->data ? msim_escape((gchar *)elem->data) :
721 g_strdup("(NULL)"); 722 g_strdup("(NULL)");
722 723
723 case MSIM_TYPE_BINARY: 724 case MSIM_TYPE_BINARY:
724 gs = (GString *)elem->data; 725 gs = (GString *)elem->data;
725 /* Do not escape! */ 726 /* Do not escape! */
726 return purple_base64_encode((guchar *)gs->str, gs->len); 727 return purple_base64_encode((guchar *)gs->str, gs->len);
727 728
728 case MSIM_TYPE_BOOLEAN: 729 case MSIM_TYPE_BOOLEAN:
729 /* Not used by messages in the wire protocol * -- see msim_msg_pack_element. 730 /* Not used by messages in the wire protocol * -- see msim_msg_pack_element.
730 * Only used by dictionaries, see msim_msg_pack_element_dict. */ 731 * Only used by dictionaries, see msim_msg_pack_element_dict. */
731 return elem->data ? g_strdup("On") : g_strdup("Off"); 732 return elem->data ? g_strdup("On") : g_strdup("Off");
732 733
733 case MSIM_TYPE_DICTIONARY: 734 case MSIM_TYPE_DICTIONARY:
734 /* TODO: pack using k=v\034k2=v2\034... */ 735 /* TODO: pack using k=v\034k2=v2\034... */
735 return msim_msg_pack_dict((MsimMessage *)elem->data); 736 return msim_msg_pack_dict((MsimMessage *)elem->data);
736 737
737 case MSIM_TYPE_LIST: 738 case MSIM_TYPE_LIST:
738 /* Pack using a|b|c|d|... */ 739 /* Pack using a|b|c|d|... */
739 gs = g_string_new(""); 740 gs = g_string_new("");
740 741
741 for (gl = (GList *)elem->data; gl != NULL; gl = g_list_next(gl)) { 742 for (gl = (GList *)elem->data; gl != NULL; gl = g_list_next(gl)) {
742 g_string_append_printf(gs, "%s", (gchar*)(gl->data)); 743 g_string_append_printf(gs, "%s", (gchar*)(gl->data));
743 744
744 /* All but last element is separated by a bar. */ 745 /* All but last element is separated by a bar. */
745 if (g_list_next(gl)) 746 if (g_list_next(gl))
746 g_string_append(gs, "|"); 747 g_string_append(gs, "|");
747 } 748 }
748 749
749 return gs->str; 750 return gs->str;
750 751
751 default: 752 default:
752 purple_debug_info("msim", "field %s, unknown type %d\n", 753 purple_debug_info("msim", "field %s, unknown type %d\n",
753 elem->name ? elem->name : "(NULL)", 754 elem->name ? elem->name : "(NULL)",
754 elem->type); 755 elem->type);
755 return NULL; 756 return NULL;
756 } 757 }
757 } 758 }
758 759
759 /** Pack an element into its protcol representation inside a dictionary. 760 /** Pack an element into its protcol representation inside a dictionary.
761 * See msim_msg_pack_element(). 762 * See msim_msg_pack_element().
762 */ 763 */
763 static void 764 static void
764 msim_msg_pack_element_dict(gpointer data, gpointer user_data) 765 msim_msg_pack_element_dict(gpointer data, gpointer user_data)
765 { 766 {
766 MsimMessageElement *elem; 767 MsimMessageElement *elem;
767 gchar *string, *data_string, ***items; 768 gchar *string, *data_string, ***items;
768 769
769 elem = (MsimMessageElement *)data; 770 elem = (MsimMessageElement *)data;
770 items = (gchar ***)user_data; 771 items = (gchar ***)user_data;
771 772
772 /* Exclude elements beginning with '_' from packed protocol messages. */ 773 /* Exclude elements beginning with '_' from packed protocol messages. */
773 if (elem->name[0] == '_') { 774 if (elem->name[0] == '_') {
774 return; 775 return;
775 } 776 }
776 777
777 data_string = msim_msg_pack_element_data(elem); 778 data_string = msim_msg_pack_element_data(elem);
778 779
779 g_return_if_fail(data_string != NULL); 780 g_return_if_fail(data_string != NULL);
780 781
781 switch (elem->type) { 782 switch (elem->type) {
782 /* These types are represented by key name/value pairs (converted above). */ 783 /* These types are represented by key name/value pairs (converted above). */
783 case MSIM_TYPE_INTEGER: 784 case MSIM_TYPE_INTEGER:
784 case MSIM_TYPE_RAW: 785 case MSIM_TYPE_RAW:
785 case MSIM_TYPE_STRING: 786 case MSIM_TYPE_STRING:
786 case MSIM_TYPE_BINARY: 787 case MSIM_TYPE_BINARY:
787 case MSIM_TYPE_DICTIONARY: 788 case MSIM_TYPE_DICTIONARY:
788 case MSIM_TYPE_LIST: 789 case MSIM_TYPE_LIST:
789 case MSIM_TYPE_BOOLEAN: /* Boolean is On or Off */ 790 case MSIM_TYPE_BOOLEAN: /* Boolean is On or Off */
790 string = g_strconcat(elem->name, "=", data_string, NULL); 791 string = g_strconcat(elem->name, "=", data_string, NULL);
791 break; 792 break;
792 793
793 default: 794 default:
794 g_free(data_string); 795 g_free(data_string);
881 * @return A string; caller must g_free(). 882 * @return A string; caller must g_free().
882 */ 883 */
883 gchar * 884 gchar *
884 msim_msg_pack_dict(MsimMessage *msg) 885 msim_msg_pack_dict(MsimMessage *msg)
885 { 886 {
886 g_return_val_if_fail(msg != NULL, NULL); 887 g_return_val_if_fail(msg != NULL, NULL);
887 888
888 return msim_msg_pack_using(msg, msim_msg_pack_element_dict, "\034", "", ""); 889 return msim_msg_pack_using(msg, msim_msg_pack_element_dict, "\034", "", "");
889 } 890 }
890 891
891 /** 892 /**
892 * Parse a raw protocol message string into a MsimMessage *. 893 * Parse a raw protocol message string into a MsimMessage *.
893 * 894 *
897 */ 898 */
898 MsimMessage * 899 MsimMessage *
899 msim_parse(gchar *raw) 900 msim_parse(gchar *raw)
900 { 901 {
901 MsimMessage *msg; 902 MsimMessage *msg;
902 gchar *token; 903 gchar *token;
903 gchar **tokens; 904 gchar **tokens;
904 gchar *key; 905 gchar *key;
905 gchar *value; 906 gchar *value;
906 int i; 907 int i;
907 908
908 g_return_val_if_fail(raw != NULL, NULL); 909 g_return_val_if_fail(raw != NULL, NULL);
909 910
910 purple_debug_info("msim", "msim_parse: got <%s>\n", raw); 911 purple_debug_info("msim", "msim_parse: got <%s>\n", raw);
911 912
912 key = NULL; 913 key = NULL;
913 914
914 /* All messages begin with a \. */ 915 /* All messages begin with a \. */
915 if (raw[0] != '\\' || raw[1] == 0) { 916 if (raw[0] != '\\' || raw[1] == 0) {
916 purple_debug_info("msim", "msim_parse: incomplete/bad string, " 917 purple_debug_info("msim", "msim_parse: incomplete/bad string, "
917 "missing initial backslash: <%s>\n", raw); 918 "missing initial backslash: <%s>\n", raw);
918 /* XXX: Should we try to recover, and read to first backslash? */ 919 /* XXX: Should we try to recover, and read to first backslash? */
919 920
920 g_free(raw); 921 g_free(raw);
921 return NULL; 922 return NULL;
922 } 923 }
923 924
924 msg = msim_msg_new(FALSE); 925 msg = msim_msg_new(FALSE);
925 926
926 for (tokens = g_strsplit(raw + 1, "\\", 0), i = 0; 927 for (tokens = g_strsplit(raw + 1, "\\", 0), i = 0;
927 (token = tokens[i]); 928 (token = tokens[i]);
928 i++) { 929 i++) {
929 #ifdef MSIM_DEBUG_PARSE 930 #ifdef MSIM_DEBUG_PARSE
930 purple_debug_info("msim", "tok=<%s>, i%2=%d\n", token, i % 2); 931 purple_debug_info("msim", "tok=<%s>, i%2=%d\n", token, i % 2);
931 #endif 932 #endif
932 if (i % 2) { 933 if (i % 2) {
933 /* Odd-numbered ordinal is a value. */ 934 /* Odd-numbered ordinal is a value. */
934 935
935 value = token; 936 value = token;
936 937
937 /* Incoming protocol messages get tagged as MSIM_TYPE_RAW, which 938 /* Incoming protocol messages get tagged as MSIM_TYPE_RAW, which
939 * convert to appropriate types for caller, and handle unescaping if needed. */ 940 * convert to appropriate types for caller, and handle unescaping if needed. */
940 msg = msim_msg_append(msg, g_strdup(key), MSIM_TYPE_RAW, g_strdup(value)); 941 msg = msim_msg_append(msg, g_strdup(key), MSIM_TYPE_RAW, g_strdup(value));
941 #ifdef MSIM_DEBUG_PARSE 942 #ifdef MSIM_DEBUG_PARSE
942 purple_debug_info("msim", "insert string: |%s|=|%s|\n", key, value); 943 purple_debug_info("msim", "insert string: |%s|=|%s|\n", key, value);
943 #endif 944 #endif
944 } else { 945 } else {
945 /* Even numbered indexes are key names. */ 946 /* Even numbered indexes are key names. */
946 key = token; 947 key = token;
947 } 948 }
948 } 949 }
949 g_strfreev(tokens); 950 g_strfreev(tokens);
950 951
951 /* Can free now since all data was copied to hash key/values */ 952 /* Can free now since all data was copied to hash key/values */
952 g_free(raw); 953 g_free(raw);
953 954
954 return msg; 955 return msg;
955 } 956 }
956 957
957 /** 958 /**
958 * Parse a \x1c-separated "dictionary" of key=value pairs into a hash table. 959 * Parse a \x1c-separated "dictionary" of key=value pairs into a hash table.
959 * 960 *
960 * @param body_str The text of the dictionary to parse. Often the 961 * @param body_str The text of the dictionary to parse. Often the
961 * value for the 'body' field. 962 * value for the 'body' field.
962 * 963 *
963 * @return Hash table of the keys and values. Must g_hash_table_destroy() when done. 964 * @return Hash table of the keys and values. Must g_hash_table_destroy() when done.
964 */ 965 */
965 GHashTable * 966 GHashTable *
966 msim_parse_body(const gchar *body_str) 967 msim_parse_body(const gchar *body_str)
967 { 968 {
968 GHashTable *table; 969 GHashTable *table;
969 gchar *item; 970 gchar *item;
970 gchar **items; 971 gchar **items;
971 gchar **elements; 972 gchar **elements;
972 guint i; 973 guint i;
973 974
974 g_return_val_if_fail(body_str != NULL, NULL); 975 g_return_val_if_fail(body_str != NULL, NULL);
975 976
976 table = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); 977 table = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
977 978
978 for (items = g_strsplit(body_str, "\x1c", 0), i = 0; 979 for (items = g_strsplit(body_str, "\x1c", 0), i = 0;
979 (item = items[i]); 980 (item = items[i]);
980 i++) { 981 i++) {
981 gchar *key, *value; 982 gchar *key, *value;
982 983
983 elements = g_strsplit(item, "=", 2); 984 elements = g_strsplit(item, "=", 2);
984 985
985 key = elements[0]; 986 key = elements[0];
986 if (!key) { 987 if (!key) {
987 purple_debug_info("msim", "msim_parse_body(%s): null key\n", 988 purple_debug_info("msim", "msim_parse_body(%s): null key\n",
988 body_str); 989 body_str);
989 g_strfreev(elements); 990 g_strfreev(elements);
990 break; 991 break;
991 } 992 }
992 993
993 value = elements[1]; 994 value = elements[1];
994 if (!value) { 995 if (!value) {
995 purple_debug_info("msim", "msim_parse_body(%s): null value\n", 996 purple_debug_info("msim", "msim_parse_body(%s): null value\n",
996 body_str); 997 body_str);
997 g_strfreev(elements); 998 g_strfreev(elements);
998 break; 999 break;
999 } 1000 }
1000 1001
1001 #ifdef MSIM_DEBUG_PARSE 1002 #ifdef MSIM_DEBUG_PARSE
1002 purple_debug_info("msim", "-- %s: %s\n", key ? key : "(NULL)", 1003 purple_debug_info("msim", "-- %s: %s\n", key ? key : "(NULL)",
1003 value ? value : "(NULL)"); 1004 value ? value : "(NULL)");
1004 #endif 1005 #endif
1005 1006
1006 /* XXX: This overwrites duplicates. */ 1007 /* XXX: This overwrites duplicates. */
1007 /* TODO: make the GHashTable values be GList's, and append to the list if 1008 /* TODO: make the GHashTable values be GList's, and append to the list if
1008 * there is already a value of the same key name. This is important for 1009 * there is already a value of the same key name. This is important for
1009 * the WebChallenge message. */ 1010 * the WebChallenge message. */
1010 g_hash_table_insert(table, g_strdup(key), g_strdup(value)); 1011 g_hash_table_insert(table, g_strdup(key), g_strdup(value));
1011 1012
1012 g_strfreev(elements); 1013 g_strfreev(elements);
1013 } 1014 }
1014 1015
1015 g_strfreev(items); 1016 g_strfreev(items);
1016 1017
1017 return table; 1018 return table;
1018 } 1019 }
1019 1020
1020 /** Search for and return the node in msg, matching name, or NULL. 1021 /** Search for and return the node in msg, matching name, or NULL.
1021 * 1022 *
1022 * @param msg Message to search within. 1023 * @param msg Message to search within.
1044 elem = i->data; 1045 elem = i->data;
1045 g_return_val_if_fail(elem != NULL, NULL); 1046 g_return_val_if_fail(elem != NULL, NULL);
1046 1047
1047 if (strcmp(elem->name, name) == 0) { 1048 if (strcmp(elem->name, name) == 0) {
1048 return i; 1049 return i;
1049 } 1050 }
1050 } 1051 }
1051 return NULL; 1052 return NULL;
1052 } 1053 }
1053 1054
1054 /** Return the first MsimMessageElement * with given name in the MsimMessage *. 1055 /** Return the first MsimMessageElement * with given name in the MsimMessage *.
1067 GList *node; 1068 GList *node;
1068 1069
1069 node = msim_msg_get_node(msg, name); 1070 node = msim_msg_get_node(msg, name);
1070 if (node) { 1071 if (node) {
1071 return (MsimMessageElement *)node->data; 1072 return (MsimMessageElement *)node->data;
1072 } else { 1073 } else {
1073 return NULL; 1074 return NULL;
1074 } 1075 }
1075 } 1076 }
1076 1077
1077 /** Return the data of an element of a given name, as a string. 1078 /** Return the data of an element of a given name, as a string.
1078 * 1079 *
1079 * @param name Name of element. 1080 * @param name Name of element.
1088 msim_msg_get_string(MsimMessage *msg, const gchar *name) 1089 msim_msg_get_string(MsimMessage *msg, const gchar *name)
1089 { 1090 {
1090 MsimMessageElement *elem; 1091 MsimMessageElement *elem;
1091 1092
1092 elem = msim_msg_get(msg, name); 1093 elem = msim_msg_get(msg, name);
1093 g_return_val_if_fail(elem != NULL , NULL); 1094 g_return_val_if_fail(elem != NULL , NULL);
1094 1095
1095 switch (elem->type) { 1096 switch (elem->type) {
1096 case MSIM_TYPE_INTEGER: 1097 case MSIM_TYPE_INTEGER:
1097 return g_strdup_printf("%d", GPOINTER_TO_UINT(elem->data)); 1098 return g_strdup_printf("%d", GPOINTER_TO_UINT(elem->data));
1098 1099
1114 1115
1115 /** Return an element as a new list. Caller frees with msim_msg_list_free(). */ 1116 /** Return an element as a new list. Caller frees with msim_msg_list_free(). */
1116 GList * 1117 GList *
1117 msim_msg_get_list(MsimMessage *msg, const gchar *name) 1118 msim_msg_get_list(MsimMessage *msg, const gchar *name)
1118 { 1119 {
1119 MsimMessageElement *elem; 1120 MsimMessageElement *elem;
1120 1121
1121 elem = msim_msg_get(msg, name); 1122 elem = msim_msg_get(msg, name);
1122 if (!elem) { 1123 if (!elem) {
1123 return NULL; 1124 return NULL;
1124 } 1125 }
1125 1126
1126 switch (elem->type) { 1127 switch (elem->type) {
1127 case MSIM_TYPE_LIST: 1128 case MSIM_TYPE_LIST:
1128 return msim_msg_list_copy((GList *)elem->data); 1129 return msim_msg_list_copy((GList *)elem->data);
1129 1130
1130 case MSIM_TYPE_RAW: 1131 case MSIM_TYPE_RAW:
1131 return msim_msg_list_parse((gchar *)elem->data); 1132 return msim_msg_list_parse((gchar *)elem->data);
1132 1133
1133 default: 1134 default:
1134 purple_debug_info("msim_msg_get_list", "type %d unknown, name %s\n", 1135 purple_debug_info("msim_msg_get_list", "type %d unknown, name %s\n",
1135 elem->type, name ? name : "(NULL)"); 1136 elem->type, name ? name : "(NULL)");
1136 return NULL; 1137 return NULL;
1137 } 1138 }
1138 } 1139 }
1139 1140
1140 /** Parse a \034-deliminated and =-separated string into a dictionary. TODO */ 1141 /** Parse a \034-deliminated and =-separated string into a dictionary. TODO */
1141 MsimMessage * 1142 MsimMessage *
1142 msim_msg_dictionary_parse(gchar *raw) 1143 msim_msg_dictionary_parse(gchar *raw)
1143 { 1144 {
1144 /* TODO - get code from msim_parse_body, but parse into MsimMessage */ 1145 /* TODO - get code from msim_parse_body, but parse into MsimMessage */
1145 return NULL; 1146 return NULL;
1146 } 1147 }
1147 1148
1148 /** Return an element as a new dictionary. Caller frees with msim_msg_free(). */ 1149 /** Return an element as a new dictionary. Caller frees with msim_msg_free(). */
1149 MsimMessage * 1150 MsimMessage *
1150 msim_msg_get_dictionary(MsimMessage *msg, const gchar *name) 1151 msim_msg_get_dictionary(MsimMessage *msg, const gchar *name)
1151 { 1152 {
1152 MsimMessageElement *elem; 1153 MsimMessageElement *elem;
1153 1154
1154 elem = msim_msg_get(msg, name); 1155 elem = msim_msg_get(msg, name);
1155 if (!elem) 1156 if (!elem) {
1156 { 1157 return NULL;
1157 return NULL; 1158 }
1158 } 1159
1159 1160 switch (elem->type) {
1160 switch (elem->type) { 1161 case MSIM_TYPE_DICTIONARY:
1161 case MSIM_TYPE_DICTIONARY: 1162 return msim_msg_clone((MsimMessage *)elem->data);
1162 return msim_msg_clone((MsimMessage *)elem->data); 1163
1163 1164 case MSIM_TYPE_RAW:
1164 case MSIM_TYPE_RAW: 1165 return msim_msg_dictionary_parse((gchar *)elem->data);
1165 return msim_msg_dictionary_parse((gchar *)elem->data); 1166
1166 1167 default:
1167 default: 1168 purple_debug_info("msim_msg_get_dictionary", "type %d unknown, name %s\n",
1168 purple_debug_info("msim_msg_get_dictionary", "type %d unknown, name %s\n", 1169 elem->type, name ? name : "(NULL)");
1169 elem->type, name ? name : "(NULL)"); 1170 return NULL;
1170 return NULL; 1171 }
1171 }
1172 } 1172 }
1173 1173
1174 /** Return the data of an element of a given name, as an integer. 1174 /** Return the data of an element of a given name, as an integer.
1175 * 1175 *
1176 * @param name Name of element. 1176 * @param name Name of element.
1188 1188
1189 elem = msim_msg_get(msg, name); 1189 elem = msim_msg_get(msg, name);
1190 1190
1191 if (!elem) { 1191 if (!elem) {
1192 return 0; 1192 return 0;
1193 } 1193 }
1194 1194
1195 switch (elem->type) { 1195 switch (elem->type) {
1196 case MSIM_TYPE_INTEGER: 1196 case MSIM_TYPE_INTEGER:
1197 return GPOINTER_TO_UINT(elem->data); 1197 return GPOINTER_TO_UINT(elem->data);
1198 1198
1218 msim_msg_get_binary(MsimMessage *msg, const gchar *name, 1218 msim_msg_get_binary(MsimMessage *msg, const gchar *name,
1219 gchar **binary_data, gsize *binary_length) 1219 gchar **binary_data, gsize *binary_length)
1220 { 1220 {
1221 MsimMessageElement *elem; 1221 MsimMessageElement *elem;
1222 1222
1223 GString *gs; 1223 GString *gs;
1224 1224
1225 elem = msim_msg_get(msg, name); 1225 elem = msim_msg_get(msg, name);
1226 if (!elem) { 1226 if (!elem) {
1227 return FALSE; 1227 return FALSE;
1228 } 1228 }
1229 1229
1230 switch (elem->type) { 1230 switch (elem->type) {
1231 case MSIM_TYPE_RAW: 1231 case MSIM_TYPE_RAW:
1232 /* Incoming messages are tagged with MSIM_TYPE_RAW, and 1232 /* Incoming messages are tagged with MSIM_TYPE_RAW, and
1233 * converted appropriately. They can still be "strings", just they won't 1233 * converted appropriately. They can still be "strings", just they won't
1251 */ 1251 */
1252 *binary_data = (gchar *)purple_base64_decode((const gchar *)elem->data, binary_length); 1252 *binary_data = (gchar *)purple_base64_decode((const gchar *)elem->data, binary_length);
1253 return TRUE; 1253 return TRUE;
1254 1254
1255 case MSIM_TYPE_BINARY: 1255 case MSIM_TYPE_BINARY:
1256 gs = (GString *)elem->data; 1256 gs = (GString *)elem->data;
1257 1257
1258 /* Duplicate data, so caller can g_free() it. */ 1258 /* Duplicate data, so caller can g_free() it. */
1259 *binary_data = g_new0(char, gs->len); 1259 *binary_data = g_new0(char, gs->len);
1260 memcpy(*binary_data, gs->str, gs->len); 1260 memcpy(*binary_data, gs->str, gs->len);
1261 1261
1262 *binary_length = gs->len; 1262 *binary_length = gs->len;
1263 1263
1264 return TRUE; 1264 return TRUE;
1265 1265
1266 1266
1267 /* Rejected because if it isn't already a GString, have to g_new0 it and 1267 /* Rejected because if it isn't already a GString, have to g_new0 it and
1268 * then caller has to ALSO free the GString! 1268 * then caller has to ALSO free the GString!
1269 * 1269 *