diff options
author | George Hazan <george.hazan@gmail.com> | 2014-09-18 21:52:10 +0000 |
---|---|---|
committer | George Hazan <george.hazan@gmail.com> | 2014-09-18 21:52:10 +0000 |
commit | 6d932bfaf11e4699355fedc45e28b353b8877130 (patch) | |
tree | 78d3f6741cf9762d2c6b97ed1f5bc472e850e15f /protocols/WhatsApp/src/WhatsAPI++ | |
parent | 4dd774d667df90583315c04696537b6397f6fc02 (diff) |
merge into trunk
git-svn-id: http://svn.miranda-ng.org/main/trunk@10515 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c
Diffstat (limited to 'protocols/WhatsApp/src/WhatsAPI++')
-rw-r--r-- | protocols/WhatsApp/src/WhatsAPI++/BinTreeNodeReader.cpp | 3 | ||||
-rw-r--r-- | protocols/WhatsApp/src/WhatsAPI++/BinTreeNodeWriter.cpp | 1 | ||||
-rw-r--r-- | protocols/WhatsApp/src/WhatsAPI++/ByteArray.cpp | 6 | ||||
-rw-r--r-- | protocols/WhatsApp/src/WhatsAPI++/FMessage.cpp | 1 | ||||
-rw-r--r-- | protocols/WhatsApp/src/WhatsAPI++/PhoneNumber.cpp | 297 | ||||
-rw-r--r-- | protocols/WhatsApp/src/WhatsAPI++/PhoneNumber.h | 23 | ||||
-rw-r--r-- | protocols/WhatsApp/src/WhatsAPI++/ProtocolTreeNode.cpp | 2 | ||||
-rw-r--r-- | protocols/WhatsApp/src/WhatsAPI++/WAConnection.h | 1 | ||||
-rw-r--r-- | protocols/WhatsApp/src/WhatsAPI++/WARegister.cpp | 94 | ||||
-rw-r--r-- | protocols/WhatsApp/src/WhatsAPI++/WARegister.h | 23 | ||||
-rw-r--r-- | protocols/WhatsApp/src/WhatsAPI++/utilities.cpp | 267 | ||||
-rw-r--r-- | protocols/WhatsApp/src/WhatsAPI++/utilities.h | 7 |
12 files changed, 557 insertions, 168 deletions
diff --git a/protocols/WhatsApp/src/WhatsAPI++/BinTreeNodeReader.cpp b/protocols/WhatsApp/src/WhatsAPI++/BinTreeNodeReader.cpp index 9da677ba87..388bf10e4a 100644 --- a/protocols/WhatsApp/src/WhatsAPI++/BinTreeNodeReader.cpp +++ b/protocols/WhatsApp/src/WhatsAPI++/BinTreeNodeReader.cpp @@ -342,6 +342,3 @@ int BinTreeNodeReader::readInt24(ISocketConnection* in) { return value;
}
-
-
-
diff --git a/protocols/WhatsApp/src/WhatsAPI++/BinTreeNodeWriter.cpp b/protocols/WhatsApp/src/WhatsAPI++/BinTreeNodeWriter.cpp index 2c244d53b7..6936de9a8b 100644 --- a/protocols/WhatsApp/src/WhatsAPI++/BinTreeNodeWriter.cpp +++ b/protocols/WhatsApp/src/WhatsAPI++/BinTreeNodeWriter.cpp @@ -264,4 +264,3 @@ BinTreeNodeWriter::~BinTreeNodeWriter() { if (this->out != NULL)
delete this->out;
}
-
diff --git a/protocols/WhatsApp/src/WhatsAPI++/ByteArray.cpp b/protocols/WhatsApp/src/WhatsAPI++/ByteArray.cpp index c9117bcfee..d52b10c549 100644 --- a/protocols/WhatsApp/src/WhatsAPI++/ByteArray.cpp +++ b/protocols/WhatsApp/src/WhatsAPI++/ByteArray.cpp @@ -147,9 +147,3 @@ void ByteArrayOutputStream::print() { _LOGDATA("%s", numbers.c_str());
_LOGDATA("]");
}
-
-
-
-
-
-
diff --git a/protocols/WhatsApp/src/WhatsAPI++/FMessage.cpp b/protocols/WhatsApp/src/WhatsAPI++/FMessage.cpp index b8586eb538..0eca3aeef7 100644 --- a/protocols/WhatsApp/src/WhatsAPI++/FMessage.cpp +++ b/protocols/WhatsApp/src/WhatsAPI++/FMessage.cpp @@ -125,4 +125,3 @@ unsigned char FMessage::getMessage_WA_Type(std::string* type) { return WA_TYPE_UNDEFINED;
}
-
diff --git a/protocols/WhatsApp/src/WhatsAPI++/PhoneNumber.cpp b/protocols/WhatsApp/src/WhatsAPI++/PhoneNumber.cpp new file mode 100644 index 0000000000..8171094d5c --- /dev/null +++ b/protocols/WhatsApp/src/WhatsAPI++/PhoneNumber.cpp @@ -0,0 +1,297 @@ +/*
+ * PhoneNumber.cpp
+ *
+ */
+
+#include "PhoneNumber.h"
+#include "WAException.h"
+
+struct CountryDescr
+{
+ char *name;
+ int countryCode, mcc, mnc;
+ char *ISO3166, *ISO639;
+}
+static countries[] =
+{
+ { "Russia", 7, 250, 20, "RU", "ru" },
+ { "Kazakhstan", 7, 401, 77, "KZ", "kk" },
+ { "Afghanistan", 93, 412, 1, "AF", "ps" },
+ { "Albania", 355, 276, 1, "AL", "sq" },
+ { "Alberta", 1403, 302, 720, "CA", "en" },
+ { "Alberta", 1780, 302, 720, "CA", "en" },
+ { "Algeria", 213, 603, 1, "DZ", "ar" },
+ { "Andorra", 376, 213, 3, "AD", "ca" },
+ { "Angola", 244, 631, 2, "AO", "pt" },
+ { "Anguilla", 1264, 365, 10, "AI", "en" },
+ { "Antarctica (Australian bases)", 6721, 232, 1, "AQ", "en" },
+ { "Antigua and Barbuda", 1268, 344, 50, "AG", "en" },
+ { "Argentina", 54, 722, 10, "AR", "es" },
+ { "Armenia", 374, 283, 10, "AM", "hy" },
+ { "Aruba", 297, 363, 1, "AW", "nl" },
+ { "Ascension", 247, 658, 1, "AC", "en" },
+ { "Australia", 61, 505, 1, "AU", "en" },
+ { "Austria", 43, 232, 3, "AT", "de" },
+ { "Azerbaijan", 994, 400, 1, "AZ", "az" },
+ { "Bahamas", 1242, 364, 39, "BS", "en" },
+ { "Bahrain", 973, 426, 1, "BH", "ar" },
+ { "Bangladesh", 880, 470, 1, "BD", "bn" },
+ { "Barbados", 1246, 342, 750, "BB", "en" },
+ { "Belarus", 375, 257, 1, "BY", "be" },
+ { "Belgium", 32, 206, 1, "BE", "nl" },
+ { "Belize", 501, 702, 67, "BZ", "es" },
+ { "Benin", 229, 616, 1, "BJ", "fr" },
+ { "Bermuda", 1441, 350, 1, "BM", "en" },
+ { "Bhutan", 975, 402, 11, "BT", "dz" },
+ { "Bolivia", 591, 736, 1, "BO", "es" },
+ { "Bosnia and Herzegovina", 387, 218, 3, "BA", "bs" },
+ { "Botswana", 267, 652, 4, "BW", "en" },
+ { "Brazil", 55, 724, 2, "BR", "pt" },
+ { "British Columbia", 1250, 302, 720, "CA", "en" },
+ { "British Columbia", 1604, 302, 720, "CA", "en" },
+ { "British Columbia", 1778, 302, 720, "CA", "en" },
+ { "British Indian Ocean Territory", 246, 348, 1, "IO", "en" },
+ { "British Virgin Islands", 1284, 348, 170, "GB", "en" },
+ { "Brunei", 673, 528, 11, "BN", "ms" },
+ { "Bulgaria", 359, 284, 3, "BG", "bg" },
+ { "Burkina Faso", 226, 613, 1, "BF", "fr" },
+ { "Burundi", 257, 642, 82, "BI", "rn" },
+ { "Cambodia", 855, 456, 2, "KH", "km" },
+ { "Cameroon", 237, 624, 1, "CM", "fr" },
+ { "Cape Verde", 238, 625, 1, "CV", "pt" },
+ { "Cayman Islands", 1345, 346, 50, "GB", "en" },
+ { "Central African Republic", 236, 623, 3, "CF", "sg" },
+ { "Chad", 235, 622, 4, "TD", "fr" },
+ { "Chile", 56, 730, 2, "CL", "es" },
+ { "China", 86, 460, 3, "CN", "en" },
+ { "Colombia", 57, 732, 102, "CO", "es" },
+ { "Comoros", 269, 654, 1, "KM", "fr" },
+ { "Democratic Republic of the Congo", 243, 630, 1, "CD", "fr" },
+ { "Republic of the Congo", 242, 629, 1, "CG", "fr" },
+ { "Cook Islands", 682, 548, 1, "CK", "en" },
+ { "Costa Rica", 506, 658, 4, "CR", "es" },
+ { "Cote d'Ivoire", 712, 612, 1, "CI", "fr" },
+ { "Croatia", 385, 219, 1, "HR", "hr" },
+ { "Cuba", 53, 368, 1, "CU", "es" },
+ { "Cyprus", 357, 280, 1, "CY", "el" },
+ { "Czech Republic", 420, 230, 2, "CZ", "cs" },
+ { "Denmark", 45, 238, 1, "DK", "da" },
+ { "Djibouti", 253, 638, 1, "DJ", "fr" },
+ { "Dominica", 1767, 366, 20, "DM", "en" },
+ { "Dominican Republic", 1809, 370, 1, "DO", "es" },
+ { "Dominican Republic", 1829, 370, 1, "DO", "en" },
+ { "East Timor", 670, 514, 1, "TL", "pt" },
+ { "Ecuador", 593, 740, 0, "EC", "es" },
+ { "Egypt", 20, 602, 2, "EG", "ar" },
+ { "El Salvador", 503, 706, 1, "SV", "es" },
+ { "Equatorial Guinea", 240, 627, 3, "GQ", "es" },
+ { "Eritrea", 291, 657, 1, "ER", "ti" },
+ { "Estonia", 372, 248, 3, "EE", "et" },
+ { "Ethiopia", 251, 636, 11, "ET", "am" },
+ { "Falkland Islands", 500, 750, 1, "FK", "en" },
+ { "Faroe Islands", 298, 288, 2, "FO", "fo" },
+ { "Fiji", 679, 542, 1, "FJ", "en" },
+ { "Finland", 358, 244, 5, "FI", "fi" },
+ { "France", 33, 208, 9, "FR", "fr" },
+ { "French Guiana", 594, 742, 1, "GF", "fr" },
+ { "French Polynesia", 689, 547, 15, "PF", "fr" },
+ { "Gabon", 241, 628, 1, "GA", "fr" },
+ { "Gambia", 220, 607, 1, "GM", "en" },
+ { "Gaza Strip", 970, 0, 0, "PS", "ar" },
+ { "Georgia", 995, 282, 1, "GE", "ka" },
+ { "Germany", 49, 262, 1, "DE", "de" },
+ { "Ghana", 233, 620, 2, "GH", "ak" },
+ { "Gibraltar", 350, 266, 9, "GI", "en" },
+ { "Greece", 30, 202, 5, "GR", "el" },
+ { "Greenland", 299, 290, 1, "GL", "kl" },
+ { "Grenada", 1473, 352, 30, "GD", "en" },
+ { "Guadeloupe", 590, 340, 1, "GP", "fr" },
+ { "Guam", 1671, 535, 32, "GU", "en" },
+ { "Guatemala", 502, 704, 1, "GT", "es" },
+ { "Guinea", 224, 611, 1, "GN", "fr" },
+ { "Guinea-Bissau", 245, 632, 3, "GW", "pt" },
+ { "Guyana", 592, 738, 1, "GY", "pt" },
+ { "Haiti", 509, 372, 2, "HT", "fr" },
+ { "Honduras", 504, 708, 2, "HN", "es" },
+ { "Hong Kong", 852, 454, 0, "HK", "zh" },
+ { "Hungary", 36, 216, 70, "HU", "hu" },
+ { "Iceland", 354, 274, 2, "IS", "is" },
+ { "India", 91, 404, 30, "IN", "hi" },
+ { "Indonesia", 62, 510, 10, "ID", "id" },
+ { "Iraq", 964, 418, 20, "IQ", "ar" },
+ { "Iran", 98, 432, 35, "IR", "fa" },
+ { "Ireland (Eire)", 353, 272, 1, "IE", "en" },
+ { "Israel", 972, 425, 1, "IL", "he" },
+ { "Italy", 39, 222, 10, "IT", "it" },
+ { "Jamaica", 1876, 338, 50, "JM", "en" },
+ { "Japan", 81, 440, 1, "JP", "ja" },
+ { "Jordan", 962, 416, 77, "JO", "ar" },
+ { "Kenya", 254, 639, 7, "KE", "sw" },
+ { "Kiribati", 686, 545, 1, "KI", "en" },
+ { "Kuwait", 965, 419, 4, "KW", "ar" },
+ { "Kyrgyzstan", 996, 437, 1, "KG", "ky" },
+ { "Laos", 856, 457, 1, "LA", "lo" },
+ { "Latvia", 371, 247, 2, "LV", "lv" },
+ { "Lebanon", 961, 415, 1, "LB", "ar" },
+ { "Lesotho", 266, 651, 1, "LS", "st" },
+ { "Liberia", 231, 618, 7, "LR", "en" },
+ { "Libya", 218, 606, 0, "LY", "ar" },
+ { "Liechtenstein", 423, 295, 2, "LI", "de" },
+ { "Lithuania", 370, 246, 3, "LT", "lt" },
+ { "Luxembourg", 352, 270, 99, "LU", "fr" },
+ { "Macau", 853, 455, 2, "MO", "pt" },
+ { "Republic of Macedonia", 389, 294, 1, "MK", "mk" },
+ { "Madagascar", 261, 646, 2, "MG", "mg" },
+ { "Malawi", 265, 650, 1, "MW", "ny" },
+ { "Malaysia", 60, 502, 16, "MY", "en" },
+ { "Maldives", 960, 472, 1, "MV", "dv" },
+ { "Mali", 223, 610, 2, "ML", "fr" },
+ { "Malta", 356, 278, 1, "MT", "mt" },
+ { "Manitoba", 1204, 302, 720, "CA", "en" },
+ { "Marshall Islands", 692, 551, 1, "MH", "mh" },
+ { "Martinique", 596, 340, 1, "MQ", "fr" },
+ { "Mauritania", 222, 609, 2, "MR", "ar" },
+ { "Mauritius", 230, 617, 1, "MU", "en" },
+ { "Mayotte", 262, 654, 1, "YT", "fr" },
+ { "Mexico", 52, 334, 3, "MX", "es" },
+ { "Federated States of Micronesia", 691, 550, 1, "FM", "en" },
+ { "Moldova", 373, 259, 1, "MD", "ru" },
+ { "Monaco", 377, 212, 1, "MC", "fr" },
+ { "Mongolia", 976, 428, 91, "MN", "mn" },
+ { "Montenegro", 382, 297, 2, "ME", "sr" },
+ { "Montserrat", 1664, 354, 860, "MS", "en" },
+ { "Morocco", 212, 604, 0, "MA", "ar" },
+ { "Mozambique", 258, 643, 4, "MZ", "pt" },
+ { "Myanmar", 95, 414, 1, "MM", "my" },
+ { "Namibia", 264, 649, 3, "NA", "en" },
+ { "Nauru", 674, 536, 2, "NR", "na" },
+ { "Netherlands", 31, 204, 4, "NL", "nl" },
+ { "Netherlands Antilles", 599, 362, 51, "AN", "nl" },
+ { "Nepal", 977, 429, 1, "NP", "ne" },
+ { "New Brunswick", 1506, 302, 720, "CA", "en" },
+ { "New Caledonia", 687, 546, 1, "NC", "fr" },
+ { "New Zealand", 64, 530, 1, "NZ", "en" },
+ { "Newfoundland", 1709, 302, 720, "CA", "en" },
+ { "Nicaragua", 505, 710, 30, "NI", "es" },
+ { "Niger", 227, 614, 4, "NE", "fr" },
+ { "Nigeria", 234, 621, 20, "NG", "ha" },
+ { "Niue", 683, 555, 1, "NU", "en" },
+ { "Norfolk Island", 6723, 505, 10, "NF", "en" },
+ { "North Korea", 850, 467, 193, "KP", "ko" },
+ { "Northern Mariana Islands", 1670, 534, 1, "MP", "en" },
+ { "Northwest Territories", 1867, 302, 720, "CA", "en" },
+ { "Norway", 47, 242, 4, "NO", "nb" },
+ { "Nova Scotia", 1902, 302, 720, "CA", "en" },
+ { "Oman", 968, 422, 2, "OM", "ar" },
+ { "Ontario", 1416, 302, 720, "CA", "en" },
+ { "Ontario", 1519, 302, 720, "CA", "en" },
+ { "Ontario", 1613, 302, 720, "CA", "en" },
+ { "Ontario", 1647, 302, 720, "CA", "en" },
+ { "Ontario", 1705, 302, 720, "CA", "en" },
+ { "Ontario", 1807, 302, 720, "CA", "en" },
+ { "Ontario", 1905, 302, 720, "CA", "en" },
+ { "Pakistan", 92, 410, 1, "PK", "en" },
+ { "Palau", 680, 552, 80, "PW", "en" },
+ { "Palestine", 970, 425, 6, "PS", "ar" },
+ { "Panama", 507, 714, 2, "PA", "es" },
+ { "Papua New Guinea", 675, 537, 3, "PG", "ho" },
+ { "Paraguay", 595, 744, 6, "PY", "es" },
+ { "Peru", 51, 716, 6, "PE", "es" },
+ { "Philippines", 63, 515, 2, "PH", "fil" },
+ { "Poland", 48, 260, 3, "PL", "pl" },
+ { "Portugal", 351, 268, 1, "PT", "pt" },
+ { "Qatar", 974, 427, 2, "QA", "ar" },
+ { "Quebec", 1418, 302, 720, "CA", "en" },
+ { "Quebec", 1450, 302, 720, "CA", "en" },
+ { "Quebec", 1514, 302, 720, "CA", "en" },
+ { "Quebec", 1819, 302, 720, "CA", "en" },
+ { "Reunion", 262, 647, 0, "RE", "fr" },
+ { "Romania", 40, 226, 1, "RO", "ro" },
+ { "Rwanda", 250, 635, 10, "RW", "rw" },
+ { "Saint-Barthelemy", 590, 340, 1, "BL", "fr" },
+ { "Saint Helena", 290, 658, 1, "SH", "en" },
+ { "Saint Kitts and Nevis", 1869, 356, 50, "KN", "en" },
+ { "Saint Lucia", 1758, 358, 50, "LC", "en" },
+ { "Saint Martin (French side)", 590, 340, 1, "MF", "fr" },
+ { "Saint Pierre and Miquelon", 508, 308, 2, "PM", "fr" },
+ { "Saint Vincent and the Grenadines", 1670, 360, 70, "VC", "en" },
+ { "Samoa", 685, 549, 1, "WS", "sm" },
+ { "Sao Tome and Principe", 239, 626, 1, "ST", "pt" },
+ { "Saskatchewan", 1306, 302, 720, "CA", "en" },
+ { "Saudi Arabia", 966, 420, 4, "SA", "ar" },
+ { "Senegal", 221, 608, 1, "SN", "wo" },
+ { "Serbia", 381, 220, 1, "RS", "sr" },
+ { "Seychelles", 248, 633, 10, "SC", "fr" },
+ { "Sierra Leone", 232, 619, 4, "SL", "en" },
+ { "Singapore", 65, 525, 1, "SG", "en" },
+ { "Slovakia", 421, 231, 4, "SK", "sk" },
+ { "Slovenia", 386, 293, 31, "SI", "sl" },
+ { "Solomon Islands", 677, 540, 2, "SB", "en" },
+ { "Somalia", 252, 637, 82, "SO", "so" },
+ { "South Africa", 27, 655, 1, "ZA", "xh" },
+ { "South Korea", 82, 450, 5, "KR", "ko" },
+ { "South Sudan", 211, 659, 2, "SS", "en" },
+ { "Spain", 34, 214, 1, "ES", "es" },
+ { "Sri Lanka", 94, 413, 1, "LK", "si" },
+ { "Sudan", 249, 634, 7, "SD", "ar" },
+ { "Suriname", 597, 746, 3, "SR", "nl" },
+ { "Swaziland", 268, 653, 10, "SZ", "ss" },
+ { "Sweden", 46, 240, 7, "SE", "sv" },
+ { "Switzerland", 41, 228, 3, "CH", "de" },
+ { "Syria", 963, 417, 1, "SY", "ar" },
+ { "Taiwan", 886, 466, 1, "TW", "cmn" },
+ { "Tajikistan", 992, 436, 1, "TJ", "tg" },
+ { "Tanzania", 255, 640, 4, "TZ", "sw" },
+ { "Thailand", 66, 520, 0, "TH", "th" },
+ { "Togo", 228, 615, 1, "TG", "fr" },
+ { "Tokelau", 690, 690, 1, "TK", "tkl" },
+ { "Tonga", 676, 539, 1, "TO", "to" },
+ { "Trinidad and Tobago", 1868, 374, 12, "TT", "en" },
+ { "Tunisia", 216, 605, 1, "TN", "ar" },
+ { "Turkey", 90, 286, 2, "TR", "tr" },
+ { "Turkmenistan", 993, 438, 1, "TM", "tk" },
+ { "Turks and Caicos Islands", 1649, 376, 50, "TC", "en" },
+ { "Tuvalu", 688, 553, 1, "TV", "tvl" },
+ { "Uganda", 256, 641, 14, "UG", "sw" },
+ { "Ukraine", 380, 255, 1, "UA", "uk" },
+ { "United Arab Emirates", 971, 424, 2, "AE", "ar" },
+ { "United Kingdom", 44, 234, 10, "GB", "en" },
+ { "United States of America", 1, 310, 4, "US", "en" },
+ { "Uruguay", 598, 748, 7, "UY", "es" },
+ { "Uzbekistan", 998, 434, 7, "UZ", "uz" },
+ { "Vanuatu", 678, 541, 5, "VU", "bi" },
+ { "Venezuela", 58, 734, 4, "VE", "es" },
+ { "Vietnam", 84, 452, 1, "VN", "vi" },
+ { "U.S. Virgin Islands", 1340, 332, 4, "VI", "en" },
+ { "Wallis and Futuna", 681, 543, 1, "WF", "fr" },
+ { "West Bank", 970, 0, 1, "PS", "ar" },
+ { "Yemen", 967, 421, 2, "YE", "ar" },
+ { "Zambia", 260, 645, 2, "ZM", "en" },
+ { "Zimbabwe", 263, 648, 2, "ZW", "en" }
+};
+
+PhoneNumber::PhoneNumber(const std::string &szNumber)
+{
+ int cc1 = atoi(szNumber.substr(0, 1).c_str()), cc2 = atoi(szNumber.substr(0, 2).c_str()), cc3 = atoi(szNumber.substr(0, 3).c_str());
+
+ for (int i = 0; i < _countof(countries); i++) {
+ CountryDescr &p = countries[i];
+ if (p.countryCode != cc1 && p.countryCode != cc2 && p.countryCode != cc3)
+ continue;
+
+ if (p.countryCode == 7)
+ if (i == 0 && (cc2 == '77' || cc2 == '76'))
+ continue;
+
+ this->Country = p.name;
+ this->countryCode = p.countryCode;
+ this->Number = szNumber.substr(1 + (size_t)floor(log10(double(p.countryCode))));
+ this->ISO3166 = p.ISO3166;
+ this->ISO639 = p.ISO639;
+ this->mcc = p.mcc;
+ this->mnc = p.mnc;
+ return;
+ }
+
+ throw new WAException("Could not dissect phone number " + szNumber);
+}
diff --git a/protocols/WhatsApp/src/WhatsAPI++/PhoneNumber.h b/protocols/WhatsApp/src/WhatsAPI++/PhoneNumber.h new file mode 100644 index 0000000000..aa3dd16ef9 --- /dev/null +++ b/protocols/WhatsApp/src/WhatsAPI++/PhoneNumber.h @@ -0,0 +1,23 @@ +/*
+ * PhoneNumber.h
+ *
+ */
+
+#ifndef PHONENUMBER_H_
+#define PHONENUMBER_H_
+
+#include <string>
+
+struct PhoneNumber
+{
+ PhoneNumber(const std::string &number);
+
+ std::string Country;
+ std::string Number;
+
+ const char *ISO3166, *ISO639;
+ int countryCode;
+ int mcc, mnc;
+};
+
+#endif /* PHONENUMBER_H_ */
diff --git a/protocols/WhatsApp/src/WhatsAPI++/ProtocolTreeNode.cpp b/protocols/WhatsApp/src/WhatsAPI++/ProtocolTreeNode.cpp index be6a658acb..a44fa27812 100644 --- a/protocols/WhatsApp/src/WhatsAPI++/ProtocolTreeNode.cpp +++ b/protocols/WhatsApp/src/WhatsAPI++/ProtocolTreeNode.cpp @@ -131,5 +131,3 @@ void ProtocolTreeNode::require(ProtocolTreeNode *node, const string& tag) { if (!tagEquals(node, tag))
throw WAException("failed require. node:" + node->toString() + "tag: " + tag, WAException::CORRUPT_STREAM_EX, 0);
}
-
-
diff --git a/protocols/WhatsApp/src/WhatsAPI++/WAConnection.h b/protocols/WhatsApp/src/WhatsAPI++/WAConnection.h index 9ee5d3e48f..96a813ecd0 100644 --- a/protocols/WhatsApp/src/WhatsAPI++/WAConnection.h +++ b/protocols/WhatsApp/src/WhatsAPI++/WAConnection.h @@ -462,5 +462,4 @@ class WAConnection { void sendDeleteAccount() throw(WAException);
};
-
#endif /* WACONNECTION_H_ */
diff --git a/protocols/WhatsApp/src/WhatsAPI++/WARegister.cpp b/protocols/WhatsApp/src/WhatsAPI++/WARegister.cpp new file mode 100644 index 0000000000..d67d2f4a8c --- /dev/null +++ b/protocols/WhatsApp/src/WhatsAPI++/WARegister.cpp @@ -0,0 +1,94 @@ +/*
+ * WARegister.cpp
+ *
+ */
+
+#include "../common.h" // #TODO Remove Miranda-dependency
+
+#include "WARegister.h"
+#include "PhoneNumber.h"
+
+using namespace Utilities;
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// Token generation
+
+static char WaKey[] = "/UIGKU1FVQa+ATM2A0za7G2KI9S/CwPYjgAbc67v7ep42eO/WeTLx1lb1cHwxpsEgF4+PmYpLd2YpGUdX/A2JQitsHzDwgcdBpUf7psX1BU=";
+static char WaSignature[] = "MIIDMjCCAvCgAwIBAgIETCU2pDALBgcqhkjOOAQDBQAwfDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExFDASBgNVBAcTC1NhbnRhIENsYXJhMRYwFAYDVQQKEw1XaGF0c0FwcCBJbmMuMRQwEgYDVQQLEwtFbmdpbmVlcmluZzEUMBIGA1UEAxMLQnJpYW4gQWN0b24wHhcNMTAwNjI1MjMwNzE2WhcNNDQwMjE1MjMwNzE2WjB8MQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEUMBIGA1UEBxMLU2FudGEgQ2xhcmExFjAUBgNVBAoTDVdoYXRzQXBwIEluYy4xFDASBgNVBAsTC0VuZ2luZWVyaW5nMRQwEgYDVQQDEwtCcmlhbiBBY3RvbjCCAbgwggEsBgcqhkjOOAQBMIIBHwKBgQD9f1OBHXUSKVLfSpwu7OTn9hG3UjzvRADDHj+AtlEmaUVdQCJR+1k9jVj6v8X1ujD2y5tVbNeBO4AdNG/yZmC3a5lQpaSfn+gEexAiwk+7qdf+t8Yb+DtX58aophUPBPuD9tPFHsMCNVQTWhaRMvZ1864rYdcq7/IiAxmd0UgBxwIVAJdgUI8VIwvMspK5gqLrhAvwWBz1AoGBAPfhoIXWmz3ey7yrXDa4V7l5lK+7+jrqgvlXTAs9B4JnUVlXjrrUWU/mcQcQgYC0SRZxI+hMKBYTt88JMozIpuE8FnqLVHyNKOCjrh4rs6Z1kW6jfwv6ITVi8ftiegEkO8yk8b6oUZCJqIPf4VrlnwaSi2ZegHtVJWQBTDv+z0kqA4GFAAKBgQDRGYtLgWh7zyRtQainJfCpiaUbzjJuhMgo4fVWZIvXHaSHBU1t5w//S0lDK2hiqkj8KpMWGywVov9eZxZy37V26dEqr/c2m5qZ0E+ynSu7sqUD7kGx/zeIcGT0H+KAVgkGNQCo5Uc0koLRWYHNtYoIvt5R3X6YZylbPftF/8ayWTALBgcqhkjOOAQDBQADLwAwLAIUAKYCp0d6z4QQdyN74JDfQ2WCyi8CFDUM4CaNB+ceVXdKtOrNTQcc0e+t";
+static char WaClassesMd5[] = "iV15qOB/jPIidogqfJ/oJA==";
+
+std::string WAToken::GenerateToken(const string &number)
+{
+ unsigned int keyLen, dataLen, classesLen;
+ mir_ptr<BYTE> key((BYTE*)mir_base64_decode(WaKey, &keyLen));
+ mir_ptr<BYTE> data((BYTE*)mir_base64_decode(WaSignature, &dataLen));
+ mir_ptr<BYTE> classes((BYTE*)mir_base64_decode(WaClassesMd5, &classesLen));
+
+ BYTE opad[64], ipad[64];
+ memset(opad, 0x5C, sizeof(opad));
+ memset(ipad, 0x36, sizeof(ipad));
+ for (int i = 0; i < sizeof(opad); i++) {
+ opad[i] = (BYTE)(opad[i] ^ key[i]);
+ ipad[i] = (BYTE)(ipad[i] ^ key[i]);
+ }
+
+ BYTE hash1[MIR_SHA1_HASH_SIZE], hash2[MIR_SHA1_HASH_SIZE];
+ mir_sha1_ctx ctx;
+ mir_sha1_init(&ctx);
+ mir_sha1_append(&ctx, ipad, sizeof(ipad));
+ mir_sha1_append(&ctx, data, dataLen);
+ mir_sha1_append(&ctx, classes, classesLen);
+ mir_sha1_append(&ctx, (PBYTE)number.c_str(), (int)number.size());
+ mir_sha1_finish(&ctx, hash1);
+
+ mir_sha1_init(&ctx);
+ mir_sha1_append(&ctx, opad, sizeof(opad));
+ mir_sha1_append(&ctx, hash1, sizeof(hash1));
+ mir_sha1_finish(&ctx, hash2);
+
+ ptrA result(mir_urlEncode(ptrA(mir_base64_encode(hash2, sizeof(hash2)))));
+ return std::string(result);
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// Account registration
+
+CMStringA WARegister::RequestCodeUrl(const std::string &phoneNumber, const std::string &code)
+{
+ try {
+ std::string id = GenerateIdentity(phoneNumber);
+
+ PhoneNumber pn(phoneNumber); + std::string token = WAToken::GenerateToken(pn.Number);
+ + const char *n = pn.Number.c_str(); + + if (!code.empty()) + return CMStringA(FORMAT, "https://v.whatsapp.net/v2/register?cc=%d&in=%s&id=%s&code=%s", pn.countryCode, n, id.c_str(), code.c_str()); + + return CMStringA(FORMAT, "https://v.whatsapp.net/v2/code?cc=%d&in=%s&to=%d%s&method=sms&mcc=%03d&mnc=%03d&token=%s&id=%s&lg=%s&lc=%s", + pn.countryCode, n, pn.countryCode, n, pn.mcc, pn.mnc, token.c_str(), id.c_str(), pn.ISO639, pn.ISO3166); + }
+ catch (...)
+ {}
+
+ return CMStringA();
+}
+
+std::string WARegister::GenerateIdentity(const std::string &phone)
+{
+ std::string id = phone;
+ std::reverse(id.begin(), id.end());
+
+ BYTE hash[MIR_SHA1_HASH_SIZE];
+ mir_sha1_hash((PBYTE)id.c_str(), (int)id.length(), hash);
+
+ id.clear();
+ for (int i = 0; i < sizeof(hash); i++) {
+ char buf[10];
+ sprintf_s(buf, "%%%02x", hash[i]);
+ id += buf;
+ }
+
+ return id;
+}
diff --git a/protocols/WhatsApp/src/WhatsAPI++/WARegister.h b/protocols/WhatsApp/src/WhatsAPI++/WARegister.h new file mode 100644 index 0000000000..f2fe0e230b --- /dev/null +++ b/protocols/WhatsApp/src/WhatsAPI++/WARegister.h @@ -0,0 +1,23 @@ +/*
+ * WARegister.h
+ */
+
+#ifndef WAREGISTER_H_
+#define WAREGISTER_H_
+
+#include <string>
+
+struct WAToken
+{
+ static std::string GenerateToken(const std::string &number);
+};
+
+class WARegister
+{
+ static std::string GenerateIdentity(const std::string &phone);
+
+public:
+ static CMStringA RequestCodeUrl(const std::string &phone, const std::string &code);
+};
+
+#endif /* WAREGISTER_H_ */
diff --git a/protocols/WhatsApp/src/WhatsAPI++/utilities.cpp b/protocols/WhatsApp/src/WhatsAPI++/utilities.cpp index f2603f9f8d..dc28b86c69 100644 --- a/protocols/WhatsApp/src/WhatsAPI++/utilities.cpp +++ b/protocols/WhatsApp/src/WhatsAPI++/utilities.cpp @@ -13,41 +13,24 @@ #include <fstream>
#include <iomanip>
-namespace Utilities{
-
+namespace Utilities {
+
const static char digits[] = {
- '0' , '1' , '2' , '3' , '4' , '5' ,
- '6' , '7' , '8' , '9' , 'a' , 'b' ,
- 'c' , 'd' , 'e' , 'f' , 'g' , 'h' ,
- 'i' , 'j' , 'k' , 'l' , 'm' , 'n' ,
- 'o' , 'p' , 'q' , 'r' , 's' , 't' ,
- 'u' , 'v' , 'w' , 'x' , 'y' , 'z'
+ '0', '1', '2', '3', '4', '5',
+ '6', '7', '8', '9', 'a', 'b',
+ 'c', 'd', 'e', 'f', 'g', 'h',
+ 'i', 'j', 'k', 'l', 'm', 'n',
+ 'o', 'p', 'q', 'r', 's', 't',
+ 'u', 'v', 'w', 'x', 'y', 'z'
};
-void configureLogging(const char* ident) {
-#ifndef _LOGWIN32
- openlog(ident, 0, LOG_USER);
-#endif
-}
-
-void closeLog() {
-#ifndef _LOGWIN32
- closelog();
-#endif
-}
-
-std::string getCountryCode(){
- return "34";
-}
-
std::string reverseString(const std::string& str)
{
return std::string(str.rbegin(), str.rend());
}
-
-
-std::string itoa(int value, unsigned int base) {
+std::string itoa(int value, unsigned int base)
+{
const char digitMap[] = "0123456789abcdef";
@@ -70,8 +53,8 @@ std::string itoa(int value, unsigned int base) { // Translating number to string with base:
- for (int i = 30; _value && i ; --i) {
- buf = digitMap[ _value % base ] + buf;
+ for (int i = 30; _value && i; --i) {
+ buf = digitMap[_value % base] + buf;
_value /= base;
}
@@ -79,24 +62,26 @@ std::string itoa(int value, unsigned int base) { }
-std::string processIdentity(const std::string& id){
+std::string processIdentity(const std::string& id)
+{
std::string buffer_str = reverseString(id);
- unsigned char digest[16];
- md5_string(buffer_str, digest);
+ unsigned char digest[16];
+ md5_string(buffer_str, digest);
buffer_str.clear();
- for(int i =0; i < 16; i++){
- int tmp = digest[i]+128;
+ for (int i = 0; i < 16; i++) {
+ int tmp = digest[i] + 128;
int f = tmp & 0xff;
- buffer_str = buffer_str.append(itoa(f,16));
+ buffer_str = buffer_str.append(itoa(f, 16));
}
return buffer_str;
}
-void debug(const std::string& msg) {
+void debug(const std::string& msg)
+{
#ifdef _LOGWIN32
cout << "DEBUG: " << msg << endl;
#else
@@ -104,7 +89,8 @@ void debug(const std::string& msg) { #endif
}
-std::string str(int64_t i, int radix ) {
+std::string str(int64_t i, int radix)
+{
if (radix < 2 || radix > 36)
throw WAException("radix must be in 2..36");
char buf[65];
@@ -130,34 +116,39 @@ std::string str(int64_t i, int radix ) { return std::string(aux, charPos, (65 - charPos));
}
-int64_t randLong() {
+int64_t randLong()
+{
std::srand((unsigned)time(NULL));
- int64_t r = (int64_t) ((char) (std::rand() % 256));
+ int64_t r = (int64_t)((char)(std::rand() % 256));
- for (int i = 0; i < 7 ; i++)
- r = (r << 8) + ((char) (std::rand() % 256));
+ for (int i = 0; i < 7; i++)
+ r = (r << 8) + ((char)(std::rand() % 256));
return r;
}
-int64_t absLong(int64_t num) {
- return (num >= 0? num: -num);
+int64_t absLong(int64_t num)
+{
+ return (num >= 0 ? num : -num);
}
-std::string intToStr(int i) {
+std::string intToStr(int i)
+{
std::stringstream convert;
convert << i;
return convert.str();
}
-std::string doubleToStr(double d) {
+std::string doubleToStr(double d)
+{
std::stringstream convert;
convert << d;
return convert.str();
}
-time_t parseBBDate(const string& s) {
+time_t parseBBDate(const string& s)
+{
_LOGDATA("parse DATE %s", s.c_str());
if (s.length() < 17)
return time(NULL);
@@ -165,16 +156,17 @@ time_t parseBBDate(const string& s) { struct tm timeinfo;
timeinfo.tm_year = atoi(s.substr(0, 4).c_str()) - 1900;
timeinfo.tm_mon = atoi(s.substr(4, 2).c_str()) - 1;
- timeinfo.tm_mday = atoi(s.substr(6,2).c_str());
- timeinfo.tm_hour = atoi(s.substr(9,2).c_str());
- timeinfo.tm_min = atoi(s.substr(12,2).c_str());
- timeinfo.tm_sec = atoi(s.substr(15,2).c_str());
+ timeinfo.tm_mday = atoi(s.substr(6, 2).c_str());
+ timeinfo.tm_hour = atoi(s.substr(9, 2).c_str());
+ timeinfo.tm_min = atoi(s.substr(12, 2).c_str());
+ timeinfo.tm_sec = atoi(s.substr(15, 2).c_str());
//return timegm(&timeinfo);
- return mktime(&timeinfo);
+ return mktime(&timeinfo);
}
-void logData(const char *format, ...) {
+void logData(const char *format, ...)
+{
va_list args;
va_start(args, format);
#ifdef _LOGWIN32
@@ -186,7 +178,8 @@ void logData(const char *format, ...) { }
-long long parseLongLong(const std::string& str) {
+long long parseLongLong(const std::string& str)
+{
std::stringstream sstr(str);
long long val;
sstr >> val;
@@ -194,8 +187,9 @@ long long parseLongLong(const std::string& str) { return val;
}
-string bytesToHex(unsigned char* bytes, int length) {
- string ret(length*2, ' ');
+string bytesToHex(unsigned char* bytes, int length)
+{
+ string ret(length * 2, ' ');
string::iterator p = ret.begin();
int i = 0;
for (int c = 0; c < length; c++) {
@@ -207,13 +201,15 @@ string bytesToHex(unsigned char* bytes, int length) { return ret;
}
-unsigned char forDigit(int b) {
+unsigned char forDigit(int b)
+{
if (b < 10)
- return (unsigned char) (48 + b);
- return (unsigned char) (97 + b - 10);
+ return (unsigned char)(48 + b);
+ return (unsigned char)(97 + b - 10);
}
-bool saveStringToFile(const string& data, const string& filePath) {
+bool saveStringToFile(const string& data, const string& filePath)
+{
std::ofstream out(filePath.c_str());
if (out.fail()) return false;
out << data;
@@ -223,10 +219,11 @@ bool saveStringToFile(const string& data, const string& filePath) { return true;
}
-bool saveBytesToFile(const std::vector<unsigned char>& data, const string& filePath) {
+bool saveBytesToFile(const std::vector<unsigned char>& data, const string& filePath)
+{
std::fstream out(filePath.c_str(), ios::out | ios::binary);
if (out.fail()) return false;
- out.write((const char*) &data[0], data.size());
+ out.write((const char*)&data[0], data.size());
if (out.fail()) return false;
out.close();
if (out.fail()) return false;
@@ -234,7 +231,8 @@ bool saveBytesToFile(const std::vector<unsigned char>& data, const string& fileP }
-bool saveBytesToFile(const string& data, const string& filePath) {
+bool saveBytesToFile(const string& data, const string& filePath)
+{
std::fstream out(filePath.c_str(), ios::out | ios::binary);
if (out.fail()) return false;
out.write(data.c_str(), data.length());
@@ -244,7 +242,8 @@ bool saveBytesToFile(const string& data, const string& filePath) { return true;
}
-vector<unsigned char>* loadFileToBytes(const string& path) {
+vector<unsigned char>* loadFileToBytes(const string& path)
+{
vector<unsigned char>* bytes = NULL;
std::ifstream in(path.c_str(), ios::in | ios::binary | ios::ate);
size_t size = in.tellg();
@@ -254,19 +253,21 @@ vector<unsigned char>* loadFileToBytes(const string& path) { char *buffer = new char[size];
in.read(buffer, size);
bytes = new vector<unsigned char>(buffer, buffer + size);
- delete [] buffer;
+ delete[] buffer;
in.close();
if (in.fail()) return NULL;
return bytes;
}
-bool fileExists(const std::string& path) {
+bool fileExists(const std::string& path)
+{
return _access(path.c_str(), 0) == 0;
}
-string removeWaDomainFromJid(const string& jid) {
+string removeWaDomainFromJid(const string& jid)
+{
string result = jid;
size_t index = jid.find("@s.whatsapp.net");
@@ -284,7 +285,8 @@ string removeWaDomainFromJid(const string& jid) { return jid;
}
-string getNameFromPath(const std::string& path) {
+string getNameFromPath(const std::string& path)
+{
size_t i = path.rfind('/');
if (i == string::npos)
i = 0;
@@ -293,11 +295,13 @@ string getNameFromPath(const std::string& path) { return path.substr(i);
}
-vector<unsigned char>* getChallengeData(const std::string& challengeFile) {
+vector<unsigned char>* getChallengeData(const std::string& challengeFile)
+{
return loadFileToBytes(challengeFile);
}
-bool saveChallengeData(const std::vector<unsigned char>& data, const std::string& challengeFile) {
+bool saveChallengeData(const std::vector<unsigned char>& data, const std::string& challengeFile)
+{
return saveBytesToFile(data, challengeFile);
}
@@ -305,42 +309,34 @@ std::string utf8_to_utf16(const std::string& utf8) {
std::vector<unsigned long> unicode;
size_t i = 0;
- while (i < utf8.size())
- {
+ while (i < utf8.size()) {
unsigned long uni;
size_t todo;
bool error = false;
unsigned char ch = utf8[i++];
- if (ch <= 0x7F)
- {
+ if (ch <= 0x7F) {
uni = ch;
todo = 0;
}
- else if (ch <= 0xBF)
- {
+ else if (ch <= 0xBF) {
throw std::logic_error("not a UTF-8 string");
}
- else if (ch <= 0xDF)
- {
- uni = ch&0x1F;
+ else if (ch <= 0xDF) {
+ uni = ch & 0x1F;
todo = 1;
}
- else if (ch <= 0xEF)
- {
- uni = ch&0x0F;
+ else if (ch <= 0xEF) {
+ uni = ch & 0x0F;
todo = 2;
}
- else if (ch <= 0xF7)
- {
- uni = ch&0x07;
+ else if (ch <= 0xF7) {
+ uni = ch & 0x07;
todo = 3;
}
- else
- {
+ else {
throw std::logic_error("not a UTF-8 string");
}
- for (size_t j = 0; j < todo; ++j)
- {
+ for (size_t j = 0; j < todo; ++j) {
if (i == utf8.size())
throw std::logic_error("not a UTF-8 string");
unsigned char ch = utf8[i++];
@@ -356,86 +352,63 @@ std::string utf8_to_utf16(const std::string& utf8) unicode.push_back(uni);
}
std::string utf16;
- for (size_t i = 0; i < unicode.size(); ++i)
- {
+ for (size_t i = 0; i < unicode.size(); ++i) {
unsigned long uni = unicode[i];
if (uni <= 0x7F) {
- utf16 += (char) uni;
+ utf16 += (char)uni;
}
else
- if (uni <= 0xFFFF)
- {
+ if (uni <= 0xFFFF) {
stringstream value;
value << std::setw(4) << std::setfill('0') << Utilities::itoa(uni, 16).c_str();
utf16 += "\\u" + value.str();
- }
- else
- {
- stringstream value1, value2;
- uni -= 0x10000;
- value1 << std::setw(4) << std::setfill('0') << Utilities::itoa(((uni >> 10) + 0xD800), 16);
- utf16 += "\\u" + value1.str();
-
- value2 << std::setw(4) << std::setfill('0') << Utilities::itoa(((uni & 0x3FF) + 0xDC00), 16);
- utf16 += "\\u" + value2.str();
- }
+ }
+ else {
+ stringstream value1, value2;
+ uni -= 0x10000;
+ value1 << std::setw(4) << std::setfill('0') << Utilities::itoa(((uni >> 10) + 0xD800), 16);
+ utf16 += "\\u" + value1.str();
+
+ value2 << std::setw(4) << std::setfill('0') << Utilities::itoa(((uni & 0x3FF) + 0xDC00), 16);
+ utf16 += "\\u" + value2.str();
+ }
}
return utf16;
}
std::string string_format(const char* fmt, va_list ap)
{
- int size = 100;
- std::string str;
- while (1) {
- str.resize(size);
- //va_start(ap, fmt);
- int n = vsnprintf((char *)str.c_str(), size, fmt, ap);
- //va_end(ap);
- if (n > -1 && n < size) {
- str.resize(n);
- return str;
- }
- if (n > -1)
- size = n + 1;
- else
- size *= 2;
- }
- return str;
+ int size = 100;
+ std::string str;
+ while (1) {
+ str.resize(size);
+ //va_start(ap, fmt);
+ int n = vsnprintf((char *)str.c_str(), size, fmt, ap);
+ //va_end(ap);
+ if (n > -1 && n < size) {
+ str.resize(n);
+ return str;
+ }
+ if (n > -1)
+ size = n + 1;
+ else
+ size *= 2;
+ }
+ return str;
}
std::string string_format(const std::string fmt, va_list ap)
{
- return string_format(fmt.c_str(), ap);
- /*
- int size = 100;
- std::string str;
- //va_list ap;
- while (1) {
- str.resize(size);
- //va_start(ap, fmt);
- int n = vsnprintf((char *)str.c_str(), size, fmt.c_str(), ap);
- //va_end(ap);
- if (n > -1 && n < size) {
- str.resize(n);
- return str;
- }
- if (n > -1)
- size = n + 1;
- else
- size *= 2;
- }
- return str;
- */
+ return string_format(fmt.c_str(), ap);
}
std::string string_format(const std::string fmt, ...)
{
- va_list ap;
- va_start(ap, fmt);
- std::string ret = string_format(fmt, ap);
- va_end(ap);
- return ret;
+ va_list ap;
+ va_start(ap, fmt);
+ std::string ret = string_format(fmt, ap);
+ va_end(ap);
+ return ret;
}
}
diff --git a/protocols/WhatsApp/src/WhatsAPI++/utilities.h b/protocols/WhatsApp/src/WhatsAPI++/utilities.h index fec1b29862..d0096489e2 100644 --- a/protocols/WhatsApp/src/WhatsAPI++/utilities.h +++ b/protocols/WhatsApp/src/WhatsAPI++/utilities.h @@ -49,9 +49,6 @@ std::string base64_encode(void*, size_t); void md5_string(const std::string& data, unsigned char digest[16]);
namespace Utilities{
- void configureLogging(const char* ident);
- void closeLog();
- string getCountryCode();
string getMcc();
string getMnc();
string reverseString(const string& str);
@@ -78,9 +75,5 @@ namespace Utilities{ std::vector<unsigned char>* getChallengeData(const std::string& file);
bool saveChallengeData(const std::vector<unsigned char>& data, const std::string& file);
std::string utf8_to_utf16(const std::string& utf8);
- std::string string_format(const std::string fmt, ...);
- std::string string_format(const std::string fmt, va_list ap);
- std::string string_format(const char* fmt, va_list ap);
}
#endif
-
|