@@ -1671,7 +1671,6 @@ FileServerRequestHandler::ResourceAccessDetails FileServerRequestHandler::prepro
1671
1671
std::string userInterfaceMode;
1672
1672
std::string userInterfaceTheme;
1673
1673
std::string savedUIState = " true" ;
1674
- const std::string& theme = urv[BRANDING_THEME];
1675
1674
1676
1675
Poco::replaceInPlace (preprocess, ACCESS_TOKEN, urv[ACCESS_TOKEN]);
1677
1676
Poco::replaceInPlace (preprocess, ACCESS_TOKEN_TTL, urv[ACCESS_TOKEN_TTL]);
@@ -1710,31 +1709,8 @@ FileServerRequestHandler::ResourceAccessDetails FileServerRequestHandler::prepro
1710
1709
config.getBool (" user_interface.statusbar_save_indicator" , false ) ? " true" : " false" ;
1711
1710
Poco::replaceInPlace (preprocess, std::string (" %STATUSBAR_SAVE_INDICATOR%" ), useStatusbarSaveIndicator);
1712
1711
1713
- static const bool useIntegrationTheme =
1714
- config.getBool (" user_interface.use_integration_theme" , true );
1715
- const bool hasIntegrationTheme =
1716
- !theme.empty () &&
1717
- FileUtil::Stat (COOLWSD::FileServerRoot + " /browser/dist/" + theme).exists ();
1718
- const std::string themePreFix = hasIntegrationTheme && useIntegrationTheme ? theme + " /" : " " ;
1719
- const std::string linkCSS (" <link rel=\" stylesheet\" href=\" %s/browser/" COOLWSD_VERSION_HASH " /" + themePreFix + " %s.css\" >" );
1720
- const std::string scriptJS (" <script src=\" %s/browser/" COOLWSD_VERSION_HASH " /" + themePreFix + " %s.js\" ></script>" );
1721
-
1722
- std::string brandCSS (Poco::format (linkCSS, responseRoot, std::string (BRANDING)));
1723
- std::string brandJS (Poco::format (scriptJS, responseRoot, std::string (BRANDING)));
1724
-
1725
- if constexpr (ConfigUtil::isSupportKeyEnabled ())
1726
- {
1727
- const std::string keyString = config.getString (" support_key" , " " );
1728
- SupportKey key (keyString);
1729
- if (!key.verify () || key.validDaysRemaining () <= 0 )
1730
- {
1731
- brandCSS = Poco::format (linkCSS, responseRoot, std::string (SUPPORT_KEY_BRANDING_UNSUPPORTED));
1732
- brandJS = Poco::format (scriptJS, responseRoot, std::string (SUPPORT_KEY_BRANDING_UNSUPPORTED));
1733
- }
1734
- }
1712
+ updateThemeResources (preprocess, responseRoot, urv[BRANDING_THEME], config);
1735
1713
1736
- Poco::replaceInPlace (preprocess, std::string (" <!--%BRANDING_CSS%-->" ), brandCSS);
1737
- Poco::replaceInPlace (preprocess, std::string (" <!--%BRANDING_JS%-->" ), brandJS);
1738
1714
Poco::replaceInPlace (preprocess, CSS_VARS, cssVarsToStyle (urv[CSS_VARS]));
1739
1715
1740
1716
if (config.getBool (" browser_logging" , false ))
@@ -1803,9 +1779,6 @@ FileServerRequestHandler::ResourceAccessDetails FileServerRequestHandler::prepro
1803
1779
uiRtlSettings = " dir=\" rtl\" " ;
1804
1780
Poco::replaceInPlace (preprocess, std::string (" %UI_RTL_SETTINGS%" ), uiRtlSettings);
1805
1781
1806
- const std::string useIntegrationThemeString = useIntegrationTheme && hasIntegrationTheme ? " true" : " false" ;
1807
- Poco::replaceInPlace (preprocess, std::string (" %USE_INTEGRATION_THEME%" ), useIntegrationThemeString);
1808
-
1809
1782
std::string enableMacrosExecution = stringifyBoolFromConfig (config, " security.enable_macros_execution" , false );
1810
1783
Poco::replaceInPlace (preprocess, std::string (" %ENABLE_MACROS_EXECUTION%" ), enableMacrosExecution);
1811
1784
@@ -2365,6 +2338,7 @@ void FileServerRequestHandler::preprocessIntegratorAdminFile(const HTTPRequest&
2365
2338
{
2366
2339
const ServerURL cnxDetails (requestDetails);
2367
2340
const std::string responseRoot = cnxDetails.getResponseRoot ();
2341
+ const auto & config = Application::instance ().config ();
2368
2342
2369
2343
static const std::string scriptJS (" <script src=\" %s/browser/" COOLWSD_VERSION_HASH " /%s.js\" ></script>" );
2370
2344
static const std::string footerPage (" <footer class=\" footer has-text-centered\" ><strong>Key:</strong> %s <strong>Expiry Date:</strong> %s</footer>" );
@@ -2391,23 +2365,8 @@ void FileServerRequestHandler::preprocessIntegratorAdminFile(const HTTPRequest&
2391
2365
Poco::replaceInPlace (adminFile, std::string (" %ENABLE_DEBUG%" ),
2392
2366
std::string (enableDebug ? " true" : " false" ));
2393
2367
2394
- std::string brandJS (Poco::format (scriptJS, responseRoot, std::string (BRANDING)));
2395
- std::string brandFooter;
2368
+ updateThemeResources (adminFile, responseRoot, urv[BRANDING_THEME], config);
2396
2369
2397
- if constexpr (ConfigUtil::isSupportKeyEnabled ())
2398
- {
2399
- const auto & config = Application::instance ().config ();
2400
- const std::string keyString = config.getString (" support_key" , " " );
2401
- SupportKey key (keyString);
2402
-
2403
- if (!key.verify () || key.validDaysRemaining () <= 0 )
2404
- {
2405
- brandJS = Poco::format (scriptJS, std::string (SUPPORT_KEY_BRANDING_UNSUPPORTED));
2406
- brandFooter = Poco::format (footerPage, key.data (), Poco::DateTimeFormatter::format (key.expiry (), Poco::DateTimeFormat::RFC822_FORMAT));
2407
- }
2408
- }
2409
-
2410
- Poco::replaceInPlace (adminFile, std::string (" <!--%BRANDING_JS%-->" ), brandJS);
2411
2370
Poco::replaceInPlace (adminFile, std::string (" %VERSION%" ), std::string (COOLWSD_VERSION_HASH));
2412
2371
Poco::replaceInPlace (adminFile, std::string (" %SERVICE_ROOT%" ), responseRoot);
2413
2372
@@ -2424,18 +2383,14 @@ void FileServerRequestHandler::preprocessIntegratorAdminFile(const HTTPRequest&
2424
2383
csp.appendDirectiveUrl (" connect-src" , cnxDetails.getWebServerUrl ());
2425
2384
csp.appendDirective (" img-src" , " 'self'" );
2426
2385
csp.appendDirective (" img-src" , " data:" ); // Equivalent to unsafe-inline!
2427
-
2428
2386
csp.appendDirective (" worker-src" , " 'self' blob:" );
2429
2387
2430
- const auto & config = Application::instance ().config ();
2431
2388
csp.merge (config.getString (" net.content_security_policy" , " " ));
2432
2389
2433
2390
response.add (" Content-Security-Policy" , csp.generate ());
2434
-
2435
2391
response.set (" Last-Modified" , Util::getHttpTimeNow ());
2436
2392
response.set (" Cache-Control" , " max-age=11059200" );
2437
2393
response.set (" ETag" , COOLWSD_VERSION_HASH);
2438
-
2439
2394
response.add (" X-Content-Type-Options" , " nosniff" );
2440
2395
response.add (" X-XSS-Protection" , " 1; mode=block" );
2441
2396
response.add (" Referrer-Policy" , " no-referrer" );
@@ -2445,7 +2400,6 @@ void FileServerRequestHandler::preprocessIntegratorAdminFile(const HTTPRequest&
2445
2400
LOG_TRC (" Sent file: " << relPath << " : " << response.getBody ());
2446
2401
}
2447
2402
2448
-
2449
2403
void FileServerRequestHandler::preprocessAdminFile (const HTTPRequest& request,
2450
2404
http::Response& response,
2451
2405
const RequestDetails& requestDetails,
@@ -2538,4 +2492,56 @@ void FileServerRequestHandler::preprocessAdminFile(const HTTPRequest& request,
2538
2492
socket->send (response);
2539
2493
}
2540
2494
2495
+ static std::string sanitizeTheme (const std::string& theme)
2496
+ {
2497
+ std::string safeTheme = theme;
2498
+ safeTheme.erase (
2499
+ std::remove_if (
2500
+ safeTheme.begin (), safeTheme.end (), [](char c)
2501
+ { return !(std::isalnum (static_cast <unsigned char >(c)) || c == ' _' || c == ' -' ); }),
2502
+ safeTheme.end ());
2503
+ return safeTheme;
2504
+ }
2505
+
2506
+ void FileServerRequestHandler::updateThemeResources (std::string& fileContent,
2507
+ const std::string& responseRoot,
2508
+ const std::string& theme,
2509
+ const Poco::Util::AbstractConfiguration& config)
2510
+ {
2511
+ static const bool useIntegrationTheme =
2512
+ config.getBool (" user_interface.use_integration_theme" , true );
2513
+
2514
+ std::string safeThemeStr = sanitizeTheme (theme);
2515
+ const bool hasIntegrationTheme =
2516
+ !safeThemeStr.empty () &&
2517
+ FileUtil::Stat (COOLWSD::FileServerRoot + " /browser/dist/" + safeThemeStr).exists ();
2518
+
2519
+ const std::string themePrefix = hasIntegrationTheme && useIntegrationTheme ? safeThemeStr + " /" : " " ;
2520
+ const std::string linkCSS = " <link rel=\" stylesheet\" href=\" " + responseRoot + " /browser/" +
2521
+ COOLWSD_VERSION_HASH + " /" + themePrefix + " %s.css\" >" ;
2522
+ const std::string themeScriptJS = " <script src=\" " + responseRoot + " /browser/" +
2523
+ COOLWSD_VERSION_HASH + " /" + themePrefix +
2524
+ " %s.js\" ></script>" ;
2525
+
2526
+ std::string brandCSS = Poco::format (linkCSS, std::string (BRANDING));
2527
+ std::string brandJS = Poco::format (themeScriptJS, std::string (BRANDING));
2528
+
2529
+ if constexpr (ConfigUtil::isSupportKeyEnabled ())
2530
+ {
2531
+ const std::string keyString = config.getString (" support_key" , " " );
2532
+ SupportKey key (keyString);
2533
+ if (!key.verify () || key.validDaysRemaining () <= 0 )
2534
+ {
2535
+ brandCSS = Poco::format (linkCSS, std::string (SUPPORT_KEY_BRANDING_UNSUPPORTED));
2536
+ brandJS = Poco::format (themeScriptJS, std::string (SUPPORT_KEY_BRANDING_UNSUPPORTED));
2537
+ }
2538
+ }
2539
+
2540
+ Poco::replaceInPlace (fileContent, std::string (" <!--%BRANDING_CSS%-->" ), brandCSS);
2541
+ Poco::replaceInPlace (fileContent, std::string (" <!--%BRANDING_JS%-->" ), brandJS);
2542
+
2543
+ const std::string useIntegrationThemeString = useIntegrationTheme && hasIntegrationTheme ? " true" : " false" ;
2544
+ Poco::replaceInPlace (fileContent, std::string (" %USE_INTEGRATION_THEME%" ), useIntegrationThemeString);
2545
+ }
2546
+
2541
2547
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
0 commit comments