1 // SoftEther UT-VPN SourceCode
\r
3 // Copyright (C) 2004-2010 SoftEther Corporation.
\r
4 // Copyright (C) 2004-2010 University of Tsukuba, Japan.
\r
5 // Copyright (C) 2003-2010 Daiyuu Nobori.
\r
6 // All Rights Reserved.
\r
8 // http://utvpn.tsukuba.ac.jp/
\r
10 // This program is free software; you can redistribute it and/or
\r
11 // modify it under the terms of the GNU General Public License
\r
12 // version 2 as published by the Free Software Foundation.
\r
14 // This program is distributed in the hope that it will be useful,
\r
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of
\r
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
\r
17 // GNU General Public License for more details.
\r
19 // You should have received a copy of the GNU General Public License version 2
\r
20 // along with this program; if not, write to the Free Software
\r
21 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
\r
23 // このファイルは GPL バージョン 2 ライセンスで公開されています。
\r
24 // 誰でもこのファイルの内容を複製、改変したり、改変したバージョンを再配布
\r
25 // することができます。ただし、原著作物を改変した場合は、原著作物の著作権表示
\r
26 // を除去することはできません。改変した著作物を配布する場合は、改変実施者の
\r
27 // 著作権表示を原著作物の著作権表示に付随して記載するようにしてください。
\r
29 // この SoftEther UT-VPN オープンソース・プロジェクトは、日本国の
\r
30 // ソフトイーサ株式会社 (SoftEther Corporation, http://www.softether.co.jp/ )
\r
31 // および筑波大学 (University of Tsukuba, http://www.tsukuba.ac.jp/ ) によって
\r
33 // 本プログラムの配布者は、本プログラムを、業としての利用以外のため、
\r
34 // および、試験または研究のために利用が行われることを想定して配布
\r
36 // SoftEther UT-VPN プロジェクトの Web サイトは http://utvpn.tsukuba.ac.jp/ に
\r
38 // 本ソフトウェアの不具合の修正、機能改良、セキュリティホールの修復などのコード
\r
39 // の改変を行った場合で、その成果物を SoftEther UT-VPN プロジェクトに提出して
\r
40 // いただける場合は、 http://utvpn.tsukuba.ac.jp/ までソースコードを送付して
\r
41 // ください。SoftEther UT-VPN プロジェクトの本体リリースまたはブランチリリース
\r
44 // GPL に基づいて原著作物が提供される本ソフトウェアの改良版を配布、販売する
\r
45 // 場合は、そのソースコードを GPL に基づいて誰にでも開示する義務が生じます。
\r
47 // 本ソフトウェアに関連する著作権、特許権、商標権はソフトイーサ株式会社
\r
48 // (SoftEther Corporation) およびその他の著作権保持者が保有しています。
\r
49 // ソフトイーサ株式会社等はこれらの権利を放棄していません。本ソフトウェアの
\r
50 // 二次著作物を配布、販売する場合は、これらの権利を侵害しないようにご注意
\r
53 // お願い: どのような通信ソフトウェアにも通常は必ず未発見の
\r
54 // セキュリティホールが潜んでいます。本ソースコードをご覧いただいた結果、
\r
55 // UT-VPN にセキュリティホールを発見された場合は、当該セキュリティホールの
\r
56 // 情報を不特定多数に開示される前に、必ず、ソフトイーサ株式会社
\r
57 // および脆弱性情報の届出を受け付ける公的機関まで通報いただき、
\r
58 // 公益保護にご協力いただきますようお願い申し上げます。
\r
60 // ソフトイーサ株式会社は、当該セキュリティホールについて迅速に対処を
\r
61 // 行い、UT-VPN および UT-VPN に関連するソフトウェアのユーザー・顧客
\r
64 // ソフトイーサへの届出先: http://www.softether.co.jp/jp/contact/
\r
65 // 日本国内の脆弱性情報届出受付公的機関:
\r
67 // http://www.ipa.go.jp/security/vuln/report/
\r
69 // 上記各事項について不明な点は、ソフトイーサ株式会社までご連絡ください。
\r
70 // 連絡先: http://www.softether.co.jp/jp/contact/
\r
72 // -----------------------------------------------
\r
75 // 新規リリース by SoftEther
\r
76 // -----------------------------------------------
\r
88 #include <Mayaqua/Mayaqua.h>
\r
90 // トークン関数の呼び出し用ロック処理
\r
91 LOCK *token_lock = NULL;
\r
92 static char *default_spliter = " ,\t\r\n";
\r
94 typedef struct BYTESTR
\r
100 static BYTESTR bytestr[] =
\r
110 // HEX 文字列を 64 bit 整数に変換
\r
111 UINT64 HexToInt64(char *str)
\r
121 if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X'))
\r
127 for (i = 0;i < len;i++)
\r
131 if ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'))
\r
133 ret = ret * 16ULL + (UINT64)HexTo4Bit(c);
\r
144 // HEX 文字列を 32 bit 整数に変換
\r
145 UINT HexToInt(char *str)
\r
155 if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X'))
\r
161 for (i = 0;i < len;i++)
\r
165 if ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'))
\r
167 ret = ret * 16 + (UINT)HexTo4Bit(c);
\r
178 // 64 bit 整数を HEX に変換
\r
179 void ToHex64(char *str, UINT64 value)
\r
181 char tmp[MAX_SIZE];
\r
191 StrCpy(tmp, 0, "");
\r
196 UINT a = (UINT)(value % (UINT64)16);
\r
197 value = value / (UINT)16;
\r
198 tmp[wp++] = FourBitToHex(a);
\r
208 for (i = 0;i < len;i++)
\r
210 str[len - i - 1] = tmp[i];
\r
215 // 32 bit 整数を HEX に変換
\r
216 void ToHex(char *str, UINT value)
\r
218 char tmp[MAX_SIZE];
\r
228 StrCpy(tmp, 0, "");
\r
233 UINT a = (UINT)(value % (UINT)16);
\r
234 value = value / (UINT)16;
\r
235 tmp[wp++] = FourBitToHex(a);
\r
245 for (i = 0;i < len;i++)
\r
247 str[len - i - 1] = tmp[i];
\r
252 // 4 bit 数値を 16 進文字列に変換
\r
253 char FourBitToHex(UINT value)
\r
255 value = value % 16;
\r
259 return '0' + value;
\r
263 return 'a' + (value - 10);
\r
267 // 16 進文字列を 4 bit 整数に変換
\r
268 UINT HexTo4Bit(char c)
\r
270 if ('0' <= c && c <= '9')
\r
274 else if ('a' <= c && c <= 'f')
\r
276 return c - 'a' + 10;
\r
278 else if ('A' <= c && c <= 'F')
\r
280 return c - 'A' + 10;
\r
288 // 標準のトークン区切り文字を取得する
\r
289 char *DefaultTokenSplitChars()
\r
294 // 指定された文字が文字列に含まれるかどうかチェック
\r
295 bool IsCharInStr(char *str, char c)
\r
305 for (i = 0;i < len;i++)
\r
316 // 文字列からトークンを切り出す (区切り文字間の空間を無視しない)
\r
317 TOKEN_LIST *ParseTokenWithNullStr(char *str, char *split_chars)
\r
327 return NullToken();
\r
329 if (split_chars == NULL)
\r
331 split_chars = DefaultTokenSplitChars();
\r
335 o = NewListFast(NULL);
\r
339 for (i = 0;i < (len + 1);i++)
\r
342 bool flag = IsCharInStr(split_chars, c);
\r
351 WriteBuf(b, &c, sizeof(char));
\r
355 WriteBuf(b, &zero, sizeof(char));
\r
357 Insert(o, CopyStr((char *)b->Buf));
\r
362 t = ZeroMalloc(sizeof(TOKEN_LIST));
\r
363 t->NumTokens = LIST_NUM(o);
\r
364 t->Token = ZeroMalloc(sizeof(char *) * t->NumTokens);
\r
366 for (i = 0;i < t->NumTokens;i++)
\r
368 t->Token[i] = LIST_DATA(o, i);
\r
377 // 文字列からトークンを切り出す (区切り文字間の空間を無視する)
\r
378 TOKEN_LIST *ParseTokenWithoutNullStr(char *str, char *split_chars)
\r
389 return NullToken();
\r
391 if (split_chars == NULL)
\r
393 split_chars = DefaultTokenSplitChars();
\r
397 o = NewListFast(NULL);
\r
402 for (i = 0;i < (len + 1);i++)
\r
405 bool flag = IsCharInStr(split_chars, c);
\r
414 WriteBuf(b, &c, sizeof(char));
\r
418 if (last_flag == false)
\r
420 WriteBuf(b, &zero, sizeof(char));
\r
422 if ((StrLen((char *)b->Buf)) != 0)
\r
424 Insert(o, CopyStr((char *)b->Buf));
\r
433 t = ZeroMalloc(sizeof(TOKEN_LIST));
\r
434 t->NumTokens = LIST_NUM(o);
\r
435 t->Token = ZeroMalloc(sizeof(char *) * t->NumTokens);
\r
437 for (i = 0;i < t->NumTokens;i++)
\r
439 t->Token[i] = LIST_DATA(o, i);
\r
448 // 文字列が含まれているかどうかチェック
\r
449 bool InStr(char *str, char *keyword)
\r
451 return InStrEx(str, keyword, false);
\r
453 bool InStrEx(char *str, char *keyword, bool case_sensitive)
\r
456 if (IsEmptyStr(str) || IsEmptyStr(keyword))
\r
461 if (SearchStrEx(str, keyword, 0, case_sensitive) == INFINITE)
\r
470 UINT IniIntValue(LIST *o, char *key)
\r
474 if (o == NULL || key == NULL)
\r
479 e = GetIniEntry(o, key);
\r
485 return ToInt(e->Value);
\r
487 UINT64 IniInt64Value(LIST *o, char *key)
\r
491 if (o == NULL || key == NULL)
\r
496 e = GetIniEntry(o, key);
\r
502 return ToInt64(e->Value);
\r
504 char *IniStrValue(LIST *o, char *key)
\r
508 if (o == NULL || key == NULL)
\r
513 e = GetIniEntry(o, key);
\r
521 wchar_t *IniUniStrValue(LIST *o, char *key)
\r
525 if (o == NULL || key == NULL)
\r
530 e = GetIniEntry(o, key);
\r
536 return e->UnicodeValue;
\r
540 void FreeIni(LIST *o)
\r
549 for (i = 0;i < LIST_NUM(o);i++)
\r
551 INI_ENTRY *e = LIST_DATA(o, i);
\r
555 Free(e->UnicodeValue);
\r
563 // INI ファイルのエントリを取得する
\r
564 INI_ENTRY *GetIniEntry(LIST *o, char *key)
\r
568 if (o == NULL || key == NULL)
\r
573 for (i = 0;i < LIST_NUM(o);i++)
\r
575 INI_ENTRY *e = LIST_DATA(o, i);
\r
577 if (StrCmpi(e->Key, key) == 0)
\r
587 LIST *ReadIni(BUF *b)
\r
596 o = NewListFast(NULL);
\r
602 char *line = CfgReadNextLine(b);
\r
611 if (IsEmptyStr(line) == false)
\r
613 if (StartWith(line, "#") == false &&
\r
614 StartWith(line, "//") == false &&
\r
615 StartWith(line, ";") == false)
\r
618 UINT size = StrLen(line) + 1;
\r
620 key = ZeroMalloc(size);
\r
621 value = ZeroMalloc(size);
\r
623 if (GetKeyAndValue(line, key, size, value, size, NULL))
\r
626 INI_ENTRY *e = ZeroMalloc(sizeof(INI_ENTRY));
\r
627 e->Key = CopyStr(key);
\r
628 e->Value = CopyStr(value);
\r
630 uni_size = CalcUtf8ToUni((BYTE *)value, StrLen(value));
\r
631 e->UnicodeValue = ZeroMalloc(uni_size);
\r
632 Utf8ToUni(e->UnicodeValue, uni_size, (BYTE *)value, StrLen(value));
\r
648 // 指定された文字が区切り文字かどうかチェック
\r
649 bool IsSplitChar(char c, char *split_str)
\r
652 char c_upper = ToUpper(c);
\r
653 if (split_str == NULL)
\r
655 split_str = default_spliter;
\r
658 len = StrLen(split_str);
\r
660 for (i = 0;i < len;i++)
\r
662 if (ToUpper(split_str[i]) == c_upper)
\r
672 bool GetKeyAndValue(char *str, char *key, UINT key_size, char *value, UINT value_size, char *split_str)
\r
675 UINT wp1 = 0, wp2 = 0;
\r
677 char *key_tmp, *value_tmp;
\r
679 if (split_str == NULL)
\r
681 split_str = default_spliter;
\r
686 key_tmp = ZeroMalloc(len + 1);
\r
687 value_tmp = ZeroMalloc(len + 1);
\r
689 for (i = 0;i < len;i++)
\r
696 if (IsSplitChar(c, split_str) == false)
\r
705 if (IsSplitChar(c, split_str) == false)
\r
717 if (IsSplitChar(c, split_str) == false)
\r
720 value_tmp[wp2] = c;
\r
726 value_tmp[wp2] = c;
\r
735 StrCpy(key, key_size, key_tmp);
\r
736 StrCpy(value, value_size, value_tmp);
\r
746 char *MakeCharArray(char c, UINT count)
\r
749 char *ret = Malloc(count + 1);
\r
751 for (i = 0;i < count;i++)
\r
760 void MakeCharArray2(char *str, char c, UINT count)
\r
764 for (i = 0;i < count;i++)
\r
773 UINT StrWidth(char *str)
\r
783 s = CopyStrToUni(str);
\r
784 ret = UniStrWidth(s);
\r
790 // 指定した文字列がすべて大文字かどうかチェックする
\r
791 bool IsAllUpperStr(char *str)
\r
802 for (i = 0;i < len;i++)
\r
806 if ((c >= '0' && c <= '9') ||
\r
807 (c >= 'A' && c <= 'Z'))
\r
820 char *NormalizeCrlf(char *str)
\r
823 UINT ret_size, i, len, wp;
\r
831 ret_size = sizeof(char) * (len + 32) * 2;
\r
832 ret = Malloc(ret_size);
\r
836 for (i = 0;i < len;i++)
\r
843 if (str[i + 1] == '\n')
\r
867 // トークンリストを重複の無いものに変換する
\r
868 TOKEN_LIST *UniqueToken(TOKEN_LIST *t)
\r
879 for (i = 0;i < t->NumTokens;i++)
\r
881 bool exists = false;
\r
883 for (j = 0;j < i;j++)
\r
885 if (StrCmpi(t->Token[j], t->Token[i]) == 0)
\r
892 if (exists == false)
\r
898 ret = ZeroMalloc(sizeof(TOKEN_LIST));
\r
899 ret->Token = ZeroMalloc(sizeof(char *) * num);
\r
900 ret->NumTokens = num;
\r
904 for (i = 0;i < t->NumTokens;i++)
\r
906 bool exists = false;
\r
908 for (j = 0;j < i;j++)
\r
910 if (StrCmpi(t->Token[j], t->Token[i]) == 0)
\r
917 if (exists == false)
\r
919 ret->Token[n++] = CopyStr(t->Token[i]);
\r
926 // バイト文字列に変換する (1,000 単位)
\r
927 void ToStrByte1000(char *str, UINT size, UINT64 v)
\r
937 bytestr[0].base_value = 1000000000UL;
\r
938 bytestr[0].base_value *= 1000UL;
\r
939 bytestr[0].base_value *= 1000UL;
\r
940 bytestr[1].base_value = 1000000000UL;
\r
941 bytestr[1].base_value *= 1000UL;
\r
942 bytestr[2].base_value = 1000000000UL;
\r
943 bytestr[3].base_value = 1000000UL;
\r
944 bytestr[4].base_value = 1000UL;
\r
945 bytestr[5].base_value = 0UL;
\r
947 for (i = 0;i < sizeof(bytestr) / sizeof(bytestr[0]);i++)
\r
949 BYTESTR *b = &bytestr[i];
\r
951 if ((v * 11UL) / 10UL >= b->base_value)
\r
953 if (b->base_value != 0)
\r
955 double d = (double)v / (double)b->base_value;
\r
956 Format(str, size, "%.2f %s", d, b->string);
\r
960 Format(str, size, "%I64u %s", v, b->string);
\r
969 void ToStrByte(char *str, UINT size, UINT64 v)
\r
979 bytestr[0].base_value = 1073741824UL;
\r
980 bytestr[0].base_value *= 1024UL;
\r
981 bytestr[0].base_value *= 1024UL;
\r
982 bytestr[1].base_value = 1073741824UL;
\r
983 bytestr[1].base_value *= 1024UL;
\r
984 bytestr[2].base_value = 1073741824UL;
\r
985 bytestr[3].base_value = 1048576UL;
\r
986 bytestr[4].base_value = 1024UL;
\r
987 bytestr[5].base_value = 0UL;
\r
989 for (i = 0;i < sizeof(bytestr) / sizeof(bytestr[0]);i++)
\r
991 BYTESTR *b = &bytestr[i];
\r
993 if ((v * 11UL) / 10UL >= b->base_value)
\r
995 if (b->base_value != 0)
\r
997 double d = (double)v / (double)b->base_value;
\r
998 Format(str, size, "%.2f %s", d, b->string);
\r
1002 Format(str, size, "%I64u %s", v, b->string);
\r
1010 // 数字を文字列に変換して 3 桁ずつカンマで区切る
\r
1011 void ToStr3(char *str, UINT size, UINT64 v)
\r
1025 len = StrLen(tmp);
\r
1027 for (i = len - 1;((int)i) >= 0;i--)
\r
1029 tmp2[wp++] = tmp[i];
\r
1035 for (i = 0;i < len;i++)
\r
1037 if (i != 0 && (i % 3) == 0)
\r
1041 tmp[wp++] = tmp2[i];
\r
1045 len = StrLen(tmp);
\r
1047 for (i = len - 1;((int)i) >= 0;i--)
\r
1049 tmp2[wp++] = tmp[i];
\r
1053 StrCpy(str, size, tmp2);
\r
1056 // MAC アドレスを文字列にする
\r
1057 void MacToStr(char *str, UINT size, UCHAR *mac_address)
\r
1060 if (str == NULL || mac_address == NULL)
\r
1065 Format(str, size, "%02X-%02X-%02X-%02X-%02X-%02X",
\r
1075 bool IsEmptyStr(char *str)
\r
1087 if (StrLen(s) == 0)
\r
1099 // トークンリストを文字列リストに変換する
\r
1100 LIST *TokenListToList(TOKEN_LIST *t)
\r
1110 o = NewListFast(NULL);
\r
1111 for (i = 0;i < t->NumTokens;i++)
\r
1113 Insert(o, CopyStr(t->Token[i]));
\r
1119 // 文字列リストをトークンリストに変換する
\r
1120 TOKEN_LIST *ListToTokenList(LIST *o)
\r
1130 t = ZeroMalloc(sizeof(TOKEN_LIST));
\r
1131 t->NumTokens = LIST_NUM(o);
\r
1132 t->Token = ZeroMalloc(sizeof(char *) * t->NumTokens);
\r
1133 for (i = 0;i < LIST_NUM(o);i++)
\r
1135 t->Token[i] = CopyStr(LIST_DATA(o, i));
\r
1142 void FreeStrList(LIST *o)
\r
1151 for (i = 0;i < LIST_NUM(o);i++)
\r
1153 char *s = LIST_DATA(o, i);
\r
1160 // 文字列リストを文字列に変換する
\r
1161 BUF *StrListToStr(LIST *o)
\r
1173 for (i = 0;i < LIST_NUM(o);i++)
\r
1175 char *s = LIST_DATA(o, i);
\r
1176 WriteBuf(b, s, StrLen(s) + 1);
\r
1180 WriteBuf(b, &c, 1);
\r
1187 // 文字列 (NULL区切り) をリストに変換する
\r
1188 LIST *StrToStrList(char *str, UINT size)
\r
1200 o = NewListFast(NULL);
\r
1214 tmp_size = StrSize(str);
\r
1215 tmp = ZeroMalloc(tmp_size);
\r
1216 StrCpy(tmp, tmp_size, str);
\r
1218 str += StrLen(str) + 1;
\r
1225 // 指定された文字列が数字かどうかチェック
\r
1226 bool IsNum(char *str)
\r
1231 char tmp[MAX_SIZE];
\r
1239 StrCpy(tmp, sizeof(tmp), str);
\r
1242 if (StrLen(tmp) == 0)
\r
1247 t = ParseToken(tmp, " ");
\r
1249 if (t->NumTokens >= 1)
\r
1251 StrCpy(tmp, sizeof(tmp), t->Token[0]);
\r
1256 len = StrLen(tmp);
\r
1257 for (i = 0;i < len;i++)
\r
1261 if (('0' <= c && c <= '9') || (c == '+') || (c == '-') || (c == ','))
\r
1272 for (i = 0;i < len;i++)
\r
1289 TOKEN_LIST *NullToken()
\r
1291 TOKEN_LIST *ret = ZeroMalloc(sizeof(TOKEN_LIST));
\r
1292 ret->Token = ZeroMalloc(0);
\r
1298 TOKEN_LIST *CopyToken(TOKEN_LIST *src)
\r
1308 ret = ZeroMalloc(sizeof(TOKEN_LIST));
\r
1309 ret->NumTokens = src->NumTokens;
\r
1310 ret->Token = ZeroMalloc(sizeof(char *) * ret->NumTokens);
\r
1311 for (i = 0;i < ret->NumTokens;i++)
\r
1313 ret->Token[i] = CopyStr(src->Token[i]);
\r
1320 TOKEN_LIST *ParseCmdLine(char *str)
\r
1324 UINT i, len, wp, mode;
\r
1327 bool ignore_space = false;
\r
1332 return NullToken();
\r
1335 o = NewListFast(NULL);
\r
1336 tmp = Malloc(StrSize(str) + 32);
\r
1341 len = StrLen(str);
\r
1342 for (i = 0;i < len;i++)
\r
1350 if (c == ' ' || c == '\t')
\r
1359 if (str[i + 1] == '\"')
\r
1361 // 2 重の " は 1 個の " 文字として見なす
\r
1367 // 1 個の " はスペース無視フラグを有効にする
\r
1368 ignore_space = true;
\r
1381 if (ignore_space == false && (c == ' ' || c == '\t'))
\r
1387 Insert(o, CopyStr(tmp));
\r
1394 if (str[i + 1] == '\"')
\r
1396 // 2 重の " は 1 個の " 文字として見なす
\r
1397 tmp[wp++] = L'\"';
\r
1402 if (ignore_space == false)
\r
1404 // 1 個の " はスペース無視フラグを有効にする
\r
1405 ignore_space = true;
\r
1409 // スペース無視フラグを無効にする
\r
1410 ignore_space = false;
\r
1426 Insert(o, CopyStr(tmp));
\r
1431 t = ZeroMalloc(sizeof(TOKEN_LIST));
\r
1432 t->NumTokens = LIST_NUM(o);
\r
1433 t->Token = ZeroMalloc(sizeof(char *) * t->NumTokens);
\r
1434 for (i = 0;i < t->NumTokens;i++)
\r
1436 t->Token[i] = LIST_DATA(o, i);
\r
1444 // 64bit 整数を文字列に変換
\r
1445 void ToStr64(char *str, UINT64 value)
\r
1447 char tmp[MAX_SIZE];
\r
1457 StrCpy(tmp, 0, "");
\r
1462 UINT a = (UINT)(value % (UINT64)10);
\r
1463 value = value / (UINT64)10;
\r
1464 tmp[wp++] = (char)('0' + a);
\r
1473 len = StrLen(tmp);
\r
1474 for (i = 0;i < len;i++)
\r
1476 str[len - i - 1] = tmp[i];
\r
1481 // 文字列を 64bit 整数に変換
\r
1482 UINT64 ToInt64(char *str)
\r
1492 len = StrLen(str);
\r
1493 for (i = 0;i < len;i++)
\r
1498 if ('0' <= c && c <= '9')
\r
1500 ret = ret * (UINT64)10 + (UINT64)(c - '0');
\r
1512 // str が key で終了するかどうかチェック
\r
1513 bool EndWith(char *str, char *key)
\r
1518 if (str == NULL || key == NULL)
\r
1524 str_len = StrLen(str);
\r
1525 key_len = StrLen(key);
\r
1526 if (str_len < key_len)
\r
1531 if (StrCmpi(str + (str_len - key_len), key) == 0)
\r
1541 // str が key で始まるかどうかチェック
\r
1542 bool StartWith(char *str, char *key)
\r
1549 if (str == NULL || key == NULL)
\r
1555 str_len = StrLen(str);
\r
1556 key_len = StrLen(key);
\r
1557 if (str_len < key_len)
\r
1561 if (str_len == 0 || key_len == 0)
\r
1565 tmp = CopyStr(str);
\r
1568 if (StrCmpi(tmp, key) == 0)
\r
1583 void PrintBin(void *data, UINT size)
\r
1595 BinToStrEx(tmp, i, data, size);
\r
1596 Print("%s\n", tmp);
\r
1600 // 文字列を MAC アドレスに変換する
\r
1601 bool StrToMac(UCHAR *mac_address, char *str)
\r
1605 if (mac_address == NULL || str == NULL)
\r
1610 b = StrToBin(str);
\r
1622 Copy(mac_address, b->Buf, 6);
\r
1629 // 16 進文字列をバイナリデータに変換する
\r
1630 BUF *StrToBin(char *str)
\r
1641 len = StrLen(str);
\r
1644 for (i = 0;i < len;i++)
\r
1648 if (('0' <= c && c <= '9') || ('A' <= c && c <= 'F'))
\r
1655 else if (tmp[1] == 0)
\r
1661 StrCpy(tmp2, sizeof(tmp2), "0x");
\r
1662 StrCat(tmp2, sizeof(tmp2), tmp);
\r
1663 data = (UCHAR)strtoul(tmp2, NULL, 0);
\r
1664 WriteBuf(b, &data, 1);
\r
1665 Zero(tmp, sizeof(tmp));
\r
1668 else if (c == ' ' || c == ',' || c == '-' || c == ':')
\r
1681 // バイナリデータを 16 進文字列に変換する (スペースも入れる)
\r
1682 void BinToStrEx(char *str, UINT str_size, void *data, UINT data_size)
\r
1685 UCHAR *buf = (UCHAR *)data;
\r
1689 if (str == NULL || data == NULL)
\r
1695 size = data_size * 3 + 1;
\r
1697 tmp = ZeroMalloc(size);
\r
1699 for (i = 0;i < data_size;i++)
\r
1701 Format(&tmp[i * 3], 0, "%02X ", buf[i]);
\r
1705 StrCpy(str, str_size, tmp);
\r
1709 void BinToStrEx2(char *str, UINT str_size, void *data, UINT data_size, char padding_char)
\r
1712 UCHAR *buf = (UCHAR *)data;
\r
1716 if (str == NULL || data == NULL)
\r
1722 size = data_size * 3 + 1;
\r
1724 tmp = ZeroMalloc(size);
\r
1726 for (i = 0;i < data_size;i++)
\r
1728 Format(&tmp[i * 3], 0, "%02X%c", buf[i], padding_char);
\r
1730 if (StrLen(tmp) >= 1)
\r
1732 if (tmp[StrLen(tmp) - 1] == padding_char)
\r
1734 tmp[StrLen(tmp) - 1] = 0;
\r
1738 StrCpy(str, str_size, tmp);
\r
1742 // バイナリデータを文字列に変換してコピーする
\r
1743 char *CopyBinToStrEx(void *data, UINT data_size)
\r
1753 size = data_size * 3 + 1;
\r
1754 ret = ZeroMalloc(size);
\r
1756 BinToStrEx(ret, size, data, data_size);
\r
1760 char *CopyBinToStr(void *data, UINT data_size)
\r
1770 size = data_size * 2 + 1;
\r
1771 ret = ZeroMalloc(size);
\r
1773 BinToStr(ret, size, data, data_size);
\r
1778 // バイナリデータを 16 進文字列に変換する
\r
1779 void BinToStr(char *str, UINT str_size, void *data, UINT data_size)
\r
1782 UCHAR *buf = (UCHAR *)data;
\r
1786 if (str == NULL || data == NULL)
\r
1796 size = data_size * 2 + 1;
\r
1798 tmp = ZeroMalloc(size);
\r
1800 for (i = 0;i < data_size;i++)
\r
1802 sprintf(&tmp[i * 2], "%02X", buf[i]);
\r
1805 StrCpy(str, str_size, tmp);
\r
1809 void BinToStrW(wchar_t *str, UINT str_size, void *data, UINT data_size)
\r
1814 if (str == NULL || data == NULL)
\r
1823 tmp_size = (data_size * 2 + 4) * sizeof(wchar_t);
\r
1824 tmp = ZeroMalloc(tmp_size);
\r
1826 BinToStr(tmp, tmp_size, data, data_size);
\r
1828 StrToUni(str, str_size, tmp);
\r
1833 // 160 ビット列を文字列にする
\r
1834 void Bit160ToStr(char *str, UCHAR *data)
\r
1837 if (str == NULL || data == NULL)
\r
1843 "%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X",
\r
1844 data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7], data[8], data[9],
\r
1845 data[10], data[11], data[12], data[13], data[14], data[15], data[16], data[17], data[18], data[19]);
\r
1848 // 128 ビット列を文字列にする
\r
1849 void Bit128ToStr(char *str, UCHAR *data)
\r
1852 if (str == NULL || data == NULL)
\r
1858 "%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X",
\r
1859 data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7], data[8], data[9],
\r
1860 data[10], data[11], data[12], data[13], data[14], data[15]);
\r
1864 char *CopyStr(char *str)
\r
1874 len = StrLen(str);
\r
1875 dst = Malloc(len + 1);
\r
1876 StrCpy(dst, len + 1, str);
\r
1881 bool IsSafeStr(char *str)
\r
1890 len = StrLen(str);
\r
1891 for (i = 0;i < len;i++)
\r
1893 if (IsSafeChar(str[i]) == false)
\r
1898 if (str[0] == ' ')
\r
1904 if (str[len - 1] == ' ')
\r
1913 bool IsSafeChar(char c)
\r
1917 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
\r
1918 "abcdefghijklmnopqrstuvwxyz"
\r
1922 len = StrLen(check_str);
\r
1923 for (i = 0;i < len;i++)
\r
1925 if (c == check_str[i])
\r
1933 // 文字列から指定した文字を削除する
\r
1934 void TruncateCharFromStr(char *str, char replace)
\r
1945 while(*src != '\0')
\r
1947 if(*src != replace)
\r
1956 //BUF *b = NewBuf();
\r
1960 //len = StrLen(str);
\r
1961 //for (i = 0;i < len;i++)
\r
1963 // char c = str[i];
\r
1965 // if (c != replace)
\r
1967 // WriteBuf(b, &c, 1);
\r
1971 //if (b->Size == 0)
\r
1974 // WriteBuf(b, &c, 1);
\r
1977 //WriteBuf(b, &zero, 1);
\r
1979 //StrCpy(str, 0, b->Buf);
\r
1985 void EnSafeStr(char *str, char replace)
\r
1992 while(*str != '\0')
\r
1994 if(IsSafeChar(*str) == false)
\r
2002 // 文字列ライブラリの動作チェック
\r
2003 bool CheckStringLibrary()
\r
2005 wchar_t *compare_str = L"TEST_TEST_123_123456789012345";
\r
2006 char *teststr = "TEST";
\r
2007 wchar_t *testunistr = L"TEST";
\r
2010 UINT64 i2 = 123456789012345ULL;
\r
2012 UniFormat(tmp, sizeof(tmp), L"%S_%s_%u_%I64u", teststr, testunistr,
\r
2015 if (UniStrCmpi(tmp, compare_str) != 0)
\r
2024 void InitStringLibrary()
\r
2027 token_lock = NewLock();
\r
2030 InitInternational();
\r
2033 if (CheckStringLibrary() == false)
\r
2036 Alert("String Library Init Failed.\r\nPlease check your locale settings.", NULL);
\r
2038 Alert("String Library Init Failed.\r\nPlease check your locale settings and iconv() libraries.", NULL);
\r
2039 #endif // OS_WIN32
\r
2045 void FreeStringLibrary()
\r
2048 FreeInternational();
\r
2051 DeleteLock(token_lock);
\r
2052 token_lock = NULL;
\r
2055 // 文字列の置換 (大文字小文字を区別しない)
\r
2056 UINT ReplaceStri(char *dst, UINT size, char *string, char *old_keyword, char *new_keyword)
\r
2058 return ReplaceStrEx(dst, size, string, old_keyword, new_keyword, false);
\r
2061 // 文字列の置換 (大文字小文字を区別する)
\r
2062 UINT ReplaceStr(char *dst, UINT size, char *string, char *old_keyword, char *new_keyword)
\r
2064 return ReplaceStrEx(dst, size, string, old_keyword, new_keyword, true);
\r
2068 UINT ReplaceStrEx(char *dst, UINT size, char *string, char *old_keyword, char *new_keyword, bool case_sensitive)
\r
2071 UINT len_string, len_old, len_new;
\r
2076 if (string == NULL || old_keyword == NULL || new_keyword == NULL)
\r
2082 len_string = StrLen(string);
\r
2083 len_old = StrLen(old_keyword);
\r
2084 len_new = StrLen(new_keyword);
\r
2087 len_ret = CalcReplaceStrEx(string, old_keyword, new_keyword, case_sensitive);
\r
2089 ret = Malloc(len_ret + 1);
\r
2090 ret[len_ret] = '\0';
\r
2099 i = SearchStrEx(string, old_keyword, i, case_sensitive);
\r
2100 if (i == INFINITE)
\r
2102 Copy(ret + wp, string + j, len_string - j);
\r
2103 wp += len_string - j;
\r
2107 Copy(ret + wp, string + j, i - j);
\r
2109 Copy(ret + wp, new_keyword, len_new);
\r
2116 StrCpy(dst, size, ret);
\r
2124 // 文字列の置換後の文字列長を計算する
\r
2125 UINT CalcReplaceStrEx(char *string, char *old_keyword, char *new_keyword, bool case_sensitive)
\r
2128 UINT len_string, len_old, len_new;
\r
2130 if (string == NULL || old_keyword == NULL || new_keyword == NULL)
\r
2136 len_string = StrLen(string);
\r
2137 len_old = StrLen(old_keyword);
\r
2138 len_new = StrLen(new_keyword);
\r
2140 if (len_old == len_new)
\r
2142 return len_string;
\r
2150 i = SearchStrEx(string, old_keyword, i, case_sensitive);
\r
2151 if (i == INFINITE)
\r
2160 return len_string + len_new * num - len_old * num;
\r
2163 // 文字列の検索 (大文字 / 小文字を区別する)
\r
2164 UINT SearchStr(char *string, char *keyword, UINT start)
\r
2166 return SearchStrEx(string, keyword, start, true);
\r
2169 // 文字列の検索 (大文字 / 小文字を区別しない)
\r
2170 UINT SearchStri(char *string, char *keyword, UINT start)
\r
2172 return SearchStrEx(string, keyword, start, false);
\r
2175 // 文字列 string から文字列 keyword を検索して最初に見つかった文字の場所を返す
\r
2176 // (1文字目に見つかったら 0, 見つからなかったら INFINITE)
\r
2177 UINT SearchStrEx(char *string, char *keyword, UINT start, bool case_sensitive)
\r
2179 UINT len_string, len_keyword;
\r
2181 char *cmp_string, *cmp_keyword;
\r
2184 if (string == NULL || keyword == NULL)
\r
2190 len_string = StrLen(string);
\r
2191 if (len_string <= start)
\r
2198 len_keyword = StrLen(keyword);
\r
2199 if (len_keyword == 0)
\r
2205 if ((len_string - start) < len_keyword)
\r
2211 if (case_sensitive)
\r
2213 cmp_string = string;
\r
2214 cmp_keyword = keyword;
\r
2218 cmp_string = Malloc(len_string + 1);
\r
2219 StrCpy(cmp_string, len_string + 1, string);
\r
2220 cmp_keyword = Malloc(len_keyword + 1);
\r
2221 StrCpy(cmp_keyword, len_keyword + 1, keyword);
\r
2222 StrUpper(cmp_string);
\r
2223 StrUpper(cmp_keyword);
\r
2228 for (i = start;i < (len_string - len_keyword + 1);i++)
\r
2231 if (!strncmp(&cmp_string[i], cmp_keyword, len_keyword))
\r
2239 if (case_sensitive == false)
\r
2242 Free(cmp_keyword);
\r
2246 if (found == false)
\r
2253 // 指定した文字がトークンリスト内にあるかどうか調べる
\r
2254 bool IsInToken(TOKEN_LIST *t, char *str)
\r
2258 if (t == NULL || str == NULL)
\r
2263 for (i = 0;i < t->NumTokens;i++)
\r
2265 if (StrCmpi(t->Token[i], str) == 0)
\r
2275 void FreeToken(TOKEN_LIST *tokens)
\r
2278 if (tokens == NULL)
\r
2282 for (i = 0;i < tokens->NumTokens;i++)
\r
2284 if (tokens->Token[i] != 0)
\r
2286 Free(tokens->Token[i]);
\r
2289 Free(tokens->Token);
\r
2294 TOKEN_LIST *ParseToken(char *src, char *separator)
\r
2298 char *str1, *str2;
\r
2303 ret = ZeroMalloc(sizeof(TOKEN_LIST));
\r
2304 ret->Token = ZeroMalloc(0);
\r
2307 if (separator == NULL)
\r
2309 separator = " ,\t\r\n";
\r
2311 len = StrLen(src);
\r
2312 str1 = Malloc(len + 1);
\r
2313 str2 = Malloc(len + 1);
\r
2314 StrCpy(str1, 0, src);
\r
2315 StrCpy(str2, 0, src);
\r
2319 tmp = strtok(str1, separator);
\r
2321 while (tmp != NULL)
\r
2324 tmp = strtok(NULL, separator);
\r
2326 ret = Malloc(sizeof(TOKEN_LIST));
\r
2327 ret->NumTokens = num;
\r
2328 ret->Token = (char **)Malloc(sizeof(char *) * num);
\r
2330 tmp = strtok(str2, separator);
\r
2331 while (tmp != NULL)
\r
2333 ret->Token[num] = (char *)Malloc(StrLen(tmp) + 1);
\r
2334 StrCpy(ret->Token[num], 0, tmp);
\r
2336 tmp = strtok(NULL, separator);
\r
2339 Unlock(token_lock);
\r
2347 bool GetLine(char *str, UINT size)
\r
2351 UINT unistr_size = (size + 1) * sizeof(wchar_t);
\r
2353 unistr = Malloc(unistr_size);
\r
2355 ret = UniGetLine(unistr, unistr_size);
\r
2357 UniToStr(str, size, unistr);
\r
2365 void TrimCrlf(char *str)
\r
2373 len = StrLen(str);
\r
2379 if (str[len - 1] == '\n')
\r
2381 if (len >= 2 && str[len - 2] == '\r')
\r
2387 else if (str[len - 1] == '\r')
\r
2394 void Trim(char *str)
\r
2410 void TrimRight(char *str)
\r
2413 UINT len, i, wp, wp2;
\r
2420 len = StrLen(str);
\r
2425 if (str[len - 1] != ' ' && str[len - 1] != '\t')
\r
2430 buf = Malloc(len + 1);
\r
2431 tmp = Malloc(len + 1);
\r
2435 for (i = 0;i < len;i++)
\r
2437 if (str[i] != ' ' && str[i] != '\t')
\r
2439 Copy(buf + wp, tmp, wp2);
\r
2442 buf[wp++] = str[i];
\r
2446 tmp[wp2++] = str[i];
\r
2450 StrCpy(str, 0, buf);
\r
2456 void TrimLeft(char *str)
\r
2466 len = StrLen(str);
\r
2471 if (str[0] != ' ' && str[0] != '\t')
\r
2476 buf = Malloc(len + 1);
\r
2479 for (i = 0;i < len;i++)
\r
2481 if (str[i] != ' ' && str[i] != '\t')
\r
2487 buf[wp++] = str[i];
\r
2491 StrCpy(str, 0, buf);
\r
2495 // 整数を 16 進文字列に変換 (8桁固定)
\r
2496 void ToStrx8(char *str, UINT i)
\r
2498 sprintf(str, "0x%08x", i);
\r
2502 void ToStrx(char *str, UINT i)
\r
2504 sprintf(str, "0x%02x", i);
\r
2508 void ToStri(char *str, int i)
\r
2510 sprintf(str, "%i", i);
\r
2514 void ToStr(char *str, UINT i)
\r
2516 sprintf(str, "%u", i);
\r
2520 int ToInti(char *str)
\r
2528 return (int)ToInt(str);
\r
2532 bool ToBool(char *str)
\r
2534 char tmp[MAX_SIZE];
\r
2541 StrCpy(tmp, sizeof(tmp), str);
\r
2544 if (IsEmptyStr(tmp))
\r
2549 if (ToInt(tmp) != 0)
\r
2554 if (StartWith("true", tmp))
\r
2559 if (StartWith("yes", tmp))
\r
2564 if (StartWith(tmp, "true"))
\r
2569 if (StartWith(tmp, "yes"))
\r
2578 UINT ToInt(char *str)
\r
2593 if ((*(str + 1) == 'x') || (*(str + 1) == 'X'))
\r
2600 return (UINT)strtoul(str, NULL, 0);
\r
2603 // 64bit 整数のためのフォーマット文字列を置換する
\r
2604 char *ReplaceFormatStringFor64(char *fmt)
\r
2615 tmp_size = StrSize(fmt) * 2;
\r
2616 tmp = ZeroMalloc(tmp_size);
\r
2619 ReplaceStrEx(tmp, tmp_size, fmt, "%ll", "%I64", false);
\r
2621 ReplaceStrEx(tmp, tmp_size, fmt, "%I64", "%ll", false);
\r
2622 #endif // OS_WIN32
\r
2624 ret = CopyStr(tmp);
\r
2631 void PrintStr(char *str)
\r
2633 wchar_t *unistr = NULL;
\r
2641 fputs(str, stdout);
\r
2643 unistr = CopyStrToUni(str);
\r
2644 UniPrintStr(unistr);
\r
2650 void PrintArgs(char *fmt, va_list args)
\r
2653 wchar_t *fmt_wchar;
\r
2661 fmt_wchar = CopyStrToUni(fmt);
\r
2662 ret = InternalFormatArgs(fmt_wchar, args, true);
\r
2664 tmp = CopyUniToStr(ret);
\r
2673 void Print(char *fmt, ...)
\r
2681 va_start(args, fmt);
\r
2682 PrintArgs(fmt, args);
\r
2686 // デバッグ文字列を引数付きで表示する
\r
2687 void DebugArgs(char *fmt, va_list args)
\r
2694 if (g_debug == false)
\r
2699 PrintArgs(fmt, args);
\r
2703 void Debug(char *fmt, ...)
\r
2711 if (g_debug == false)
\r
2716 va_start(args, fmt);
\r
2718 DebugArgs(fmt, args);
\r
2723 // 文字列をフォーマットして結果を返す
\r
2724 char *CopyFormat(char *fmt, ...)
\r
2736 size = MAX(StrSize(fmt) * 10, MAX_SIZE * 10);
\r
2737 buf = Malloc(size);
\r
2739 va_start(args, fmt);
\r
2740 FormatArgs(buf, size, fmt, args);
\r
2742 ret = CopyStr(buf);
\r
2750 void Format(char *buf, UINT size, char *fmt, ...)
\r
2754 if (buf == NULL || fmt == NULL)
\r
2759 va_start(args, fmt);
\r
2760 FormatArgs(buf, size, fmt, args);
\r
2764 // 文字列をフォーマットする (引数リスト)
\r
2765 void FormatArgs(char *buf, UINT size, char *fmt, va_list args)
\r
2770 if (buf == NULL || fmt == NULL)
\r
2775 tag = CopyStrToUni(fmt);
\r
2776 ret = InternalFormatArgs(tag, args, true);
\r
2778 UniToStr(buf, size, ret);
\r
2783 // 文字列を大文字・小文字を区別せずに比較する
\r
2784 int StrCmpi(char *str1, char *str2)
\r
2788 if (str1 == NULL && str2 == NULL)
\r
2806 c1 = ToUpper(str1[i]);
\r
2807 c2 = ToUpper(str2[i]);
\r
2816 if (str1[i] == 0 || str2[i] == 0)
\r
2825 int StrCmp(char *str1, char *str2)
\r
2828 if (str1 == NULL && str2 == NULL)
\r
2841 return strcmp(str1, str2);
\r
2845 void StrLower(char *str)
\r
2854 len = StrLen(str);
\r
2855 for (i = 0;i < len;i++)
\r
2857 str[i] = ToLower(str[i]);
\r
2862 void StrUpper(char *str)
\r
2871 len = StrLen(str);
\r
2872 for (i = 0;i < len;i++)
\r
2874 str[i] = ToUpper(str[i]);
\r
2879 char ToLower(char c)
\r
2881 if ('A' <= c && c <= 'Z')
\r
2889 char ToUpper(char c)
\r
2891 if ('a' <= c && c <= 'z')
\r
2899 UINT StrCat(char *dst, UINT size, char *src)
\r
2901 UINT len1, len2, len_test;
\r
2903 if (dst == NULL || src == NULL)
\r
2909 KS_INC(KS_STRCAT_COUNT);
\r
2914 size = 0x7fffffff;
\r
2917 len1 = StrLen(dst);
\r
2918 len2 = StrLen(src);
\r
2919 len_test = len1 + len2 + 1;
\r
2920 if (len_test > size)
\r
2922 if (len2 <= (len_test - size))
\r
2926 len2 -= len_test - size;
\r
2928 Copy(dst + len1, src, len2);
\r
2929 dst[len1 + len2] = 0;
\r
2931 return len1 + len2;
\r
2933 UINT StrCatLeft(char *dst, UINT size, char *src)
\r
2937 if (dst == NULL || src == NULL)
\r
2943 StrCpy(dst, size, src);
\r
2944 StrCat(dst, size, s);
\r
2948 return StrLen(dst);
\r
2952 UINT StrCpy(char *dst, UINT size, char *src)
\r
2958 return StrLen(src);
\r
2960 if (dst == NULL || src == NULL)
\r
2962 if (src == NULL && dst != NULL)
\r
2979 size = 0x7fffffff;
\r
2983 len = StrLen(src);
\r
2984 if (len <= (size - 1))
\r
2986 Copy(dst, src, len + 1);
\r
2991 Copy(dst, src, len);
\r
2996 KS_INC(KS_STRCPY_COUNT);
\r
3001 // 文字列バッファが指定されたサイズに収まっているかどうかを確認
\r
3002 bool StrCheckSize(char *str, UINT size)
\r
3005 if (str == NULL || size == 0)
\r
3010 return StrCheckLen(str, size - 1);
\r
3013 // 文字列が指定された長さ以内であることを確認
\r
3014 bool StrCheckLen(char *str, UINT len)
\r
3025 KS_INC(KS_STRCHECK_COUNT);
\r
3029 if (str[i] == '\0')
\r
3041 // 文字列を格納するために必要なメモリサイズを取得
\r
3042 UINT StrSize(char *str)
\r
3050 return StrLen(str) + 1;
\r
3054 UINT StrLen(char *str)
\r
3063 KS_INC(KS_STRLEN_COUNT);
\r
3065 return (UINT)strlen(str);
\r