// /*************************************************************************** // Aaru Data Preservation Suite // ---------------------------------------------------------------------------- // // Filename : Symbian.cs // Author(s) : Natalia Portillo // // Component : Symbian plugin. // // --[ Description ] ---------------------------------------------------------- // // Identifies Symbian installer (.sis) packages and shows information. // // --[ License ] -------------------------------------------------------------- // // This library is free software; you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as // published by the Free Software Foundation; either version 2.1 of the // License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, but // WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, see . // // ---------------------------------------------------------------------------- // Copyright © 2011-2025 Natalia Portillo // ****************************************************************************/ using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Runtime.InteropServices; #pragma warning disable CS0169 // Field is never used #pragma warning disable CS0649 // Field is never assigned to, and will always have its default value namespace Aaru.Archives; [SuppressMessage("ReSharper", "UnusedType.Global")] [SuppressMessage("ReSharper", "UnusedType.Local")] [SuppressMessage("ReSharper", "InconsistentNaming")] [SuppressMessage("ReSharper", "InheritdocConsiderUsage")] [SuppressMessage("ReSharper", "NotAccessedField.Local")] [SuppressMessage("ReSharper", "ClassCanBeSealed.Local")] public sealed partial class Symbian { #region Nested type: AttributeConditionalExpression /// /// Contains an attribute to be used as a parameter in a conditional expression /// class AttributeConditionalExpression : ConditionalExpression { public Attribute attribute; public uint unused; } #endregion #region Nested type: BaseFileRecord /// /// Common fields to simple file record and multiple file record /// [StructLayout(LayoutKind.Sequential, Pack = 1)] struct BaseFileRecord { /// /// File record type, in this case or /// /// public FileRecordType recordType; /// /// File type /// public FileType type; /// /// File details /// public FileDetails details; /// /// Length in bytes of the source name (filename on the machine that built the SIS) /// public uint sourceNameLen; /// /// Pointer to the source name /// public uint sourceNamePtr; /// /// Length in bytes of the destination name (filename+path it will be installed to. '!:' for drive means allow the user /// to pick destination drive) /// public uint destinationNameLen; /// /// Pointer to the destination name /// public uint destinationNamePtr; } #endregion #region Nested type: CapabilitiesRecord /// /// TODO: Unclear, check on real files /// struct CapabilitiesRecord { public uint[] keys; public uint[] values; } #endregion #region Nested type: CertificatesRecord /// /// Holds signature certifications, but the exact distribution of them is unclear /// struct CertificatesRecord { public ushort year; public ushort month; public ushort day; public ushort hour; public ushort minute; public ushort second; public uint numberOfCertificates; } #endregion #region Nested type: ComponentRecord /// /// Component record as pointed by the header /// struct ComponentRecord { /// /// Lengths of the component names, array sorted as language records /// public uint[] namesLengths; /// /// Pointers to the component names, array sorted as language records /// public uint[] namesPointers; /// /// Decoded names, not on-disk /// public string[] names; } #endregion #region Nested type: ConditionalEndRecord /// /// Contains an 'else' or 'endif' expression /// struct ConditionalEndRecord { /// /// File record type in this case or /// public FileRecordType recordType; } #endregion #region Nested type: ConditionalExpression /// /// Conditional expression base /// class ConditionalExpression { /// /// Conditional type /// public ConditionalType type; } #endregion #region Nested type: ConditionalRecord /// /// Contains an 'if' or 'else if' condition /// struct ConditionalRecord { /// /// File record type in this case or /// public FileRecordType recordType; /// /// Length in bytes of the record and all contained expressions /// public uint length; /// /// Conditional expression(s) (chain) /// public ConditionalExpression expression; } #endregion #region Nested type: DecodedFileRecord /// /// On-memory structure /// struct DecodedFileRecord { /// /// File type /// public FileType type; /// /// File details /// public FileDetails details; /// /// Source name (filename on the machine that built the SIS) /// public string sourceName; /// /// Destination name (filename+path it will be installed to. '!:' for drive means allow the user /// to pick destination drive) /// public string destinationName; /// /// Length in bytes of the (compressed or uncompressed) file /// public uint length; /// /// Pointer to the (compressed or uncompressed) file data /// public uint pointer; /// /// EPOC Release >= 6, uncompressed file length /// public uint originalLength; /// /// EPOC Release >= 6, MIME type string /// public string mime; /// /// Language, or null for no language /// public string language; } #endregion #region Nested type: MultipleFileRecord /// /// Multiple language file record, cannot be marshalled /// struct MultipleFileRecord { /// /// Common fields to simple file record and multiple file record /// public BaseFileRecord record; /// /// Lengths in bytes of the (compressed or uncompressed) files, array sorted as language records /// public uint[] lengths; /// /// Pointers to the (compressed or uncompressed) files data, array sorted as language records /// public uint[] pointers; /// /// EPOC Release >= 6, uncompressed files lengths, array sorted as language records /// public uint[] originalLengths; /// /// EPOC Release >= 6, length in bytes of MIME type string /// public uint mimeLen; /// /// EPOC Release >= 6, pointer to MIME type string /// public uint mimePtr; } #endregion #region Nested type: NumberConditionalExpression /// /// Contains a number to be used as a parameter in a conditional expression /// class NumberConditionalExpression : ConditionalExpression { public uint number; public uint unused; } #endregion #region Nested type: OptionRecord struct OptionRecord { /// /// Pointer to the option name lengths, array sorted as language records /// public uint[] lengths; /// /// Pointer to the option names, array sorted as language records /// public uint[] pointers; public Dictionary names; } #endregion #region Nested type: OptionsLineRecord struct OptionsLineRecord { /// /// File record type in this case /// public FileRecordType recordType; /// /// How many options follow /// public uint numberOfOptions; /// /// Option records /// public OptionRecord[] options; /// /// 128-bit bitmap of selected options /// [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] public ulong[] selectedOptions; } #endregion #region Nested type: RequisiteRecord struct RequisiteRecord { /// /// UID of the required component /// public uint uid; /// /// Major version of the required component /// public ushort majorVersion; /// /// Minor version of the required component /// public ushort minorVersion; /// /// Variant of the required component, usually set to 0 and not checked by installer /// public uint variant; /// /// Lengths of the requisite names, array sorted as language records /// public uint[] namesLengths; /// /// Pointers to the requisite names, array sorted as language records /// public uint[] namesPointers; } #endregion #region Nested type: SimpleFileRecord /// /// Simple file record, can be marshalled /// [StructLayout(LayoutKind.Sequential, Pack = 1)] struct SimpleFileRecord { /// /// Common fields to simple file record and multiple file record /// public BaseFileRecord record; /// /// Length in bytes of the (compressed or uncompressed) file /// public uint length; /// /// Pointer to the (compressed or uncompressed) file data /// public uint pointer; /// /// EPOC Release >= 6, uncompressed file length /// public uint originalLength; /// /// EPOC Release >= 6, length in bytes of MIME type string /// public uint mimeLen; /// /// EPOC Release >= 6, pointer to MIME type string /// public uint mimePtr; } #endregion #region Nested type: StringConditionalExpression /// /// Points to a string used as a parameter in a conditional expression /// class StringConditionalExpression : ConditionalExpression { public uint length; public uint pointer; public string @string; } #endregion #region Nested type: SubConditionalExpression /// /// Conditional expression that contains a single sub-expression /// class SubConditionalExpression : ConditionalExpression { /// /// Sub-expression /// public ConditionalExpression subExpression; } #endregion #region Nested type: SymbianHeader [StructLayout(LayoutKind.Sequential, Pack = 1)] struct SymbianHeader { /// /// Application UID before SymbianOS 9, magic after /// public uint uid1; /// /// EPOC release magic before SOS 9, NULLs after /// public uint uid2; /// /// Application UID after SOS 9, magic before /// public uint uid3; /// /// Checksum of UIDs 1 to 3 /// public uint uid4; /// /// CRC16 of all header /// public ushort crc16; /// /// Number of languages /// public ushort languages; /// /// Number of files /// public ushort files; /// /// Number of requisites /// public ushort requisites; /// /// Installed language (only residual SIS) /// public ushort inst_lang; /// /// Installed files (only residual SIS) /// public ushort inst_files; /// /// Installed drive (only residual SIS), NULL or 0x0021 /// public ushort inst_drive; /// /// Number of capabilities /// public ushort capabilities; /// /// Version of Symbian Installer required /// public uint inst_version; /// /// Option flags /// public SymbianOptions options; /// /// Type /// public SymbianType type; /// /// Major version of application /// public ushort major; /// /// Minor version of application /// public ushort minor; /// /// Variant when SIS is a prerequisite for other SISs /// public uint variant; /// /// Pointer to language records /// public uint lang_ptr; /// /// Pointer to file records /// public uint files_ptr; /// /// Pointer to requisite records /// public uint reqs_ptr; /// /// Pointer to certificate records /// public uint certs_ptr; /// /// Pointer to component name record /// public uint comp_ptr; // From EPOC Release 6 /// /// Pointer to signature record /// public uint sig_ptr; /// /// Pointer to capability records /// public uint caps_ptr; /// /// Installed space (only residual SIS) /// public uint instspace; /// /// Space required /// public uint maxinsspc; /// /// Reserved /// public ulong reserved1; /// /// Reserved /// public ulong reserved2; } #endregion #region Nested type: TwoSubsConditionalExpression /// /// Conditional expression that contains two sub-expressions /// class TwoSubsConditionalExpression : ConditionalExpression { /// /// Left hand side sub-expression /// public ConditionalExpression leftOperand; /// /// Right hand side sub-expression /// public ConditionalExpression rightOperand; } #endregion }