Zum Hauptinhalt springen
tsecurity.de LIVE
Echtzeit-Radar & Feeds
Alle RSS Feeds
👥 Community & Social
Windows Tipps & SecurityNighthawk M7 Pro im Test: Flexibler, aber teurer 5G-Router(21.09.2026 um 10:30 Uhr)
Sichere ProgrammierungNeue Gmail-Funktion: So sparst du jetzt Zeit bei Einmalcodes(21.09.2026 um 10:00 Uhr)
Sichere ProgrammierungYour GIF exporter is fine — the container is the problem(21.09.2026 um 10:01 Uhr)
Sichere ProgrammierungCSS, Motion, or GSAP? I Choose by Who Owns the Animation(21.09.2026 um 10:12 Uhr)
Windows Tipps & SecurityNighthawk M7 Pro im Test: Flexibler, aber teurer 5G-Router(21.09.2026 um 10:30 Uhr)
Sichere ProgrammierungNeue Gmail-Funktion: So sparst du jetzt Zeit bei Einmalcodes(21.09.2026 um 10:00 Uhr)
Sichere ProgrammierungYour GIF exporter is fine — the container is the problem(21.09.2026 um 10:01 Uhr)
Sichere ProgrammierungCSS, Motion, or GSAP? I Choose by Who Owns the Animation(21.09.2026 um 10:12 Uhr)
Intelligence View
⚡ tsecurity.de Intelligence

How to Build a Flutter MRZ and VIN Scanner for Android, iOS, Web, Windows, and Linux

Benefiting from the cross-platform nature of Dynamsoft Capture Vision, we created flutter_ocr_sdk to enable MRZ recognition across Android, iOS, Web, Windows, and Linux. With the latest version of Dynamsoft Capture Vision, the plugin now…

0
↗ Quelle (dev.to)
Reagiere als Erste:r — dein Feedback zählt!

Benefiting from the cross-platform nature of Dynamsoft Capture Vision, we created flutter_ocr_sdk to enable MRZ recognition across Android, iOS, Web, Windows, and Linux. With the latest version of Dynamsoft Capture Vision, the plugin now supports VIN scanning as well, offering unified APIs across all platforms. In this article, we’ll cover how to add VIN capabilities to the existing Flutter plugin and how to build a cross-platform MRZ and VIN scanner app for Android, iOS, Web, Windows, and Linux.






Flutter MRZ/VIN Scanner Demo





  • Android






  • iOS






  • Web






  • Windows






  • Linux










Integrating Dynamsoft Capture Vision SDKs



In the following sections, we’ll walk through how to integrate Dynamsoft Capture Vision SDKs for each supported platform.






Desktop Integration



Download and unzip the Dynamsoft Capture Vision C++ SDK.



Due to the 100MB size limitation on pub.dev, we compress the model and template files into a zip archive and download it at runtime on on Windows and Linux.




import 'dart:io';
import 'package:path/path.dart' as p;
import 'package:http/http.dart' as http;
import 'package:archive/archive.dart';

const _zipUrl =
'https://github.com/yushulx/flutter_ocr_sdk/releases/download/v2.0.0/resources.zip';

const _zipName = 'resources.zip';

Future<void> download() async {
final execDir = Directory(p.dirname(Platform.resolvedExecutable));

final targetDir =
Platform.isWindows ? execDir : Directory(p.join(execDir.path, 'lib'));
targetDir.createSync(recursive: true);

final cacheDir =
Directory(p.join(Directory.systemTemp.path, 'flutter_ocr_sdk'));
cacheDir.createSync(recursive: true);
final zipCacheFile = File(p.join(cacheDir.path, _zipName));

if (!zipCacheFile.existsSync()) {
stdout.writeln('Downloading resources.zip to ${zipCacheFile.path} …');
final resp = await http.get(Uri.parse(_zipUrl));
if (resp.statusCode != 200) {
stderr.writeln('Failed to download ($_zipUrl): HTTP ${resp.statusCode}');
exit(1);
}
zipCacheFile.writeAsBytesSync(resp.bodyBytes);
stdout.writeln('✅ Cached zip in temp.');
} else {
stdout.writeln('✅ Using cached zip: ${zipCacheFile.path}');
}

final bytes = zipCacheFile.readAsBytesSync();
final archive = ZipDecoder().decodeBytes(bytes);
for (final file in archive) {
final outPath = p.join(targetDir.path, file.name);
if (file.isFile) {
final outFile = File(outPath);
outFile.createSync(recursive: true);
outFile.writeAsBytesSync(file.content as List<int>);
} else {
Directory(outPath).createSync(recursive: true);
}
}

stdout.writeln('✅ Resources unpacked to: ${targetDir.path}');
}









