diff --git a/lib/flutter_archive.dart b/lib/flutter_archive.dart index 5cdbf5e..38bc77d 100644 --- a/lib/flutter_archive.dart +++ b/lib/flutter_archive.dart @@ -214,3 +214,17 @@ class ZipEntry { final int? crc; final CompressionMethod? compressionMethod; } + +/// +/// Checks whether the file starts with the needed file header +/// +Future isZipFile(File file) async { + // https://en.wikipedia.org/wiki/ZIP_(file_format) + final randomAccessFile = file.openSync(mode: FileMode.read); + final bytes = await randomAccessFile.read(4); + return bytes.length > 3 && + bytes[0] == 0x50 && + bytes[1] == 0x4B && + bytes[2] == 0x03 && + bytes[3] == 0x04; +} diff --git a/pubspec.yaml b/pubspec.yaml index d6a97fe..4bccd20 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -11,10 +11,12 @@ environment: dependencies: flutter: sdk: flutter + dev_dependencies: flutter_test: sdk: flutter + mockito: ^5.0.16 # For information on the generic Dart part of this file, see the # following page: https://dart.dev/tools/pub/pubspec diff --git a/test/flutter_archive_test.dart b/test/flutter_archive_test.dart index 00a5538..823735f 100644 --- a/test/flutter_archive_test.dart +++ b/test/flutter_archive_test.dart @@ -1,10 +1,16 @@ +import 'dart:io'; +import 'dart:typed_data'; + import 'package:flutter/services.dart'; +import 'package:flutter_archive/flutter_archive.dart'; import 'package:flutter_test/flutter_test.dart'; +import 'package:mockito/mockito.dart'; void main() { const MethodChannel channel = MethodChannel('flutter_archive'); setUp(() { + TestWidgetsFlutterBinding.ensureInitialized(); channel.setMockMethodCallHandler((MethodCall methodCall) async { return true; }); @@ -17,4 +23,34 @@ void main() { test('getPlatformVersion', () async { // TODO }); + + test('isZipFile', () async { + expect(await isZipFile(MockFile(true)), true); + expect(await isZipFile(MockFile(false)), false); + }); +} + +class MockFile extends Mock implements File, RandomAccessFile { + final bool _isZipFile; + + MockFile(this._isZipFile); + + @override + Future open({FileMode mode = FileMode.read}) async { + return this; + } + + @override + RandomAccessFile openSync({FileMode mode = FileMode.read}) { + return this; + } + + @override + Future read(int count) async { + if (_isZipFile) { + return Uint8List.fromList([0x50, 0x4B, 0x03, 0x04]); + } else { + return Uint8List.fromList([]); + } + } }