1// 2// This file is part of the aMule Project. 3// 4// Copyright (c) 2008-2011 D��vai Tam��s ( gonosztopi@amule.org ) 5// Copyright (c) 2008-2011 aMule Team ( admin@amule.org / http://www.amule.org ) 6// 7// Any parts of this program derived from the xMule, lMule or eMule project, 8// or contributed by third-party developers are copyrighted by their 9// respective authors. 10// 11// This program is free software; you can redistribute it and/or modify 12// it under the terms of the GNU General Public License as published by 13// the Free Software Foundation; either version 2 of the License, or 14// (at your option) any later version. 15// 16// This program is distributed in the hope that it will be useful, 17// but WITHOUT ANY WARRANTY; without even the implied warranty of 18// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19// GNU General Public License for more details. 20// 21// You should have received a copy of the GNU General Public License 22// along with this program; if not, write to the Free Software 23// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 24// 25 26#include "Print.h" 27#include <wx/datetime.h> 28#include <tags/FileTags.h> 29#include <tags/ServerTags.h> 30#include <tags/TagTypes.h> 31#include <protocol/ed2k/Client2Server/UDP.h> 32#include "../../OtherFunctions.h" 33#include "../../Friend.h" // Needed for FF_NAME 34#include "../../KnownFile.h" // Needed for PR_* 35#include "../../NetworkFunctions.h" // Needed for Uint32toStringIP 36 37#include <cctype> 38#include <map> 39#include <iostream> 40 41SDMODE g_stringDecodeMode; 42 43wxString MakePrintableString(const wxString& s) 44{ 45 wxString str = s; 46 unsigned c = 0; 47 for (unsigned i = 0; i < str.length(); i++) { 48 c |= (wxChar) str[i]; 49 } 50 51 if (c <= 0xff && GetStringsMode() != SD_NONE) { 52 wxCharBuffer buf = str.To8BitData(); 53 wxString test = UTF82unicode(buf.data()); 54 if (!test.empty()) { 55 str = test; 56 c = 0; 57 for (unsigned i = 0; i < str.length(); i++) { 58 c |= (wxChar) str[i]; 59 } 60 } 61 } 62 63 wxString retval = wxT("\""); 64 65 if (GetStringsMode() == SD_DISPLAY) { 66 retval += str; 67 } else if (GetStringsMode() == SD_UTF8) { 68 str = wxString::From8BitData((const char *)str.utf8_str()); 69 c = 0xff; 70 } 71 72 if (GetStringsMode() != SD_DISPLAY) { 73 for (unsigned i = 0; i < str.length(); i++) { 74 if (GetStringsMode() == SD_NONE ? ((unsigned)str[i] >= ' ' && (unsigned)str[i] <= 0x7f) : std::isprint(str[i])) { 75 retval += str[i]; 76 } else if (c <= 0xff) { 77 retval += wxString::Format(wxT("\\x%02x"), str[i]); 78 } else { 79 retval += wxString::Format(wxT("\\u%04x"), str[i]); 80 } 81 } 82 } 83 84 retval += wxT("\""); 85 return retval; 86} 87 88std::ostream& operator<<(std::ostream& x, const CTimeT& y) 89{ 90 if ((time_t)y != 0) { 91 wxDateTime dt((time_t)y); 92 return x << (time_t)y << " (" << dt.Format(wxDefaultDateTimeFormat, wxDateTime::UTC) << " UTC)"; 93 } else { 94 return x << "0 (Never)"; 95 } 96} 97 98std::ostream& operator<<(std::ostream& x, const CKadIP& ip) 99{ 100 return x << hex(ip) << " (" << Uint32toStringIP(wxUINT32_SWAP_ALWAYS(ip)) << ')'; 101} 102 103std::ostream& operator<<(std::ostream& x, const CeD2kIP& ip) 104{ 105 return x << hex(ip) << " (" << Uint32toStringIP(ip) << ')'; 106} 107 108static inline wxString TagNameString(const wxString& name) 109{ 110 if (name.length() == 1) { 111 return wxString::Format(wxT("\"\\x%02x\""), name[0]); 112 } else if (name.length() > 1) { 113 if (name[0] == FT_GAPSTART || name[0] == FT_GAPEND) { 114 return wxString::Format(wxT("\"\\x%02x"), name[0]) + name.substr(1) + wxT("\""); 115 } 116 } 117 return wxT("\"") + name + wxT("\""); 118} 119 120#define TEST_VALUE(VALUE) if (value == VALUE) return #VALUE; else 121 122const char* DecodeTagNameID(uint8_t value) 123{ 124 TEST_VALUE(FT_FILENAME) 125 TEST_VALUE(FT_FILESIZE) 126 TEST_VALUE(FT_FILESIZE_HI) 127 TEST_VALUE(FT_FILETYPE) 128 TEST_VALUE(FT_FILEFORMAT) 129 TEST_VALUE(FT_LASTSEENCOMPLETE) 130 TEST_VALUE(FT_TRANSFERRED) 131 TEST_VALUE(FT_GAPSTART) 132 TEST_VALUE(FT_GAPEND) 133 TEST_VALUE(FT_PARTFILENAME) 134 TEST_VALUE(FT_OLDDLPRIORITY) 135 TEST_VALUE(FT_STATUS) 136 TEST_VALUE(FT_SOURCES) 137 TEST_VALUE(FT_PERMISSIONS) 138 TEST_VALUE(FT_OLDULPRIORITY) 139 TEST_VALUE(FT_DLPRIORITY) 140 TEST_VALUE(FT_ULPRIORITY) 141 TEST_VALUE(FT_KADLASTPUBLISHKEY) 142 TEST_VALUE(FT_KADLASTPUBLISHSRC) 143 TEST_VALUE(FT_FLAGS) 144 TEST_VALUE(FT_DL_ACTIVE_TIME) 145 TEST_VALUE(FT_CORRUPTEDPARTS) 146 TEST_VALUE(FT_DL_PREVIEW) 147 TEST_VALUE(FT_KADLASTPUBLISHNOTES) 148 TEST_VALUE(FT_AICH_HASH) 149 TEST_VALUE(FT_COMPLETE_SOURCES) 150 TEST_VALUE(FT_PUBLISHINFO) 151 TEST_VALUE(FT_ATTRANSFERRED) 152 TEST_VALUE(FT_ATREQUESTED) 153 TEST_VALUE(FT_ATACCEPTED) 154 TEST_VALUE(FT_CATEGORY) 155 TEST_VALUE(FT_ATTRANSFERREDHI) 156 TEST_VALUE(FT_MEDIA_ARTIST) 157 TEST_VALUE(FT_MEDIA_ALBUM) 158 TEST_VALUE(FT_MEDIA_TITLE) 159 TEST_VALUE(FT_MEDIA_LENGTH) 160 TEST_VALUE(FT_MEDIA_BITRATE) 161 TEST_VALUE(FT_MEDIA_CODEC) 162 TEST_VALUE(FT_FILERATING) 163 return "??"; 164} 165 166const char* DecodeTagName(const wxString& value) 167{ 168 TEST_VALUE(TAG_FILENAME) 169 TEST_VALUE(TAG_FILESIZE) 170 TEST_VALUE(TAG_FILESIZE_HI) 171 TEST_VALUE(TAG_FILETYPE) 172 TEST_VALUE(TAG_FILEFORMAT) 173 TEST_VALUE(TAG_COLLECTION) 174 TEST_VALUE(TAG_PART_PATH) 175 TEST_VALUE(TAG_PART_HASH) 176 TEST_VALUE(TAG_COPIED) 177 TEST_VALUE(TAG_GAP_START) 178 TEST_VALUE(TAG_GAP_END) 179 TEST_VALUE(TAG_DESCRIPTION) 180 TEST_VALUE(TAG_PING) 181 TEST_VALUE(TAG_FAIL) 182 TEST_VALUE(TAG_PREFERENCE) 183 TEST_VALUE(TAG_PORT) 184 TEST_VALUE(TAG_IP_ADDRESS) 185 TEST_VALUE(TAG_VERSION) 186 TEST_VALUE(TAG_TEMPFILE) 187 TEST_VALUE(TAG_PRIORITY) 188 TEST_VALUE(TAG_STATUS) 189 TEST_VALUE(TAG_SOURCES) 190 TEST_VALUE(TAG_AVAILABILITY) 191 TEST_VALUE(TAG_PERMISSIONS) 192 TEST_VALUE(TAG_QTIME) 193 TEST_VALUE(TAG_PARTS) 194 TEST_VALUE(TAG_PUBLISHINFO) 195 TEST_VALUE(TAG_MEDIA_ARTIST) 196 TEST_VALUE(TAG_MEDIA_ALBUM) 197 TEST_VALUE(TAG_MEDIA_TITLE) 198 TEST_VALUE(TAG_MEDIA_LENGTH) 199 TEST_VALUE(TAG_MEDIA_BITRATE) 200 TEST_VALUE(TAG_MEDIA_CODEC) 201 TEST_VALUE(TAG_ENCRYPTION) 202 TEST_VALUE(TAG_FILERATING) 203 TEST_VALUE(TAG_BUDDYHASH) 204 TEST_VALUE(TAG_CLIENTLOWID) 205 TEST_VALUE(TAG_SERVERPORT) 206 TEST_VALUE(TAG_SERVERIP) 207 TEST_VALUE(TAG_SOURCEUPORT) 208 TEST_VALUE(TAG_SOURCEPORT) 209 TEST_VALUE(TAG_SOURCEIP) 210 TEST_VALUE(TAG_SOURCETYPE) 211 return "??"; 212} 213 214const char* DecodeTagType(uint8_t value) 215{ 216 TEST_VALUE(TAGTYPE_HASH16) 217 TEST_VALUE(TAGTYPE_STRING) 218 TEST_VALUE(TAGTYPE_UINT32) 219 TEST_VALUE(TAGTYPE_FLOAT32) 220 TEST_VALUE(TAGTYPE_BOOL) 221 TEST_VALUE(TAGTYPE_BOOLARRAY) 222 TEST_VALUE(TAGTYPE_BLOB) 223 TEST_VALUE(TAGTYPE_UINT16) 224 TEST_VALUE(TAGTYPE_UINT8) 225 TEST_VALUE(TAGTYPE_BSOB) 226 TEST_VALUE(TAGTYPE_UINT64) 227 TEST_VALUE(TAGTYPE_STR1) 228 TEST_VALUE(TAGTYPE_STR2) 229 TEST_VALUE(TAGTYPE_STR3) 230 TEST_VALUE(TAGTYPE_STR4) 231 TEST_VALUE(TAGTYPE_STR5) 232 TEST_VALUE(TAGTYPE_STR6) 233 TEST_VALUE(TAGTYPE_STR7) 234 TEST_VALUE(TAGTYPE_STR8) 235 TEST_VALUE(TAGTYPE_STR9) 236 TEST_VALUE(TAGTYPE_STR10) 237 TEST_VALUE(TAGTYPE_STR11) 238 TEST_VALUE(TAGTYPE_STR12) 239 TEST_VALUE(TAGTYPE_STR13) 240 TEST_VALUE(TAGTYPE_STR14) 241 TEST_VALUE(TAGTYPE_STR15) 242 TEST_VALUE(TAGTYPE_STR16) 243 TEST_VALUE(TAGTYPE_STR17) 244 TEST_VALUE(TAGTYPE_STR18) 245 TEST_VALUE(TAGTYPE_STR19) 246 TEST_VALUE(TAGTYPE_STR20) 247 TEST_VALUE(TAGTYPE_STR21) 248 TEST_VALUE(TAGTYPE_STR22) 249 return "??"; 250} 251 252const char* DecodeServerTagNameID(uint8_t value) 253{ 254 TEST_VALUE(ST_SERVERNAME) 255 TEST_VALUE(ST_DESCRIPTION) 256 TEST_VALUE(ST_PING) 257 TEST_VALUE(ST_FAIL) 258 TEST_VALUE(ST_PREFERENCE) 259 TEST_VALUE(ST_DYNIP) 260 TEST_VALUE(ST_LASTPING_DEPRECATED) 261 TEST_VALUE(ST_MAXUSERS) 262 TEST_VALUE(ST_SOFTFILES) 263 TEST_VALUE(ST_HARDFILES) 264 TEST_VALUE(ST_LASTPING) 265 TEST_VALUE(ST_VERSION) 266 TEST_VALUE(ST_UDPFLAGS) 267 TEST_VALUE(ST_AUXPORTSLIST) 268 TEST_VALUE(ST_LOWIDUSERS) 269 TEST_VALUE(ST_UDPKEY) 270 TEST_VALUE(ST_UDPKEYIP) 271 TEST_VALUE(ST_TCPPORTOBFUSCATION) 272 TEST_VALUE(ST_UDPPORTOBFUSCATION) 273 return "??"; 274} 275 276const char* DecodeFriendTagNameID(uint8_t value) 277{ 278 TEST_VALUE(FF_NAME) 279 return "??"; 280} 281 282typedef std::map<uint32_t, const char*> FlagMap; 283 284class CFlagDecoder 285{ 286 public: 287 void AddFlag(uint32_t bit, const char* name) 288 { 289 m_flags[bit] = name; 290 } 291 292 wxString DecodeFlags(uint32_t flags) 293 { 294 uint32_t cur_flag = 1; 295 wxString result; 296 while (flags) { 297 if (flags & 1) { 298 if (!result.empty()) { 299 result += wxT(" | "); 300 } 301 FlagMap::const_iterator it = m_flags.find(cur_flag); 302 if (it != m_flags.end()) { 303 result += wxString::FromAscii(it->second); 304 } else { 305 result += wxString::Format(wxT("%#x"), cur_flag); 306 } 307 } 308 cur_flag <<= 1; 309 flags >>= 1; 310 } 311 return result; 312 } 313 314 private: 315 FlagMap m_flags; 316}; 317 318#define ADD_DECODER_FLAG(decoder, FLAG) decoder.AddFlag(FLAG, #FLAG) 319 320std::ostream& operator<<(std::ostream& out, const CTag& tag) 321{ 322 out << "{ "; 323 if (tag.GetName().empty()) { 324 out << hex(tag.GetNameID()) << ' ' << DecodeTagNameID(tag.GetNameID()); 325 } else { 326 out << TagNameString(tag.GetName()) << ' '; 327 bool name_decoded = false; 328 if (tag.IsInt() && tag.GetName().length() > 1) { 329 wxCharBuffer ascii_name = tag.GetName().ToAscii(); 330 char gap_mark = ascii_name ? ascii_name[(size_t)0] : 0; 331 if (gap_mark == FT_GAPSTART || gap_mark == FT_GAPEND) { 332 unsigned long gapkey; 333 if (tag.GetName().Mid(1).ToULong(&gapkey)) { 334 out << DecodeTagNameID(gap_mark) << wxString::Format(wxT("[%lu]"), gapkey); 335 name_decoded = true; 336 } 337 } 338 } 339 if (!name_decoded) { 340 out << DecodeTagName(tag.GetName()); 341 } 342 } 343 out << ", " << (unsigned)tag.GetType() << ' ' << DecodeTagType(tag.GetType()) << ", "; 344 if (tag.IsInt()) { 345 if (tag.GetName() == TAG_SOURCEIP) { 346 out << CKadIP(tag.GetInt()); 347 } else if (tag.GetName() == TAG_SERVERIP) { 348 out << CeD2kIP(tag.GetInt()); 349 } else if (tag.GetName() == TAG_ENCRYPTION) { 350 uint8_t enc = tag.GetInt(); 351 out << hex(enc); 352 if (enc) { 353 CFlagDecoder decoder; 354 decoder.AddFlag(0x01, "CryptSupported"); 355 decoder.AddFlag(0x02, "CryptRequested"); 356 decoder.AddFlag(0x04, "CryptRequired"); 357 decoder.AddFlag(0x08, "SupportsDirectCallback"); 358 out << " (" << decoder.DecodeFlags(enc) << ')'; 359 } 360 } else if (tag.GetNameID() == FT_LASTSEENCOMPLETE 361 || tag.GetNameID() == FT_KADLASTPUBLISHSRC 362 || tag.GetNameID() == FT_KADLASTPUBLISHNOTES 363 || tag.GetNameID() == FT_KADLASTPUBLISHKEY 364 ) { 365 out << CTimeT(tag.GetInt()); 366 } else if (tag.GetName() == TAG_FILESIZE 367 || tag.GetNameID() == FT_FILESIZE 368 || tag.GetNameID() == FT_TRANSFERRED 369 || tag.GetNameID() == FT_ATTRANSFERRED 370 ) { 371 out << tag.GetInt() << " (" << CastItoXBytes(tag.GetInt()) << ')'; 372 } else if (tag.GetNameID() == FT_ULPRIORITY 373 || tag.GetNameID() == FT_DLPRIORITY 374 || tag.GetNameID() == FT_OLDULPRIORITY 375 || tag.GetNameID() == FT_OLDDLPRIORITY 376 ) { 377 out << tag.GetInt() << ' '; 378 switch (tag.GetInt()) { 379 case PR_VERYLOW: out << "PR_VERYLOW"; break; 380 case PR_LOW: out << "PR_LOW"; break; 381 case PR_NORMAL: out << "PR_NORMAL"; break; 382 case PR_HIGH: out << "PR_HIGH"; break; 383 case PR_VERYHIGH: out << "PR_VERYHIGH"; break; 384 case PR_AUTO: out << "PR_AUTO"; break; 385 case PR_POWERSHARE: out << "PR_POWERSHARE"; break; 386 } 387 } else { 388 out << tag.GetInt(); 389 } 390 } else if (tag.IsStr()) { 391 out << MakePrintableString(tag.GetStr()); 392 } else if (tag.IsFloat()) { 393 out << tag.GetFloat(); 394 } else if (tag.IsHash()) { 395 out << tag.GetHash(); 396 } else if (tag.IsBlob()) { 397 out << wxString::Format(wxT("(size = %u)"), tag.GetBlobSize()); 398 } else if (tag.IsBsob()) { 399 out << wxString::Format(wxT("(size = %u)"), tag.GetBsobSize()); 400 } else { 401 out << "(...)"; 402 } 403 out << " }"; 404 return out; 405} 406 407std::ostream& operator<<(std::ostream& out, const CServerTag& tag) 408{ 409 out << "{ "; 410 if (tag.GetName().empty()) { 411 out << hex(tag.GetNameID()) << ' ' << DecodeServerTagNameID(tag.GetNameID()); 412 } else { 413 out << TagNameString(tag.GetName()); 414 } 415 out << ", " << (unsigned)tag.GetType() << ' ' << DecodeTagType(tag.GetType()) << ", "; 416 if (tag.IsInt()) { 417 if (tag.GetNameID() == ST_DYNIP || tag.GetNameID() == ST_UDPKEYIP) { 418 out << CeD2kIP(tag.GetInt()); 419 } else if (tag.GetNameID() == ST_UDPKEY) { 420 out << hex((uint32_t)tag.GetInt()); 421 } else if (tag.GetNameID() == ST_UDPFLAGS) { 422 uint32_t flags = tag.GetInt(); 423 out << hex(flags); 424 if (flags) { 425 CFlagDecoder decoder; 426 ADD_DECODER_FLAG(decoder, SRV_UDPFLG_EXT_GETSOURCES); 427 ADD_DECODER_FLAG(decoder, SRV_UDPFLG_EXT_GETFILES); 428 ADD_DECODER_FLAG(decoder, SRV_UDPFLG_NEWTAGS); 429 ADD_DECODER_FLAG(decoder, SRV_UDPFLG_UNICODE); 430 ADD_DECODER_FLAG(decoder, SRV_UDPFLG_EXT_GETSOURCES2); 431 ADD_DECODER_FLAG(decoder, SRV_UDPFLG_LARGEFILES); 432 ADD_DECODER_FLAG(decoder, SRV_UDPFLG_UDPOBFUSCATION); 433 ADD_DECODER_FLAG(decoder, SRV_UDPFLG_TCPOBFUSCATION); 434 out << " (" << decoder.DecodeFlags(flags) << ')'; 435 } 436 } else if (tag.GetNameID() == ST_PREFERENCE) { 437 out << tag.GetInt() << ' '; 438 switch (tag.GetInt()) { 439 case 0: out << "SRV_PR_NORMAL"; break; 440 case 1: out << "SRV_PR_HIGH"; break; 441 case 2: out << "SRV_PR_LOW"; break; 442 default: out << "??"; 443 } 444 } else { 445 out << tag.GetInt(); 446 } 447 } else if (tag.IsStr()) { 448 out << MakePrintableString(tag.GetStr()); 449 } else if (tag.IsFloat()) { 450 out << tag.GetFloat(); 451 } else if (tag.IsHash()) { 452 out << tag.GetHash(); 453 } else if (tag.IsBlob()) { 454 out << wxString::Format(wxT("(size = %u)"), tag.GetBlobSize()); 455 } else if (tag.IsBsob()) { 456 out << wxString::Format(wxT("(size = %u)"), tag.GetBsobSize()); 457 } else { 458 out << "(...)"; 459 } 460 out << " }"; 461 return out; 462} 463 464std::ostream& operator<<(std::ostream& out, const CFriendTag& tag) 465{ 466 out << "{ "; 467 if (tag.GetName().empty()) { 468 out << hex(tag.GetNameID()) << ' ' << DecodeFriendTagNameID(tag.GetNameID()); 469 } else { 470 out << TagNameString(tag.GetName()); 471 } 472 out << ", " << (unsigned)tag.GetType() << ' ' << DecodeTagType(tag.GetType()) << ", "; 473 if (tag.IsInt()) { 474 out << tag.GetInt(); 475 } else if (tag.IsStr()) { 476 out << MakePrintableString(tag.GetStr()); 477 } else if (tag.IsFloat()) { 478 out << tag.GetFloat(); 479 } else if (tag.IsHash()) { 480 out << tag.GetHash(); 481 } else if (tag.IsBlob()) { 482 out << wxString::Format(wxT("(size = %u)"), tag.GetBlobSize()); 483 } else if (tag.IsBsob()) { 484 out << wxString::Format(wxT("(size = %u)"), tag.GetBsobSize()); 485 } else { 486 out << "(...)"; 487 } 488 out << " }"; 489 return out; 490} 491