svvitch
digital signage player
|
00001 #include "Utils.h" 00002 00003 #include <algorithm> 00004 #include <fstream> 00005 #include <iostream> 00006 #include <vector> 00007 #include <set> 00008 #include <Poco/Buffer.h> 00009 #include <Poco/MD5Engine.h> 00010 #include <Poco/DigestStream.h> 00011 #include <Poco/File.h> 00012 #include <Poco/FileStream.h> 00013 #include <Poco/Logger.h> 00014 #include <Poco/format.h> 00015 #include <Poco/string.h> 00016 #include <Poco/StreamCopier.h> 00017 #include <Poco/UnicodeConverter.h> 00018 #include <Poco/RegularExpression.h> 00019 #include <Poco/NumberParser.h> 00020 00021 using std::copy; 00022 using std::set; 00023 using std::sort; 00024 using std::vector; 00025 using Poco::DigestEngine; 00026 using Poco::File; 00027 using Poco::MD5Engine; 00028 using Poco::DigestOutputStream; 00029 using Poco::StreamCopier; 00030 00031 00032 const string svvitch::version() { 00033 return "1.10"; 00034 } 00035 00036 bool svvitch::readFile(const string& fileName, LPVOID* ref) { 00037 Poco::Logger& log(Poco::Logger::get("")); 00038 // dicファイルの読込み 00039 try { 00040 File file(fileName); 00041 if (file.exists()) { 00042 Poco::FileInputStream is(file.path()); 00043 if (is.good()) { 00044 LPBYTE buf = new BYTE[(UINT)file.getSize()]; 00045 ZeroMemory(buf, (UINT)file.getSize()); 00046 #define BUFFER_SIZE (8192) 00047 Poco::Buffer<char> buffer(BUFFER_SIZE); 00048 std::streamsize len = 0; 00049 is.read(buffer.begin(), BUFFER_SIZE); 00050 std::streamsize n = is.gcount(); 00051 while (n > 0) { 00052 CopyMemory(&buf[len], buffer.begin(), n); 00053 len += n; 00054 if (is) { 00055 is.read(buffer.begin(), BUFFER_SIZE); 00056 n = is.gcount(); 00057 } 00058 else n = 0; 00059 } 00060 is.close(); 00061 log.information(Poco::format("load file size: %d", len)); 00062 *ref = (LPVOID)buf; 00063 return true; 00064 } else { 00065 log.warning(Poco::format("failed not read file: %s", file.path())); 00066 } 00067 } else { 00068 log.warning(Poco::format("file not found: %s", file.path())); 00069 } 00070 } catch (Poco::IOException& ex) { 00071 log.warning(Poco::format("failed read file: %s", ex.displayText())); 00072 } 00073 return false; 00074 } 00075 00076 void svvitch::sjis_utf8(const string& in, string& out) { 00077 wstring wstring; 00078 sjis_utf16(in, wstring); 00079 Poco::UnicodeConverter::toUTF8(wstring, out); 00080 } 00081 00082 void svvitch::sjis_utf16(const string& in, wstring& out) { 00083 int len = ::MultiByteToWideChar(CP_ACP, 0, in.c_str(), -1, NULL, 0); 00084 if (len > 0) { 00085 vector<wchar_t> utf16(len); 00086 if (::MultiByteToWideChar(CP_ACP, 0, in.c_str(), -1, &utf16[0], len)) { 00087 out = &utf16[0]; 00088 } 00089 utf16.clear(); 00090 } else { 00091 out = L""; 00092 } 00093 } 00094 00095 00096 void svvitch::utf16_sjis(const wstring& wstr, string& out) { 00097 int len = ::WideCharToMultiByte(CP_ACP, 0, wstr.c_str(), -1, NULL, 0, NULL, NULL); 00098 if (len > 0) { 00099 vector<char> sjis(len); 00100 if (::WideCharToMultiByte(CP_ACP, 0, wstr.c_str(), -1, &sjis[0], len, NULL, NULL)) { 00101 out = &sjis[0]; 00102 } 00103 sjis.clear(); 00104 } else { 00105 out.clear(); 00106 } 00107 } 00108 00109 00110 void svvitch::utf8_sjis(const string& str, string& out) { 00111 std::wstring wstr; 00112 // UTF-8をUTF-16に変換 00113 Poco::UnicodeConverter::toUTF16(str, wstr); 00114 utf16_sjis(wstr, out); // UTF-16をシフトJISに変換 00115 } 00116 00117 00118 int svvitch::fileCount(const Path& path) { 00119 int count = 0; 00120 File dir(path); 00121 if (dir.isDirectory()) { 00122 vector<File> list; 00123 dir.list(list); 00124 for (vector<File>::iterator it = list.begin(); it != list.end(); it++) { 00125 File f = *it; 00126 if (f.isDirectory()) { 00127 count += fileCount(Path(f.path())); 00128 } else { 00129 count++; 00130 } 00131 } 00132 } else if (!dir.exists()) { 00133 count++; 00134 } 00135 return count; 00136 } 00137 00138 string svvitch::md5(const Path& path) { 00139 std::wstring wfile; 00140 Poco::UnicodeConverter::toUTF16(path.toString(), wfile); 00141 std::ifstream is(wfile.c_str(), std::ios::binary); 00142 if (is.good()) { 00143 MD5Engine md5; 00144 DigestOutputStream dos(md5); 00145 StreamCopier::copyStream(is, dos); 00146 dos.close(); 00147 return DigestEngine::digestToHex(md5.digest()); 00148 } 00149 return string(""); 00150 } 00151 00152 string svvitch::join(const vector<string>& v, const string& c) { 00153 string s; 00154 for (vector<string>::const_iterator p = v.begin(); p != v.end(); p++) { 00155 s += *p; 00156 if (p != v.end() -1) s += c; 00157 } 00158 return s; 00159 } 00160 00161 void svvitch::split(const string& s, char c, vector<string>& v, int splits) { 00162 string::size_type pos = 0; 00163 string::size_type j = s.find(c); 00164 00165 int count = 0; 00166 while (j != string::npos) { 00167 if (splits > 0 && (splits - 1) == count) { 00168 v.push_back(s.substr(pos)); 00169 break; 00170 } 00171 v.push_back(s.substr(pos, j - pos)); 00172 pos = ++j; 00173 j = s.find(c, j); 00174 00175 if (j == string::npos) v.push_back(s.substr(pos, s.length())); 00176 count++; 00177 } 00178 if (v.empty()) v.push_back(s); 00179 } 00180 00181 bool svvitch::parseMultiNumbers(const string& s, int min, int max, vector<int>& result) { 00182 Poco::Logger& log(Poco::Logger::get("")); 00183 set<int> num; 00184 vector<string> datas; 00185 split(s, ',', datas); // カンマを区切る 00186 for (vector<string>::const_iterator p = datas.begin(); p != datas.end(); p++) { 00187 string data = Poco::trim(*p); 00188 if (!data.empty()) { 00189 if (data[0] == '-') { 00190 // 開始省略範囲 00191 int n; 00192 if (Poco::NumberParser::tryParse(Poco::trim(data.substr(1)), n)) { 00193 for (int i = min; i <= n; i++) num.insert(i); 00194 } else { 00195 log.warning(Poco::format("parse failed: %s", data)); 00196 return false; 00197 } 00198 00199 } else if (data[data.size() - 1] == '-') { 00200 // 終了省略範囲 00201 int n; 00202 if (Poco::NumberParser::tryParse(Poco::trim(data.substr(0, data.size() - 1)), n)) { 00203 for (int i = n; i <= max; i++) num.insert(i); 00204 } else { 00205 log.warning(Poco::format("parse failed: %s", data)); 00206 return false; 00207 } 00208 00209 } else if (data.find("-") != string::npos) { 00210 // 範囲指定 00211 int i = data.find("-"); 00212 int n1, n2; 00213 if (!Poco::NumberParser::tryParse(Poco::trim(data.substr(0, i)), n1) || n1 < min) { 00214 log.warning(Poco::format("parse failed: %s", data)); 00215 return false; 00216 } 00217 if (!Poco::NumberParser::tryParse(Poco::trim(data.substr(i + 1)), n2) || n2 > max) { 00218 log.warning(Poco::format("parse failed: %s", data)); 00219 return false; 00220 } 00221 for (int i = n1; i <= n2; i++) num.insert(i); 00222 00223 } else { 00224 // 単独数値 00225 int n = -1; 00226 if (Poco::NumberParser::tryParse(data, n) && (n >= min && n <= max)) { 00227 num.insert(n); 00228 } else { 00229 log.warning(Poco::format("parse failed: %s", data)); 00230 return false; 00231 } 00232 } 00233 } 00234 } 00235 for (set<int>::const_iterator p = num.begin(); p != num.end(); p++) result.push_back(*p); 00236 sort(result.begin(), result.end()); 00237 return true; 00238 } 00239 00240 string svvitch::formatJSON(const string& s) { 00241 if (!s.empty()) { 00242 int i = s.length() - 1; 00243 if (s.c_str()[0] == '[' && s.c_str()[i] == ']') { 00244 return s; 00245 } else if (s.c_str()[0] == '{' && s.c_str()[i] == '}') { 00246 return s; 00247 } 00248 string rep; 00249 for (i = 0; i < s.length(); ++i) { 00250 char c = s.at(i); 00251 if (c == '¥"') { 00252 rep.append("""); 00253 } else if (c == '¥¥') { 00254 rep.append("¥¥¥¥"); 00255 } else { 00256 rep += c; 00257 } 00258 } 00259 return "¥"" + rep + "¥""; 00260 } 00261 return "¥"¥""; 00262 } 00263 00264 string svvitch::formatJSON(const map<string, string>& obj) { 00265 vector<string> params; 00266 for (map<string, string>::const_iterator it = obj.begin(); it != obj.end(); it++) { 00267 params.push_back(Poco::format("¥"%s¥":%s", it->first, it->second)); 00268 } 00269 return Poco::format("{%s}", svvitch::join(params, ",")); 00270 } 00271 00272 string svvitch::formatJSONArray(const vector<string>& list) { 00273 vector<string> params; 00274 for (vector<string>::const_iterator it = list.begin(); it != list.end(); it++) { 00275 params.push_back(formatJSON(*it)); 00276 } 00277 return Poco::format("[%s]", svvitch::join(params, ",")); 00278 } 00279 00280 void svvitch::parseJSON(const string& json, map<string, string>& map) { 00281 string key; 00282 bool inText = false; 00283 int start = -1; 00284 int inArray = 0; 00285 int inMap = 0; 00286 string::size_type pos = 0; 00287 for (; json.length() > pos; pos++) { 00288 char c = json.at(pos); 00289 switch (c) { 00290 case '{': 00291 if (!inText) { 00292 // Mapブロック開始 00293 if (inMap == 1 && start == -1) { 00294 start = pos; 00295 } 00296 inMap++; 00297 } 00298 break; 00299 case '}': 00300 if (!inText) { 00301 // Mapブロック終了 00302 inMap--; 00303 if (inMap == 0 && start != -1) { 00304 if (!key.empty()) { 00305 string value = json.substr(start, pos - start); 00306 map[trimQuotationMark(key)] = trimQuotationMark(value); 00307 } 00308 } 00309 } 00310 break; 00311 case '[': 00312 if (!inText) { 00313 // arrayブロック開始 00314 if (inArray == 0 && start == -1) { 00315 // Textブロック開始 00316 start = pos; 00317 } 00318 inArray++; 00319 } 00320 break; 00321 case ']': 00322 if (!inText) { 00323 // arrayブロック終了 00324 inArray--; 00325 } 00326 break; 00327 case '¥"': 00328 if (inMap <= 1 && inArray == 0) { 00329 if (start != -1) { 00330 // Textブロック終了 00331 inText = false; 00332 } else { 00333 // Textブロック開始 00334 start = pos; 00335 inText = true; 00336 } 00337 } else { 00338 // arrayブロック内はスルー 00339 } 00340 break; 00341 case ':': 00342 if (!inText) { 00343 // キーブロック終了 00344 if (inMap <= 1 && inArray == 0) { 00345 if (start != -1) { 00346 key = json.substr(start, pos - start); 00347 start = -1; 00348 } 00349 } else { 00350 // arrayブロック内はスルー 00351 } 00352 } 00353 break; 00354 case ',': 00355 if (!inText) { 00356 // 値ブロック終了 00357 if (inMap <= 1 && inArray == 0) { 00358 if (inMap > 0 && !key.empty()) { 00359 string value = json.substr(start, pos - start); 00360 map[trimQuotationMark(key)] = trimQuotationMark(value); 00361 key.clear(); 00362 } 00363 start = -1; 00364 } else { 00365 // arrayブロック内はスルー 00366 } 00367 } 00368 break; 00369 case ' ': 00370 // 空白はスルー 00371 break; 00372 default: 00373 if (start == -1) { 00374 start = pos; 00375 } 00376 } 00377 } 00378 } 00379 00380 void svvitch::parseJSONArray(const string& json, vector<string>& v) { 00381 string key; 00382 int start = -1; 00383 int inArray = 0; 00384 string::size_type pos = 0; 00385 for (; json.length() > pos; pos++) { 00386 char c = json.at(pos); 00387 switch (c) { 00388 case '[': 00389 // arrayブロック開始 00390 inArray++; 00391 break; 00392 case ']': 00393 // arrayブロック終了 00394 inArray--; 00395 if (inArray == 0 && start != -1) { 00396 string value = json.substr(start, pos - start); 00397 v.push_back(trimQuotationMark(value)); 00398 } 00399 break; 00400 case '¥"': 00401 if (start != -1) { 00402 // Textブロック終了 00403 } else { 00404 // Textブロック開始 00405 start = pos; 00406 } 00407 break; 00408 case ',': 00409 // 値ブロック終了 00410 string value = json.substr(start, pos - start); 00411 v.push_back(trimQuotationMark(value)); 00412 start = -1; 00413 break; 00414 } 00415 } 00416 } 00417 00418 string svvitch::trimQuotationMark(const string& s) { 00419 char q = s.at(0); 00420 switch (q) { 00421 case '¥"': 00422 //case '[': 00423 //case '}': 00424 if (s.at(s.length() - 1) == q) { 00425 return s.substr(1, s.length() - 2); 00426 } 00427 } 00428 return s; 00429 } 00430 00431 string svvitch::findLastOfText(const string& src, const string& find) { 00432 string s; 00433 int i = src.find_last_of(find); 00434 if (i == string::npos) { 00435 s = src; 00436 } else { 00437 s = src.substr(i + 1); 00438 } 00439 return s; 00440 } 00441 00442 vector<int> svvitch::parseTimes(const string& timeText) { 00443 Poco::RegularExpression re("[¥¥s:/]+"); 00444 int pos = 0; 00445 Poco::RegularExpression::Match match; 00446 vector<int> time; 00447 while (re.match(timeText, pos, match) > 0) { 00448 string s = timeText.substr(pos, match.offset - pos); 00449 if (s == "*") { 00450 time.push_back(-1); 00451 } else { 00452 time.push_back(Poco::NumberParser::parse(s)); 00453 } 00454 pos = (match.offset + match.length); 00455 } 00456 string s = timeText.substr(pos); 00457 if (s == "*") { 00458 time.push_back(-1); 00459 } else { 00460 time.push_back(Poco::NumberParser::parse(s)); 00461 } 00462 return time; 00463 } 00464 00465 void svvitch::rebootWindows(BOOL shutdown, BOOL force) { 00466 HANDLE hToken; 00467 LUID Luid; 00468 HANDLE hProcess = GetCurrentProcess(); 00469 OpenProcessToken(hProcess, TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES, &hToken); 00470 LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME, &Luid); 00471 TOKEN_PRIVILEGES tokenNew, tokenPre; 00472 tokenNew.PrivilegeCount = 1; 00473 tokenNew.Privileges[0].Luid = Luid; 00474 tokenNew.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; 00475 DWORD ret; 00476 AdjustTokenPrivileges(hToken, FALSE, &tokenNew, sizeof(tokenPre), &tokenPre, &ret); 00477 00478 //case 1: uFlag = EWX_LOGOFF; break; 00479 //case 2: uFlag = EWX_POWEROFF; break; 00480 //case 3: uFlag = EWX_REBOOT; break; 00481 //case 4: uFlag = EWX_SHUTDOWN; break; 00482 UINT flag; 00483 if (shutdown) { 00484 // 電源OFF 00485 flag = EWX_POWEROFF; 00486 } else { 00487 // 再起動(default) 00488 flag = EWX_REBOOT; 00489 } 00490 if (force) { 00491 // プロセス強制終了 00492 flag |= EWX_FORCE; 00493 } 00494 ExitWindowsEx(flag, 0); 00495 }