mirror of
https://github.com/4jcraft/4jcraft.git
synced 2026-04-29 20:23:38 +00:00
fix UIStructsmerge Platform/Common/Leaderboards
This commit is contained in:
parent
b9d18bf641
commit
4eda6e89fd
|
|
@ -0,0 +1,97 @@
|
|||
#include "../../stdafx.h"
|
||||
#include "LeaderboardInterface.h"
|
||||
|
||||
LeaderboardInterface::LeaderboardInterface(LeaderboardManager* man) {
|
||||
m_manager = man;
|
||||
m_pending = false;
|
||||
|
||||
m_filter = (LeaderboardManager::EFilterMode)-1;
|
||||
m_callback = NULL;
|
||||
m_difficulty = 0;
|
||||
m_type = LeaderboardManager::eStatsType_UNDEFINED;
|
||||
m_startIndex = 0;
|
||||
m_readCount = 0;
|
||||
|
||||
m_manager->OpenSession();
|
||||
}
|
||||
|
||||
LeaderboardInterface::~LeaderboardInterface() {
|
||||
m_manager->CancelOperation();
|
||||
m_manager->CloseSession();
|
||||
}
|
||||
|
||||
void LeaderboardInterface::ReadStats_Friends(
|
||||
LeaderboardReadListener* callback, int difficulty,
|
||||
LeaderboardManager::EStatsType type, PlayerUID myUID,
|
||||
unsigned int startIndex, unsigned int readCount) {
|
||||
m_filter = LeaderboardManager::eFM_Friends;
|
||||
m_pending = true;
|
||||
|
||||
m_callback = callback;
|
||||
m_difficulty = difficulty;
|
||||
m_type = type;
|
||||
m_myUID = myUID;
|
||||
m_startIndex = startIndex;
|
||||
m_readCount = readCount;
|
||||
|
||||
tick();
|
||||
}
|
||||
|
||||
void LeaderboardInterface::ReadStats_MyScore(
|
||||
LeaderboardReadListener* callback, int difficulty,
|
||||
LeaderboardManager::EStatsType type, PlayerUID myUID,
|
||||
unsigned int readCount) {
|
||||
m_filter = LeaderboardManager::eFM_MyScore;
|
||||
m_pending = true;
|
||||
|
||||
m_callback = callback;
|
||||
m_difficulty = difficulty;
|
||||
m_type = type;
|
||||
m_myUID = myUID;
|
||||
m_readCount = readCount;
|
||||
|
||||
tick();
|
||||
}
|
||||
|
||||
void LeaderboardInterface::ReadStats_TopRank(
|
||||
LeaderboardReadListener* callback, int difficulty,
|
||||
LeaderboardManager::EStatsType type, unsigned int startIndex,
|
||||
unsigned int readCount) {
|
||||
m_filter = LeaderboardManager::eFM_TopRank;
|
||||
m_pending = true;
|
||||
|
||||
m_callback = callback;
|
||||
m_difficulty = difficulty;
|
||||
m_type = type;
|
||||
m_startIndex = startIndex;
|
||||
m_readCount = readCount;
|
||||
|
||||
tick();
|
||||
}
|
||||
|
||||
void LeaderboardInterface::CancelOperation() {
|
||||
m_manager->CancelOperation();
|
||||
m_pending = false;
|
||||
}
|
||||
|
||||
void LeaderboardInterface::tick() {
|
||||
if (m_pending) m_pending = !callManager();
|
||||
}
|
||||
|
||||
bool LeaderboardInterface::callManager() {
|
||||
switch (m_filter) {
|
||||
case LeaderboardManager::eFM_Friends:
|
||||
return m_manager->ReadStats_Friends(m_callback, m_difficulty,
|
||||
m_type, m_myUID, m_startIndex,
|
||||
m_readCount);
|
||||
case LeaderboardManager::eFM_MyScore:
|
||||
return m_manager->ReadStats_MyScore(m_callback, m_difficulty,
|
||||
m_type, m_myUID, m_readCount);
|
||||
case LeaderboardManager::eFM_TopRank:
|
||||
return m_manager->ReadStats_TopRank(
|
||||
m_callback, m_difficulty, m_type, m_startIndex, m_readCount);
|
||||
default:
|
||||
assert(false);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
#pragma once
|
||||
|
||||
#include "LeaderboardManager.h"
|
||||
|
||||
// 4J-JEV: Simple interface for handling ReadStat failures.
|
||||
class LeaderboardInterface {
|
||||
private:
|
||||
LeaderboardManager* m_manager;
|
||||
bool m_pending;
|
||||
|
||||
// Arguments.
|
||||
LeaderboardManager::EFilterMode m_filter;
|
||||
LeaderboardReadListener* m_callback;
|
||||
int m_difficulty;
|
||||
LeaderboardManager::EStatsType m_type;
|
||||
PlayerUID m_myUID;
|
||||
unsigned int m_startIndex;
|
||||
unsigned int m_readCount;
|
||||
|
||||
public:
|
||||
LeaderboardInterface(LeaderboardManager* man);
|
||||
~LeaderboardInterface();
|
||||
|
||||
void ReadStats_Friends(LeaderboardReadListener* callback, int difficulty,
|
||||
LeaderboardManager::EStatsType type, PlayerUID myUID,
|
||||
unsigned int startIndex, unsigned int readCount);
|
||||
void ReadStats_MyScore(LeaderboardReadListener* callback, int difficulty,
|
||||
LeaderboardManager::EStatsType type, PlayerUID myUID,
|
||||
unsigned int readCount);
|
||||
void ReadStats_TopRank(LeaderboardReadListener* callback, int difficulty,
|
||||
LeaderboardManager::EStatsType type,
|
||||
unsigned int startIndex, unsigned int readCount);
|
||||
|
||||
void CancelOperation();
|
||||
|
||||
void tick();
|
||||
|
||||
private:
|
||||
bool callManager();
|
||||
};
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -0,0 +1,145 @@
|
|||
#pragma once
|
||||
|
||||
#include "Common/Leaderboards/LeaderboardManager.h"
|
||||
|
||||
#ifdef __PS3__
|
||||
typedef CellRtcTick SonyRtcTick;
|
||||
#else
|
||||
typedef SceRtcTick SonyRtcTick;
|
||||
#endif
|
||||
|
||||
class SonyLeaderboardManager : public LeaderboardManager {
|
||||
protected:
|
||||
enum EStatsState {
|
||||
eStatsState_Idle,
|
||||
eStatsState_Getting,
|
||||
eStatsState_Failed,
|
||||
eStatsState_Ready,
|
||||
eStatsState_Canceled,
|
||||
eStatsState_Max
|
||||
};
|
||||
|
||||
public:
|
||||
SonyLeaderboardManager();
|
||||
virtual ~SonyLeaderboardManager();
|
||||
|
||||
protected:
|
||||
unsigned short m_openSessions;
|
||||
|
||||
C4JThread* m_threadScoreboard;
|
||||
bool m_running;
|
||||
|
||||
int m_titleContext;
|
||||
int32_t m_requestId;
|
||||
|
||||
// SceNpId m_myNpId;
|
||||
|
||||
static int scoreboardThreadEntry(LPVOID lpParam);
|
||||
void scoreboardThreadInternal();
|
||||
|
||||
virtual bool getScoreByIds();
|
||||
virtual bool getScoreByRange();
|
||||
|
||||
virtual bool setScore();
|
||||
|
||||
std::queue<RegisterScore> m_views;
|
||||
|
||||
CRITICAL_SECTION m_csViewsLock;
|
||||
|
||||
EStatsState m_eStatsState; // State of the stats read
|
||||
// EFilterMode m_eFilterMode;
|
||||
|
||||
ReadScore* m_scores;
|
||||
unsigned int m_maxRank;
|
||||
// SceNpScoreRankData *m_stats;
|
||||
|
||||
public:
|
||||
virtual void Tick();
|
||||
|
||||
// Open a session
|
||||
virtual bool OpenSession();
|
||||
|
||||
// Close a session
|
||||
virtual void CloseSession();
|
||||
|
||||
// Delete a session
|
||||
virtual void DeleteSession();
|
||||
|
||||
// Write the given stats
|
||||
// This is called synchronously and will not free any memory allocated for
|
||||
// views when it is done
|
||||
|
||||
virtual bool WriteStats(unsigned int viewCount, ViewIn views);
|
||||
|
||||
virtual bool ReadStats_Friends(LeaderboardReadListener* callback,
|
||||
int difficulty, EStatsType type,
|
||||
PlayerUID myUID, unsigned int startIndex,
|
||||
unsigned int readCount);
|
||||
virtual bool ReadStats_MyScore(LeaderboardReadListener* callback,
|
||||
int difficulty, EStatsType type,
|
||||
PlayerUID myUID, unsigned int readCount);
|
||||
virtual bool ReadStats_TopRank(LeaderboardReadListener* callback,
|
||||
int difficulty, EStatsType type,
|
||||
unsigned int startIndex,
|
||||
unsigned int readCount);
|
||||
|
||||
// Perform a flush of the stats
|
||||
virtual void FlushStats();
|
||||
|
||||
// Cancel the current operation
|
||||
virtual void CancelOperation();
|
||||
|
||||
// Is the leaderboard manager idle.
|
||||
virtual bool isIdle();
|
||||
|
||||
protected:
|
||||
int getBoardId(int difficulty, EStatsType);
|
||||
|
||||
SceNpScorePlayerRankData* addPadding(unsigned int num,
|
||||
SceNpScoreRankData* rankData);
|
||||
|
||||
void convertToOutput(unsigned int& num, ReadScore* out,
|
||||
SceNpScorePlayerRankData* rankData,
|
||||
SceNpScoreComment* comm);
|
||||
|
||||
void toBinary(void* out, SceNpScoreComment* in);
|
||||
void fromBinary(SceNpScoreComment** out, void* in);
|
||||
|
||||
void toBase32(SceNpScoreComment* out, void* in);
|
||||
void fromBase32(void* out, SceNpScoreComment* in);
|
||||
|
||||
void toSymbols(char*);
|
||||
void fromSymbols(char*);
|
||||
|
||||
bool test_string(std::string);
|
||||
|
||||
void initReadScoreStruct(ReadScore& out, SceNpScoreRankData&);
|
||||
void fillReadScoreStruct(ReadScore& out, SceNpScoreComment& comment);
|
||||
|
||||
static bool SortByRank(const ReadScore& lhs, const ReadScore& rhs);
|
||||
|
||||
protected:
|
||||
// 4J-JEV: Interface differences:
|
||||
|
||||
// Sce NP score library function redirects.
|
||||
virtual HRESULT initialiseScoreUtility() { return ERROR_SUCCESS; }
|
||||
virtual bool scoreUtilityAlreadyInitialised(HRESULT hr) { return false; }
|
||||
|
||||
virtual HRESULT createTitleContext(const SceNpId& npId) = 0;
|
||||
virtual HRESULT destroyTitleContext(int titleContext) = 0;
|
||||
|
||||
virtual HRESULT createTransactionContext(int titleContext) = 0;
|
||||
virtual HRESULT abortTransactionContext(int transactionContext) = 0;
|
||||
virtual HRESULT destroyTransactionContext(int transactionContext) = 0;
|
||||
|
||||
virtual HRESULT fillByIdsQuery(const SceNpId& myNpId, SceNpId*& npIds,
|
||||
uint32_t& len);
|
||||
|
||||
#if (defined __ORBIS__) || (defined __PSVITA__)
|
||||
virtual HRESULT getFriendsList(
|
||||
sce::Toolkit::NP::Utilities::Future<sce::Toolkit::NP::FriendsList>&
|
||||
friendsList) = 0;
|
||||
#endif
|
||||
|
||||
virtual char* getComment(SceNpScoreComment* comment) = 0;
|
||||
};
|
||||
133
Minecraft.Client/Platform/Common/Leaderboards/base64.cpp
Normal file
133
Minecraft.Client/Platform/Common/Leaderboards/base64.cpp
Normal file
|
|
@ -0,0 +1,133 @@
|
|||
/*
|
||||
base64.cpp and base64.h
|
||||
|
||||
Copyright (C) 2004-2008 Ren<EFBFBD> Nyffenegger
|
||||
|
||||
This source code is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the author be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this source code must not be misrepresented; you must not
|
||||
claim that you wrote the original source code. If you use this source code
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original source code.
|
||||
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
Ren<EFBFBD> Nyffenegger rene.nyffenegger@adp-gmbh.ch
|
||||
|
||||
*/
|
||||
|
||||
#include "../../stdafx.h"
|
||||
|
||||
#include "base64.h"
|
||||
#include <iostream>
|
||||
|
||||
static const sstd::td::string base64_chars =
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
"abcdefghijklmnopqrstuvwxyz"
|
||||
"0123456789+/";
|
||||
|
||||
static inline bool is_base64(unsigned char c) {
|
||||
return (isalnum(c) || (c == '+') || (c == '/'));
|
||||
}
|
||||
|
||||
// 4J ADDED,
|
||||
sstd::td::string base64_encode(sstd::td::string str) {
|
||||
return base64_encode(reinterpret_cast<const unsigned char*>(str.c_str()),
|
||||
str.length());
|
||||
}
|
||||
|
||||
sstd::td::string base64_encode(unsigned char const* bytes_to_encode,
|
||||
unsigned int in_len) {
|
||||
std::string ret;
|
||||
int i = 0;
|
||||
int j = 0;
|
||||
unsigned char char_array_3[3];
|
||||
unsigned char char_array_4[4];
|
||||
|
||||
while (in_len--) {
|
||||
char_array_3[i++] = *(bytes_to_encode++);
|
||||
if (i == 3) {
|
||||
char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
|
||||
char_array_4[1] = ((char_array_3[0] & 0x03) << 4) +
|
||||
((char_array_3[1] & 0xf0) >> 4);
|
||||
char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) +
|
||||
((char_array_3[2] & 0xc0) >> 6);
|
||||
char_array_4[3] = char_array_3[2] & 0x3f;
|
||||
|
||||
for (int ii = 0; (ii < 4); ii++)
|
||||
ret += base64_chars[char_array_4[ii]];
|
||||
i = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (i) {
|
||||
for (j = i; j < 3; j++) char_array_3[j] = '\0';
|
||||
|
||||
char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
|
||||
char_array_4[1] =
|
||||
((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
|
||||
char_array_4[2] =
|
||||
((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
|
||||
char_array_4[3] = char_array_3[2] & 0x3f;
|
||||
|
||||
for (j = 0; (j < i + 1); j++) ret += base64_chars[char_array_4[j]];
|
||||
|
||||
while ((i++ < 3)) ret += '=';
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
sstd::td::string base64_decode(sstd::td::string const& encoded_string) {
|
||||
int in_len = encoded_string.size();
|
||||
int i = 0;
|
||||
int j = 0;
|
||||
int in_ = 0;
|
||||
unsigned char char_array_4[4], char_array_3[3];
|
||||
std::string ret;
|
||||
|
||||
while (in_len-- && (encoded_string[in_] != '=') &&
|
||||
is_base64(encoded_string[in_])) {
|
||||
char_array_4[i++] = encoded_string[in_];
|
||||
in_++;
|
||||
if (i == 4) {
|
||||
for (i = 0; i < 4; i++)
|
||||
char_array_4[i] = base64_chars.find(char_array_4[i]);
|
||||
|
||||
char_array_3[0] =
|
||||
(char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);
|
||||
char_array_3[1] = ((char_array_4[1] & 0xf) << 4) +
|
||||
((char_array_4[2] & 0x3c) >> 2);
|
||||
char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];
|
||||
|
||||
for (i = 0; (i < 3); i++) ret += char_array_3[i];
|
||||
i = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (i) {
|
||||
for (j = i; j < 4; j++) char_array_4[j] = 0;
|
||||
|
||||
for (j = 0; j < 4; j++)
|
||||
char_array_4[j] = base64_chars.find(char_array_4[j]);
|
||||
|
||||
char_array_3[0] =
|
||||
(char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);
|
||||
char_array_3[1] =
|
||||
((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
|
||||
char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];
|
||||
|
||||
for (j = 0; (j < i - 1); j++) ret += char_array_3[j];
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
7
Minecraft.Client/Platform/Common/Leaderboards/base64.h
Normal file
7
Minecraft.Client/Platform/Common/Leaderboards/base64.h
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
std::string base64_encode(std::string str);
|
||||
std::string base64_encode(unsigned char const*, unsigned int len);
|
||||
std::string base64_decode(std::string const& s);
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include "UIScene.h"
|
||||
#include "../Leaderboards/LeaderboardManager.h"
|
||||
#include "../Leaderboards/LeaderboardInterface.h"
|
||||
|
||||
class UIScene_LeaderboardsMenu : public UIScene,
|
||||
public LeaderboardReadListener {
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
#include <cstdint>
|
||||
|
||||
#include "UIEnums.h"
|
||||
#include "../App_Defines.h"
|
||||
|
||||
class Container;
|
||||
class Inventory;
|
||||
|
|
@ -253,54 +254,79 @@ typedef struct _JoinMenuInitData {
|
|||
|
||||
// More Options
|
||||
typedef struct _LaunchMoreOptionsMenuInitData {
|
||||
bool bOnlineGame = true;
|
||||
bool bInviteOnly = false;
|
||||
bool bAllowFriendsOfFriends = true;
|
||||
bool bOnlineGame;
|
||||
bool bInviteOnly;
|
||||
bool bAllowFriendsOfFriends;
|
||||
|
||||
bool bGenerateOptions = false;
|
||||
bool bStructures = false;
|
||||
bool bFlatWorld = false;
|
||||
bool bBonusChest = false;
|
||||
bool bGenerateOptions;
|
||||
bool bStructures;
|
||||
bool bFlatWorld;
|
||||
bool bBonusChest;
|
||||
|
||||
bool bPVP = true;
|
||||
bool bTrust = false;
|
||||
bool bFireSpreads = true;
|
||||
bool bTNT = true;
|
||||
bool bPVP;
|
||||
bool bTrust;
|
||||
bool bFireSpreads;
|
||||
bool bTNT;
|
||||
|
||||
bool bHostPrivileges = false;
|
||||
bool bResetNether = false;
|
||||
bool bHostPrivileges;
|
||||
bool bResetNether;
|
||||
|
||||
bool bOnlineSettingChangedBySystem = false;
|
||||
bool bMobGriefing;
|
||||
bool bKeepInventory;
|
||||
bool bDoMobSpawning;
|
||||
bool bDoMobLoot;
|
||||
bool bDoTileDrops;
|
||||
bool bNaturalRegeneration;
|
||||
bool bDoDaylightCycle;
|
||||
|
||||
bool bDoMobSpawning = false;
|
||||
bool bDoDaylightCycle = false;
|
||||
int iPad = -1;
|
||||
bool bOnlineSettingChangedBySystem;
|
||||
|
||||
std::uint32_t dwTexturePack = 0;
|
||||
int iPad;
|
||||
|
||||
std::wstring seed = L"";
|
||||
int worldSize = 3;
|
||||
bool bDisableSaving = false;
|
||||
DWORD dwTexturePack;
|
||||
|
||||
std::wstring seed;
|
||||
int worldSize;
|
||||
bool bDisableSaving;
|
||||
|
||||
EGameHostOptionWorldSize currentWorldSize;
|
||||
EGameHostOptionWorldSize newWorldSize;
|
||||
bool newWorldSizeOverwriteEdges;
|
||||
|
||||
_LaunchMoreOptionsMenuInitData() {
|
||||
memset(this, 0, sizeof(_LaunchMoreOptionsMenuInitData));
|
||||
bOnlineGame = true;
|
||||
bInviteOnly = false;
|
||||
bAllowFriendsOfFriends = true;
|
||||
bGenerateOptions = false;
|
||||
bStructures = false;
|
||||
bFlatWorld = false;
|
||||
bBonusChest = false;
|
||||
bPVP = true;
|
||||
bTrust = false;
|
||||
bFireSpreads = true;
|
||||
worldSize = 3;
|
||||
seed = L"";
|
||||
bDisableSaving = false;
|
||||
newWorldSize = e_worldSize_Unknown;
|
||||
newWorldSizeOverwriteEdges = false;
|
||||
bTNT = false;
|
||||
bHostPrivileges = false;
|
||||
bResetNether = false;
|
||||
bMobGriefing = true;
|
||||
bKeepInventory = false;
|
||||
bDoMobSpawning = false;
|
||||
bDoMobLoot = true;
|
||||
bDoTileDrops = true;
|
||||
bNaturalRegeneration = true;
|
||||
bDoDaylightCycle = true;
|
||||
bOnlineSettingChangedBySystem = false;
|
||||
|
||||
iPad = 0;
|
||||
|
||||
dwTexturePack = 0;
|
||||
|
||||
worldSize = 3;
|
||||
seed = L"";
|
||||
bDisableSaving = false;
|
||||
|
||||
currentWorldSize = e_worldSize_Unknown;
|
||||
newWorldSize = e_worldSize_Unknown;
|
||||
newWorldSizeOverwriteEdges = false;
|
||||
}
|
||||
} LaunchMoreOptionsMenuInitData;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,13 @@
|
|||
/*
|
||||
/*
|
||||
base64.cpp and base64.h
|
||||
|
||||
Copyright (C) 2004-2008 Ren<EFBFBD> Nyffenegger
|
||||
base64 encoding and decoding with C++.
|
||||
More information at
|
||||
https://renenyffenegger.ch/notes/development/Base64/Encoding-and-decoding-base-64-with-cpp
|
||||
|
||||
Version: 2.rc.09 (release candidate)
|
||||
|
||||
Copyright (C) 2004-2017, 2020-2022 René Nyffenegger
|
||||
|
||||
This source code is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the author be held liable for any damages
|
||||
|
|
@ -21,136 +27,256 @@
|
|||
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
Ren<EFBFBD> Nyffenegger rene.nyffenegger@adp-gmbh.ch
|
||||
René Nyffenegger rene.nyffenegger@adp-gmbh.ch
|
||||
|
||||
*/
|
||||
|
||||
#include "../../../../Minecraft.World/Platform/stdafx.h"
|
||||
|
||||
#include "base64.h"
|
||||
#include <iostream>
|
||||
|
||||
static const std::wstring base64_chars =
|
||||
L"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
L"abcdefghijklmnopqrstuvwxyz"
|
||||
L"0123456789+/";
|
||||
#include <algorithm>
|
||||
#include <stdexcept>
|
||||
|
||||
//
|
||||
// Depending on the url parameter in base64_chars, one of
|
||||
// two sets of base64 characters needs to be chosen.
|
||||
// They differ in their last two characters.
|
||||
//
|
||||
static const char* base64_chars[2] = {
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
"abcdefghijklmnopqrstuvwxyz"
|
||||
"0123456789"
|
||||
"+/",
|
||||
|
||||
static inline bool is_base64(wchar_t c)
|
||||
{
|
||||
return (isalnum(c) || (c == L'+') || (c == L'/'));
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
"abcdefghijklmnopqrstuvwxyz"
|
||||
"0123456789"
|
||||
"-_"};
|
||||
|
||||
static unsigned int pos_of_char(const unsigned char chr) {
|
||||
//
|
||||
// Return the position of chr within base64_encode()
|
||||
//
|
||||
|
||||
if (chr >= 'A' && chr <= 'Z') return chr - 'A';
|
||||
else if (chr >= 'a' && chr <= 'z') return chr - 'a' + ('Z' - 'A') + 1;
|
||||
else if (chr >= '0' && chr <= '9') return chr - '0' + ('Z' - 'A') + ('z' - 'a') + 2;
|
||||
else if (chr == '+' || chr == '-') return 62; // Be liberal with input and accept both url ('-') and non-url ('+') base 64 characters (
|
||||
else if (chr == '/' || chr == '_') return 63; // Ditto for '/' and '_'
|
||||
else
|
||||
//
|
||||
// 2020-10-23: Throw std::exception rather than const char*
|
||||
//(Pablo Martin-Gomez, https://github.com/Bouska)
|
||||
//
|
||||
throw std::runtime_error("Input is not valid base64-encoded data.");
|
||||
}
|
||||
|
||||
// 4J changed to use Platform::String
|
||||
Platform::String^ base64_encode(unsigned char* chars_to_encode, unsigned int in_len)
|
||||
{
|
||||
std::wstring ret;
|
||||
int i = 0;
|
||||
int j = 0;
|
||||
unsigned char char_array_3[3];
|
||||
unsigned char char_array_4[4];
|
||||
static std::string insert_linebreaks(std::string str, size_t distance) {
|
||||
//
|
||||
// Provided by https://github.com/JomaCorpFX, adapted by me.
|
||||
//
|
||||
if (!str.length()) {
|
||||
return "";
|
||||
}
|
||||
|
||||
while (in_len--)
|
||||
{
|
||||
char_array_3[i++] = *(chars_to_encode++);
|
||||
if (i == 3)
|
||||
{
|
||||
char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
|
||||
char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
|
||||
char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
|
||||
char_array_4[3] = char_array_3[2] & 0x3f;
|
||||
size_t pos = distance;
|
||||
|
||||
for(int ii = 0; (ii <4) ; ii++)
|
||||
{
|
||||
ret += base64_chars[char_array_4[ii]];
|
||||
}
|
||||
i = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (i)
|
||||
{
|
||||
for(j = i; j < 3; j++)
|
||||
{
|
||||
char_array_3[j] = '\0';
|
||||
}
|
||||
|
||||
char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
|
||||
char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
|
||||
char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
|
||||
char_array_4[3] = char_array_3[2] & 0x3f;
|
||||
|
||||
for (j = 0; (j < i + 1); j++)
|
||||
{
|
||||
ret += base64_chars[char_array_4[j]];
|
||||
}
|
||||
|
||||
while((i++ < 3))
|
||||
{
|
||||
ret += L'=';
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return ref new Platform::String(ret.c_str());
|
||||
while (pos < str.size()) {
|
||||
str.insert(pos, "\n");
|
||||
pos += distance + 1;
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
void base64_decode(Platform::String ^encoded_string, unsigned char *output, unsigned int out_len)
|
||||
{
|
||||
int in_len = encoded_string->Length();
|
||||
int i = 0;
|
||||
int j = 0;
|
||||
int in_ = 0;
|
||||
unsigned char char_array_4[4];
|
||||
unsigned char char_array_3[3];
|
||||
template <typename String, unsigned int line_length>
|
||||
static std::string encode_with_line_breaks(String s) {
|
||||
return insert_linebreaks(base64_encode(s, false), line_length);
|
||||
}
|
||||
|
||||
unsigned char *pucOut = output;
|
||||
template <typename String>
|
||||
static std::string encode_pem(String s) {
|
||||
return encode_with_line_breaks<String, 64>(s);
|
||||
}
|
||||
|
||||
while (in_len-- && ( encoded_string->Data()[in_] != L'=') && is_base64(encoded_string->Data()[in_]))
|
||||
{
|
||||
char_array_4[i++] = (unsigned char)(encoded_string->Data()[in_]);
|
||||
in_++;
|
||||
if (i ==4)
|
||||
{
|
||||
for (i = 0; i <4; i++)
|
||||
{
|
||||
char_array_4[i] = (unsigned char )base64_chars.find(char_array_4[i]);
|
||||
}
|
||||
template <typename String>
|
||||
static std::string encode_mime(String s) {
|
||||
return encode_with_line_breaks<String, 76>(s);
|
||||
}
|
||||
|
||||
char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);
|
||||
char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
|
||||
char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];
|
||||
template <typename String>
|
||||
static std::string encode(String s, bool url) {
|
||||
return base64_encode(reinterpret_cast<const unsigned char*>(s.data()), s.length(), url);
|
||||
}
|
||||
|
||||
for (i = 0; (i < 3); i++)
|
||||
{
|
||||
*pucOut++ = char_array_3[i];
|
||||
if( ( pucOut - output ) >= out_len ) return;
|
||||
}
|
||||
i = 0;
|
||||
}
|
||||
}
|
||||
std::string base64_encode(unsigned char const* bytes_to_encode, size_t in_len, bool url) {
|
||||
|
||||
if(i)
|
||||
{
|
||||
for (j = i; j <4; j++)
|
||||
{
|
||||
char_array_4[j] = 0;
|
||||
}
|
||||
size_t len_encoded = (in_len +2) / 3 * 4;
|
||||
|
||||
for (j = 0; j <4; j++)
|
||||
{
|
||||
char_array_4[j] = (unsigned char )base64_chars.find(char_array_4[j]);
|
||||
}
|
||||
unsigned char trailing_char = url ? '.' : '=';
|
||||
|
||||
char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);
|
||||
char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
|
||||
char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];
|
||||
//
|
||||
// Choose set of base64 characters. They differ
|
||||
// for the last two positions, depending on the url
|
||||
// parameter.
|
||||
// A bool (as is the parameter url) is guaranteed
|
||||
// to evaluate to either 0 or 1 in C++ therefore,
|
||||
// the correct character set is chosen by subscripting
|
||||
// base64_chars with url.
|
||||
//
|
||||
const char* base64_chars_ = base64_chars[url];
|
||||
|
||||
for (j = 0; (j < i - 1); j++)
|
||||
{
|
||||
*pucOut++ = char_array_3[j];
|
||||
if( ( pucOut - output ) >= out_len ) return;
|
||||
}
|
||||
}
|
||||
}
|
||||
std::string ret;
|
||||
ret.reserve(len_encoded);
|
||||
|
||||
unsigned int pos = 0;
|
||||
|
||||
while (pos < in_len) {
|
||||
ret.push_back(base64_chars_[(bytes_to_encode[pos + 0] & 0xfc) >> 2]);
|
||||
|
||||
if (pos+1 < in_len) {
|
||||
ret.push_back(base64_chars_[((bytes_to_encode[pos + 0] & 0x03) << 4) + ((bytes_to_encode[pos + 1] & 0xf0) >> 4)]);
|
||||
|
||||
if (pos+2 < in_len) {
|
||||
ret.push_back(base64_chars_[((bytes_to_encode[pos + 1] & 0x0f) << 2) + ((bytes_to_encode[pos + 2] & 0xc0) >> 6)]);
|
||||
ret.push_back(base64_chars_[ bytes_to_encode[pos + 2] & 0x3f]);
|
||||
}
|
||||
else {
|
||||
ret.push_back(base64_chars_[(bytes_to_encode[pos + 1] & 0x0f) << 2]);
|
||||
ret.push_back(trailing_char);
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
||||
ret.push_back(base64_chars_[(bytes_to_encode[pos + 0] & 0x03) << 4]);
|
||||
ret.push_back(trailing_char);
|
||||
ret.push_back(trailing_char);
|
||||
}
|
||||
|
||||
pos += 3;
|
||||
}
|
||||
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
template <typename String>
|
||||
static std::string decode(String const& encoded_string, bool remove_linebreaks) {
|
||||
//
|
||||
// decode(…) is templated so that it can be used with String = const std::string&
|
||||
// or std::string_view (requires at least C++17)
|
||||
//
|
||||
|
||||
if (encoded_string.empty()) return std::string();
|
||||
|
||||
if (remove_linebreaks) {
|
||||
|
||||
std::string copy(encoded_string);
|
||||
|
||||
copy.erase(std::remove(copy.begin(), copy.end(), '\n'), copy.end());
|
||||
|
||||
return base64_decode(copy, false);
|
||||
}
|
||||
|
||||
size_t length_of_string = encoded_string.length();
|
||||
size_t pos = 0;
|
||||
|
||||
//
|
||||
// The approximate length (bytes) of the decoded string might be one or
|
||||
// two bytes smaller, depending on the amount of trailing equal signs
|
||||
// in the encoded string. This approximation is needed to reserve
|
||||
// enough space in the string to be returned.
|
||||
//
|
||||
size_t approx_length_of_decoded_string = length_of_string / 4 * 3;
|
||||
std::string ret;
|
||||
ret.reserve(approx_length_of_decoded_string);
|
||||
|
||||
while (pos < length_of_string) {
|
||||
//
|
||||
// Iterate over encoded input string in chunks. The size of all
|
||||
// chunks except the last one is 4 bytes.
|
||||
//
|
||||
// The last chunk might be padded with equal signs or dots
|
||||
// in order to make it 4 bytes in size as well, but this
|
||||
// is not required as per RFC 2045.
|
||||
//
|
||||
// All chunks except the last one produce three output bytes.
|
||||
//
|
||||
// The last chunk produces at least one and up to three bytes.
|
||||
//
|
||||
|
||||
size_t pos_of_char_1 = pos_of_char(encoded_string.at(pos+1) );
|
||||
|
||||
//
|
||||
// Emit the first output byte that is produced in each chunk:
|
||||
//
|
||||
ret.push_back(static_cast<std::string::value_type>( ( (pos_of_char(encoded_string.at(pos+0)) ) << 2 ) + ( (pos_of_char_1 & 0x30 ) >> 4)));
|
||||
|
||||
if ( ( pos + 2 < length_of_string ) && // Check for data that is not padded with equal signs (which is allowed by RFC 2045)
|
||||
encoded_string.at(pos+2) != '=' &&
|
||||
encoded_string.at(pos+2) != '.' // accept URL-safe base 64 strings, too, so check for '.' also.
|
||||
)
|
||||
{
|
||||
//
|
||||
// Emit a chunk's second byte (which might not be produced in the last chunk).
|
||||
//
|
||||
unsigned int pos_of_char_2 = pos_of_char(encoded_string.at(pos+2) );
|
||||
ret.push_back(static_cast<std::string::value_type>( (( pos_of_char_1 & 0x0f) << 4) + (( pos_of_char_2 & 0x3c) >> 2)));
|
||||
|
||||
if ( ( pos + 3 < length_of_string ) &&
|
||||
encoded_string.at(pos+3) != '=' &&
|
||||
encoded_string.at(pos+3) != '.'
|
||||
)
|
||||
{
|
||||
//
|
||||
// Emit a chunk's third byte (which might not be produced in the last chunk).
|
||||
//
|
||||
ret.push_back(static_cast<std::string::value_type>( ( (pos_of_char_2 & 0x03 ) << 6 ) + pos_of_char(encoded_string.at(pos+3)) ));
|
||||
}
|
||||
}
|
||||
|
||||
pos += 4;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::string base64_decode(std::string const& s, bool remove_linebreaks) {
|
||||
return decode(s, remove_linebreaks);
|
||||
}
|
||||
|
||||
std::string base64_encode(std::string const& s, bool url) {
|
||||
return encode(s, url);
|
||||
}
|
||||
|
||||
std::string base64_encode_pem (std::string const& s) {
|
||||
return encode_pem(s);
|
||||
}
|
||||
|
||||
std::string base64_encode_mime(std::string const& s) {
|
||||
return encode_mime(s);
|
||||
}
|
||||
|
||||
#if __cplusplus >= 201703L
|
||||
//
|
||||
// Interface with std::string_view rather than const std::string&
|
||||
// Requires C++17
|
||||
// Provided by Yannic Bonenberger (https://github.com/Yannic)
|
||||
//
|
||||
|
||||
std::string base64_encode(std::string_view s, bool url) {
|
||||
return encode(s, url);
|
||||
}
|
||||
|
||||
std::string base64_encode_pem(std::string_view s) {
|
||||
return encode_pem(s);
|
||||
}
|
||||
|
||||
std::string base64_encode_mime(std::string_view s) {
|
||||
return encode_mime(s);
|
||||
}
|
||||
|
||||
std::string base64_decode(std::string_view s, bool remove_linebreaks) {
|
||||
return decode(s, remove_linebreaks);
|
||||
}
|
||||
|
||||
#endif // __cplusplus >= 201703L
|
||||
|
|
@ -1,6 +1,35 @@
|
|||
#pragma once
|
||||
//
|
||||
// base64 encoding and decoding with C++.
|
||||
// Version: 2.rc.09 (release candidate)
|
||||
//
|
||||
|
||||
#ifndef BASE64_H_C0CE2A47_D10E_42C9_A27C_C883944E704A
|
||||
#define BASE64_H_C0CE2A47_D10E_42C9_A27C_C883944E704A
|
||||
|
||||
#include <string>
|
||||
|
||||
Platform::String^ base64_encode(unsigned char* chars_to_encode, unsigned int in_len);
|
||||
void base64_decode(Platform::String ^encoded_string, unsigned char *output, unsigned int out_len);
|
||||
#if __cplusplus >= 201703L
|
||||
#include <string_view>
|
||||
#endif // __cplusplus >= 201703L
|
||||
|
||||
std::string base64_encode (std::string const& s, bool url = false);
|
||||
std::string base64_encode_pem (std::string const& s);
|
||||
std::string base64_encode_mime(std::string const& s);
|
||||
|
||||
std::string base64_decode(std::string const& s, bool remove_linebreaks = false);
|
||||
std::string base64_encode(unsigned char const*, size_t len, bool url = false);
|
||||
|
||||
#if __cplusplus >= 201703L
|
||||
//
|
||||
// Interface with std::string_view rather than const std::string&
|
||||
// Requires C++17
|
||||
// Provided by Yannic Bonenberger (https://github.com/Yannic)
|
||||
//
|
||||
std::string base64_encode (std::string_view s, bool url = false);
|
||||
std::string base64_encode_pem (std::string_view s);
|
||||
std::string base64_encode_mime(std::string_view s);
|
||||
|
||||
std::string base64_decode(std::string_view s, bool remove_linebreaks = false);
|
||||
#endif // __cplusplus >= 201703L
|
||||
|
||||
#endif /* BASE64_H_C0CE2A47_D10E_42C9_A27C_C883944E704A */
|
||||
Loading…
Reference in a new issue