#include #include #include #include "data.h" extern CfgA& g_cfg; extern FileView g_fvElv; extern FileView g_fvDlv; void OpenOnline(int iEp) { wchar_t url[sizeof(g_cfg.url)+4]; Swprintf(url, L"%s%d", g_cfg.url, iEp); INT_PTR r = reinterpret_cast( ShellExecute(nullptr, L"open", url, nullptr, nullptr, SW_SHOWNORMAL)); if (r <= 32) throw Win32Error(); } void OpenWiki(int iEp) { const DlvDataA& d = g_fvDlv.At(iEp-1); wchar_t url[sizeof(d.wiki)+35]; Swprintf(url, L"https://www.detectiveconanworld.com%s", d.wiki); INT_PTR r = reinterpret_cast( ShellExecute(nullptr, L"open", url, nullptr, nullptr, SW_SHOWNORMAL)); if (r <= 32) throw Win32Error(); } static inline bool MatchFileName(wchar_t (&file)[MAX_PATH], const wchar_t* const siEp) noexcept { /* This is a hand-written parser that matches file names of * the type "Detective Conan - 010.mkv". */ wchar_t* f = file; /* Match Detective Conan prefix. */ if (*f != L'D' && *f != L'd') return false; f++; if (wcsncmp(f, L"etective", 8) != 0) return false; f += 8; if (*f != L' ' && *f != L'_' && *f != L'-') return false; f++; if (*f != L'C' && *f != L'c') return false; f++; if (wcsncmp(f, L"onan", 4) != 0) return false; f += 4; /* Match garbage before episode number. */ while (*f == L' ' || *f == L'_' || *f == L'-' || *f == L'0') f++; /* Match episode number. */ size_t lenEp = wcslen(siEp); if (wcsncmp(f, siEp, lenEp) != 0) return false; f += lenEp; if (isdigit(*f)) return false; return true; } static bool FindMatchingFile(wchar_t (&file)[MAX_PATH], const wchar_t* const root, const wchar_t* const siEp, const int level = 0) { /* Don't recurse too much. */ if (level > 3) return false; wchar_t pat[MAX_PATH]; Swprintf(pat, L"%s\\*", root); WIN32_FIND_DATA fdata; HANDLE hf = FindFirstFile(pat, &fdata); if (hf == INVALID_HANDLE_VALUE) throw Win32Error().what(); do { if (fdata.cFileName[0] == L'.') continue; if (fdata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { /* Recurse into directory. */ wchar_t root2[MAX_PATH]; Swprintf(root2, L"%s\\%s", root, fdata.cFileName); try { if (FindMatchingFile(file, root2, siEp, level+1)) return true; } catch (...) { FindClose(hf); throw; } } else /* Try to match file name. */ if (MatchFileName(fdata.cFileName, siEp)) { Swprintf(file, L"%s\\%s", root, fdata.cFileName); return true; } } while (FindNextFile(hf, &fdata)); DWORD e = GetLastError(); FindClose(hf); if (e != ERROR_NO_MORE_FILES) throw Win32Error(e); return false; } bool OpenLocally(int iEp) { wchar_t file[MAX_PATH]; if (FindMatchingFile(file, g_cfg.root, g_fvElv.At(iEp-1).siEp)) { INT_PTR r = reinterpret_cast( ShellExecute(nullptr, L"open", file, nullptr, nullptr, SW_SHOWNORMAL)); if (r <= 32) throw Win32Error(); return true; } else return false; }