瀏覽代碼

Merge pull request #69943 from timothyqiu/3.x-cherrypicks

Cherry-picks for the 3.x branch (future 3.6) - 9th batch
Rémi Verschelde 2 年之前
父節點
當前提交
495a1e3fb9

+ 3 - 0
.github/workflows/linux_builds.yml

@@ -72,6 +72,9 @@ jobs:
       - name: Setup python and scons
       - name: Setup python and scons
         uses: ./.github/actions/godot-deps
         uses: ./.github/actions/godot-deps
 
 
+      - name: Setup GCC problem matcher
+        uses: ammaraskar/gcc-problem-matcher@master
+
       - name: Compilation
       - name: Compilation
         uses: ./.github/actions/godot-build
         uses: ./.github/actions/godot-build
         with:
         with:

+ 3 - 0
.github/workflows/windows_builds.yml

@@ -45,6 +45,9 @@ jobs:
       - name: Setup python and scons
       - name: Setup python and scons
         uses: ./.github/actions/godot-deps
         uses: ./.github/actions/godot-deps
 
 
+      - name: Setup MSVC problem matcher
+        uses: ammaraskar/msvc-problem-matcher@master
+
       - name: Compilation
       - name: Compilation
         uses: ./.github/actions/godot-build
         uses: ./.github/actions/godot-build
         with:
         with:

+ 3 - 0
.gitignore

@@ -241,6 +241,8 @@ xcuserdata/
 [Rr]eleases/
 [Rr]eleases/
 x64/
 x64/
 x86/
 x86/
+# Not build results, this is Theora source code.
+!thirdparty/libtheora/x86/
 [Ww][Ii][Nn]32/
 [Ww][Ii][Nn]32/
 [Aa][Rr][Mm]/
 [Aa][Rr][Mm]/
 [Aa][Rr][Mm]64/
 [Aa][Rr][Mm]64/
@@ -317,6 +319,7 @@ _ReSharper*/
 
 
 # Others
 # Others
 ClientBin/
 ClientBin/
+enc_temp_folder/
 ~$*
 ~$*
 *.dbmdl
 *.dbmdl
 *.dbproj.schemaview
 *.dbproj.schemaview

+ 1 - 1
core/os/input_event.cpp

@@ -1099,7 +1099,7 @@ bool InputEventAction::shortcut_match(const Ref<InputEvent> &p_event, bool p_exa
 		return false;
 		return false;
 	}
 	}
 
 
