1
0
mirror of synced 2024-11-12 00:40:51 +01:00

Initial commit

This commit is contained in:
Yuchen Ji 2022-04-05 01:55:32 +08:00
commit d9c717de6f
55 changed files with 2865 additions and 0 deletions

View File

@ -0,0 +1,13 @@
# Default ignored files
/shelf/
/workspace.xml
# Rider ignored files
/projectSettingsUpdater.xml
/.idea.Embedio-test.iml
/modules.xml
/contentModel.xml
# Editor-based HTTP Client requests
/httpRequests/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml

View File

@ -0,0 +1,29 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="DataSourceManagerImpl" format="xml" multifile-model="true">
<data-source source="LOCAL" name="card" uuid="7bf27c58-38de-41e7-b19b-c8212b4120e6">
<driver-ref>sqlite.xerial</driver-ref>
<synchronize>true</synchronize>
<jdbc-driver>org.sqlite.JDBC</jdbc-driver>
<jdbc-url>jdbc:sqlite:C:\Users\10614\RiderProjects\Embedio-test\GC-local-server-rewrite\db\card.db3</jdbc-url>
<working-dir>$ProjectFileDir$</working-dir>
<libraries>
<library>
<url>file://$APPLICATION_CONFIG_DIR$/jdbc-drivers/Xerial SQLiteJDBC/3.36.0.3/sqlite-jdbc-3.36.0.3.jar</url>
</library>
</libraries>
</data-source>
<data-source source="LOCAL" name="music" uuid="54da1572-ff2e-4bdb-880e-177dd34312b5">
<driver-ref>sqlite.xerial</driver-ref>
<synchronize>true</synchronize>
<jdbc-driver>org.sqlite.JDBC</jdbc-driver>
<jdbc-url>jdbc:sqlite:C:\Users\10614\RiderProjects\Embedio-test\GC-local-server-rewrite\db\music.db3</jdbc-url>
<working-dir>$ProjectFileDir$</working-dir>
<libraries>
<library>
<url>file://$APPLICATION_CONFIG_DIR$/jdbc-drivers/Xerial SQLiteJDBC/3.36.0.3/sqlite-jdbc-3.36.0.3.jar</url>
</library>
</libraries>
</data-source>
</component>
</project>

View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Encoding" addBOMForNewFiles="with BOM under Windows, with no BOM otherwise" />
</project>

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="UserContentModel">
<attachedFolders />
<explicitIncludes />
<explicitExcludes />
</component>
</project>

View File

@ -0,0 +1,13 @@
# Default ignored files
/shelf/
/workspace.xml
# Rider ignored files
/modules.xml
/.idea.GC-local-server-rewrite.iml
/projectSettingsUpdater.xml
/contentModel.xml
# Editor-based HTTP Client requests
/httpRequests/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml

View File

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="DataSourceManagerImpl" format="xml" multifile-model="true">
<data-source source="LOCAL" name="card" uuid="115a7206-912c-4128-b8d4-a552698ecb5e">
<driver-ref>sqlite.xerial</driver-ref>
<synchronize>true</synchronize>
<jdbc-driver>org.sqlite.JDBC</jdbc-driver>
<jdbc-url>jdbc:sqlite:C:\Users\10614\RiderProjects\GC-local-server-rewrite\GC-local-server-rewrite\db\card.db3</jdbc-url>
<working-dir>$ProjectFileDir$</working-dir>
<libraries>
<library>
<url>file://$APPLICATION_CONFIG_DIR$/jdbc-drivers/Xerial SQLiteJDBC/3.36.0.3/sqlite-jdbc-3.36.0.3.jar</url>
</library>
</libraries>
</data-source>
</component>
</project>

View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Encoding" addBOMForNewFiles="with BOM under Windows, with no BOM otherwise" />
</project>

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="UserContentModel">
<attachedFolders />
<explicitIncludes />
<explicitExcludes />
</component>
</project>

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>

View File

@ -0,0 +1,16 @@

Microsoft Visual Studio Solution File, Format Version 12.00
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GC-local-server-rewrite", "GC-local-server-rewrite\GC-local-server-rewrite.csproj", "{D5FFF2E8-6591-4967-8883-A28F453F0524}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{D5FFF2E8-6591-4967-8883-A28F453F0524}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D5FFF2E8-6591-4967-8883-A28F453F0524}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D5FFF2E8-6591-4967-8883-A28F453F0524}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D5FFF2E8-6591-4967-8883-A28F453F0524}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
EndGlobal

View File

@ -0,0 +1,6 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:Boolean x:Key="/Default/UserDictionary/Words/=BDATA/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Fcol/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Incom/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Pcol/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Respone/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>

437
GC-local-server-rewrite/.gitignore vendored Normal file
View File