Windows





  1. Copy *.h, *.lib and *.dll files to your Flutter project Windows directory.





    • flutter_ocr_sdk/windows/include


    • flutter_ocr_sdk/windows/lib.

    • flutter_ocr_sdk/windows/bin




  2. Update CMakeLists.txt in the windows directory:


    cmake_minimum_required(VERSION 3.14)

    set(PROJECT_NAME "flutter_ocr_sdk")
    project(${PROJECT_NAME} LANGUAGES CXX)

    set(PLUGIN_NAME "flutter_ocr_sdk_plugin")

    link_directories("${PROJECT_SOURCE_DIR}/lib/")

    list(APPEND PLUGIN_SOURCES
    "flutter_ocr_sdk_plugin.cpp"
    "flutter_ocr_sdk_plugin.h"
    )

    add_library(${PLUGIN_NAME} SHARED
    "include/flutter_ocr_sdk/flutter_ocr_sdk_plugin_c_api.h"
    "flutter_ocr_sdk_plugin_c_api.cpp"
    ${PLUGIN_SOURCES}
    )

    apply_standard_settings(${PLUGIN_NAME})

    set_target_properties(${PLUGIN_NAME} PROPERTIES
    CXX_VISIBILITY_PRESET hidden)
    target_compile_definitions(${PLUGIN_NAME} PRIVATE FLUTTER_PLUGIN_IMPL)

    target_include_directories(${PLUGIN_NAME} INTERFACE
    "${CMAKE_CURRENT_SOURCE_DIR}/include")

    target_compile_options(${PLUGIN_NAME} PRIVATE /wd4121 /W3 /WX-)

    target_link_libraries(${PLUGIN_NAME} PRIVATE flutter flutter_wrapper_plugin "DynamsoftCorex64" "DynamsoftLicensex64" "DynamsoftCaptureVisionRouterx64" "DynamsoftUtilityx64")

    set(flutter_ocr_sdk_bundled_libraries
    "${PROJECT_SOURCE_DIR}/bin/"
    PARENT_SCOPE
    )








Linux





  1. Copy *.h, *.so files to your Flutter project Linux directory.





    • flutter_ocr_sdk/linux/include

    • flutter_ocr_sdk/linux/lib




  2. Update CMakeLists.txt in the linux directory:


    cmake_minimum_required(VERSION 3.10)

    set(PROJECT_NAME "flutter_ocr_sdk")
    project(${PROJECT_NAME} LANGUAGES CXX)

    set(PLUGIN_NAME "flutter_ocr_sdk_plugin")

    link_directories("${CMAKE_CURRENT_SOURCE_DIR}/lib")

    add_library(${PLUGIN_NAME} SHARED
    "flutter_ocr_sdk_plugin.cc"
    )

    apply_standard_settings(${PLUGIN_NAME})

    set_target_properties(${PLUGIN_NAME} PROPERTIES
    CXX_VISIBILITY_PRESET hidden)
    target_compile_definitions(${PLUGIN_NAME} PRIVATE FLUTTER_PLUGIN_IMPL)

    target_include_directories(${PLUGIN_NAME} INTERFACE
    "${CMAKE_CURRENT_SOURCE_DIR}/include")
    target_link_libraries(${PLUGIN_NAME} PRIVATE flutter "DynamsoftCore" "DynamsoftLicense" "DynamsoftCaptureVisionRouter" "DynamsoftUtility")
    target_link_libraries(${PLUGIN_NAME} PRIVATE PkgConfig::GTK)

    set_target_properties(${PLUGIN_NAME} PROPERTIES
    INSTALL_RPATH "$ORIGIN"
    BUILD_RPATH "$ORIGIN"
    )

    set(flutter_ocr_sdk_bundled_libraries
    ""
    PARENT_SCOPE
    )

    install(DIRECTORY
    "${PROJECT_SOURCE_DIR}/../linux/lib/"
    DESTINATION "${CMAKE_INSTALL_PREFIX}/lib/"
    )








