comparison libpurple/protocols/oscar/family_icbm.c @ 29852:a538cb73f897

propagate from branch 'im.pidgin.pidgin' (head b0098e2250f135d121960d8152e144e7e344125e) to branch 'im.pidgin.cpw.rekkanoryo.icqxstatus' (head dcd3ab65d5cfcd79b00a7b95ab5fe788da64c112)
author Marcus Lundblad <ml@update.uu.se>
date Sun, 07 Feb 2010 19:31:56 +0000
parents 28d73d34d792 5391094529c6
children a0fb6798d87c
comparison
equal deleted inserted replaced
29372:791606778223 29852:a538cb73f897
2622 aim_rxcallback_t userfunc; 2622 aim_rxcallback_t userfunc;
2623 guint16 channel, reason; 2623 guint16 channel, reason;
2624 char *bn; 2624 char *bn;
2625 guchar *cookie; 2625 guchar *cookie;
2626 guint8 bnlen; 2626 guint8 bnlen;
2627 char *xml = NULL;
2628 int hdrlen;
2629 int curpos;
2630 int num1,num2;
2631 char *desc, *title, *temp;
2632 PurpleAccount *account;
2633 PurpleBuddy *buddy;
2634 PurplePresence *presence;
2635 PurpleStatus *status;
2627 2636
2628 cookie = byte_stream_getraw(bs, 8); 2637 cookie = byte_stream_getraw(bs, 8);
2629 channel = byte_stream_get16(bs); 2638 channel = byte_stream_get16(bs);
2630 bnlen = byte_stream_get8(bs); 2639 bnlen = byte_stream_get8(bs);
2631 bn = byte_stream_getstr(bs, bnlen); 2640 bn = byte_stream_getstr(bs, bnlen);
2632 reason = byte_stream_get16(bs); 2641 reason = byte_stream_get16(bs);
2633 2642
2634 if (channel == 0x0002) 2643 if (channel == 0x0002)
2635 { 2644 {
2636 if (reason == 0x0003) /* channel-specific */ 2645 hdrlen = byte_stream_getle16(bs);
2637 /* parse status note text */ 2646 if ( ((hdrlen == 27 ) && (bs->len > (27 + 51)))) {
2638 parse_status_note_text(od, cookie, bn, bs); 2647 byte_stream_advance(bs, 51);
2639 2648 num1 = byte_stream_getle16(bs);
2640 byte_stream_get16(bs); /* Unknown */ 2649 num2 = byte_stream_getle16(bs);
2641 byte_stream_get16(bs); /* Unknown */ 2650 purple_debug_misc("oscar", "X-Status: Num1 %i, num2 %i\n",num1, num2);
2642 if ((userfunc = aim_callhandler(od, snac->family, snac->subtype))) 2651
2643 ret = userfunc(od, conn, frame, channel, bn, reason, cookie); 2652 if(((num1 == 0x4f00)&&(num2 == 0x3b00))) {
2653 byte_stream_advance(bs, 86);
2654 curpos = byte_stream_curpos(bs);
2655 xml = byte_stream_getstr(bs, bs->len - curpos);
2656 purple_debug_misc("oscar", "X-Status: Received XML reply\n");
2657 if(xml) {
2658 /* purple_debug_misc("oscar", "X-Status: XML reply: %s\n", (const char*) xml); */
2659 if ((desc=strstr(xml,"&lt;desc&gt;")) != NULL) {
2660 temp=strstr(xml,"&lt;/desc&gt;");
2661 temp[0]=0;
2662 desc=desc+12;
2663 }
2664 if ((title=strstr(xml,"&lt;title&gt;")) != NULL) {
2665 temp=strstr(xml,"&lt;/title&gt;");
2666 temp[0]=0;
2667 title=title+13;
2668 } else {
2669 title="";
2670 }
2671 strcpy(xml,title);
2672 if (desc) {
2673 strcat(xml, " - ");
2674 strcat(xml, desc);
2675 }
2676 purple_debug_misc("oscar", "X-Status reply: %s\n", (const char*)xml);
2677 account = purple_connection_get_account(od->gc);
2678 buddy = purple_find_buddy(account, sn);
2679 presence = purple_buddy_get_presence(buddy);
2680 status = purple_presence_get_active_status(presence);
2681 purple_prpl_got_user_status(account, sn,
2682 purple_status_get_id(status), "message", xml, NULL);
2683 } else {
2684 purple_debug_misc("oscar", "X-Status: Can't get XML reply string\n");
2685 }
2686 } else {
2687 purple_debug_misc("oscar", "X-Status: 0x0004, 0x000b not an xstatus reply\n" );
2688 /* if ((userfunc = aim_callhandler(od, snac->family, snac->subtype)))
2689 ret = userfunc(od, conn, frame, channel, sn, reason); */
2690 }
2691
2692 }
2644 2693
2645 } else if (channel == 0x0004) { /* ICQ message */ 2694 } else if (channel == 0x0004) { /* ICQ message */
2646 switch (reason) { 2695 switch (reason) {
2647 case 0x0003: { /* ICQ status message. Maybe other stuff too, you never know with these people. */ 2696 case 0x0003: { /* ICQ status message. Maybe other stuff too, you never know with these people. */
2648 guint8 statusmsgtype, *msg; 2697 guint8 statusmsgtype, *msg;
2697 } /* end switch */ 2746 } /* end switch */
2698 } 2747 }
2699 2748
2700 g_free(cookie); 2749 g_free(cookie);
2701 g_free(bn); 2750 g_free(bn);
2751 g_free(xml);
2702 2752
2703 return ret; 2753 return ret;
2704 } 2754 }
2705 2755
2706 /* 2756 /*
2799 */ 2849 */
2800 byte_stream_put16(&bs, event); 2850 byte_stream_put16(&bs, event);
2801 2851
2802 flap_connection_send_snac(od, conn, SNAC_FAMILY_ICBM, 0x0014, 0x0000, snacid, &bs); 2852 flap_connection_send_snac(od, conn, SNAC_FAMILY_ICBM, 0x0014, 0x0000, snacid, &bs);
2803 2853
2854 byte_stream_destroy(&bs);
2855
2856 return 0;
2857 }
2858
2859 /*
2860 * Subtype 0x0006 - Send eXtra Status request
2861 */
2862 int icq_im_xstatus_request(OscarData *od, const char *sn)
2863 {
2864 FlapConnection *conn;
2865 aim_snacid_t snacid;
2866 guchar cookie[8];
2867 GSList *outer_tlvlist = NULL, *inner_tlvlist = NULL;
2868 ByteStream bs, header, plugindata;
2869 PurpleAccount *account;
2870 const char *fmt;
2871 char *statxml;
2872 int xmllen;
2873
2874 static const guint8 pluginid[] =
2875 {
2876 0x09, 0x46, 0x13, 0x49, 0x4C, 0x7F, 0x11, 0xD1,
2877 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00
2878 };
2879
2880 static const guint8 c_plugindata[] =
2881 {
2882 0x1B, 0x00, 0x0A,
2883 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2884 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0xF9, 0xD1, 0x0E, 0x00, 0xF9, 0xD1, 0x00, 0x00,
2885 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1A, 0x00, 0x00, 0x00, 0x01, 0x00,
2886 0x01, 0x00, 0x00, 0x4F, 0x00, 0x3B, 0x60, 0xB3, 0xEF, 0xD8, 0x2A, 0x6C, 0x45, 0xA4, 0xE0, 0x9C,
2887 0x5A, 0x5E, 0x67, 0xE8, 0x65, 0x08, 0x00, 0x2A, 0x00, 0x00, 0x00, 0x53, 0x63, 0x72, 0x69, 0x70,
2888 0x74, 0x20, 0x50, 0x6C, 0x75, 0x67, 0x2D, 0x69, 0x6E, 0x3A, 0x20, 0x52, 0x65, 0x6D, 0x6F, 0x74,
2889 0x65, 0x20, 0x4E, 0x6F, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41,
2890 0x72, 0x72, 0x69, 0x76, 0x65, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2891 0x00, 0x00, 0x00, 0x00, 0x14, 0x01, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00
2892 };
2893
2894 if (!od || !(conn = flap_connection_findbygroup(od, 0x0004)))
2895 return -EINVAL;
2896
2897 if (!sn)
2898 return -EINVAL;
2899
2900 fmt = "<N><QUERY>&lt;Q&gt;&lt;PluginID&gt;srvMng&lt;/PluginID&gt;&lt;/Q&gt;</QUERY><NOTIFY>&lt;srv&gt;&lt;id&gt;cAwaySrv&lt;/id&gt;&lt;req&gt;&lt;id&gt;AwayStat&lt;/id&gt;&lt;trans&gt;2&lt;/trans&gt;&lt;senderId&gt;%s&lt;/senderId&gt;&lt;/req&gt;&lt;/srv&gt;</NOTIFY></N>\r\n";
2901
2902 account = purple_connection_get_account(od->gc);
2903 xmllen = strlen(fmt) - 2 + strlen(account->username);
2904
2905 statxml = (char*) g_malloc(xmllen);
2906 snprintf(statxml, xmllen, fmt, account->username);
2907
2908 aim_icbm_makecookie(cookie);
2909
2910 byte_stream_new(&bs, 10 + 8 + 2 + 1 + strlen(sn) + 2
2911 + 2 + 2 + 8 + 16 + 2 + 2 + 2 + 2 + 2
2912 + 2 + 2 + sizeof(c_plugindata) + xmllen
2913 + 2 + 2);
2914
2915 snacid = aim_cachesnac(od, 0x0004, 0x0006, 0x0000, NULL, 0);
2916 aim_im_puticbm(&bs, cookie, 0x0002, sn);
2917
2918 byte_stream_new(&header, (7*2) + 16 + 8 + 2 + sizeof(c_plugindata) + xmllen); /* TLV 0x0005 Stream + Size */
2919 byte_stream_new(&plugindata, (sizeof(c_plugindata) + xmllen));
2920
2921 byte_stream_put16(&header, 0x0000); /* Message Type: Request */
2922 byte_stream_putraw(&header, cookie, sizeof(cookie)); /* Message ID */
2923 byte_stream_putraw(&header, pluginid, sizeof(pluginid)); /* Plugin ID */
2924
2925 aim_tlvlist_add_16(&inner_tlvlist, 0x000a, 0x0001);
2926 aim_tlvlist_add_noval(&inner_tlvlist, 0x000f);
2927
2928 /* Add Plugin Specific Data */
2929 byte_stream_putraw(&plugindata, c_plugindata, sizeof(c_plugindata)); /* Content of TLV 0x2711 */
2930 byte_stream_putstr(&plugindata, statxml);
2931
2932 aim_tlvlist_add_raw(&inner_tlvlist, 0x2711, (sizeof(c_plugindata) + xmllen), plugindata.data);
2933
2934 aim_tlvlist_write(&header, &inner_tlvlist);
2935
2936
2937 aim_tlvlist_add_raw(&outer_tlvlist, 0x0005, byte_stream_curpos(&header), header.data);
2938 aim_tlvlist_add_noval(&outer_tlvlist, 0x0003); /* Empty TLV 0x0003 */
2939
2940 aim_tlvlist_write(&bs, &outer_tlvlist);
2941
2942 purple_debug_misc("oscar", "X-Status Request\n");
2943 flap_connection_send_snac_with_priority(od, conn, 0x0004, 0x0006, 0x0000, snacid, &bs, TRUE);
2944
2945 aim_tlvlist_free(inner_tlvlist);
2946 aim_tlvlist_free(outer_tlvlist);
2947 byte_stream_destroy(&header);
2948 byte_stream_destroy(&plugindata);
2949 byte_stream_destroy(&bs);
2950 g_free(statxml);
2951
2952 return 0;
2953 }
2954
2955 int icq_relay_xstatus(OscarData *od, const char *sn, const guchar *cookie)
2956 {
2957 FlapConnection *conn;
2958 ByteStream bs;
2959 aim_snacid_t snacid;
2960 PurpleAccount *account;
2961 PurpleStatus *status;
2962 const char *fmt;
2963 const char *formatted_msg;
2964 char *msg;
2965 char *statxml;
2966 const char *title;
2967 int len;
2968
2969 static const guint8 plugindata[] = {
2970 0x1B, 0x00,
2971 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2972 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2973 0x01, 0x00, 0x00, 0x00, 0x00, 0xF9, 0xD1, 0x0E, 0x00, 0xF9, 0xD1,
2974 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2975 0x00, 0x1A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x4F,
2976 0x00, 0x3B, 0x60, 0xB3, 0xEF, 0xD8, 0x2A, 0x6C, 0x45, 0xA4, 0xE0,
2977 0x9C, 0x5A, 0x5E, 0x67, 0xE8, 0x65, 0x08, 0x00, 0x2A, 0x00, 0x00,
2978 0x00, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x20, 0x50, 0x6C, 0x75,
2979 0x67, 0x2D, 0x69, 0x6E, 0x3A, 0x20, 0x52, 0x65, 0x6D, 0x6F, 0x74,
2980 0x65, 0x20, 0x4E, 0x6F, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74,
2981 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x72, 0x72, 0x69, 0x76, 0x65, 0x00,
2982 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2983 0x00, 0x00, 0x00, 0xF3, 0x01, 0x00, 0x00, 0xEF, 0x01, 0x00, 0x00
2984 };
2985
2986 fmt = "<NR><RES>&lt;ret event='OnRemoteNotification'&gt;&lt;srv&gt;&lt;id&gt;cAwaySrv&lt;/id&gt;&lt;val srv_id='cAwaySrv'&gt;&lt;Root&gt;&lt;CASXtraSetAwayMessage&gt;&lt;/CASXtraSetAwayMessage&gt;&l t;uin&gt;%s&lt;/uin&gt;&lt;index&gt;1&lt;/index&gt;&lt;title&gt;%s&lt;/title&gt;&lt;desc&gt;%s&lt;/desc&gt;&lt;/Root&gt;&lt;/val&gt;&lt;/srv&gt;&lt;srv&gt;&lt;id&gt;cRandomizerSrv&lt;/id&gt;&lt;val srv_id='cRandomizerSrv'&gt;undefined&lt;/val&gt;&lt;/srv&gt;&lt;/ret&gt;</RES></NR>\r\n";
2987
2988
2989 if (!od || !(conn = flap_connection_findbygroup(od, 0x0002)))
2990 return -EINVAL;
2991
2992 if (!sn)
2993 return -EINVAL;
2994
2995 account = purple_connection_get_account(od->gc);
2996 if(!account) return -EINVAL;
2997
2998 /* if (!strcmp(account->username, sn))
2999 icq_im_xstatus_request(od, sn); */
3000
3001 status = purple_presence_get_active_status(account->presence);
3002 if (!status) return -EINVAL;
3003 title = purple_status_get_name(status);
3004 if (!title) return -EINVAL;
3005 formatted_msg = purple_status_get_attr_string(status, "message");
3006 if (!formatted_msg) return -EINVAL;
3007 msg = purple_markup_strip_html(formatted_msg);
3008 if (!msg) return -EINVAL;
3009 len = strlen(fmt)-6+strlen(account->username)+strlen(title)+strlen(msg);
3010 statxml = (char*) g_malloc(len);
3011
3012 snprintf(statxml, len, fmt,
3013 account->username, title, msg);
3014
3015 purple_debug_misc("oscar", "X-Status AutoReply: %s, %s\n", formatted_msg, msg);
3016
3017 byte_stream_new(&bs, 10 + 8 + 2 + 1 + strlen(sn) + 2 + sizeof(plugindata) + strlen(statxml)); /* 16 extra */
3018
3019 snacid = aim_cachesnac(od, 0x0004, 0x000b, 0x0000, NULL, 0);
3020 aim_im_puticbm(&bs, cookie, 0x0002, sn);
3021 byte_stream_put16(&bs, 0x0003);
3022 byte_stream_putraw(&bs, plugindata, sizeof(plugindata));
3023 byte_stream_putraw(&bs, (const guint8*)statxml, strlen(statxml));
3024
3025 flap_connection_send_snac_with_priority(od, conn, 0x0004, 0x000b, 0x0000, snacid, &bs, TRUE);
3026
3027 g_free(statxml);
3028 g_free(msg);
2804 byte_stream_destroy(&bs); 3029 byte_stream_destroy(&bs);
2805 3030
2806 return 0; 3031 return 0;
2807 } 3032 }
2808 3033