diff --git a/.github/build.sh b/.github/build.sh index 8e17c3c93..452034477 100755 --- a/.github/build.sh +++ b/.github/build.sh @@ -369,7 +369,6 @@ zipalign = andriod_sdk_build_tools / 'zipalign' apksigner = andriod_sdk_build_tools / 'apksigner' ANDROID_INI meson_configure+=$'\t'--cross-file=.github/android-ghactions.ini - meson_configure+=$'\t'-Dhttp=false fi meson_configure+=$'\t'-Dc_args=[$c_args] meson_configure+=$'\t'-Dcpp_args=[$c_args] diff --git a/android/AndroidManifest.template.xml b/android/AndroidManifest.template.xml index 9f998578b..68ce6bbdc 100644 --- a/android/AndroidManifest.template.xml +++ b/android/AndroidManifest.template.xml @@ -33,7 +33,7 @@ android:name="android.hardware.type.pc" android:required="false" /> - + @ANDROID_PERMISSIONS@ aliases = ks.aliases(); + while (aliases.hasMoreElements()) { + String alias = (String)aliases.nextElement(); + java.security.cert.X509Certificate cert = (java.security.cert.X509Certificate)ks.getCertificate(alias); + allPems += "-----BEGIN CERTIFICATE-----\n" + Base64.getMimeEncoder().encodeToString(cert.getEncoded()) + "\n-----END CERTIFICATE-----\n";; + } + } + } catch (IOException e) { + e.printStackTrace(); + return ""; + } catch (KeyStoreException e) { + e.printStackTrace(); + return ""; + } catch (NoSuchAlgorithmException e) { + e.printStackTrace(); + return ""; + } catch (java.security.cert.CertificateException e) { + e.printStackTrace(); + return ""; + } + return allPems; + } } diff --git a/meson.build b/meson.build index cf9776775..a3b96320f 100644 --- a/meson.build +++ b/meson.build @@ -173,9 +173,6 @@ elif lua_variant == 'luajit' endif enable_http = get_option('http') -if host_platform == 'android' - enable_http = false -endif if host_platform == 'android' android_ndk_toolchain_prefix = meson.get_external_property('android_ndk_toolchain_prefix') android_platform = meson.get_external_property('android_platform') diff --git a/src/client/http/requestmanager/AndroidCertProvider.cpp b/src/client/http/requestmanager/AndroidCertProvider.cpp new file mode 100644 index 000000000..63ef6ccd9 --- /dev/null +++ b/src/client/http/requestmanager/AndroidCertProvider.cpp @@ -0,0 +1,86 @@ +#include "CurlError.h" +#include "common/String.h" +#include "Config.h" +#include +#include +#include +#include + +static jclass FindClass(JNIEnv *env, const char *name) +{ + jobject nativeActivity = (jobject)SDL_AndroidGetActivity(); if (!nativeActivity) return NULL; + jclass acl = env->GetObjectClass(nativeActivity); if (!acl ) return NULL; + jmethodID getClassLoader = env->GetMethodID(acl, "getClassLoader", "()Ljava/lang/ClassLoader;"); if (!getClassLoader) return NULL; + jobject cls = env->CallObjectMethod(nativeActivity, getClassLoader); if (!cls ) return NULL; + jclass classLoader = env->FindClass("java/lang/ClassLoader"); if (!classLoader ) return NULL; + jmethodID findClass = env->GetMethodID(classLoader, "loadClass", "(Ljava/lang/String;)Ljava/lang/Class;"); if (!findClass ) return NULL; + jstring strClassName = env->NewStringUTF(name); if (!strClassName ) return NULL; + jclass clazz = (jclass)(env->CallObjectMethod(cls, findClass, strClassName)); + env->DeleteLocalRef(strClassName); + return clazz; +} + +namespace http +{ + void UseSystemCertProvider(CURL *easy) + { + struct DoOnce + { + ByteString allPems; + + void InitPem() + { + auto die = [](ByteString message) { + __android_log_print(ANDROID_LOG_ERROR, "AndroidCertProvider", "%s", ("failed to enumerate system certificates: " + message).c_str()); + }; + auto *env = (JNIEnv *)SDL_AndroidGetJNIEnv(); + if (!env) + { + return die("SDL_AndroidGetJNIEnv failed"); + } + jclass mPowderActivity = FindClass(env, ByteString::Build(APPID, ".PowderActivity").c_str()); + if (!mPowderActivity) + { + return die("FindClass failed"); + } + jmethodID midGetCertificateBundle = env->GetStaticMethodID(mPowderActivity, "getCertificateBundle", "()Ljava/lang/String;"); + if (!midGetCertificateBundle) + { + return die("GetStaticMethodID failed"); + } + jstring str = (jstring)env->CallStaticObjectMethod(mPowderActivity, midGetCertificateBundle); + if (!str) + { + return die("getCertificateBundle failed"); + } + const char *utf = env->GetStringUTFChars(str, 0); + if (utf) + { + allPems = utf; + env->ReleaseStringUTFChars(str, utf); + } + else + { + __android_log_print(ANDROID_LOG_ERROR, "AndroidCertProvider", "out of memory???"); + } + env->DeleteLocalRef(str); + __android_log_print(ANDROID_LOG_ERROR, "AndroidCertProvider", "certificate bundle loaded"); + } + + DoOnce() + { + InitPem(); + } + }; + + static DoOnce doOnce; + if (doOnce.allPems.size()) + { + curl_blob blob; + blob.data = &doOnce.allPems[0]; + blob.len = doOnce.allPems.size(); + blob.flags = CURL_BLOB_COPY; + HandleCURLcode(curl_easy_setopt(easy, CURLOPT_CAINFO_BLOB, &blob)); + } + } +} diff --git a/src/client/http/requestmanager/meson.build b/src/client/http/requestmanager/meson.build index c2de3e7b1..94ae54646 100644 --- a/src/client/http/requestmanager/meson.build +++ b/src/client/http/requestmanager/meson.build @@ -13,6 +13,10 @@ else use_system_cert_provider = true client_files += files('WindowsCertProvider.cpp') endif + if host_platform == 'android' + use_system_cert_provider = true + client_files += files('AndroidCertProvider.cpp') + endif endif conf_data.set('NOHTTP', (not enable_http).to_string()) conf_data.set('USE_SYSTEM_CERT_PROVIDER', use_system_cert_provider.to_string()) diff --git a/src/gui/game/Tool.h b/src/gui/game/Tool.h index 97c3c9dd9..273b347b1 100644 --- a/src/gui/game/Tool.h +++ b/src/gui/game/Tool.h @@ -10,7 +10,7 @@ class Simulation; class Brush; class VideoBuffer; -class Particle; +struct Particle; class Tool { diff --git a/src/meson.build b/src/meson.build index 5894519a0..1ad17e6b3 100644 --- a/src/meson.build +++ b/src/meson.build @@ -49,6 +49,18 @@ conf_data.set('APPID', app_id) conf_data.set('APPDATA', get_option('app_data')) conf_data.set('APPVENDOR', get_option('app_vendor')) +if host_platform == 'android' + android_permissions = [ + '', + ] + if enable_http + android_permissions += [ + '', + ] + endif + conf_data.set('ANDROID_PERMISSIONS', '\n'.join(android_permissions)) +endif + powder_files = files( 'SDLCompat.cpp', 'PowderToySDL.cpp',