diff --git a/ios/Runner/Info.plist b/ios/Runner/Info.plist
index bac0a92..02b5d74 100644
--- a/ios/Runner/Info.plist
+++ b/ios/Runner/Info.plist
@@ -61,6 +61,12 @@
UIApplicationSupportsIndirectInputEvents
NSCameraUsageDescription
- Камера нужна для сканирования QR-кода входа в веб-версию и приложение MAX на компьютере.
+ Камера нужна для съёмки фото и видео в чатах, сканирования QR-кода входа и работы веб-приложений.
+ NSMicrophoneUsageDescription
+ Микрофон нужен для записи голосовых сообщений, видео и звонков.
+ NSPhotoLibraryUsageDescription
+ Доступ к галерее нужен, чтобы отправлять фото и видео в чатах.
+ NSPhotoLibraryAddUsageDescription
+ Доступ к галерее нужен, чтобы сохранять полученные фото и видео.
diff --git a/lib/backend/api.dart b/lib/backend/api.dart
index a3fb613..43234f8 100644
--- a/lib/backend/api.dart
+++ b/lib/backend/api.dart
@@ -301,15 +301,15 @@ class Api {
/// Стрим всех входящих пушей от сервера.
Stream get pushStream => _dispatcher.pushStream;
- void dispose() {
+ Future dispose() async {
_autoReconnect = false;
_reconnectTimer?.cancel();
_cleanup();
_dispatcher.dispose();
- _connection.dispose();
- _stateController.close();
- _sessionExpiredController.close();
- _handshakeSuccessController.close();
+ await _connection.dispose();
+ await _stateController.close();
+ await _sessionExpiredController.close();
+ await _handshakeSuccessController.close();
}
// Внутрянка
diff --git a/lib/backend/modules/account.dart b/lib/backend/modules/account.dart
index 333f0d9..a71307d 100644
--- a/lib/backend/modules/account.dart
+++ b/lib/backend/modules/account.dart
@@ -19,6 +19,11 @@ String _normalizeAuthPhone(String phone) {
return '+$digits';
}
+String _maskPhone(String phone) {
+ if (phone.length <= 5) return '***';
+ return '${phone.substring(0, 3)}***${phone.substring(phone.length - 2)}';
+}
+
class PrivacyConfig {
final String searchByPhone;
final String incomingCall;
@@ -1408,7 +1413,7 @@ class AccountModule {
'language': language,
};
- logger.i('Запрос OTP-кода: phone=$normalizedPhone type=${type.value}');
+ logger.i('Запрос OTP-кода: phone=${_maskPhone(normalizedPhone)} type=${type.value}');
final packet = await _api.sendRequest(Opcode.authRequest, payload);
diff --git a/lib/backend/modules/chats.dart b/lib/backend/modules/chats.dart
index bcc1a7a..0699017 100644
--- a/lib/backend/modules/chats.dart
+++ b/lib/backend/modules/chats.dart
@@ -191,6 +191,7 @@ class ChatsModule {
static StreamSubscription? _globalPushSub;
static StreamSubscription? _globalStateSub;
+ static Future _pushQueue = Future.value();
static final Set _dirtyChats = {};
static final Set _knownChats = {};
@@ -203,7 +204,7 @@ class ChatsModule {
static void attachGlobalPushHandlers(Api api) {
_globalPushSub?.cancel();
_globalStateSub?.cancel();
- _globalPushSub = api.pushStream.listen(_handleGlobalPush);
+ _globalPushSub = api.pushStream.listen(_enqueueGlobalPush);
_globalStateSub = api.stateStream.listen(_handleSessionState);
if (api.state != SessionState.online) {
_markAllKnownChatsDirty();
@@ -240,6 +241,14 @@ class ChatsModule {
_dirtyChats.addAll(_knownChats);
}
+ static void _enqueueGlobalPush(Packet packet) {
+ _pushQueue = _pushQueue
+ .then((_) => _handleGlobalPush(packet))
+ .catchError((Object e) {
+ logger.w('Ошибка обработки пуша: $e');
+ });
+ }
+
static Future _handleGlobalPush(Packet packet) async {
switch (packet.opcode) {
case Opcode.notifMessage:
diff --git a/lib/backend/modules/digital_id.dart b/lib/backend/modules/digital_id.dart
index 19e4bb1..03a66ec 100644
--- a/lib/backend/modules/digital_id.dart
+++ b/lib/backend/modules/digital_id.dart
@@ -286,6 +286,7 @@ class DigitalIdModule {
await _send('DELETE', '/v3/digital-id/delete-profile');
final accountId = await TokenStorage.getActiveAccountId();
if (accountId != null) {
+ await TokenStorage.deleteSecure('${_tokenKey}_$accountId');
await AppDatabase.setSyncValue(accountId, _tokenKey, '');
}
}
@@ -293,14 +294,23 @@ class DigitalIdModule {
Future _storedToken() async {
final accountId = await TokenStorage.getActiveAccountId();
if (accountId == null) return null;
- final value = await AppDatabase.getSyncValue(accountId, _tokenKey);
- return (value != null && value.isNotEmpty) ? value : null;
+ final secureKey = '${_tokenKey}_$accountId';
+ final secured = await TokenStorage.readSecure(secureKey);
+ if (secured != null && secured.isNotEmpty) return secured;
+
+ final legacy = await AppDatabase.getSyncValue(accountId, _tokenKey);
+ if (legacy != null && legacy.isNotEmpty) {
+ await TokenStorage.writeSecure(secureKey, legacy);
+ await AppDatabase.setSyncValue(accountId, _tokenKey, '');
+ return legacy;
+ }
+ return null;
}
Future _saveToken(String token) async {
final accountId = await TokenStorage.getActiveAccountId();
if (accountId != null) {
- await AppDatabase.setSyncValue(accountId, _tokenKey, token);
+ await TokenStorage.writeSecure('${_tokenKey}_$accountId', token);
}
}
diff --git a/lib/backend/modules/file_uploader.dart b/lib/backend/modules/file_uploader.dart
index 3091e60..3dc5342 100644
--- a/lib/backend/modules/file_uploader.dart
+++ b/lib/backend/modules/file_uploader.dart
@@ -7,6 +7,7 @@ import '../api.dart';
import '../../core/config/proxy_config.dart';
import '../../core/protocol/opcode_map.dart';
import '../../core/transport/proxy_connector.dart';
+import '../../core/transport/tls_config.dart';
import '../../core/utils/logger.dart';
import 'messages.dart';
@@ -158,11 +159,12 @@ class FileUploader {
? await ProxyConnector(proxySettings).connect(uri.host, uri.port)
: await Socket.connect(uri.host, uri.port);
if (uri.scheme != 'https') return base;
- return SecureSocket.secure(
- base,
- host: uri.host,
- onBadCertificate: (_) => true,
- );
+ final allowInsecure = await TlsConfig.isInsecureAllowed();
+ if (allowInsecure) {
+ logger.w('TLS: проверка сертификата отключена (дебаг) — загрузка уязвима к MitM');
+ return SecureSocket.secure(base, host: uri.host, onBadCertificate: (_) => true);
+ }
+ return SecureSocket.secure(base, host: uri.host);
}
void _writeHeaders(
diff --git a/lib/backend/modules/messages.dart b/lib/backend/modules/messages.dart
index e893153..bbca3cb 100644
--- a/lib/backend/modules/messages.dart
+++ b/lib/backend/modules/messages.dart
@@ -250,6 +250,18 @@ class CachedMessage {
);
}
+ static List _decodeRows(List