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); }
void split_timestamp(ULL timestamp, int& out_year, int& out_month, int& out_day, int& out_hour, int& out_minute, int& out_second) { date_to_ymd(timestamp_date(timestamp), out_year, out_month, out_day); time_to_hms(timestamp_time(timestamp), out_hour, out_minute, out_second); }
/* * backlog_split() * * dzieli linie tekstu w buforze na linie ekranowe. * * - w - okno do podzielenia * * XXX function uses n->x0, y0, width, height !!! call calc_window_dimension(). !!! */ static int backlog_split(window_t *w, backlog_line_t *b, gboolean show, int y) { ncurses_window_t *n = w->priv_data; int rows_count = 0; /* timestamp */ int ts_width = 0; gchar *ts_str = NULL; fstr_attr_t *ts_attr = NULL; /* prompt */ int prompt_width = b->line->prompt_empty ? 0 : xmbswidth(b->line->str, b->line->prompt_len); /* text */ char *str = b->line->str + b->line->prompt_len; fstr_attr_t *attr = b->line->attr + b->line->prompt_len; /* set timestamp */ if (b->line->ts && formated_config_timestamp && config_timestamp_show && (!w->floating || w->id == WINDOW_LASTLOG_ID)) { fstring_t *s = fstring_new(timestamp_time(formated_config_timestamp, b->line->ts)); ts_str = s->str; ts_attr = s->attr; xfree(s); ts_width = xmbswidth(ts_str, xstrlen(ts_str)); } while (*str || rows_count==0) { int len, last_space = 0; int width = n->width - prompt_width; if ((rows_count==0) || !(config_display_indent==1 && prompt_width==0)) width -= ts_width; len = wrap_line(w, width, str, attr, &last_space); if (show && (0 <= y && y < n->height)) { wmove(n->window, n->y0 + y, n->x0); if (ts_width && ((config_display_indent==0) || (rows_count==0))) { ncurses_fstring_print_fast(n->window, ts_str, ts_attr, -1); } else if (config_display_indent==2 || prompt_width) wmove(n->window, n->y0 + y, n->x0 + ts_width); if (prompt_width) /* print prompt */ ncurses_fstring_print_fast(n->window, b->line->str, b->line->attr, b->line->prompt_len); if (width > 0) /* print text */ ncurses_fstring_print_fast(n->window, str, attr, len); } rows_count++; if (w->nowrap) break; str += len + last_space; attr += len + last_space; y++; } if (show && (n->marker == b) && (0 <= y && y < n->height)) draw_thin_red_line(w, n->y0 + y); xfree(ts_str); xfree(ts_attr); return rows_count; }
/* * Normalization of hours, minutes, and seconds is different than normalization of years, months, and day. * A specific time is a number of hours, minutes, and seconds that has already elapsed (e.g. 3:00 PM means * that 15 hours of the day have elapsed). A specific date is not a number of years, months, and days that * have elapsed, they indicate the current year, month, and day -- they indicate which year, month, and day * that we are in (e.g. 12/3/2009 at 8:00 AM means that 2008 years, 11 months, 2 days, 8 hours have elapsed). */ ULL operator+(const ULL& ts, const Interval& i) { // ULL t = 0; // int year,month,day,hours,minutes,seconds; // year = month = day = hours = minutes = seconds = 0; ULL t = 0; int year,month,day,hours,minutes,seconds; long inc = 0; long multiple; year = month = day = hours = minutes = seconds = 0; date_to_ymd(timestamp_date(ts), year, month, day); time_to_hms(timestamp_time(ts), hours, minutes, seconds); // add the interval's seconds, minutes, hours, and years to the values extracted from the timestamp (ts); // we'll add the months and days later seconds += i.seconds; minutes += i.minutes; hours += i.hours; year += i.years; // Since adding a number of months might affect the day, we want to normalize the months before // we go into normalizing the days. // For example: 1/29/2009 + 1 month = 1/28/2009 // but: 1/29/2008 + 1 month = 1/29/2009 // Also: 1/30/2009 + 1 month = 1/28/2009 // and: 1/31/2009 + 2 months = 3/31/2009 // ** I am assuming the the day we fall on depends on how many days the target month has in it -- If ** // ** the target month has fewer days in it than the origin month, and the origin day is a day that ** // ** the target month doesn't have, then the target day will be the last day of the target month. ** // normalize month count //int origin_month_length = days_in_month(year, month); month += i.months; // figure out how many years worth of months we can increment our year count by, // and determine which month we will be in after we remove that number of years worth of months from the month count. /* if(month > 12) { year += (month - 1) / 12; month = ((month - 1) % 12) + 1; } */ // see http://tinyurl.com/nu97yg for a demonstration of why this math works multiple = 12; inc = floor((double)(month - 1) / multiple); year += inc; month = ((month - 1) - multiple*inc) + 1; int target_month_length = days_in_month(year, month); if(/* target_month_length < origin_month_length && */ day > target_month_length) { // adjust the day of the month if we need to day = target_month_length; // set the day to the last day in the (shorter) target month } /* // normalize seconds, minutes, and hours. minutes += seconds / 60; seconds %= 60; hours += minutes / 60; minutes %= 60; // we've already normalized the month count so adding to the day count is ok here (we'll normalize the day count afterward). day += hours / 24; hours %= 24; */ // normalize seconds, minutes, and hours. multiple = 60; inc = floor((double)seconds / multiple); minutes += inc; seconds = seconds - multiple*inc; inc = floor((double)minutes / multiple); hours += inc; minutes = minutes - multiple*inc; // we've already normalized the month count so adding to the day count is ok here (we'll normalize the day count afterward). multiple = 24; inc = floor((double)hours / multiple); day += inc; hours = hours - multiple*inc; // normalize day count multiple = 12; day += i.days; int dpm = days_in_month(year, month); //cout << day << " " << dpm << endl; while(day > dpm) { day -= dpm; month++; // re-normalize month if needed inc = floor((double)(month - 1) / multiple); year += inc; month = ((month - 1) - multiple*inc) + 1; dpm = days_in_month(year, month); } while(day < 1) { month--; dpm = days_in_month(year, month); day += dpm; // re-normalize month if needed inc = floor((double)(month - 1) / multiple); year += inc; month = ((month - 1) - multiple*inc) + 1; //dpm = days_in_month(year, month); } t = join_timestamp(year, month, day, hours, minutes, seconds); return t; }