Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for packing asar files (sync only). #8

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions sync/Test/App.config
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8" ?>
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.1"/>
</startup>
</configuration>
</configuration>
89 changes: 69 additions & 20 deletions sync/Test/Program.cs
Original file line number Diff line number Diff line change
@@ -1,32 +1,81 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using asardotnet;
using Newtonsoft.Json.Linq;

namespace Test {
class Program {
static void Main(string[] args) {

AsarArchive asarArhive = new AsarArchive("D:\\Downloads\\app.asar");
AsarExtractor extractor = new AsarExtractor();

extractor.ExtractAll(asarArhive, "G:\\Asardotnet\\out\\");

// extractor.Extract(asarArhive, "app/index.js", "G:\\Asardotnet\\out\\index.js");
namespace asardotnet
{
class Program
{
static void PrintUsage()
{
Console.WriteLine("\n Usage: Test.exe [command] [options]");
Console.WriteLine("\n Commands:");
Console.WriteLine("\n pack|p <dir> <output>\n create asar archive");
Console.WriteLine("\n list|l <archive>\n list files of asar archive");
Console.WriteLine("\n extract-file|ef <archive> <filename>\n extract one file from asar archive");
Console.WriteLine("\n extract|e <archive> <dest>\n extract asar archive");
Console.WriteLine("\n");
}

// AsarExtractor extractor = new AsarExtractor();
// extractor.Extract(asarArhive, "NotificationWindow.js", "");
static void Main(string[] args)
{
if (args.Length < 2)
{
PrintUsage();
return;
}

// AsarExtractor asarExtractor = new AsarExtractor();
AsarArchive asarArchive;
AsarExtractor extractor = new AsarExtractor();
AsarPacker packer = new AsarPacker();

//asarExtractor.Extract(asarArhive, "G:\\Asardotnet\\extract\\");
switch (args[0].ToLower())
{
case "e":
case "extract":
if (args.Length != 3 || !File.Exists(args[1]))
{

// asarExtractor.ExtractFile(asarArhive, 8528, 6479);
PrintUsage();
return;
}
asarArchive = new AsarArchive(args[1]);
extractor.ExtractAll(asarArchive, args[2]);
return;
case "ef":
case "extract-file":
if (args.Length != 3)
{
PrintUsage();
return;
}
asarArchive = new AsarArchive(args[1]);
extractor.Extract(asarArchive, args[1], args[2]);
break;
case "l":
case "list":
if (!File.Exists(args[1]))
{
PrintUsage();
return;
}
asarArchive = new AsarArchive(args[1]);
extractor.ListAll(asarArchive);
return;
case "p":
case "pack":
if (args.Length != 3)
{
PrintUsage();
break;
}
packer.Pack(args[1], args[2]);
return;
default:
break;
}
}
}
}
}
3 changes: 2 additions & 1 deletion sync/Test/Test.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,9 @@
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Test</RootNamespace>
<AssemblyName>Test</AssemblyName>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<TargetFrameworkVersion>v4.5.1</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<TargetFrameworkProfile />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
Expand Down
76 changes: 52 additions & 24 deletions sync/asardotnet/AsarArchive.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,63 +26,87 @@
* */

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using Newtonsoft.Json.Linq;

namespace asardotnet {
public class AsarArchive {
namespace asardotnet
{
public class AsarArchive
{
private const int SIZE_UINT = 4;

private readonly int _baseOffset;

public int GetBaseOffset() { return _baseOffset; }

private readonly byte[] _bytes;

public byte[] GetBytes() { return _bytes; }

private readonly String _filePath;
public String GetFilePath() { return _filePath; }
private readonly string _filePath;

public string GetFilePath() { return _filePath; }

private Header _header;

public Header GetHeader() { return _header; }

public struct Header {
public struct Header
{
private readonly byte[] _headerInfo;

public byte[] GetHeaderInfo() { return _headerInfo; }

private readonly int _headerLength;

public int GetHeaderLenth() { return _headerLength; }

private readonly byte[] _headerData;

public byte[] GetHeaderData() { return _headerData; }

private readonly JObject _headerJson;

public JObject GetHeaderJson() { return _headerJson; }

public Header(byte[] hinfo, int length, byte[] data, JObject hjson) {
public Header(byte[] hinfo, int length, byte[] data, JObject hjson)
{
_headerInfo = hinfo;
_headerLength = length;
_headerData = data;
_headerJson = hjson;
}
}

public AsarArchive(String filePath) {
if(!File.Exists(filePath))
public AsarArchive()
{

}

public AsarArchive(string filePath)
{
if (!File.Exists(filePath))
throw new AsarExceptions(AsarException.ASAR_FILE_CANT_FIND);

_filePath = filePath;

try {
try
{
_bytes = File.ReadAllBytes(filePath);
} catch(Exception ex) {
}
catch (Exception ex)
{
throw new AsarExceptions(AsarException.ASAR_FILE_CANT_READ, ex.ToString());
}

try {
try
{
_header = ReadAsarHeader(ref _bytes);
_baseOffset = _header.GetHeaderLenth();
} catch(Exception _ex) {
}
catch (Exception _ex)
{
throw _ex;
}
}
Expand All @@ -91,29 +115,33 @@ public AsarArchive(String filePath) {
* Exceptions should never be thrown as long as the file
* was created with nodejs asar algorithm
*/
private static Header ReadAsarHeader(ref byte[] bytes) {
int SIZE_LONG = 2 * SIZE_UINT;
int SIZE_INFO = 2 * SIZE_LONG;
private static Header ReadAsarHeader(ref byte[] bytes)
{
int SIZE_LONG = 2 * SIZE_UINT; // 8
int SIZE_INFO = 2 * SIZE_LONG; // 16

// Header Info
byte[] headerInfo = bytes.Take(SIZE_INFO).ToArray();
byte[] headerInfo = bytes.Take(SIZE_INFO).ToArray(); // 16

if(headerInfo.Length < SIZE_INFO)
if (headerInfo.Length < SIZE_INFO) // 16
throw new AsarExceptions(AsarException.ASAR_INVALID_FILE_SIZE);

byte[] asarFileDescriptor = headerInfo.Take(SIZE_LONG).ToArray();
byte[] asarPayloadSize = asarFileDescriptor.Take(SIZE_UINT).ToArray();
byte[] asarFileDescriptor = headerInfo.Take(SIZE_LONG).ToArray(); // 16
byte[] asarPayloadSize = asarFileDescriptor.Take(SIZE_UINT).ToArray(); // 4

int payloadSize = BitConverter.ToInt32(asarPayloadSize, 0);
int payloadOffset = asarFileDescriptor.Length - payloadSize;
int payloadOffset = asarFileDescriptor.Length - payloadSize; // 16 - 4 = 12

if(payloadSize != SIZE_UINT && payloadSize != SIZE_LONG)
// payload size should be 4
if (payloadSize != SIZE_UINT && payloadSize != SIZE_LONG)
throw new AsarExceptions(AsarException.ASAR_INVALID_DESCRIPTOR);

// skip to byte 12 and read 4 bytes into headerLength
byte[] asarHeaderLength = asarFileDescriptor.Skip(payloadOffset).Take(SIZE_UINT).ToArray();

int headerLength = BitConverter.ToInt32(asarHeaderLength, 0);

// skip 8 and take 8
byte[] asarFileHeader = headerInfo.Skip(SIZE_LONG).Take(SIZE_LONG).ToArray();
byte[] asarHeaderPayloadSize = asarFileHeader.Take(SIZE_UINT).ToArray();

Expand All @@ -126,7 +154,7 @@ private static Header ReadAsarHeader(ref byte[] bytes) {
// Data Table
byte[] hdata = bytes.Skip(SIZE_INFO).Take(dataTableSize).ToArray();

if(hdata.Length != dataTableSize)
if (hdata.Length != dataTableSize)
throw new AsarExceptions(AsarException.ASAR_INVALID_FILE_SIZE);

int asarDataOffset = asarFileDescriptor.Length + headerLength;
Expand Down
34 changes: 22 additions & 12 deletions sync/asardotnet/AsarExceptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,32 +27,39 @@

using System;

namespace asardotnet {
public enum AsarException {
namespace asardotnet
{
public enum AsarException
{
ASAR_FILE_CANT_FIND,
ASAR_FILE_CANT_READ,
ASAR_INVALID_DESCRIPTOR,
ASAR_INVALID_FILE_SIZE
};
}

public class AsarExceptions: Exception {
public class AsarExceptions : Exception
{
private readonly AsarException _asarException;

private readonly string _asarMessage;

public AsarExceptions(AsarException ex) : this(ex, "") { }

public AsarExceptions(AsarException ex, String customMessage) {
public AsarExceptions(AsarException ex, String customMessage)
{
_asarException = ex;
if(customMessage.Length > 0)
if (customMessage.Length > 0)
_asarMessage = customMessage;
else
_asarMessage = GetMessage(ex);
}

private String GetMessage(AsarException ex) {
String result;
private string GetMessage(AsarException ex)
{
string result;

switch(ex) {
switch (ex)
{
case AsarException.ASAR_FILE_CANT_FIND:
result = "Error: The specified file couldn't be found.";
break;
Expand All @@ -73,15 +80,18 @@ private String GetMessage(AsarException ex) {
return result;
}

public AsarException GetExceptionCode() {
public AsarException GetExceptionCode()
{
return _asarException;
}

public String GetExceptionMessage() {
public string GetExceptionMessage()
{
return _asarMessage;
}

override public String ToString() {
override public String ToString()
{
return "(Code " + GetExceptionCode() + ") " + GetExceptionMessage();
}
}
Expand Down
Loading