Update codebase

This commit is contained in:
Hamza-Ayed
2026-08-09 16:56:13 +03:00
parent 95e2e4f35d
commit b64debaa88
1058 changed files with 164327 additions and 113928 deletions
@@ -1,4 +1,4 @@
import 'package:tripz_rider/print.dart';
import 'package:siro_rider/print.dart';
import 'dart:io';
// import 'package:flutter_sound/flutter_sound.dart';
@@ -1,8 +1,8 @@
import 'package:geolocator/geolocator.dart';
import 'package:intaleq_maps/intaleq_maps.dart';
import 'package:tripz_rider/constant/box_name.dart';
import 'package:tripz_rider/constant/country_polygons.dart';
import 'package:tripz_rider/main.dart';
import 'package:siro_rider/constant/box_name.dart';
import 'package:siro_rider/constant/country_polygons.dart';
import 'package:siro_rider/main.dart';
import '../../print.dart';
class CountryLogic {
@@ -159,8 +159,7 @@ class CountryLogic {
if (!serviceEnabled) return null;
LocationPermission permission = await Geolocator.checkPermission();
if (permission == LocationPermission.denied ||
permission == LocationPermission.deniedForever) {
if (permission == LocationPermission.denied || permission == LocationPermission.deniedForever) {
return null;
}
+91 -30
View File
@@ -1,12 +1,12 @@
import 'dart:async';
import 'dart:convert';
import 'package:tripz_rider/constant/box_name.dart';
import 'package:tripz_rider/constant/links.dart';
import 'package:tripz_rider/controller/auth/login_controller.dart';
import 'package:tripz_rider/main.dart';
import 'package:siro_rider/constant/box_name.dart';
import 'package:siro_rider/constant/links.dart';
import 'package:siro_rider/controller/auth/login_controller.dart';
import 'package:siro_rider/main.dart';
import 'package:get/get.dart';
import 'package:http/http.dart' as http;
import 'package:tripz_rider/env/env.dart';
import 'package:siro_rider/env/env.dart';
import '../../constant/api_key.dart';
@@ -24,7 +24,6 @@ class CRUD {
final NetGuard _netGuard = NetGuard();
final _client = SslPinning.createPinnedClient();
static bool _isRefreshingJWT = false;
static String _lastErrorSignature = '';
static DateTime _lastErrorTimestamp = DateTime(2000);
static const Duration _errorLogDebounceDuration = Duration(minutes: 1);
@@ -98,31 +97,50 @@ class CRUD {
Future<String> _getJwt() async {
try {
final String? encryptedJwt = await storage.read(key: BoxName.jwt);
if (encryptedJwt == null || encryptedJwt.isEmpty) {
final String? fallback = box.read(BoxName.jwt);
final jwt = await storage.read(key: BoxName.jwt);
if (jwt == null || jwt.toString().isEmpty) {
// إذا كان التخزين الآمن فارغاً، نحاول استخراج التوكن القديم من GetStorage للركاب القدامى
final fallback = box.read(BoxName.jwt);
if (fallback != null) {
return r(fallback).toString().split(Env.addd)[0];
try {
return r(fallback).toString().split(Env.addd)[0]; // فك تشفير القديم
} catch (_) {
return fallback.toString(); // ربما تم تخزينه بدون تشفير
}
}
return '';
}
return r(encryptedJwt).toString().split(Env.addd)[0];
} catch (e) {
Log.print('Error reading JWT from SecureStorage: $e');
final String? fallback = box.read(BoxName.jwt);
if (fallback != null) {
return r(fallback).toString().split(Env.addd)[0];
// التحقق السريع إذا كان التوكن لا يزال مشفراً (يبدأ برموز غريبة وليس ey)
if (!jwt.startsWith('ey')) {
try {
return r(jwt).toString().split(Env.addd)[0];
} catch (_) {}
}
return jwt;
} catch (_) {
return '';
}
}
// ═══════════════════════════════════════════════════════════════
// _ensureJwt — يضمن وجود توكن صالح قبل الإرسال
// ═══════════════════════════════════════════════════════════════
Future<String> _ensureJwt() async {
String token = await _getJwt();
if (_isJwtValid(token)) return token;
final ok = await Get.put(LoginController()).getJWT();
if (!ok) return '';
return await _getJwt();
}
/// Centralized request handler with retry for weak networks.
/// For Syria (3G): 60s total timeout, 3 retries, exponential backoff.
Future<dynamic> _makeRequest({
required String link,
Map<String, dynamic>? payload,
required Map<String, String> headers,
bool allowRefresh = true,
}) async {
const totalTimeout = Duration(seconds: 60);
@@ -180,17 +198,33 @@ class CRUD {
}
}
// 429 → السيرفر رافض بسبب الضغط؛ ممنوع نجدّد التوكن أو نعيد المحاولة
if (sc == 429) {
Log.print('🛑 [RES] 429 rate limited — $link');
return 'rate_limited';
}
// 401 → تجديد التوكن مرة واحدة ثم إعادة الطلب مرة واحدة فقط
if (sc == 401) {
// تخطي تجديد التوكن لـ endpoints غير حرجة (مثل تسجيل الأخطاء)
final isNonCritical = link.contains('errorApp.php');
if (!_isRefreshingJWT && !isNonCritical) {
_isRefreshingJWT = true;
try {
await Get.put(LoginController()).getJWT();
} finally {
_isRefreshingJWT = false;
}
}
return 'token_expired';
if (isNonCritical || !allowRefresh) return 'token_expired';
final refreshed = await Get.put(LoginController()).getJWT();
if (!refreshed) return 'token_expired';
final newToken = await _getJwt();
if (newToken.isEmpty) return 'token_expired';
// إعادة الطلب بالتوكن الجديد — allowRefresh: false يمنع أي تكرار إضافي
final retryHeaders = Map<String, String>.from(headers)
..['Authorization'] = 'Bearer $newToken';
return await _makeRequest(
link: link,
payload: payload,
headers: retryHeaders,
allowRefresh: false,
);
}
if (sc >= 500) {
@@ -206,7 +240,14 @@ class CRUD {
required String link,
Map<String, dynamic>? payload,
}) async {
String token = await _getJwt();
String token = await _ensureJwt();
if (token.isEmpty) {
// إذا فشل الحصول على توكن، لا ترسل الطلب للباك إند لأنّه سيرفض حتماً.
// باستثناء تسجيل الدخول لأنه لا يحتاج توكن
if (!link.contains('login') && !link.contains('errorApp.php')) {
return 'token_expired';
}
}
final headers = {
'Content-Type': 'application/x-www-form-urlencoded',
@@ -221,7 +262,12 @@ class CRUD {
required String link,
Map<String, dynamic>? payload,
}) async {
String token = await _getJwt();
String token = await _ensureJwt();
if (token.isEmpty) {
if (!link.contains('login') && !link.contains('errorApp.php')) {
return 'token_expired';
}
}
final headers = {
'Content-Type': 'application/x-www-form-urlencoded',
@@ -238,6 +284,16 @@ class CRUD {
// التغيير: إضافة X-Device-FP header
// 3 headers معاً: JWT + HMAC + FP
// ═══════════════════════════════════════════════════════════════
/// توكن المحفظة صار يُخزَّن ويُعاد استخدامه. لو رفضه السيرفر (توكن
/// مُلغى أو تغيّر سرّ التوقيع) نمسح النسخة المخزّنة كي يُطلب توكن
/// جديد في المحاولة التالية بدل أن نعلق على توكن ميت.
void _invalidateWalletJwtIfRejected(dynamic result) {
if (result == 'token_expired') {
Log.print('🗑️ توكن المحفظة مرفوض — مسح النسخة المخزّنة.');
box.remove(BoxName.walletJwt);
}
}
Future<dynamic> postWallet({
required String link,
Map<String, dynamic>? payload,
@@ -251,11 +307,13 @@ class CRUD {
'X-HMAC-Auth': hmac.toString(),
'X-Device-FP': _getFpHeader(),
};
Log.print('headers: $headers');
Log.print('payload: $payload');
Log.print('link: $link');
return await _makeRequest(link: link, payload: payload, headers: headers);
final result =
await _makeRequest(link: link, payload: payload, headers: headers);
_invalidateWalletJwtIfRejected(result);
return result;
}
Future<dynamic> getWallet({
@@ -272,7 +330,10 @@ class CRUD {
'X-Device-FP': _getFpHeader(),
};
return await _makeRequest(link: link, payload: payload, headers: headers);
final result =
await _makeRequest(link: link, payload: payload, headers: headers);
_invalidateWalletJwtIfRejected(result);
return result;
}
// =======================================================================
@@ -1,6 +1,6 @@
import 'dart:convert';
import 'dart:math';
import 'package:tripz_rider/env/env.dart';
import 'package:siro_rider/env/env.dart';
import 'package:encrypt/encrypt.dart' as encrypt;
import 'package:flutter/foundation.dart';
import 'package:secure_string_operations/secure_string_operations.dart';
@@ -42,6 +42,15 @@ class EncryptionHelper {
debugPrint("EncryptionHelper initialized successfully.");
}
/// Encrypts a string using AES-256-CBC with constant IV (deterministic)
/// Same input always produces the same output
String encryptDataCbc(String plainText) {
final cbcEncrypter =
encrypt.Encrypter(encrypt.AES(key, mode: encrypt.AESMode.cbc));
final encrypted = cbcEncrypter.encrypt(plainText, iv: iv);
return encrypted.base64;
}
/// ✅ FIX H-04: Encrypts a string using AES-256-GCM (new) with random IV
String encryptData(String plainText) {
try {
@@ -1,5 +1,5 @@
import 'package:geolocator/geolocator.dart';
import 'package:tripz_rider/services/geofencing_service.dart';
import 'package:siro_rider/services/geofencing_service.dart';
import 'package:get/get.dart';
import 'package:flutter/material.dart';
@@ -20,7 +20,7 @@ class GeoLocation {
// Prominent Disclosure for Background Location
bool? userAgreed = await Get.defaultDialog<bool>(
title: 'صلاحية الموقع'.tr,
middleText: 'يجمع تطبيق تريبز بيانات الموقع لتفعيل ميزة التتبع الجغرافي (Geofence) ولتمكين السائق من الوصول إليك بدقة وتتبع رحلتك حتى عندما يكون التطبيق في الخلفية أو مغلقاً.'.tr,
middleText: 'يجمع تطبيق سيرو بيانات الموقع لتفعيل ميزة التتبع الجغرافي (Geofence) ولتمكين السائق من الوصول إليك بدقة وتتبع رحلتك حتى عندما يكون التطبيق في الخلفية أو مغلقاً.'.tr,
titleStyle: const TextStyle(fontWeight: FontWeight.bold),
textConfirm: 'موافق'.tr,
textCancel: 'إلغاء'.tr,
@@ -53,7 +53,7 @@ class GeoLocation {
// Update Geofences based on the fresh location
try {
TripzGeofencingService.syncZonesWithServer(position.latitude, position.longitude);
SiroGeofencingService.syncZonesWithServer(position.latitude, position.longitude);
} catch (e) {
// Ignore errors so it doesn't break the main location flow
}
@@ -1,7 +1,7 @@
import 'package:tripz_rider/print.dart';
import 'package:siro_rider/print.dart';
import 'package:url_launcher/url_launcher.dart';
import 'dart:io';
import 'package:tripz_rider/controller/functions/country_logic.dart';
import 'package:siro_rider/controller/functions/country_logic.dart';
void showInBrowser(String url) async {
if (await canLaunchUrl(Uri.parse(url))) {
@@ -2,11 +2,11 @@
// import 'package:get/get.dart';
// import 'package:location/location.dart';
// import 'package:tripz_rider/constant/box_name.dart';
// import 'package:tripz_rider/constant/links.dart';
// import 'package:tripz_rider/controller/functions/crud.dart';
// import 'package:tripz_rider/controller/home/payment/captain_wallet_controller.dart';
// import 'package:tripz_rider/main.dart';
// import 'package:siro_rider/constant/box_name.dart';
// import 'package:siro_rider/constant/links.dart';
// import 'package:siro_rider/controller/functions/crud.dart';
// import 'package:siro_rider/controller/home/payment/captain_wallet_controller.dart';
// import 'package:siro_rider/main.dart';
// // LocationController.dart
// class LocationController extends GetxController {
@@ -2,26 +2,26 @@ import 'dart:io';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:tripz_rider/constant/box_name.dart';
import 'package:tripz_rider/constant/colors.dart';
import 'package:tripz_rider/constant/links.dart';
import 'package:tripz_rider/controller/functions/crud.dart';
import 'package:tripz_rider/main.dart';
import 'package:tripz_rider/onbording_page.dart';
import 'package:tripz_rider/views/widgets/elevated_btn.dart';
import 'package:tripz_rider/views/widgets/my_textField.dart';
import 'package:tripz_rider/views/widgets/error_snakbar.dart';
import 'package:siro_rider/constant/box_name.dart';
import 'package:siro_rider/constant/colors.dart';
import 'package:siro_rider/constant/links.dart';
import 'package:siro_rider/controller/functions/crud.dart';
import 'package:siro_rider/main.dart';
import 'package:siro_rider/onbording_page.dart';
import 'package:siro_rider/views/widgets/elevated_btn.dart';
import 'package:siro_rider/views/widgets/my_textField.dart';
import 'package:siro_rider/views/widgets/error_snakbar.dart';
import '../../constant/style.dart';
import 'package:tripz_rider/controller/home/map/map_socket_controller.dart';
import 'package:tripz_rider/controller/home/map/map_engine_controller.dart';
import 'package:tripz_rider/controller/home/map/location_search_controller.dart';
import 'package:tripz_rider/controller/home/map/nearby_drivers_controller.dart';
import 'package:tripz_rider/controller/home/map/ride_lifecycle_controller.dart';
import 'package:tripz_rider/controller/home/map/ui_interactions_controller.dart';
import 'package:tripz_rider/controller/home/menu_controller.dart';
import 'package:tripz_rider/controller/home/points_for_rider_controller.dart';
import 'package:tripz_rider/controller/functions/secure_storage.dart';
import 'package:siro_rider/controller/home/map/map_socket_controller.dart';
import 'package:siro_rider/controller/home/map/map_engine_controller.dart';
import 'package:siro_rider/controller/home/map/location_search_controller.dart';
import 'package:siro_rider/controller/home/map/nearby_drivers_controller.dart';
import 'package:siro_rider/controller/home/map/ride_lifecycle_controller.dart';
import 'package:siro_rider/controller/home/map/ui_interactions_controller.dart';
import 'package:siro_rider/controller/home/menu_controller.dart';
import 'package:siro_rider/controller/home/points_for_rider_controller.dart';
import 'package:siro_rider/controller/functions/secure_storage.dart';
class LogOutController extends GetxController {
TextEditingController checkTxtController = TextEditingController();
@@ -69,8 +69,8 @@ checkForBounusInvitation() {
void showUpdateDialog(BuildContext context) {
final String storeUrl = Platform.isAndroid
? 'https://play.google.com/store/apps/details?id=com.Tripz.tripz'
: 'https://apps.apple.com/jo/app/tripz-rider/id6748075179';
? 'https://play.google.com/store/apps/details?id=com.Siro.siro'
: 'https://apps.apple.com/jo/app/siro-rider/id6748075179';
showGeneralDialog(
context: context,
barrierDismissible: false,
@@ -190,15 +190,11 @@ void showUpdateDialog(BuildContext context) {
class DeviceHelper {
static Future<String> getDeviceFingerprint() async {
// ── التحقق من وجود بصمة مخزّنة مسبقاً ──────────────────────
// AES-GCM يستخدم IV عشوائي كل مرة، فالتشفير ينتج نتيجة مختلفة
// حتى لو النص الأصلي نفسه. لذلك نخزّن البصمة المشفرة أول مرة
// ونرجعها من التخزين في كل مرة بعدها لضمان الثبات.
final String? cachedFp = box.read(BoxName.deviceFpEncrypted);
if (cachedFp != null && cachedFp.isNotEmpty) {
return cachedFp;
}
// ── البصمة حتمية: AES-CBC بـ IV ثابت ────────────────────────
// نفس الجهاز ⇒ نفس الناتج دائماً، حتى بعد مسح بيانات التطبيق أو
// إعادة التثبيت. لذلك لا نعتمد على الكاش كمصدر للثبات (كان ضرورياً
// أيام AES-GCM بالـ IV العشوائي)، بل نعيد الحساب في كل مرة ونكتب
// القيمة في التخزين فقط لتقرأها بقية الشاشات.
final DeviceInfoPlugin deviceInfoPlugin = DeviceInfoPlugin();
var deviceData;
@@ -231,7 +227,7 @@ class DeviceHelper {
// Generate and return the encrypted fingerprint
final String fingerprint = '${deviceId}_$deviceModel';
final String encryptedFp =
EncryptionHelper.instance.encryptData(fingerprint);
EncryptionHelper.instance.encryptDataCbc(fingerprint);
box.write(BoxName.deviceFpEncrypted, encryptedFp);
//Log.print(EncryptionHelper.instance.encryptData(fingerprint));
return encryptedFp;
@@ -1,8 +1,8 @@
import 'dart:convert';
import 'package:tripz_rider/constant/box_name.dart';
import 'package:tripz_rider/constant/info.dart';
import 'package:tripz_rider/controller/auth/login_controller.dart';
import 'package:siro_rider/constant/box_name.dart';
import 'package:siro_rider/constant/info.dart';
import 'package:siro_rider/controller/auth/login_controller.dart';
import 'package:jwt_decoder/jwt_decoder.dart';
import '../../constant/links.dart';
@@ -1,4 +1,4 @@
import 'package:tripz_rider/print.dart';
import 'package:siro_rider/print.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:get/get.dart';
@@ -8,7 +8,7 @@ import '../../main.dart';
class SecurityChecks {
static const platform = MethodChannel(
'com.Tripz.tripz/security'); // Choose a unique channel name
'com.Siro.siro/security'); // Choose a unique channel name
static Future<bool> isDeviceCompromised() async {
try {
@@ -1,13 +1,13 @@
import 'dart:convert';
import 'package:tripz_rider/constant/api_key.dart';
import 'package:tripz_rider/constant/box_name.dart';
import 'package:tripz_rider/constant/info.dart';
import 'package:tripz_rider/constant/links.dart';
import 'package:tripz_rider/controller/auth/login_controller.dart';
import 'package:tripz_rider/env/env.dart';
import 'package:tripz_rider/main.dart';
import 'package:tripz_rider/views/widgets/elevated_btn.dart';
import 'package:siro_rider/constant/api_key.dart';
import 'package:siro_rider/constant/box_name.dart';
import 'package:siro_rider/constant/info.dart';
import 'package:siro_rider/constant/links.dart';
import 'package:siro_rider/controller/auth/login_controller.dart';
import 'package:siro_rider/env/env.dart';
import 'package:siro_rider/main.dart';
import 'package:siro_rider/views/widgets/elevated_btn.dart';
import 'package:get/get.dart';
import 'package:http/http.dart' as http;
@@ -8,11 +8,11 @@ class SslPinning {
SslPinning._();
static final Map<String, List<String>> _pins = {
'tripz.xyz': [
'intaleq.xyz': [
'/tNRUeeLxUhQU5gbgdpVWC6QBGAqc/ujg8Kcf0wQiAM=',
'Hlx/0EWNDH5Xkt2KzvqxUzbw0vvEsyZSlibialSyGqI=',
],
'tripzmove.com': [
'siromove.com': [
'C5+lpZ7tcVwmwQIMcRtPbsQtWLABXhQzejna0wHESsl=',
'diGVwiVYbubAI3RW4hB9xU8e/CH2GnkuvVFZE8zmgzI=',
],
@@ -1,7 +1,7 @@
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:tripz_rider/constant/colors.dart';
import 'package:tripz_rider/constant/style.dart';
import 'package:siro_rider/constant/colors.dart';
import 'package:siro_rider/constant/style.dart';
class Toast {
static void show(BuildContext context, String message, Color color) {
+1 -1
View File
@@ -1,5 +1,5 @@
import 'dart:io';
import 'package:tripz_rider/constant/box_name.dart';
import 'package:siro_rider/constant/box_name.dart';
import 'package:flutter/material.dart';
import 'package:flutter_tts/flutter_tts.dart';
import 'package:get/get.dart';
@@ -1,14 +1,14 @@
import 'dart:convert';
import 'dart:io';
import 'package:tripz_rider/constant/api_key.dart';
import 'package:siro_rider/constant/api_key.dart';
import 'package:get/get.dart';
import 'package:http/http.dart' as http;
import 'package:image_cropper/image_cropper.dart';
import 'package:image_picker/image_picker.dart';
import 'package:path/path.dart';
import 'package:secure_string_operations/secure_string_operations.dart';
import 'package:tripz_rider/views/widgets/error_snakbar.dart';
import 'package:siro_rider/views/widgets/error_snakbar.dart';
import '../../constant/box_name.dart';
import '../../constant/char_map.dart';