@ -0,0 +1,437 @@
### JetBrains template
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
# User-specific stuff
.idea/**/workspace.xml
.idea/**/tasks.xml
.idea/**/usage.statistics.xml
.idea/**/dictionaries
.idea/**/shelf
# Generated files
.idea/**/contentModel.xml
# Sensitive or high-churn files
.idea/**/dataSources/
.idea/**/dataSources.ids
.idea/**/dataSources.local.xml
.idea/**/sqlDataSources.xml
.idea/**/dynamic.xml
.idea/**/uiDesigner.xml
.idea/**/dbnavigator.xml
# Gradle
.idea/**/gradle.xml
.idea/**/libraries
# Gradle and Maven with auto-import
# When using Gradle or Maven with auto-import, you should exclude module files,
# since they will be recreated, and may cause churn. Uncomment if using
# auto-import.
# .idea/artifacts
# .idea/compiler.xml
# .idea/jarRepositories.xml
# .idea/modules.xml
# .idea/*.iml
# .idea/modules
# *.iml
# *.ipr
# CMake
cmake-build-*/
# Mongo Explorer plugin
.idea/**/mongoSettings.xml
# File-based project format
*.iws
# IntelliJ
out/
# mpeltonen/sbt-idea plugin
.idea_modules/
# JIRA plugin
atlassian-ide-plugin.xml
# Cursive Clojure plugin
.idea/replstate.xml
# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties
fabric.properties
# Editor-based Rest Client
.idea/httpRequests
# Android studio 3.1+ serialized cache file
.idea/caches/build_file_checksums.ser
### VisualStudio template
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
##
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
# User-specific files
*.rsuser
*.suo
*.user
*.userosscache
*.sln.docstates
# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs
# Mono auto generated files
mono_crash.*
# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
[Ww][Ii][Nn]32/
[Aa][Rr][Mm]/
[Aa][Rr][Mm]64/
bld/
[Bb]in/
[Oo]bj/
[Ll]og/
[Ll]ogs/
# Visual Studio 2015/2017 cache/options directory
.vs/
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/
# Visual Studio 2017 auto generated files
Generated\ Files/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
# NUnit
*.VisualState.xml
TestResult.xml
nunit-*.xml
# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c
# Benchmark Results
BenchmarkDotNet.Artifacts/
# .NET Core
project.lock.json
project.fragment.lock.json
artifacts/
# ASP.NET Scaffolding
ScaffoldingReadMe.txt
# StyleCop
StyleCopReport.xml
# Files built by Visual Studio
*_i.c
*_p.c
*_h.h
*.ilk
*.meta
*.obj
*.iobj
*.pch
*.pdb
*.ipdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*_wpftmp.csproj
*.log
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc
# Chutzpah Test files
_Chutzpah*
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opendb
*.opensdf
*.sdf
*.cachefile
*.VC.db
*.VC.VC.opendb
# Visual Studio profiler
*.psess
*.vsp
*.vspx
*.sap
# Visual Studio Trace Files
*.e2e
# TFS 2012 Local Workspace
$tf/
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user
# TeamCity is a build add-in
_TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
# AxoCover is a Code Coverage Tool
.axoCover/*
!.axoCover/settings.json
# Coverlet is a free, cross platform Code Coverage Tool
coverage*.json
coverage*.xml
coverage*.info
# Visual Studio code coverage results
*.coverage
*.coveragexml
# NCrunch
_NCrunch_*
.*crunch*.local.xml
nCrunchTemp_*
# MightyMoose
*.mm.*
AutoTest.Net/
# Web workbench (sass)
.sass-cache/
# Installshield output folder
[Ee]xpress/
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html
# Click-Once directory
publish/
# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
# Note: Comment the next line if you want to checkin your web deploy settings,
# but database connection strings (with potential passwords) will be unencrypted
*.pubxml
*.publishproj
# Microsoft Azure Web App publish settings. Comment the next line if you want to
# checkin your Azure Web App publish settings, but sensitive information contained
# in these scripts will be unencrypted
PublishScripts/
# NuGet Packages
*.nupkg
# NuGet Symbol Packages
*.snupkg
# The packages folder can be ignored because of Package Restore
**/[Pp]ackages/*
# except build/, which is used as an MSBuild target.
!**/[Pp]ackages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/[Pp]ackages/repositories.config
# NuGet v3's project.json files produces more ignorable files
*.nuget.props
*.nuget.targets
# Microsoft Azure Build Output
csx/
*.build.csdef
# Microsoft Azure Emulator
ecf/
rcf/
# Windows Store app package directories and files
AppPackages/
BundleArtifacts/
Package.StoreAssociation.xml
_pkginfo.txt
*.appx
*.appxbundle
*.appxupload
# Visual Studio cache files
# files ending in .cache can be ignored
*.[Cc]ache
# but keep track of directories ending in .cache
!?*.[Cc]ache/
# Others
ClientBin/
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.jfm
*.pfx
*.publishsettings
orleans.codegen.cs
# Including strong name files can present a security risk
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
#*.snk
# Since there are multiple workflows, uncomment next line to ignore bower_components
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
#bower_components/
# RIA/Silverlight projects
Generated_Code/
# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
ServiceFabricBackup/
*.rptproj.bak
# SQL Server files
*.mdf
*.ldf
*.ndf
# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings
*.rptproj.rsuser
*- [Bb]ackup.rdl
*- [Bb]ackup ([0-9]).rdl
*- [Bb]ackup ([0-9][0-9]).rdl
# Microsoft Fakes
FakesAssemblies/
# GhostDoc plugin setting file
*.GhostDoc.xml
# Node.js Tools for Visual Studio
.ntvs_analysis.dat
node_modules/
# Visual Studio 6 build log
*.plg
# Visual Studio 6 workspace options file
*.opt
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
*.vbw
# Visual Studio LightSwitch build output
**/*.HTMLClient/GeneratedArtifacts
**/*.DesktopClient/GeneratedArtifacts
**/*.DesktopClient/ModelManifest.xml
**/*.Server/GeneratedArtifacts
**/*.Server/ModelManifest.xml
_Pvt_Extensions
# Paket dependency manager
.paket/paket.exe
paket-files/
# FAKE - F# Make
.fake/
# CodeRush personal settings
.cr/personal
# Python Tools for Visual Studio (PTVS)
__pycache__/
*.pyc
# Cake - Uncomment if you are using it
# tools/**
# !tools/packages.config
# Tabs Studio
*.tss
# Telerik's JustMock configuration file
*.jmconfig
# BizTalk build output
*.btp.cs
*.btm.cs
*.odx.cs
*.xsd.cs
# OpenCover UI analysis results
OpenCover/
# Azure Stream Analytics local run output
ASALocalRun/
# MSBuild Binary and Structured Log
*.binlog
# NVidia Nsight GPU debugger configuration file
*.nvuser
# MFractors (Xamarin productivity tool) working folder
.mfractor/
# Local History for Visual Studio
.localhistory/
# BeatPulse healthcheck temp database
healthchecksdb
# Backup folder for Package Reference Convert tool in Visual Studio 2017
MigrationBackup/
# Ionide (cross platform F# VS Code tools) working folder
.ionide/
# Fody - auto-generated XML schema
FodyWeavers.xsd

View File

@ -0,0 +1,25 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework>
<RootNamespace>GCLocalServerRewrite</RootNamespace>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="CertificateManager" Version="1.0.8" />
<PackageReference Include="ChoETL" Version="1.2.1.44" />
<PackageReference Include="EmbedIO" Version="3.4.3" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="6.0.0" />
<PackageReference Include="sqlite-net2" Version="2.0.7" />
<PackageReference Include="SQLitePCLRaw.bundle_e_sqlite3" Version="2.0.7" />
<PackageReference Include="System.Security.Cryptography.X509Certificates" Version="4.3.2" />
</ItemGroup>
<ItemGroup>
<Folder Include="log" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<appSettings>
<add key="AvatarCount" value="294"/>
<add key="NavigatorCount" value="71"/>
<add key="ItemCount" value="21"/>
<add key="SkinCount" value="21"/>
<add key="SeCount" value="25"/>
<add key="TitleCount" value="4942"/>
</appSettings>
</configuration>

View File

@ -0,0 +1,85 @@
using GCLocalServerRewrite.common;
using GCLocalServerRewrite.server;
using SQLitePCL;
using Swan;
using Swan.Logging;
namespace GCLocalServerRewrite;
internal class Program
{
private static void Main(string[] args)
{
Batteries_V2.Init();
InitializeLogging();
var urlPrefixes = args.Length > 0 ? args : new[] { "http://*:80", "https://*:443" };
using (var cts = new CancellationTokenSource())
{
Task.WaitAll(
RunWebServerAsync(urlPrefixes, cts.Token),
Task.CompletedTask,
WaitForUserBreakAsync(cts.Cancel));
}
// Clean up
"Bye".Info(nameof(Program));
Terminal.Flush();
Console.WriteLine("Press any key to exit.");
WaitForKeypress();
}
private static void InitializeLogging()
{
if (!Directory.Exists(PathHelper.LogRootPath))
{
Directory.CreateDirectory(PathHelper.LogRootPath);
}
Logger.RegisterLogger(new FileLogger(PathHelper.LogRootPath, true));
}
/// <summary>
/// Create and run a web server.
/// </summary>
/// <param name="urlPrefixes"></param>
/// <param name="cancellationToken"></param>
private static async Task RunWebServerAsync(string[] urlPrefixes, CancellationToken cancellationToken)
{
using var server = Server.CreateWebServer(urlPrefixes);
await server.RunAsync(cancellationToken).ConfigureAwait(false);
}
/// <summary>
/// Prompt the user to press any key;
/// when a key is next pressed, call the specified action to cancel operations.
/// </summary>
/// <param name="cancel"> Cancel Action to call </param>
private static async Task WaitForUserBreakAsync(Action cancel)
{
// Be sure to run in parallel.
await Task.Yield();
"Press any key to stop the web server.".Info(nameof(Program));
WaitForKeypress();
"Stopping...".Info(nameof(Program));
cancel();
}
/// <summary>
/// Clear the console input buffer and wait for a keypress
/// </summary>
private static void WaitForKeypress()
{
while (Console.KeyAvailable)
{
Console.ReadKey(true);
}
Console.ReadKey(true);
}
}

View File

@ -0,0 +1,74 @@
using EmbedIO;
namespace GCLocalServerRewrite.backports;
/// <summary>
/// Provides custom response serializer callbacks.
/// </summary>
public static class CustomResponseSerializer
{
private static readonly ResponseSerializerCallback CHUNKED_ENCODING_BASE_SERIALIZER = GetBaseSerializer(false);
private static readonly ResponseSerializerCallback BUFFERING_BASE_SERIALIZER = GetBaseSerializer(true);
/// <summary>
/// Sends data in a HTTP response without serialization.
/// </summary>
/// <param name="bufferResponse">
/// <see langword="true" /> to write the response body to a memory buffer first,
/// then send it all together with a <c>Content-Length</c> header; <see langword="false" /> to use chunked
/// transfer encoding.
/// </param>
/// <returns>A <see cref="ResponseSerializerCallback" /> that can be used to serialize data to a HTTP response.</returns>
/// <remarks>
/// <para>
/// <see cref="string" />s and one-dimensional arrays of <see cref="byte" />s
/// are sent to the client unchanged; every other type is converted to a string.
/// </para>
/// <para>
/// The <see cref="IHttpResponse.ContentType">ContentType</see> set on the response is used to negotiate
/// a compression method, according to request headers.
/// </para>
/// <para>
/// Strings (and other types converted to strings) are sent with the encoding specified by
/// <see cref="IHttpResponse.ContentEncoding" />.
/// </para>
/// </remarks>
public static ResponseSerializerCallback None(bool bufferResponse)
{
return bufferResponse ? BUFFERING_BASE_SERIALIZER : CHUNKED_ENCODING_BASE_SERIALIZER;
}
private static ResponseSerializerCallback GetBaseSerializer(bool bufferResponse)
{
return async (context, data) =>
{
if (data is null)
{
return;
}
var isBinaryResponse = data is byte[];
if (!context.TryDetermineCompression(context.Response.ContentType, out var preferCompression))
{
preferCompression = true;
}
preferCompression = false;
if (isBinaryResponse)
{
var responseBytes = (byte[])data;
using var stream = context.OpenResponseStream(bufferResponse, preferCompression);
await stream.WriteAsync(responseBytes).ConfigureAwait(false);
}
else
{
var responseString = data is string stringData ? stringData : data.ToString() ?? string.Empty;
await using var text = context.OpenResponseText(context.Response.ContentEncoding, bufferResponse,
preferCompression);
await text.WriteAsync(responseString).ConfigureAwait(false);
}
};
}
}

View File

@ -0,0 +1,234 @@
using System.Diagnostics;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using CertificateManager;
using CertificateManager.Models;
using Microsoft.Extensions.DependencyInjection;
using Swan;
using Swan.Logging;
namespace GCLocalServerRewrite.common;
public static class CertificateHelper
{
private const X509KeyUsageFlags ROOT_CA_X509_KEY_USAGE_FLAGS = X509KeyUsageFlags.KeyCertSign |
X509KeyUsageFlags.DataEncipherment |
X509KeyUsageFlags.KeyEncipherment |
X509KeyUsageFlags.DigitalSignature;
private const X509KeyStorageFlags X509_KEY_STORAGE_FLAGS_MACHINE = X509KeyStorageFlags.PersistKeySet
| X509KeyStorageFlags.MachineKeySet;
private const X509KeyUsageFlags CERT_X509_KEY_USAGE_FLAGS = X509KeyUsageFlags.DataEncipherment |
X509KeyUsageFlags.KeyEncipherment |
X509KeyUsageFlags.DigitalSignature;
private static readonly DistinguishedName ROOT_CA_DISTINGUISHED_NAME = new()
{
CommonName = Configs.ROOT_CA_CN
};
private static readonly DistinguishedName CERT_DISTINGUISHED_NAME = new()
{
CommonName = Configs.CERT_CN
};
private static readonly BasicConstraints ROOT_CA_BASIC_CONSTRAINTS = new()
{
CertificateAuthority = true,
HasPathLengthConstraint = true,
PathLengthConstraint = 3,
Critical = true
};
public static readonly BasicConstraints CERT_BASIC_CONSTRAINTS = new()
{
CertificateAuthority = false,
HasPathLengthConstraint = false,
PathLengthConstraint = 0,
Critical = true,
};
private static readonly SubjectAlternativeName SUBJECT_ALTERNATIVE_NAME = new()
{
DnsName = new List<string>
{
"localhost"
}
};
private static readonly ValidityPeriod VALIDITY_PERIOD = new()
{
ValidFrom = DateTime.UtcNow,
ValidTo = DateTime.UtcNow.AddYears(3)
};
private static readonly OidCollection OID_COLLECTION = new()
{
OidLookup.AnyPurpose
};
public static X509Certificate2 InitializeCertificate()
{
if (CertificateExists())
{
var existingCert = GetCertificate(StoreName.My, StoreLocation.LocalMachine, Configs.CERT_CN);
if (existingCert != null)
{
return existingCert;
}
}
RemovePreviousCert(StoreName.My, StoreLocation.LocalMachine);
RemovePreviousCert(StoreName.Root, StoreLocation.LocalMachine);
var serviceProvider = new ServiceCollection()
.AddCertificateManager().BuildServiceProvider();
var createCertificates = serviceProvider.GetService<CreateCertificates>();
if (createCertificates == null)
{
throw SelfCheck.Failure("Cannot initialize CreateCertificates service!");
}
var rootCa = createCertificates.NewRsaSelfSignedCertificate(
ROOT_CA_DISTINGUISHED_NAME,
ROOT_CA_BASIC_CONSTRAINTS,
VALIDITY_PERIOD,
SUBJECT_ALTERNATIVE_NAME,
OID_COLLECTION,
ROOT_CA_X509_KEY_USAGE_FLAGS,
new RsaConfiguration()
);
var cert = createCertificates.NewRsaChainedCertificate(
CERT_DISTINGUISHED_NAME,
CERT_BASIC_CONSTRAINTS,
VALIDITY_PERIOD,
SUBJECT_ALTERNATIVE_NAME,
rootCa,
OID_COLLECTION,
CERT_X509_KEY_USAGE_FLAGS,
new RsaConfiguration()
);
var exportService = serviceProvider.GetService<ImportExportCertificate>();
if (exportService == null)
{
throw SelfCheck.Failure("Cannot initialize ImportExportCertificate service!");
}
var rootCaPfxBytes = exportService.ExportRootPfx(null, rootCa);
var certPfxBytes = exportService.ExportChainedCertificatePfx(null, cert, rootCa);
var rootCaWithPrivateKey = new X509Certificate2(rootCaPfxBytes, (string)null!,
X509_KEY_STORAGE_FLAGS_MACHINE);
var certWithPrivateKey = new X509Certificate2(certPfxBytes, (string)null!,
X509_KEY_STORAGE_FLAGS_MACHINE);
AddCertToStore(rootCaWithPrivateKey, StoreName.My, StoreLocation.LocalMachine);
AddCertToStore(rootCaWithPrivateKey, StoreName.Root, StoreLocation.LocalMachine);
AddCertToStore(certWithPrivateKey, StoreName.My, StoreLocation.LocalMachine);
return certWithPrivateKey;
}
private static void AddCertToStore(X509Certificate2 cert, StoreName storeName, StoreLocation storeLocation)
{
try
{
var store = new X509Store(storeName, storeLocation);
store.Open(OpenFlags.ReadWrite);
store.Add(cert);
store.Close();
}
catch (Exception e)
{
e.Error(e.Source ?? "", e.Message);
}
}
private static void RemovePreviousCert(StoreName storeName, StoreLocation storeLocation)
{
try
{
var store = new X509Store(storeName, storeLocation);
store.Open(OpenFlags.ReadWrite);
var result = store.Certificates.Find(X509FindType.FindByIssuerName, Configs.ROOT_CA_CN, true);
if (result.Any())
{
store.RemoveRange(result);
"Removed previous certs!".Info();
}
store.Close();
}
catch (Exception e)
{
e.Error(e.Source ?? "", e.Message);
}
}
private static bool CertificateExists()
{
try
{
var store = new X509Store(StoreName.My, StoreLocation.LocalMachine);
store.Open(OpenFlags.ReadOnly);
var result = store.Certificates.Find(X509FindType.FindByIssuerName, Configs.ROOT_CA_CN, true);
if (result.Count == 2)
{
"Certificate exists!".Info();
return true;
}
store.Close();
"Certificate not found! Will generate new certs...".Info();
return false;
}
catch (Exception e)
{
e.Error(e.Source ?? "", e.Message);
return false;
}
}
private static X509Certificate2? GetCertificate(StoreName storeName, StoreLocation storeLocation, string commonName)
{
try
{
var store = new X509Store(storeName, storeLocation);
store.Open(OpenFlags.ReadWrite);
var result = store.Certificates.Find(X509FindType.FindBySubjectDistinguishedName,
$"CN={commonName}", true);
if (result.Any())
{
$"Certificate CN={commonName} found!".Info();
return result.First();
}
store.Close();
return null;
}
catch (Exception e)
{
e.Error(e.Source ?? "", e.Message);
return null;
}
}
}

View File

@ -0,0 +1,140 @@
using System.Configuration;
namespace GCLocalServerRewrite.common;
public static class Configs
{
public const bool USE_FILE_CACHE = true;
public const string ROOT_CA_CN = "Taito Arcade Machine CA";
public const string CERT_CN = "GC local server";
public const string DB_FOLDER = "db";
public const string LOG_FOLDER = "log";
public const string LOG_BASE_NAME = "log";
public const string STATIC_FOLDER = "static";
public const string CARD_SERVICE_BASE_ROUTE = "/service/card";
public const string UPLOAD_SERVICE_BASE_ROUTE = "/service/upload";
public const string RESPONE_SERVICE_BASE_ROUTE = "/service/respone";
public const string INCOM_SERVICE_BASE_ROUTE = "/service/incom";
public const string RANK_BASE_ROUTE = "/ranking";
public const string ALIVE_BASE_ROUTE = "/alive";
public const string SERVER_BASE_ROUTE = "/server";
public const string STATIC_BASE_ROUTE = "/static";
public const string CARD_DB_NAME = "card.db3";
public const string MUSIC_DB_NAME = "music.db3";
public const string ROOT_XPATH = "/root";
public const string DATA_XPATH = $"{ROOT_XPATH}/data";
public const string CARD = "card";
public const string CARD_XPATH = $"{ROOT_XPATH}/{CARD}";
public const string CARD_DETAIL = "card_detail";
public const string CARD_DETAIL_XPATH = $"{ROOT_XPATH}/{CARD_DETAIL}";
public const string CARD_DETAIL_RECORD_XPATH = $"{CARD_DETAIL_XPATH}/record";
public const string CARD_BDATA = "card_bdata";
public const string CARD_BDATA_XPATH = $"{ROOT_XPATH}/{CARD_BDATA}";
public const string MUSIC = "music";
public const string MUSIC_XPATH = $"{ROOT_XPATH}/{MUSIC}/record";
public const string MUSIC_EXTRA = "music_extra";
public const string MUSIC_EXTRA_XPATH = $"{ROOT_XPATH}/{MUSIC_EXTRA}/record";
public const string MUSIC_AOU = "music_aou";
public const string MUSIC_AOU_XPATH = $"{ROOT_XPATH}/{MUSIC_AOU}";
public const string ITEM = "item";
public const string ITEM_XPATH = $"{ROOT_XPATH}/{ITEM}/record";
public const string AVATAR = "avatar";
public const string AVATAR_XPATH = $"{ROOT_XPATH}/{AVATAR}/record";
public const string SKIN = "skin";
public const string SKIN_XPATH = $"{ROOT_XPATH}/{SKIN}/record";
public const string TITLE = "title";
public const string TITLE_XPATH = $"{ROOT_XPATH}/{TITLE}/record";
public const string NAVIGATOR = "navigator";
public const string NAVIGATOR_XPATH = $"{ROOT_XPATH}/{NAVIGATOR}/record";
public const string COIN = "coin";
public const string COIN_XPATH = $"{ROOT_XPATH}/{COIN}";
public const string UNLOCK_REWARD = "unlock_reward";
public const string UNLOCK_REWARD_XPATH = $"{ROOT_XPATH}/{UNLOCK_REWARD}/record";
public const string UNLOCK_KEYNUM = "unlock_keynum";
public const string UNLOCK_KEYNUM_XPATH = $"{ROOT_XPATH}/{UNLOCK_KEYNUM}/record";
public const string SOUND_EFFECT = "sound_effect";
public const string SE_XPATH = $"{ROOT_XPATH}/{SOUND_EFFECT}/record";
public const string GET_MESSAGE = "get_message";
public const string TOTAL_TROPHY = "total_trophy";
public const string TOTAL_TROPHY_XPATH = $"{ROOT_XPATH}/{TOTAL_TROPHY}";
public const string EVENT_REWARD = "event_reward";
public const string COND = "cond";
public const string SESSION_XPATH = $"{ROOT_XPATH}/session";
public const string RANK_STATUS_XPATH = $"{ROOT_XPATH}/ranking_status";
public const int GC4_EX_GID = 303801;
public static readonly int AVATAR_COUNT = int.Parse(
ConfigurationManager.AppSettings.Get("AvatarCount") ?? "294");
public static readonly int NAVIGATOR_COUNT = int.Parse(
ConfigurationManager.AppSettings.Get("NavigatorCount") ?? "71");
public static readonly int ITEM_COUNT = int.Parse(
ConfigurationManager.AppSettings.Get("ItemCount") ?? "21");
public static readonly int TITLE_COUNT = int.Parse(
ConfigurationManager.AppSettings.Get("TitleCount") ?? "4942");
public static readonly int SKIN_COUNT = int.Parse(
ConfigurationManager.AppSettings.Get("SkinCount") ?? "21");
public static readonly int SE_COUNT = int.Parse(
ConfigurationManager.AppSettings.Get("SeCount") ?? "25");
}

View File

@ -0,0 +1,40 @@
using SQLite.Net2;
namespace GCLocalServerRewrite.common;
public class DatabaseHelper
{
/// <summary>
/// Static method to allow local data services to initialise their associated database conveniently.
/// </summary>
/// <param name="databaseName">The SQLite database name</param>
/// <param name="tables">The SQLite database tables to create (if required)</param>
/// <returns>An initialised SQLite database connection</returns>
public static SQLiteConnection InitializeLocalDatabase(string databaseName, params Type[] tables)
{
if (!Directory.Exists(PathHelper.DataBaseRootPath))
{
Directory.CreateDirectory(PathHelper.DataBaseRootPath);
}
var databasePath = Path.Combine(PathHelper.DataBaseRootPath, databaseName);
var database = new SQLiteConnection(databasePath);
foreach (var table in tables)
{
database.CreateTable(table);
}
return database;
}
public static SQLiteConnection ConnectDatabase(string databaseName)
{
var databasePath = Path.Combine(PathHelper.DataBaseRootPath, databaseName);
var database = new SQLiteConnection(databasePath);
return database;
}
}

View File

@ -0,0 +1,39 @@
using System.Diagnostics;
namespace GCLocalServerRewrite.common;
public class PathHelper
{
/// <summary>
/// Gets the local path of html/static files.
/// </summary>
public static string HtmlRootPath => Path.Combine(BasePath, Configs.STATIC_FOLDER);
/// <summary>
/// Root path for database, when debug, it's under source root, when release, it's the exe dir
/// </summary>
public static string DataBaseRootPath => Path.Combine(BasePath, Configs.DB_FOLDER);
public static string LogRootPath => Path.Combine(BasePath, Configs.LOG_FOLDER, Configs.LOG_BASE_NAME);
private static string BasePath
{
get
{
var assemblyPath = Path.GetDirectoryName(typeof(Program).Assembly.Location);
#if DEBUG
Debug.Assert(assemblyPath != null, $"{nameof(assemblyPath)} != null");
var parentFullName = Directory.GetParent(assemblyPath)?.Parent?.Parent?.FullName;
Debug.Assert(parentFullName != null, $"{nameof(parentFullName)} != null");
return parentFullName;
#else
return assemblyPath;
#endif
}
}
}

View File

@ -0,0 +1,34 @@
using System.Net;
using System.Net.Mime;
using System.Text;
using EmbedIO;
using EmbedIO.Routing;
using EmbedIO.WebApi;
namespace GCLocalServerRewrite.controllers;
public class AliveController : WebApiController
{
[Route(HttpVerbs.Get, "/i.php")]
// ReSharper disable once UnusedMember.Global
public string Check()
{
HttpContext.Response.ContentType = MediaTypeNames.Text.Html;
HttpContext.Response.ContentEncoding = Encoding.Default;
HttpContext.Response.KeepAlive = true;
return "REMOTE ADDRESS: 127.0.0.1\n" +
"SERVER NAME:nesys.home\n" +
"SERVER ADDR:239.1.1.1";
}
[Route(HttpVerbs.Get, "/{id}/Alive.txt")]
// ReSharper disable once UnusedMember.Global
public void AliveFile()
{
HttpContext.Response.SetEmptyResponse((int)HttpStatusCode.OK);
HttpContext.Response.ContentType = MediaTypeNames.Text.Plain;
HttpContext.Response.ContentEncoding = Encoding.Default;
HttpContext.Response.KeepAlive = true;
}
}

View File

@ -0,0 +1,529 @@
using System.Data;
using System.Net.Mime;
using System.Text;
using System.Xml.Linq;
using ChoETL;
using EmbedIO;
using EmbedIO.Routing;
using EmbedIO.WebApi;
using GCLocalServerRewrite.common;
using GCLocalServerRewrite.models;
using SQLite.Net2;
using Swan.Logging;
namespace GCLocalServerRewrite.controllers;
public class CardServiceController : WebApiController
{
private readonly SQLiteConnection cardSqLiteConnection;
private readonly SQLiteConnection musicSqLiteConnection;
public CardServiceController()
{
cardSqLiteConnection = DatabaseHelper.ConnectDatabase(Configs.CARD_DB_NAME);
musicSqLiteConnection = DatabaseHelper.ConnectDatabase(Configs.MUSIC_DB_NAME);
}
[Route(HttpVerbs.Post, "/cardn.cgi")]
// ReSharper disable once UnusedMember.Global
public string CardService([FormField] int gid, [FormField("mac_addr")] string mac, [FormField] int type,
[FormField("card_no")] long cardId, [FormField("data")] string xmlData)
{
HttpContext.Response.ContentType = MediaTypeNames.Application.Octet;
HttpContext.Response.ContentEncoding = Encoding.Default;
HttpContext.Response.KeepAlive = true;
if (gid != Configs.GC4_EX_GID)
{
throw new ArgumentOutOfRangeException(nameof(gid));
}
if (!Enum.IsDefined(typeof(CardRequestType), type))
{
throw new ArgumentOutOfRangeException(nameof(type));
}
var requestType = (CardRequestType)type;
switch (requestType)
{
#region ReadRequests
case CardRequestType.ReadCard:
{
$"Getting read request, type is {requestType}".Info();
return ConstructResponse(Card(cardId));
}
case CardRequestType.ReadCardDetail:
{
$"Getting read request, type is {requestType}".Info();
return ConstructResponse(CardDetail(cardId, xmlData));
}
case CardRequestType.ReadCardDetails:
{
$"Getting read request, type is {requestType}".Info();
return ConstructResponse(CardDetails(cardId));
}
case CardRequestType.ReadCardBData:
{
$"Getting read request, type is {requestType}".Info();
return ConstructResponse(CardBData(cardId));
}
case CardRequestType.ReadAvatar:
{
$"Getting read request, type is {requestType}".Info();
return ConstructResponse(
GetStaticCount<Avatar>(cardId, Configs.AVATAR_COUNT, Configs.AVATAR_XPATH));
}
case CardRequestType.ReadItem:
{
$"Getting read request, type is {requestType}".Info();
return ConstructResponse(
GetStaticCount<Item>(cardId, Configs.ITEM_COUNT, Configs.ITEM_XPATH));
}
case CardRequestType.ReadSkin:
{
$"Getting read request, type is {requestType}".Info();
return ConstructResponse(
GetStaticCount<Skin>(cardId, Configs.SKIN_COUNT, Configs.SKIN_XPATH));
}
case CardRequestType.ReadTitle:
{
$"Getting read request, type is {requestType}".Info();
return ConstructResponse(
GetStaticCount<Title>(cardId, Configs.TITLE_COUNT, Configs.TITLE_XPATH));
}
case CardRequestType.ReadMusic:
{
$"Getting read request, type is {requestType}".Info();
return ConstructResponse(MusicUnlock());
}
case CardRequestType.ReadEventReward:
{
$"Getting read request, type is {requestType}".Info();
return ConstructResponse(
GenerateEmptyXML(Configs.EVENT_REWARD));
}
case CardRequestType.ReadNavigator:
{
$"Getting read request, type is {requestType}".Info();
return ConstructResponse(
GetStaticCount<Navigator>(cardId, Configs.NAVIGATOR_COUNT, Configs.NAVIGATOR_XPATH));
}
case CardRequestType.ReadMusicExtra:
{
$"Getting read request, type is {requestType}".Info();
return ConstructResponse(MusicExtra());
}
case CardRequestType.ReadMusicAou:
{
$"Getting read request, type is {requestType}".Info();
return ConstructResponse(GenerateEmptyXML(Configs.MUSIC_AOU));
}
case CardRequestType.ReadCoin:
{
$"Getting read request, type is {requestType}".Info();
return ConstructResponse(Coin(cardId));
}
case CardRequestType.ReadUnlockReward:
{
$"Getting read request, type is {requestType}".Info();
return ConstructResponse(UnlockReward(cardId));
}
case CardRequestType.ReadUnlockKeynum:
{
$"Getting read request, type is {requestType}".Info();
return ConstructResponse(UnlockKeynum(cardId));
}
case CardRequestType.ReadSoundEffect:
{
$"Getting read request, type is {requestType}".Info();
return ConstructResponse(
GetStaticCount<SoundEffect>(cardId, Configs.SE_COUNT, Configs.SE_XPATH));
}
case CardRequestType.ReadGetMessage:
{
$"Getting read request, type is {requestType}".Info();
return ConstructResponse(GenerateEmptyXML(Configs.GET_MESSAGE));
}
case CardRequestType.ReadCond:
{
$"Getting read request, type is {requestType}".Info();
return ConstructResponse(GenerateEmptyXML(Configs.COND));
}
case CardRequestType.ReadTotalTrophy:
{
$"Getting read request, type is {requestType}".Info();
return ConstructResponse(TotalTrophy(cardId));
}
case CardRequestType.SessionStart:
case CardRequestType.SessionGet:
{
$"Getting read request, type is {requestType}".Info();
return ConstructResponse(GetSession(cardId, mac));
}
#endregion
#region WriteRequests
case CardRequestType.WriteCardDetail:
{
$"Getting write request, type is {requestType}\n Data is {xmlData}".Info();
Write<CardDetail>(cardId, xmlData);
return ConstructResponse(xmlData);
}
case CardRequestType.WriteCardBData:
{
$"Getting write request, type is {requestType}\n Data is {xmlData}".Info();
Write<CardBData>(cardId, xmlData);
return ConstructResponse(xmlData);
}
case CardRequestType.WriteCard:
{
$"Getting write request, type is {requestType}\n Data is {xmlData}".Info();
Write<Card>(cardId, xmlData);
return ConstructResponse(xmlData);
}
case CardRequestType.WriteAvatar:
case CardRequestType.WriteItem:
case CardRequestType.WriteTitle:
case CardRequestType.WriteMusicDetail:
case CardRequestType.WriteNavigator:
case CardRequestType.WriteCoin:
case CardRequestType.WriteSkin:
case CardRequestType.WriteUnlockKeynum:
case CardRequestType.WriteSoundEffect:
{
$"Getting write request, type is {requestType}\n Data is {xmlData}".Info();
return ConstructResponse(xmlData);
}
#endregion
default:
#pragma warning disable CA2208
throw new ArgumentOutOfRangeException(nameof(requestType));
#pragma warning restore CA2208
}
}
#region ReadImplementation
private string Card(long cardId)
{
var result = cardSqLiteConnection.Table<Card>().Where(card => card.CardId == cardId);
if (!result.Any())
{
return GenerateEmptyXML(Configs.CARD);
}
var card = result.First();
return GenerateSingleXml(card, Configs.CARD_XPATH);
}
private string CardDetail(long cardId, string xmlData)
{
var reader = new ChoXmlReader<CardDetailReadData>(new StringReader(xmlData));
var data = reader.Read();
var result = cardSqLiteConnection.Table<CardDetail>()
.Where(detail => detail.CardId == cardId &&
detail.Pcol1 == data.Pcol1 && detail.Pcol2 == data.Pcol2 &&
detail.Pcol3 == data.Pcol3);
if (!result.Any())
{
return GenerateEmptyXML(Configs.CARD_DETAIL);
}
var cardDetail = result.First();
return GenerateSingleXml(cardDetail, Configs.CARD_DETAIL_RECORD_XPATH);
}
private string CardDetails(long cardId)
{
var result = cardSqLiteConnection.Table<CardDetail>()
.Where(detail => detail.CardId == cardId);
if (!result.Any())
{
return GenerateEmptyXML(Configs.CARD_DETAIL);
}
var cardDetails = result.ToList();
return GenerateRecordsXml(cardDetails, Configs.CARD_DETAIL_XPATH);
}
private string CardBData(long cardId)
{
var result = cardSqLiteConnection.Table<CardBData>()
.Where(detail => detail.CardId == cardId);
if (!result.Any())
{
return GenerateEmptyXML(Configs.CARD_BDATA);
}
var cardBData = result.First();
return GenerateSingleXml(cardBData, Configs.CARD_BDATA_XPATH);
}
private static string GetStaticCount<T>(long cardId, int count, string xpath)
where T : Record, IIdModel, ICardIdModel, new()
{
var models = new List<T>();
for (var id = 1; id <= count; id++)
{
var model = new T();
model.SetId(id);
model.SetCardId(cardId);
models.Add(model);
}
return GenerateRecordsXml(models, xpath);
}
private static string GetSession(long cardId, string mac)
{
var session = new Session
{
CardId = cardId,
Mac = mac,
SessionId = "12345678901234567890123456789012",
Expires = 9999,
PlayerId = 1
};
return GenerateSingleXml(session, Configs.SESSION_XPATH);
}
private static string TotalTrophy(long cardId)
{
var trophy = new TotalTrophy
{
CardId = cardId,
TrophyNum = 9
};
return GenerateSingleXml(trophy, Configs.TOTAL_TROPHY_XPATH);
}
private static string Coin(long cardId)
{
var coin = new Coin
{
CardId = cardId,
CurrentCoins = 999999,
TotalCoins = 999999,
MonthlyCoins = 999999
};
return GenerateSingleXml(coin, Configs.COIN_XPATH);
}
private static string UnlockReward(long cardId)
{
var unlockRewards = new List<UnlockReward>
{
new()
{
CardId = cardId,
RewardType = 1,
RewardId = 1,
TargetId = 1,
TargetNum = 1,
KeyNum = 3
}
};
return GenerateRecordsXml(unlockRewards, Configs.UNLOCK_REWARD_XPATH);
}
private static string UnlockKeynum(long cardId)
{
var unlockKeynums = new List<UnlockKeynum>
{
new()
{
CardId = cardId,
RewardId = 1,
KeyNum = 0,
RewardCount = 1
}
};
return GenerateRecordsXml(unlockKeynums, Configs.UNLOCK_KEYNUM_XPATH);
}
private string MusicUnlock()
{
var result = musicSqLiteConnection.Table<Music>().ToList();
return GenerateRecordsXml(result, Configs.MUSIC_XPATH);
}
private string MusicExtra()
{
var result = musicSqLiteConnection.Table<MusicExtra>().ToList();
return GenerateRecordsXml(result, Configs.MUSIC_EXTRA_XPATH);
}
#endregion
#region HelperMethods
private static string ConstructResponse(string xml)
{
return "1\n" +
"10,10\n" +
xml;
}
private static string GenerateEmptyXML(string fieldName)
{
var xml = new XDocument(new XElement("root",
new XElement(fieldName)));
xml.Declaration = new XDeclaration("1.0", "UTF-8", null);
return xml.ToString();
}
private static string GenerateSingleXml<T>(T obj, string xpath) where T: class
{
var sb = new StringBuilder();
using (var writer = new ChoXmlWriter<T>(sb))
{
writer.Configuration.OmitXmlDeclaration = false;
writer.Configuration.UseXmlSerialization = true;
writer.WithXPath(xpath);
writer.Write(obj);
}
return sb.ToString();
}
private static string GenerateRecordsXml<T>(IReadOnlyList<T> list, string xpath) where T : Record
{
var stringBuilder = new StringBuilder();
using (var writer = new ChoXmlWriter<T>(stringBuilder))
{
writer.Configuration.OmitXmlDeclaration = false;
writer.Configuration.UseXmlSerialization = true;
writer.WithXPath(xpath);
for (var i = 0; i < list.Count; i++)
{
var obj = list[i];
obj.RecordId = i + 1;
writer.Write(obj);
}
}
return stringBuilder.ToString();
}
#endregion
#region WriteImplementation
private void Write<T>(long cardId, string xmlData) where T : class, ICardIdModel
{
var reader = new ChoXmlReader<T>(new StringReader(xmlData)).WithXPath(Configs.DATA_XPATH);
var writeObject = reader.Read();
if (writeObject == null)
{
throw new HttpRequestException();
}
writeObject.SetCardId(cardId);
var rowsAffected = cardSqLiteConnection.InsertOrReplace(writeObject, typeof(T));
if (rowsAffected == 0)
{
throw new ApplicationException("Update database failed!");
}
$"Updated {typeof(T)}".Info();
}
#endregion
private enum CardRequestType
{
// Read data
ReadCard = 259,
ReadCardDetail = 260,
ReadCardDetails = 261,
ReadCardBData = 264,
ReadAvatar = 418,
ReadItem = 420,
ReadSkin = 422,
ReadTitle = 424,
ReadMusic = 428,
ReadEventReward = 441,
ReadNavigator = 443,
ReadMusicExtra = 465,
ReadMusicAou = 467,
ReadCoin = 468,
ReadUnlockReward = 507,
ReadUnlockKeynum = 509,
ReadSoundEffect = 8458,
ReadGetMessage = 8461,
ReadCond = 8465,
ReadTotalTrophy = 8468,
// Sessions
SessionGet = 401,
SessionStart = 402,
// Write data
WriteCard = 771,
WriteCardDetail = 772,
WriteCardBData = 776,
WriteAvatar = 929,
WriteItem = 931,
WriteTitle = 935,
WriteMusicDetail = 94,
WriteNavigator = 954,
WriteCoin = 980,
WriteSkin = 933,
WriteUnlockKeynum = 1020,
WriteSoundEffect = 8969
}
}

View File

@ -0,0 +1,32 @@
using System.Net.Mime;
using System.Text;
using EmbedIO;
using EmbedIO.Routing;
using EmbedIO.WebApi;
namespace GCLocalServerRewrite.controllers;
public class IncomServiceController : WebApiController
{
[Route(HttpVerbs.Post, "/incom.php")]
// ReSharper disable once UnusedMember.Global
public string IncomService()
{
HttpContext.Response.ContentType = MediaTypeNames.Text.Plain;
HttpContext.Response.ContentEncoding = Encoding.Default;
HttpContext.Response.KeepAlive = true;
return "1+1";
}
[Route(HttpVerbs.Post, "/incomALL.php")]
// ReSharper disable once UnusedMember.Global
public string IncomAllService()
{
HttpContext.Response.ContentType = MediaTypeNames.Text.Plain;
HttpContext.Response.ContentEncoding = Encoding.Default;
HttpContext.Response.KeepAlive = true;
return "1+1";
}
}

View File

@ -0,0 +1,109 @@
using System.Net.Mime;
using System.Text;
using System.Xml;
using ChoETL;
using EmbedIO;
using EmbedIO.Routing;
using EmbedIO.WebApi;
using GCLocalServerRewrite.common;
using GCLocalServerRewrite.models;
using Swan;
using Swan.Logging;
// ReSharper disable UnusedMember.Global
namespace GCLocalServerRewrite.controllers;
public class RankController : WebApiController
{
[Route(HttpVerbs.Get, "/ranking.php")]
public string Rank([QueryField("cmd_type")] int type)
{
HttpContext.Response.ContentType = MediaTypeNames.Application.Octet;
HttpContext.Response.ContentEncoding = Encoding.Default;
HttpContext.Response.KeepAlive = true;
if (!Enum.IsDefined(typeof(RankType), type))
{
throw new ArgumentOutOfRangeException(nameof(type));
}
var requestType = (RankType)type;
switch (requestType)
{
case RankType.GlobalRank:
case RankType.UnknownRank1:
case RankType.UnknownRank2:
case RankType.UnknownRank3:
$"Getting rank request, type is {requestType}".Info();
return ConstructResponse(RankTemp("score_rank"));
case RankType.PlayNumRank:
$"Getting rank request, type is {requestType}".Info();
return ConstructResponse(RankTemp("play_num_rank"));
case RankType.EventRank:
$"Getting rank request, type is {requestType}".Info();
return ConstructResponse(RankTemp("event_rank"));
default:
#pragma warning disable CA2208
throw new ArgumentOutOfRangeException(nameof(requestType));
#pragma warning restore CA2208
}
}
private static string ConstructResponse(string xml)
{
return "1\n" +
xml;
}
// TODO: Add proper rank support
private static string RankTemp(string rankType)
{
var rankStatus = new RankStatus
{
Rows = 0,
Status = 0
};
var sb = new StringBuilder();
using (var writer = new ChoXmlWriter<RankStatus>(sb))
{
writer.Configuration.OmitXmlDeclaration = false;
writer.Configuration.UseXmlSerialization = true;
writer.WithXPath(Configs.RANK_STATUS_XPATH);
writer.Write(rankStatus);
}
var document = new XmlDocument();
document.LoadXml(sb.ToString());
var root = document.DocumentElement;
if (root == null)
{
throw SelfCheck.Failure("Internal XML error!");
}
root.AppendChild(document.CreateElement(rankType));
var stringWriter = new StringWriter();
var xmlTextWriter = new XmlTextWriter(stringWriter);
document.WriteTo(xmlTextWriter);
return stringWriter.ToString();
}
private enum RankType
{
GlobalRank = 4119,
PlayNumRank = 6657,
EventRank = 6661,
UnknownRank1 = 6666,
UnknownRank2 = 6667,
UnknownRank3 = 4098
}
}

View File

@ -0,0 +1,21 @@
using System.Net.Mime;
using System.Text;
using EmbedIO;
using EmbedIO.Routing;
using EmbedIO.WebApi;
namespace GCLocalServerRewrite.controllers;
public class ResponeServiceController : WebApiController
{
[Route(HttpVerbs.Post, "/respone.php")]
// ReSharper disable once UnusedMember.Global
public string ResponeService()
{
HttpContext.Response.ContentType = MediaTypeNames.Text.Plain;
HttpContext.Response.ContentEncoding = Encoding.Default;
HttpContext.Response.KeepAlive = true;
return "1";
}
}

View File

@ -0,0 +1,138 @@
using System.Collections.Specialized;
using System.Net.Mime;
using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions;
using EmbedIO;
using EmbedIO.Routing;
using EmbedIO.WebApi;
using GCLocalServerRewrite.common;
using Swan.Logging;
// ReSharper disable UnusedMember.Global
namespace GCLocalServerRewrite.controllers;
public class ServerController : WebApiController
{
[Route(HttpVerbs.Get, "/certify.php")]
public string Certify([QueryData] NameValueCollection parameters)
{
HttpContext.Response.ContentType = MediaTypeNames.Text.Plain;
HttpContext.Response.ContentEncoding = Encoding.Default;
HttpContext.Response.KeepAlive = true;
var gid = parameters["gid"];
var mac = parameters["mac"];
var random = parameters["r"];
var hash = parameters["md"];
if (gid == null)
{
return QuitWithError(ErrorCode.ErrorNoGid);
}
if (mac == null)
{
return QuitWithError(ErrorCode.ErrorNoMac);
}
if (random == null)
{
return QuitWithError(ErrorCode.ErrorNoRandom);
}
if (hash == null)
{
return QuitWithError(ErrorCode.ErrorNoHash);
}
if (!MacValid(mac))
{
return QuitWithError(ErrorCode.ErrorInvalidMac);
}
if (!Md5Valid(hash))
{
return QuitWithError(ErrorCode.ErrorInvalidHash);
}
using var md5 = MD5.Create();
var ticket = string.Join(string.Empty,
md5.ComputeHash(Encoding.UTF8.GetBytes(gid)).Select(b => b.ToString("x2")));
var response = "host=card_id=7020392000147361\n" +
"no=1337\n" +
"name=123\n" +
"pref=nesys\n" +
"addr=nesys@home\n" +
"x-next-time=15\n" +
$"x-img=http://localhost{Configs.STATIC_BASE_ROUTE}/news.png\n" +
$"x-ranking=http://localhost{Configs.RANK_BASE_ROUTE}/ranking.php\n" +
$"ticket={ticket}";
return response;
}
[Route(HttpVerbs.Get, "/cursel.php")]
public string Cursel()
{
HttpContext.Response.ContentType = MediaTypeNames.Text.Plain;
HttpContext.Response.ContentEncoding = Encoding.Default;
HttpContext.Response.KeepAlive = true;
return "1\n";
}
[Route(HttpVerbs.Get, "/data.php")]
public string Data()
{
HttpContext.Response.ContentType = MediaTypeNames.Text.Plain;
HttpContext.Response.ContentEncoding = Encoding.Default;
HttpContext.Response.KeepAlive = true;
return "count=1\n" +
"nexttime=0\n";
}
[Route(HttpVerbs.Get, "/gameinfo.php")]
public string GameInfo()
{
HttpContext.Response.ContentType = MediaTypeNames.Text.Plain;
HttpContext.Response.ContentEncoding = Encoding.Default;
HttpContext.Response.KeepAlive = true;
return "0\n" +
"3\n" +
"301000,test1\n" +
"302000,test2\n" +
"303000,test3";
}
private static bool MacValid(string mac)
{
return Regex.IsMatch(mac, "^[a-fA-F0-9]{12}$");
}
private static bool Md5Valid(string md5)
{
return Regex.IsMatch(md5, "^[a-fA-F0-9]{32}$");
}
private static string QuitWithError(ErrorCode errorCode)
{
return $"error={(int)errorCode}";
}
private enum ErrorCode
{
ErrorNoGid,
ErrorNoMac,
ErrorNoRandom,
ErrorNoHash,
ErrorInvalidMac,
ErrorInvalidHash
}
}

View File

@ -0,0 +1,22 @@
using System.Net.Mime;
using System.Text;
using EmbedIO;
using EmbedIO.Routing;
using EmbedIO.WebApi;
namespace GCLocalServerRewrite.controllers;
public class UploadServiceController : WebApiController
{
[Route(HttpVerbs.Post, "/upload.php")]
// ReSharper disable once UnusedMember.Global
public string UploadService()
{
HttpContext.Response.ContentType = MediaTypeNames.Text.Plain;
HttpContext.Response.ContentEncoding = Encoding.Default;
HttpContext.Response.KeepAlive = true;
return "1\n" +
"OK";
}
}

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,34 @@
using System.Xml.Serialization;
namespace GCLocalServerRewrite.models;
public class Avatar : Record , IIdModel, ICardIdModel
{
[XmlElement(ElementName = "card_id")]
public long CardId { get; set; }
[XmlElement(ElementName = "avatar_id")]
public int AvatarId { get; set; }
[XmlElement("created")]
public string? Created { get; set; } = "1";
[XmlElement("modified")]
public string? Modified { get; set; } = "1";
[XmlElement("new_flag")]
public int NewFlag { get; set; } = 1;
[XmlElement("use_flag")]
public int UseFlag { get; set; } = 1;
public void SetId(int id)
{
AvatarId = id;
}
public void SetCardId(long cardId)
{
CardId = cardId;
}
}

View File

@ -0,0 +1,60 @@
using System.Xml.Serialization;
using ChoETL;
using SQLite.Net2;
namespace GCLocalServerRewrite.models;
[Table("card_main")]
public class Card : ICardIdModel
{
[PrimaryKey]
[Column("card_id")]
[ChoXmlElementRecordField(FieldName = "card_id")]
[XmlElement(ElementName = "card_id")]
public long? CardId { get; set; }
[Column("player_name")]
[ChoXmlElementRecordField(FieldName = "player_name")]
[XmlElement(ElementName = "player_name")]
public string? PlayerName { get; set; }
[Column("score_i1")]
[ChoXmlElementRecordField(FieldName = "score_i1")]
[XmlElement("score_i1")]
public int Score { get; set; }
[Column("fcol1")]
[ChoXmlElementRecordField(FieldName = "fcol1")]
[XmlElement("fcol1")]
public int Fcol1 { get; set; }
[Column("fcol2")]
[ChoXmlElementRecordField(FieldName = "fcol2")]
[XmlElement("fcol2")]
public int Fcol2 { get; set; }
[Column("fcol3")]
[ChoXmlElementRecordField(FieldName = "fcol3")]
[XmlElement("fcol3")]
public int Fcol3 { get; set; }
[Column("achieve_status")]
[ChoXmlElementRecordField(FieldName = "achieve_status")]
[XmlElement("achieve_status")]
public string? AchieveStatus { get; set; } = string.Empty;
[Column("created")]
[ChoXmlElementRecordField(FieldName = "created")]
[XmlElement("created")]
public string Created { get; set; } = "1";
[Column("updated")]
[ChoXmlElementRecordField(FieldName = "updated")]
[XmlElement("updated")]
public string Updated { get; set; } = "1";
public void SetCardId(long cardId)
{
CardId = cardId;
}
}

View File

@ -0,0 +1,30 @@
using System.Xml.Serialization;
using ChoETL;
using SQLite.Net2;
namespace GCLocalServerRewrite.models;
[Table("card_bdata")]
public class CardBData : ICardIdModel
{
[PrimaryKey]
[Column("card_id")]
[ChoXmlElementRecordField(FieldName = "card_id")]
[XmlElement(ElementName = "card_id")]
public long? CardId { get; set; }
[Column("bdata")]
[ChoXmlElementRecordField(FieldName = "bdata")]
[XmlElement(ElementName = "bdata")]
public string BData { get; set; } = string.Empty;
[Column("bdata_size")]
[ChoXmlElementRecordField(FieldName = "bdata_size")]
[XmlElement(ElementName = "bdata_size")]
public int BDataSize { get; set; }
public void SetCardId(long cardId)
{
CardId = cardId;
}
}

View File

@ -0,0 +1,98 @@
using System.Xml.Serialization;
using ChoETL;
using SQLite.Net2;
namespace GCLocalServerRewrite.models;
[Table("card_detail")]
public class CardDetail : Record, ICardIdModel
{
[PrimaryKey]
[Column("card_id")]
[ChoXmlElementRecordField(FieldName = "card_id")]
[XmlElement(ElementName = "card_id")]
public long CardId { get; set; }
[PrimaryKey]
[Column("pcol1")]
[ChoXmlElementRecordField(FieldName = "pcol1")]
[XmlElement(ElementName = "pcol1")]
public int Pcol1 { get; set; }
[PrimaryKey]
[Column("pcol2")]
[ChoXmlElementRecordField(FieldName = "pcol2")]
[XmlElement(ElementName = "pcol2")]
public int Pcol2 { get; set; }
[PrimaryKey]
[Column("pcol3")]
[ChoXmlElementRecordField(FieldName = "pcol3")]
[XmlElement(ElementName = "pcol3")]
public int Pcol3 { get; set; }
[Column("score_i1")]
[ChoXmlElementRecordField(FieldName = "score_i1")]
[XmlElement(ElementName = "score_i1")]
public long ScoreI1 { get; set; }
[Column("score_ui1")]
[ChoXmlElementRecordField(FieldName = "score_ui1")]
[XmlElement(ElementName = "score_ui1")]
public long ScoreUi1 { get; set; }
[Column("score_ui2")]
[ChoXmlElementRecordField(FieldName = "score_ui2")]
[XmlElement(ElementName = "score_ui2")]
public long ScoreUi2 { get; set; }
[Column("score_ui3")]
[ChoXmlElementRecordField(FieldName = "score_ui3")]
[XmlElement(ElementName = "score_ui3")]
public long ScoreUi3 { get; set; }
[Column("score_ui4")]
[ChoXmlElementRecordField(FieldName = "score_ui4")]
[XmlElement(ElementName = "score_ui4")]
public long ScoreUi4 { get; set; }
[Column("score_ui5")]
[ChoXmlElementRecordField(FieldName = "score_ui5")]
[XmlElement(ElementName = "score_ui5")]
public long ScoreUi5 { get; set; }
[Column("score_ui6")]
[ChoXmlElementRecordField(FieldName = "score_ui6")]
[XmlElement(ElementName = "score_ui6")]
public long ScoreUi6 { get; set; }
[Column("score_bi1")]
[ChoXmlElementRecordField(FieldName = "score_bi1")]
[XmlElement(ElementName = "score_bi1")]
public long ScoreBi1 { get; set; }
[Column("last_play_tenpo_id")]
[ChoXmlElementRecordField(FieldName = "last_play_tenpo_id")]
[XmlElement(ElementName = "last_play_tenpo_id")]
public string LastPlayShopId { get; set; } = "1337";
[Column("fcol1")]
[ChoXmlElementRecordField(FieldName = "fcol1")]
[XmlElement("fcol1")]
public int Fcol1 { get; set; }
[Column("fcol2")]
[ChoXmlElementRecordField(FieldName = "fcol2")]
[XmlElement("fcol2")]
public int Fcol2 { get; set; }
[Column("fcol3")]
[ChoXmlElementRecordField(FieldName = "fcol3")]
[XmlElement("fcol3")]
public int Fcol3 { get; set; }
public void SetCardId(long cardId)
{
CardId = cardId;
}
}

View File

@ -0,0 +1,20 @@
using System.Xml.Serialization;
using ChoETL;
namespace GCLocalServerRewrite.models;
[ChoXmlRecordObject(XPath = "/root/data")]
public class CardDetailReadData
{
[XmlElement(ElementName = "pcol1")]
[ChoXmlElementRecordField(FieldName = "pcol1")]
public int Pcol1 { get; set; }
[XmlElement(ElementName = "pcol2")]
[ChoXmlElementRecordField(FieldName = "pcol2")]
public int Pcol2 { get; set; }
[XmlElement(ElementName = "pcol3")]
[ChoXmlElementRecordField(FieldName = "pcol3")]
public int Pcol3 { get; set; }
}

View File

@ -0,0 +1,24 @@
using System.Xml.Serialization;
namespace GCLocalServerRewrite.models;
public class Coin
{
[XmlElement(ElementName = "card_id")]
public long CardId { get; set; }
[XmlElement(ElementName = "current")]
public int CurrentCoins { get; set; }
[XmlElement(ElementName = "total")]
public int TotalCoins { get; set; }
[XmlElement("monthly")]
public int MonthlyCoins { get; set; }
[XmlElement("created")]
public string? Created { get; set; } = "1";
[XmlElement("modified")]
public string? Modified { get; set; } = "1";
}

View File

@ -0,0 +1,6 @@
namespace GCLocalServerRewrite.models;
public interface ICardIdModel
{
public void SetCardId(long cardId);
}

View File

@ -0,0 +1,6 @@
namespace GCLocalServerRewrite.models;
public interface IIdModel
{
public void SetId(int id);
}

View File

@ -0,0 +1,37 @@
using System.Xml.Serialization;
namespace GCLocalServerRewrite.models;
public class Item : Record, IIdModel, ICardIdModel
{
[XmlElement(ElementName = "card_id")]
public long CardId { get; set; }
[XmlElement(ElementName = "item_id")]
public int ItemId { get; set; }
[XmlElement(ElementName = "item_num")]
public int ItemNum { get; set; } = 90;
[XmlElement("created")]
public string? Created { get; set; } = "1";
[XmlElement("modified")]
public string? Modified { get; set; } = "1";
[XmlElement("new_flag")]
public int NewFlag { get; set; } = 1;
[XmlElement("use_flag")]
public int UseFlag { get; set; } = 1;
public void SetId(int id)
{
ItemId = id;
}
public void SetCardId(long cardId)
{
CardId = cardId;
}
}

View File

@ -0,0 +1,37 @@
using System.Xml.Serialization;
using SQLite.Net2;
namespace GCLocalServerRewrite.models;
[Table("music_unlock")]
public class Music : Record
{
[PrimaryKey]
[Column("music_id")]
[XmlElement("music_id")]
public int MusicId { get; set; }
[Column("title")]
[XmlElement(ElementName = "title", IsNullable = true)]
public string? Title { get; set; }
[Column("artist")]
[XmlElement(ElementName = "artist", IsNullable = true)]
public string? Artist { get; set; }
[Column("release_date")]
[XmlElement(ElementName = "release_date", IsNullable = true)]
public string? ReleaseDate { get; set; }
[Column("end_date")]
[XmlElement(ElementName = "end_date", IsNullable = true)]
public string? EndDate { get; set; }
[Column("new_flag")]
[XmlElement("new_flag")]
public int NewFlag { get; set; }
[Column("use_flag")]
[XmlElement("use_flag")]
public int UseFlag { get; set; }
}

View File

@ -0,0 +1,37 @@
using System.Xml.Serialization;
using SQLite.Net2;
namespace GCLocalServerRewrite.models;
[Table("music_aou")]
public class MusicAou : Record
{
[PrimaryKey]
[Column("music_id")]
[XmlElement("music_id")]
public int MusicId { get; set; }
[Column("title")]
[XmlElement(ElementName = "title", IsNullable = true)]
public string? Title { get; set; }
[Column("artist")]
[XmlElement(ElementName = "artist", IsNullable = true)]
public string? Artist { get; set; }
[Column("release_date")]
[XmlElement(ElementName = "release_date", IsNullable = true)]
public string? ReleaseDate { get; set; }
[Column("end_date")]
[XmlElement(ElementName = "end_date", IsNullable = true)]
public string? EndDate { get; set; }
[Column("new_flag")]
[XmlElement("new_flag")]
public int NewFlag { get; set; }
[Column("use_flag")]
[XmlElement("use_flag")]
public int UseFlag { get; set; }
}

View File

@ -0,0 +1,17 @@
using System.Xml.Serialization;
using SQLite.Net2;
namespace GCLocalServerRewrite.models;
[Table("music_extra")]
public class MusicExtra : Record
{
[PrimaryKey]
[Column("music_id")]
[XmlElement("music_id")]
public int MusicId { get; set; }
[Column("use_flag")]
[XmlElement("use_flag")]
public int UseFlag { get; set; }
}

View File

@ -0,0 +1,34 @@
using System.Xml.Serialization;
namespace GCLocalServerRewrite.models;
public class Navigator : Record, IIdModel, ICardIdModel
{
[XmlElement(ElementName = "card_id")]
public long CardId { get; set; }
[XmlElement(ElementName = "navigator_id")]
public int NavigatorId { get; set; }
[XmlElement("created")]
public string? Created { get; set; } = "1";
[XmlElement("modified")]
public string? Modified { get; set; } = "1";
[XmlElement("new_flag")]
public int NewFlag { get; set; } = 1;
[XmlElement("use_flag")]
public int UseFlag { get; set; } = 1;
public void SetId(int id)
{
NavigatorId = id;
}
public void SetCardId(long cardId)
{
CardId = cardId;
}
}

View File

@ -0,0 +1,21 @@
using System.Xml.Serialization;
namespace GCLocalServerRewrite.models;
public class RankStatus
{
[XmlElement("table_name")]
public string? TableName { get; set; }
[XmlElement("start_date")]
public string StartDate { get; set; } = "2017-05-30";
[XmlElement("end_date")]
public string EndDate { get; set; } = "2018-05-30";
[XmlElement("status")]
public int Status { get; set; }
[XmlElement("rows")]
public int Rows { get; set; }
}

View File

@ -0,0 +1,10 @@
using System.Xml.Serialization;
using ChoETL;
namespace GCLocalServerRewrite.models;
public class Record
{
[XmlAttribute(AttributeName = "id")]
public int RecordId { get; set; }
}

View File

@ -0,0 +1,21 @@
using System.Xml.Serialization;
namespace GCLocalServerRewrite.models;
public class Session
{
[XmlElement(ElementName = "card_id")]
public long CardId { get; set; }
[XmlElement(ElementName = "mac_addr")]
public string? Mac { get; set; }
[XmlElement(ElementName = "session_id")]
public string? SessionId { get; set; }
[XmlElement(ElementName = "expires")]
public int Expires { get; set; }
[XmlElement(ElementName = "player_id")]
public int PlayerId { get; set; }
}

View File

@ -0,0 +1,34 @@
using System.Xml.Serialization;
namespace GCLocalServerRewrite.models;
public class Skin : Record, IIdModel, ICardIdModel
{
[XmlElement(ElementName = "card_id")]
public long CardId { get; set; }
[XmlElement(ElementName = "skin_id")]
public int SkinId { get; set; }
[XmlElement("created")]
public string? Created { get; set; } = "1";
[XmlElement("modified")]
public string? Modified { get; set; } = "1";
[XmlElement("new_flag")]
public int NewFlag { get; set; } = 1;
[XmlElement("use_flag")]
public int UseFlag { get; set; } = 1;
public void SetId(int id)
{
SkinId = id;
}
public void SetCardId(long cardId)
{
CardId = cardId;
}
}

View File

@ -0,0 +1,34 @@
using System.Xml.Serialization;
namespace GCLocalServerRewrite.models;
public class SoundEffect : Record, IIdModel, ICardIdModel
{
[XmlElement(ElementName = "card_id")]
public long CardId { get; set; }
[XmlElement(ElementName = "sound_effect_id")]
public int SeId { get; set; }
[XmlElement("created")]
public string? Created { get; set; } = "1";
[XmlElement("modified")]
public string? Modified { get; set; } = "1";
[XmlElement("new_flag")]
public int NewFlag { get; set; } = 1;
[XmlElement("use_flag")]
public int UseFlag { get; set; } = 1;
public void SetId(int id)
{
SeId = id;
}
public void SetCardId(long cardId)
{
CardId = cardId;
}
}

View File

@ -0,0 +1,34 @@
using System.Xml.Serialization;
namespace GCLocalServerRewrite.models;
public class Title : Record, IIdModel, ICardIdModel
{
[XmlElement(ElementName = "card_id")]
public long CardId { get; set; }
[XmlElement(ElementName = "title_id")]
public int TitleId { get; set; }
[XmlElement("created")]
public string? Created { get; set; } = "1";
[XmlElement("modified")]
public string? Modified { get; set; } = "1";
[XmlElement("new_flag")]
public int NewFlag { get; set; } = 1;
[XmlElement("use_flag")]
public int UseFlag { get; set; } = 1;
public void SetId(int id)
{
TitleId = id;
}
public void SetCardId(long cardId)
{
CardId = cardId;
}
}

View File

@ -0,0 +1,12 @@
using System.Xml.Serialization;
namespace GCLocalServerRewrite.models;
public class TotalTrophy
{
[XmlElement(ElementName = "card_id")]
public long CardId { get; set; }
[XmlElement(ElementName = "total_trophy_num")]
public int TrophyNum { get; set; }
}

View File

@ -0,0 +1,33 @@
using System.Xml.Serialization;
namespace GCLocalServerRewrite.models;
public class UnlockKeynum : Record
{
[XmlElement(ElementName = "card_id")]
public long CardId { get; set; }
[XmlElement(ElementName = "reward_id")]
public int RewardId { get; set; }
[XmlElement(ElementName = "key_num")]
public int KeyNum { get; set; }
[XmlElement(ElementName = "reward_count")]
public int RewardCount { get; set; }
[XmlElement("expired_flag")]
public int ExpiredFlag { get; set; }
[XmlElement("use_flag")]
public int UseFlag { get; set; } = 1;
[XmlElement("cash_flag")]
public int CashFlag { get; set; }
[XmlElement("created")]
public string? Created { get; set; } = "1";
[XmlElement("modified")]
public string? Modified { get; set; } = "1";
}

View File

@ -0,0 +1,57 @@
using System.Xml.Serialization;
namespace GCLocalServerRewrite.models;
public class UnlockReward : Record
{
[XmlElement(ElementName = "card_id")]
public long CardId { get; set; }
[XmlElement(ElementName = "reward_id")]
public int RewardId { get; set; }
[XmlElement(ElementName = "reward_type")]
public int RewardType { get; set; }
[XmlElement(ElementName = "open_date")]
public string? OpenDate { get; set; } = "2021-05-30";
[XmlElement(ElementName = "close_date")]
public string? CloseDate { get; set; } = "2030-05-30";
[XmlElement(ElementName = "open_time")]
public string? OpenTime { get; set; } = "00:00:01";
[XmlElement(ElementName = "close_time")]
public string? CloseTime { get; set; } = "23:59:59";
[XmlElement(ElementName = "target_id")]
public int TargetId { get; set; }
[XmlElement(ElementName = "target_num")]
public int TargetNum { get; set; }
[XmlElement(ElementName = "key_num")]
public int KeyNum { get; set; }
[XmlElement("display_flag")]
public int DisplayFlag { get; set; } = 1;
[XmlElement("use_flag")]
public int UseFlag { get; set; } = 1;
[XmlElement("limited_flag")]
public int LimitedFlag { get; set; }
[XmlElement("open_unixtime")]
public long OpenUnixTime { get; set; } = 1622304001;
[XmlElement("close_unixtime")]
public long CloseUnixTime { get; set; } = 1906387199;
[XmlElement("created")]
public string? Created { get; set; } = "1";
[XmlElement("modified")]
public string? Modified { get; set; } = "1";
}

View File

@ -0,0 +1,65 @@
using EmbedIO;
using EmbedIO.Actions;
using EmbedIO.Files;
using EmbedIO.WebApi;
using GCLocalServerRewrite.backports;
using GCLocalServerRewrite.common;
using GCLocalServerRewrite.controllers;
using GCLocalServerRewrite.models;
using Swan.Logging;
namespace GCLocalServerRewrite.server;
public class Server
{
public static WebServer CreateWebServer(string[] urlPrefixes)
{
InitializeDatabase();
var cert = CertificateHelper.InitializeCertificate();
var server = new WebServer(webServerOptions => webServerOptions
.WithUrlPrefixes(urlPrefixes)
.WithCertificate(cert)
.WithMode(HttpListenerMode.EmbedIO))
.WithLocalSessionManager()
.WithCors(
"http://unosquare.github.io,http://run.plnkr.co",
"content-type, accept",
"post")
.WithWebApi(Configs.CARD_SERVICE_BASE_ROUTE, CustomResponseSerializer.None(true),
module => module.WithController<CardServiceController>())
.WithWebApi(Configs.UPLOAD_SERVICE_BASE_ROUTE, CustomResponseSerializer.None(true),
module => module.WithController<UploadServiceController>())
.WithWebApi(Configs.RESPONE_SERVICE_BASE_ROUTE, CustomResponseSerializer.None(true),
module => module.WithController<ResponeServiceController>())
.WithWebApi(Configs.INCOM_SERVICE_BASE_ROUTE, CustomResponseSerializer.None(true),
module => module.WithController<IncomServiceController>())
.WithWebApi(Configs.ALIVE_BASE_ROUTE, CustomResponseSerializer.None(true),
module => module.WithController<AliveController>())
.WithWebApi(Configs.SERVER_BASE_ROUTE, CustomResponseSerializer.None(true),
module => module.WithController<ServerController>())
.WithWebApi(Configs.RANK_BASE_ROUTE, CustomResponseSerializer.None(true),
module => module.WithController<RankController>())
.WithStaticFolder(Configs.STATIC_BASE_ROUTE, PathHelper.HtmlRootPath, true, m => m
.WithContentCaching(Configs.USE_FILE_CACHE))
// Add static files after other modules to avoid conflicts
.WithStaticFolder("/", PathHelper.HtmlRootPath, true, m => m
.WithContentCaching(Configs.USE_FILE_CACHE))
.WithModule(new ActionModule("/", HttpVerbs.Any,
ctx => ctx.SendDataAsync(new { Message = "Error" })));
// Listen for state changes.
server.StateChanged += (_, e) => $"WebServer New State - {e.NewState}".Info();
return server;
}
private static void InitializeDatabase()
{
DatabaseHelper.InitializeLocalDatabase(Configs.CARD_DB_NAME,
typeof(Card), typeof(CardBData), typeof(CardDetail));
DatabaseHelper.InitializeLocalDatabase(Configs.MUSIC_DB_NAME,
typeof(Music), typeof(MusicAou), typeof(MusicExtra));
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

View File

@ -0,0 +1,10 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
Hello world!
</body>
</html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 818 B