diff --git a/CMakeLists.txt b/CMakeLists.txt index a6c9952f7..0853ac0c2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -31,6 +31,7 @@ target_sources( cef-headers.hpp deps/base64/base64.cpp deps/base64/base64.hpp + deps/ip-string.hpp deps/signal-restore.cpp deps/signal-restore.hpp deps/wide-string.cpp diff --git a/browser-app.cpp b/browser-app.cpp index 5d2c4dc76..92fb32a02 100644 --- a/browser-app.cpp +++ b/browser-app.cpp @@ -50,7 +50,8 @@ CefRefPtr BrowserApp::GetBrowserProcessHandler() void BrowserApp::OnRegisterCustomSchemes(CefRawPtr registrar) { - registrar->AddCustomScheme("http", CEF_SCHEME_OPTION_STANDARD | CEF_SCHEME_OPTION_CORS_ENABLED); + registrar->AddCustomScheme("obsbrowser", CEF_SCHEME_OPTION_STANDARD | CEF_SCHEME_OPTION_CORS_ENABLED | + CEF_SCHEME_OPTION_FETCH_ENABLED); } void BrowserApp::OnBeforeChildProcessLaunch(CefRefPtr command_line) diff --git a/browser-scheme.cpp b/browser-scheme.cpp index c8d93697c..9591fc438 100644 --- a/browser-scheme.cpp +++ b/browser-scheme.cpp @@ -17,6 +17,7 @@ ******************************************************************************/ #include "browser-scheme.hpp" +#include "ip-string.hpp" #include "wide-string.hpp" #include @@ -41,18 +42,28 @@ CefRefPtr BrowserSchemeHandlerFactory::Create(CefRefPtr stream = CefStreamReader::CreateForFile(path.substr(1)); -#else - CefRefPtr stream = CefStreamReader::CreateForFile(path); -#endif - - if (stream) { - CefString mimeType = CefGetMimeType(fileExtension); - if (mimeType.empty()) - mimeType = "application/octet-stream"; - return new CefStreamResourceHandler(mimeType, stream); - } else { + std::string filePath = path.substr(path.find_first_not_of("/")); + std::string checkString = filePath.substr(0, filePath.find_first_of("/")); + + // An IP address should never be a valid path for CreateForFile normally, but in some cases an OS + // can resolve one as such. As an extra safeguard, we prevent any IP addresses in the path. + if (checkForIpv4String(checkString)) { + return nullptr; + } + + if (checkForIpv6String(checkString)) { + return nullptr; + } + + CefRefPtr stream = CefStreamReader::CreateForFile(filePath); + if (!stream) { return nullptr; } + + CefString mimeType = CefGetMimeType(fileExtension); + if (mimeType.empty()) { + mimeType = "application/octet-stream"; + } + + return new CefStreamResourceHandler(mimeType, stream); } diff --git a/cmake/os-linux.cmake b/cmake/os-linux.cmake index 98108066c..5376cfaf9 100644 --- a/cmake/os-linux.cmake +++ b/cmake/os-linux.cmake @@ -21,6 +21,8 @@ target_include_directories(browser-helper PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/d target_link_libraries(browser-helper PRIVATE CEF::Wrapper CEF::Library) +target_sources(obs-browser PRIVATE deps/ip-string.cpp) + set(OBS_EXECUTABLE_DESTINATION "${OBS_PLUGIN_DESTINATION}") # cmake-format: off diff --git a/cmake/os-macos.cmake b/cmake/os-macos.cmake index 56c2e3025..3ebc3bcb7 100644 --- a/cmake/os-macos.cmake +++ b/cmake/os-macos.cmake @@ -54,6 +54,8 @@ foreach(helper IN LISTS helper_suffixes) "${CMAKE_CURRENT_SOURCE_DIR}/cmake/macos/entitlements-helper${helper_plist}.plist") endforeach() +target_sources(obs-browser PRIVATE deps/ip-string.cpp) + set_target_properties( obs-browser PROPERTIES AUTOMOC ON diff --git a/cmake/os-windows.cmake b/cmake/os-windows.cmake index db3c18760..1484ea7d7 100644 --- a/cmake/os-windows.cmake +++ b/cmake/os-windows.cmake @@ -22,6 +22,9 @@ target_compile_definitions(obs-browser-helper PRIVATE ENABLE_BROWSER_SHARED_TEXT target_link_libraries(obs-browser-helper PRIVATE CEF::Wrapper CEF::Library nlohmann_json::nlohmann_json) target_link_options(obs-browser-helper PRIVATE /IGNORE:4099 /SUBSYSTEM:WINDOWS) +target_link_libraries(obs-browser PRIVATE Ws2_32) +target_sources(obs-browser PRIVATE deps/ip-string-windows.cpp) + set(OBS_EXECUTABLE_DESTINATION "${OBS_PLUGIN_DESTINATION}") set_target_properties_obs( obs-browser-helper diff --git a/deps/ip-string-posix.cpp b/deps/ip-string-posix.cpp new file mode 100644 index 000000000..187874b51 --- /dev/null +++ b/deps/ip-string-posix.cpp @@ -0,0 +1,35 @@ +/****************************************************************************** + Copyright (C) 2026 by Warchamp7 + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + ******************************************************************************/ + +#include "ip-string.hpp" + +#include +#include + +bool checkForIpv4String(const std::string &path) +{ + sockaddr_in sa4; + + return inet_pton(AF_INET, path.c_str(), &sa4.sin_addr) == 1; +} + +bool checkForIpv6String(const std::string &path) +{ + sockaddr_in6 sa6; + + return inet_pton(AF_INET6, path.c_str(), &sa6.sin6_addr) == 1; +} diff --git a/deps/ip-string-windows.cpp b/deps/ip-string-windows.cpp new file mode 100644 index 000000000..9efaadd89 --- /dev/null +++ b/deps/ip-string-windows.cpp @@ -0,0 +1,37 @@ +/****************************************************************************** + Copyright (C) 2026 by Warchamp7 + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + ******************************************************************************/ + +#include "ip-string.hpp" + +#include +#define WIN32_LEAN_AND_MEAN +#include +#include + +bool checkForIpv4String(const std::string &path) +{ + sockaddr_in sa4; + + return inet_pton(AF_INET, path.c_str(), &sa4.sin_addr) == 1; +} + +bool checkForIpv6String(const std::string &path) +{ + sockaddr_in6 sa6; + + return inet_pton(AF_INET6, path.c_str(), &sa6.sin6_addr) == 1; +} diff --git a/deps/ip-string.hpp b/deps/ip-string.hpp new file mode 100644 index 000000000..0b3833392 --- /dev/null +++ b/deps/ip-string.hpp @@ -0,0 +1,23 @@ +/****************************************************************************** + Copyright (C) 2026 by Warchamp7 + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + ******************************************************************************/ + +#pragma once + +#include + +extern bool checkForIpv4String(const std::string &path); +extern bool checkForIpv6String(const std::string &path); diff --git a/obs-browser-plugin.cpp b/obs-browser-plugin.cpp index 4d9233e37..05e6c43f6 100644 --- a/obs-browser-plugin.cpp +++ b/obs-browser-plugin.cpp @@ -388,9 +388,8 @@ static void BrowserInit(void) return; } - /* Register http://absolute/ scheme handler for older - * CEF builds which do not support file:// URLs */ - CefRegisterSchemeHandlerFactory("http", "absolute", new BrowserSchemeHandlerFactory()); + // Register custom scheme handler for local browser sources + CefRegisterSchemeHandlerFactory("obsbrowser", "file", new BrowserSchemeHandlerFactory()); os_event_signal(cef_started_event); } diff --git a/obs-browser-source.cpp b/obs-browser-source.cpp index 00324b922..193bda971 100644 --- a/obs-browser-source.cpp +++ b/obs-browser-source.cpp @@ -498,8 +498,8 @@ void BrowserSource::Update(obs_data_t *settings) while (n_url.find("%2F") != std::string::npos) n_url.replace(n_url.find("%2F"), 3, "/"); - /* http://absolute/ based mapping for older CEF */ - n_url = "http://absolute/" + n_url; + // Local files are routed through our custom scheme handler to give them acess to other local files + n_url = "obsbrowser://file/" + n_url; } if (n_is_local == is_local && n_fps_custom == fps_custom && n_fps == fps &&