Skip to content

Commit

Permalink
Port Headerer from SabreTools, add build scripts
Browse files Browse the repository at this point in the history
  • Loading branch information
mnadareski committed Oct 25, 2024
1 parent a5e172f commit c19c734
Show file tree
Hide file tree
Showing 12 changed files with 876 additions and 0 deletions.
50 changes: 50 additions & 0 deletions .github/workflows/build_and_publish.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
name: Build and Publish

on:
push:
branches: [ "main" ]

jobs:
build:
runs-on: ubuntu-latest

strategy:
matrix:
project: [Headerer]
runtime: [win-x86, win-x64, win-arm64, linux-x64, linux-arm64, osx-x64]
framework: [net8.0] #[net20, net35, net40, net452, net472, net48, netcoreapp3.1, net5.0, net6.0, net7.0, net8.0]

steps:
- uses: actions/checkout@v4

- name: Setup .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: 8.0.x

- name: Restore dependencies
run: dotnet restore

- name: Build
run: dotnet publish ${{ matrix.project }}/${{ matrix.project }}.csproj -f ${{ matrix.framework }} -r ${{ matrix.runtime }} -c Debug --self-contained true --version-suffix ${{ github.sha }} ${{ (startsWith(matrix.framework, 'net5') || startsWith(matrix.framework, 'net6') || startsWith(matrix.framework, 'net7') || startsWith(matrix.framework, 'net8')) && '-p:PublishSingleFile=true' || ''}}

- name: Archive build
run: zip -r ${{ matrix.project }}_${{ matrix.framework }}_${{ matrix.runtime }}_debug.zip ${{ matrix.project }}/bin/Debug/${{ matrix.framework }}/${{ matrix.runtime }}/publish/

- name: Upload build
uses: actions/upload-artifact@v4
with:
name: ${{ matrix.project }}_${{ matrix.framework }}_${{ matrix.runtime }}_debug
path: ${{ matrix.project }}_${{ matrix.framework }}_${{ matrix.runtime }}_debug.zip

- name: Upload to rolling
uses: ncipollo/[email protected]
with:
allowUpdates: True
artifacts: ${{ matrix.project }}_${{ matrix.framework }}_${{ matrix.runtime }}_debug.zip
body: 'Last built commit: ${{ github.sha }}'
name: 'Rolling Release'
prerelease: True
replacesArtifacts: True
tag: "rolling"
updateOnlyUnreleased: True
129 changes: 129 additions & 0 deletions Headerer/Database.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
using System;
using System.Collections.Generic;
using System.IO;
using Microsoft.Data.Sqlite;
using SabreTools.IO;

namespace Headerer
{
internal static class Database
{
#region Constants

/// <summary>
/// Default location for the database
/// </summary>
private static readonly string DbFileName = Path.Combine(PathTool.GetRuntimeDirectory(), "Headerer.sqlite");

/// <summary>
/// Connection string for the database
/// </summary>
private static readonly string DbConnectionString = $"Data Source={DbFileName};";

#endregion

/// <summary>
/// Add a header to the database
/// </summary>
/// <param name="header">String representing the header bytes</param>
/// <param name="SHA1">SHA-1 of the deheadered file</param>
/// <param name="type">Name of the source skipper file</param>
/// <param name="debug">Enable additional log statements for debugging</param>
public static void AddHeader(string header, string SHA1, string source, bool debug)
{
// Ensure the database exists
EnsureDatabase();

// Open the database connection
SqliteConnection dbc = new(DbConnectionString);
dbc.Open();

string query = $"SELECT * FROM data WHERE sha1='{SHA1}' AND header='{header}'";
var slc = new SqliteCommand(query, dbc);
SqliteDataReader sldr = slc.ExecuteReader();
bool exists = sldr.HasRows;

if (!exists)
{
query = $"INSERT INTO data (sha1, header, type) VALUES ('{SHA1}', '{header}', '{source}')";
slc = new SqliteCommand(query, dbc);
if (debug) Console.WriteLine($"Result of inserting header: {slc.ExecuteNonQuery()}");
}

// Dispose of database objects
slc.Dispose();
sldr.Dispose();
dbc.Dispose();
}

/// <summary>
/// Retrieve headers from the database
/// </summary>
/// <param name="SHA1">SHA-1 of the deheadered file</param>
/// <param name="debug">Enable additional log statements for debugging</param>
/// <returns>List of strings representing the headers to add</returns>
public static List<string> RetrieveHeaders(string SHA1, bool debug)
{
// Ensure the database exists
EnsureDatabase();

// Open the database connection
var dbc = new SqliteConnection(DbConnectionString);
dbc.Open();

// Create the output list of headers
List<string> headers = [];

string query = $"SELECT header, type FROM data WHERE sha1='{SHA1}'";
var slc = new SqliteCommand(query, dbc);
SqliteDataReader sldr = slc.ExecuteReader();

if (sldr.HasRows)
{
while (sldr.Read())
{
if (debug) Console.WriteLine($"Found match with rom type '{sldr.GetString(1)}'");
headers.Add(sldr.GetString(0));
}
}
else
{
Console.Error.WriteLine("No matching header could be found!");
}

// Dispose of database objects
slc.Dispose();
sldr.Dispose();
dbc.Dispose();

return headers;
}

/// <summary>
/// Ensure that the database exists and has the proper schema
/// </summary>
private static void EnsureDatabase()
{
// Make sure the file exists
if (!File.Exists(DbFileName))
File.Create(DbFileName);

// Open the database connection
SqliteConnection dbc = new(DbConnectionString);
dbc.Open();

// Make sure the database has the correct schema
string query = @"
CREATE TABLE IF NOT EXISTS data (
'sha1' TEXT NOT NULL,
'header' TEXT NOT NULL,
'type' TEXT NOT NULL,
PRIMARY KEY (sha1, header, type)
)";
SqliteCommand slc = new(query, dbc);
slc.ExecuteNonQuery();
slc.Dispose();
dbc.Dispose();
}
}
}
71 changes: 71 additions & 0 deletions Headerer/Extract.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
using System;
using System.IO;
using SabreTools.Hashing;
using SabreTools.IO.Extensions;
using SabreTools.Skippers;

