#include "protocol.h" #include "donkey.h" #include "sPacket.h" #include "misc.h" #include "cygwin.h" #include "sTag.h" #include "opcodes.h" // Tag handling unsigned sTag::count = 0; sTag::sTag () {{{ count++; loc = NULL; name = NULL; type = NULL; codec = NULL; desc = NULL; artist = NULL; title = NULL; album = NULL; length = NULL; bitrate = NULL; temp = NULL; corrupt_dat = NULL; corrupt_len = 0; transfered = 0; size = 0; client_udp= 4672; version = 0; users = 0; files = 0; port = 0; gap_start = 0; gap_end = 0; pref = 0; prio = 0; compress = 0; ip.s_addr = 0; ul_prio = 0; dl_prio = 0; status = 0; users_max = 0; fail = 0; last_ping = 0; }}} sTag::~sTag() {{{ count--; if (loc != NULL) Free2 (loc ); if (name != NULL) Free2 (name ); if (type != NULL) Free2 (type ); if (codec != NULL) Free2 (codec ); if (desc != NULL) Free2 (desc ); if (artist != NULL) Free2 (artist ); if (title != NULL) Free2 (title ); if (album != NULL) Free2 (album ); if (length != NULL) Free2 (length ); if (bitrate != NULL) Free2 (bitrate ); if (temp != NULL) Free2 (temp ); if (corrupt_dat != NULL) free (corrupt_dat); gap_map.clear(); }}} static void replace_str (char **dst, char **src) {{{ if ((*dst) != NULL) free (*dst); *dst = *src; *src = NULL; }}} sTag *parse_tag (unsigned char *data, size_t *len) {{{ ASSERT (NULL != data); ASSERT (NULL != len ); if (data == NULL) {{{ *len = 0; return NULL; }}} if (*len == 0) return NULL; unsigned char *DATA = data; size_t LEN = *len; unsigned char *start = data; unsigned count = GET_U4(&data, len); if (count == 0) return NULL; class sTag *tag = new sTag(); char *key = NULL; char *val_str = NULL; do { unsigned type = GET_U1 (&data, len); key = GET_S2_ (&data, len); uint32_t val_int = 0; tHash hash2; if (*len == 0) break; switch (type) { case STRING : val_str = GET_S2_ (&data, len); break; case INTEGER : val_int = GET_U4 (&data, len); break; case HASH : GET_HASH (&data, len, hash2); break; case tagFLOAT: GET_U4 (&data, len); break; case tagBLOB : val_int = GET_U4 (&data, len); val_str = reinterpret_cast(MALLOC (val_int)); memcpy(val_str, data, val_int); data += val_int; *len -= val_int; break; default : printf("Tag Type ? 0x%02x\n", type); dump (DATA, LEN); delete tag; unsigned char *ende = data; *len = (ende - start); if (key != NULL) Free2 (key); key = NULL; if (val_str != NULL) Free2 (val_str); val_str = NULL; return NULL; } if (strlen(key) == 1) {{{ unsigned char short_tag = key[0]; switch(short_tag) { case 0x01: replace_str (&tag->name , &val_str); break; // tName case 0x03: replace_str (&tag->type , &val_str); break; // tType case 0x04: replace_str (&tag->codec, &val_str); break; // tCodec case 0x0B: replace_str (&tag->desc , &val_str); break; // tDescription case 0x12: replace_str (&tag->temp , &val_str); break; // tTempfile case 0x02: tag->size = val_int; break; // tSize case 0x08: tag->transfered = val_int; break; // tTransfered case 0x09: tag->gap_start = val_int; break; // tGap_start case 0x0A: tag->gap_end = val_int; break; // tGap_end case 0x0D: tag->fail = val_int; break; // tFail case 0x0E: tag->pref = val_int; break; // tPref case 0x0F: tag->port = (val_int); break; // tPort case 0x11: tag->version = val_int; break; // tVersion case 0x13: tag->prio = val_int; break; // tPrio case 0x14: tag->status = val_int; break; // tStatus case 0x17: tag->ul_prio = val_int; break; case 0x18: tag->dl_prio = val_int; break; // tPrio_dl case 0x20: tag->compress = val_int; break; // tCompress case 0x21: tag->client_udp =(val_int); break; // tUDP_client_port case 0x05: break; // tCollection (deprecated) case 0x06: break; // tPart_path case 0x07: break; // tPart_hash case 0x0C: break; // tPing case 0x10: break; // tIP case 0x15: break; // tSources case 0x16: break; // tQTime case 0x22: break; // UDP Version case 0x23: break; // source exchange case 0x24: break; // comment file case 0x25: break; // extended request case 0x26: break; // cDonkey signature case 0x50: break; case 0x51: break; case 0x52: break; case 0x53: break; // only 0 ? case 0x55: break; // eMule mod info ? case 0x83: break; // eMule mod info case 0x82: break; // eMule mod info case 0x94: break; // eMule mod info case 0x66: break; // eMule ?? case 0x67: /* FluX (R6) */ break; case 0x99: break; // eMule ?? case 'v' : break; // eMule ? case 'w' : break; // eMule ? case 'x' : break; // eMule ? case 'y' : break; // eMule ? case 0x80: break; // ?? case 0x86: tag->last_ping = val_int; break; // server.met case 0x87: tag->users_max = val_int; break; // Server.met case 0x88: /* 78 */ break; default : printf("KEY 0x%02X (%u) ", short_tag, type); if (type == 2) printf ("Val %s\n", val_str); if (type == 3) printf ("Val %i\n", val_int); break; } }}} else {{{ if (0 == strcmp (key, FT_LONG_ARTIST )) { replace_str (&tag->artist , &val_str); } else if (0 == strcmp (key, FT_LONG_TITLE )) { replace_str (&tag->title , &val_str); } else if (0 == strcmp (key, FT_LONG_ALBUM )) { replace_str (&tag->album , &val_str); } else if (0 == strcmp (key, FT_LONG_LENGTH )) { replace_str (&tag->length , &val_str); } else if (0 == strcmp (key, FT_LONG_BITRATE )) { replace_str (&tag->bitrate, &val_str); } else if (0 == strcmp (key, FT_LONG_CODEC )) { replace_str (&tag->codec , &val_str); } else if (0 == strcmp (key, CT_LONG_LOC )) { replace_str (&tag->loc , &val_str); } else if (0 == strcmp (key, CT_LONG_IP )) { tag->ip.s_addr = val_int; } else if (0 == strcmp (key, CT_LONG_PORT )) { tag->port = (val_int); } else if (0 == strcmp (key, ST_LONG_USERS )) { tag->users = val_int; } else if (0 == strcmp (key, ST_LONG_FILES )) { tag->files = val_int; } else if (0 == strcmp (key, "corrupt" )) { tag->corrupt_dat = reinterpret_cast(val_str); tag->corrupt_len = val_int; val_str = NULL; } else if (key[0] == FT_GAPSTART) {{{ unsigned idx = atoi (key + 1); tGap_map::iterator i = tag->gap_map.find(idx); if (i == tag->gap_map.end()) { struct sGap gap; gap.von = val_int; gap.bis = 0; gap.val = 0; tag->gap_map[idx] = gap; } else i->second.von = val_int; }}} else if (key[0] == FT_GAPEND ) {{{ unsigned idx = atoi (key + 1); tGap_map::iterator i = tag->gap_map.find(idx); if (i == tag->gap_map.end()) { struct sGap gap; gap.von = 0; gap.bis = val_int; gap.val = 0; tag->gap_map[idx] = gap; } else i->second.bis = val_int; }}} else { printf("KEY %s (%u) ", key, type); if (type == 2) printf ("Val %s\n", val_str); if (type == 3) printf ("Val %i\n", val_int); } }}} if (key != NULL) Free2 (key); key = NULL; if (val_str != NULL) Free2 (val_str); val_str = NULL; } while (--count > 0 && *len > 0); if (key != NULL) Free2 (key); key = NULL; if (val_str != NULL) Free2 (val_str); val_str = NULL; unsigned char *ende = data; *len = ende - start; return tag; }}} void dump (unsigned char *data, size_t len) {{{ char digit[17]="0123456789ABCDEF"; char out[80]; memset(out,' ',80); out[48]=' '; out[65]='\n'; out[66]=0; for (int i = 0; len-->0; i++) { unsigned ii = i & 15; unsigned char tmp = *(data++); out[3*ii+0] = digit[15 & (tmp>>4)]; out[3*ii+1] = digit[15 & (tmp )]; if (tmp>='A' && tmp<='Z') out[49+ii]=tmp; else if (tmp>='a' && tmp<='z') out[49+ii]=tmp; else if (tmp>='0' && tmp<='9') out[49+ii]=tmp; else out[49+ii]=' '; if (15 == (i % 16)) { printf("%s",out); memset(out,' ',80); out[48]=' '; out[65]='\n'; out[66]=0; } } printf("%s",out); }}} bool add_intTag (unsigned char **buf, size_t *len, const char *key, size_t val) {{{ ASSERT(buf != NULL); ASSERT(*buf != NULL); ASSERT(key != NULL); ASSERT(key[0] != 0); ASSERT(1 + 2 + strlen(key) + 4 <= *len); ADD_U1 (buf, len, 3); ADD_S2 (buf, len, key); ADD_U4 (buf, len, val); return true; }}} bool add_strTag (unsigned char **buf, size_t *len, const char *key, const char* val) {{{ ASSERT(1 + 2 + strlen(key) + 2 + strlen(val) <= *len); ADD_U1 (buf, len, 2); ADD_S2 (buf, len, key); ADD_S2 (buf, len, val); return true; }}} bool add_intTag (unsigned char **buf, size_t *len, uint8_t key, size_t val) {{{ ASSERT(8 <= *len); ADD_U1 (buf, len, 3); ADD_U2 (buf, len, 1); ADD_U1 (buf, len, key); ADD_U4 (buf, len, val); return true; }}} bool add_strTag (unsigned char **buf, size_t *len, uint8_t key, const char* val) {{{ assert(val != NULL); ASSERT(4 + 2 + strlen(val) <= *len); ADD_U1 (buf, len, 2); ADD_U2 (buf, len, 1); ADD_U1 (buf, len, key); ADD_S2 (buf, len, val); return true; }}} bool add_bobTag (unsigned char **buf, size_t *len, const char *key, const char* val, size_t count) {{{ assert(val != NULL); ASSERT(1+2+strlen(key)+4+count <= *len); ADD_U1 (buf, len, tagBLOB); ADD_S2 (buf, len, key); ADD_U4 (buf, len, count); memcpy(*buf, val, count); *buf += count; *len -= count; return true; }}} bool add_strCmp (unsigned char **buf, size_t *len, const char *key) {{{ ASSERT(1 + 2 + strlen(key) <= *len); ADD_U1 (buf, len, 1); ADD_S2 (buf, len, key); return true; }}} // {{ Raw Packet Handling uint32_t GET_U4 (unsigned char **buf, size_t *len) {{{ if (*len < 4) { *len = 0; return 0; } uint32_t ret = ctol32(*(reinterpret_cast(*buf))); (*len) -= 4; (*buf) += 4; return ret; }}} uint16_t GET_U2 (unsigned char **buf, size_t *len) {{{ if (*len < 2) { *len = 0; return 0; } uint16_t ret = ctol16(*(reinterpret_cast(*buf))); (*len) -= 2; (*buf) += 2; return ret; }}} uint8_t GET_U1 (unsigned char **buf, size_t *len) {{{ if (*len < 1) { *len = 0; return 0; } uint8_t ret = (**buf); (*len) -= 1; (*buf) += 1; return ret; }}} char * GET_S2_ (unsigned char **buf, size_t *len) {{{ if (*len < 2 ) { *len = 0; return NULL; } unsigned LEN = GET_U2 (buf, len); if (*len < LEN) { *len = 0; return NULL; } char *ret = reinterpret_cast(MALLOC (LEN+1)); ASSERT(ret != NULL); memcpy(ret, *buf, LEN); ret[LEN] = 0; (*len) -= LEN; (*buf) += LEN; return ret; }}} bool GET_HASH (unsigned char **buf, size_t *len, uint8_t *dst) {{{ if (*len < HASH_LEN) { bzero (dst, HASH_LEN); return false; } memcpy (dst, *buf, HASH_LEN); *len -= HASH_LEN; *buf += HASH_LEN; return true; }}} bool ADD_F4 (unsigned char **buf, size_t *len, double val) {{{ ASSERT(*len >= 4); if (*len < 4) { *len = 0; return false; } *(reinterpret_cast(*buf)) = val; (*len) -= 4; (*buf) += 4; return true; }}} bool ADD_U4 (unsigned char **buf, size_t *len, size_t val) {{{ ASSERT(*len >= 4); if (*len < 4) { *len = 0; return false; } *(reinterpret_cast(*buf)) = ctol32(val); (*len) -= 4; (*buf) += 4; return true; }}} bool ADD_U2 (unsigned char **buf, size_t *len, size_t val) {{{ ASSERT(val < 65536); ASSERT(*len >= 2); if (*len < 2) { *len = 0; return false; } *(reinterpret_cast(*buf)) = ctol16(val); (*len) -= 2; (*buf) += 2; return true; }}} bool ADD_U1 (unsigned char **buf, size_t *len, uint8_t val) {{{ ASSERT(buf != NULL); ASSERT(*buf != NULL); ASSERT(*len >= 1); if (*len < 1) { *len = 0; return false; } *(reinterpret_cast(*buf)) = val; (*len) -= 1; (*buf) += 1; return true; }}} bool ADD_S2 (unsigned char **buf, size_t *len, const char *val) {{{ size_t cnt = strlen(val); ASSERT (*len >= 2 + cnt); ASSERT (cnt < 0x10000); ADD_U2 (buf, len, cnt); memcpy (*buf, val , cnt); (*buf) += cnt; (*len) -= cnt; return true; }}} bool ADD_HASH (unsigned char **buf, size_t *len, const uint8_t *hash ) {{{ ASSERT(*len >= HASH_LEN); if (*len < HASH_LEN) { *len = 0; return false; } memcpy(*buf, hash, HASH_LEN); (*len) -= HASH_LEN; (*buf) += HASH_LEN; return true; }}} // }}}