Mobile Integration






Android



Add the following dependencies in android/build.gradle:




dependencies {
implementation "com.dynamsoft:dynamsoftcapturevisionbundle:2.6.1003"
implementation "com.dynamsoft:dynamsoftmrz:3.4.20"
implementation "com.dynamsoft:dynamsoftvin:3.4.20"
}






The dynamsoftcapturevisionbundle contains the core engine, while dynamsoftmrz and dynamsoftvin provide models for MRZ and VIN recognition respectively.






iOS



Add the following dependencies in ios/flutter_ocr_sdk.podspec:




s.dependency 'DynamsoftVIN', '3.4.20'
s.dependency 'DynamsoftMRZ', '3.4.20'
s.dependency 'DynamsoftCaptureVisionBundle', '2.6.1004'









Web Integration



Include the JavaScript library in index.html:




<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/dcv.bundle.min.js"></script>









API Overview and Implementation



The Flutter plugin provides the following four methods:






































Method Description Parameters Return Type
Future<int?> init(String key) Initializes the OCR SDK with a license key.
key: License string
Future<int?>
Future<List<List<OcrLine>>?> recognizeBuffer(Uint8List bytes, int width, int height, int stride, int format, int rotation) Performs OCR on a raw image buffer.
bytes: RGBA image buffer  
width, height: Image dimensions
stride: Row bytes
format: Pixel format index
rotation: 0/90/180/270
Future<List<List<OcrLine>>?>
Future<List<List<OcrLine>>?> recognizeFile(String filename) Performs OCR on an image file.
filename: Path to the image file
Future<List<List<OcrLine>>?>
Future<int?> loadModel({ModelType modelType = ModelType.mrz}) Loads the OCR model by type (mrz or vin).
modelType: Optional, defaults to ModelType.mrz
Future<int?>


To switch between MRZ and VIN scanning, call loadModel with the appropriate ModelType before using the recognition methods. Both recognizeBuffer and recognizeFile return a list of recognized lines, each containing either MRZ or VIN data.



The OcrLine class is defined as follows:





import 'mrz_result.dart';
import 'vin_result.dart';

class OcrLine {
int confidence = 0;
String text = '';

int x1 = 0, y1 = 0, x2 = 0, y2 = 0, x3 = 0, y3 = 0, x4 = 0, y4 = 0;

MrzResult? mrzResult;
VinResult? vinResult;

@override
String toString() {
String result = '';
result += 'Confidence: $confidence\n';
result += 'Text: $text\n';
result += 'x1: $x1\n';
result += 'y1: $y1\n';
result += 'x2: $x2\n';
result += 'y2: $y2\n';
result += 'x3: $x3\n';
result += 'y3: $y3\n';
result += 'x4: $x4\n';

if (mrzResult != null) {
result += mrzResult.toString();
}

if (vinResult != null) {
result += vinResult.toString();
}

return result;
}
}


class MrzResult {

String? type;
String? nationality;
String? surname;
String? givenName;
String? docNumber;
String? issuingCountry;
String? birthDate;
String? gender;
String? expiration;
String? lines;

MrzResult(
{String? type,
String? nationality,
String? surname,
String? givenName,
String? docNumber,
String? issuingCountry,
String? birthDate,
String? gender,
String? expiration,
String? lines})
: this.type = type ?? 'N/A',
this.nationality = nationality ?? 'N/A',
this.surname = surname ?? 'N/A',
this.givenName = givenName ?? 'N/A',
this.docNumber = docNumber ?? 'N/A',
this.issuingCountry = issuingCountry ?? 'N/A',
this.birthDate = birthDate ?? 'N/A',
this.gender = gender ?? 'N/A',
this.expiration = expiration ?? 'N/A',
this.lines = lines ?? 'N/A';

@override
String toString() {
if (type == null || type!.isEmpty) return "No results";

String result = '';

result += 'Type: $type\n\n';
result += 'Nationality: $nationality\n\n';
result += 'Surname: $surname\n\n';
result += 'Given name: $givenName\n\n';
result += 'Passport Number: $docNumber\n\n';
result += 'Issue Country: $issuingCountry\n\n';
result += 'Date of birth: $birthDate\n\n';
result += 'Gender: $gender\n\n';
result += 'Expiration: $expiration\n\n';

return result;
}

Map<String, dynamic> toJson() => {
'type': type ?? '',
'nationality': nationality ?? '',
'surname': surname ?? '',
'givenName': givenName ?? '',
'docNumber': docNumber ?? '',
'issuingCountry': issuingCountry ?? '',
'birthDate': birthDate ?? '',
'gender': gender ?? '',
'expiration': expiration ?? '',
'lines': lines,
};

factory MrzResult.fromJson(Map<String, dynamic> json) {
return MrzResult(
type: json['type'],
nationality: json['nationality'],
surname: json['surname'],
givenName: json['givenName'],
docNumber: json['docNumber'],
issuingCountry: json['issuingCountry'],
birthDate: json['birthDate'],
gender: json['gender'],
expiration: json['expiration'],
lines: json['lines'],
);
}
}

