Skip to content
Merged
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
39 changes: 25 additions & 14 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
cmake_minimum_required(VERSION 3.15)
project(xiloader CXX)

set_property(GLOBAL PROPERTY CXX_STANDARD 17)
set_property(GLOBAL PROPERTY CXX_STANDARD_REQUIRED ON)
set_property(GLOBAL PROPERTY CXX_EXTENSIONS ON)
set_property(GLOBAL PROPERTY LINKER_LANGUAGE CXX)
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS ON)
set(LINKER_LANGUAGE CXX)
set(USE_FOLDERS ON)

set(CMAKE_POSITION_INDEPENDENT_CODE ON)

Expand All @@ -17,9 +17,13 @@ elseif(CMAKE_SIZEOF_VOID_P EQUAL 4)
endif()

include(cmake/CPM.cmake)
include(cmake/detours.cmake)

include(cmake/argparse.cmake)
include(cmake/detours.cmake)
include(cmake/ftxui.cmake)
include(cmake/json.cmake)
include(cmake/mbedtls.cmake)
include(cmake/qr-code-generator.cmake)

configure_file(
src/xiloader.rc.in
Expand All @@ -28,6 +32,7 @@ configure_file(

# xiloader
add_executable(xiloader
src/command_handler.h
src/console.cpp
src/console.h
src/defines.h
Expand All @@ -36,6 +41,7 @@ add_executable(xiloader
src/functions.cpp
src/functions.h
src/main.cpp
src/menus.h
src/network.cpp
src/network.h
src/polcore.h
Expand All @@ -49,14 +55,19 @@ target_include_directories(xiloader PUBLIC ${PROJECT_SOURCE_DIR}/xiloader)

target_link_libraries(xiloader PUBLIC
detours
argparse
crypt32
psapi
ws2_32
iphlpapi
MbedTLS::mbedtls
MbedTLS::mbedcrypto
MbedTLS::mbedx509)
argparse
crypt32
psapi
ws2_32
iphlpapi
MbedTLS::mbedtls
MbedTLS::mbedcrypto
MbedTLS::mbedx509
nlohmann_json::nlohmann_json
ftxui::screen
ftxui::dom
ftxui::component
qr-code-generator)

message(STATUS "CMAKE_VERSION: ${CMAKE_VERSION}")
message(STATUS "CMAKE_BUILD_TYPE: ${CMAKE_BUILD_TYPE}")
Expand Down
2 changes: 1 addition & 1 deletion cmake/CPM.cmake
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
set(CPM_DOWNLOAD_VERSION 0.34.1)
set(CPM_DOWNLOAD_VERSION 0.42.0)

if(CPM_SOURCE_CACHE)
# Expand relative path. This is important if the provided path contains a tilde (~)
Expand Down
5 changes: 5 additions & 0 deletions cmake/ftxui.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
CPMAddPackage(
NAME ftxui
GITHUB_REPOSITORY arthursonzogni/ftxui
GIT_TAG v6.1.9
)
8 changes: 8 additions & 0 deletions cmake/json.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
CPMAddPackage(
NAME nlohmann_json
GITHUB_REPOSITORY nlohmann/json
GIT_TAG v3.12.0
OPTIONS
"JSON_ImplicitConversions OFF" #Recommended by the author
"JSON_BuildTests OFF"
)
2 changes: 1 addition & 1 deletion cmake/mbedtls.cmake
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
CPMAddPackage(
NAME mbedtls
GITHUB_REPOSITORY Mbed-TLS/mbedtls
GIT_TAG mbedtls-3.6.4
GIT_TAG mbedtls-3.6.5
OPTIONS
"ENABLE_PROGRAMS OFF"
"ENABLE_TESTING OFF"
Expand Down
19 changes: 19 additions & 0 deletions cmake/qr-code-generator.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
CPMAddPackage(
NAME qr-code-generator
GITHUB_REPOSITORY nayuki/QR-Code-generator
GIT_TAG 720f62bddb7226106071d4728c292cb1df519ceb
LANGUAGES CXX

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Even if you're not going to build this, or it doesn't come with a cmake file, you should still mark this as DOWNLOAD_ONLY

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added

DOWNLOAD_ONLY
)

if(qr-code-generator_ADDED)
add_library(qr-code-generator
STATIC
${qr-code-generator_SOURCE_DIR}/cpp/qrcodegen.cpp
${qr-code-generator_SOURCE_DIR}/cpp/qrcodegen.hpp
)
target_include_directories(qr-code-generator
SYSTEM INTERFACE
${qr-code-generator_SOURCE_DIR}/cpp
)
endif()
203 changes: 203 additions & 0 deletions src/command_handler.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,203 @@
/*
===========================================================================

Copyright (c) 2025 LandSandBoat Dev Teams

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program 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 General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program. If not, see http://www.gnu.org/licenses/

===========================================================================
*/

#pragma once

/* Externals */
namespace globals
{
extern std::string g_ServerAddress;
extern std::string g_Username;
extern std::string g_Password;
extern std::string g_OtpCode;
extern char g_SessionHash[16];
extern std::string g_Email;
extern std::array<uint8_t, 3> g_VersionNumber;
extern uint16_t g_ServerPort;
extern uint16_t g_LoginDataPort;
extern uint16_t g_LoginViewPort;
extern uint16_t g_LoginAuthPort;
extern char* g_CharacterList;
extern bool g_IsRunning;
extern bool g_FirstLogin;
} // namespace globals

#include "defines.h"
#include "helpers.h"
#include "network.h"

#include <nlohmann/json.hpp>
#include <qrcodegen.hpp>

using json = nlohmann::json;

bool handleLoginCommand(int8_t command, json& login_reply_json, uint32_t& accountId, SOCKET& sock)
{
/* Handle the obtained result.. */
switch (command)
{
case 0x0001: // Success (Login)
{
std::optional maybeAccountId = jsonGet<uint32_t>(login_reply_json, "account_id");
if (maybeAccountId.has_value())
{
accountId = maybeAccountId.value();
}
else
{
xiloader::console::output(xiloader::color::error, "xi_connect failed to reply with an account ID");
break;
}

auto maybeSessionHash = jsonGet<char, 16>(login_reply_json, "session_hash");

if (maybeSessionHash.has_value())
{
std::memcpy(&globals::g_SessionHash, maybeSessionHash.value().data(), maybeSessionHash.value().size());
}
else
{
xiloader::console::output(xiloader::color::error, "xi_connect failed to reply with a valid session hash");
break;
}

xiloader::console::output(xiloader::color::success, "Successfully logged in as %s!", globals::g_Username.c_str());

shutdown(sock, SD_BOTH);

return true;
}
case 0x0002: // Error (Login)
{
xiloader::console::output(xiloader::color::error, "Failed to login. Invalid username or password.");

return false;
}
case 0x0003: // Success (Create Account)
{
xiloader::console::output(xiloader::color::success, "Account successfully created!");

return false;
}
case 0x0004: // Error (Create Account)
{
xiloader::console::output(xiloader::color::error, "Failed to create the new account. Username already taken.");

return false;
}
case 0x0006: // Success (Changed Password)
{
xiloader::console::output(xiloader::color::success, "Password updated successfully!");
globals::g_Password.clear();

return false;
}
case 0x0007: // Error (Changed Password)
{
xiloader::console::output(xiloader::color::error, "Failed to change password.");
globals::g_Password.clear();

return false;
}

// Commands 0x0008 through 0x0008 are currently unused

case 0x000A:
{
xiloader::console::output(xiloader::color::error, "Failed to login. Account already logged in.");

return false;
}
case 0x000B:
{
xiloader::console::output(xiloader::color::error, "Failed to login. Expected xiloader version mismatch; check with your provider.");

return false;
}

// LOGIN_SUCCESS_CREATE_TOTP
case 0x0010:
{
std::string uri = "";
std::optional<std::string> maybeURI = jsonGet<std::string>(login_reply_json, "TOTP_uri");
if (maybeURI.has_value())
{
uri = maybeURI.value();
}
else
{
xiloader::console::output(xiloader::color::error, "xi_connect failed to reply with a valid TOTP_uri");
return false;
}

qrcodegen::QrCode qrCode = qrcodegen::QrCode::encodeText(uri.c_str(), qrcodegen::QrCode::Ecc::LOW);

std::string svgString = qrToSvgString(qrCode, 4);
std::string svgFilePath = writeSvgToDisk("temp.svg", svgString);

xiloader::console::output(xiloader::color::info, "Open your authenticator application on your phone and prepare to scan the QR code.");

bool display = menus::okCancelDialog("Open QR code in my default browser");
if (display)
{
ShellExecuteA(nullptr, "open", svgFilePath.c_str(), nullptr, nullptr, SW_SHOWNORMAL);
xiloader::console::output(xiloader::color::info, "Once saved please use the \"Validate 2FA OTP\" option to verify the OTP.");
}

return false;
}

// LOGIN_SUCCESS_VERIFY_TOTP
case 0x0011:
{
xiloader::console::output(xiloader::color::info, "Your TOTP has been registered with the server");
xiloader::console::output(xiloader::color::info, "You are now required to use an OTP to login.");

std::optional<std::string> maybeRecoveryCode = jsonGet<std::string>(login_reply_json, "recovery_code");
if (maybeRecoveryCode.has_value())
{
xiloader::console::output(xiloader::color::info, "Your recovery code is '%s'. Please write this down!", maybeRecoveryCode.value().c_str());
xiloader::console::output(xiloader::color::info, "Tip: Try using shift + leftclick to select the text if it doesn't work.", maybeRecoveryCode.value().c_str());
xiloader::console::output(xiloader::color::info, "You may remove you may remove your TOTP with this recovery code.");
}

std::string svgFilePath = getTemporaryPath() + "temp.svg";
if (std::filesystem::exists(svgFilePath))
{
std::filesystem::remove(svgFilePath);
}

return false;
}

// LOGIN_SUCCESS_REMOVE_TOTP
case 0x0012:
{
xiloader::console::output(xiloader::color::info, "Your TOTP has been removed.");
xiloader::console::output(xiloader::color::info, "You no longer need to use an OTP code to login.");

return false;
}

}

return false;
}
24 changes: 16 additions & 8 deletions src/console.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,7 @@ This file is part of DarkStar-server source code.
===========================================================================
*/

#ifndef __XILOADER_CONSOLE_H_INCLUDED__
#define __XILOADER_CONSOLE_H_INCLUDED__

#if defined (_MSC_VER) && (_MSC_VER >= 1020)
#pragma once
#endif

#include <windows.h>
#include <iostream>
Expand Down Expand Up @@ -94,7 +89,7 @@ namespace xiloader

/**
* @brief Prints a text fragment with the specified color to the console.
*
*
* @param c The color to print the fragment with.
* @param message The fragment to print.
*/
Expand Down Expand Up @@ -152,6 +147,21 @@ namespace xiloader
std::cout << std::endl;
}

static void printMultiLine(std::string msg, const std::string delimiter, const xiloader::color color)
{
auto pos = msg.find(delimiter);

while (pos != -1)
{
xiloader::console::output(color, "%s", msg.substr(0, pos).c_str());
msg.erase(0, pos + delimiter.length());

pos = msg.find(delimiter);
}

xiloader::console::output(color, "%s", msg.c_str());
}

/**
* @brief Hides the console window.
*/
Expand All @@ -164,5 +174,3 @@ namespace xiloader
};

}; // namespace xiloader

#endif // __XILOADER_CONSOLE_H_INCLUDED__
Loading