Milestone 5: deliver embedded RDP sessions and lifecycle hardening
This commit is contained in:
30
third_party/FreeRDP/client/SDL/common/CMakeLists.txt
vendored
Normal file
30
third_party/FreeRDP/client/SDL/common/CMakeLists.txt
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
# FreeRDP: A Remote Desktop Protocol Implementation
|
||||
# FreeRDP SDL Client
|
||||
#
|
||||
# Copyright 2024 Armin Novak <anovak@thincast.com>
|
||||
# Copyright 2024 Thincast Technologies GmbH
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
add_subdirectory(aad)
|
||||
add_subdirectory(res)
|
||||
|
||||
add_library(
|
||||
sdl-common-prefs STATIC sdl_prefs.hpp sdl_prefs.cpp scoped_guard.hpp sdl_common_utils.hpp sdl_common_utils.cpp
|
||||
)
|
||||
target_link_libraries(sdl-common-prefs winpr freerdp)
|
||||
set_property(TARGET sdl-common-prefs PROPERTY FOLDER "Client/Common")
|
||||
|
||||
if(BUILD_TESTING_INTERNAL OR BUILD_TESTING)
|
||||
add_subdirectory(test)
|
||||
endif()
|
||||
55
third_party/FreeRDP/client/SDL/common/aad/CMakeLists.txt
vendored
Normal file
55
third_party/FreeRDP/client/SDL/common/aad/CMakeLists.txt
vendored
Normal file
@@ -0,0 +1,55 @@
|
||||
# FreeRDP: A Remote Desktop Protocol Implementation
|
||||
# FreeRDP SDL Client
|
||||
#
|
||||
# Copyright 2024 Armin Novak <anovak@thincast.com>
|
||||
# Copyright 2024 Thincast Technologies GmbH
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
option(WITH_WEBVIEW "Build with WebView support for AAD login popup browser" OFF)
|
||||
if(WITH_WEBVIEW)
|
||||
set(SRCS sdl_webview.hpp webview_impl.hpp sdl_webview.cpp)
|
||||
set(LIBS winpr)
|
||||
|
||||
include(FetchContent)
|
||||
|
||||
set(FETCHCONTENT_SOURCE_DIR_WEBVIEW "${CMAKE_CURRENT_SOURCE_DIR}/../../../../external/webview")
|
||||
if(IS_DIRECTORY "${FETCHCONTENT_SOURCE_DIR_WEBVIEW}")
|
||||
message("Using existing source from ${FETCHCONTENT_SOURCE_DIR_WEBVIEW}")
|
||||
else()
|
||||
unset(FETCHCONTENT_SOURCE_DIR_WEBVIEW)
|
||||
endif()
|
||||
|
||||
set(WEBVIEW_BUILD_DOCS OFF CACHE INTERNAL "fetchcontent default")
|
||||
set(WEBVIEW_BUILD_SHARED_LIBRARY OFF CACHE INTERNAL "fetchcontent default")
|
||||
set(WEBVIEW_BUILD_STATIC_LIBRARY ON CACHE INTERNAL "fetchcontent default")
|
||||
set(WEBVIEW_BUILD_TESTS OFF CACHE INTERNAL "fetchcontent default")
|
||||
set(WEBVIEW_BUILD_EXAMPLES OFF CACHE INTERNAL "fetchcontent default")
|
||||
FetchContent_Declare(webview GIT_REPOSITORY https://github.com/akallabeth/webview GIT_TAG navigation-listener SYSTEM)
|
||||
FetchContent_MakeAvailable(webview)
|
||||
|
||||
list(APPEND SRCS webview_impl.cpp)
|
||||
|
||||
list(APPEND LIBS webview::core)
|
||||
|
||||
include_directories(${CMAKE_CURRENT_BINARY_DIR})
|
||||
|
||||
add_library(sdl-common-aad-view STATIC ${SRCS})
|
||||
set_property(TARGET sdl-common-aad-view PROPERTY FOLDER "Client/SDL/Common")
|
||||
|
||||
target_include_directories(sdl-common-aad-view PUBLIC ${CMAKE_CURRENT_BINARY_DIR})
|
||||
target_link_libraries(sdl-common-aad-view PRIVATE ${LIBS})
|
||||
target_compile_definitions(sdl-common-aad-view PUBLIC ${DEFINITIONS})
|
||||
else()
|
||||
add_library(sdl-common-aad-view STATIC dummy.cpp)
|
||||
endif()
|
||||
0
third_party/FreeRDP/client/SDL/common/aad/dummy.cpp
vendored
Normal file
0
third_party/FreeRDP/client/SDL/common/aad/dummy.cpp
vendored
Normal file
155
third_party/FreeRDP/client/SDL/common/aad/sdl_webview.cpp
vendored
Normal file
155
third_party/FreeRDP/client/SDL/common/aad/sdl_webview.cpp
vendored
Normal file
@@ -0,0 +1,155 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* Popup browser for AAD authentication
|
||||
*
|
||||
* Copyright 2023 Isaac Klein <fifthdegree@protonmail.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <cstdlib>
|
||||
#include <memory>
|
||||
|
||||
#include <winpr/string.h>
|
||||
#include <freerdp/log.h>
|
||||
#include <freerdp/utils/aad.h>
|
||||
|
||||
#include "sdl_webview.hpp"
|
||||
#include "webview_impl.hpp"
|
||||
|
||||
#define TAG CLIENT_TAG("SDL.webview")
|
||||
|
||||
static std::string from_settings(const rdpSettings* settings, FreeRDP_Settings_Keys_String id)
|
||||
{
|
||||
auto val = freerdp_settings_get_string(settings, id);
|
||||
if (!val)
|
||||
{
|
||||
WLog_WARN(TAG, "Settings key %s is nullptr", freerdp_settings_get_name_for_key(id));
|
||||
return "";
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
static std::string from_aad_wellknown(rdpContext* context, AAD_WELLKNOWN_VALUES which)
|
||||
{
|
||||
auto val = freerdp_utils_aad_get_wellknown_string(context, which);
|
||||
|
||||
if (!val)
|
||||
{
|
||||
WLog_WARN(TAG, "[wellknown] key %s is nullptr",
|
||||
freerdp_utils_aad_wellknwon_value_name(which));
|
||||
return "";
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
static BOOL sdl_webview_get_rdsaad_access_token(freerdp* instance, const char* scope,
|
||||
const char* req_cnf, char** token)
|
||||
{
|
||||
WINPR_ASSERT(instance);
|
||||
WINPR_ASSERT(scope);
|
||||
WINPR_ASSERT(req_cnf);
|
||||
WINPR_ASSERT(token);
|
||||
|
||||
WINPR_UNUSED(instance);
|
||||
|
||||
auto context = instance->context;
|
||||
WINPR_UNUSED(context);
|
||||
|
||||
auto settings = context->settings;
|
||||
WINPR_ASSERT(settings);
|
||||
|
||||
std::shared_ptr<char> request(freerdp_client_get_aad_url((rdpClientContext*)instance->context,
|
||||
FREERDP_CLIENT_AAD_AUTH_REQUEST,
|
||||
scope),
|
||||
free);
|
||||
const std::string title = "FreeRDP WebView - AAD access token";
|
||||
std::string code;
|
||||
auto rc = webview_impl_run(title, request.get(), code);
|
||||
if (!rc || code.empty())
|
||||
return FALSE;
|
||||
|
||||
std::shared_ptr<char> token_request(
|
||||
freerdp_client_get_aad_url((rdpClientContext*)instance->context,
|
||||
FREERDP_CLIENT_AAD_TOKEN_REQUEST, scope, code.c_str(), req_cnf),
|
||||
free);
|
||||
return client_common_get_access_token(instance, token_request.get(), token);
|
||||
}
|
||||
|
||||
static BOOL sdl_webview_get_avd_access_token(freerdp* instance, char** token)
|
||||
{
|
||||
WINPR_ASSERT(token);
|
||||
WINPR_ASSERT(instance);
|
||||
WINPR_ASSERT(instance->context);
|
||||
|
||||
std::shared_ptr<char> request(freerdp_client_get_aad_url((rdpClientContext*)instance->context,
|
||||
FREERDP_CLIENT_AAD_AVD_AUTH_REQUEST),
|
||||
free);
|
||||
|
||||
const std::string title = "FreeRDP WebView - AVD access token";
|
||||
std::string code;
|
||||
auto rc = webview_impl_run(title, request.get(), code);
|
||||
if (!rc || code.empty())
|
||||
return FALSE;
|
||||
|
||||
std::shared_ptr<char> token_request(
|
||||
freerdp_client_get_aad_url((rdpClientContext*)instance->context,
|
||||
FREERDP_CLIENT_AAD_AVD_TOKEN_REQUEST, code.c_str()),
|
||||
free);
|
||||
return client_common_get_access_token(instance, token_request.get(), token);
|
||||
}
|
||||
|
||||
BOOL sdl_webview_get_access_token(freerdp* instance, AccessTokenType tokenType, char** token,
|
||||
size_t count, ...)
|
||||
{
|
||||
WINPR_ASSERT(instance);
|
||||
WINPR_ASSERT(token);
|
||||
switch (tokenType)
|
||||
{
|
||||
case ACCESS_TOKEN_TYPE_AAD:
|
||||
{
|
||||
if (count < 2)
|
||||
{
|
||||
WLog_ERR(TAG,
|
||||
"ACCESS_TOKEN_TYPE_AAD expected 2 additional arguments, but got %" PRIuz
|
||||
", aborting",
|
||||
count);
|
||||
return FALSE;
|
||||
}
|
||||
else if (count > 2)
|
||||
WLog_WARN(TAG,
|
||||
"ACCESS_TOKEN_TYPE_AAD expected 2 additional arguments, but got %" PRIuz
|
||||
", ignoring",
|
||||
count);
|
||||
va_list ap = {};
|
||||
va_start(ap, count);
|
||||
const char* scope = va_arg(ap, const char*);
|
||||
const char* req_cnf = va_arg(ap, const char*);
|
||||
const BOOL rc = sdl_webview_get_rdsaad_access_token(instance, scope, req_cnf, token);
|
||||
va_end(ap);
|
||||
return rc;
|
||||
}
|
||||
case ACCESS_TOKEN_TYPE_AVD:
|
||||
if (count != 0)
|
||||
WLog_WARN(TAG,
|
||||
"ACCESS_TOKEN_TYPE_AVD expected 0 additional arguments, but got %" PRIuz
|
||||
", ignoring",
|
||||
count);
|
||||
return sdl_webview_get_avd_access_token(instance, token);
|
||||
default:
|
||||
WLog_ERR(TAG, "Unexpected value for AccessTokenType [%" PRIuz "], aborting", tokenType);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
34
third_party/FreeRDP/client/SDL/common/aad/sdl_webview.hpp
vendored
Normal file
34
third_party/FreeRDP/client/SDL/common/aad/sdl_webview.hpp
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* Popup browser for AAD authentication
|
||||
*
|
||||
* Copyright 2023 Isaac Klein <fifthdegree@protonmail.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <freerdp/freerdp.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
[[nodiscard]] BOOL sdl_webview_get_access_token(freerdp* instance, AccessTokenType tokenType,
|
||||
char** token, size_t count, ...);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
179
third_party/FreeRDP/client/SDL/common/aad/webview_impl.cpp
vendored
Normal file
179
third_party/FreeRDP/client/SDL/common/aad/webview_impl.cpp
vendored
Normal file
@@ -0,0 +1,179 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* Popup browser for AAD authentication
|
||||
*
|
||||
* Copyright 2023 Isaac Klein <fifthdegree@protonmail.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <webview.h>
|
||||
|
||||
#include "webview_impl.hpp"
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <cctype>
|
||||
#include <map>
|
||||
#include <regex>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <freerdp/log.h>
|
||||
#include <winpr/string.h>
|
||||
|
||||
#define TAG FREERDP_TAG("client.SDL.common.aad")
|
||||
|
||||
class fkt_arg
|
||||
{
|
||||
public:
|
||||
fkt_arg(const std::string& url)
|
||||
{
|
||||
auto args = urlsplit(url);
|
||||
auto redir = args.find("redirect_uri");
|
||||
if (redir == args.end())
|
||||
{
|
||||
WLog_ERR(TAG,
|
||||
"[Webview] url %s does not contain a redirect_uri parameter, "
|
||||
"aborting.",
|
||||
url.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
_redirect_uri = from_url_encoded_str(redir->second);
|
||||
}
|
||||
}
|
||||
|
||||
bool valid() const
|
||||
{
|
||||
return !_redirect_uri.empty();
|
||||
}
|
||||
|
||||
bool getCode(std::string& c) const
|
||||
{
|
||||
c = _code;
|
||||
return !c.empty();
|
||||
}
|
||||
|
||||
bool handle(const std::string& uri) const
|
||||
{
|
||||
std::string duri = from_url_encoded_str(uri);
|
||||
if (duri.length() < _redirect_uri.length())
|
||||
return false;
|
||||
auto rc = _strnicmp(duri.c_str(), _redirect_uri.c_str(), _redirect_uri.length());
|
||||
return rc == 0;
|
||||
}
|
||||
|
||||
bool parse(const std::string& uri)
|
||||
{
|
||||
_args = urlsplit(uri);
|
||||
auto err = _args.find("error");
|
||||
if (err != _args.end())
|
||||
{
|
||||
auto suberr = _args.find("error_subcode");
|
||||
WLog_ERR(TAG, "[Webview] %s: %s, %s: %s", err->first.c_str(), err->second.c_str(),
|
||||
suberr->first.c_str(), suberr->second.c_str());
|
||||
return false;
|
||||
}
|
||||
auto val = _args.find("code");
|
||||
if (val == _args.end())
|
||||
{
|
||||
WLog_ERR(TAG, "[Webview] no code parameter detected in redirect URI %s", uri.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
_code = val->second;
|
||||
return true;
|
||||
}
|
||||
|
||||
protected:
|
||||
static std::string from_url_encoded_str(const std::string& str)
|
||||
{
|
||||
std::string cxxstr;
|
||||
auto cstr = winpr_str_url_decode(str.c_str(), str.length());
|
||||
if (cstr)
|
||||
{
|
||||
cxxstr = std::string(cstr);
|
||||
free(cstr);
|
||||
}
|
||||
return cxxstr;
|
||||
}
|
||||
|
||||
static std::vector<std::string> split(const std::string& input, const std::string& regex)
|
||||
{
|
||||
// passing -1 as the submatch index parameter performs splitting
|
||||
std::regex re(regex);
|
||||
std::sregex_token_iterator first{ input.begin(), input.end(), re, -1 };
|
||||
std::sregex_token_iterator last;
|
||||
return { first, last };
|
||||
}
|
||||
|
||||
static std::map<std::string, std::string> urlsplit(const std::string& url)
|
||||
{
|
||||
auto pos = url.find('?');
|
||||
if (pos == std::string::npos)
|
||||
return {};
|
||||
|
||||
pos++; // skip '?'
|
||||
auto surl = url.substr(pos);
|
||||
auto args = split(surl, "&");
|
||||
|
||||
std::map<std::string, std::string> argmap;
|
||||
for (const auto& arg : args)
|
||||
{
|
||||
auto kv = split(arg, "=");
|
||||
if (kv.size() == 2)
|
||||
argmap.insert({ kv[0], kv[1] });
|
||||
}
|
||||
|
||||
return argmap;
|
||||
}
|
||||
|
||||
private:
|
||||
std::string _redirect_uri;
|
||||
std::string _code;
|
||||
std::map<std::string, std::string> _args;
|
||||
};
|
||||
|
||||
static void fkt(webview_t webview, const char* uri, webview_navigation_event_t type, void* arg)
|
||||
{
|
||||
assert(arg);
|
||||
auto rcode = static_cast<fkt_arg*>(arg);
|
||||
|
||||
if (type != WEBVIEW_LOAD_FINISHED)
|
||||
return;
|
||||
|
||||
if (!rcode->handle(uri))
|
||||
return;
|
||||
|
||||
(void)rcode->parse(uri);
|
||||
webview_terminate(webview);
|
||||
}
|
||||
|
||||
bool webview_impl_run(const std::string& title, const std::string& url, std::string& code)
|
||||
{
|
||||
webview::webview w(false, nullptr);
|
||||
|
||||
w.set_title(title);
|
||||
w.set_size(800, 600, WEBVIEW_HINT_NONE);
|
||||
|
||||
fkt_arg arg(url);
|
||||
if (!arg.valid())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
w.add_navigation_listener(fkt, &arg);
|
||||
w.navigate(url);
|
||||
w.run();
|
||||
return arg.getCode(code);
|
||||
}
|
||||
25
third_party/FreeRDP/client/SDL/common/aad/webview_impl.hpp
vendored
Normal file
25
third_party/FreeRDP/client/SDL/common/aad/webview_impl.hpp
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* Popup browser for AAD authentication
|
||||
*
|
||||
* Copyright 2023 Isaac Klein <fifthdegree@protonmail.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
[[nodiscard]] bool webview_impl_run(const std::string& title, const std::string& url,
|
||||
std::string& code);
|
||||
130
third_party/FreeRDP/client/SDL/common/man/sdl-freerdp-config.1.in
vendored
Normal file
130
third_party/FreeRDP/client/SDL/common/man/sdl-freerdp-config.1.in
vendored
Normal file
@@ -0,0 +1,130 @@
|
||||
.SH "CONFIGURATION FILE"
|
||||
.PP
|
||||
Format and Location:
|
||||
.RS 4
|
||||
The configuration file is stored per user\&.
|
||||
.br
|
||||
|
||||
The
|
||||
\fIXDG_CONFIG_HOME\fR
|
||||
environment variable can be used to override the base directory\&.
|
||||
.br
|
||||
|
||||
This defaults to
|
||||
\fI~/\&.config\fR
|
||||
The location relative to
|
||||
\fIXDG_CONFIG_HOME\fR
|
||||
is
|
||||
\fI$XDG_CONFIG_HOME/@VENDOR_PRODUCT@/sdl\-freerdp\&.json\fR
|
||||
.br
|
||||
|
||||
The configuration is stored in JSON format
|
||||
.RE
|
||||
.PP
|
||||
Supported options:
|
||||
.RS 4
|
||||
.PP
|
||||
\fISDL_KeyModMask\fR
|
||||
.RS 4
|
||||
.PP
|
||||
.RS 4
|
||||
Defines the key combination required for SDL client shortcuts\&.
|
||||
.br
|
||||
|
||||
Default
|
||||
\fIKMOD_RSHIFT\fR
|
||||
.br
|
||||
|
||||
An array of
|
||||
\fISDL_Keymod\fR
|
||||
strings as defined at
|
||||
\fI@SDL_WIKI_BASE_URL@/SDL_Keymod\fR
|
||||
.br
|
||||
use \fRKEYMOD_NONE\fR to disable hotkeys
|
||||
.RE
|
||||
.RE
|
||||
.PP
|
||||
\fISDL_Fullscreen\fR
|
||||
.RS 4
|
||||
.PP
|
||||
.RS 4
|
||||
Toggles client fullscreen state\&.
|
||||
.br
|
||||
|
||||
Default
|
||||
\fISDL_SCANCODE_RETURN\fR\&.
|
||||
.br
|
||||
|
||||
A string as defined at
|
||||
\fI@SDL_WIKI_BASE_URL@/SDL_Scancode\fR
|
||||
.RE
|
||||
.RE
|
||||
.PP
|
||||
\fISDL_Minimize\fR
|
||||
.RS 4
|
||||
.PP
|
||||
.RS 4
|
||||
Minimizes the client window
|
||||
.br
|
||||
|
||||
Default
|
||||
\fISDL_SCANCODE_M\fR\&.
|
||||
.br
|
||||
|
||||
A string as defined at
|
||||
\fI@SDL_WIKI_BASE_URL@/SDL_Scancode\fR
|
||||
.RE
|
||||
.RE
|
||||
.PP
|
||||
\fISDL_Resizeable\fR
|
||||
.RS 4
|
||||
.PP
|
||||
.RS 4
|
||||
Toggles local window resizeable state\&.
|
||||
.br
|
||||
|
||||
Default
|
||||
\fISDL_SCANCODE_R\fR\&.
|
||||
.br
|
||||
|
||||
A string as defined at
|
||||
\fI@SDL_WIKI_BASE_URL@/SDL_Scancode\fR
|
||||
.RE
|
||||
.RE
|
||||
.PP
|
||||
\fISDL_Grab\fR
|
||||
.RS 4
|
||||
.PP
|
||||
.RS 4
|
||||
Toggles keyboard and mouse grab state.
|
||||
.br
|
||||
If keyboard is grabbed the local system shortcuts do no longer work and are sent to the remote system.
|
||||
.br
|
||||
If the Mouse is grabbed (optional) local gesture detection does not work and the mouse might not be able to leave the RDP window. Mouse events are not altered.\&.
|
||||
.br
|
||||
|
||||
Default
|
||||
\fISDL_SCANCODE_G\fR\&.
|
||||
.br
|
||||
|
||||
A string as defined at
|
||||
\fI@SDL_WIKI_BASE_URL@/SDL_Scancode\fR
|
||||
.RE
|
||||
.RE
|
||||
.PP
|
||||
\fISDL_Disconnect\fR
|
||||
.RS 4
|
||||
.PP
|
||||
.RS 4
|
||||
Disconnects from the RDP session\&.
|
||||
.br
|
||||
|
||||
Default
|
||||
\fISDL_SCANCODE_D\fR\&.
|
||||
.br
|
||||
|
||||
A string as defined at
|
||||
\fI@SDL_WIKI_BASE_URL@/SDL_Scancode\fR
|
||||
.RE
|
||||
.RE
|
||||
.RE
|
||||
116
third_party/FreeRDP/client/SDL/common/man/sdl-freerdp-examples.1.in
vendored
Normal file
116
third_party/FreeRDP/client/SDL/common/man/sdl-freerdp-examples.1.in
vendored
Normal file
@@ -0,0 +1,116 @@
|
||||
.SH "EXAMPLES"
|
||||
.PP
|
||||
\fB@MANPAGE_NAME@ connection\&.rdp /p:Pwd123! /f\fR
|
||||
.RS 4
|
||||
Connect in fullscreen mode using a stored configuration
|
||||
\fIconnection\&.rdp\fR
|
||||
and the password
|
||||
\fIPwd123!\fR
|
||||
.RE
|
||||
.PP
|
||||
\fB@MANPAGE_NAME@ /u:USER /size:50%h /v:rdp\&.contoso\&.com\fR
|
||||
.RS 4
|
||||
Connect to host
|
||||
\fIrdp\&.contoso\&.com\fR
|
||||
with user
|
||||
\fIUSER\fR
|
||||
and a size of
|
||||
\fI50 percent of the height\fR\&. If width (w) is set instead of height (h) like /size:50%w\&. 50 percent of the width is used\&.
|
||||
.RE
|
||||
.PP
|
||||
\fB@MANPAGE_NAME@ /u:CONTOSO\e\eJohnDoe /p:Pwd123! /v:rdp\&.contoso\&.com\fR
|
||||
.RS 4
|
||||
Connect to host
|
||||
\fIrdp\&.contoso\&.com\fR
|
||||
with user
|
||||
\fICONTOSO\e\eJohnDoe\fR
|
||||
and password
|
||||
\fIPwd123!\fR
|
||||
.RE
|
||||
.PP
|
||||
\fB@MANPAGE_NAME@ /u:JohnDoe /p:Pwd123! /w:1366 /h:768 /v:192\&.168\&.1\&.100:4489\fR
|
||||
.RS 4
|
||||
Connect to host
|
||||
\fI192\&.168\&.1\&.100\fR
|
||||
on port
|
||||
\fI4489\fR
|
||||
with user
|
||||
\fIJohnDoe\fR, password
|
||||
\fIPwd123!\fR\&. The screen width is set to
|
||||
\fI1366\fR
|
||||
and the height to
|
||||
\fI768\fR
|
||||
.RE
|
||||
.PP
|
||||
\fB@MANPAGE_NAME@ /u:JohnDoe /p:Pwd123! /vmconnect:C824F53E\-95D2\-46C6\-9A18\-23A5BB403532 /v:192\&.168\&.1\&.100\fR
|
||||
.RS 4
|
||||
Establish a connection to host
|
||||
\fI192\&.168\&.1\&.100\fR
|
||||
with user
|
||||
\fIJohnDoe\fR, password
|
||||
\fIPwd123!\fR
|
||||
and connect to Hyper\-V console (use port 2179, disable negotiation) with VMID
|
||||
\fIC824F53E\-95D2\-46C6\-9A18\-23A5BB403532\fR
|
||||
.RE
|
||||
.PP
|
||||
\fB+clipboard\fR
|
||||
.RS 4
|
||||
Activate clipboard redirection
|
||||
.RE
|
||||
.PP
|
||||
\fB/drive:home,/home/user\fR
|
||||
.RS 4
|
||||
Activate drive redirection of
|
||||
\fI/home/user\fR
|
||||
as home drive
|
||||
.RE
|
||||
.PP
|
||||
\fB/smartcard:<device>\fR
|
||||
.RS 4
|
||||
Activate smartcard redirection for device
|
||||
\fIdevice\fR
|
||||
.RE
|
||||
.PP
|
||||
\fB/printer:<device>,<driver>\fR
|
||||
.RS 4
|
||||
Activate printer redirection for printer
|
||||
\fIdevice\fR
|
||||
using driver
|
||||
\fIdriver\fR
|
||||
.RE
|
||||
.PP
|
||||
\fB/serial:<device>\fR
|
||||
.RS 4
|
||||
Activate serial port redirection for port
|
||||
\fIdevice\fR
|
||||
.RE
|
||||
.PP
|
||||
\fB/parallel:<device>\fR
|
||||
.RS 4
|
||||
Activate parallel port redirection for port
|
||||
\fIdevice\fR
|
||||
.RE
|
||||
.PP
|
||||
\fB/sound:sys:alsa\fR
|
||||
.RS 4
|
||||
Activate audio output redirection using device
|
||||
\fIsys:alsa\fR
|
||||
.RE
|
||||
.PP
|
||||
\fB/microphone:sys:alsa\fR
|
||||
.RS 4
|
||||
Activate audio input redirection using device
|
||||
\fIsys:alsa\fR
|
||||
.RE
|
||||
.PP
|
||||
\fB/multimedia:sys:alsa\fR
|
||||
.RS 4
|
||||
Activate multimedia redirection using device
|
||||
\fIsys:alsa\fR
|
||||
.RE
|
||||
.PP
|
||||
\fB/usb:id,dev:054c:0268\fR
|
||||
.RS 4
|
||||
Activate USB device redirection for the device identified by
|
||||
\fI054c:0268\fR
|
||||
.RE
|
||||
24
third_party/FreeRDP/client/SDL/common/man/sdl-global-config.1.in
vendored
Normal file
24
third_party/FreeRDP/client/SDL/common/man/sdl-global-config.1.in
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
.SH "GLOBAL CONFIGURATION (SDL3 client)"
|
||||
.PP
|
||||
The SDL3 client configuration location is
|
||||
\fI@SYSCONF_DIR@/sdl-freerdp\&.json\fR
|
||||
.br
|
||||
|
||||
File format is JSON
|
||||
.RE
|
||||
.PP
|
||||
Supported options:
|
||||
.RS 4
|
||||
.PP
|
||||
\fIisUserConfigEnabled\fR
|
||||
.RS 4
|
||||
.PP
|
||||
.RS 4
|
||||
\fIJSON boolean\fR
|
||||
.br
|
||||
|
||||
Allow or block per user configuration file support.
|
||||
.RE
|
||||
.RE
|
||||
.PP
|
||||
All user level options from \fBCONFIGURATION FILE\fR can be set here too
|
||||
108
third_party/FreeRDP/client/SDL/common/res/CMakeLists.txt
vendored
Normal file
108
third_party/FreeRDP/client/SDL/common/res/CMakeLists.txt
vendored
Normal file
@@ -0,0 +1,108 @@
|
||||
# FreeRDP: A Remote Desktop Protocol Implementation
|
||||
# FreeRDP SDL Client
|
||||
#
|
||||
# Copyright 2024 Armin Novak <anovak@thincast.com>
|
||||
# Copyright 2024 Thincast Technologies GmbH
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
set(FACTORY_SRCS "")
|
||||
set(FACTORY_HDR "")
|
||||
set(FACTORY_CLASSES "")
|
||||
|
||||
include(ConvertFileToHexArray)
|
||||
|
||||
macro(convert_to_bin FILE FILE_TYPE)
|
||||
get_filename_component(FILE_NAME ${FILE} NAME)
|
||||
string(REGEX REPLACE "[^a-zA-Z0-9]" "_" TARGET_NAME ${FILE_NAME})
|
||||
|
||||
set(FILE_BIN_DIR ${CMAKE_CURRENT_BINARY_DIR}/bin)
|
||||
|
||||
set(FILENAME ${FILE_NAME})
|
||||
set(CLASSNAME ${TARGET_NAME})
|
||||
set(CLASSTYPE ${FILE_TYPE})
|
||||
|
||||
file_to_hex_array("${FILE}" FILEDATA)
|
||||
|
||||
cleaning_configure_file(resource.hpp.in ${FILE_BIN_DIR}/${TARGET_NAME}.hpp @ONLY)
|
||||
|
||||
cleaning_configure_file(resource.cpp.in ${FILE_BIN_DIR}/${TARGET_NAME}.cpp @ONLY)
|
||||
|
||||
list(APPEND FACTORY_HDR ${FILE_BIN_DIR}/${TARGET_NAME}.hpp)
|
||||
list(APPEND FACTORY_SRCS ${FILE_BIN_DIR}/${TARGET_NAME}.cpp)
|
||||
|
||||
list(APPEND FACTORY_CLASSES ${TARGET_NAME})
|
||||
endmacro()
|
||||
|
||||
set(SRCS sdl_resource_manager.cpp sdl_resource_manager.hpp)
|
||||
|
||||
set(RES_SVG_FILES ${CMAKE_SOURCE_DIR}/resources/FreeRDP_Icon.svg ${CMAKE_SOURCE_DIR}/resources/icon_info.svg
|
||||
${CMAKE_SOURCE_DIR}/resources/icon_warning.svg ${CMAKE_SOURCE_DIR}/resources/icon_error.svg
|
||||
)
|
||||
|
||||
set(RES_FONT_FILES ${CMAKE_SOURCE_DIR}/resources/font/OpenSans-VariableFont_wdth,wght.ttf)
|
||||
|
||||
option(SDL_USE_COMPILED_RESOURCES "Compile in images/fonts" ON)
|
||||
|
||||
if(SDL_USE_COMPILED_RESOURCES)
|
||||
list(APPEND SRCS sdl_resource_file.cpp sdl_resource_file.hpp)
|
||||
|
||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
|
||||
|
||||
if(WITH_SDL_IMAGE_DIALOGS)
|
||||
foreach(FILE ${RES_SVG_FILES})
|
||||
convert_to_bin("${FILE}" "images")
|
||||
endforeach()
|
||||
endif()
|
||||
|
||||
foreach(FILE ${RES_FONT_FILES})
|
||||
convert_to_bin("${FILE}" "fonts")
|
||||
endforeach()
|
||||
add_compile_definitions(SDL_USE_COMPILED_RESOURCES)
|
||||
|
||||
set(FINIT ${CMAKE_CURRENT_BINARY_DIR}/resource-init.cpp)
|
||||
list(APPEND FACTORY_SRCS ${FINIT})
|
||||
|
||||
write_file(${FINIT} "#include <sdl_resource_manager.hpp>")
|
||||
foreach(HDR ${FACTORY_HDR})
|
||||
write_file(${FINIT} "#include <${HDR}>" APPEND)
|
||||
endforeach()
|
||||
|
||||
write_file(${FINIT} "void SDLResourceManager::init() {" APPEND)
|
||||
foreach(CLASS ${FACTORY_CLASSES})
|
||||
write_file(${FINIT} "\t${CLASS}::init();" APPEND)
|
||||
endforeach()
|
||||
write_file(${FINIT} "}" APPEND)
|
||||
else()
|
||||
option(SDL_USE_VENDOR_PRODUCT_CONFIG_DIR "Use <vendor>/<product> path for resources" OFF)
|
||||
set(SDL_RESOURCE_ROOT ${CMAKE_INSTALL_FULL_DATAROOTDIR})
|
||||
if(SDL_USE_VENDOR_PRODUCT_CONFIG_DIR)
|
||||
string(APPEND SDL_RESOURCE_ROOT "/${VENDOR}")
|
||||
endif()
|
||||
string(APPEND SDL_RESOURCE_ROOT "/${PRODUCT}")
|
||||
|
||||
if(WITH_BINARY_VERSIONING)
|
||||
string(APPEND SDL_RESOURCE_ROOT "${FREERDP_VERSION_MAJOR}")
|
||||
endif()
|
||||
|
||||
add_compile_definitions(SDL_RESOURCE_ROOT="${SDL_RESOURCE_ROOT}")
|
||||
|
||||
if(WITH_SDL_IMAGE_DIALOGS)
|
||||
install(FILES ${RES_SVG_FILES} DESTINATION ${SDL_RESOURCE_ROOT}/images)
|
||||
endif()
|
||||
|
||||
install(FILES ${RES_FONT_FILES} DESTINATION ${SDL_RESOURCE_ROOT}/fonts)
|
||||
endif()
|
||||
|
||||
add_library(sdl-common-client-res STATIC ${RES_FILES} ${SRCS} ${FACTORY_HDR} ${FACTORY_SRCS})
|
||||
set_property(TARGET sdl-common-client-res PROPERTY POSITION_INDEPENDENT_CODE ON)
|
||||
set_property(TARGET sdl-common-client-res PROPERTY FOLDER "Client/Common")
|
||||
28
third_party/FreeRDP/client/SDL/common/res/resource.cpp.in
vendored
Normal file
28
third_party/FreeRDP/client/SDL/common/res/resource.cpp.in
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
/* AUTOGENERATED file, do not edit
|
||||
*
|
||||
* part of @PROJECT_NAME@
|
||||
* generated by 'CMake' from common/res/resource.cpp.in
|
||||
*
|
||||
* contains the converted file '@FILENAME@'
|
||||
*/
|
||||
|
||||
#include <vector>
|
||||
#include "@CLASSNAME@.hpp"
|
||||
|
||||
std::string @CLASSNAME@::name() noexcept {
|
||||
return "@FILENAME@";
|
||||
}
|
||||
std::string @CLASSNAME@::type() noexcept {
|
||||
return "@CLASSTYPE@";
|
||||
}
|
||||
|
||||
// NOLINTNEXTLINE(clang-diagnostic-global-constructors)
|
||||
const SDLResourceFile @CLASSNAME@::_initializer(type(), name(), init());
|
||||
|
||||
std::vector<unsigned char> @CLASSNAME@::init() noexcept {
|
||||
static const unsigned char data[] = {
|
||||
@FILEDATA@
|
||||
};
|
||||
return std::vector<unsigned char>(data, data + sizeof(data));
|
||||
}
|
||||
|
||||
34
third_party/FreeRDP/client/SDL/common/res/resource.hpp.in
vendored
Normal file
34
third_party/FreeRDP/client/SDL/common/res/resource.hpp.in
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
/* AUTOGENERATED file, do not edit
|
||||
*
|
||||
* part of @PROJECT_NAME@
|
||||
* generated by 'CMake' from common/res/resource.hpp.in
|
||||
*
|
||||
* contains the converted file '@FILENAME@'
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include "sdl_resource_file.hpp"
|
||||
|
||||
class @CLASSNAME@
|
||||
{
|
||||
friend class SDLResourceManager;
|
||||
|
||||
public:
|
||||
@CLASSNAME@() = delete;
|
||||
~@CLASSNAME@() = delete;
|
||||
|
||||
@CLASSNAME@(const @CLASSNAME@&) = delete;
|
||||
@CLASSNAME@(@CLASSNAME@&&) = delete;
|
||||
|
||||
@CLASSNAME@& operator=(const @CLASSNAME@&) = delete;
|
||||
@CLASSNAME@& operator=(@CLASSNAME@&&) = delete;
|
||||
|
||||
static std::string name() noexcept;
|
||||
static std::string type() noexcept;
|
||||
|
||||
protected:
|
||||
static std::vector<unsigned char> init() noexcept;
|
||||
static const SDLResourceFile _initializer;
|
||||
};
|
||||
27
third_party/FreeRDP/client/SDL/common/res/sdl_resource_file.cpp
vendored
Normal file
27
third_party/FreeRDP/client/SDL/common/res/sdl_resource_file.cpp
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
*
|
||||
* Copyright 2023 Armin Novak <armin.novak@thincast.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#include "sdl_resource_file.hpp"
|
||||
#include "sdl_resource_manager.hpp"
|
||||
|
||||
SDLResourceFile::SDLResourceFile(const std::string& type, const std::string& id,
|
||||
const std::vector<unsigned char>& data) noexcept
|
||||
{
|
||||
SDLResourceManager::insert(type, id, data);
|
||||
}
|
||||
|
||||
SDLResourceFile::~SDLResourceFile() = default;
|
||||
34
third_party/FreeRDP/client/SDL/common/res/sdl_resource_file.hpp
vendored
Normal file
34
third_party/FreeRDP/client/SDL/common/res/sdl_resource_file.hpp
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
*
|
||||
* Copyright 2023 Armin Novak <armin.novak@thincast.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
class SDLResourceFile
|
||||
{
|
||||
public:
|
||||
SDLResourceFile(const std::string& type, const std::string& id,
|
||||
const std::vector<unsigned char>& data) noexcept;
|
||||
virtual ~SDLResourceFile();
|
||||
|
||||
SDLResourceFile(const SDLResourceFile& other) = delete;
|
||||
SDLResourceFile(SDLResourceFile&& other) = delete;
|
||||
SDLResourceFile& operator=(const SDLResourceFile& other) = delete;
|
||||
SDLResourceFile& operator=(SDLResourceFile&& other) = delete;
|
||||
};
|
||||
102
third_party/FreeRDP/client/SDL/common/res/sdl_resource_manager.cpp
vendored
Normal file
102
third_party/FreeRDP/client/SDL/common/res/sdl_resource_manager.cpp
vendored
Normal file
@@ -0,0 +1,102 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
*
|
||||
* Copyright 2023 Armin Novak <armin.novak@thincast.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#include "sdl_resource_manager.hpp"
|
||||
#include <iostream>
|
||||
#if __has_include(<filesystem>)
|
||||
#include <filesystem>
|
||||
namespace fs = std::filesystem;
|
||||
#elif __has_include(<experimental/filesystem>)
|
||||
#include <experimental/filesystem>
|
||||
namespace fs = std::experimental::filesystem;
|
||||
#else
|
||||
#error Could not find system header "<filesystem>" or "<experimental/filesystem>"
|
||||
#endif
|
||||
|
||||
std::string SDLResourceManager::typeFonts()
|
||||
{
|
||||
return "fonts";
|
||||
}
|
||||
|
||||
std::string SDLResourceManager::typeImages()
|
||||
{
|
||||
return "images";
|
||||
}
|
||||
|
||||
void SDLResourceManager::insert(const std::string& type, const std::string& id,
|
||||
const std::vector<unsigned char>& data)
|
||||
{
|
||||
std::string uuid = type + "/" + id;
|
||||
resources().emplace(uuid, data);
|
||||
}
|
||||
|
||||
bool SDLResourceManager::useCompiledResources()
|
||||
{
|
||||
#if defined(SDL_USE_COMPILED_RESOURCES)
|
||||
return true;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
const std::vector<unsigned char>* SDLResourceManager::data(const std::string& type,
|
||||
const std::string& id)
|
||||
{
|
||||
#if defined(SDL_USE_COMPILED_RESOURCES)
|
||||
std::string uuid = type + "/" + id;
|
||||
auto val = resources().find(uuid);
|
||||
if (val == resources().end())
|
||||
return nullptr;
|
||||
|
||||
return &val->second;
|
||||
#else
|
||||
return nullptr;
|
||||
#endif
|
||||
}
|
||||
|
||||
std::string SDLResourceManager::filename([[maybe_unused]] const std::string& type,
|
||||
[[maybe_unused]] const std::string& id)
|
||||
{
|
||||
#if defined(SDL_RESOURCE_ROOT)
|
||||
std::string uuid = type + "/" + id;
|
||||
fs::path path(SDL_RESOURCE_ROOT);
|
||||
path /= type;
|
||||
path /= id;
|
||||
|
||||
if (!fs::exists(path))
|
||||
{
|
||||
std::cerr << "sdl-freerdp expects resource '" << uuid << "' at location "
|
||||
<< fs::absolute(path) << std::endl;
|
||||
std::cerr << "file not found, application will fail" << std::endl;
|
||||
return "";
|
||||
}
|
||||
return path.u8string();
|
||||
#else
|
||||
return "";
|
||||
#endif
|
||||
}
|
||||
|
||||
std::map<std::string, std::vector<unsigned char>>& SDLResourceManager::resources()
|
||||
{
|
||||
|
||||
static std::map<std::string, std::vector<unsigned char>> resources = {};
|
||||
#if defined(SDL_USE_COMPILED_RESOURCES)
|
||||
if (resources.empty())
|
||||
init();
|
||||
#endif
|
||||
return resources;
|
||||
}
|
||||
54
third_party/FreeRDP/client/SDL/common/res/sdl_resource_manager.hpp
vendored
Normal file
54
third_party/FreeRDP/client/SDL/common/res/sdl_resource_manager.hpp
vendored
Normal file
@@ -0,0 +1,54 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
*
|
||||
* Copyright 2023 Armin Novak <armin.novak@thincast.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
class SDLResourceManager
|
||||
{
|
||||
friend class SDLResourceFile;
|
||||
|
||||
public:
|
||||
SDLResourceManager() = delete;
|
||||
SDLResourceManager(const SDLResourceManager& other) = delete;
|
||||
SDLResourceManager(const SDLResourceManager&& other) = delete;
|
||||
~SDLResourceManager() = delete;
|
||||
SDLResourceManager operator=(const SDLResourceManager& other) = delete;
|
||||
SDLResourceManager& operator=(SDLResourceManager&& other) = delete;
|
||||
|
||||
[[nodiscard]] static std::string typeFonts();
|
||||
[[nodiscard]] static std::string typeImages();
|
||||
|
||||
protected:
|
||||
static void insert(const std::string& type, const std::string& id,
|
||||
const std::vector<unsigned char>& data);
|
||||
|
||||
[[nodiscard]] static const std::vector<unsigned char>* data(const std::string& type,
|
||||
const std::string& id);
|
||||
[[nodiscard]] static std::string filename(const std::string& type, const std::string& id);
|
||||
|
||||
[[nodiscard]] static bool useCompiledResources();
|
||||
|
||||
private:
|
||||
[[nodiscard]] static std::map<std::string, std::vector<unsigned char>>& resources();
|
||||
#if defined(SDL_USE_COMPILED_RESOURCES)
|
||||
static void init(); // implemented in generated file
|
||||
#endif
|
||||
};
|
||||
56
third_party/FreeRDP/client/SDL/common/scoped_guard.hpp
vendored
Normal file
56
third_party/FreeRDP/client/SDL/common/scoped_guard.hpp
vendored
Normal file
@@ -0,0 +1,56 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* SDL ScopeGuard
|
||||
*
|
||||
* Copyright 2024 Armin Novak <armin.novak@thincast.com>
|
||||
* Copyright 2024 Thincast Technologies GmbH
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <functional>
|
||||
|
||||
class ScopeGuard
|
||||
{
|
||||
public:
|
||||
template <class Callable> explicit ScopeGuard(Callable&& cleanupFunction)
|
||||
try : f(std::forward<Callable>(cleanupFunction))
|
||||
{
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
cleanupFunction();
|
||||
throw;
|
||||
}
|
||||
|
||||
~ScopeGuard()
|
||||
{
|
||||
if (f)
|
||||
f();
|
||||
}
|
||||
|
||||
void dismiss() noexcept
|
||||
{
|
||||
f = nullptr;
|
||||
}
|
||||
|
||||
ScopeGuard(const ScopeGuard&) = delete;
|
||||
ScopeGuard(ScopeGuard&& other) noexcept = delete;
|
||||
ScopeGuard& operator=(const ScopeGuard&) = delete;
|
||||
ScopeGuard& operator=(const ScopeGuard&&) = delete;
|
||||
|
||||
private:
|
||||
std::function<void()> f;
|
||||
};
|
||||
103
third_party/FreeRDP/client/SDL/common/sdl_common_utils.cpp
vendored
Normal file
103
third_party/FreeRDP/client/SDL/common/sdl_common_utils.cpp
vendored
Normal file
@@ -0,0 +1,103 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* SDL common utilitis
|
||||
*
|
||||
* Copyright 2025 Armin Novak <armin.novak@thincast.com>
|
||||
* Copyright 2025 Thincast Technologies GmbH
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "sdl_common_utils.hpp"
|
||||
|
||||
CriticalSection::CriticalSection()
|
||||
{
|
||||
InitializeCriticalSection(&_section);
|
||||
}
|
||||
|
||||
CriticalSection::~CriticalSection()
|
||||
{
|
||||
DeleteCriticalSection(&_section);
|
||||
}
|
||||
|
||||
void CriticalSection::lock()
|
||||
{
|
||||
EnterCriticalSection(&_section);
|
||||
}
|
||||
|
||||
void CriticalSection::unlock()
|
||||
{
|
||||
LeaveCriticalSection(&_section);
|
||||
}
|
||||
|
||||
WinPREvent::WinPREvent(bool initial) : _handle(CreateEventA(nullptr, TRUE, initial, nullptr))
|
||||
{
|
||||
}
|
||||
|
||||
WinPREvent::~WinPREvent()
|
||||
{
|
||||
(void)CloseHandle(_handle);
|
||||
}
|
||||
|
||||
void WinPREvent::set()
|
||||
{
|
||||
(void)SetEvent(_handle);
|
||||
}
|
||||
|
||||
void WinPREvent::clear()
|
||||
{
|
||||
(void)ResetEvent(_handle);
|
||||
}
|
||||
|
||||
bool WinPREvent::isSet() const
|
||||
{
|
||||
return WaitForSingleObject(_handle, 0) == WAIT_OBJECT_0;
|
||||
}
|
||||
|
||||
HANDLE WinPREvent::handle() const
|
||||
{
|
||||
return _handle;
|
||||
}
|
||||
|
||||
bool operator==(const rdpMonitor& l, const rdpMonitor& r)
|
||||
{
|
||||
if (l.x != r.x)
|
||||
return false;
|
||||
if (l.y != r.y)
|
||||
return false;
|
||||
if (l.width != r.width)
|
||||
return false;
|
||||
if (l.height != r.height)
|
||||
return false;
|
||||
if (l.is_primary != r.is_primary)
|
||||
return false;
|
||||
if (l.orig_screen != r.orig_screen)
|
||||
return false;
|
||||
|
||||
return l.attributes == r.attributes;
|
||||
}
|
||||
|
||||
bool operator==(const MONITOR_ATTRIBUTES& l, const MONITOR_ATTRIBUTES& r)
|
||||
{
|
||||
if (l.physicalWidth != r.physicalWidth)
|
||||
return false;
|
||||
if (l.physicalHeight != r.physicalHeight)
|
||||
return false;
|
||||
if (l.orientation != r.orientation)
|
||||
return false;
|
||||
if (l.desktopScaleFactor != r.desktopScaleFactor)
|
||||
return false;
|
||||
if (l.deviceScaleFactor != r.deviceScaleFactor)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
69
third_party/FreeRDP/client/SDL/common/sdl_common_utils.hpp
vendored
Normal file
69
third_party/FreeRDP/client/SDL/common/sdl_common_utils.hpp
vendored
Normal file
@@ -0,0 +1,69 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* SDL common utilitis
|
||||
*
|
||||
* Copyright 2025 Armin Novak <armin.novak@thincast.com>
|
||||
* Copyright 2025 Thincast Technologies GmbH
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <freerdp/settings_types.h>
|
||||
|
||||
using CStringPtr = std::unique_ptr<char, decltype(std::free)*>;
|
||||
|
||||
bool operator==(const MONITOR_ATTRIBUTES& l, const MONITOR_ATTRIBUTES& r);
|
||||
bool operator==(const rdpMonitor& l, const rdpMonitor& r);
|
||||
|
||||
class WinPREvent
|
||||
{
|
||||
public:
|
||||
explicit WinPREvent(bool initial = false);
|
||||
WinPREvent(const WinPREvent& other) = delete;
|
||||
WinPREvent(WinPREvent&& other) = delete;
|
||||
|
||||
WinPREvent& operator=(const WinPREvent& other) = delete;
|
||||
WinPREvent& operator=(WinPREvent&& other) = delete;
|
||||
|
||||
~WinPREvent();
|
||||
|
||||
void set();
|
||||
void clear();
|
||||
[[nodiscard]] bool isSet() const;
|
||||
|
||||
[[nodiscard]] HANDLE handle() const;
|
||||
|
||||
private:
|
||||
HANDLE _handle;
|
||||
};
|
||||
|
||||
class CriticalSection
|
||||
{
|
||||
public:
|
||||
CriticalSection();
|
||||
CriticalSection(const CriticalSection& other) = delete;
|
||||
CriticalSection(CriticalSection&& other) = delete;
|
||||
~CriticalSection();
|
||||
|
||||
CriticalSection& operator=(const CriticalSection& other) = delete;
|
||||
CriticalSection& operator=(const CriticalSection&& other) = delete;
|
||||
|
||||
void lock();
|
||||
void unlock();
|
||||
|
||||
private:
|
||||
CRITICAL_SECTION _section{};
|
||||
};
|
||||
243
third_party/FreeRDP/client/SDL/common/sdl_prefs.cpp
vendored
Normal file
243
third_party/FreeRDP/client/SDL/common/sdl_prefs.cpp
vendored
Normal file
@@ -0,0 +1,243 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* SDL Prefs
|
||||
*
|
||||
* Copyright 2022 Armin Novak <armin.novak@thincast.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#if __has_include(<filesystem>)
|
||||
#include <filesystem>
|
||||
#include <utility>
|
||||
namespace fs = std::filesystem;
|
||||
#elif __has_include(<experimental/filesystem>)
|
||||
#include <experimental/filesystem>
|
||||
namespace fs = std::experimental::filesystem;
|
||||
#else
|
||||
#error Could not find system header "<filesystem>" or "<experimental/filesystem>"
|
||||
#endif
|
||||
|
||||
#include "sdl_prefs.hpp"
|
||||
#include "sdl_common_utils.hpp"
|
||||
|
||||
#include <winpr/path.h>
|
||||
#include <winpr/config.h>
|
||||
#include <winpr/json.h>
|
||||
|
||||
#include <freerdp/version.h>
|
||||
#include <freerdp/settings.h>
|
||||
#include <freerdp/utils/helpers.h>
|
||||
|
||||
SdlPref::WINPR_JSONPtr SdlPref::get(bool systemConfigOnly) const
|
||||
{
|
||||
auto config = get_pref_file(systemConfigOnly);
|
||||
return { WINPR_JSON_ParseFromFile(config.c_str()), WINPR_JSON_Delete };
|
||||
}
|
||||
|
||||
WINPR_JSON* SdlPref::get_item(const std::string& key, bool systemConfigOnly) const
|
||||
{
|
||||
/* If we request a system setting or user settings are disabled */
|
||||
if (systemConfigOnly || !is_user_config_enabled())
|
||||
return get_item(_system_config, key);
|
||||
|
||||
/* Get the user setting */
|
||||
auto res = get_item(_config, key);
|
||||
|
||||
/* User setting does not exist, fall back to system setting */
|
||||
if (!res)
|
||||
res = get_item(_system_config, key);
|
||||
return res;
|
||||
}
|
||||
|
||||
WINPR_JSON* SdlPref::get_item(const WINPR_JSONPtr& config, const std::string& key) const
|
||||
{
|
||||
if (!config)
|
||||
return nullptr;
|
||||
return WINPR_JSON_GetObjectItemCaseSensitive(config.get(), key.c_str());
|
||||
}
|
||||
|
||||
bool SdlPref::get_bool(const WINPR_JSONPtr& config, const std::string& key, bool fallback) const
|
||||
{
|
||||
auto item = get_item(config, key);
|
||||
if (!item || !WINPR_JSON_IsBool(item))
|
||||
return fallback;
|
||||
return WINPR_JSON_IsTrue(item);
|
||||
}
|
||||
|
||||
bool SdlPref::is_user_config_enabled() const
|
||||
{
|
||||
auto& config = _system_config;
|
||||
if (!config)
|
||||
return true;
|
||||
return get_bool(config, "isUserConfigEnabled", true);
|
||||
}
|
||||
|
||||
std::string SdlPref::item_to_str(WINPR_JSON* item, const std::string& fallback)
|
||||
{
|
||||
if (!item || !WINPR_JSON_IsString(item))
|
||||
return fallback;
|
||||
auto str = WINPR_JSON_GetStringValue(item);
|
||||
if (!str)
|
||||
return {};
|
||||
return str;
|
||||
}
|
||||
|
||||
std::string SdlPref::get_string(const std::string& key, const std::string& fallback,
|
||||
bool systemConfigOnly) const
|
||||
{
|
||||
auto item = get_item(key, systemConfigOnly);
|
||||
return item_to_str(item, fallback);
|
||||
}
|
||||
|
||||
bool SdlPref::get_bool(const std::string& key, bool fallback, bool systemConfigOnly) const
|
||||
{
|
||||
auto& config = systemConfigOnly ? _system_config : _config;
|
||||
return get_bool(config, key, fallback);
|
||||
}
|
||||
|
||||
int64_t SdlPref::get_int(const std::string& key, int64_t fallback, bool systemConfigOnly) const
|
||||
{
|
||||
auto item = get_item(key, systemConfigOnly);
|
||||
if (!item || !WINPR_JSON_IsNumber(item))
|
||||
return fallback;
|
||||
auto val = WINPR_JSON_GetNumberValue(item);
|
||||
return static_cast<int64_t>(val);
|
||||
}
|
||||
|
||||
std::vector<std::string> SdlPref::get_array(const std::string& key,
|
||||
const std::vector<std::string>& fallback,
|
||||
bool systemConfigOnly) const
|
||||
{
|
||||
auto item = get_item(key, systemConfigOnly);
|
||||
if (!item || !WINPR_JSON_IsArray(item))
|
||||
return fallback;
|
||||
|
||||
std::vector<std::string> values;
|
||||
for (size_t x = 0; x < WINPR_JSON_GetArraySize(item); x++)
|
||||
{
|
||||
auto cur = WINPR_JSON_GetArrayItem(item, x);
|
||||
values.push_back(item_to_str(cur));
|
||||
}
|
||||
|
||||
return values;
|
||||
}
|
||||
|
||||
void SdlPref::print_config_file_help(int version)
|
||||
{
|
||||
#if defined(WITH_WINPR_JSON)
|
||||
const std::string url = "https://wiki.libsdl.org/SDL" + std::to_string(version);
|
||||
std::cout << "GLOBAL CONFIGURATION FILE" << std::endl;
|
||||
std::cout << std::endl;
|
||||
std::cout << " The SDL client supports some system defined configuration options."
|
||||
<< std::endl;
|
||||
std::cout << " Settings are stored in JSON format" << std::endl;
|
||||
std::cout << " The location is a system configuration file. Location for current machine is "
|
||||
<< SdlPref::instance()->get_pref_file(true) << std::endl;
|
||||
std::cout << std::endl;
|
||||
std::cout << " The following configuration options are supported:" << std::endl;
|
||||
std::cout << std::endl;
|
||||
std::cout << " isUserConfigEnabled" << std::endl;
|
||||
std::cout << " Allows to enable/disable user specific configuration files." << std::endl;
|
||||
std::cout << " Default enabled" << std::endl;
|
||||
std::cout << std::endl;
|
||||
std::cout << " All options of the following user configuration file are also supported here."
|
||||
<< std::endl;
|
||||
std::cout << std::endl;
|
||||
|
||||
std::cout << "CONFIGURATION FILE" << std::endl;
|
||||
std::cout << std::endl;
|
||||
std::cout << " The SDL client supports some user defined configuration options." << std::endl;
|
||||
std::cout << " Settings are stored in JSON format" << std::endl;
|
||||
std::cout << " The location is a per user file. Location for current user is "
|
||||
<< SdlPref::instance()->get_pref_file() << std::endl;
|
||||
std::cout
|
||||
<< " The XDG_CONFIG_HOME environment variable can be used to override the base directory."
|
||||
<< std::endl;
|
||||
std::cout << std::endl;
|
||||
std::cout << " The following configuration options are supported:" << std::endl;
|
||||
std::cout << std::endl;
|
||||
std::cout << " SDL_KeyModMask" << std::endl;
|
||||
std::cout << " Defines the key combination required for SDL client shortcuts."
|
||||
<< std::endl;
|
||||
std::cout << " Default KMOD_RSHIFT" << std::endl;
|
||||
std::cout << " An array of SDL_Keymod strings as defined at "
|
||||
""
|
||||
<< url << "/SDL_Keymod" << std::endl;
|
||||
std::cout << std::endl;
|
||||
std::cout << " SDL_Fullscreen" << std::endl;
|
||||
std::cout << " Toggles client fullscreen state." << std::endl;
|
||||
std::cout << " Default SDL_SCANCODE_RETURN." << std::endl;
|
||||
std::cout << " A string as "
|
||||
"defined at "
|
||||
<< url << "/SDLScancodeLookup" << std::endl;
|
||||
std::cout << std::endl;
|
||||
std::cout << " SDL_Minimize" << std::endl;
|
||||
std::cout << " Minimizes client windows." << std::endl;
|
||||
std::cout << " Default SDL_SCANCODE_M." << std::endl;
|
||||
std::cout << " A string as "
|
||||
"defined at "
|
||||
<< url << "/SDLScancodeLookup" << std::endl;
|
||||
std::cout << std::endl;
|
||||
std::cout << " SDL_Resizeable" << std::endl;
|
||||
std::cout << " Toggles local window resizeable state." << std::endl;
|
||||
std::cout << " Default SDL_SCANCODE_R." << std::endl;
|
||||
std::cout << " A string as "
|
||||
"defined at "
|
||||
<< url << "/SDLScancodeLookup" << std::endl;
|
||||
std::cout << std::endl;
|
||||
std::cout << " SDL_Grab" << std::endl;
|
||||
std::cout << " Toggles keyboard and mouse grab state." << std::endl;
|
||||
std::cout << " Default SDL_SCANCODE_G." << std::endl;
|
||||
std::cout << " A string as "
|
||||
"defined at "
|
||||
<< url << "/SDLScancodeLookup" << std::endl;
|
||||
std::cout << std::endl;
|
||||
std::cout << " SDL_Disconnect" << std::endl;
|
||||
std::cout << " Disconnects from the RDP session." << std::endl;
|
||||
std::cout << " Default SDL_SCANCODE_D." << std::endl;
|
||||
std::cout << " A string as defined at " << url << "/SDLScancodeLookup" << std::endl;
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
SdlPref::SdlPref(std::string file)
|
||||
: _name(std::move(file)), _system_name(get_default_file(true)), _config(get(false)),
|
||||
_system_config(get(true))
|
||||
{
|
||||
}
|
||||
|
||||
std::string SdlPref::get_default_file(bool systemConfigOnly)
|
||||
{
|
||||
CStringPtr name(freerdp_GetConfigFilePath(systemConfigOnly, "sdl-freerdp.json"), free);
|
||||
fs::path config{ name.get() };
|
||||
return config.string();
|
||||
}
|
||||
|
||||
std::shared_ptr<SdlPref> SdlPref::instance(const std::string& name)
|
||||
{
|
||||
static std::shared_ptr<SdlPref> _instance;
|
||||
if (!_instance || (_instance->get_pref_file() != name))
|
||||
_instance.reset(new SdlPref(name));
|
||||
return _instance;
|
||||
}
|
||||
|
||||
std::string SdlPref::get_pref_file(bool systemConfigOnly) const
|
||||
{
|
||||
if (systemConfigOnly)
|
||||
return _system_name;
|
||||
|
||||
return _name;
|
||||
}
|
||||
69
third_party/FreeRDP/client/SDL/common/sdl_prefs.hpp
vendored
Normal file
69
third_party/FreeRDP/client/SDL/common/sdl_prefs.hpp
vendored
Normal file
@@ -0,0 +1,69 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* SDL Prefs
|
||||
*
|
||||
* Copyright 2022 Armin Novak <armin.novak@thincast.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#include <winpr/json.h>
|
||||
|
||||
class SdlPref
|
||||
{
|
||||
public:
|
||||
[[nodiscard]] static std::shared_ptr<SdlPref>
|
||||
instance(const std::string& name = SdlPref::get_default_file(false));
|
||||
|
||||
[[nodiscard]] std::string get_pref_file(bool systemConfigOnly = false) const;
|
||||
|
||||
[[nodiscard]] std::string get_string(const std::string& key, const std::string& fallback = "",
|
||||
bool systemConfigOnly = false) const;
|
||||
[[nodiscard]] int64_t get_int(const std::string& key, int64_t fallback = 0,
|
||||
bool systemConfigOnly = false) const;
|
||||
[[nodiscard]] bool get_bool(const std::string& key, bool fallback = false,
|
||||
bool systemConfigOnly = false) const;
|
||||
[[nodiscard]] std::vector<std::string> get_array(const std::string& key,
|
||||
const std::vector<std::string>& fallback = {},
|
||||
bool systemConfigOnly = false) const;
|
||||
|
||||
static void print_config_file_help(int version);
|
||||
|
||||
private:
|
||||
using WINPR_JSONPtr = std::unique_ptr<WINPR_JSON, decltype(&WINPR_JSON_Delete)>;
|
||||
|
||||
std::string _name;
|
||||
std::string _system_name;
|
||||
WINPR_JSONPtr _config;
|
||||
WINPR_JSONPtr _system_config;
|
||||
|
||||
explicit SdlPref(std::string file);
|
||||
|
||||
[[nodiscard]] WINPR_JSON* get_item(const std::string& key, bool systemConfigOnly) const;
|
||||
[[nodiscard]] WINPR_JSON* get_item(const WINPR_JSONPtr& config, const std::string& key) const;
|
||||
|
||||
[[nodiscard]] WINPR_JSONPtr get(bool systemConfigOnly) const;
|
||||
[[nodiscard]] bool get_bool(const WINPR_JSONPtr& config, const std::string& key,
|
||||
bool fallback = false) const;
|
||||
|
||||
[[nodiscard]] bool is_user_config_enabled() const;
|
||||
|
||||
[[nodiscard]] static std::string get_default_file(bool systemConfigOnly);
|
||||
[[nodiscard]] static std::string item_to_str(WINPR_JSON* item,
|
||||
const std::string& fallback = "");
|
||||
};
|
||||
39
third_party/FreeRDP/client/SDL/common/test/CMakeLists.txt
vendored
Normal file
39
third_party/FreeRDP/client/SDL/common/test/CMakeLists.txt
vendored
Normal file
@@ -0,0 +1,39 @@
|
||||
set(MODULE_NAME "TestSDL2")
|
||||
set(MODULE_PREFIX "TEST_SDL")
|
||||
|
||||
set(${MODULE_PREFIX}_DRIVER ${MODULE_NAME}.cpp)
|
||||
|
||||
set(${MODULE_PREFIX}_TESTS TestSDLPrefs.cpp TestSDLWebview.cpp)
|
||||
|
||||
disable_warnings_for_directory(${CMAKE_CURRENT_BINARY_DIR})
|
||||
|
||||
create_test_sourcelist(${MODULE_PREFIX}_SRCS ${${MODULE_PREFIX}_DRIVER} ${${MODULE_PREFIX}_TESTS})
|
||||
|
||||
include_directories("${CMAKE_CURRENT_SOURCE_DIR}/../aad")
|
||||
include_directories("${CMAKE_CURRENT_BINARY_DIR}/../aad")
|
||||
|
||||
add_executable(${MODULE_NAME} ${${MODULE_PREFIX}_SRCS})
|
||||
|
||||
set(${MODULE_PREFIX}_LIBS freerdp freerdp-client winpr sdl-common-prefs sdl-common-aad-view)
|
||||
|
||||
target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS})
|
||||
|
||||
set_target_properties(${MODULE_NAME} PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${TESTING_OUTPUT_DIRECTORY}")
|
||||
|
||||
set(TEST_SRC_AREA "${CMAKE_CURRENT_SOURCE_DIR}")
|
||||
set(TEST_BIN_AREA "${CMAKE_CURRENT_BINARY_DIR}")
|
||||
|
||||
if(WIN32)
|
||||
string(REPLACE "\\" "\\\\" TEST_SRC_AREA "${TEST_SRC_AREA}")
|
||||
string(REPLACE "\\" "\\\\" TEST_BIN_AREA "${TEST_BIN_AREA}")
|
||||
endif()
|
||||
|
||||
add_compile_definitions(TEST_SRC_AREA="${TEST_SRC_AREA}")
|
||||
add_compile_definitions(TEST_BIN_AREA="${TEST_BIN_AREA}")
|
||||
|
||||
foreach(test ${${MODULE_PREFIX}_TESTS})
|
||||
get_filename_component(TestName ${test} NAME_WE)
|
||||
add_test(${TestName} ${TESTING_OUTPUT_DIRECTORY}/${MODULE_NAME} ${TestName})
|
||||
endforeach()
|
||||
|
||||
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "FreeRDP/Client/Test")
|
||||
121
third_party/FreeRDP/client/SDL/common/test/TestSDLPrefs.cpp
vendored
Normal file
121
third_party/FreeRDP/client/SDL/common/test/TestSDLPrefs.cpp
vendored
Normal file
@@ -0,0 +1,121 @@
|
||||
#include "../sdl_prefs.hpp"
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
|
||||
#include <winpr/config.h>
|
||||
#include <winpr/winpr.h>
|
||||
|
||||
#if __has_include(<filesystem>)
|
||||
#include <filesystem>
|
||||
namespace fs = std::filesystem;
|
||||
#elif __has_include(<experimental/filesystem>)
|
||||
#include <experimental/filesystem>
|
||||
namespace fs = std::experimental::filesystem;
|
||||
#else
|
||||
#error Could not find system header "<filesystem>" or "<experimental/filesystem>"
|
||||
#endif
|
||||
|
||||
static std::shared_ptr<SdlPref> instance()
|
||||
{
|
||||
#if !defined(TEST_SRC_AREA)
|
||||
#error "Please define TEST_SRC_AREA to the source directory of this test case"
|
||||
#endif
|
||||
fs::path src(TEST_SRC_AREA);
|
||||
src /= "sdl-freerdp.json";
|
||||
if (!fs::exists(src))
|
||||
{
|
||||
std::cerr << "[ERROR] test configuration file '" << src << "' does not exist" << std::endl;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return SdlPref::instance(src.string());
|
||||
}
|
||||
|
||||
int TestSDLPrefs(int argc, char* argv[])
|
||||
{
|
||||
WINPR_UNUSED(argc);
|
||||
WINPR_UNUSED(argv);
|
||||
|
||||
#if defined(WITH_WINPR_JSON)
|
||||
printf("implementation: json\n");
|
||||
#else
|
||||
printf("implementation: fallback\n");
|
||||
#endif
|
||||
|
||||
#if defined(WITH_WINPR_JSON)
|
||||
printf("config: %s\n", instance()->get_pref_file().c_str());
|
||||
#endif
|
||||
|
||||
auto string_value = instance()->get_string("string_key", "cba");
|
||||
#if defined(WITH_WINPR_JSON)
|
||||
if (string_value != "abc")
|
||||
return -1;
|
||||
#else
|
||||
if (string_value != "cba")
|
||||
return -1;
|
||||
#endif
|
||||
|
||||
auto string_value_nonexistent = instance()->get_string("string_key_nonexistent", "cba");
|
||||
if (string_value_nonexistent != "cba")
|
||||
return -1;
|
||||
|
||||
auto int_value = instance()->get_int("int_key", 321);
|
||||
#if defined(WITH_WINPR_JSON)
|
||||
if (int_value != 123)
|
||||
return -1;
|
||||
#else
|
||||
if (int_value != 321)
|
||||
return -1;
|
||||
#endif
|
||||
|
||||
auto int_value_nonexistent = instance()->get_int("int_key_nonexistent", 321);
|
||||
if (int_value_nonexistent != 321)
|
||||
return -1;
|
||||
|
||||
auto bool_value = instance()->get_bool("bool_key", false);
|
||||
#if defined(WITH_WINPR_JSON)
|
||||
if (!bool_value)
|
||||
return -1;
|
||||
#else
|
||||
if (bool_value)
|
||||
return -1;
|
||||
#endif
|
||||
|
||||
auto bool_value_nonexistent = instance()->get_bool("bool_key_nonexistent", false);
|
||||
if (bool_value_nonexistent)
|
||||
return -1;
|
||||
|
||||
auto array_value = instance()->get_array("array_key", { "c", "b", "a" });
|
||||
if (array_value.size() != 3)
|
||||
return -1;
|
||||
#if defined(WITH_WINPR_JSON)
|
||||
if (array_value.at(0) != "a")
|
||||
return -1;
|
||||
if (array_value.at(1) != "b")
|
||||
return -1;
|
||||
if (array_value.at(2) != "c")
|
||||
return -1;
|
||||
#else
|
||||
if (array_value.at(0) != "c")
|
||||
return -1;
|
||||
if (array_value.at(1) != "b")
|
||||
return -1;
|
||||
if (array_value.at(2) != "a")
|
||||
return -1;
|
||||
#endif
|
||||
|
||||
auto array_value_nonexistent =
|
||||
instance()->get_array("array_key_nonexistent", { "c", "b", "a" });
|
||||
if (array_value_nonexistent.size() != 3)
|
||||
return -1;
|
||||
|
||||
if (array_value_nonexistent.at(0) != "c")
|
||||
return -1;
|
||||
if (array_value_nonexistent.at(1) != "b")
|
||||
return -1;
|
||||
if (array_value_nonexistent.at(2) != "a")
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
30
third_party/FreeRDP/client/SDL/common/test/TestSDLWebview.cpp
vendored
Normal file
30
third_party/FreeRDP/client/SDL/common/test/TestSDLWebview.cpp
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <memory>
|
||||
|
||||
#include <winpr/config.h>
|
||||
#include <winpr/winpr.h>
|
||||
|
||||
#include <sdl_webview.hpp>
|
||||
|
||||
int TestSDLWebview(WINPR_ATTR_UNUSED int argc, WINPR_ATTR_UNUSED char* argv[])
|
||||
{
|
||||
#if 0
|
||||
RDP_CLIENT_ENTRY_POINTS entry = {};
|
||||
entry.Version = RDP_CLIENT_INTERFACE_VERSION;
|
||||
entry.Size = sizeof(RDP_CLIENT_ENTRY_POINTS_V1);
|
||||
entry.ContextSize = sizeof(rdpContext);
|
||||
|
||||
std::shared_ptr<rdpContext> context(freerdp_client_context_new(&entry),
|
||||
[](rdpContext* ptr) { freerdp_client_context_free(ptr); });
|
||||
|
||||
char* token = nullptr;
|
||||
if (!sdl_webview_get_access_token(context->instance, ACCESS_TOKEN_TYPE_AAD, &token, 2, "scope",
|
||||
"foobar"))
|
||||
{
|
||||
std::cerr << "test failed!" << std::endl;
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
10
third_party/FreeRDP/client/SDL/common/test/sdl-freerdp.json
vendored
Normal file
10
third_party/FreeRDP/client/SDL/common/test/sdl-freerdp.json
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"string_key": "abc",
|
||||
"int_key": 123,
|
||||
"bool_key": true,
|
||||
"array_key": [
|
||||
"a",
|
||||
"b",
|
||||
"c"
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user