diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000000..bc0ade18a3 --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,46 @@ +on: [ push, pull_request ] +name: Build +jobs: + build: + name: OpenBubbles APK + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + + - name: Update submodules + run: git submodule update --init --recursive --remote + + - name: Free Disk Space (Ubuntu) + uses: jlumbroso/free-disk-space@main + with: + tool-cache: true + android: false + dotnet: true + haskell: true + large-packages: true + swap-storage: true + + - name: Set up Rust + uses: actions-rs/toolchain@v1 + with: + toolchain: stable + + - name: Set up Flutter + uses: subosito/flutter-action@v2 + with: + channel: stable + flutter-version: 3.24.0 + + - name: Set up Java + uses: actions/setup-java@v2 + with: + java-version: '21' + distribution: 'temurin' + + - name: Install Protobuf compiler + run: sudo apt-get install -y protobuf-compiler + + # First run is expected to fail until ffmpeg_kit_flutter_new is fixed. + - name: Run Build Script + run: | + ./build.sh \ No newline at end of file diff --git a/.gitignore b/.gitignore index 7e848794a5..43f6aef084 100644 --- a/.gitignore +++ b/.gitignore @@ -40,6 +40,10 @@ pubspeck.lock **/android/.settings **/releases +# Android +android/app/.cxx +android/local.properties + #objectbox .dart_tool/* !.dart_tool/build @@ -57,4 +61,8 @@ pubspeck.lock native-lib/target/** /rust/src/api/hw_testing.plist -/rust/src/api/id_testing.plist \ No newline at end of file +/rust/src/api/id_testing.plist + +# Android +android/app/local.properties +android/app/.gradle/** \ No newline at end of file diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000000..4a1b8001f5 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,8 @@ +[submodule "rustpush"] + path = rustpush + url = https://github.com/OpenBubbles/rustpush.git + branch = master +[submodule "android-smsmms"] + path = android-smsmms + url = https://github.com/OpenBubbles/android-smsmms.git + branch = master diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index db0adb5686..6c487ab178 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -44,6 +44,8 @@ In order to start contributing, follow these steps: 6. Pull the latest changes, or a specific branch you want to start from * Pull code from the main repository's master branch: `git pull upstream master` * Checkout a specific branch: `git checkout upstream ` +7. Initialize and update git submodules (required for building the Rust components) + * `git submodule update --init --recursive` ## Picking an Issue diff --git a/android-smsmms b/android-smsmms new file mode 160000 index 0000000000..36f34f482d --- /dev/null +++ b/android-smsmms @@ -0,0 +1 @@ +Subproject commit 36f34f482dd5546c929f448d746c3124875a4faa diff --git a/android/gradle.properties b/android/gradle.properties index 0961483fdc..3313a4d1da 100644 --- a/android/gradle.properties +++ b/android/gradle.properties @@ -1,3 +1,3 @@ -org.gradle.jvmargs=-Xmx4608M +org.gradle.jvmargs=-Xmx6400M android.useAndroidX=true android.enableJetifier=true diff --git a/android/settings.gradle b/android/settings.gradle index 616de4a171..f9a32e54ed 100644 --- a/android/settings.gradle +++ b/android/settings.gradle @@ -27,5 +27,6 @@ plugins { } include ":android-smsmms" -project(":android-smsmms").projectDir = file("/home/tae/Downloads/telephony_plus/android-smsmms/library") +project(":android-smsmms").projectDir = new File(rootProject.projectDir, "../android-smsmms/library") + include ":app" \ No newline at end of file diff --git a/build.sh b/build.sh new file mode 100755 index 0000000000..5a4c57fdd9 --- /dev/null +++ b/build.sh @@ -0,0 +1,28 @@ +#!/usr/bin/env bash + +# Pull submodules +git submodule update --init --recursive --remote + +# Set up fake certificates for FairPlay +mkdir -p rustpush/certs/fairplay + +cert_names=( + "4056631661436364584235346952193" + "4056631661436364584235346952194" + "4056631661436364584235346952195" + "4056631661436364584235346952196" + "4056631661436364584235346952197" + "4056631661436364584235346952198" + "4056631661436364584235346952199" + "4056631661436364584235346952200" + "4056631661436364584235346952201" + "4056631661436364584235346952208" +) + +for name in "${cert_names[@]}"; do + touch rustpush/certs/fairplay/$name.pem + touch rustpush/certs/fairplay/$name.crt +done + +# Build APK +flutter build apk --flavor alpha --debug --target-platform android-arm64 \ No newline at end of file diff --git a/ios/.gitignore b/ios/.gitignore index e96ef602b8..efcebfeecd 100644 --- a/ios/.gitignore +++ b/ios/.gitignore @@ -22,6 +22,7 @@ Flutter/app.flx Flutter/app.zip Flutter/flutter_assets/ Flutter/flutter_export_environment.sh +Flutter/ephemeral/** ServiceDefinitions.json Runner/GeneratedPluginRegistrant.* diff --git a/lib/services/backend/action_handler.dart b/lib/services/backend/action_handler.dart index 0a87019b8c..de593eb227 100644 --- a/lib/services/backend/action_handler.dart +++ b/lib/services/backend/action_handler.dart @@ -11,12 +11,12 @@ import 'package:bluebubbles/services/network/backend_service.dart'; import 'package:bluebubbles/utils/logger/logger.dart'; import 'package:collection/collection.dart'; import 'package:dio/dio.dart'; -import 'package:ffmpeg_kit_flutter/ffmpeg_kit.dart'; -import 'package:ffmpeg_kit_flutter/ffprobe_kit.dart'; -import 'package:ffmpeg_kit_flutter/log.dart'; -import 'package:ffmpeg_kit_flutter/return_code.dart'; -import 'package:ffmpeg_kit_flutter/session.dart'; -import 'package:ffmpeg_kit_flutter/statistics.dart'; +import 'package:ffmpeg_kit_flutter_new/ffmpeg_kit.dart'; +import 'package:ffmpeg_kit_flutter_new/ffprobe_kit.dart'; +import 'package:ffmpeg_kit_flutter_new/log.dart'; +import 'package:ffmpeg_kit_flutter_new/return_code.dart'; +import 'package:ffmpeg_kit_flutter_new/session.dart'; +import 'package:ffmpeg_kit_flutter_new/statistics.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart' hide Response; diff --git a/lib/services/rustpush/rustpush_service.dart b/lib/services/rustpush/rustpush_service.dart index d0575dc143..4e1d5a4b32 100644 --- a/lib/services/rustpush/rustpush_service.dart +++ b/lib/services/rustpush/rustpush_service.dart @@ -22,7 +22,7 @@ import 'package:bluebubbles/utils/crypto_utils.dart'; import 'package:bluebubbles/utils/logger/logger.dart'; import 'package:collection/collection.dart'; import 'package:crypto/crypto.dart'; -import 'package:ffmpeg_kit_flutter/ffmpeg_kit.dart'; +import 'package:ffmpeg_kit_flutter_new/ffmpeg_kit.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_rust_bridge/flutter_rust_bridge.dart'; diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift index 0d900698bb..9cae1dbfef 100644 --- a/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/macos/Flutter/GeneratedPluginRegistrant.swift @@ -13,7 +13,7 @@ import desktop_webview_auth import device_info_plus import dynamic_color import emoji_picker_flutter -import ffmpeg_kit_flutter +import ffmpeg_kit_flutter_new import file_selector_macos import flutter_image_compress_macos import flutter_inappwebview_macos diff --git a/pubspec.lock b/pubspec.lock index 8d3aa0bc0e..3855647f92 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -367,6 +367,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.4.2" + cli_config: + dependency: transitive + description: + name: cli_config + sha256: ac20a183a07002b700f0c25e61b7ee46b23c309d76ab7b7640a028f18e4d99ec + url: "https://pub.dev" + source: hosted + version: "0.2.0" cli_util: dependency: transitive description: @@ -443,10 +451,10 @@ packages: dependency: transitive description: name: coverage - sha256: "4b03e11f6d5b8f6e5bb5e9f7889a56fe6c5cbe942da5378ea4d4d7f73ef9dfe5" + sha256: "802bd084fb82e55df091ec8ad1553a7331b61c08251eef19a508b6f3f3a9858d" url: "https://pub.dev" source: hosted - version: "1.11.0" + version: "1.13.1" crop_your_image: dependency: "direct main" description: @@ -729,14 +737,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.3" - ffmpeg_kit_flutter: + ffmpeg_kit_flutter_new: dependency: "direct main" description: - name: ffmpeg_kit_flutter - sha256: "843aae41823ca94a0988d975b4b6cdc6948744b9b7e2707d81a3a9cd237b0100" + name: ffmpeg_kit_flutter_new + sha256: a6f881b2a41c8900733afef1806e069f58ab48e395174552e98157eb10d8adc0 url: "https://pub.dev" source: hosted - version: "6.0.3" + version: "3.2.0" ffmpeg_kit_flutter_platform_interface: dependency: transitive description: @@ -3124,9 +3132,11 @@ packages: telephony_plus: dependency: "direct main" description: - path: "/home/tae/Downloads/telephony_plus" - relative: false - source: path + path: "." + ref: "6db951e1e2e055e8ec844ccaf4319161f6fe6e3e" + resolved-ref: "6db951e1e2e055e8ec844ccaf4319161f6fe6e3e" + url: "https://github.com/stevesoltys/telephony_plus.git" + source: git version: "0.0.1" term_glyph: dependency: transitive diff --git a/pubspec.yaml b/pubspec.yaml index b7a9278209..0c808b0d21 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -202,10 +202,12 @@ dependencies: path: rust_builder freezed_annotation: ^2.4.1 telephony_plus: - path: /home/tae/Downloads/telephony_plus + git: + url: https://github.com/stevesoltys/telephony_plus.git + ref: 6db951e1e2e055e8ec844ccaf4319161f6fe6e3e barcode_widget: ^2.0.4 vpn_connection_detector: ^1.0.6 - ffmpeg_kit_flutter: 6.0.3 + ffmpeg_kit_flutter_new: ^3.2.0 dotted_border: ^2.1.0 external_path: ^2.0.1 flutter_inappwebview: ^6.1.5 @@ -332,7 +334,6 @@ flutter: - assets/badges/badge-10.ico - assets/rustpush/uti-map.json - assets/scripts/AppleAccountSetup.js - - .env # An image asset can refer to one or more resolution-specific "variants", see # https://flutter.dev/assets-and-images/#resolution-aware. # For details regarding adding assets from package dependencies, see diff --git a/rust/Cargo.toml b/rust/Cargo.toml index abb94fa8c9..6407054474 100644 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -8,14 +8,13 @@ crate-type = ["cdylib", "staticlib"] [dependencies] flutter_rust_bridge = "=2.3.0" -rustpush = { path = "/home/tae/Documents/GitHub/rustpush", features = ["macos-validation-data"] } +rustpush = { path = "../rustpush", features = ["macos-validation-data", "remote-anisette-v3"] } plist = "1.5.0" tokio = { version = "1", features = ["full"] } -serde = { version = "1.0", features = ["derive", "rc"] } +serde = { version = "1.0.219", features = ["derive", "rc"] } anyhow = "1.0.75" uniffi = { git = "https://github.com/mozilla/uniffi-rs", features = [ "cli", "tokio" ] } async-recursion = "1.0.5" -icloud_auth = { path = "/home/tae/Documents/GitHub/apple-private-apis/icloud-auth", default-features = false, features = ["remote-clearadi"] } prost = "0.12" # Only necessary if using Protobuf well-known types: prost-types = "0.12" diff --git a/rust/src/api/api.rs b/rust/src/api/api.rs index 1432c2db74..943f591ee9 100644 --- a/rust/src/api/api.rs +++ b/rust/src/api/api.rs @@ -4,7 +4,7 @@ use std::{borrow::{Borrow, BorrowMut}, collections::HashSet, fs::{self, File}, f pub use std::time::SystemTime; use anyhow::anyhow; use flutter_rust_bridge::{frb, IntoDart, JoinHandle}; -use icloud_auth::{default_provider, ArcAnisetteClient, LoginClientInfo}; +use rustpush::{default_provider, ArcAnisetteClient, LoginClientInfo}; use log::{debug, error, info, warn}; use plist::{Data, Dictionary}; pub use plist::Value; @@ -19,7 +19,7 @@ use rustpush::AnisetteProvider; pub use rustpush::findmy::{FindMyFriendsClient, FindMyPhoneClient}; pub use rustpush::sharedstreams::{SharedAlbum, SyncStatus}; pub use rustpush::cloudkit_proto::EscrowData; -pub use icloud_auth::DefaultAnisetteProvider; +pub use rustpush::DefaultAnisetteProvider; use uniffi::HandleAlloc; use rand::Rng; use uuid::Uuid; @@ -422,7 +422,7 @@ async fn restore(curr_state: &PushState) { if let Ok(mut lock) = inner.cancel_poll_recv.try_lock() { let _ = lock.try_recv(); } - + if needs_rereg { // mark rereg let _ = inner.client.as_ref().unwrap().identity.refresh_now().await; @@ -434,7 +434,7 @@ async fn restore(curr_state: &PushState) { if let Ok(mut state) = plist::from_file::<_, GSAConfig>(inner.conf_dir.join("gsa.plist")) { let mut apple_account = AppleAccount::new_with_anisette(get_login_config(&*inner).await, inner.anisette.clone().unwrap()).expect("aacbf?"); - + apple_account.username = Some(state.username.clone()); apple_account.hashed_password = Some(state.password.clone().into()); @@ -476,7 +476,7 @@ async fn restore(curr_state: &PushState) { } info!("heer"); - + let facetime_path = inner.conf_dir.join("facetime.plist"); let state: FTState = plist::from_file(&facetime_path).unwrap_or_default(); inner.ft_client = Some(FTClient::new(state, Box::new(move |state| { @@ -1861,8 +1861,8 @@ pub async fn get_quota_info(state: &Arc) -> anyhow::Result let info = inner.token_provider.as_ref().expect("No token provider!"); let storage_info = info.get_storage_info().await?; Ok(QuotaInfo { - total_bytes: storage_info.storage_data.quota_info_in_bytes.total_quota, - available_bytes: storage_info.storage_data.quota_info_in_bytes.total_available, + total_bytes: storage_info.storage_data.quota_info_in_bytes.total_quota, + available_bytes: storage_info.storage_data.quota_info_in_bytes.total_available, messages_bytes: storage_info.storage_usage_by_media.iter().find(|m| &m.media_key == "messages").map(|m| m.usage_in_bytes).unwrap_or(0), }) } @@ -1876,7 +1876,7 @@ struct GSAConfig { async fn do_login(conf_dir: &Path, account: &mut AppleAccount, cookie: Option<&str>, anisette: &ArcAnisetteClient, os_config: &dyn OSConfig) -> anyhow::Result { account.update_postdata("Apple Device", None, &["icloud", "imessage", "facetime"]).await?; - + let Some(pet) = account.get_pet() else { return Err(anyhow!("No pet!")) }; let Some(spd) = &account.spd else { return Err(anyhow!("No spd!")) }; @@ -1898,7 +1898,7 @@ async fn do_login(conf_dir: &Path, account: &mut AppleAccount, username: String, password: String let mut inner = state.0.write().await; let mut apple_account = AppleAccount::new_with_anisette(get_login_config(&*inner).await, inner.anisette.clone().unwrap())?; - + let mut password_hasher = sha2::Sha256::new(); password_hasher.update(&password.as_bytes()); let hashed_password = password_hasher.finalize(); @@ -2014,7 +2014,7 @@ pub async fn supports_keychain(state: &Arc) -> bool { pub async fn is_in_clique(state: &Arc) -> bool { let inner = state.0.read().await; let Some(keychain) = inner.keychain.clone() else { return false }; - + keychain.is_in_clique().await } @@ -2248,7 +2248,7 @@ pub async fn upload_cloud_attachments(state: &Arc, files: Vec<(String hashes.push(prepared.total_sig.clone()); to_upload.push((prepared, std::fs::File::open(file)?, record.clone())); } - + let results = cloud_messages_client.upload_attachments(to_upload).await?; let mut finish = HashMap::new(); @@ -2271,7 +2271,7 @@ pub async fn upload_group_photo(state: &Arc, files: Vec<(String, Stri hashes.push(prepared.total_sig.clone()); to_upload.push((prepared, std::fs::File::open(file)?, record.clone())); } - + let results = cloud_messages_client.upload_group_photo(to_upload).await?; let mut finish = HashMap::new(); diff --git a/rust/src/api/mirrors.rs b/rust/src/api/mirrors.rs index d59175af6b..2dbb65b1a9 100644 --- a/rust/src/api/mirrors.rs +++ b/rust/src/api/mirrors.rs @@ -4,8 +4,7 @@ pub use rustpush::name_photo_sharing::{IMessageNameRecord, IMessagePosterRecord, pub use rustpush::{DeleteTarget, MoveToRecycleBinMessage, OperatedChat}; pub use rustpush::{SetTranscriptBackgroundMessage, ShareProfileMessage, SharedPoster, UpdateProfileSharingMessage, UpdateProfileMessage, NSArrayClass, TextFlags, TextEffect, TextFormat, ScheduleMode, SupportAction, NSArray, SupportAlert, PrivateDeviceInfo, PermanentDeleteMessage, NormalMessage, MessageType, UpdateExtensionMessage, ErrorMessage, UnsendMessage, EditMessage, PartExtension, IconChangeMessage, RichLinkImageAttachmentSubstitute, ChangeParticipantMessage, ReactMessage, Reaction, ReactMessageType, RenameMessage, LPLinkMetadata, NSURL, LPIconMetadata, LPImageMetadata, LinkMeta, ExtensionApp, NSDictionaryClass, BalloonLayout, Balloon, IndexedMessagePart, AttachmentType, macos::MacOSConfig, Message, MessageTarget, macos::HardwareConfig, APSConnection, APSConnectionResource, APSState, Attachment, AuthPhone, IDSUserIdentity, MMCSFile, MessageInst, MessagePart, MessageParts, OSConfig, RelayConfig, ResourceState}; pub use rustpush::{TypingApp, ApsData, ApsAlert, AkData, IdmsCircleMessage, IdmsRequestedSignIn, TeardownSignIn, IdmsMessage, CertifiedContext, PushError, IDSUser, IMClient, ConversationData, ReportMessage, register}; -pub use icloud_auth::{VerifyBody, TrustedPhoneNumber}; -pub use icloud_auth::{LoginState, AppleAccount}; +pub use rustpush::{VerifyBody, TrustedPhoneNumber, LoginState, AppleAccount}; pub use rustpush::findmy::{Follow, Address, Location, FoundDevice}; pub use rustpush::facetime::{FTSession, FTMode, FTParticipant, FTMember, LetMeInRequest, FTMessage}; pub use rustpush::facetime::facetimep::{ConversationParticipant, ConversationLink}; diff --git a/rustpush b/rustpush new file mode 160000 index 0000000000..f8e5b87034 --- /dev/null +++ b/rustpush @@ -0,0 +1 @@ +Subproject commit f8e5b87034348bc472edb74f9ef14ec5ba15687e