class VinResult {
String? vinString;
String? wmi;
String? region;
String? vds;
String? checkDigit;
String? modelYear;
String? plantCode;
String? serialNumber;

VinResult({
String? vinString,
String? wmi,
String? region,
String? vds,
String? checkDigit,
String? modelYear,
String? plantCode,
String? serialNumber,
}) : vinString = vinString ?? 'N/A',
wmi = wmi ?? 'N/A',
region = region ?? 'N/A',
vds = vds ?? 'N/A',
checkDigit = checkDigit ?? 'N/A',
modelYear = modelYear ?? 'N/A',
plantCode = plantCode ?? 'N/A',
serialNumber = serialNumber ?? 'N/A';

@override
String toString() {
return "VIN String: " +
vinString! +
"\n" +
"WMI: " +
wmi! +
"\n" +
"Region: " +
region! +
"\n" +
"VDS: " +
vds! +
"\n" +
"Check Digit: " +
checkDigit! +
"\n" +
"Model Year: " +
modelYear! +
"\n" +
"Manufacturer plant: " +
plantCode! +
"\n" +
"Serial Number: " +
serialNumber!;
}

Map<String, dynamic> toJson() => {
'vinString': vinString,
'wmi': wmi,
'region': region,
'vds': vds,
'checkDigit': checkDigit,
'modelYear': modelYear,
'plantCode': plantCode,
'serialNumber': serialNumber,
};

factory VinResult.fromJson(Map<String, dynamic> json) {
return VinResult(
vinString: json['vinString'],
wmi: json['wmi'],
region: json['region'],
vds: json['vds'],
checkDigit: json['checkDigit'],
modelYear: json['modelYear'],
plantCode: json['plantCode'],
serialNumber: json['serialNumber'],
);
}
}










Dart Method Implementation





  • init() initializes the SDK with a license key. It should be called before any recognition methods. For Windows and Linux, it also downloads the model and template files if they are not already present.


    @override
    Future<int?> init(String key) async {
    if (Platform.isLinux || Platform.isWindows) {
    await download();
    }
    return await methodChannel.invokeMethod<int>('init', {'key': key});
    }




  • loadModel() sets the OCR mode by loading the appropriate template:


    enum ModelType { mrz, vin }

    @override
    Future<int?> loadModel({ModelType modelType = ModelType.mrz}) async {
    String templateName = "ReadPassportAndId";

    if (modelType == ModelType.vin) {
    templateName = "ReadVINText";
    }

    int ret = await methodChannel
    .invokeMethod('loadModel', {'template': templateName});
    return ret;
    }




  • recognizeFile() performs OCR on an image file. It takes the file path as a parameter and returns a list of recognized lines.


    @override
    Future<List<List<OcrLine>>?> recognizeFile(String filename) async {
    List<dynamic>? results = await methodChannel.invokeMethod('recognizeFile', {
    'filename': filename,
    });

    if (results == null || results.isEmpty) return [];

    return _resultWrapper(results);
    }




  • recognizeBuffer() performs OCR on a raw image buffer. It takes the image data, dimensions, stride, pixel format, and rotation as parameters. The method returns a list of recognized lines.


    @override
    Future<List<List<OcrLine>>?> recognizeBuffer(Uint8List bytes, int width,
    int height, int stride, int format, int rotation) async {
    List<dynamic>? results =
    await methodChannel.invokeMethod('recognizeBuffer', {
    'bytes': bytes,
    'width': width,
    'height': height,
    'stride': stride,
    'format': format,
    'rotation': rotation
    });

    if (results == null || results.isEmpty) return [];

    return _resultWrapper(results);
    }