namespace Headerer
{
internal static class Extract
{
/// <summary>
/// Detect header skipper compliance and create an output file
/// </summary>
/// <param name="file">Name of the file to be parsed</param>
/// <param name="outDir">Output directory to write the file to, empty means the same directory as the input file</param>
/// <param name="nostore">True if headers should not be stored in the database, false otherwise</param>
/// <param name="debug">Enable additional log statements for debugging</param>
/// <returns>True if the output file was created, false otherwise</returns>
public static bool DetectTransformStore(string file, string? outDir, bool nostore, bool debug = false)
{
// Create the output directory if it doesn't exist
if (!string.IsNullOrWhiteSpace(outDir) && !Directory.Exists(outDir))
Directory.CreateDirectory(outDir);

Console.WriteLine($"\nGetting skipper information for '{file}'");

// Get the skipper rule that matches the file, if any
SkipperMatch.Init();
Rule rule = SkipperMatch.GetMatchingRule(file, string.Empty);

// If we have an empty rule, return false
if (rule.Tests == null || rule.Tests.Length == 0 || rule.Operation != HeaderSkipOperation.None)
return false;

Console.WriteLine("File has a valid copier header");

// Get the header bytes from the file first
string hstr;
try
{
// Extract the header as a string for the database
using var fs = File.OpenRead(file);
int startOffset = int.Parse(rule.StartOffset ?? "0");
byte[] hbin = new byte[startOffset];
fs.Read(hbin, 0, startOffset);
hstr = ByteArrayExtensions.ByteArrayToString(hbin)!;
}
catch
{
return false;
}

// Apply the rule to the file
string newfile = string.IsNullOrWhiteSpace(outDir) ? Path.GetFullPath(file) + ".new" : Path.Combine(outDir, Path.GetFileName(file));
rule.TransformFile(file, newfile);

// If the output file doesn't exist, return false
if (!File.Exists(newfile))
return false;

// Now add the information to the database if it's not already there
if (!nostore)
{
string sha1 = HashTool.GetFileHash(newfile, HashType.SHA1) ?? string.Empty;
Database.AddHeader(hstr, sha1, rule.SourceFile!, debug);
}

return true;
}
}
}
10 changes: 10 additions & 0 deletions Headerer/Feature.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
namespace Headerer
{
internal enum Feature
{
NONE = 0,

Extract,
Restore,
}
}
49 changes: 49 additions & 0 deletions Headerer/Headerer.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<!-- Assembly Properties -->
<TargetFrameworks>net48;netcoreapp3.1;net5.0;net6.0;net7.0;net8.0</TargetFrameworks>
<OutputType>Exe</OutputType>
<CheckEolTargetFramework>false</CheckEolTargetFramework>
<IncludeSourceRevisionInInformationalVersion>false</IncludeSourceRevisionInInformationalVersion>
<LangVersion>latest</LangVersion>
<Nullable>enable</Nullable>
<SuppressTfmSupportBuildWarnings>true</SuppressTfmSupportBuildWarnings>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<Version>1.1.2</Version>

<!-- Package Properties -->
<Authors>Matt Nadareski</Authors>
<Copyright>Copyright (c)2016-2024 Matt Nadareski</Copyright>
<PackageProjectUrl>https://github.com/SabreTools/</PackageProjectUrl>
<PackageLicenseExpression>MIT</PackageLicenseExpression>
<RepositoryType>git</RepositoryType>
<RepositoryUrl>https://github.com/SabreTools/SabreTools</RepositoryUrl>
</PropertyGroup>

<!-- Support All Frameworks -->
<PropertyGroup Condition="$(TargetFramework.StartsWith(`net2`)) OR $(TargetFramework.StartsWith(`net3`)) OR $(TargetFramework.StartsWith(`net4`))">
<RuntimeIdentifiers>win-x86;win-x64</RuntimeIdentifiers>
</PropertyGroup>
<PropertyGroup Condition="$(TargetFramework.StartsWith(`netcoreapp`)) OR $(TargetFramework.StartsWith(`net5`))">
<RuntimeIdentifiers>win-x86;win-x64;win-arm64;linux-x64;linux-arm64;osx-x64</RuntimeIdentifiers>
</PropertyGroup>
<PropertyGroup Condition="$(TargetFramework.StartsWith(`net6`)) OR $(TargetFramework.StartsWith(`net7`)) OR $(TargetFramework.StartsWith(`net8`))">
<RuntimeIdentifiers>win-x86;win-x64;win-arm64;linux-x64;linux-arm64;osx-x64;osx-arm64</RuntimeIdentifiers>
</PropertyGroup>
<PropertyGroup Condition="$(RuntimeIdentifier.StartsWith(`osx-arm`))">
<TargetFrameworks>net6.0;net7.0;net8.0</TargetFrameworks>
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="..\SabreTools.Skippers\SabreTools.Skippers.csproj" />
</ItemGroup>

<ItemGroup>
<PackageReference Include="Microsoft.Data.Sqlite" Version="8.0.10" />
<PackageReference Include="SabreTools.Hashing" Version="1.2.2" />
<PackageReference Include="SabreTools.IO" Version="1.4.13" />
</ItemGroup>

</Project>

Loading

0 comments on commit c19c734

Please sign in to comment.