Reads guarded legacy-compatible .apkg archives into AnkiIO's in-memory package model.
More...
Static Public Member Functions | |
| static async Task< AnkiPackage > | ReadAsync (string path, AnkiPackageLimits? limits=null, CancellationToken cancellationToken=default) |
| Reads a package file without modifying the source file or an Anki profile. | |
| static async Task< AnkiPackage > | ReadAsync (Stream source, AnkiPackageLimits? limits=null, CancellationToken cancellationToken=default) |
| Reads a package from a readable, seekable caller-owned stream and leaves it open. | |
Reads guarded legacy-compatible .apkg archives into AnkiIO's in-memory package model.
This reader treats the ZIP directory, entry names and sizes, media map, and SQLite database as untrusted. It validates AnkiPackageLimits and archive metadata before extracting the collection database or copying media. Limits mitigate common archive-exhaustion attacks but are not a sandbox; see AnkiPackageLimits for the threat model and choose smaller bounds for network uploads.
The supported input is a ZIP archive containing collection.anki2 and legacy JSON model/deck metadata. Collection schema values 11 and 18 are accepted only when that metadata is still JSON. Modern native entries such as collection.anki21, collection.anki21b, schema-18 protobuf metadata, and meta are not decoded. Anki 26.05 was verified to import the legacy representation written by AnkiIO; this reader does not claim general support for every package exported by that version.
Decks, notes, front/back templates, cards, supported scheduling fields, low three-bit card flags, descriptions, field editor settings, browser-only template formats, and mapped media are reconstructed. Review-log rows, deck configuration, graves, unknown SQLite columns, note/card auxiliary columns, and unsupported model metadata are not preserved. Consult AnkiPackage.Diagnostics after reading.
Media payloads are eagerly copied into AnkiPackage.Media and are not attached to individual decks. The returned package owns those copies and no archive handles, but may retain memory proportional to allowed media size. Separate calls may run concurrently when they use separate streams; returned graphs are mutable and not thread-safe.
Definition at line 43 of file AnkiPackageReader.cs.
|
inlinestatic |
Reads a package from a readable, seekable caller-owned stream and leaves it open.
| source | A readable, seekable stream containing the complete package archive. |
| limits | Optional archive defenses. null selects AnkiPackageLimits.Default. |
| cancellationToken | Cancels extraction, database reads, media copying, and JSON deserialization. |
Position source at the beginning of the complete ZIP archive before calling. The caller retains ownership and the stream remains open on success or failure. Its final position is unspecified and the original position is not restored. Do not read, write, seek, or dispose it concurrently. Seeking is required because the ZIP central directory must be inspected before extraction. The collection database is copied to an isolated temporary directory and removed afterward; media is copied eagerly into the returned package. Cancellation is observed by asynchronous stream, database, and media operations, not every synchronous metadata check.
| ArgumentNullException | source is null. |
| ArgumentException | source is not readable and seekable. |
| ArgumentOutOfRangeException | limits contains a non-positive count or byte bound, or a non-finite or non-positive compression ratio. |
| ObjectDisposedException | source has been disposed. |
| AnkiPackageSecurityException | The archive violates a configured size, ratio, count, path, link, or media-map safety rule. |
| NotSupportedException | The archive lacks supported legacy collection data or uses unsupported collection metadata. |
| InvalidDataException | The ZIP data or a supported package relationship is malformed. |
| JsonException | The media map or legacy JSON metadata is malformed. |
| Microsoft.Data.Sqlite.SqliteException | The extracted collection is not a readable supported SQLite database. |
| InvalidOperationException | Malformed content creates a conflicting media registration or invalid object relationship. |
| OutOfMemoryException | The process cannot allocate memory for an extracted media payload. |
| OverflowException | The aggregate uncompressed archive length cannot be represented by long. |
| UnauthorizedAccessException | The temporary workspace cannot be accessed. |
| IOException | The source, a temporary file, or a temporary directory cannot be read, written, or removed. |
| OperationCanceledException | cancellationToken is canceled. |
Definition at line 115 of file AnkiPackageReader.cs.
|
inlinestatic |
Reads a package file without modifying the source file or an Anki profile.
| path | The path of the legacy-compatible .apkg archive to read. |
| limits | Optional archive defenses. null selects AnkiPackageLimits.Default. |
| cancellationToken | Cancels extraction, database reads, media copying, and JSON deserialization. |
The source file is opened with read access and file sharing for other readers, and is closed before the task completes. The file is never modified and no Anki profile is opened. The collection database is extracted into an isolated temporary directory that is removed on success, cancellation, or failure. Media is copied eagerly into the returned package. Cancellation is observed by asynchronous file, database, and media operations; synchronous ZIP metadata validation is not individually cancelable.
| ArgumentNullException | path is null. |
| ArgumentException | path is blank or has invalid path syntax. |
| ArgumentOutOfRangeException | limits contains a non-positive count or byte bound, or a non-finite or non-positive compression ratio. |
| PathTooLongException | path exceeds a platform path-length limit. |
| FileNotFoundException | The package file does not exist. |
| DirectoryNotFoundException | A path directory does not exist. |
| UnauthorizedAccessException | The package or temporary workspace cannot be accessed. |
| AnkiPackageSecurityException | The archive violates a configured size, ratio, count, path, link, or media-map safety rule. |
| NotSupportedException | The archive lacks supported legacy collection data or uses unsupported collection metadata. |
| InvalidDataException | The ZIP data or a supported package relationship is malformed. |
| JsonException | The media map or legacy JSON metadata is malformed. |
| Microsoft.Data.Sqlite.SqliteException | The extracted collection is not a readable supported SQLite database. |
| InvalidOperationException | Malformed content creates a conflicting media registration or invalid object relationship. |
| OutOfMemoryException | The process cannot allocate memory for an extracted media payload. |
| OverflowException | The aggregate uncompressed archive length cannot be represented by long. |
| IOException | A package, temporary file, or temporary directory cannot be read, written, or removed. |
| OperationCanceledException | cancellationToken is canceled. |
Definition at line 76 of file AnkiPackageReader.cs.