Platform-Specific Code



Dynamsoft Capture Vision provides both synchronous (capture()) and asynchronous (startCapturing()) recognition APIs. On the web, both are asynchronous.






Desktop (Windows/Linux)






CCaptureVisionRouter *cvr = new CCaptureVisionRouter;
CFileFetcher *fileFetcher = new CFileFetcher();

// File
fileFetcher->SetFile(filename);

// Buffer
CImageData *imageData = new CImageData(stride * height, buffer, width, height, stride, getPixelFormat(format), rotation);
fileFetcher->SetFile(imageData);

// Start capturing
char errorMsg[512] = {0};
int errorCode = cvr->StartCapturing(modelName.c_str(), false, errorMsg, 512);
if (errorCode != 0)
{
printf("StartCapturing: %s\n", errorMsg);
}









Android & iOS





  • Android


    // File
    final Result r = result;
    mExecutor.execute(new Runnable() {
    @Override
    public void run() {
    ArrayList<ArrayList<HashMap<String, Object>>> ret = null;
    CapturedResult results = null;
    try {
    results = mRouter.capture(fileName, templateName);
    ret = wrapResults(results);
    } catch (Exception e) {
    Log.e(TAG, e.toString());
    }

    final ArrayList<ArrayList<HashMap<String, Object>>> finalResults = ret;
    mHandler.post(new Runnable() {
    @Override
    public void run() {
    r.success(finalResults);
    }
    });

    }
    });

    // Buffer
    final Result r = result;
    mExecutor.execute(new Runnable() {
    @Override
    public void run() {
    ArrayList<ArrayList<HashMap<String, Object>>> ret = null;
    CapturedResult results = null;

    try {
    ImageData imageData = new ImageData();
    imageData.bytes = bytes;
    imageData.width = width;
    imageData.height = height;
    imageData.stride = stride;
    imageData.format = format;
    imageData.orientation = rotation;
    results = mRouter.capture(imageData, templateName);
    ret = wrapResults(results);
    } catch (Exception e) {
    Log.e(TAG, e.toString());
    }
    final ArrayList<ArrayList<HashMap<String, Object>>> finalResults = ret;
    mHandler.post(new Runnable() {
    @Override
    public void run() {
    r.success(finalResults);
    }
    });

    }
    });





  • iOS


    // File
    DispatchQueue.global().async {
    let filename: String = arguments.value(forKey: "filename") as! String
    let res = self.cvr.captureFromFile(filename, templateName: self.templateName)
    result(self.wrapResults(result: res))
    }

    // Buffer
    DispatchQueue.global().async {
    let buffer: FlutterStandardTypedData =
    arguments.value(forKey: "bytes") as! FlutterStandardTypedData
    let width: Int = arguments.value(forKey: "width") as! Int
    let height: Int = arguments.value(forKey: "height") as! Int
    let stride: Int = arguments.value(forKey: "stride") as! Int
    let format: Int = arguments.value(forKey: "format") as! Int
    let rotation: Int = arguments.value(forKey: "rotation") as! Int
    let enumImagePixelFormat = ImagePixelFormat(rawValue: format)
    let imageData = ImageData.init()
    imageData.bytes = buffer.data
    imageData.width = UInt(width)
    imageData.height = UInt(height)
    imageData.stride = UInt(stride)
    imageData.format = enumImagePixelFormat!
    imageData.orientation = rotation
    let res = self.cvr.captureFromBuffer(imageData, templateName: self.templateName)
    result(self.wrapResults(result: res))
    }








Web






@JS()
@anonymous
class CapturedItem {
external int get type;
external String get text;
external String get formatString;
external Location get location;
external int get angle;
external Uint8List get bytes;
external int get confidence;
}

@JS()
@anonymous
class CapturedResult {
external List<CapturedItem> get items;
}

@JS('CVR.CaptureVisionRouter')
class CaptureVisionRouter {
external static PromiseJsImpl<CaptureVisionRouter> createInstance();
external PromiseJsImpl<CapturedResult> capture(dynamic data, String template);
}

