// SoftEther VPN Source Code - Stable Edition Repository // Mayaqua Kernel // // SoftEther VPN Server, Client and Bridge are free software under GPLv2. // // Copyright (c) Daiyuu Nobori. // Copyright (c) SoftEther VPN Project, University of Tsukuba, Japan. // Copyright (c) SoftEther Corporation. // // All Rights Reserved. // // http://www.softether.org/ // // Author: Daiyuu Nobori, Ph.D. // Comments: Tetsuo Sugiyama, Ph.D. // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License // version 2 as published by the Free Software Foundation. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License version 2 // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // // THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE // AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE. // // // THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN, // UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY, // MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS // SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS // SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER // CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL // DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING, // MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR // SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND // CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO // EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO, // JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION // AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN // THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE. // // USE ONLY IN JAPAN. DO NOT USE THIS SOFTWARE IN ANOTHER COUNTRY UNLESS // YOU HAVE A CONFIRMATION THAT THIS SOFTWARE DOES NOT VIOLATE ANY // CRIMINAL LAWS OR CIVIL RIGHTS IN THAT PARTICULAR COUNTRY. USING THIS // SOFTWARE IN OTHER COUNTRIES IS COMPLETELY AT YOUR OWN RISK. THE // SOFTETHER VPN PROJECT HAS DEVELOPED AND DISTRIBUTED THIS SOFTWARE TO // COMPLY ONLY WITH THE JAPANESE LAWS AND EXISTING CIVIL RIGHTS INCLUDING // PATENTS WHICH ARE SUBJECTS APPLY IN JAPAN. OTHER COUNTRIES' LAWS OR // CIVIL RIGHTS ARE NONE OF OUR CONCERNS NOR RESPONSIBILITIES. WE HAVE // NEVER INVESTIGATED ANY CRIMINAL REGULATIONS, CIVIL LAWS OR // INTELLECTUAL PROPERTY RIGHTS INCLUDING PATENTS IN ANY OF OTHER 200+ // COUNTRIES AND TERRITORIES. BY NATURE, THERE ARE 200+ REGIONS IN THE // WORLD, WITH DIFFERENT LAWS. IT IS IMPOSSIBLE TO VERIFY EVERY // COUNTRIES' LAWS, REGULATIONS AND CIVIL RIGHTS TO MAKE THE SOFTWARE // COMPLY WITH ALL COUNTRIES' LAWS BY THE PROJECT. EVEN IF YOU WILL BE // SUED BY A PRIVATE ENTITY OR BE DAMAGED BY A PUBLIC SERVANT IN YOUR // COUNTRY, THE DEVELOPERS OF THIS SOFTWARE WILL NEVER BE LIABLE TO // RECOVER OR COMPENSATE SUCH DAMAGES, CRIMINAL OR CIVIL // RESPONSIBILITIES. NOTE THAT THIS LINE IS NOT LICENSE RESTRICTION BUT // JUST A STATEMENT FOR WARNING AND DISCLAIMER. // // // SOURCE CODE CONTRIBUTION // ------------------------ // // Your contribution to SoftEther VPN Project is much appreciated. // Please send patches to us through GitHub. // Read the SoftEther VPN Patch Acceptance Policy in advance: // http://www.softether.org/5-download/src/9.patch // // // DEAR SECURITY EXPERTS // --------------------- // // If you find a bug or a security vulnerability please kindly inform us // about the problem immediately so that we can fix the security problem // to protect a lot of users around the world as soon as possible. // // Our e-mail address for security reports is: // softether-vpn-security [at] softether.org // // Please note that the above e-mail address is not a technical support // inquiry address. If you need technical assistance, please visit // http://www.softether.org/ and ask your question on the users forum. // // Thank you for your cooperation. // // // NO MEMORY OR RESOURCE LEAKS // --------------------------- // // The memory-leaks and resource-leaks verification under the stress // test has been passed before release this source code. // Str.c // String processing routine #include #include #include #include #include #include #include #include #include // Locking for call the token handling function LOCK *token_lock = NULL; static char *default_spliter = " ,\t\r\n"; typedef struct BYTESTR { UINT64 base_value; char *string; } BYTESTR; static BYTESTR bytestr[] = { {0, "PBytes"}, {0, "TBytes"}, {0, "GBytes"}, {0, "MBytes"}, {0, "KBytes"}, {0, "Bytes"}, }; // Change the case of the string by the bit array void SetStrCaseAccordingToBits(char *str, UINT bits) { UINT i, len; // Validate arguments if (str == NULL) { return; } len = StrLen(str); for (i = 0;i < len;i++) { char c = str[i]; if (bits & 0x01) { c = ToUpper(c); } else { c = ToLower(c); } str[i] = c; bits = bits / 2; } } // Normalize the integer list string void NormalizeIntListStr(char *dst, UINT dst_size, char *src, bool sorted, char *separate_str) { LIST *o; o = StrToIntList(src, sorted); IntListToStr(dst, dst_size, o, separate_str); ReleaseIntList(o); } // Convert the string to an integer list LIST *StrToIntList(char *str, bool sorted) { LIST *o; TOKEN_LIST *t; o = NewIntList(sorted); t = ParseTokenWithoutNullStr(str, " ,/;\t"); if (t != NULL) { UINT i; for (i = 0;i < t->NumTokens;i++) { char *s = t->Token[i]; if (IsEmptyStr(s) == false) { if (IsNum(s)) { InsertIntDistinct(o, ToInt(s)); } } } FreeToken(t); } return o; } // Convert an integer list to a string void IntListToStr(char *str, UINT str_size, LIST *o, char *separate_str) { UINT i; ClearStr(str, str_size); // Validate arguments if (o == NULL) { return; } if (IsEmptyStr(separate_str)) { separate_str = ", "; } for (i = 0;i < LIST_NUM(o);i++) { char tmp[MAX_SIZE]; UINT *v = LIST_DATA(o, i); ToStr(tmp, *v); StrCat(str, str_size, tmp); if (i != (LIST_NUM(o) - 1)) { StrCat(str, str_size, separate_str); } } } // Initialize the string void ClearStr(char *str, UINT str_size) { StrCpy(str, str_size, ""); } // Search for the ASCII string in the binary data sequence UINT SearchAsciiInBinary(void *data, UINT size, char *str, bool case_sensitive) { UINT ret = INFINITE; char *tmp; // Validate arguments if (data == NULL || size == 0 || str == NULL) { return INFINITE; } tmp = ZeroMalloc(size + 1); Copy(tmp, data, size); ret = SearchStrEx(tmp, str, 0, case_sensitive); Free(tmp); return ret; } // Convert the HEX string to a 64 bit integer UINT64 HexToInt64(char *str) { UINT len, i; UINT64 ret = 0; // Validate arguments if (str == NULL) { return 0; } if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X')) { str += 2; } len = StrLen(str); for (i = 0;i < len;i++) { char c = str[i]; if ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F')) { ret = ret * 16ULL + (UINT64)HexTo4Bit(c); } else { break; } } return ret; } // Convert the HEX string to a 32 bit integer UINT HexToInt(char *str) { UINT len, i; UINT ret = 0; // Validate arguments if (str == NULL) { return 0; } if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X')) { str += 2; } len = StrLen(str); for (i = 0;i < len;i++) { char c = str[i]; if ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F')) { ret = ret * 16 + (UINT)HexTo4Bit(c); } else { break; } } return ret; } // Convert a 64 bit integer to a HEX void ToHex64(char *str, UINT64 value) { char tmp[MAX_SIZE]; UINT wp = 0; UINT len, i; // Validate arguments if (str == NULL) { return; } // Set to empty character StrCpy(tmp, 0, ""); // Append from the last digit while (true) { UINT a = (UINT)(value % (UINT64)16); value = value / (UINT)16; tmp[wp++] = FourBitToHex(a); if (value == 0) { tmp[wp++] = 0; break; } } // Reverse order len = StrLen(tmp); for (i = 0;i < len;i++) { str[len - i - 1] = tmp[i]; } str[len] = 0; } // Convert a 32 bit integer into HEX void ToHex(char *str, UINT value) { char tmp[MAX_SIZE]; UINT wp = 0; UINT len, i; // Validate arguments if (str == NULL) { return; } // Set to empty character StrCpy(tmp, 0, ""); // Append from the last digit while (true) { UINT a = (UINT)(value % (UINT)16); value = value / (UINT)16; tmp[wp++] = FourBitToHex(a); if (value == 0) { tmp[wp++] = 0; break; } } // Reverse order len = StrLen(tmp); for (i = 0;i < len;i++) { str[len - i - 1] = tmp[i]; } str[len] = 0; } // Converts a 4 bit value to hexadecimal string char FourBitToHex(UINT value) { value = value % 16; if (value <= 9) { return '0' + value; } else { return 'a' + (value - 10); } } // Convert a hexadecimal string to a 4 bit integer UINT HexTo4Bit(char c) { if ('0' <= c && c <= '9') { return c - '0'; } else if ('a' <= c && c <= 'f') { return c - 'a' + 10; } else if ('A' <= c && c <= 'F') { return c - 'A' + 10; } else { return 0; } } // Get a standard token delimiter char *DefaultTokenSplitChars() { return " ,\t\r\n"; } // Check whether the specified character is in the string bool IsCharInStr(char *str, char c) { UINT i, len; // Validate arguments if (str == NULL) { return false; } len = StrLen(str); for (i = 0;i < len;i++) { if (str[i] == c) { return true; } } return false; } // Cut out the token from the string (not ignore the blanks between delimiters) TOKEN_LIST *ParseTokenWithNullStr(char *str, char *split_chars) { LIST *o; UINT i, len; BUF *b; char zero = 0; TOKEN_LIST *t; // Validate arguments if (str == NULL) { return NullToken(); } if (split_chars == NULL) { split_chars = DefaultTokenSplitChars(); } b = NewBuf(); o = NewListFast(NULL); len = StrLen(str); for (i = 0;i < (len + 1);i++) { char c = str[i]; bool flag = IsCharInStr(split_chars, c); if (c == '\0') { flag = true; } if (flag == false) { WriteBuf(b, &c, sizeof(char)); } else { WriteBuf(b, &zero, sizeof(char)); Insert(o, CopyStr((char *)b->Buf)); ClearBuf(b); } } t = ZeroMalloc(sizeof(TOKEN_LIST)); t->NumTokens = LIST_NUM(o); t->Token = ZeroMalloc(sizeof(char *) * t->NumTokens); for (i = 0;i < t->NumTokens;i++) { t->Token[i] = LIST_DATA(o, i); } ReleaseList(o); FreeBuf(b); return t; } // Check whether the string contains at least one of the specified tokens bool InStrList(char *target_str, char *tokens, char *splitter, bool case_sensitive) { TOKEN_LIST *t; bool ret = false; UINT i; // Validate arguments if (target_str == NULL || tokens == NULL || splitter == NULL) { return false; } t = ParseTokenWithoutNullStr(tokens, splitter); if (t != NULL) { for (i = 0;i < t->NumTokens;i++) { if (InStrEx(target_str, t->Token[i], case_sensitive)) { ret = true; // printf("%s\n", t->Token[i]); } if (ret) { break; } } FreeToken(t); } return ret; } // Confirm whether the specified string is in the token list bool IsStrInStrTokenList(char *str_list, char *str, char *split_chars, bool case_sensitive) { TOKEN_LIST *t; bool ret = false; UINT i; // Validate arguments if (str_list == NULL || str == NULL) { return false; } t = ParseTokenWithoutNullStr(str_list, split_chars); if (t != NULL) { for (i = 0;i < t->NumTokens;i++) { if ((case_sensitive == false) && (StrCmpi(t->Token[i], str) == 0)) { ret = true; } if ((case_sensitive) && (StrCmp(t->Token[i], str) == 0)) { ret = true; } if (ret) { break; } } FreeToken(t); } return ret; } // Cut out the token from string (Ignore blanks between delimiters) TOKEN_LIST *ParseTokenWithoutNullStr(char *str, char *split_chars) { LIST *o; UINT i, len; bool last_flag; BUF *b; char zero = 0; TOKEN_LIST *t; // Validate arguments if (str == NULL) { return NullToken(); } if (split_chars == NULL) { split_chars = DefaultTokenSplitChars(); } b = NewBuf(); o = NewListFast(NULL); len = StrLen(str); last_flag = false; for (i = 0;i < (len + 1);i++) { char c = str[i]; bool flag = IsCharInStr(split_chars, c); if (c == '\0') { flag = true; } if (flag == false) { WriteBuf(b, &c, sizeof(char)); } else { if (last_flag == false) { WriteBuf(b, &zero, sizeof(char)); if ((StrLen((char *)b->Buf)) != 0) { Insert(o, CopyStr((char *)b->Buf)); } ClearBuf(b); } } last_flag = flag; } t = ZeroMalloc(sizeof(TOKEN_LIST)); t->NumTokens = LIST_NUM(o); t->Token = ZeroMalloc(sizeof(char *) * t->NumTokens); for (i = 0;i < t->NumTokens;i++) { t->Token[i] = LIST_DATA(o, i); } ReleaseList(o); FreeBuf(b); return t; } // Check whether the string is included bool InStr(char *str, char *keyword) { return InStrEx(str, keyword, false); } bool InStrEx(char *str, char *keyword, bool case_sensitive) { // Validate arguments if (IsEmptyStr(str) || IsEmptyStr(keyword)) { return false; } if (SearchStrEx(str, keyword, 0, case_sensitive) == INFINITE) { return false; } return true; } // Get a value from the INI UINT IniIntValue(LIST *o, char *key) { INI_ENTRY *e; // Validate arguments if (o == NULL || key == NULL) { return 0; } e = GetIniEntry(o, key); if (e == NULL) { return 0; } return ToInt(e->Value); } UINT64 IniInt64Value(LIST *o, char *key) { INI_ENTRY *e; // Validate arguments if (o == NULL || key == NULL) { return 0; } e = GetIniEntry(o, key); if (e == NULL) { return 0; } return ToInt64(e->Value); } char *IniStrValue(LIST *o, char *key) { INI_ENTRY *e; // Validate arguments if (o == NULL || key == NULL) { return 0; } e = GetIniEntry(o, key); if (e == NULL) { return ""; } return e->Value; } wchar_t *IniUniStrValue(LIST *o, char *key) { INI_ENTRY *e; // Validate arguments if (o == NULL || key == NULL) { return 0; } e = GetIniEntry(o, key); if (e == NULL) { return L""; } return e->UnicodeValue; } // Check whether the specified value is in the INI bool IniHasValue(LIST *o, char *key) { INI_ENTRY *e; // Validate arguments if (o == NULL || key == NULL) { return false; } e = GetIniEntry(o, key); if (e == NULL) { return false; } return true; } // Release the INI void FreeIni(LIST *o) { UINT i; // Validate arguments if (o == NULL) { return; } for (i = 0;i < LIST_NUM(o);i++) { INI_ENTRY *e = LIST_DATA(o, i); Free(e->Key); Free(e->Value); Free(e->UnicodeValue); Free(e); } ReleaseList(o); } // Get an entry in the INI file INI_ENTRY *GetIniEntry(LIST *o, char *key) { UINT i; // Validate arguments if (o == NULL || key == NULL) { return NULL; } for (i = 0;i < LIST_NUM(o);i++) { INI_ENTRY *e = LIST_DATA(o, i); if (StrCmpi(e->Key, key) == 0) { return e; } } return NULL; } // Read an INI file LIST *ReadIni(BUF *b) { LIST *o; // Validate arguments if (b == NULL) { return NULL; } o = NewListFast(NULL); SeekBuf(b, 0, 0); while (true) { char *line = CfgReadNextLine(b); if (line == NULL) { break; } Trim(line); if (IsEmptyStr(line) == false) { if (StartWith(line, "#") == false && StartWith(line, "//") == false && StartWith(line, ";") == false) { char *key, *value; UINT size = StrLen(line) + 1; key = ZeroMalloc(size); value = ZeroMalloc(size); if (GetKeyAndValue(line, key, size, value, size, NULL)) { UINT uni_size; INI_ENTRY *e = ZeroMalloc(sizeof(INI_ENTRY)); e->Key = CopyStr(key); e->Value = CopyStr(value); uni_size = CalcUtf8ToUni((BYTE *)value, StrLen(value)); e->UnicodeValue = ZeroMalloc(uni_size); Utf8ToUni(e->UnicodeValue, uni_size, (BYTE *)value, StrLen(value)); Add(o, e); } Free(key); Free(value); } } Free(line); } return o; } // Check whether the specified character is a delimiter bool IsSplitChar(char c, char *split_str) { UINT i, len; char c_upper = ToUpper(c); if (split_str == NULL) { split_str = default_spliter; } len = StrLen(split_str); for (i = 0;i < len;i++) { if (ToUpper(split_str[i]) == c_upper) { return true; } } return false; } // Get the keys and the value from the string bool GetKeyAndValue(char *str, char *key, UINT key_size, char *value, UINT value_size, char *split_str) { UINT mode = 0; UINT wp1 = 0, wp2 = 0; UINT i, len; char *key_tmp, *value_tmp; bool ret = false; if (split_str == NULL) { split_str = default_spliter; } len = StrLen(str); key_tmp = ZeroMalloc(len + 1); value_tmp = ZeroMalloc(len + 1); for (i = 0;i < len;i++) { char c = str[i]; switch (mode) { case 0: if (IsSplitChar(c, split_str) == false) { mode = 1; key_tmp[wp1] = c; wp1++; } break; case 1: if (IsSplitChar(c, split_str) == false) { key_tmp[wp1] = c; wp1++; } else { mode = 2; } break; case 2: if (IsSplitChar(c, split_str) == false) { mode = 3; value_tmp[wp2] = c; wp2++; } break; case 3: value_tmp[wp2] = c; wp2++; break; } } if (mode != 0) { ret = true; StrCpy(key, key_size, key_tmp); StrCpy(value, value_size, value_tmp); } Free(key_tmp); Free(value_tmp); return ret; } // Generate a sequence of specified character char *MakeCharArray(char c, UINT count) { UINT i; char *ret = Malloc(count + 1); for (i = 0;i < count;i++) { ret[i] = c; } ret[count] = 0; return ret; } void MakeCharArray2(char *str, char c, UINT count) { UINT i; for (i = 0;i < count;i++) { str[i] = c; } str[count] = 0; } // Get the width of the specified string UINT StrWidth(char *str) { wchar_t *s; UINT ret; // Validate arguments if (str == NULL) { return 0; } s = CopyStrToUni(str); ret = UniStrWidth(s); Free(s); return ret; } // Check whether the specified string is all uppercase bool IsAllUpperStr(char *str) { UINT i, len; // Validate arguments if (str == NULL) { return false; } len = StrLen(str); for (i = 0;i < len;i++) { char c = str[i]; if ((c >= '0' && c <= '9') || (c >= 'A' && c <= 'Z')) { } else { return false; } } return true; } // Normalize the line breaks char *NormalizeCrlf(char *str) { char *ret; UINT ret_size, i, len, wp; // Validate arguments if (str == NULL) { return NULL; } len = StrLen(str); ret_size = sizeof(char) * (len + 32) * 2; ret = Malloc(ret_size); wp = 0; for (i = 0;i < len;i++) { char c = str[i]; switch (c) { case '\r': if (str[i + 1] == '\n') { i++; } ret[wp++] = '\r'; ret[wp++] = '\n'; break; case '\n': ret[wp++] = '\r'; ret[wp++] = '\n'; break; default: ret[wp++] = c; break; } } ret[wp++] = 0; return ret; } // Remove duplications from the token list TOKEN_LIST *UniqueToken(TOKEN_LIST *t) { UINT i, num, j, n; TOKEN_LIST *ret; // Validate arguments if (t == NULL) { return NULL; } num = 0; for (i = 0;i < t->NumTokens;i++) { bool exists = false; for (j = 0;j < i;j++) { if (StrCmpi(t->Token[j], t->Token[i]) == 0) { exists = true; break; } } if (exists == false) { num++; } } ret = ZeroMalloc(sizeof(TOKEN_LIST)); ret->Token = ZeroMalloc(sizeof(char *) * num); ret->NumTokens = num; n = 0; for (i = 0;i < t->NumTokens;i++) { bool exists = false; for (j = 0;j < i;j++) { if (StrCmpi(t->Token[j], t->Token[i]) == 0) { exists = true; break; } } if (exists == false) { ret->Token[n++] = CopyStr(t->Token[i]); } } return ret; } // Convert a value to a byte string (by 1,000) void ToStrByte1000(char *str, UINT size, UINT64 v) { UINT i; // Validate arguments if (str == NULL) { return; } // Warning measures in gcc bytestr[0].base_value = 1000000000UL; bytestr[0].base_value *= 1000UL; bytestr[0].base_value *= 1000UL; bytestr[1].base_value = 1000000000UL; bytestr[1].base_value *= 1000UL; bytestr[2].base_value = 1000000000UL; bytestr[3].base_value = 1000000UL; bytestr[4].base_value = 1000UL; bytestr[5].base_value = 0UL; for (i = 0;i < sizeof(bytestr) / sizeof(bytestr[0]);i++) { BYTESTR *b = &bytestr[i]; if ((v * 11UL) / 10UL >= b->base_value) { if (b->base_value != 0) { double d = (double)v / (double)b->base_value; Format(str, size, "%.2f %s", d, b->string); } else { Format(str, size, "%I64u %s", v, b->string); } break; } } } // Convert a value to a byte string void ToStrByte(char *str, UINT size, UINT64 v) { UINT i; // Validate arguments if (str == NULL) { return; } // Warning measures in gcc bytestr[0].base_value = 1073741824UL; bytestr[0].base_value *= 1024UL; bytestr[0].base_value *= 1024UL; bytestr[1].base_value = 1073741824UL; bytestr[1].base_value *= 1024UL; bytestr[2].base_value = 1073741824UL; bytestr[3].base_value = 1048576UL; bytestr[4].base_value = 1024UL; bytestr[5].base_value = 0UL; for (i = 0;i < sizeof(bytestr) / sizeof(bytestr[0]);i++) { BYTESTR *b = &bytestr[i]; if ((v * 11UL) / 10UL >= b->base_value) { if (b->base_value != 0) { double d = (double)v / (double)b->base_value; Format(str, size, "%.2f %s", d, b->string); } else { Format(str, size, "%I64u %s", v, b->string); } break; } } } // Convert the number to a string, and separate it with commas by three orders of magnitude void ToStr3(char *str, UINT size, UINT64 v) { char tmp[128]; char tmp2[128]; UINT i, len, wp; // Validate arguments if (str == NULL) { return; } ToStr64(tmp, v); wp = 0; len = StrLen(tmp); for (i = len - 1;((int)i) >= 0;i--) { tmp2[wp++] = tmp[i]; } tmp2[wp++] = 0; wp = 0; for (i = 0;i < len;i++) { if (i != 0 && (i % 3) == 0) { tmp[wp++] = ','; } tmp[wp++] = tmp2[i]; } tmp[wp++] = 0; wp = 0; len = StrLen(tmp); for (i = len - 1;((int)i) >= 0;i--) { tmp2[wp++] = tmp[i]; } tmp2[wp++] = 0; StrCpy(str, size, tmp2); } // Convert the MAC address to a string void MacToStr(char *str, UINT size, UCHAR *mac_address) { // Validate arguments if (str == NULL || mac_address == NULL) { return; } Format(str, size, "%02X-%02X-%02X-%02X-%02X-%02X", mac_address[0], mac_address[1], mac_address[2], mac_address[3], mac_address[4], mac_address[5]); } // Examine whether the string is empty bool IsEmptyStr(char *str) { char *s; // Validate arguments if (str == NULL) { return true; } s = CopyStr(str); Trim(s); if (StrLen(s) == 0) { Free(s); return true; } else { Free(s); return false; } } // Convert the token list to a string list LIST *TokenListToList(TOKEN_LIST *t) { UINT i; LIST *o; // Validate arguments if (t == NULL) { return NULL; } o = NewListFast(NULL); for (i = 0;i < t->NumTokens;i++) { Insert(o, CopyStr(t->Token[i])); } return o; } // Convert a string list to a token list TOKEN_LIST *ListToTokenList(LIST *o) { UINT i; TOKEN_LIST *t; // Validate arguments if (o == NULL) { return NULL; } t = ZeroMalloc(sizeof(TOKEN_LIST)); t->NumTokens = LIST_NUM(o); t->Token = ZeroMalloc(sizeof(char *) * t->NumTokens); for (i = 0;i < LIST_NUM(o);i++) { t->Token[i] = CopyStr(LIST_DATA(o, i)); } return t; } // Free the string list void FreeStrList(LIST *o) { UINT i; // Validate arguments if (o == NULL) { return; } for (i = 0;i < LIST_NUM(o);i++) { char *s = LIST_DATA(o, i); Free(s); } ReleaseList(o); } // Convert the string list to a string BUF *StrListToStr(LIST *o) { BUF *b; UINT i; char c; // Validate arguments if (o == NULL) { return NULL; } b = NewBuf(); for (i = 0;i < LIST_NUM(o);i++) { char *s = LIST_DATA(o, i); WriteBuf(b, s, StrLen(s) + 1); } c = 0; WriteBuf(b, &c, 1); SeekBuf(b, 0, 0); return b; } // Convert a (NULL delimited) string to a list LIST *StrToStrList(char *str, UINT size) { LIST *o; char *tmp; UINT tmp_size; UINT i; // Validate arguments if (str == NULL) { return NULL; } o = NewListFast(NULL); i = 0; while (true) { if (i >= size) { break; } if (*str == 0) { break; } tmp_size = StrSize(str); tmp = ZeroMalloc(tmp_size); StrCpy(tmp, tmp_size, str); Add(o, tmp); str += StrLen(str) + 1; i++; } return o; } // Check whether the specified string is a number bool IsNum(char *str) { char c; UINT i, len; UINT n = 0; char tmp[MAX_SIZE]; TOKEN_LIST *t; // Validate arguments if (str == NULL) { return false; } StrCpy(tmp, sizeof(tmp), str); Trim(tmp); if (StrLen(tmp) == 0) { return false; } t = ParseToken(tmp, " "); if (t->NumTokens >= 1) { StrCpy(tmp, sizeof(tmp), t->Token[0]); } FreeToken(t); len = StrLen(tmp); for (i = 0;i < len;i++) { bool b = false; c = tmp[i]; if (('0' <= c && c <= '9') || (c == '+') || (c == '-') || (c == ',')) { b = true; } if (b == false) { return false; } } for (i = 0;i < len;i++) { c = tmp[i]; if (c == '-') { n++; } } if (n >= 2) { return false; } return true; } // Empty token list TOKEN_LIST *NullToken() { TOKEN_LIST *ret = ZeroMalloc(sizeof(TOKEN_LIST)); ret->Token = ZeroMalloc(0); return ret; } // Copy the token list TOKEN_LIST *CopyToken(TOKEN_LIST *src) { TOKEN_LIST *ret; UINT i; // Validate arguments if (src == NULL) { return NULL; } ret = ZeroMalloc(sizeof(TOKEN_LIST)); ret->NumTokens = src->NumTokens; ret->Token = ZeroMalloc(sizeof(char *) * ret->NumTokens); for (i = 0;i < ret->NumTokens;i++) { ret->Token[i] = CopyStr(src->Token[i]); } return ret; } // Parse the command line TOKEN_LIST *ParseCmdLine(char *str) { TOKEN_LIST *t; LIST *o; UINT i, len, wp, mode; char c; char *tmp; bool ignore_space = false; // Validate arguments if (str == NULL) { // There is no token return NullToken(); } o = NewListFast(NULL); tmp = Malloc(StrSize(str) + 32); wp = 0; mode = 0; len = StrLen(str); for (i = 0;i < len;i++) { c = str[i]; switch (mode) { case 0: // Mode to discover the next token if (c == ' ' || c == '\t') { // Advance to the next character } else { // Start of the token if (c == '\"') { if (str[i + 1] == '\"') { // Regard "" as a single " tmp[wp++] = '\"'; i++; } else { // Enable the ignoring space flag for a single " ignore_space = true; } } else { tmp[wp++] = c; } mode = 1; } break; case 1: if (ignore_space == false && (c == ' ' || c == '\t')) { // End of the token tmp[wp++] = 0; wp = 0; Insert(o, CopyStr(tmp)); mode = 0; } else { if (c == '\"') { if (str[i + 1] == '\"') { // Regard "" as a single " tmp[wp++] = L'\"'; i++; } else { if (ignore_space == false) { // Enable the ignoring space flag for a single " ignore_space = true; } else { // Disable the space ignore flag ignore_space = false; } } } else { tmp[wp++] = c; } } break; } } if (wp != 0) { tmp[wp++] = 0; Insert(o, CopyStr(tmp)); } Free(tmp); t = ZeroMalloc(sizeof(TOKEN_LIST)); t->NumTokens = LIST_NUM(o); t->Token = ZeroMalloc(sizeof(char *) * t->NumTokens); for (i = 0;i < t->NumTokens;i++) { t->Token[i] = LIST_DATA(o, i); } ReleaseList(o); return t; } // Convert a 64-bit integer to a string void ToStr64(char *str, UINT64 value) { char tmp[MAX_SIZE]; UINT wp = 0; UINT len, i; // Validate arguments if (str == NULL) { return; } // Set to empty character StrCpy(tmp, 0, ""); // Append from the last digit while (true) { UINT a = (UINT)(value % (UINT64)10); value = value / (UINT64)10; tmp[wp++] = (char)('0' + a); if (value == 0) { tmp[wp++] = 0; break; } } // Reverse order len = StrLen(tmp); for (i = 0;i < len;i++) { str[len - i - 1] = tmp[i]; } str[len] = 0; } // Convert a string to a 64-bit integer UINT64 ToInt64(char *str) { UINT len, i; UINT64 ret = 0; // Validate arguments if (str == NULL) { return 0; } len = StrLen(str); for (i = 0;i < len;i++) { char c = str[i]; if (c != ',') { if ('0' <= c && c <= '9') { ret = ret * (UINT64)10 + (UINT64)(c - '0'); } else { break; } } } return ret; } // Check whether the str ends with the key bool EndWith(char *str, char *key) { UINT str_len; UINT key_len; // Validate arguments if (str == NULL || key == NULL) { return false; } // Comparison str_len = StrLen(str); key_len = StrLen(key); if (str_len < key_len) { return false; } if (StrCmpi(str + (str_len - key_len), key) == 0) { return true; } else { return false; } } // Check whether the str starts with the key bool StartWith(char *str, char *key) { UINT str_len; UINT key_len; char *tmp; bool ret; // Validate arguments if (str == NULL || key == NULL) { return false; } // Comparison str_len = StrLen(str); key_len = StrLen(key); if (str_len < key_len) { return false; } if (str_len == 0 || key_len == 0) { return false; } tmp = CopyStr(str); tmp[key_len] = 0; if (StrCmpi(tmp, key) == 0) { ret = true; } else { ret = false; } Free(tmp); return ret; } // Display the binary data void PrintBin(void *data, UINT size) { char *tmp; UINT i; // Validate arguments if (data == NULL) { return; } i = size * 3 + 1; tmp = Malloc(i); BinToStrEx(tmp, i, data, size); Print("%s\n", tmp); Free(tmp); } // Convert the string to a MAC address bool StrToMac(UCHAR *mac_address, char *str) { BUF *b; // Validate arguments if (mac_address == NULL || str == NULL) { return false; } b = StrToBin(str); if (b == NULL) { return false; } if (b->Size != 6) { FreeBuf(b); return false; } Copy(mac_address, b->Buf, 6); FreeBuf(b); return true; } // Convert a hexadecimal string to a binary data BUF *StrToBin(char *str) { BUF *b; UINT len, i; char tmp[3]; // Validate arguments if (str == NULL) { return NULL; } len = StrLen(str); tmp[0] = 0; b = NewBuf(); for (i = 0;i < len;i++) { char c = str[i]; c = ToUpper(c); if (('0' <= c && c <= '9') || ('A' <= c && c <= 'F')) { if (tmp[0] == 0) { tmp[0] = c; tmp[1] = 0; } else if (tmp[1] == 0) { UCHAR data; char tmp2[64]; tmp[1] = c; tmp[2] = 0; StrCpy(tmp2, sizeof(tmp2), "0x"); StrCat(tmp2, sizeof(tmp2), tmp); data = (UCHAR)strtoul(tmp2, NULL, 0); WriteBuf(b, &data, 1); Zero(tmp, sizeof(tmp)); } } else if (c == ' ' || c == ',' || c == '-' || c == ':') { // Do Nothing } else { break; } } return b; } // Convert the binary data to a hexadecimal string (with space) void BinToStrEx(char *str, UINT str_size, void *data, UINT data_size) { char *tmp; UCHAR *buf = (UCHAR *)data; UINT size; UINT i; // Validate arguments if (str == NULL || data == NULL) { return; } // Calculation of size size = data_size * 3 + 1; // Memory allocation tmp = ZeroMalloc(size); // Conversion for (i = 0;i < data_size;i++) { Format(&tmp[i * 3], 0, "%02X ", buf[i]); } Trim(tmp); // Copy StrCpy(str, str_size, tmp); // Memory release Free(tmp); } void BinToStrEx2(char *str, UINT str_size, void *data, UINT data_size, char padding_char) { char *tmp; UCHAR *buf = (UCHAR *)data; UINT size; UINT i; // Validate arguments if (str == NULL || data == NULL) { return; } // Calculation of size size = data_size * 3 + 1; // Memory allocation tmp = ZeroMalloc(size); // Conversion for (i = 0;i < data_size;i++) { Format(&tmp[i * 3], 0, "%02X%c", buf[i], padding_char); } if (StrLen(tmp) >= 1) { if (tmp[StrLen(tmp) - 1] == padding_char) { tmp[StrLen(tmp) - 1] = 0; } } // Copy StrCpy(str, str_size, tmp); // Memory release Free(tmp); } // Convert the binary data to a string, and copy it char *CopyBinToStrEx(void *data, UINT data_size) { char *ret; UINT size; // Validate arguments if (data == NULL) { return NULL; } size = data_size * 3 + 1; ret = ZeroMalloc(size); BinToStrEx(ret, size, data, data_size); return ret; } char *CopyBinToStr(void *data, UINT data_size) { char *ret; UINT size; // Validate arguments if (data == NULL) { return NULL; } size = data_size * 2 + 1; ret = ZeroMalloc(size); BinToStr(ret, size, data, data_size); return ret; } // Convert the binary data to a hexadecimal string void BinToStr(char *str, UINT str_size, void *data, UINT data_size) { char *tmp; UCHAR *buf = (UCHAR *)data; UINT size; UINT i; // Validate arguments if (str == NULL || data == NULL) { if (str != NULL) { str[0] = 0; } return; } // Calculation of size size = data_size * 2 + 1; // Memory allocation tmp = ZeroMalloc(size); // Conversion for (i = 0;i < data_size;i++) { sprintf(&tmp[i * 2], "%02X", buf[i]); } // Copy StrCpy(str, str_size, tmp); // Memory release Free(tmp); } void BinToStrW(wchar_t *str, UINT str_size, void *data, UINT data_size) { char *tmp; UINT tmp_size; // Validate arguments if (str == NULL || data == NULL) { if (str != NULL) { str[0] = 0; } return; } tmp_size = (data_size * 2 + 4) * sizeof(wchar_t); tmp = ZeroMalloc(tmp_size); BinToStr(tmp, tmp_size, data, data_size); StrToUni(str, str_size, tmp); Free(tmp); } // Convert a 160-bit sequence into a string void Bit160ToStr(char *str, UCHAR *data) { // Validate arguments if (str == NULL || data == NULL) { return; } Format(str, 0, "%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X", data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7], data[8], data[9], data[10], data[11], data[12], data[13], data[14], data[15], data[16], data[17], data[18], data[19]); } // Make a string from a 128-bit sequence void Bit128ToStr(char *str, UCHAR *data) { // Validate arguments if (str == NULL || data == NULL) { return; } Format(str, 0, "%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X", data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7], data[8], data[9], data[10], data[11], data[12], data[13], data[14], data[15]); } // Copy a string char *CopyStr(char *str) { UINT len; char *dst; // Validate arguments if (str == NULL) { return NULL; } len = StrLen(str); dst = Malloc(len + 1); StrCpy(dst, len + 1, str); return dst; } // Check whether the string is safe bool IsSafeStr(char *str) { UINT i, len; // Validate arguments if (str == NULL) { return false; } len = StrLen(str); for (i = 0;i < len;i++) { if (IsSafeChar(str[i]) == false) { return false; } } if (str[0] == ' ') { return false; } if (len != 0) { if (str[len - 1] == ' ') { return false; } } return true; } // Check whether the character can be displayed bool IsPrintableAsciiChar(char c) { UCHAR uc = (UCHAR)c; if (uc <= 31) { return false; } if (uc >= 127) { return false; } return true; } // Check whether the string that can be displayed bool IsPrintableAsciiStr(char *str) { UINT i, len; // Validate arguments if (str == NULL) { return false; } len = StrLen(str); for (i = 0;i < len;i++) { char c = str[i]; if (IsPrintableAsciiChar(c) == false) { return false; } } return true; } // Convert a string to a displayable string void EnPrintableAsciiStr(char *str, char replace) { UINT i, len; // Validate arguments if (str == NULL) { return; } len = StrLen(str); for (i = 0;i < len;i++) { char c = str[i]; if (IsPrintableAsciiChar(c) == false) { str[i] = replace; } } } // Check whether the character is safe bool IsSafeChar(char c) { UINT i, len; char *check_str = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "abcdefghijklmnopqrstuvwxyz" "0123456789" " ()-_#%&."; len = StrLen(check_str); for (i = 0;i < len;i++) { if (c == check_str[i]) { return true; } } return false; } // Remove the specified character from a string void TruncateCharFromStr(char *str, char replace) { char *src,*dst; if (str == NULL) { return; } src = dst = str; while(*src != '\0') { if(*src != replace) { *dst = *src; dst++; } src++; } *dst = *src; //BUF *b = NewBuf(); //UINT i, len; //char zero = 0; //len = StrLen(str); //for (i = 0;i < len;i++) //{ // char c = str[i]; // if (c != replace) // { // WriteBuf(b, &c, 1); // } //} //if (b->Size == 0) //{ // char c = '_'; // WriteBuf(b, &c, 1); //} //WriteBuf(b, &zero, 1); //StrCpy(str, 0, b->Buf); //FreeBuf(b); } // Replace the unsafe characters void EnSafeStr(char *str, char replace) { if (str == NULL) { return; } while(*str != '\0') { if(IsSafeChar(*str) == false) { *str = replace; } str++; } } // Operation check of string library bool CheckStringLibrary() { wchar_t *compare_str = L"TEST_TEST_123_123456789012345"; char *teststr = "TEST"; wchar_t *testunistr = L"TEST"; wchar_t tmp[64]; UINT i1 = 123; UINT64 i2 = 123456789012345ULL; UniFormat(tmp, sizeof(tmp), L"%S_%s_%u_%I64u", teststr, testunistr, i1, i2); if (UniStrCmpi(tmp, compare_str) != 0) { return false; } return true; } // Initialize the string library void InitStringLibrary() { // Create a lock for token token_lock = NewLock(); // Initialization of the International Library InitInternational(); // Operation check if (CheckStringLibrary() == false) { #ifdef OS_WIN32 Alert("String Library Init Failed.\r\nPlease check your locale settings.", NULL); #else // OS_WIN32 Alert("String Library Init Failed.\r\nPlease check your locale settings and iconv() libraries.", NULL); #endif // OS_WIN32 exit(0); } } // Release of the string library void FreeStringLibrary() { // Release of the International Library FreeInternational(); // Release of the lock for token DeleteLock(token_lock); token_lock = NULL; } // String replaceing (case insensitive) UINT ReplaceStri(char *dst, UINT size, char *string, char *old_keyword, char *new_keyword) { return ReplaceStrEx(dst, size, string, old_keyword, new_keyword, false); } // String replaceing (case sensitive) UINT ReplaceStr(char *dst, UINT size, char *string, char *old_keyword, char *new_keyword) { return ReplaceStrEx(dst, size, string, old_keyword, new_keyword, true); } // String replaceing UINT ReplaceStrEx(char *dst, UINT size, char *string, char *old_keyword, char *new_keyword, bool case_sensitive) { UINT i, j, num; UINT len_string, len_old, len_new; UINT len_ret; UINT wp; char *ret; // Validate arguments if (string == NULL || old_keyword == NULL || new_keyword == NULL) { return 0; } // Get the length of the string len_string = StrLen(string); len_old = StrLen(old_keyword); len_new = StrLen(new_keyword); // Calculate the final string length len_ret = CalcReplaceStrEx(string, old_keyword, new_keyword, case_sensitive); // Memory allocation ret = Malloc(len_ret + 1); ret[len_ret] = '\0'; // Search and Replace i = 0; j = 0; num = 0; wp = 0; while (true) { i = SearchStrEx(string, old_keyword, i, case_sensitive); if (i == INFINITE) { Copy(ret + wp, string + j, len_string - j); wp += len_string - j; break; } num++; Copy(ret + wp, string + j, i - j); wp += i - j; Copy(ret + wp, new_keyword, len_new); wp += len_new; i += len_old; j = i; } // Copy of the search results StrCpy(dst, size, ret); // Memory release Free(ret); return num; } // Calculate the length of the result of string replacement UINT CalcReplaceStrEx(char *string, char *old_keyword, char *new_keyword, bool case_sensitive) { UINT i, num; UINT len_string, len_old, len_new; // Validate arguments if (string == NULL || old_keyword == NULL || new_keyword == NULL) { return 0; } // Get the length of the string len_string = StrLen(string); len_old = StrLen(old_keyword); len_new = StrLen(new_keyword); if (len_old == len_new) { return len_string; } // Search num = 0; i = 0; while (true) { i = SearchStrEx(string, old_keyword, i, case_sensitive); if (i == INFINITE) { break; } i += len_old; num++; } // Calculation return len_string + len_new * num - len_old * num; } // Search for a string (distinguish between upper / lower case) UINT SearchStr(char *string, char *keyword, UINT start) { return SearchStrEx(string, keyword, start, true); } // Search for a string (Don't distinguish between upper / lower case) UINT SearchStri(char *string, char *keyword, UINT start) { return SearchStrEx(string, keyword, start, false); } // Examine whether the string contains the specified character bool InChar(char *string, char c) { UINT i, len; // Validate arguments if (string == NULL) { return false; } len = StrLen(string); for (i = 0;i < len;i++) { if (string[i] == c) { return true; } } return false; } // Return the position of the first found keyword in the string // (Found at first character: returns 0, Not found: returns INFINITE) UINT SearchStrEx(char *string, char *keyword, UINT start, bool case_sensitive) { UINT len_string, len_keyword; UINT i; char *cmp_string, *cmp_keyword; bool found; // Validate arguments if (string == NULL || keyword == NULL) { return INFINITE; } // Get the length of string len_string = StrLen(string); if (len_string <= start) { // Value of start is invalid return INFINITE; } // Get the length of the keyword len_keyword = StrLen(keyword); if (len_keyword == 0) { // There is no keyword in the string return INFINITE; } if ((len_string - start) < len_keyword) { // The keyword is longer than the string return INFINITE; } if (case_sensitive) { cmp_string = string; cmp_keyword = keyword; } else { cmp_string = Malloc(len_string + 1); StrCpy(cmp_string, len_string + 1, string); cmp_keyword = Malloc(len_keyword + 1); StrCpy(cmp_keyword, len_keyword + 1, keyword); StrUpper(cmp_string); StrUpper(cmp_keyword); } // Search found = false; for (i = start;i < (len_string - len_keyword + 1);i++) { // Compare if (!strncmp(&cmp_string[i], cmp_keyword, len_keyword)) { // Found found = true; break; } } if (case_sensitive == false) { // Memory release Free(cmp_keyword); Free(cmp_string); } if (found == false) { return INFINITE; } return i; } // Determine whether the specified character is in the token list bool IsInToken(TOKEN_LIST *t, char *str) { UINT i; // Validate arguments if (t == NULL || str == NULL) { return false; } for (i = 0;i < t->NumTokens;i++) { if (StrCmpi(t->Token[i], str) == 0) { return true; } } return false; } // Release of the token list void FreeToken(TOKEN_LIST *tokens) { UINT i; if (tokens == NULL) { return; } for (i = 0;i < tokens->NumTokens;i++) { if (tokens->Token[i] != 0) { Free(tokens->Token[i]); } } Free(tokens->Token); Free(tokens); } // Parse the token TOKEN_LIST *ParseToken(char *src, char *separator) { TOKEN_LIST *ret; char *tmp; char *str1, *str2; UINT len; UINT num; if (src == NULL) { ret = ZeroMalloc(sizeof(TOKEN_LIST)); ret->Token = ZeroMalloc(0); return ret; } if (separator == NULL) { separator = " ,\t\r\n"; } len = StrLen(src); str1 = Malloc(len + 1); str2 = Malloc(len + 1); StrCpy(str1, 0, src); StrCpy(str2, 0, src); Lock(token_lock); { tmp = strtok(str1, separator); num = 0; while (tmp != NULL) { num++; tmp = strtok(NULL, separator); } ret = Malloc(sizeof(TOKEN_LIST)); ret->NumTokens = num; ret->Token = (char **)Malloc(sizeof(char *) * num); num = 0; tmp = strtok(str2, separator); while (tmp != NULL) { ret->Token[num] = (char *)Malloc(StrLen(tmp) + 1); StrCpy(ret->Token[num], 0, tmp); num++; tmp = strtok(NULL, separator); } } Unlock(token_lock); Free(str1); Free(str2); return ret; } // Get a line from standard input bool GetLine(char *str, UINT size) { bool ret; wchar_t *unistr; UINT unistr_size = (size + 1) * sizeof(wchar_t); unistr = Malloc(unistr_size); ret = UniGetLine(unistr, unistr_size); UniToStr(str, size, unistr); Free(unistr); return ret; } // Remove '\r' and '\n' at the end void TrimCrlf(char *str) { UINT len; // Validate arguments if (str == NULL) { return; } len = StrLen(str); if (len == 0) { return; } if (str[len - 1] == '\n') { if (len >= 2 && str[len - 2] == '\r') { str[len - 2] = 0; } str[len - 1] = 0; } else if (str[len - 1] == '\r') { str[len - 1] = 0; } } // Remove white spaces of the both side of the string void Trim(char *str) { // Validate arguments if (str == NULL) { return; } // Trim on the left side TrimLeft(str); // Trim on the right side TrimRight(str); } // Remove white spaces on the right side of the string void TrimRight(char *str) { char *buf, *tmp; UINT len, i, wp, wp2; BOOL flag; // Validate arguments if (str == NULL) { return; } len = StrLen(str); if (len == 0) { return; } if (str[len - 1] != ' ' && str[len - 1] != '\t') { return; } buf = Malloc(len + 1); tmp = Malloc(len + 1); flag = FALSE; wp = 0; wp2 = 0; for (i = 0;i < len;i++) { if (str[i] != ' ' && str[i] != '\t') { Copy(buf + wp, tmp, wp2); wp += wp2; wp2 = 0; buf[wp++] = str[i]; } else { tmp[wp2++] = str[i]; } } buf[wp] = 0; StrCpy(str, 0, buf); Free(buf); Free(tmp); } // Remove white spaces from the left side of the string void TrimLeft(char *str) { char *buf; UINT len, i, wp; BOOL flag; // Validate arguments if (str == NULL) { return; } len = StrLen(str); if (len == 0) { return; } if (str[0] != ' ' && str[0] != '\t') { return; } buf = Malloc(len + 1); flag = FALSE; wp = 0; for (i = 0;i < len;i++) { if (str[i] != ' ' && str[i] != '\t') { flag = TRUE; } if (flag) { buf[wp++] = str[i]; } } buf[wp] = 0; StrCpy(str, 0, buf); Free(buf); } // Convert an integer to a hexadecimal string (8-digit fixed) void ToStrx8(char *str, UINT i) { sprintf(str, "0x%08x", i); } // Convert an integer to a hexadecimal string void ToStrx(char *str, UINT i) { sprintf(str, "0x%02x", i); } // Convert a signed integer to a string void ToStri(char *str, int i) { sprintf(str, "%i", i); } // Convert an integer to a string void ToStr(char *str, UINT i) { sprintf(str, "%u", i); } // Convert the string to a signed integer int ToInti(char *str) { // Validate arguments if (str == NULL) { return 0; } return (int)ToInt(str); } // Convert a string to a Boolean value bool ToBool(char *str) { char tmp[MAX_SIZE]; // Validate arguments if (str == NULL) { return false; } StrCpy(tmp, sizeof(tmp), str); Trim(tmp); if (IsEmptyStr(tmp)) { return false; } if (ToInt(tmp) != 0) { return true; } if (StartWith("true", tmp)) { return true; } if (StartWith("yes", tmp)) { return true; } if (StartWith(tmp, "true")) { return true; } if (StartWith(tmp, "yes")) { return true; } return false; } // Convert a string to an integer UINT ToInt(char *str) { // Validate arguments if (str == NULL) { return 0; } // Ignore the octal literal while (true) { if (*str != '0') { break; } if ((*(str + 1) == 'x') || (*(str + 1) == 'X')) { break; } str++; } return (UINT)strtoul(str, NULL, 0); } // Replace a format string for 64-bit integer char *ReplaceFormatStringFor64(char *fmt) { char *tmp; char *ret; UINT tmp_size; // Validate arguments if (fmt == NULL) { return NULL; } tmp_size = StrSize(fmt) * 2; tmp = ZeroMalloc(tmp_size); #ifdef OS_WIN32 ReplaceStrEx(tmp, tmp_size, fmt, "%ll", "%I64", false); #else // OS_WIN32 ReplaceStrEx(tmp, tmp_size, fmt, "%I64", "%ll", false); #endif // OS_WIN32 ret = CopyStr(tmp); Free(tmp); return ret; } // Display the string on the screen void PrintStr(char *str) { wchar_t *unistr = NULL; // Validate arguments if (str == NULL) { return; } #ifdef OS_UNIX fputs(str, stdout); #else // OS_UNIX unistr = CopyStrToUni(str); UniPrintStr(unistr); Free(unistr); #endif // OS_UNIX } // Display a string with arguments void PrintArgs(char *fmt, va_list args) { wchar_t *ret; wchar_t *fmt_wchar; char *tmp; // Validate arguments if (fmt == NULL) { return; } fmt_wchar = CopyStrToUni(fmt); ret = InternalFormatArgs(fmt_wchar, args, true); tmp = CopyUniToStr(ret); PrintStr(tmp); Free(tmp); Free(ret); Free(fmt_wchar); } // Display a string void Print(char *fmt, ...) { va_list args; if (fmt == NULL) { return; } va_start(args, fmt); PrintArgs(fmt, args); va_end(args); } // Display a debug string with arguments void DebugArgs(char *fmt, va_list args) { // Validate arguments if (fmt == NULL) { return; } if (g_debug == false) { return; } PrintArgs(fmt, args); } // Display a debug string void Debug(char *fmt, ...) { va_list args; // Validate arguments if (fmt == NULL) { return; } if (g_debug == false) { return; } va_start(args, fmt); DebugArgs(fmt, args); va_end(args); } // Format the string, and return the result char *CopyFormat(char *fmt, ...) { char *buf; char *ret; UINT size; va_list args; // Validate arguments if (fmt == NULL) { return NULL; } size = MAX(StrSize(fmt) * 10, MAX_SIZE * 10); buf = Malloc(size); va_start(args, fmt); FormatArgs(buf, size, fmt, args); ret = CopyStr(buf); Free(buf); va_end(args); return ret; } // Format the string void Format(char *buf, UINT size, char *fmt, ...) { va_list args; // Validate arguments if (buf == NULL || fmt == NULL) { return; } va_start(args, fmt); FormatArgs(buf, size, fmt, args); va_end(args); } // Format the string (argument list) void FormatArgs(char *buf, UINT size, char *fmt, va_list args) { wchar_t *tag; wchar_t *ret; // Validate arguments if (buf == NULL || fmt == NULL) { return; } tag = CopyStrToUni(fmt); ret = InternalFormatArgs(tag, args, true); UniToStr(buf, size, ret); Free(ret); Free(tag); } // Compare the strings in case-insensitive mode int StrCmpi(char *str1, char *str2) { UINT i; // Validate arguments if (str1 == NULL && str2 == NULL) { return 0; } if (str1 == NULL) { return 1; } if (str2 == NULL) { return -1; } // String comparison i = 0; while (true) { char c1, c2; c1 = ToUpper(str1[i]); c2 = ToUpper(str2[i]); if (c1 > c2) { return 1; } else if (c1 < c2) { return -1; } if (str1[i] == 0 || str2[i] == 0) { return 0; } i++; } } // Compare the string int StrCmp(char *str1, char *str2) { // Validate arguments if (str1 == NULL && str2 == NULL) { return 0; } if (str1 == NULL) { return 1; } if (str2 == NULL) { return -1; } return strcmp(str1, str2); } // Uncapitalize the string void StrLower(char *str) { UINT len, i; // Validate arguments if (str == NULL) { return; } len = StrLen(str); for (i = 0;i < len;i++) { str[i] = ToLower(str[i]); } } // Capitalize the string void StrUpper(char *str) { UINT len, i; // Validate arguments if (str == NULL) { return; } len = StrLen(str); for (i = 0;i < len;i++) { str[i] = ToUpper(str[i]); } } // Uncapitalize a character char ToLower(char c) { if ('A' <= c && c <= 'Z') { c += 'z' - 'Z'; } return c; } // Capitalize a character char ToUpper(char c) { if ('a' <= c && c <= 'z') { c += 'Z' - 'z'; } return c; } // Combine the string UINT StrCat(char *dst, UINT size, char *src) { UINT len1, len2, len_test; // Validate arguments if (dst == NULL || src == NULL) { return 0; } // KS KS_INC(KS_STRCAT_COUNT); if (size == 0) { // Ignore the length size = 0x7fffffff; } len1 = StrLen(dst); len2 = StrLen(src); len_test = len1 + len2 + 1; if (len_test > size) { if (len2 <= (len_test - size)) { return 0; } len2 -= len_test - size; } Copy(dst + len1, src, len2); dst[len1 + len2] = 0; return len1 + len2; } UINT StrCatLeft(char *dst, UINT size, char *src) { char *s; // Validate arguments if (dst == NULL || src == NULL) { return 0; } s = CopyStr(dst); StrCpy(dst, size, src); StrCat(dst, size, s); Free(s); return StrLen(dst); } // Copy a string UINT StrCpy(char *dst, UINT size, char *src) { UINT len; // Validate arguments if (dst == src) { return StrLen(src); } if (dst == NULL || src == NULL) { if (src == NULL && dst != NULL) { if (size >= 1) { dst[0] = '\0'; } } return 0; } if (size == 1) { dst[0] = '\0'; return 0; } if (size == 0) { // Ignore the length size = 0x7fffffff; } // Check the length len = StrLen(src); if (len <= (size - 1)) { Copy(dst, src, len + 1); } else { len = size - 1; Copy(dst, src, len); dst[len] = '\0'; } // KS KS_INC(KS_STRCPY_COUNT); return len; } // Check whether the string buffer is within the specified size bool StrCheckSize(char *str, UINT size) { // Validate arguments if (str == NULL || size == 0) { return false; } return StrCheckLen(str, size - 1); } // Make sure that the string is within the specified length bool StrCheckLen(char *str, UINT len) { UINT count = 0; UINT i; // Validate arguments if (str == NULL) { return false; } // KS KS_INC(KS_STRCHECK_COUNT); for (i = 0;;i++) { if (str[i] == '\0') { return true; } count++; if (count > len) { return false; } } } // Get the memory size needed to store the string UINT StrSize(char *str) { // Validate arguments if (str == NULL) { return 0; } return StrLen(str) + 1; } // Get the length of the string UINT StrLen(char *str) { // Validate arguments if (str == NULL) { return 0; } // KS KS_INC(KS_STRLEN_COUNT); return (UINT)strlen(str); }