Loading editor/src/htmlimport.cpp +39 −4 Changes for editor/src/htmlimport.cpp: 39 added lines, 4 removed lines. Original line number Diff line number Diff line Loading @@ -1571,10 +1571,32 @@ bool blogi::htmlimport::convertHtmlToWidgetXml(const std::string &html, // globalJs (inline <script> blocks, with no src, are left untouched). const int kMaxExternalStylesheets = 10; const size_t kMaxStylesheetBytes = 3 * 1024 * 1024; // Cumulative cap across ALL fetched stylesheets combined, independent of // the per-sheet/count caps above: a real page-builder site can easily // have 10 stylesheets a few hundred KB each, and the resulting page-level // CSS is still something a browser renders fine. Kept far more generous // than the JS budget below since CSS failing to apply is silently // degraded styling, not a broken/oversized response. const size_t kMaxTotalCssBytes = 2 * 1024 * 1024; int externalCssSeen = 0; size_t totalCssBytes = 0; const int kMaxExternalScripts = 10; const size_t kMaxScriptBytes = 5 * 1024 * 1024; // Cumulative cap across ALL fetched scripts combined: unlike CSS, a // fetched external script's contents get inlined into the final page's // GlobalJs verbatim and executed as-is (see webedit_api.cpp's // handleImportHtml/renderTree) -- but it was written for the ORIGINAL // page's DOM, not blogi's widget-rendered version of it, so it's already // unlikely to do anything useful, and a large bundle (a full framework // runtime, analytics, etc.) only adds risk (uncaught errors breaking the // rest of the inlined script) and response size for no real benefit. // Confirmed against a real site: 9 external scripts (including a full // React build) totalling 2.7MB inlined this way correlated with preview/ // publish requests failing outright, likely from the resulting multi-MB // response tripping something size-related downstream -- so this is // capped much tighter than the per-script/stylesheet budgets above. const size_t kMaxTotalJsBytes = 300 * 1024; int externalJsSeen = 0; std::string globalJs; Loading @@ -1592,7 +1614,7 @@ bool blogi::htmlimport::convertHtmlToWidgetXml(const std::string &html, src.compare(0, 8, "https://") == 0; if (isAbsolute) { if (externalJsSeen >= kMaxExternalScripts) { if (externalJsSeen >= kMaxExternalScripts || globalJs.size() >= kMaxTotalJsBytes) { if (outStats) outStats->jsFailed++; } else { externalJsSeen++; Loading @@ -1602,7 +1624,15 @@ bool blogi::htmlimport::convertHtmlToWidgetXml(const std::string &html, try { std::vector<std::uint8_t> bytes; std::string fetchError; if (fetchExternalResource(src, kMaxScriptBytes, "", // Cap THIS fetch to whatever's left of the total // JS budget, not just the flat per-script cap -- // otherwise a single large script fetched while // still under budget (e.g. the first one) could // blow straight past kMaxTotalJsBytes in one go, // and only later scripts would actually get // rejected by the size check above. size_t remainingBudget = kMaxTotalJsBytes - globalJs.size(); if (fetchExternalResource(src, std::min(kMaxScriptBytes, remainingBudget), "", bytes, fetchError)) { if (!globalJs.empty()) globalJs += "\n;\n"; globalJs.append(bytes.begin(), bytes.end()); Loading Loading @@ -1657,7 +1687,7 @@ bool blogi::htmlimport::convertHtmlToWidgetXml(const std::string &html, href.compare(0, 8, "https://") == 0; if (rel.find("stylesheet") != std::string::npos && isAbsolute) { if (externalCssSeen >= kMaxExternalStylesheets) { if (externalCssSeen >= kMaxExternalStylesheets || totalCssBytes >= kMaxTotalCssBytes) { if (outStats) outStats->cssFailed++; } else { externalCssSeen++; Loading @@ -1669,8 +1699,13 @@ bool blogi::htmlimport::convertHtmlToWidgetXml(const std::string &html, try { std::vector<std::uint8_t> bytes; std::string fetchError; if (fetchExternalResource(href, kMaxStylesheetBytes, // See the analogous JS budget comment above: // cap this fetch to what's left of the total // CSS budget, not just the flat per-sheet cap. size_t remainingBudget = kMaxTotalCssBytes - totalCssBytes; if (fetchExternalResource(href, std::min(kMaxStylesheetBytes, remainingBudget), "text/css", bytes, fetchError)) { totalCssBytes += bytes.size(); std::string cssText(bytes.begin(), bytes.end()); // This sheet's own url(...) references are // relative to ITS location (href), not the Loading Loading
editor/src/htmlimport.cpp +39 −4 Changes for editor/src/htmlimport.cpp: 39 added lines, 4 removed lines. Original line number Diff line number Diff line Loading @@ -1571,10 +1571,32 @@ bool blogi::htmlimport::convertHtmlToWidgetXml(const std::string &html, // globalJs (inline <script> blocks, with no src, are left untouched). const int kMaxExternalStylesheets = 10; const size_t kMaxStylesheetBytes = 3 * 1024 * 1024; // Cumulative cap across ALL fetched stylesheets combined, independent of // the per-sheet/count caps above: a real page-builder site can easily // have 10 stylesheets a few hundred KB each, and the resulting page-level // CSS is still something a browser renders fine. Kept far more generous // than the JS budget below since CSS failing to apply is silently // degraded styling, not a broken/oversized response. const size_t kMaxTotalCssBytes = 2 * 1024 * 1024; int externalCssSeen = 0; size_t totalCssBytes = 0; const int kMaxExternalScripts = 10; const size_t kMaxScriptBytes = 5 * 1024 * 1024; // Cumulative cap across ALL fetched scripts combined: unlike CSS, a // fetched external script's contents get inlined into the final page's // GlobalJs verbatim and executed as-is (see webedit_api.cpp's // handleImportHtml/renderTree) -- but it was written for the ORIGINAL // page's DOM, not blogi's widget-rendered version of it, so it's already // unlikely to do anything useful, and a large bundle (a full framework // runtime, analytics, etc.) only adds risk (uncaught errors breaking the // rest of the inlined script) and response size for no real benefit. // Confirmed against a real site: 9 external scripts (including a full // React build) totalling 2.7MB inlined this way correlated with preview/ // publish requests failing outright, likely from the resulting multi-MB // response tripping something size-related downstream -- so this is // capped much tighter than the per-script/stylesheet budgets above. const size_t kMaxTotalJsBytes = 300 * 1024; int externalJsSeen = 0; std::string globalJs; Loading @@ -1592,7 +1614,7 @@ bool blogi::htmlimport::convertHtmlToWidgetXml(const std::string &html, src.compare(0, 8, "https://") == 0; if (isAbsolute) { if (externalJsSeen >= kMaxExternalScripts) { if (externalJsSeen >= kMaxExternalScripts || globalJs.size() >= kMaxTotalJsBytes) { if (outStats) outStats->jsFailed++; } else { externalJsSeen++; Loading @@ -1602,7 +1624,15 @@ bool blogi::htmlimport::convertHtmlToWidgetXml(const std::string &html, try { std::vector<std::uint8_t> bytes; std::string fetchError; if (fetchExternalResource(src, kMaxScriptBytes, "", // Cap THIS fetch to whatever's left of the total // JS budget, not just the flat per-script cap -- // otherwise a single large script fetched while // still under budget (e.g. the first one) could // blow straight past kMaxTotalJsBytes in one go, // and only later scripts would actually get // rejected by the size check above. size_t remainingBudget = kMaxTotalJsBytes - globalJs.size(); if (fetchExternalResource(src, std::min(kMaxScriptBytes, remainingBudget), "", bytes, fetchError)) { if (!globalJs.empty()) globalJs += "\n;\n"; globalJs.append(bytes.begin(), bytes.end()); Loading Loading @@ -1657,7 +1687,7 @@ bool blogi::htmlimport::convertHtmlToWidgetXml(const std::string &html, href.compare(0, 8, "https://") == 0; if (rel.find("stylesheet") != std::string::npos && isAbsolute) { if (externalCssSeen >= kMaxExternalStylesheets) { if (externalCssSeen >= kMaxExternalStylesheets || totalCssBytes >= kMaxTotalCssBytes) { if (outStats) outStats->cssFailed++; } else { externalCssSeen++; Loading @@ -1669,8 +1699,13 @@ bool blogi::htmlimport::convertHtmlToWidgetXml(const std::string &html, try { std::vector<std::uint8_t> bytes; std::string fetchError; if (fetchExternalResource(href, kMaxStylesheetBytes, // See the analogous JS budget comment above: // cap this fetch to what's left of the total // CSS budget, not just the flat per-sheet cap. size_t remainingBudget = kMaxTotalCssBytes - totalCssBytes; if (fetchExternalResource(href, std::min(kMaxStylesheetBytes, remainingBudget), "text/css", bytes, fetchError)) { totalCssBytes += bytes.size(); std::string cssText(bytes.begin(), bytes.end()); // This sheet's own url(...) references are // relative to ITS location (href), not the Loading