-	return p_event->is_action(action);
+	return p_event->is_action(action, p_exact_match);
 }
 }
 
 
 bool InputEventAction::is_action(const StringName &p_action) const {
 bool InputEventAction::is_action(const StringName &p_action) const {

+ 2 - 1
core/os/os.cpp

@@ -39,6 +39,7 @@
 #include "servers/audio_server.h"
 #include "servers/audio_server.h"
 
 
 #include <stdarg.h>
 #include <stdarg.h>
+#include <thread>
 
 
 OS *OS::singleton = nullptr;
 OS *OS::singleton = nullptr;
 uint64_t OS::target_ticks = 0;
 uint64_t OS::target_ticks = 0;
@@ -525,7 +526,7 @@ String OS::get_unique_id() const {
 }
 }
 
 
 int OS::get_processor_count() const {
 int OS::get_processor_count() const {
-	return 1;
+	return std::thread::hardware_concurrency();
 }
 }
 
 
 String OS::get_processor_name() const {
 String OS::get_processor_name() const {

+ 2 - 1
doc/classes/Particles2D.xml

@@ -13,7 +13,8 @@
 	</description>
 	</description>
 	<tutorials>
 	<tutorials>
 		<link title="Particle systems (2D)">$DOCS_URL/tutorials/2d/particle_systems_2d.html</link>
 		<link title="Particle systems (2D)">$DOCS_URL/tutorials/2d/particle_systems_2d.html</link>
-		<link title="2D Dodge The Creeps Demo">https://godotengine.org/asset-library/asset/515</link>
+		<link title="2D Particles Demo">https://godotengine.org/asset-library/asset/118</link>
+		<link title="2D Dodge The Creeps Demo (uses GPUParticles2D for the trail behind the player)">https://godotengine.org/asset-library/asset/515</link>
 	</tutorials>
 	</tutorials>
 	<methods>
 	<methods>
 		<method name="capture_rect" qualifiers="const">
 		<method name="capture_rect" qualifiers="const">

+ 1 - 0
doc/classes/SceneTree.xml

@@ -375,6 +375,7 @@
 		</constant>
 		</constant>
 		<constant name="GROUP_CALL_UNIQUE" value="4" enum="GroupCallFlags">
 		<constant name="GROUP_CALL_UNIQUE" value="4" enum="GroupCallFlags">
 			Call a group only once even if the call is executed many times.
 			Call a group only once even if the call is executed many times.
+			[b]Note:[/b] Arguments are not taken into account when deciding whether the call is unique or not. Therefore when the same method is called with different arguments, only the first call will be performed.
 		</constant>
 		</constant>
 		<constant name="STRETCH_MODE_DISABLED" value="0" enum="StretchMode">
 		<constant name="STRETCH_MODE_DISABLED" value="0" enum="StretchMode">
 			No stretching.
 			No stretching.

+ 0 - 4
drivers/unix/os_unix.cpp

@@ -460,10 +460,6 @@ bool OS_Unix::set_environment(const String &p_var, const String &p_value) const
 	return setenv(p_var.utf8().get_data(), p_value.utf8().get_data(), /* overwrite: */ true) == 0;
 	return setenv(p_var.utf8().get_data(), p_value.utf8().get_data(), /* overwrite: */ true) == 0;
 }
 }
 
 
-int OS_Unix::get_processor_count() const {
-	return sysconf(_SC_NPROCESSORS_CONF);
-}
-
 String OS_Unix::get_user_data_dir() const {
 String OS_Unix::get_user_data_dir() const {
 	String appname = get_safe_dir_name(ProjectSettings::get_singleton()->get("application/config/name"));
 	String appname = get_safe_dir_name(ProjectSettings::get_singleton()->get("application/config/name"));
 	if (appname != "") {
 	if (appname != "") {

+ 0 - 2
drivers/unix/os_unix.h

@@ -95,8 +95,6 @@ public:
 	virtual bool set_environment(const String &p_var, const String &p_value) const;
 	virtual bool set_environment(const String &p_var, const String &p_value) const;
 	virtual String get_locale() const;
 	virtual String get_locale() const;
 
 
-	virtual int get_processor_count() const;
-
 	virtual void debug_break();
 	virtual void debug_break();
 	virtual void initialize_debugging();
 	virtual void initialize_debugging();
 
 

+ 4 - 2
modules/gdscript/doc_classes/@GDScript.xml

@@ -359,7 +359,7 @@
 		<method name="get_stack">
 		<method name="get_stack">
 			<return type="Array" />
 			<return type="Array" />
 			<description>
 			<description>
-				Returns an array of dictionaries representing the current call stack.
+				Returns an array of dictionaries representing the current call stack. See also [method print_stack].
 				[codeblock]
 				[codeblock]
 				func _ready():
 				func _ready():
 				    foo()
 				    foo()
@@ -374,6 +374,7 @@
 				[codeblock]
 				[codeblock]
 				[{function:bar, line:12, source:res://script.gd}, {function:foo, line:9, source:res://script.gd}, {function:_ready, line:6, source:res://script.gd}]
 				[{function:bar, line:12, source:res://script.gd}, {function:foo, line:9, source:res://script.gd}, {function:_ready, line:6, source:res://script.gd}]
 				[/codeblock]
 				[/codeblock]
+				[b]Note:[/b] [method get_stack] only works if the running instance is connected to a debugging server (i.e. an editor instance). [method get_stack] will not work in projects exported in release mode, or in projects exported in debug mode if not connected to a debugging server.
 			</description>
 			</description>
 		</method>
 		</method>
 		<method name="hash">
 		<method name="hash">
@@ -727,11 +728,12 @@
 		<method name="print_stack">
 		<method name="print_stack">
 			<return type="void" />
 			<return type="void" />
 			<description>
 			<description>
-				Prints a stack track at code location, only works when running with debugger turned on.
+				Prints a stack trace at the current code location. See also [method get_stack].
 				Output in the console would look something like this:
 				Output in the console would look something like this:
 				[codeblock]
 				[codeblock]
 				Frame 0 - res://test.gd:16 in function '_process'
 				Frame 0 - res://test.gd:16 in function '_process'
 				[/codeblock]
 				[/codeblock]
+				[b]Note:[/b] [method print_stack] only works if the running instance is connected to a debugging server (i.e. an editor instance). [method print_stack] will not work in projects exported in release mode, or in projects exported in debug mode if not connected to a debugging server.
 			</description>
 			</description>
 		</method>
 		</method>
 		<method name="printerr" qualifiers="vararg">
 		<method name="printerr" qualifiers="vararg">

+ 1 - 1
modules/regex/SCsub

@@ -58,10 +58,10 @@ if env["builtin_pcre2"]:
         env_pcre2["OBJSUFFIX"] = "_" + width + env_pcre2["OBJSUFFIX"]
         env_pcre2["OBJSUFFIX"] = "_" + width + env_pcre2["OBJSUFFIX"]
         env_pcre2.Append(CPPDEFINES=[("PCRE2_CODE_UNIT_WIDTH", width)])
         env_pcre2.Append(CPPDEFINES=[("PCRE2_CODE_UNIT_WIDTH", width)])
         env_pcre2.add_source_files(thirdparty_obj, thirdparty_sources)
         env_pcre2.add_source_files(thirdparty_obj, thirdparty_sources)
-        env.modules_sources += thirdparty_obj
 
 
     pcre2_builtin("16")
     pcre2_builtin("16")
     pcre2_builtin("32")
     pcre2_builtin("32")
+    env.modules_sources += thirdparty_obj
 
 
 
 
 # Godot source files
 # Godot source files

+ 1 - 1
platform/windows/crash_handler_windows.cpp

@@ -156,7 +156,7 @@ DWORD CrashHandlerException(EXCEPTION_POINTERS *ep) {
 		return EXCEPTION_CONTINUE_SEARCH;
 		return EXCEPTION_CONTINUE_SEARCH;
 	}
 	}
 
 
-	SymSetOptions(SymGetOptions() | SYMOPT_LOAD_LINES | SYMOPT_UNDNAME);
+	SymSetOptions(SymGetOptions() | SYMOPT_LOAD_LINES | SYMOPT_UNDNAME | SYMOPT_EXACT_SYMBOLS);
 	EnumProcessModules(process, &module_handles[0], module_handles.size() * sizeof(HMODULE), &cbNeeded);
 	EnumProcessModules(process, &module_handles[0], module_handles.size() * sizeof(HMODULE), &cbNeeded);
 	module_handles.resize(cbNeeded / sizeof(HMODULE));
 	module_handles.resize(cbNeeded / sizeof(HMODULE));
 	EnumProcessModules(process, &module_handles[0], module_handles.size() * sizeof(HMODULE), &cbNeeded);
 	EnumProcessModules(process, &module_handles[0], module_handles.size() * sizeof(HMODULE), &cbNeeded);

+ 0 - 10
platform/windows/os_windows.cpp

@@ -3339,16 +3339,6 @@ BOOL is_wow64() {
 	return wow64;
 	return wow64;
 }
 }
 
 
-int OS_Windows::get_processor_count() const {
-	SYSTEM_INFO sysinfo;
-	if (is_wow64())
-		GetNativeSystemInfo(&sysinfo);
-	else
-		GetSystemInfo(&sysinfo);
-
-	return sysinfo.dwNumberOfProcessors;
-}
-
 String OS_Windows::get_processor_name() const {
 String OS_Windows::get_processor_name() const {
 	const String id = "Hardware\\Description\\System\\CentralProcessor\\0";
 	const String id = "Hardware\\Description\\System\\CentralProcessor\\0";
 
 

+ 0 - 1
platform/windows/os_windows.h

@@ -552,7 +552,6 @@ public:
 
 
 	virtual String get_locale() const;
 	virtual String get_locale() const;
 
 
-	virtual int get_processor_count() const;
 	virtual String get_processor_name() const;
 	virtual String get_processor_name() const;
 
 
 	virtual LatinKeyboardVariant get_latin_keyboard_variant() const;
 	virtual LatinKeyboardVariant get_latin_keyboard_variant() const;

+ 1 - 1
platform/x11/joypad_linux.cpp

@@ -222,8 +222,8 @@ void JoypadLinux::monitor_joypads() {
 			}
 			}
 		}
 		}
 		closedir(input_directory);
 		closedir(input_directory);
+		usleep(1000000); // 1s
 	}
 	}
-	usleep(1000000); // 1s
 }
 }
 
 
 void JoypadLinux::close_joypads() {
 void JoypadLinux::close_joypads() {

+ 3 - 1
scene/2d/navigation_polygon.cpp

@@ -295,7 +295,9 @@ void NavigationPolygon::make_polygons_from_outlines() {
 
 
 	TriangulatorPartition tpart;
 	TriangulatorPartition tpart;
 	if (tpart.ConvexPartition_HM(&in_poly, &out_poly) == 0) { //failed!
 	if (tpart.ConvexPartition_HM(&in_poly, &out_poly) == 0) { //failed!
-		ERR_PRINT("NavigationPolygon: Convex partition failed!");
+		ERR_PRINT("NavigationPolygon: Convex partition failed! Failed to convert outlines to a valid NavigationMesh."
+				  "\nNavigationPolygon outlines can not overlap vertices or edges inside same outline or with other outlines or have any intersections."
+				  "\nAdd the outmost and largest outline first. To add holes inside this outline add the smaller outlines with opposite winding order.");
 		return;
 		return;
 	}
 	}
 
 

+ 1 - 1
scene/gui/range.cpp

@@ -78,7 +78,7 @@ void Range::Shared::emit_changed(const char *p_what) {
 
 
 void Range::set_value(double p_val) {
 void Range::set_value(double p_val) {
 	if (shared->step > 0) {
 	if (shared->step > 0) {
-		p_val = Math::round(p_val / shared->step) * shared->step;
+		p_val = Math::round((p_val - shared->min) / shared->step) * shared->step + shared->min;
 	}
 	}
 
 
 	if (_rounded_values) {
 	if (_rounded_values) {

+ 1 - 1
servers/physics/shape_sw.cpp

@@ -1967,7 +1967,7 @@ void HeightMapShapeSW::_get_cell(const Vector3 &p_point, int &r_x, int &r_y, int
 	Vector3 clamped_point(p_point);
 	Vector3 clamped_point(p_point);
 	clamped_point.x = CLAMP(p_point.x, pos_local.x, pos_local.x + aabb.size.x);
 	clamped_point.x = CLAMP(p_point.x, pos_local.x, pos_local.x + aabb.size.x);
 	clamped_point.y = CLAMP(p_point.y, pos_local.y, pos_local.y + aabb.size.y);
 	clamped_point.y = CLAMP(p_point.y, pos_local.y, pos_local.y + aabb.size.y);
-	clamped_point.z = CLAMP(p_point.z, pos_local.z, pos_local.x + aabb.size.z);
+	clamped_point.z = CLAMP(p_point.z, pos_local.z, pos_local.z + aabb.size.z);
 
 
 	r_x = (clamped_point.x < 0.0) ? (clamped_point.x - 0.5) : (clamped_point.x + 0.5);
 	r_x = (clamped_point.x < 0.0) ? (clamped_point.x - 0.5) : (clamped_point.x + 0.5);
 	r_y = (clamped_point.y < 0.0) ? (clamped_point.y - 0.5) : (clamped_point.y + 0.5);
 	r_y = (clamped_point.y < 0.0) ? (clamped_point.y - 0.5) : (clamped_point.y + 0.5);

+ 1 - 1
thirdparty/README.md

@@ -35,7 +35,7 @@ Includes some patches in the `patches` folder which have been sent upstream.
 ## certs
 ## certs
 
 
 - Upstream: Mozilla, via https://github.com/bagder/ca-bundle
 - Upstream: Mozilla, via https://github.com/bagder/ca-bundle
-- Version: git (7f33e7eb8472dbcf31fdcf50cd216c89a282825d, 2022)
+- Version: git (b2f7415648411b6fd7c298c6c92d6552f0165f60, 2022)
 - License: MPL 2.0
 - License: MPL 2.0
 
 
 
 

+ 48 - 2
thirdparty/certs/ca-certificates.crt

@@ -1,7 +1,7 @@
 ##
 ##
 ## Bundle of CA Root Certificates
 ## Bundle of CA Root Certificates
 ##
 ##
-## Certificate data from Mozilla as of: Tue Jul 19 14:20:01 2022 GMT
+## Certificate data from Mozilla as of: Fri Oct 21 16:14:43 2022 GMT
 ##
 ##
 ## This is a bundle of X.509 certificates of public Certificate Authorities
 ## This is a bundle of X.509 certificates of public Certificate Authorities
 ## (CA). These were automatically extracted from Mozilla's root certificates
 ## (CA). These were automatically extracted from Mozilla's root certificates
@@ -14,7 +14,7 @@
 ## Just configure this file as the SSLCACertificateFile.
 ## Just configure this file as the SSLCACertificateFile.
 ##
 ##
 ## Conversion done with mk-ca-bundle.pl version 1.29.
 ## Conversion done with mk-ca-bundle.pl version 1.29.
-## SHA256: 9bf3799611fb58197f61d45e71ce3dc19f30e7dd73731915872ce5108a7bb066
+## SHA256: 3ff8bd209b5f2e739b9f2b96eacb694a774114685b02978257824f37ff528f71
 ##
 ##
 
 
 
 
@@ -3458,3 +3458,49 @@ zPUwHQYDVR0OBBYEFP+CMXI++cRmbK04ntGwUYilkMz1MA4GA1UdDwEB/wQEAwIBBjAKBggqhkjO
 PQQDAwNpADBmAjEA5gVYaWHlLcoNy/EZCL3W/VGSGn5jVASQkZo1kTmZ+gepZpO6yGjUij/67W4W
 PQQDAwNpADBmAjEA5gVYaWHlLcoNy/EZCL3W/VGSGn5jVASQkZo1kTmZ+gepZpO6yGjUij/67W4W
 Aie3AjEA3VoXK3YdZUKWpqxdinlW2Iob35reX8dQj7FbcQwm32pAAOwzkSFxvmjkI6TZraE3
 Aie3AjEA3VoXK3YdZUKWpqxdinlW2Iob35reX8dQj7FbcQwm32pAAOwzkSFxvmjkI6TZraE3
 -----END CERTIFICATE-----
 -----END CERTIFICATE-----
+
+Security Communication RootCA3
+==============================
+-----BEGIN CERTIFICATE-----
+MIIFfzCCA2egAwIBAgIJAOF8N0D9G/5nMA0GCSqGSIb3DQEBDAUAMF0xCzAJBgNVBAYTAkpQMSUw
+IwYDVQQKExxTRUNPTSBUcnVzdCBTeXN0ZW1zIENPLixMVEQuMScwJQYDVQQDEx5TZWN1cml0eSBD
+b21tdW5pY2F0aW9uIFJvb3RDQTMwHhcNMTYwNjE2MDYxNzE2WhcNMzgwMTE4MDYxNzE2WjBdMQsw
+CQYDVQQGEwJKUDElMCMGA1UEChMcU0VDT00gVHJ1c3QgU3lzdGVtcyBDTy4sTFRELjEnMCUGA1UE
+AxMeU2VjdXJpdHkgQ29tbXVuaWNhdGlvbiBSb290Q0EzMIICIjANBgkqhkiG9w0BAQEFAAOCAg8A
+MIICCgKCAgEA48lySfcw3gl8qUCBWNO0Ot26YQ+TUG5pPDXC7ltzkBtnTCHsXzW7OT4rCmDvu20r
+hvtxosis5FaU+cmvsXLUIKx00rgVrVH+hXShuRD+BYD5UpOzQD11EKzAlrenfna84xtSGc4RHwsE
+NPXY9Wk8d/Nk9A2qhd7gCVAEF5aEt8iKvE1y/By7z/MGTfmfZPd+pmaGNXHIEYBMwXFAWB6+oHP2
+/D5Q4eAvJj1+XCO1eXDe+uDRpdYMQXF79+qMHIjH7Iv10S9VlkZ8WjtYO/u62C21Jdp6Ts9EriGm
+npjKIG58u4iFW/vAEGK78vknR+/RiTlDxN/e4UG/VHMgly1s2vPUB6PmudhvrvyMGS7TZ2crldtY
+XLVqAvO4g160a75BflcJdURQVc1aEWEhCmHCqYj9E7wtiS/NYeCVvsq1e+F7NGcLH7YMx3weGVPK
+p7FKFSBWFHA9K4IsD50VHUeAR/94mQ4xr28+j+2GaR57GIgUssL8gjMunEst+3A7caoreyYn8xrC
+3PsXuKHqy6C0rtOUfnrQq8PsOC0RLoi/1D+tEjtCrI8Cbn3M0V9hvqG8OmpI6iZVIhZdXw3/JzOf
+GAN0iltSIEdrRU0id4xVJ/CvHozJgyJUt5rQT9nO/NkuHJYosQLTA70lUhw0Zk8jq/R3gpYd0Vcw
+CBEF/VfR2ccCAwEAAaNCMEAwHQYDVR0OBBYEFGQUfPxYchamCik0FW8qy7z8r6irMA4GA1UdDwEB
+/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBDAUAA4ICAQDcAiMI4u8hOscNtybS
+YpOnpSNyByCCYN8Y11StaSWSntkUz5m5UoHPrmyKO1o5yGwBQ8IibQLwYs1OY0PAFNr0Y/Dq9HHu
+Tofjcan0yVflLl8cebsjqodEV+m9NU1Bu0soo5iyG9kLFwfl9+qd9XbXv8S2gVj/yP9kaWJ5rW4O
+H3/uHWnlt3Jxs/6lATWUVCvAUm2PVcTJ0rjLyjQIUYWg9by0F1jqClx6vWPGOi//lkkZhOpn2ASx
+YfQAW0q3nHE3GYV5v4GwxxMOdnE+OoAGrgYWp421wsTL/0ClXI2lyTrtcoHKXJg80jQDdwj98ClZ
+XSEIx2C/pHF7uNkegr4Jr2VvKKu/S7XuPghHJ6APbw+LP6yVGPO5DtxnVW5inkYO0QR4ynKudtml
++LLfiAlhi+8kTtFZP1rUPcmTPCtk9YENFpb3ksP+MW/oKjJ0DvRMmEoYDjBU1cXrvMUVnuiZIesn
+KwkK2/HmcBhWuwzkvvnoEKQTkrgc4NtnHVMDpCKn3F2SEDzq//wbEBrD2NCcnWXL0CsnMQMeNuE9
+dnUM/0Umud1RvCPHX9jYhxBAEg09ODfnRDwYwFMJZI//1ZqmfHAuc1Uh6N//g7kdPjIe1qZ9LPFm
+6Vwdp6POXiUyK+OVrCoHzrQoeIY8LaadTdJ0MN1kURXbg4NR16/9M51NZg==
+-----END CERTIFICATE-----
+
+Security Communication ECC RootCA1
+==================================
+-----BEGIN CERTIFICATE-----
+MIICODCCAb6gAwIBAgIJANZdm7N4gS7rMAoGCCqGSM49BAMDMGExCzAJBgNVBAYTAkpQMSUwIwYD
+VQQKExxTRUNPTSBUcnVzdCBTeXN0ZW1zIENPLixMVEQuMSswKQYDVQQDEyJTZWN1cml0eSBDb21t
+dW5pY2F0aW9uIEVDQyBSb290Q0ExMB4XDTE2MDYxNjA1MTUyOFoXDTM4MDExODA1MTUyOFowYTEL
+MAkGA1UEBhMCSlAxJTAjBgNVBAoTHFNFQ09NIFRydXN0IFN5c3RlbXMgQ08uLExURC4xKzApBgNV
+BAMTIlNlY3VyaXR5IENvbW11bmljYXRpb24gRUNDIFJvb3RDQTEwdjAQBgcqhkjOPQIBBgUrgQQA
+IgNiAASkpW9gAwPDvTH00xecK4R1rOX9PVdu12O/5gSJko6BnOPpR27KkBLIE+CnnfdldB9sELLo
+5OnvbYUymUSxXv3MdhDYW72ixvnWQuRXdtyQwjWpS4g8EkdtXP9JTxpKULGjQjBAMB0GA1UdDgQW
+BBSGHOf+LaVKiwj+KBH6vqNm+GBZLzAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAK
+BggqhkjOPQQDAwNoADBlAjAVXUI9/Lbu9zuxNuie9sRGKEkz0FhDKmMpzE2xtHqiuQ04pV1IKv3L
+snNdo4gIxwwCMQDAqy0Obe0YottT6SXbVQjgUMzfRGEWgqtJsLKB7HOHeLRMsmIbEvoWTSVLY70e
+N9k=
+-----END CERTIFICATE-----