// File
CapturedResult capturedResult = await handleThenable(_cvr!.capture(file, modelName));

// Buffer
final dsImage = jsify({
'bytes': bytes,
'width': width,
'height': height,
'stride': stride,
'format': format,
'orientation': rotation
});

CapturedResult capturedResult = await handleThenable(_cvr!.capture(dsImage, modelName));









Updating the Example for MRZ and VIN Recognition





  1. Add ToggleButtons to switch between MRZ and VIN modes in home_page.dart:


    return Scaffold(
    body: Column(
    children: [
    title,
    description,
    Center(
    child: ToggleButtons(
    borderRadius: BorderRadius.circular(10),
    isSelected: [isMrzSelected, !isMrzSelected],
    selectedColor: Colors.white,
    fillColor: Colors.orange,
    color: Colors.grey,
    children: const [
    Padding(
    padding: EdgeInsets.symmetric(horizontal: 20),
    child: Text('MRZ'),
    ),
    Padding(
    padding: EdgeInsets.symmetric(horizontal: 20),
    child: Text('VIN'),
    ),
    ],
    onPressed: (index) {
    setState(() {
    isMrzSelected = (index == 0);
    if (isMrzSelected) {
    switchModel(ModelType.mrz);
    } else {
    switchModel(ModelType.vin);
    }
    });
    },
    ),
    ),
    ...
    ],
    ),
    );




  2. Request a trial license key for Dynamsoft Capture Vision and set it in global.dart:


    Future<int> initSDK() async {
    int? ret = await detector.init(
    "LICENSE-KEY");

    if (ret == 0) isLicenseValid = true;
    return await detector.loadModel(modelType: model) ?? -1;
    }





  3. Run the app on the target platform:


    cd example
    flutter run -d chrome # Run on Web
    flutter run -d linux # Run on Linux
    flutter run -d windows # Run on Windows
    flutter run # Run on default connected device (e.g., Android)



    Flutter Windows MRZ and VIN scanner








Source Code



https://github.com/yushulx/flutter_ocr_sdk

Ähnliche Beiträge
🔍 Verwandte News

Auch interessante Nachrichten How to Build a Flutter MRZ and VIN Scanner for Android, iOS, Web, Windows, and Linux

Thematisch verwandte Begriffe: Build, Flutter, Scanner, Android · 6 Treffer

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Zum Aktualisieren ziehen
ZERO-DAY CVE-2026-94036 | A security flaw has been discovered in D-Link DIR-X1860 and DIR-X1860Z u…
Advisory →
TTS Reader • tsecurity.de Voice
tsecurity.de Icon
tsecurity.de App
Offline-Lesen, Eilmeldungen & 0ms Ladezeit

Installiere tsecurity.de direkt auf deinen Home-Bildschirm für das ultimative Vollbild-Magazinerlebnis ohne Browser-Leisten.

Nächster Beitrag
Themen-Radar & Intelligence Matrix
Echtzeit-Taxonomie nach Angriffsvektoren & Plattformen

tsecurity.de Live Threat Radar

🔴 LIVE RADAR
MONITORING
AKTIV
CVE-DATENBANK
LIVE
🔍
Community Radar & Live Chat
Sentinel Bot online • Live-Stream
Dein Cluster: Security Explorer
Match:
lädt…
Verbindung zum Community-Stream wird aufgebaut...
Bearbeitungsmodus — Senden überschreibt deine Nachricht
Community-Puls — was gerade passiert
lädt…
Aktivitäten deiner Analysten
lädt…
Neues Thema oder Eilmeldung einreichen

Reiche interessante Links, Zero-Days oder Debatten ein. Die Community entscheidet per Upvote über die Veröffentlichung.

Heiß diskutierte Einreichungen
🔖 Gespeicherte Artikel
📂 Keine gespeicherten Artikel vorhanden.
Zurück Ziehen Vor
Links: vorheriger Artikel Rechts: nächster Artikel unten: schließen
News NIS-2 Frühwarnung Tier-1 Intel ⏱️ 3 Min vor 10 Min
Artikeldaten werden geladen...

Zurück: vorheriger Vor: nächster
↗ Original-Quelle
Social Reaktionen Deine Reaktion zählt
Einstufung & Relevanz-Poll 0 Stimmen
In sozialen Netzwerken teilen 1-Klick