void ChmDoc::FixPathCodepage(AutoFree& path, UINT& fileCP) { if (!path || HasData(path)) return; AutoFree utf8Path(ToUtf8((unsigned char*)path.Get())); if (HasData(utf8Path)) { path.Set(utf8Path.StealData()); fileCP = codepage; } else if (fileCP != codepage) { utf8Path.Set(ToUtf8((unsigned char*)path.Get(), fileCP)); if (HasData(utf8Path)) { path.Set(utf8Path.StealData()); codepage = fileCP; } } }
void HtmlPrettyPrintTest() { size_t lenOut; AutoFree data; data.Set(PrettyPrintHtml("<p><b>Test</b></p>", (size_t)-1, lenOut)); utassert(str::Len(data) == lenOut && str::Eq(data, "<p><b>Test</b></p>\n")); data.Set(PrettyPrintHtml("<p><b>Test</p>", (size_t)-1, lenOut)); utassert(str::Len(data) == lenOut && str::Eq(data, "<p><b>Test</p>\n")); data.Set(PrettyPrintHtml("<html><body><p>Content</p></body></html>", (size_t)-1, lenOut)); utassert(str::Len(data) == lenOut && str::Eq(data, "<html>\n\t<body>\n\t\t<p>Content</p>\n\t</body>\n</html>\n")); data.Set(PrettyPrintHtml("<html><body><p>Content</html></body>", (size_t)-1, lenOut)); // TODO: add newline before non-matching </html> ? // TODO: insert missing closing tags (</p> and </body>)? utassert(str::Len(data) == lenOut && str::Eq(data, "<html>\n\t<body>\n\t\t<p>Content</html>\n</body>\n")); data.Set(PrettyPrintHtml("<p attr=' value '><b> bold text </b> </p>", (size_t)-1, lenOut)); // TODO: normalize whitespace? utassert(str::Len(data) == lenOut && str::Eq(data, "<p attr=' value '><b> bold text </b></p>\n")); }
bool ChmDoc::HasData(const char* fileName) { if (!fileName) return nullptr; AutoFree tmpName; if (!str::StartsWith(fileName, "/")) { tmpName.Set(str::Join("/", fileName)); fileName = tmpName; } else if (str::StartsWith(fileName, "///")) fileName += 2; struct chmUnitInfo info; return chm_resolve_object(chmHandle, fileName, &info) == CHM_RESOLVE_SUCCESS; }
unsigned char* ChmDoc::GetData(const char* fileName, size_t* lenOut) { AutoFree fileNameTmp; if (!str::StartsWith(fileName, "/")) { fileNameTmp.Set(str::Join("/", fileName)); fileName = fileNameTmp; } else if (str::StartsWith(fileName, "///")) { fileName += 2; } struct chmUnitInfo info; int res = chm_resolve_object(chmHandle, fileName, &info); if (CHM_RESOLVE_SUCCESS != res && str::FindChar(fileName, '\\')) { // Microsoft's HTML Help CHM viewer tolerates backslashes in URLs fileNameTmp.SetCopy(fileName); str::TransChars(fileNameTmp, "\\", "/"); fileName = fileNameTmp; res = chm_resolve_object(chmHandle, fileName, &info); } if (CHM_RESOLVE_SUCCESS != res) return nullptr; size_t len = (size_t)info.length; if (len > 128 * 1024 * 1024) { // don't allow anything above 128 MB return nullptr; } // +1 for 0 terminator for C string compatibility ScopedMem<unsigned char> data((unsigned char*)malloc(len + 1)); if (!data) return nullptr; if (!chm_retrieve_object(chmHandle, &info, data.Get(), 0, len)) return nullptr; data[len] = '\0'; if (lenOut) *lenOut = len; return data.StealData(); }