|
@@ -31,6 +31,7 @@
|
|
|
#include "core/os/file_access.h"
|
|
|
#include "core/os/os.h"
|
|
|
#include "editor/editor_export.h"
|
|
|
+#include "editor/editor_node.h"
|
|
|
#include "editor/editor_settings.h"
|
|
|
#include "platform/windows/logo.gen.h"
|
|
|
|
|
@@ -38,11 +39,22 @@ static Error fixup_embedded_pck(const String &p_path, int64_t p_embedded_start,
|
|
|
|
|
|
class EditorExportPlatformWindows : public EditorExportPlatformPC {
|
|
|
|
|
|
+ Error _code_sign(const Ref<EditorExportPreset> &p_preset, const String &p_path);
|
|
|
+
|
|
|
public:
|
|
|
virtual Error export_project(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags = 0);
|
|
|
+ virtual Error sign_shared_object(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path);
|
|
|
virtual void get_export_options(List<ExportOption> *r_options);
|
|
|
};
|
|
|
|
|
|
+Error EditorExportPlatformWindows::sign_shared_object(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path) {
|
|
|
+ if (p_preset->get("codesign/enable")) {
|
|
|
+ return _code_sign(p_preset, p_path);
|
|
|
+ } else {
|
|
|
+ return OK;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
Error EditorExportPlatformWindows::export_project(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags) {
|
|
|
Error err = EditorExportPlatformPC::export_project(p_preset, p_debug, p_path, p_flags);
|
|
|
|
|
@@ -133,12 +145,28 @@ Error EditorExportPlatformWindows::export_project(const Ref<EditorExportPreset>
|
|
|
OS::get_singleton()->execute(wine_path, args, true);
|
|
|
#endif
|
|
|
|
|
|
- return OK;
|
|
|
+ if (p_preset->get("codesign/enable") && err == OK) {
|
|
|
+ err = _code_sign(p_preset, p_path);
|
|
|
+ }
|
|
|
+
|
|
|
+ return err;
|
|
|
}
|
|
|
|
|
|
void EditorExportPlatformWindows::get_export_options(List<ExportOption> *r_options) {
|
|
|
EditorExportPlatformPC::get_export_options(r_options);
|
|
|
|
|
|
+ r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "codesign/enable"), false));
|
|
|
+#ifdef WINDOWS_ENABLED
|
|
|
+ r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "codesign/identity_type", PROPERTY_HINT_ENUM, "Select automatically,Use PKCS12 file (specify *.PFX/*.P12 file),Use certificate store (specify SHA1 hash)"), 0));
|
|
|
+#endif
|
|
|
+ r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "codesign/identity", PROPERTY_HINT_GLOBAL_FILE, "*.pfx,*.p12"), ""));
|
|
|
+ r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "codesign/password"), ""));
|
|
|
+ r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "codesign/timestamp"), true));
|
|
|
+ r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "codesign/timestamp_server_url"), ""));
|
|
|
+ r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "codesign/digest_algorithm", PROPERTY_HINT_ENUM, "SHA1,SHA256"), 1));
|
|
|
+ r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "codesign/description"), ""));
|
|
|
+ r_options->push_back(ExportOption(PropertyInfo(Variant::POOL_STRING_ARRAY, "codesign/custom_options"), PoolStringArray()));
|
|
|
+
|
|
|
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/icon", PROPERTY_HINT_FILE, "*.ico"), ""));
|
|
|
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/file_version", PROPERTY_HINT_PLACEHOLDER_TEXT, "1.0.0"), ""));
|
|
|
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/product_version", PROPERTY_HINT_PLACEHOLDER_TEXT, "1.0.0"), ""));
|
|
@@ -149,11 +177,164 @@ void EditorExportPlatformWindows::get_export_options(List<ExportOption> *r_optio
|
|
|
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/trademarks"), ""));
|
|
|
}
|
|
|
|
|
|
+Error EditorExportPlatformWindows::_code_sign(const Ref<EditorExportPreset> &p_preset, const String &p_path) {
|
|
|
+ List<String> args;
|
|
|
+
|
|
|
+#ifdef WINDOWS_ENABLED
|
|
|
+ String signtool_path = EditorSettings::get_singleton()->get("export/windows/signtool");
|
|
|
+ if (signtool_path != String() && !FileAccess::exists(signtool_path)) {
|
|
|
+ ERR_PRINTS("Could not find signtool executable at " + signtool_path + ", aborting.");
|
|
|
+ return ERR_FILE_NOT_FOUND;
|
|
|
+ }
|
|
|
+ if (signtool_path == String()) {
|
|
|
+ signtool_path = "signtool"; // try to run signtool from PATH
|
|
|
+ }
|
|
|
+#else
|
|
|
+ String signtool_path = EditorSettings::get_singleton()->get("export/windows/osslsigncode");
|
|
|
+ if (signtool_path != String() && !FileAccess::exists(signtool_path)) {
|
|
|
+ ERR_PRINTS("Could not find osslsigncode executable at " + signtool_path + ", aborting.");
|
|
|
+ return ERR_FILE_NOT_FOUND;
|
|
|
+ }
|
|
|
+ if (signtool_path == String()) {
|
|
|
+ signtool_path = "osslsigncode"; // try to run signtool from PATH
|
|
|
+ }
|
|
|
+#endif
|
|
|
+
|
|
|
+ args.push_back("sign");
|
|
|
+
|
|
|
+ //identity
|
|
|
+#ifdef WINDOWS_ENABLED
|
|
|
+ int id_type = p_preset->get("codesign/identity_type");
|
|
|
+ if (id_type == 0) { //auto select
|
|
|
+ args.push_back("/a");
|
|
|
+ } else if (id_type == 1) { //pkcs12
|
|
|
+ if (p_preset->get("codesign/identity") != "") {
|
|
|
+ args.push_back("/f");
|
|
|
+ args.push_back(p_preset->get("codesign/identity"));
|
|
|
+ } else {
|
|
|
+ EditorNode::add_io_error("codesign: no identity found");
|
|
|
+ return FAILED;
|
|
|
+ }
|
|
|
+ } else if (id_type == 2) { //Windows certificate store
|
|
|
+ if (p_preset->get("codesign/identity") != "") {
|
|
|
+ args.push_back("/sha1");
|
|
|
+ args.push_back(p_preset->get("codesign/identity"));
|
|
|
+ } else {
|
|
|
+ EditorNode::add_io_error("codesign: no identity found");
|
|
|
+ return FAILED;
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ EditorNode::add_io_error("codesign: invalid identity type");
|
|
|
+ return FAILED;
|
|
|
+ }
|
|
|
+#else
|
|
|
+ if (p_preset->get("codesign/identity") != "") {
|
|
|
+ args.push_back("-pkcs12");
|
|
|
+ args.push_back(p_preset->get("codesign/identity"));
|
|
|
+ } else {
|
|
|
+ EditorNode::add_io_error("codesign: no identity found");
|
|
|
+ return FAILED;
|
|
|
+ }
|
|
|
+#endif
|
|
|
+
|
|
|
+ //password
|
|
|
+ if (p_preset->get("codesign/password") != "") {
|
|
|
+#ifdef WINDOWS_ENABLED
|
|
|
+ args.push_back("/p");
|
|
|
+#else
|
|
|
+ args.push_back("-pass");
|
|
|
+#endif
|
|
|
+ args.push_back(p_preset->get("codesign/password"));
|
|
|
+ }
|
|
|
+
|
|
|
+ //timestamp
|
|
|
+ if (p_preset->get("codesign/timestamp")) {
|
|
|
+ if (p_preset->get("codesign/timestamp_server") != "") {
|
|
|
+#ifdef WINDOWS_ENABLED
|
|
|
+ args.push_back("/tr");
|
|
|
+ args.push_back(p_preset->get("codesign/timestamp_server_url"));
|
|
|
+ args.push_back("/td");
|
|
|
+ if ((int)p_preset->get("codesign/digest_algorithm") == 0) {
|
|
|
+ args.push_back("sha1");
|
|
|
+ } else {
|
|
|
+ args.push_back("sha256");
|
|
|
+ }
|
|
|
+#else
|
|
|
+ args.push_back("-ts");
|
|
|
+ args.push_back(p_preset->get("codesign/timestamp_server_url"));
|
|
|
+#endif
|
|
|
+ } else {
|
|
|
+ EditorNode::add_io_error("codesign: invalid timestamp server");
|
|
|
+ return FAILED;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ //digest
|
|
|
+#ifdef WINDOWS_ENABLED
|
|
|
+ args.push_back("/fd");
|
|
|
+#else
|
|
|
+ args.push_back("-h");
|
|
|
+#endif
|
|
|
+ if ((int)p_preset->get("codesign/digest_algorithm") == 0) {
|
|
|
+ args.push_back("sha1");
|
|
|
+ } else {
|
|
|
+ args.push_back("sha256");
|
|
|
+ }
|
|
|
+
|
|
|
+ //description
|
|
|
+ if (p_preset->get("codesign/description") != "") {
|
|
|
+#ifdef WINDOWS_ENABLED
|
|
|
+ args.push_back("/d");
|
|
|
+#else
|
|
|
+ args.push_back("-n");
|
|
|
+#endif
|
|
|
+ args.push_back(p_preset->get("codesign/description"));
|
|
|
+ }
|
|
|
+
|
|
|
+ //user options
|
|
|
+ PoolStringArray user_args = p_preset->get("codesign/custom_options");
|
|
|
+ for (int i = 0; i < user_args.size(); i++) {
|
|
|
+ String user_arg = user_args[i].strip_edges();
|
|
|
+ if (!user_arg.empty()) {
|
|
|
+ args.push_back(user_arg);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+#ifndef WINDOWS_ENABLED
|
|
|
+ args.push_back("-in");
|
|
|
+#endif
|
|
|
+ args.push_back(p_path);
|
|
|
+#ifndef WINDOWS_ENABLED
|
|
|
+ args.push_back("-out");
|
|
|
+ args.push_back(p_path);
|
|
|
+#endif
|
|
|
+
|
|
|
+ String str;
|
|
|
+ Error err = OS::get_singleton()->execute(signtool_path, args, true, NULL, &str, NULL, true);
|
|
|
+ ERR_FAIL_COND_V(err != OK, err);
|
|
|
+
|
|
|
+ print_line("codesign (" + p_path + "): " + str);
|
|
|
+#ifndef WINDOWS_ENABLED
|
|
|
+ if (str.find("SignTool Error") != -1) {
|
|
|
+#else
|
|
|
+ if (str.find("Failed") != -1) {
|
|
|
+#endif
|
|
|
+ return FAILED;
|
|
|
+ }
|
|
|
+
|
|
|
+ return OK;
|
|
|
+}
|
|
|
+
|
|
|
void register_windows_exporter() {
|
|
|
|
|
|
EDITOR_DEF("export/windows/rcedit", "");
|
|
|
EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::STRING, "export/windows/rcedit", PROPERTY_HINT_GLOBAL_FILE, "*.exe"));
|
|
|
-#ifndef WINDOWS_ENABLED
|
|
|
+#ifdef WINDOWS_ENABLED
|
|
|
+ EDITOR_DEF("export/windows/signtool", "");
|
|
|
+ EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::STRING, "export/windows/signtool", PROPERTY_HINT_GLOBAL_FILE, "*.exe"));
|
|
|
+#else
|
|
|
+ EDITOR_DEF("export/windows/osslsigncode", "");
|
|
|
+ EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::STRING, "export/windows/osslsigncode", PROPERTY_HINT_GLOBAL_FILE));
|
|
|
// On non-Windows we need WINE to run rcedit
|
|
|
EDITOR_DEF("export/windows/wine", "");
|
|
|
EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::STRING, "export/windows/wine", PROPERTY_HINT_GLOBAL_FILE));
|