mirror of
https://github.com/aaru-dps/Aaru.git
synced 2025-12-16 11:14:25 +00:00
327 lines
13 KiB
C#
327 lines
13 KiB
C#
// /***************************************************************************
|
|
// Aaru Data Preservation Suite
|
|
// ----------------------------------------------------------------------------
|
|
//
|
|
// Filename : Symbian.cs
|
|
// Author(s) : Natalia Portillo <claunia@claunia.com>
|
|
//
|
|
// 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 <http://www.gnu.org/licenses/>.
|
|
//
|
|
// ----------------------------------------------------------------------------
|
|
// Copyright © 2011-2025 Natalia Portillo
|
|
// ****************************************************************************/
|
|
|
|
using System;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Text;
|
|
|
|
namespace Aaru.Archives;
|
|
|
|
public sealed partial class Symbian
|
|
{
|
|
ConditionalExpression ParseConditionalExpression(BinaryReader br, uint maxOffset, StringBuilder sb,
|
|
ref Attribute? attribute)
|
|
{
|
|
if(br.BaseStream.Position >= maxOffset) return null;
|
|
|
|
var type = (ConditionalType)br.ReadUInt32();
|
|
var operatorString = "";
|
|
|
|
SubConditionalExpression subExpression;
|
|
TwoSubsConditionalExpression twoSubsConditionalExpression;
|
|
|
|
switch(type)
|
|
{
|
|
case ConditionalType.Equals:
|
|
if(type == ConditionalType.Equals) operatorString = " == ";
|
|
|
|
twoSubsConditionalExpression = new TwoSubsConditionalExpression
|
|
{
|
|
type = type
|
|
};
|
|
|
|
sb.Append("(");
|
|
twoSubsConditionalExpression.leftOperand = ParseConditionalExpression(br, maxOffset, sb, ref attribute);
|
|
sb.Append(operatorString);
|
|
|
|
twoSubsConditionalExpression.rightOperand =
|
|
ParseConditionalExpression(br, maxOffset, sb, ref attribute);
|
|
|
|
sb.Append(")");
|
|
|
|
attribute = null;
|
|
|
|
return twoSubsConditionalExpression;
|
|
case ConditionalType.Differs:
|
|
operatorString = " != ";
|
|
goto case ConditionalType.Equals;
|
|
case ConditionalType.GreaterThan:
|
|
operatorString = " > ";
|
|
goto case ConditionalType.Equals;
|
|
case ConditionalType.LessThan:
|
|
operatorString = " < ";
|
|
goto case ConditionalType.Equals;
|
|
case ConditionalType.GreaterOrEqualThan:
|
|
operatorString = " >= ";
|
|
goto case ConditionalType.Equals;
|
|
case ConditionalType.LessOrEqualThan:
|
|
operatorString = " <= ";
|
|
goto case ConditionalType.Equals;
|
|
case ConditionalType.And:
|
|
operatorString = " && ";
|
|
goto case ConditionalType.Equals;
|
|
case ConditionalType.Or:
|
|
operatorString = " || ";
|
|
goto case ConditionalType.Equals;
|
|
case ConditionalType.Exists:
|
|
sb.Append("exists(");
|
|
|
|
subExpression = new SubConditionalExpression
|
|
{
|
|
type = type,
|
|
subExpression = ParseConditionalExpression(br, maxOffset, sb, ref attribute)
|
|
};
|
|
|
|
sb.Append(")");
|
|
|
|
attribute = null;
|
|
|
|
return subExpression;
|
|
case ConditionalType.DeviceCapability:
|
|
sb.Append("devcap(");
|
|
|
|
subExpression = new SubConditionalExpression
|
|
{
|
|
type = type,
|
|
subExpression = ParseConditionalExpression(br, maxOffset, sb, ref attribute)
|
|
};
|
|
|
|
sb.Append(')');
|
|
|
|
attribute = null;
|
|
|
|
return subExpression;
|
|
case ConditionalType.ApplicationCapability:
|
|
twoSubsConditionalExpression = new TwoSubsConditionalExpression
|
|
{
|
|
type = type
|
|
};
|
|
|
|
sb.Append("appcap(");
|
|
twoSubsConditionalExpression.leftOperand = ParseConditionalExpression(br, maxOffset, sb, ref attribute);
|
|
sb.Append(", ");
|
|
|
|
twoSubsConditionalExpression.rightOperand =
|
|
ParseConditionalExpression(br, maxOffset, sb, ref attribute);
|
|
|
|
sb.Append(')');
|
|
|
|
attribute = null;
|
|
|
|
return twoSubsConditionalExpression;
|
|
case ConditionalType.Not:
|
|
sb.Append('!');
|
|
|
|
subExpression = new SubConditionalExpression
|
|
{
|
|
type = type,
|
|
subExpression = ParseConditionalExpression(br, maxOffset, sb, ref attribute)
|
|
};
|
|
|
|
attribute = null;
|
|
|
|
return subExpression;
|
|
case ConditionalType.String:
|
|
var stringExpression = new StringConditionalExpression
|
|
{
|
|
type = type,
|
|
length = br.ReadUInt32(),
|
|
pointer = br.ReadUInt32()
|
|
};
|
|
|
|
long position = br.BaseStream.Position;
|
|
|
|
br.BaseStream.Seek(stringExpression.pointer, SeekOrigin.Begin);
|
|
byte[] buffer = br.ReadBytes((int)stringExpression.length);
|
|
stringExpression.@string = _encoding.GetString(buffer);
|
|
|
|
br.BaseStream.Seek(position, SeekOrigin.Begin);
|
|
|
|
sb.Append($"\"{stringExpression.@string}\"");
|
|
|
|
attribute = null;
|
|
|
|
break;
|
|
case ConditionalType.Attribute:
|
|
var attributeExpression = new AttributeConditionalExpression
|
|
{
|
|
type = type,
|
|
attribute = (Attribute)br.ReadUInt32(),
|
|
unused = br.ReadUInt32()
|
|
};
|
|
|
|
if((int)attributeExpression.attribute > 0x2000)
|
|
{
|
|
int optionIndex = (int)attributeExpression.attribute - 0x2000;
|
|
|
|
if(optionIndex <= _options.Count)
|
|
{
|
|
OptionRecord option = _options[optionIndex - 1];
|
|
option.names.TryGetValue("EN", out string optionName);
|
|
optionName ??= option.names.Values.FirstOrDefault() ?? optionIndex.ToString();
|
|
sb.Append($"option(\"{optionName}\", ENABLED)");
|
|
}
|
|
else
|
|
sb.Append($"option({optionIndex}, ENABLED");
|
|
}
|
|
else
|
|
sb.Append($"{attributeExpression.attribute}");
|
|
|
|
attribute = attributeExpression.attribute;
|
|
|
|
return attributeExpression;
|
|
case ConditionalType.Number:
|
|
var numberExpression = new NumberConditionalExpression
|
|
{
|
|
type = type,
|
|
number = br.ReadUInt32(),
|
|
unused = br.ReadUInt32()
|
|
};
|
|
|
|
if(attribute is null)
|
|
sb.Append($"0x{numberExpression.number:X8}");
|
|
else if((uint)attribute.Value < 0x2000)
|
|
{
|
|
switch(attribute)
|
|
{
|
|
case Attribute.Manufacturer:
|
|
sb.Append($"{(ManufacturerCode)numberExpression.number}");
|
|
|
|
break;
|
|
case Attribute.ManufacturerHardwareRev:
|
|
case Attribute.ManufacturerSoftwareRev:
|
|
case Attribute.DeviceFamilyRev:
|
|
sb.Append($"{numberExpression.number >> 8}.{numberExpression.number & 0xFF}");
|
|
|
|
break;
|
|
case Attribute.MachineUid:
|
|
sb.Append($"{DecodeMachineUid(numberExpression.number)}");
|
|
|
|
break;
|
|
case Attribute.DeviceFamily:
|
|
sb.Append($"{(DeviceFamilyCode)numberExpression.number}");
|
|
|
|
break;
|
|
case Attribute.CPU:
|
|
sb.Append($"{(CpuCode)numberExpression.number}");
|
|
|
|
break;
|
|
case Attribute.CPUArch:
|
|
sb.Append($"{(CpuArchitecture)numberExpression.number}");
|
|
|
|
break;
|
|
case Attribute.CPUABI:
|
|
sb.Append($"{(CpuAbiCode)numberExpression.number}");
|
|
|
|
break;
|
|
case Attribute.CPUSpeed:
|
|
sb.Append($"{numberExpression.number / 1024}MHz");
|
|
|
|
break;
|
|
case Attribute.SystemTickPeriod:
|
|
sb.Append($"{numberExpression.number}μs");
|
|
|
|
break;
|
|
case Attribute.MemoryRAM:
|
|
case Attribute.MemoryRAMFree:
|
|
case Attribute.MemoryROM:
|
|
case Attribute.MemoryPageSize:
|
|
case Attribute.Keyboard:
|
|
case Attribute.KeyboardDeviceKeys:
|
|
case Attribute.KeyboardAppKeys:
|
|
case Attribute.KeyboardClickVolumeMax:
|
|
case Attribute.DisplayXPixels:
|
|
case Attribute.DisplayYPixels:
|
|
case Attribute.DisplayXTwips:
|
|
case Attribute.DisplayYTwips:
|
|
case Attribute.DisplayColors:
|
|
case Attribute.DisplayContrastMax:
|
|
case Attribute.PenX:
|
|
case Attribute.PenY:
|
|
case Attribute.PenClickVolumeMax:
|
|
case Attribute.MouseX:
|
|
case Attribute.MouseY:
|
|
case Attribute.MouseButtons:
|
|
case Attribute.LEDs:
|
|
case Attribute.DisplayBrightnessMax:
|
|
case Attribute.KeyboardBacklightState:
|
|
case Attribute.AccessoryPower:
|
|
case Attribute.NumHalAttributes:
|
|
case Attribute.Language:
|
|
sb.Append($"{numberExpression.number}");
|
|
|
|
break;
|
|
case Attribute.PowerBackup:
|
|
case Attribute.KeyboardClick:
|
|
case Attribute.Backlight:
|
|
case Attribute.Pen:
|
|
case Attribute.PenDisplayOn:
|
|
case Attribute.PenClick:
|
|
case Attribute.Mouse:
|
|
case Attribute.CaseSwitch:
|
|
case Attribute.IntegratedPhone:
|
|
case Attribute.RemoteInstall:
|
|
sb.Append(numberExpression.number == 0 ? "false" : "true");
|
|
|
|
break;
|
|
default:
|
|
sb.Append($"0x{numberExpression.number:X8}");
|
|
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
int optionIndex = (int)attribute - 0x2000;
|
|
|
|
if(optionIndex <= _options.Count)
|
|
{
|
|
OptionRecord option = _options[optionIndex - 1];
|
|
option.names.TryGetValue("EN", out string optionName);
|
|
optionName ??= option.names.Values.FirstOrDefault() ?? optionIndex.ToString();
|
|
sb.Append($"option(\"{optionName}\", {(numberExpression.number == 0 ? "DISABLED" : "ENABLED")})");
|
|
}
|
|
else
|
|
sb.Append($"option({optionIndex}, {(numberExpression.number == 0 ? "DISABLED" : "ENABLED")}");
|
|
}
|
|
|
|
attribute = null;
|
|
|
|
return numberExpression;
|
|
default:
|
|
throw new ArgumentOutOfRangeException();
|
|
}
|
|
|
|
return null;
|
|
}
|
|
} |