comparison libpurple/protocols/myspace/message.c @ 17973:acff371d7908

Fix crash when deleting buddies on Windows. This was done by correctly printing null strings in MsimMessage debug messages, since _uid_before had a NULL value when being sent to postprocessing. Closes #2400.
author Jeffrey Connelly <jaconnel@calpoly.edu>
date Sat, 04 Aug 2007 17:43:37 +0000
parents a2298513db8b
children b2d81d13f015
comparison
equal deleted inserted replaced
17972:8f49acac9d1c 17973:acff371d7908
116 static MsimMessage * 116 static MsimMessage *
117 msim_msg_new_v(va_list argp) 117 msim_msg_new_v(va_list argp)
118 { 118 {
119 gchar *key, *value; 119 gchar *key, *value;
120 MsimMessageType type; 120 MsimMessageType type;
121 GString *gs;
122 GList *gl;
123 MsimMessage *msg; 121 MsimMessage *msg;
124 122
125 /* Begin with an empty message. */ 123 /* Begin with an empty message. */
126 msg = NULL; 124 msg = NULL;
127 125
151 149
152 msg = msim_msg_append(msg, key, type, value); 150 msg = msim_msg_append(msg, key, type, value);
153 break; 151 break;
154 152
155 case MSIM_TYPE_BINARY: 153 case MSIM_TYPE_BINARY:
156 gs = va_arg(argp, GString *); 154 {
157 155 GString *gs;
158 g_return_val_if_fail(gs != NULL, FALSE); 156
159 157 gs = va_arg(argp, GString *);
160 /* msim_msg_free() will free this GString the caller created. */ 158
161 msg = msim_msg_append(msg, key, type, gs); 159 g_return_val_if_fail(gs != NULL, FALSE);
162 break; 160
161 /* msim_msg_free() will free this GString the caller created. */
162 msg = msim_msg_append(msg, key, type, gs);
163 break;
164 }
163 165
164 case MSIM_TYPE_LIST: 166 case MSIM_TYPE_LIST:
165 gl = va_arg(argp, GList *); 167 {
166 168 GList *gl;
167 g_return_val_if_fail(gl != NULL, FALSE); 169
168 170 gl = va_arg(argp, GList *);
169 msg = msim_msg_append(msg, key, type, gl); 171
172 g_return_val_if_fail(gl != NULL, FALSE);
173
174 msg = msim_msg_append(msg, key, type, gl);
175 break;
176 }
177
178 case MSIM_TYPE_DICTIONARY:
179 {
180 MsimMessage *dict;
181
182 dict = va_arg(argp, MsimMessage *);
183
184 g_return_val_if_fail(dict != NULL, FALSE);
185
186 msg = msim_msg_append(msg, key, type, dict);
187 break;
188 }
170 189
171 default: 190 default:
172 purple_debug_info("msim", "msim_send: unknown type %d\n", type); 191 purple_debug_info("msim", "msim_send: unknown type %d\n", type);
173 break; 192 break;
174 } 193 }
266 gs = (GString *)elem->data; 285 gs = (GString *)elem->data;
267 286
268 new_data = g_string_new_len(gs->str, gs->len); 287 new_data = g_string_new_len(gs->str, gs->len);
269 } 288 }
270 break; 289 break;
271 /* TODO: other types */ 290 case MSIM_TYPE_DICTIONARY:
291 {
292 MsimMessage *dict;
293
294 dict = (MsimMessage *)elem->data;
295
296 new_data = msim_msg_clone(dict);
297 }
298 break;
299
272 default: 300 default:
273 purple_debug_info("msim", "msim_msg_clone_element: unknown type %d\n", elem->type); 301 purple_debug_info("msim", "msim_msg_clone_element: unknown type %d\n", elem->type);
274 g_return_if_fail(NULL); 302 g_return_if_fail(NULL);
275 } 303 }
276 304
328 /* Free the GString itself and the binary data. */ 356 /* Free the GString itself and the binary data. */
329 g_string_free((GString *)elem->data, TRUE); 357 g_string_free((GString *)elem->data, TRUE);
330 break; 358 break;
331 359
332 case MSIM_TYPE_DICTIONARY: 360 case MSIM_TYPE_DICTIONARY:
333 /* TODO: free dictionary */ 361 msim_msg_free((MsimMessage *)elem->data);
334 break; 362 break;
335 363
336 case MSIM_TYPE_LIST: 364 case MSIM_TYPE_LIST:
337 g_list_free((GList *)elem->data); 365 g_list_free((GList *)elem->data);
338 break; 366 break;
450 * 478 *
451 * * MSIM_TYPE_RAW: gchar *. The data WILL BE FREED - use g_strdup() if needed. 479 * * MSIM_TYPE_RAW: gchar *. The data WILL BE FREED - use g_strdup() if needed.
452 * 480 *
453 * * MSIM_TYPE_BINARY: g_string_new_len(data, length). The data AND GString will be freed. 481 * * MSIM_TYPE_BINARY: g_string_new_len(data, length). The data AND GString will be freed.
454 * 482 *
455 * * MSIM_TYPE_DICTIONARY: TODO 483 * * MSIM_TYPE_DICTIONARY: An MsimMessage *. Freed when message is destroyed.
456 * 484 *
457 * * MSIM_TYPE_LIST: GList * of gchar *. Again, everything will be freed. 485 * * MSIM_TYPE_LIST: GList * of gchar *. Again, everything will be freed.
458 * 486 *
459 * */ 487 * */
460 MsimMessage * 488 MsimMessage *
538 items = user_data; 566 items = user_data;
539 567
540 switch (elem->type) 568 switch (elem->type)
541 { 569 {
542 case MSIM_TYPE_INTEGER: 570 case MSIM_TYPE_INTEGER:
543 string = g_strdup_printf("%s(integer): %d", elem->name, GPOINTER_TO_UINT(elem->data)); 571 string = g_strdup_printf("%s(integer): %d", elem->name,
572 GPOINTER_TO_UINT(elem->data));
544 break; 573 break;
545 574
546 case MSIM_TYPE_RAW: 575 case MSIM_TYPE_RAW:
547 string = g_strdup_printf("%s(raw): %s", elem->name, (gchar *)elem->data); 576 string = g_strdup_printf("%s(raw): %s", elem->name,
577 elem->data ? (gchar *)elem->data : "(NULL)");
548 break; 578 break;
549 579
550 case MSIM_TYPE_STRING: 580 case MSIM_TYPE_STRING:
551 string = g_strdup_printf("%s(string): %s", elem->name, (gchar *)elem->data); 581 string = g_strdup_printf("%s(string): %s", elem->name,
582 elem->data ? (gchar *)elem->data : "(NULL)");
552 break; 583 break;
553 584
554 case MSIM_TYPE_BINARY: 585 case MSIM_TYPE_BINARY:
555 gs = (GString *)elem->data; 586 gs = (GString *)elem->data;
556 binary = purple_base64_encode((guchar*)gs->str, gs->len); 587 binary = purple_base64_encode((guchar*)gs->str, gs->len);
558 g_free(binary); 589 g_free(binary);
559 break; 590 break;
560 591
561 case MSIM_TYPE_BOOLEAN: 592 case MSIM_TYPE_BOOLEAN:
562 string = g_strdup_printf("%s(boolean): %s", elem->name, 593 string = g_strdup_printf("%s(boolean): %s", elem->name,
563 GPOINTER_TO_UINT(elem->data) ? "TRUE" : "FALSE"); 594 elem->data ? "TRUE" : "FALSE");
564 break; 595 break;
565 596
566 case MSIM_TYPE_DICTIONARY: 597 case MSIM_TYPE_DICTIONARY:
567 /* TODO: provide human-readable output of dictionary. */ 598 {
568 string = g_strdup_printf("%s(dict): TODO", elem->name); 599 gchar *s;
600
601 if (!elem->data)
602 s = g_strdup("(NULL)");
603 else
604 s = msim_msg_dump_to_str((MsimMessage *)elem->data);
605
606 if (!s)
607 s = g_strdup("(NULL, couldn't msim_msg_dump_to_str)");
608
609 string = g_strdup_printf("%s(dict): %s", elem->name, s);
610
611 g_free(s);
612 }
569 break; 613 break;
570 614
571 case MSIM_TYPE_LIST: 615 case MSIM_TYPE_LIST:
572 { 616 {
573 GString *gs; 617 GString *gs;
587 string = gs->str; 631 string = gs->str;
588 } 632 }
589 break; 633 break;
590 634
591 default: 635 default:
592 string = g_strdup_printf("%s(unknown type %d", elem->name, elem->type); 636 string = g_strdup_printf("%s(unknown type %d",
637 elem->name ? elem->name : "(NULL)", elem->type);
593 break; 638 break;
594 } 639 }
595 640
596 **items = string; 641 **items = string;
597 ++(*items); 642 ++(*items);
601 * 646 *
602 * @param fmt_string A static string, in which '%s' will be replaced. 647 * @param fmt_string A static string, in which '%s' will be replaced.
603 */ 648 */
604 void 649 void
605 msim_msg_dump(const gchar *fmt_string, MsimMessage *msg) 650 msim_msg_dump(const gchar *fmt_string, MsimMessage *msg)
651 {
652 gchar *debug_str;
653
654 g_return_if_fail(fmt_string != NULL);
655
656 debug_str = msim_msg_dump_to_str(msg);
657
658 g_return_if_fail(debug_str != NULL);
659
660 purple_debug_info("msim_msg_dump", "debug_str=%s\n", debug_str);
661
662
663 purple_debug_info("msim", fmt_string, debug_str);
664
665 g_free(debug_str);
666 }
667
668 /** Return a human-readable string of the message.
669 *
670 * @return A new gchar *, must be g_free()'d.
671 */
672 gchar *
673 msim_msg_dump_to_str(MsimMessage *msg)
606 { 674 {
607 gchar *debug_str; 675 gchar *debug_str;
608 676
609 if (!msg) 677 if (!msg)
610 { 678 {
612 } else { 680 } else {
613 debug_str = msim_msg_pack_using(msg, msim_msg_debug_string_element, 681 debug_str = msim_msg_pack_using(msg, msim_msg_debug_string_element,
614 "\n", "<MsimMessage: \n", "\n/MsimMessage>"); 682 "\n", "<MsimMessage: \n", "\n/MsimMessage>");
615 } 683 }
616 684
617 g_return_if_fail(debug_str != NULL); 685 return debug_str;
618
619 purple_debug_info("msim", fmt_string, debug_str);
620
621 g_free(debug_str);
622 } 686 }
623 687
624 /** Return a message element data as a new string for a raw protocol message, converting from other types (integer, etc.) if necessary. 688 /** Return a message element data as a new string for a raw protocol message, converting from other types (integer, etc.) if necessary.
625 * 689 *
626 * @return const gchar * The data as a string, or NULL. Caller must g_free(). 690 * @return const gchar * The data as a string, or NULL. Caller must g_free().
641 /* Not un-escaped - this is a raw element, already escaped if necessary. */ 705 /* Not un-escaped - this is a raw element, already escaped if necessary. */
642 return (gchar *)g_strdup((gchar *)elem->data); 706 return (gchar *)g_strdup((gchar *)elem->data);
643 707
644 case MSIM_TYPE_STRING: 708 case MSIM_TYPE_STRING:
645 /* Strings get escaped. msim_escape() creates a new string. */ 709 /* Strings get escaped. msim_escape() creates a new string. */
646 return msim_escape((gchar *)elem->data); 710 g_return_val_if_fail(elem->data != NULL, NULL);
711 return elem->data ? msim_escape((gchar *)elem->data) :
712 g_strdup("(NULL)");
647 713
648 case MSIM_TYPE_BINARY: 714 case MSIM_TYPE_BINARY:
649 { 715 {
650 GString *gs; 716 GString *gs;
651 717
653 /* Do not escape! */ 719 /* Do not escape! */
654 return purple_base64_encode((guchar *)gs->str, gs->len); 720 return purple_base64_encode((guchar *)gs->str, gs->len);
655 } 721 }
656 722
657 case MSIM_TYPE_BOOLEAN: 723 case MSIM_TYPE_BOOLEAN:
658 /* Not used by the wire protocol * -- see msim_msg_pack_element. */ 724 /* Not used by messages in the wire protocol * -- see msim_msg_pack_element.
659 return NULL; 725 * Only used by dictionaries, see msim_msg_pack_element_dict. */
726 return elem->data ? g_strdup("On") : g_strdup("Off");
660 727
661 case MSIM_TYPE_DICTIONARY: 728 case MSIM_TYPE_DICTIONARY:
662 /* TODO: pack using k=v\034k2=v2\034... */ 729 /* TODO: pack using k=v\034k2=v2\034... */
663 return NULL; 730 return msim_msg_pack_dict((MsimMessage *)elem->data);
664 731
665 case MSIM_TYPE_LIST: 732 case MSIM_TYPE_LIST:
666 /* Pack using a|b|c|d|... */ 733 /* Pack using a|b|c|d|... */
667 { 734 {
668 GString *gs; 735 GString *gs;
682 purple_debug_info("msim", "field %s, unknown type %d\n", elem->name, elem->type); 749 purple_debug_info("msim", "field %s, unknown type %d\n", elem->name, elem->type);
683 return NULL; 750 return NULL;
684 } 751 }
685 } 752 }
686 753
754 /** Pack an element into its protcol representation inside a dictionary.
755 *
756 * See msim_msg_pack_element().
757 */
758 static void
759 msim_msg_pack_element_dict(gpointer data, gpointer user_data)
760 {
761 MsimMessageElement *elem;
762 gchar *string, *data_string, ***items;
763
764 elem = (MsimMessageElement *)data;
765 items = (gchar ***)user_data;
766
767 /* Exclude elements beginning with '_' from packed protocol messages. */
768 if (elem->name[0] == '_')
769 {
770 return;
771 }
772
773 data_string = msim_msg_pack_element_data(elem);
774
775 g_return_if_fail(data_string != NULL);
776
777 switch (elem->type)
778 {
779 /* These types are represented by key name/value pairs (converted above). */
780 case MSIM_TYPE_INTEGER:
781 case MSIM_TYPE_RAW:
782 case MSIM_TYPE_STRING:
783 case MSIM_TYPE_BINARY:
784 case MSIM_TYPE_DICTIONARY:
785 case MSIM_TYPE_LIST:
786 case MSIM_TYPE_BOOLEAN: /* Boolean is On or Off */
787 string = g_strconcat(elem->name, "\\", data_string, NULL);
788 break;
789
790 default:
791 g_free(data_string);
792 g_return_if_fail(FALSE);
793 break;
794 }
795
796 g_free(data_string);
797
798 **items = string;
799 ++(*items);
800 }
801
687 /** Pack an element into its protocol representation. 802 /** Pack an element into its protocol representation.
688 * 803 *
689 * @param data Pointer to an MsimMessageElement. 804 * @param data Pointer to an MsimMessageElement.
690 * @param user_data Pointer to a gchar ** array of string items. 805 * @param user_data Pointer to a gchar ** array of string items.
691 * 806 *
700 MsimMessageElement *elem; 815 MsimMessageElement *elem;
701 gchar *string, *data_string; 816 gchar *string, *data_string;
702 gchar ***items; 817 gchar ***items;
703 818
704 elem = (MsimMessageElement *)data; 819 elem = (MsimMessageElement *)data;
705 items = user_data; 820 items = (gchar ***)user_data;
706 821
707 /* Exclude elements beginning with '_' from packed protocol messages. */ 822 /* Exclude elements beginning with '_' from packed protocol messages. */
708 if (elem->name[0] == '_') 823 if (elem->name[0] == '_')
709 { 824 {
710 return; 825 return;
747 **items = string; 862 **items = string;
748 ++(*items); 863 ++(*items);
749 } 864 }
750 865
751 866
752 /** Return a packed string suitable for sending over the wire. 867 /** Return a packed string of a message suitable for sending over the wire.
753 * 868 *
754 * @return A string. Caller must g_free(). 869 * @return A string. Caller must g_free().
755 */ 870 */
756 gchar * 871 gchar *
757 msim_msg_pack(MsimMessage *msg) 872 msim_msg_pack(MsimMessage *msg)
758 { 873 {
759 g_return_val_if_fail(msg != NULL, NULL); 874 g_return_val_if_fail(msg != NULL, NULL);
760 875
761 return msim_msg_pack_using(msg, msim_msg_pack_element, "\\", "\\", "\\final\\"); 876 return msim_msg_pack_using(msg, msim_msg_pack_element, "\\", "\\", "\\final\\");
877 }
878
879 /** Return a packed string of a dictionary, suitable for embedding in MSIM_TYPE_DICTIONARY.
880 *
881 * @return A string; caller must g_free().
882 */
883 gchar *
884 msim_msg_pack_dict(MsimMessage *msg)
885 {
886 g_return_val_if_fail(msg != NULL, NULL);
887
888 return msim_msg_pack_using(msg, msim_msg_pack_element_dict, "\034", "", "");
762 } 889 }
763 890
764 /** 891 /**
765 * Parse a raw protocol message string into a MsimMessage *. 892 * Parse a raw protocol message string into a MsimMessage *.
766 * 893 *
1003 return NULL; 1130 return NULL;
1004 1131
1005 switch (elem->type) 1132 switch (elem->type)
1006 { 1133 {
1007 case MSIM_TYPE_LIST: 1134 case MSIM_TYPE_LIST:
1008 return msim_msg_list_copy((GList *)(elem->data)); 1135 return msim_msg_list_copy((GList *)elem->data);
1009 1136
1010 case MSIM_TYPE_RAW: 1137 case MSIM_TYPE_RAW:
1011 return msim_msg_list_parse((gchar *)(elem->data)); 1138 return msim_msg_list_parse((gchar *)elem->data);
1012 1139
1013 default: 1140 default:
1014 purple_debug_info("msim_msg_get_list", "type %d unknown, name %s\n", 1141 purple_debug_info("msim_msg_get_list", "type %d unknown, name %s\n",
1142 elem->type, name);
1143 return NULL;
1144 }
1145 }
1146
1147 /** Parse a \034-deliminated and =-separated string into a dictionary. TODO */
1148 MsimMessage *
1149 msim_msg_dictionary_parse(gchar *raw)
1150 {
1151 /* TODO - get code from msim_parse_body, but parse into MsimMessage */
1152 return NULL;
1153 }
1154
1155 /** Return an element as a new dictionary. Caller frees with msim_msg_free(). */
1156 MsimMessage *
1157 msim_msg_get_dictionary(MsimMessage *msg, const gchar *name)
1158 {
1159 MsimMessageElement *elem;
1160
1161 elem = msim_msg_get(msg, name);
1162 if (!elem)
1163 return NULL;
1164
1165 switch (elem->type)
1166 {
1167 case MSIM_TYPE_DICTIONARY:
1168 return msim_msg_clone((MsimMessage *)elem->data);
1169
1170 case MSIM_TYPE_RAW:
1171 return msim_msg_dictionary_parse((gchar *)elem->data);
1172
1173 default:
1174 purple_debug_info("msim_msg_get_dictionary", "type %d unknown, name %s\n",
1015 elem->type, name); 1175 elem->type, name);
1016 return NULL; 1176 return NULL;
1017 } 1177 }
1018 } 1178 }
1019 1179