Esempio n. 1
0
static TIMER(irc_autorejoin_timer) {
	irc_onkick_handler_t *d = data;
	if (type == 1) {
		xfree(d->nick);
		xfree(d->kickedby);
		xfree(d->chan);
		xfree(d);
		return 0;
	}

	debug_white("irc_autorejoin_timer() rejoining to: %s\n", d->chan);
	irc_autorejoin(d->s, IRC_REJOIN_KICK, (d->chan)+4);
	return -1;
}
void debug_function(struct board *board)
	{
    clrscr();
    switch(board->turn)
		{
		case WHITE:
			debug_black(board);
			break;

		case BLACK:
			debug_white(board);
			break;

		}
	}
static int check_replyreq(session_t *s, unsigned char **buf, int *len, int *type) {
	struct {
		uint16_t type;
		uint16_t len;
	} tlv;
	struct {
		uint16_t len;
		uint32_t uid;
		uint16_t type;
		uint16_t id;
	} pkt;

	if (!icq_unpack(*buf, buf, len, "WW", &tlv.type, &tlv.len) || (tlv.type != 0x0001) || (tlv.len < 10)) {
		debug_error("check_replyreq() broken(1)\n");
		return 0;
	}

	if (*len!=tlv.len) {
		debug_error("icq_snac_extension_replyreq() broken(1,5)\n");
		return 0;
	}

	if (!icq_unpack(*buf, buf, len, "wiwW", &pkt.len, &pkt.uid, &pkt.type, &pkt.id)) {
		debug_error("icq_snac_extension_replyreq() broken(2)\n");
		return 0;
	}

	debug_white("icq_snac_extension_replyreq() uid=%d type=%.4x (len=%d, len2=%d)\n", pkt.uid, pkt.type, *len, pkt.len);

	if (xstrcmp(s->uid+4, itoa(pkt.uid))) {
		debug_error("icq_snac_extension_replyreq() 1919 UIN mismatch: %s vs %ld.\n", s->uid+4, pkt.uid);
		return 0;
	}

	if (tlv.len - 2 != pkt.len) {
		debug("icq_snac_extension_replyreq() 1743 Size mismatch in packet lengths.\n");
		return 0;
	}

	*type = pkt.type;

	return 1;
}
static int icq_meta_info_reply(session_t *s, unsigned char *buf, int len, private_data_t **info, int show) {
	/* SNAC(15,03)/07DA SRV_META_INFO_REPLY	Meta information response
	 *
	 * This is the server response to client meta info request SNAC(15,02)/07D0.
	 */
	struct {
		uint16_t subtype;
		uint8_t result;
		unsigned char *data;
	} pkt;
	int userinfo = 0;

	metasnac_subhandler_t handler;

	if (!ICQ_UNPACK(&pkt.data, "wc", &pkt.subtype, &pkt.result)) {
		debug_error("icq_meta_info_reply() broken\n");
		return -1;
	}

	debug_white("icq_meta_info_reply() subtype=%.4x result=%.2x (len=%d)\n", pkt.subtype, pkt.result, len);

	if ( (handler = get_userinfo_extension_handler(pkt.subtype)) ) {
		userinfo = 1;
	} else {
		switch (pkt.subtype) {
			/* search */
			case SRV_LAST_USER_FOUND:	handler = icq_snac_extension_userfound_last; break;
			case SRV_USER_FOUND:		handler = icq_snac_extension_userfound; break;
		
			case META_SET_FULLINFO_ACK:	handler = icq_snac_extension_fullinfo_ack; break;

			case SRV_RANDOM_FOUND:		handler = NULL; break;	/* XXX, SRV_RANDOM_FOUND */
			default:			handler = NULL;
		}
	}

	__displayed = 0;
	if (!handler) {
		debug_error("icq_meta_info_reply() ignored: %.4x\n", pkt.subtype);
		icq_hexdump(DEBUG_ERROR, pkt.data, len);
		return 0;
	} else {
		int uid = info ? private_item_get_int(info, "uid") : -1;
		debug_function("icq_snac_extensions_%s()", icq_lookuptable(meta_name, pkt.subtype));
		if (userinfo)
			debug_function(" uid: %u", uid);
		debug_function("\n");

		if (pkt.result == 0x0A) {
			handler(s, pkt.data, len, info);
		} else if (!userinfo){
			/* Failed search */
			debug_error("icq_snac_extension_userfound() search error: %u\n", pkt.result);
		}

		if (show) {
			__display_info(s, pkt.subtype, *info);
			if (__displayed)
				print("icq_userinfo_end", session_name(s), itoa(uid));
		}
	}

	return 0;
}
static int icq_snac_extension_userfound_common(session_t *s, unsigned char *buf, int len, int islast) {
	char *nickname = NULL;
	char *first_name = NULL;
	char *last_name = NULL;
	char *email = NULL;
	char *full_name;
	char *temp;
	const char *__age = NULL;
	const char *__gender = "";
	char *__active;

	uint32_t uin;
	uint16_t len2;
	uint16_t status, age;
	uint8_t auth, gender;

	/* XXX, sprawdzic czy mamy cookie. */

	if (!ICQ_UNPACK(&buf, "w", &len2))
		return -1;

	if (len < len2)
		return -1;

	if (!ICQ_UNPACK(&buf, "i", &uin))
		return -1;

	if (!ICQ_UNPACK(&buf, "S", &temp)) goto cleanup;
	nickname = xstrdup(temp);

	if (!ICQ_UNPACK(&buf, "S", &temp)) goto cleanup;
	first_name = xstrdup(temp);

	if (!ICQ_UNPACK(&buf, "S", &temp)) goto cleanup;
	last_name = xstrdup(temp);

	if (!ICQ_UNPACK(&buf, "S", &temp)) goto cleanup;
	email = xstrdup(temp);

	if (first_name[0] && last_name[0])
		full_name = saprintf("%s %s", first_name, last_name);
	else
		full_name = xstrdup(first_name[0] ? first_name : last_name);

	if (ICQ_UNPACK(&buf, "cwcw", &auth, &status, &gender, &age)) {
		if (age)
			__age = itoa(age);		// XXX calculate birthyear?
		if (gender)
			__gender = (gender==2) ? "m" : "f";
	} else {
		debug_error("icq_snac_extension_userfound_common() broken\n");
		auth = status = gender = age = 0;
	}

	/* XXX, "search_results_multi", "search_results_single" */
	/* XXX, instead of email we had city */
	/* XXX, some time ago i was thinking to of function which
	 * 	if data was truncated [because of width in format]
	 * 	it'd take another line to complete..
	 *
	 * 	i don't like truncation of data for instance:
	 * 	 08:17:12  97320776 | darkjames    | Jakub Zawadz | -    | darkjames@po
	 *
	 * 	i was thinking about:
	 * 	           97320776 | darkjames    | Jakub Zawwdz | -    | darkjames@po
	 * 	                                     ki                    czta.onet.pl
	 *
	 * 	of course we can do more magic, and wrap...
	 * 					     Jakub
	 * 					     Zawadzki
	 *
	 * 	or maybe let's  align to center? :)
	 * 						 Jakub
	 * 					       Zawadzki
	 */

	{
		const char *fvalue;
		/* XXX ?wo? new formats for icq status
		 * status (0 - offline, 1 - online, 2 - non_webaware)
		 */
		switch (status) {
			case 0:
				fvalue = format_find("search_results_multi_notavail");
				break;
			case 1:
				fvalue = format_find("search_results_multi_avail");
				break;
			default:
				fvalue = format_find("search_results_multi_unknown");
				break;
		}
		temp = format_string(fvalue);
		/* XXX ?wo? add format for "auth" */
		__active = saprintf("%s %s", temp, auth ? " " : "A");
		xfree(temp);
	}
	print_info(NULL, s, "search_results_multi", itoa(uin), full_name, nickname, email,
			__age ? __age : ("-"), __gender, __active);

	xfree(__active);
	xfree(full_name);

	if (islast && len>=4) {
		uint32_t omit;
		ICQ_UNPACK(&buf, "I", &omit);
		debug_warn("icq_snac_extension_userfound_last() Bulshit warning!\n");
		debug_white("icq_snac_extension_userfound_last() %d search results omitted\n", omit);
	}

	icq_hexdump(DEBUG_WHITE, buf, len);

	xfree(nickname); xfree(first_name); xfree(last_name); xfree(email);
	return 0;

cleanup:
	xfree(nickname); xfree(first_name); xfree(last_name); xfree(email);
	return -1;
}
static void icq_get_user_info(session_t *s, userlist_t *u, struct icq_tlv_list *tlvs, int newstatus) {
    int caps = 0, desc_chg = 0;
    char *descr = NULL;
    icq_tlv_t *t;

    if (!u)
        return;

    debug_function("icq_get_user_info() %s\n", u->uid);

    descr = u->descr ? xstrdup(u->descr) : NULL;

    user_private_item_set_int(u, "idle", 0);
    user_private_item_set_int(u, "status_f", 0);
    user_private_item_set_int(u, "xstatus", 0);

    for (t = tlvs; t; t = t->next) {

        /* Check t->len */
        switch (t->type) {
        case 0x01:
            if (tlv_length_check("icq_get_user_info()", t, 2))
                continue;
            break;
        case 0x03:
        case 0x04:
        case 0x05:
        case 0x06:
        case 0x0a:
        case 0x0f:
            if (tlv_length_check("icq_get_user_info()", t, 4))
                continue;
            break;
        }
        /* now we've got trusted length */
        switch (t->type) {
        case 0x01: /* User class */
            user_private_item_set_int(u, "class", t->nr);
            break;

        case 0x03: /* Time when client gone online (unix time_t) */
            user_private_item_set_int(u, "online", t->nr);
            break;

        case 0x04: /* idle timer */
        {
            uint16_t idle;
            if ( (idle = t->nr) )
                user_private_item_set_int(u, "idle", time(NULL) - 60*idle);
            break;
        }

        case 0x05: /* Time when this account was registered (unix time_t) */
            user_private_item_set_int(u, "member", t->nr);
            break;

        case 0x06:
        {
            /* User status
             *
             * ICQ service presence notifications use user status field which consist
             * of two parts. First is a various flags (birthday flag, webaware flag,
             * etc). Second is a user status (online, away, busy, etc) flags.
             */
            uint16_t status	= t->nr & 0xffff;
            uint16_t flags	= t->nr >> 16;

            user_private_item_set_int(u, "status_f", flags);
            debug_white(" %s status flags=0x%04x status=0x%04x\n", u->uid, flags, status);
            newstatus = icq2ekg_status(status);
            break;
        }

        case 0x0a: /* IP address */
        {
            uint32_t ip;
            if (icq_unpack_nc(t->buf, t->len, "i", &ip)) {
                if (ip)
                    user_private_item_set_int(u, "ip", ip);
            }
            break;
        }

        case 0x0c: /* DC info */
        {
            struct {
                uint32_t ip;
                uint32_t port;
                uint8_t tcp_flag;
                uint16_t version;
                uint32_t conn_cookie;
                uint32_t web_port;
                uint32_t client_features;
                /* faked time signatures, used to identify clients */
                uint32_t ts1;
                uint32_t ts2;
                uint32_t ts3;
                uint16_t junk;
            } tlv_c;

            if (!icq_unpack_nc(t->buf, t->len, "IICWIII",
                               &tlv_c.ip, &tlv_c.port,
                               &tlv_c.tcp_flag, &tlv_c.version,
                               &tlv_c.conn_cookie, &tlv_c.web_port,
                               &tlv_c.client_features))
            {
                debug_error(" %s TLV(C) corrupted?\n", u->uid);
                continue;
            } else {
                user_private_item_set_int(u, "dcc.ip", tlv_c.ip);
                user_private_item_set_int(u, "dcc.port", tlv_c.port);
                user_private_item_set_int(u, "dcc.flag", tlv_c.tcp_flag);
                user_private_item_set_int(u, "version", tlv_c.version);
                user_private_item_set_int(u, "dcc.cookie", tlv_c.conn_cookie);
                user_private_item_set_int(u, "dcc.web_port", tlv_c.web_port);	// ?wo? do we need it?
                if (t->len >= 12 && icq_unpack_nc(t->buf, t->len, "23 III", &tlv_c.ts1, &tlv_c.ts3, &tlv_c.ts3))
                    ;
            }
            break;
        }

        case 0x0d: /* Client capabilities list */
        {
            unsigned char *data = t->buf;
            int d_len = t->len;

            if (tlv_length_check("icq_get_user_info()", t, t->len & ~0xF))
                break;
            while (d_len > 0) {
                int cid = icq_cap_id(data);
                if (cid != CAP_UNKNOWN) {
                    caps |= 1 << cid;
                } else if ((cid = icq_xstatus_id(data))) {
                    user_private_item_set_int(u, "xstatus", cid);
                } else {
                    /* ?wo? client id???*/
                    debug_error("Unknown cap\n");
                    icq_hexdump(DEBUG_ERROR, data, 0x10);
                }
                data  += 0x10;		// capability length
                d_len -= 0x10;
            }
            break;
        }

        case 0x0e: /* AOL users. No values */
            break;

        case 0x0f:
        case 0x10: /* Online time in seconds */
            break;

        case 0x19: /* short caps */
        {
            unsigned char *data = t->buf;
            int d_len = t->len;

            while (d_len > 0) {
                int cid = icq_short_cap_id(data);
                if (cid != CAP_UNKNOWN) {
                    caps |= 1 << cid;
                } else {
                    /* WTF? */
                }
                data  += 2;		// short capability length
                d_len -= 2;
            }
            break;
        }

        case 0x1d: /* user icon id & hash */
        {
            static char empty_item[0x10] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
            unsigned char *t_data = t->buf;
            int t_len = t->len;

            while (t_len > 0) {

                uint16_t item_type;
                uint8_t item_flags;
                uint8_t item_len;

                if (!icq_unpack(t_data, &t_data, &t_len, "WCC", &item_type, &item_flags, &item_len)) {
                    debug_error(" %s TLV(1D) corrupted?\n", u->uid);
                    break;
                }

                /* just some validity check */
                if (item_len > t_len)
                    item_len = t_len;

                if ((item_type == 0x02) && (item_flags == 4)) {
                    /* iChat online message */
                    if (item_len>4) {
                        char *tmp;
                        uint16_t enc;
                        icq_unpack_nc(t_data, item_len, "Uw", &tmp, &enc);
                        descr = !enc ? ekg_utf8_to_locale_dup(tmp) : xstrdup(tmp);
                    }
                    desc_chg = 1;
                } else if ((item_type == 0x0e) && (item_len>7)) {
                    /* 000E: Custom Status (ICQ6) */
                    char *tmp = xstrndup((char *)t_data, item_len);
                    if ( !xstrncmp(tmp, "icqmood", 7) && xisdigit(*(tmp+7)) ) {
                        int xstatus = atoi(tmp+7) + 1;
                        if (xstatus<=XSTATUS_COUNT)
                            user_private_item_set_int(u, "xstatus", xstatus);
                    }
                    xfree(tmp);
                } else if (memcmp(t_data, empty_item, (item_len < 0x10) ? item_len : 0x10)) {
                    /* Item types
                     * 	0000: AIM mini avatar
                     * 	0001: AIM/ICQ avatar ID/hash (len 5 or 16 bytes)
                     * 	0002: iChat online message
                     *	0008: ICQ Flash avatar hash (16 bytes)
                     * 	0009: iTunes music store link
                     *	000C: ICQ contact photo (16 bytes)
                     *	000D: ?
                     */

                    debug_white(" %s has got avatar: type: %d flags: %d\n", u->uid, item_type, item_flags);
                    icq_hexdump(DEBUG_WHITE, t_data, item_len);
                    /* XXX, display message, get? do something? */
                }

                t_data += item_len;
                t_len -= item_len;
            }
            break;
        }
        default:
            if (t->len==4)
                debug_warn(" %s Unknown TLV(0x%x) len=4 v=%d (0x%x) (%s)\n", u->uid, t->type, t->nr, t->nr, t->nr?timestamp_time("%Y-%m-%d %H:%M:%S", t->nr):"");
            else
                debug_error(" %s Unknown TLV(0x%x) len=%d\n", u->uid, t->type, t->len);
        }
    }

    if (desc_chg || (newstatus != u->status)) {
        if (!descr && !desc_chg && u->descr)
            descr = xstrdup(u->descr);

        protocol_status_emit(s, u->uid, newstatus, descr, time(NULL));
    }

    if (!desc_chg) {
        if (u->status == EKG_STATUS_NA) {
            icq_send_snac(s, 0x02, 0x05, NULL, NULL,	/* Request user info */
                          "Ws",
                          (uint32_t) 1,			/* request type (1 - general info, 2 - short user info, 3 - away message, 4 - client capabilities) */
                          u->uid+4);
        } else {
            icq_get_description(s, u->uid+4, u->status);
        }
    }

    if (u->status == EKG_STATUS_NA) {
        user_private_item_set_int(u, "online", 0);
        user_private_item_set_int(u, "last_ip", user_private_item_get_int(u, "ip"));
        user_private_item_set_int(u, "ip", 0);
        if (user_private_item_get_int(u, "version") < 8) {
            caps &= ~(1<<CAP_SRV_RELAY);
            debug_warn("icq_snac_buddy_online() Forcing simple messages due to compatibility issues (%s).\n", u->uid);
        }
    }

    user_private_item_set_int(u, "caps", caps);
    user_private_item_set_int(u, "utf", (caps && (1<<CAP_UTF)) ? 1:0);

    xfree(descr);
}