highscores can now be submitted to and retrieved from a server

main
Martin Felis (berta) 2011-03-16 17:03:41 +01:00
parent f57a4e9fb9
commit 21239c9962
22 changed files with 2264 additions and 61 deletions

View File

@ -9,8 +9,6 @@ namespace asteroids {
int Controller::OnInit (int argc, char *argv[]) {
Engine::ControllerBase::OnInit (argc, argv);
mBindings[SDLK_q] = "quit";
mBindings[SDLK_UP] = "+forward";
mBindings[SDLK_LEFT] = "+turnleft";
mBindings[SDLK_RIGHT] = "+turnright";

View File

@ -2,6 +2,7 @@
#include <fstream>
#include <algorithm>
#include <boost/filesystem.hpp>
#include <SDL/SDL_net.h>
#include "Model.h"
#include "Physics.h"
@ -17,6 +18,10 @@ namespace asteroids {
static Model* ModelInstance = NULL;
Engine::Variable Model::HighscoreServerName ("highscore_server_name", "asteroids.fysx.org");
Engine::Variable Model::HighscoreServerPath ("highscore_server_path", "/highscore/highscore.php?format=raw");
Engine::Variable Model::UseServerHighscore ("use_server_highscore", "false");
/*
* Inherited Module functions
*/
@ -40,20 +45,20 @@ int Model::OnInit (int argc, char* argv[]) {
// First we reset the highscore list
mHighscoreList.clear();
// then we try to load values from the file
LoadHighscoreList();
// LoadHighscoreList();
// if we have less than the usual number of entries we add default values
if (mHighscoreList.size() < 10) {
AddHighscoreEntry ("Imperator", 1000000);
AddHighscoreEntry ("Darth Vader", 800000);
AddHighscoreEntry ("Luke Skywalker", 600000);
AddHighscoreEntry ("Han Solo", 400000);
AddHighscoreEntry ("Princess Leia", 200000);
AddHighscoreEntry ("C3PO", 100000);
AddHighscoreEntry ("R2-D2", 50000);
AddHighscoreEntry ("Chewy", 10000);
AddHighscoreEntry ("Mr. Ewok", 5000);
AddHighscoreEntry ("Jabba the Hutt", 1000);
AddLocalHighscoreEntry ("Imperator", 1000000);
AddLocalHighscoreEntry ("Darth Vader", 800000);
AddLocalHighscoreEntry ("Luke Skywalker", 600000);
AddLocalHighscoreEntry ("Han Solo", 400000);
AddLocalHighscoreEntry ("Princess Leia", 200000);
AddLocalHighscoreEntry ("C3PO", 100000);
AddLocalHighscoreEntry ("R2-D2", 50000);
AddLocalHighscoreEntry ("Chewy", 10000);
AddLocalHighscoreEntry ("Mr. Ewok", 5000);
AddLocalHighscoreEntry ("Jabba the Hutt", 1000);
}
// Reset the newest highscore entry index which may be used for highlighting
@ -69,12 +74,28 @@ int Model::OnInit (int argc, char* argv[]) {
mLevelAuthor = "";
mLevelTitle = "";
// initialize SDL_net to be able to retrieve highscore from the internet
if (SDLNet_Init() == -1) {
Engine::LogError("SDLNet_Init: %s\n", SDLNet_GetError());
}
SubmitGlobalHigscoreEntry ("asteroids_full", 321321321);
Engine::RegisterListener (this, EventAccelerateStart);
Engine::RegisterListener (this, EventAccelerateStop);
return result;
}
void Model::OnDestroy() {
Engine::ModelBase::OnDestroy();
mAsteroids.clear();
mLevelList.clear();
SaveLocalHighscoreList();
SDLNet_Quit();
}
bool Model::OnReceiveEvent (const Engine::EventBasePtr &event) {
switch (event->mEventType) {
case EventAccelerateStart:
@ -151,27 +172,13 @@ unsigned int Model::InitLevelList () {
return mLevelList.size();
}
void Model::LoadHighscoreList () {
Engine::LogDebug ("Loading highscore file");
boost::filesystem::path highscore_file(Engine::GetUserDirFullPath("/highscore.dat"));
void Model::ParseHighscoreStream (std::istream &highscore_stream) {
std::string line;
// if the file does not exist, we create it and write standard values into
// it.
if (!boost::filesystem::exists(highscore_file))
return;
if (!boost::filesystem::is_regular_file(highscore_file)) {
Engine::LogError ("Could not load highscore file: %s is not a regular file!", highscore_file.filename().c_str());
}
std::ifstream score_stream (highscore_file.filename().c_str());
while (!score_stream.eof()) {
while (getline(highscore_stream, line)) {
std::string name;
unsigned int points;
std::string line;
getline (score_stream, line);
std::string::size_type delimiter = line.find ('\t');
if (delimiter == std::string::npos)
break;
@ -182,11 +189,48 @@ void Model::LoadHighscoreList () {
points_stream >> points;
Engine::LogDebug ("Read Highscore Entry Name: %s Points: %d", name.c_str(), points);
AddHighscoreEntry (name, points);
AddLocalHighscoreEntry (name, points);
}
}
void Model::SaveHighscoreList () {
void Model::LoadHighscoreList () {
mHighscoreList.clear();
if (Model::UseServerHighscore.GetBoolValue()) {
Engine::LogMessage ("Retrieving Highscore from server");
std::stringstream global_highscore_stream;
if (PullGlobalHighscore(global_highscore_stream)) {
ParseHighscoreStream(global_highscore_stream);
return;
}
}
LoadLocalHighscoreList();
}
void Model::LoadLocalHighscoreList () {
Engine::LogDebug ("Loading local highscore file");
boost::filesystem::path highscore_file(Engine::GetUserDirFullPath("/highscore.dat"));
// if the file does not exist, we create it and write standard values into
// it.
if (!boost::filesystem::exists(highscore_file))
return;
if (!boost::filesystem::is_regular_file(highscore_file)) {
Engine::LogError ("Could not load highscore file: %s is not a regular file!", highscore_file.filename().c_str());
}
std::ifstream score_stream (highscore_file.filename().c_str());
ParseHighscoreStream (score_stream);
score_stream.close();
}
void Model::SaveLocalHighscoreList () {
Engine::LogDebug ("Saving local highscore file");
std::ofstream highscore_file (Engine::GetUserDirFullPath("/highscore.dat").c_str());
std::list<HighscoreEntry>::iterator iter = mHighscoreList.begin();
@ -207,7 +251,7 @@ bool highscore_cmp (Model::HighscoreEntry a, Model::HighscoreEntry b) {
*
* \TODO Re-think usage of mNewestHighscoreEntryIndex variable in this function
*/
unsigned int Model::AddHighscoreEntry(const std::string &name, const unsigned int points) {
unsigned int Model::AddLocalHighscoreEntry(const std::string &name, const unsigned int points) {
HighscoreEntry entry;
entry.name = name;
entry.points = points;
@ -239,13 +283,192 @@ unsigned int Model::AddHighscoreEntry(const std::string &name, const unsigned in
// if we have all 10 entries then we can save
// the highscore
SaveHighscoreList();
SaveLocalHighscoreList();
mNewestHighscoreEntryIndex = 99999;
return 99999;
}
bool Model::PullGlobalHighscore(std::stringstream &highscore_stream) {
highscore_stream.str("");
IPaddress server_address;
if (SDLNet_ResolveHost (&server_address, Model::HighscoreServerName.GetStringValue().c_str(), 80) == -1) {
Engine::LogWarning ("SDL_net resolve host: %s", SDLNet_GetError());
return false;
}
char ip_address_char[4];
memcpy (&ip_address_char[0], &server_address.host, sizeof(char) * 4);
int ip_address[4];
ip_address[0] = static_cast<int>(ip_address_char[0]);
ip_address[1] = static_cast<int>(ip_address_char[1]);
ip_address[2] = static_cast<int>(ip_address_char[2]);
ip_address[3] = static_cast<int>(ip_address_char[3]);
Engine::LogMessage ("Pulling global highscore from server %s (%d.%d.%d.%d)",
Model::HighscoreServerName.GetStringValue().c_str(),
ip_address[0],
ip_address[1],
ip_address[2],
ip_address[3]
);
TCPsocket server_socket = SDLNet_TCP_Open (&server_address);
if (!server_socket) {
Engine::LogError ("SDL_net tcp open: %s", SDLNet_GetError());
return false;
}
std::string http_query_string;
http_query_string = std::string ("GET ") + Model::HighscoreServerPath.GetStringValue() + std::string(" HTTP/1.1\r\nHost: asteroids.fysx.org\r\nConnection: close\r\n\r\n");
int bytes_sent;
bytes_sent = SDLNet_TCP_Send (server_socket, http_query_string.c_str(), http_query_string.size());
if (bytes_sent != http_query_string.size()) {
Engine::LogError ("SDL_net tcp send: %s", SDLNet_GetError());
return false;
}
char receive_buffer[255];
std::string http_result;
bool receiving = true;
while (receiving) {
// reset the buffer
bzero (&receive_buffer[0], 255);
// read the data
int received_bytes = SDLNet_TCP_Recv (server_socket, receive_buffer, 255);
if (received_bytes <= 0) {
receiving = false;
}
http_result.append (receive_buffer, received_bytes);
}
// we have to strip the whitespaces twice to cut out the content
http_result = strip_whitespaces (http_result);
http_result = http_result.substr (http_result.find ("\n\r"), http_result.size());
http_result = strip_whitespaces (http_result);
Engine::LogDebug ("Received Highscore: %s", http_result.c_str());
SDLNet_TCP_Close (server_socket);
highscore_stream.str(http_result);
return true;
}
bool Model::SubmitGlobalHigscoreEntry (const std::string &name, const unsigned int points) {
IPaddress server_address;
if (SDLNet_ResolveHost (&server_address, Model::HighscoreServerName.GetStringValue().c_str(), 80) == -1) {
Engine::LogWarning ("SDL_net resolve host: %s", SDLNet_GetError());
return false;
}
char ip_address_char[4];
memcpy (&ip_address_char[0], &server_address.host, sizeof(char) * 4);
int ip_address[4];
ip_address[0] = static_cast<int>(ip_address_char[0]);
ip_address[1] = static_cast<int>(ip_address_char[1]);
ip_address[2] = static_cast<int>(ip_address_char[2]);
ip_address[3] = static_cast<int>(ip_address_char[3]);
Engine::LogDebug ("Submitting highscore player_name='%s' score_value='%d' to server %s (%d.%d.%d.%d)",
name.c_str(),
points,
Model::HighscoreServerName.GetStringValue().c_str(),
ip_address[0],
ip_address[1],
ip_address[2],
ip_address[3]
);
TCPsocket server_socket = SDLNet_TCP_Open (&server_address);
if (!server_socket) {
Engine::LogError ("SDL_net tcp open: %s", SDLNet_GetError());
return false;
}
std::stringstream points_stringstream;
points_stringstream << points;
std::stringstream hash_input;
hash_input << name << ":" << points << ":" << sha256_hash ("asteroids rule");
std::string key = sha256_hash (hash_input.str());
std::string http_query_string;
http_query_string = std::string ("GET ")
+ Model::HighscoreServerPath.GetStringValue()
+ std::string("&player_name=") + name
+ std::string("&score_value=") + points_stringstream.str()
+ std::string("&key=") + key
+ std::string(" HTTP/1.1\r\nHost: asteroids.fysx.org\r\nConnection: close\r\n\r\n");
int bytes_sent;
bytes_sent = SDLNet_TCP_Send (server_socket, http_query_string.c_str(), http_query_string.size());
if (bytes_sent != http_query_string.size()) {
Engine::LogError ("SDL_net tcp send: %s", SDLNet_GetError());
return false;
}
char receive_buffer[255];
std::string http_result;
bool receiving = true;
while (receiving) {
// reset the buffer
bzero (&receive_buffer[0], 255);
// read the data
int received_bytes = SDLNet_TCP_Recv (server_socket, receive_buffer, 255);
if (received_bytes <= 0) {
receiving = false;
}
http_result.append (receive_buffer, received_bytes);
}
// we have to strip the whitespaces twice to cut out the content
http_result = strip_whitespaces (http_result);
http_result = http_result.substr (http_result.find ("\n\r"), http_result.size());
http_result = strip_whitespaces (http_result);
SDLNet_TCP_Close (server_socket);
if (http_result == "OK") {
Engine::LogDebug ("Submission successful: %s", http_result.c_str());
LoadHighscoreList();
return true;
} else {
Engine::LogMessage ("Submission unsuccessful: %s", http_result.c_str());
}
return false;
}
void Model::SubmitHighscoreEntry (const std::string &name, const unsigned int points) {
if (Model::UseServerHighscore.GetBoolValue()) {
Engine::LogMessage ("Sending highscore entry to the server");
SubmitGlobalHigscoreEntry (name, points);
} else {
AddLocalHighscoreEntry (name, points);
}
}
int Model::DoLoadLevel (const char* filename) {
Engine::LogMessage ("Loading level from %s", filename);
std::fstream level_file (filename, std::ios::in);
@ -403,11 +626,11 @@ void Model::SetGameState (const unsigned int &state) {
}
bool Model::OnGameOver() {
Engine::LogMessage ("Points = %d lowest = %d", mPoints, mHighscoreList.back().points );
Engine::LogDebug ("Points = %d lowest = %d", mPoints, mHighscoreList.back().points );
SubmitHighscoreEntry (mPlayerName, mPoints);
if (mPoints > mHighscoreList.back().points) {
Engine::LogMessage ("New Highscore!");
AddHighscoreEntry (mPlayerName, mPoints);
}
return false;
@ -425,7 +648,7 @@ void Model::OnNewGame() {
}
void Model::OnShipExplode () {
Engine::PlaySound(Engine::GetResourceFullPath("/data/sounds/rock_destroyed.wav"));
Engine::PlaySound(Engine::GetResourceFullPath("/data/sounds/ship_destroyed.wav"));
mPlayerLives --;

View File

@ -63,22 +63,22 @@ class Model : public Engine::ModelBase {
unsigned int points;
};
void ParseHighscoreStream (std::istream &highscore_stream);
void LoadHighscoreList ();
void SaveHighscoreList ();
unsigned int AddHighscoreEntry(const std::string &name, const unsigned int points);
bool HighscoreCmp (HighscoreEntry a, HighscoreEntry b);
bool PullGlobalHighscore (std::stringstream &highscore_stream);
bool SubmitGlobalHigscoreEntry (const std::string &name, const unsigned int points);
void SubmitHighscoreEntry (const std::string &name, const unsigned int points);
unsigned int AddLocalHighscoreEntry(const std::string &name, const unsigned int points);
void LoadLocalHighscoreList ();
void SaveLocalHighscoreList ();
std::list<HighscoreEntry> mHighscoreList;
unsigned int mNewestHighscoreEntryIndex;
protected:
/** \brief Initializes the system */
virtual int OnInit (int argc, char* argv[]);
virtual void OnDestroy() {
Engine::ModelBase::OnDestroy();
mAsteroids.clear();
mLevelList.clear();
SaveHighscoreList();
};
virtual void OnDestroy();
virtual void OnRegisterCommands ();
virtual void OnCreateEntity (const int type, const unsigned int id);
@ -100,6 +100,11 @@ class Model : public Engine::ModelBase {
std::string mLevelAuthor;
std::string mLevelTitle;
static Engine::Variable HighscoreServerName;
static Engine::Variable HighscoreServerPath;
static Engine::Variable UseServerHighscore;
static Engine::Variable UseServerHighscoreAsked;
virtual bool OnReceiveEvent (const Engine::EventBasePtr &event);
friend class View;

View File

@ -710,8 +710,8 @@ void View::DrawUiHighscore() {
while (highscore_iter != GetModel()->mHighscoreList.end()) {
// Check whether we have to highlight an entry (such as when entering
// the name)
if (GetModel()->mNewestHighscoreEntryIndex < GetModel()->mHighscoreList.size()
&& GetModel()->mNewestHighscoreEntryIndex == i) {
if (GetModel()->GetPlayerName() == highscore_iter->name
&& GetModel()->GetPoints() == highscore_iter->points) {
// we highlight the newest entry
SelectFont("console.ttf color=#e8d500 size=23");
} else {
@ -726,7 +726,8 @@ void View::DrawUiHighscore() {
highscore_iter++;
}
if (Engine::GUI::Button (1, "Back to Menu", screen_right * 0.5 - 250 * 0.5, y + 16, button_width, button_height)) {
if (Engine::GUI::Button (1, "Back to Menu", screen_right * 0.5 - 250 * 0.5, y + 16, button_width, button_height)
|| Engine::GUI::CheckKeyPressed(SDLK_ESCAPE) ) {
PopViewState();
}
}
@ -752,7 +753,8 @@ void View::DrawUiOptions() {
}
if (Engine::GUI::Button (5, "Back", screen_right * 0.5 - 100, 380, button_width, button_height)) {
if (Engine::GUI::Button (5, "Back", screen_right * 0.5 - 100, 380, button_width, button_height)
|| Engine::GUI::CheckKeyPressed(SDLK_ESCAPE) ) {
PopViewState();
}
}
@ -773,7 +775,7 @@ _Music\r\
DJad - Space Exploration\r\
\r\
_Sounds\r\
Marcus Zetterquist\r\
Martin Felis\r\
\r\
_Libraries\r\
libSDL\r\
@ -782,11 +784,15 @@ _Libraries\r\
freetype2\r\
boost\r\
libpng\r\
\r\
Aaron D. Gifford's sha2 code\r\
\r\
_Tools\r\
GIMP\r\
Blender\r\
CMake\r\
sfxr-sdl\r\
Audacity\r\
\r\
_Special Thanks\r\
to my wonderful wife Katrina\r\
@ -795,7 +801,6 @@ _Special Thanks\r\
\r\
\r\
\r\
\r\
_http://www.fysx.org\r\
\r\
\r\
@ -804,6 +809,7 @@ _http://www.fysx.org\r\
\r\
\r\
\r\
\r\
:created with vim.\r\
::wq\r\
\r\
@ -876,7 +882,9 @@ void View::DrawUiEnterPlayername() {
SelectFont("console.ttf size=23");
Engine::GUI::Label (1, "Enter your name: ", screen_right * 0.5 - 220, 250);
if (Engine::GUI::LineEdit (2, screen_right * 0.5 + 20, 238, player_name, 16)) {
std::string valid_chars ("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890-_!.");
if (Engine::GUI::LineEditMasked (2, screen_right * 0.5 + 20, 238, player_name, 16, valid_chars)) {
GetModel()->SetPlayerName(player_name);
}
@ -887,7 +895,8 @@ void View::DrawUiEnterPlayername() {
GetModel()->SetGameState(GameStateRunning);
}
if (Engine::GUI::Button (5, "Back", 20, 500, 180, 40)) {
if (Engine::GUI::Button (5, "Back", 20, 500, 180, 40)
|| Engine::GUI::CheckKeyPressed(SDLK_ESCAPE) ) {
PopViewState();
}
}

View File

@ -8,6 +8,7 @@
#include "Model.h"
#include "Physics.h"
#include "EntityFactory.h"
#include "Game.h"
#include <boost/filesystem.hpp>
@ -164,12 +165,15 @@ int main (int argc, char* argv[]) {
Engine::PlayMusic (Engine::GetResourceFullPath("/data/sounds/intro_music.ogg"));
asteroids::GetModel()->LoadHighscoreList();
engine.MainLoop ();
// save the configuration
std::ofstream config_file (engine.GetUserDirFullPath("/config.rc").c_str());
config_file << "set effects_volume " << Engine::GetEffectsVolume() << std::endl;
config_file << "set music_volume " << Engine::GetMusicVolume() << std::endl;
config_file << "set use_server_highscore " << Engine::GetVariableString("use_server_highscore") << std::endl;
config_file.close();
SDL_WM_SetIcon(NULL,NULL);

View File

@ -4,6 +4,7 @@ LIST( APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/CMake )
FIND_PACKAGE (SDL REQUIRED)
FIND_PACKAGE (SDL_mixer REQUIRED)
FIND_PACKAGE (SDL_net REQUIRED)
FIND_PACKAGE (OpenGL REQUIRED)
FIND_PACKAGE (PNG REQUIRED)
FIND_PACKAGE (FreeType2 REQUIRED)
@ -43,10 +44,12 @@ SET ( ENGINE_SRCS
INCLUDE_DIRECTORIES (
${Boost_INCLUDE_DIRS}
${SDLMIXER_INCLUDE_DIRS}
${SDLNET_INCLUDE_DIRS}
${PROJECT_SOURCE_DIR}
libraries/mathlib/
libraries/coll2d/include
libraries/oglft/liboglft
libraries/sha2/
${FREETYPE2_INCLUDE_DIR}
)
@ -55,12 +58,14 @@ ADD_LIBRARY ( Engine STATIC ${ENGINE_SRCS} )
TARGET_LINK_LIBRARIES ( Engine
${SDL_LIBRARY}
${SDLMIXER_LIBRARY}
${SDLNET_LIBRARY}
${OPENGL_LIBRARIES}
${PNG_LIBRARIES}
${Boost_LIBRARIES}
mathlib
oglft
coll2d
sha2
)
ADD_SUBDIRECTORY ( tests )

View File

@ -37,6 +37,8 @@ int Engine::OnInit (int argc, char* argv[]) {
EngineInstance = this;
mStatus = EngineStatusUndefined;
/* Phase 0: Logging, Events, Variables, Commands, SDL */
/* Initialization of the base modules */
if (mLogging == NULL)
mLogging = new Logging ();
@ -77,6 +79,13 @@ int Engine::OnInit (int argc, char* argv[]) {
}
SDL_WM_SetCaption("Engine Initializing","Engine Initializing");
/* Now register the commands */
mLogging->RegisterCommands ();
mVariables->RegisterCommands ();
mCommands->RegisterCommands ();
/* Phase 1: Sounds, Model, EntityFactory, Physics, View, Camera, Controller*/
/* Sound */
mSoundManager = new SoundBase();
mSoundManager->Init (argc, argv);
@ -96,7 +105,6 @@ int Engine::OnInit (int argc, char* argv[]) {
mModel->mEntityFactory = mEntityFactory;
/* Physics */
if (mPhysics == NULL) {
mPhysics = new PhysicsBase ();
@ -142,11 +150,7 @@ int Engine::OnInit (int argc, char* argv[]) {
mController->Init (argc, argv);
/* Now register the commands */
mLogging->RegisterCommands ();
mVariables->RegisterCommands ();
mCommands->RegisterCommands ();
mModel->mPhysics->RegisterCommands ();
mModel->RegisterCommands ();

View File

@ -546,6 +546,151 @@ bool LineEdit (int id, int x, int y, std::string &text_value, const int &maxleng
return false;
}
bool LineEditMasked (int id, int x, int y, std::string &text_value, const int &maxlength, const std::string &valid_chars) {
controller = EngineGetController();
assert (controller);
int textpos_x = x + 8;
int textpos_y = y + 5;
y -= 16;
int w = maxlength * 16;
int h = 30;
// LogMessage ("id = %d hotitem = %d activeitem = %d kbditem = %d key = %s", id, controller->uistate.hotitem, controller->uistate.activeitem, controller->uistate.kbditem, convert_keycode (controller->uistate.last_keysym));
// Check for hotness
if (regionhit (x, y, w, h)) {
controller->uistate.hotitem = id;
if (controller->uistate.activeitem == 0
&& controller->GetButtonState(MouseButtonLeft)) {
controller->uistate.activeitem = id;
}
}
if (controller->uistate.kbditem == 0) {
controller->uistate.hotitem = id;
controller->uistate.kbditem = id;
controller->uistate.last_unicode = 0;
return false;
}
// If we have keyboard focus, we highlight the widget
if ( controller->uistate.kbditem == id) {
if (controller->uistate.activeitem == id) {
glColor3f (0.8, 0.8, 0.8);
DrawBlock (x, y, w, h);
} else {
glColor3f (0.7, 0.7, 0.7);
DrawBlock (x, y, w, h);
}
} else {
glColor3f (0.4, 0.4, 0.4);
DrawBlock (x, y, w, h);
}
// Rendering of the current value
float width, height;
view = EngineGetView ();
assert (view);
glColor3f (1., 1., 1.);
std::string text_output = text_value;
if (controller->uistate.kbditem == id && SDL_GetTicks() >> 9 & 1)
text_output += "_";
SelectFont("console.ttf size=23");
view->DrawGLStringMeasure(text_value.c_str(), &width, &height);
view->DrawGLString(textpos_x, textpos_y, text_output.c_str());
// Keyboard Logic
if (controller->uistate.kbditem == id) {
switch (controller->uistate.last_keysym) {
case SDLK_DOWN:
controller->uistate.kbditem = 0;
controller->uistate.hotitem = 0;
controller->uistate.last_keysym = SDLK_CLEAR;
break;
case SDLK_UP:
controller->uistate.kbditem = controller->uistate.lastwidget;
controller->uistate.hotitem = controller->uistate.lastwidget;
controller->uistate.last_keysym = SDLK_CLEAR;
break;
case SDLK_CLEAR:
controller->uistate.last_keysym = SDLK_CLEAR;
controller->uistate.last_unicode = 0;
return false;
break;
case SDLK_ESCAPE:
controller->uistate.last_keysym = SDLK_CLEAR;
controller->uistate.last_unicode = 0;
controller->uistate.hotitem = 0;
controller->uistate.kbditem = 0;
return false;
break;
case SDLK_TAB:
controller->uistate.last_keysym = SDLK_CLEAR;
controller->uistate.last_unicode = 0;
controller->uistate.hotitem = 0;
controller->uistate.kbditem = 0;
return false;
break;
case SDLK_RETURN:
controller->uistate.last_keysym = SDLK_CLEAR;
controller->uistate.last_unicode = 0;
controller->uistate.hotitem = 0;
controller->uistate.kbditem = 0;
return true;
break;
case SDLK_BACKSPACE:
if (text_value.size() > 0) {
text_value = text_value.substr(0, text_value.size() - 1);
controller->uistate.last_keysym = SDLK_CLEAR;
controller->uistate.last_unicode = 0;
return true;
}
break;
default:
// The raw input processing
if (maxlength > 0 && text_value.size() < maxlength) {
if (controller->uistate.last_unicode) {
if ((controller->uistate.last_unicode & 0xFF80) == 0) {
char c = controller->uistate.last_unicode & 0x7F;
// we do not want to add special characters such as backspaces
// etc.
if (c >= 0x20 && valid_chars.find(c) != std::string::npos ) {
text_value += c;
}
controller->uistate.last_unicode = 0;
return true;
} else {
LogWarning ("Input key not supported!");
return false;
}
}
}
break;
}
}
controller->uistate.lastwidget = id;
// Mouse Logic
if (controller->GetButtonState(MouseButtonLeft) == false
&& controller->uistate.hotitem == id
&& controller->uistate.activeitem == id) {
controller->uistate.kbditem = id;
controller->uistate.last_unicode = 0;
}
return false;
}
float VerticalSlider (int id, int x, int y, int w, int h, float min_value, float max_value, float &value) {
const int knob_width = 16;
const int knob_height = h * 2;

View File

@ -38,6 +38,8 @@ bool CheckButton (int id, const char* caption, bool state, int x, int y, int w,
bool LineEdit (int id, int x, int y, std::string &text_value, const int &maxlength);
bool LineEditMasked (int id, int x, int y, std::string &text_value, const int &maxlength, const std::string &valid_chars);
float VerticalSlider (int id, int x, int y, int w, int h, float min_value, float max_value, float &value);
/** \brief Checks whether a given key is currently pressed

View File

@ -7,7 +7,12 @@
#include <boost/filesystem.hpp>
#include <cstdlib>
#include <sha2.h>
std::string strip_whitespaces (const std::string input_str) {
if (input_str.size() == 0)
return input_str;
std::string result = input_str.substr(input_str.find_first_not_of (" \t\n\r"), input_str.size());
return result.substr (0, result.find_last_not_of(" \t\n\r") + 1);
}
@ -36,3 +41,15 @@ bool create_dir (const std::string &dir_str) {
return false;
}
std::string sha256_hash (std::string input) {
char result_buf[64];
SHA256_CTX ctx256;
SHA256_Init(&ctx256);
SHA256_Update(&ctx256, (unsigned char*) input.c_str(), input.size());
SHA256_End (&ctx256, result_buf);
return std::string (result_buf, 64);
}

View File

@ -5,5 +5,6 @@
std::string strip_whitespaces (const std::string input_str);
bool create_dir (const std::string &dir_str);
std::string sha256_hash (std::string input);
#endif /* _UTILS_H */

View File

@ -63,6 +63,7 @@ Variable::Variable (const std::string &name, const std::string &value) {
mName = name;
mStringValue = value;
mFloatValue = atof (value.c_str());
mBoolValue = ParseBoolValue (value);
if (VariablesInstance == NULL) {
delayed_variables.push_back (this);
@ -81,7 +82,7 @@ Variable::Variable (const std::string &name, const std::string &value) {
}
void Variable::RegisterVariable (const std::string &name) {
if (! VariablesInstance ) {
if (! VariablesInstance ) {
LogError ("Unable to register Variable '%s': Variables System not initialized!", name.c_str());
return;
}
@ -89,6 +90,23 @@ void Variable::RegisterVariable (const std::string &name) {
VariablesInstance->RegisterVariable (name, this);
}
bool Variable::ParseBoolValue (std::string value) {
float float_value = atof (value.c_str());
if (float_value != 0.)
return true;
// transform to upper case
unsigned int i;
for (i = 0; i < value.size(); i++)
value[i] = tolower (value[i]);
// std::transform (value.begin(), value.end(), value.begin(), ::tolower);
if (value == "true"
|| value == "yes")
return true;
}
/*
* Global functions
*/

View File

@ -26,6 +26,7 @@ bool Cmd_Set (const std::vector<std::string> args) {
if (test) {
test->SetStringValue (args[1]);
test->SetFloatValue (atof (args[1].c_str()));
test->SetBoolValueFromString (args[1]);
return true;
}

View File

@ -29,12 +29,22 @@ class Variable {
float& GetFloatValue () {
return mFloatValue;
}
/** \brief Returns the float value of the Variable */
bool& GetBoolValue () {
return mBoolValue;
}
void SetStringValue (const std::string &value) {
mStringValue = value;
}
void SetFloatValue (float value) {
mFloatValue = value;
}
void SetBoolValue (bool value) {
mBoolValue = value;
}
void SetBoolValueFromString (std::string str_value) {
mBoolValue = ParseBoolValue (str_value);
}
private:
/** \brief The default constructor must not be used.
@ -48,9 +58,21 @@ class Variable {
/** \brief Registeres this Variable with the Variables System */
void RegisterVariable (const std::string &name);
/** \brief Parses the input value and checks whether it resembles true or not
*
* Valid true expressions are:
* - any float values that are unequal to zero
* - true (case insensitive)
* - yes (case insensitive)
*
* \returns true if value contains a value that qualifies as a valid "true" expression
*/
bool ParseBoolValue (std::string value);
std::string mName;
std::string mStringValue;
float mFloatValue;
bool mBoolValue;
friend class Variables;
};
@ -63,6 +85,9 @@ bool SetVariableValue (const std::string &name, const std::string &value);
std::string& GetVariableString (const std::string &name, std::string def = "");
/** \brief Returns the float value of the Variable with the given name */
float& GetVariableFloat (const std::string &name, float def = 0.);
/** \brief Returns the boolean value of the Variable with the given name */
bool& GetVariableBool (const std::string &name, bool def = false);
}
#endif // _VARIABLESGLOBAL_H

View File

@ -1,3 +1,4 @@
ADD_SUBDIRECTORY ( mathlib )
ADD_SUBDIRECTORY ( coll2d )
ADD_SUBDIRECTORY ( oglft )
ADD_SUBDIRECTORY ( sha2 )

View File

@ -0,0 +1,6 @@
PROJECT (SHA2 CXX)
SET ( SRCS
sha2.c
)
ADD_LIBRARY ( sha2 STATIC sha2.c)

View File

@ -0,0 +1,272 @@
VERSION:
This is version 1.0 RELEASE
While this is my "release" version, due to lack of additional
official test vectors against which to verify this implementation's
correctness, beware that there may be implementation bugs. Also,
it has not yet been tested on very many other architectures,
big-endian machines in particular.
LICENSE:
This implementation is released freely under an open-source BSD
license which appears at the top of each source code file.
WHAT IT IS:
The files sha2.h and sha2.c implement the SHA-256, SHA-384, and SHA-512
hash algorithms as described in the PDF document found at the following
web address:
http://csrc.nist.gov/cryptval/shs/sha256-384-512.pdf
The interface is similar to the interface to SHA-1 found in the OpenSSL
library.
The file sha2prog.c is a simple program that accepts input from either
STDIN or reads one or more files specified on the command line, and then
generates the specified hash (either SHA-256, SHA-384, SHA-512, or any
combination thereof, including all three at once).
LIMITATIONS:
This implementation has several limitations:
* Input data is only accepted in octet-length increments. No sub-byte
data is handled. The NIST document describes how to handle sub-byte
input data, but for ease of implementation this version will only
accept message data in multiples of bytes.
* This implementation utilizes 64-bit integer data types. If your
system and compiler does not have a 64-bit integer data type, this
implementation will not work.
* Because of the use of 64-bit operations, many 32-bit architectures
that do have 64-bit data types but do operations most efficiently
on 32-bit words, this implementation may be slower than an
implementation designed to use only 32-bit words (emulating the
64-bit operations).
* On platforms with 128-bit integer data types, the SHA-384 and SHA-512
bit counters used by this implementation might be better off using
the 128-bit type instead of simulating it with two 64-bit integers.
* This implementation was written in C in hopes of portability and for
the fun of it during my spare time. It is probably not the most
efficient or fastest C implementation. I welcome suggestions,
however, that suggest ways to speed things up without breaking
portability. I also welcome suggestions to improve portability.
* As mentioned above, this code has NOT been thoroughly tested.
This is perhaps the most severe limitation.
BEFORE YOU COMPILE (OPTIONS):
Each of the options described below may either be defined in the sha2.h
header file (or in the sha2.c file in some cases), or on the command
line at compile time if your compiler supports such things. For
example:
#define SHA2_USE_INTTYPES_H
#define SHA2_UNROLL_TRANSFORM
Or:
cc -c -DSHA2_UNROLL_TRANSFORM sha2.c
cc -c -DBYTE_ORDER=4321 -DBIG_ENDIAN=4321 sha2.c
Here are the available options. Read on below for a description of
each one:
SHA2_USE_INTTYPES_H
SHA2_USE_MEMSET_MEMCPY/SHA2_USE_BZERO_BCOPY
SHA2_UNROLL_TRANSFORM
BYTE_ORDER (LITTLE_ENDIAN/BIG_ENDIAN)
* SHA2_USE_INTTYPES_H option:
By default, this code uses u_intXX_t data types for 8 bit, 32 bit, and
64 bit unsigned integer type definitions. Most BSD systems define these,
as does Linux. However, some (like Compaq's Tru64 Unix) may instead
use uintXX_t data types as defined by recent ANSI C standards and as
included in the inttypes.h header file. Those wanting to use inttypes.h
need to define this either in sha.h or at compile time.
On those systems where NEITHER definitions are available, you will need
to edit both sha2.h and sha2.c and define things by hand in the appropriate
sections.
* BYTE_ORDER definitions:
This code assumes that BYTE_ORDER will be defined by the system during
compile to either equal LITTLE_ENDIAN or BIG_ENDIAN. If your system
does not define these, you may need to define them by hand in the sha.c
file according to the byte ordering conventions of your system.
* SHA2_USE_MEMSET_MEMCPY or SHA2_USE_BZERO_BCOPY
The code in sha2.c can use either memset()/memcpy() for memory block
operations, or bzero()/mcopy(). If you define neither of these, the
code will default to memset()/memcpy(). You can define either at the
command line or in sha2.h or in sha2.c.
* SHA2_UNROLL_TRANSFORM
By defining this either on the command line or in sha2.h or sha2.c,
the code will use macros to partially "unroll" the SHA transform
function. This usually generates bigger executables. It CAN (but
not necessarily WILL) generate faster code when you tell your compiler
to optimize things. For example, on the FreeBSD and Linux x86 systems
I tested things on (using gcc), when I optimized with just -O2 and
unrolled the transform, the hash transform was faster by 15-30%. On
these same systems, if I did NO optimization, the unrolled transform
was SLOWER, much slower (I'm guessing because the code was breaking
the cache, but I'm not sure). Your mileage may vary.
PORTABILITY:
The code in sha2.c and sha2.h is intended to be portable. It may
require that you do a few #definitions in the .h file. I've successfully
compiled and tested the sha2.c and sha2.h code on Apple's OS X (on
a PPC), FreeBSD 4.1.1 on Intel, Linux on Intel, FreeBSD on the Alpha,
and even under Windows98SE using Metrowerks C. The utility/example
programs (sha2prog.c, sha2test.c, and sha2speed.c) will very likely
have more trouble in portability since they do I/O.
To get sha2.c/sha2.h working under Windows, I had to define
SHA2_USE_INTTYPES_H, BYTE_ORDER, LITTLE_ENDIAN, and had to comment
out the include of <sys/types.h> in sha2.h. With a bit more work
I got the test program to run and verified that all the test
cases passed.
SUGGESTIONS/BUG FIXES:
If you make changes to get it working on other architectures, if you fix
any bugs, or if you make changes that improve this implementation's
efficiency that would be relatively portable and you're willing to release
your changes under the same license, please send them to me for possible
inclusion in future versions.
If you know where I can find some additional test vectors, please let me
know.
CHANGE HISTORY:
0.8 to 0.9 - Fixed spelling errors, changed to u_intXX_t type usage,
removed names from prototypes, added prototypes to sha2.c,
and a few things I can't recall.
0.9 to 0.9.5 - Add a new define in sha2.c that permits one to compile
it to either use memcpy()/memset() or bcopy()/bzero()
for memory block copying and zeroing. Added support
for unrolled SHA-256/384/512 transform loops. Just
compile with SHA2_UNROLL_TRANSFORM to enable. It takes
longer to compile, but I hope it is a bit faster. I
need to do some test to see whether or not it is. Oh,
in sha2.c, you either need to define SHA2_USE_BZERO_BCOPY
or SHA2_USE_MEMSET_MEMCPY to choose which way you want
to compile. *Whew* It's amazing how quickly something
simple starts to grow more complex even in the span of
just a few hours. I didn't really intend to do this much.
0.9.5 to 0.9.6 - Added a test program (sha2test) which tests against several
known test vectors. WARNING: Some of the test output
hashes are NOT from NIST's documentation and are the
output of this implementation and so may be incorrect.
0.9.6 to 0.9.7 - Fixed a bug that could cause invalid output in certain
cases and added an assumed scenario where zero-length
data is hashed. Also changed the rotation macros to use
a temporary variable as this reduces the number of operations.
When data is fed in blocks of the right length, copying of
data is reduced in this version. Added SHAYXZ_Data()
functions for ease of hashing a set of data. Added another
file sha2speed.c for doing speed testing. Added another test
vector with a larger data size (16KB). Fixed u_intXX_t and
uintXX_t handling by adding a define for SHA2_USE_INTTYPES_H
as well as made a few other minor changes to get rid of
warnings when compiling on Compaq's Tru64 Unix.
0.9.7 to 0.9.8 - The bug fix in 0.9.7 was incomplete and in some cases made
things worse. I believe that 0.9.8 fixes the bug completely
so that output is correct. I cannot verify this, however,
because of the lack of test vectors against which to do such
verification. All versions correctly matched the very few
NIST-provided vectors, but unfortunately the bug only
appeared in longer message data sets.
0.9.8 to 0.9.9 - Fixed some really bad typos and mistakes on my part that
only affected big-endian systems. I didn't have direct
access for testing before this version. Thanks to
Lucas Marshall for giving me access to his OS X system.
0.9.9 to 1.0.0b1 Added a few more test samples and made a few changes to
make things easier compiling on several other platforms.
Also I experimented with alternate macro definitions
in the SHA2_UNROLL_TRANSFORM version (see sha2.slower.c)
and eliminated the T1 temporary variable (the compiler
would of course still use internal temporary storage
during expression evaluation, but I'd hoped the compiler
would be more efficient), but unfortunately under FreeBSD
4.1.1-STABLE on an x86 platform, the change slowed things
down.
1.0.0b1 to 1.0 RELEASE Fixed an off-by-one implementation bug that affected
SHA-256 when hashed data length L = 55 + 64 * X where X is
either zero or a positive integer, and another (basically
the same bug) bug in SHA-384 and SHA-512 that showed up when
hashed data lengths L = 111 + 128 * X. Thanks to Rogier
van de Pol for sending me test data that revealed the bug.
The fix was very simple (just two tiny changes). Also,
I finally put the files into RCS so future changes will be
easier to manage. The sha2prog.c file was rewritten to
be more useful to me, and I got rid of the old C testing
program and now use a perl script with a subdirectory full
of test data. It's a more flexible test system.
LATEST VERSION:
The latest version and documentation (if any ;) should always be available
on the web at:
http://www.aarongifford.com/computers/sha.html
CONTACT ME:
I can be reached via email at:
Aaron Gifford <m e @ a a r o n g i f f o r d . c o m>
Please don't send support questions. I don't have the time to answer and
they'll probably be ignored. Bug fixes, or patches that add something useful
will be gratefully accepted, however.
If you use this implementation, I would enjoy getting a brief email message
letting me know who you are and what use to which it is being put. There
is no requirement to do so. I just think it would be fun.
EXAMPLES:
Here's an example of compiling and using the sha2 program (in this example
I build it using the unrolled transform version with -O2 optimizations),
and then running the perl testing script:
cc -O2 -DSHA2_UNROLL_TRANSFORM -Wall -o sha2 sha2prog.c sha2.c
% ./sha2test.pl
[most of the perl script output deleted for brevity]
===== RESULTS (18 VECTOR DATA FILES HASHED) =====
HASH TYPE NO. OF TESTS PASSED FAILED
--------- ------------ ------ ------
SHA-256 18 18 0
SHA-384 18 18 0
SHA-512 18 18 0
----------------------------------------------
TOTAL: 54 54 0
NO ERRORS! ALL TESTS WERE SUCCESSFUL!
ALL TEST VECTORS PASSED!
That's all folks! Have fun!
Aaron out.

1065
engine/libraries/sha2/sha2.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,197 @@
/*
* FILE: sha2.h
* AUTHOR: Aaron D. Gifford - http://www.aarongifford.com/
*
* Copyright (c) 2000-2001, Aaron D. Gifford
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holder nor the names of contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTOR(S) ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTOR(S) BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: sha2.h,v 1.1 2001/11/08 00:02:01 adg Exp adg $
*/
#ifndef __SHA2_H__
#define __SHA2_H__
#ifdef __cplusplus
extern "C" {
#endif
/*
* Import u_intXX_t size_t type definitions from system headers. You
* may need to change this, or define these things yourself in this
* file.
*/
#include <sys/types.h>
#ifdef SHA2_USE_INTTYPES_H
#include <inttypes.h>
#endif /* SHA2_USE_INTTYPES_H */
/*** SHA-256/384/512 Various Length Definitions ***********************/
#define SHA256_BLOCK_LENGTH 64
#define SHA256_DIGEST_LENGTH 32
#define SHA256_DIGEST_STRING_LENGTH (SHA256_DIGEST_LENGTH * 2 + 1)
#define SHA384_BLOCK_LENGTH 128
#define SHA384_DIGEST_LENGTH 48
#define SHA384_DIGEST_STRING_LENGTH (SHA384_DIGEST_LENGTH * 2 + 1)
#define SHA512_BLOCK_LENGTH 128
#define SHA512_DIGEST_LENGTH 64
#define SHA512_DIGEST_STRING_LENGTH (SHA512_DIGEST_LENGTH * 2 + 1)
/*** SHA-256/384/512 Context Structures *******************************/
/* NOTE: If your architecture does not define either u_intXX_t types or
* uintXX_t (from inttypes.h), you may need to define things by hand
* for your system:
*/
#if 0
typedef unsigned char u_int8_t; /* 1-byte (8-bits) */
typedef unsigned int u_int32_t; /* 4-bytes (32-bits) */
typedef unsigned long long u_int64_t; /* 8-bytes (64-bits) */
#endif
/*
* Most BSD systems already define u_intXX_t types, as does Linux.
* Some systems, however, like Compaq's Tru64 Unix instead can use
* uintXX_t types defined by very recent ANSI C standards and included
* in the file:
*
* #include <inttypes.h>
*
* If you choose to use <inttypes.h> then please define:
*
* #define SHA2_USE_INTTYPES_H
*
* Or on the command line during compile:
*
* cc -DSHA2_USE_INTTYPES_H ...
*/
#ifdef SHA2_USE_INTTYPES_H
typedef struct _SHA256_CTX {
uint32_t state[8];
uint64_t bitcount;
uint8_t buffer[SHA256_BLOCK_LENGTH];
} SHA256_CTX;
typedef struct _SHA512_CTX {
uint64_t state[8];
uint64_t bitcount[2];
uint8_t buffer[SHA512_BLOCK_LENGTH];
} SHA512_CTX;
#else /* SHA2_USE_INTTYPES_H */
typedef struct _SHA256_CTX {
u_int32_t state[8];
u_int64_t bitcount;
u_int8_t buffer[SHA256_BLOCK_LENGTH];
} SHA256_CTX;
typedef struct _SHA512_CTX {
u_int64_t state[8];
u_int64_t bitcount[2];
u_int8_t buffer[SHA512_BLOCK_LENGTH];
} SHA512_CTX;
#endif /* SHA2_USE_INTTYPES_H */
typedef SHA512_CTX SHA384_CTX;
/*** SHA-256/384/512 Function Prototypes ******************************/
#ifndef NOPROTO
#ifdef SHA2_USE_INTTYPES_H
void SHA256_Init(SHA256_CTX *);
void SHA256_Update(SHA256_CTX*, const uint8_t*, size_t);
void SHA256_Final(uint8_t[SHA256_DIGEST_LENGTH], SHA256_CTX*);
char* SHA256_End(SHA256_CTX*, char[SHA256_DIGEST_STRING_LENGTH]);
char* SHA256_Data(const uint8_t*, size_t, char[SHA256_DIGEST_STRING_LENGTH]);
void SHA384_Init(SHA384_CTX*);
void SHA384_Update(SHA384_CTX*, const uint8_t*, size_t);
void SHA384_Final(uint8_t[SHA384_DIGEST_LENGTH], SHA384_CTX*);
char* SHA384_End(SHA384_CTX*, char[SHA384_DIGEST_STRING_LENGTH]);
char* SHA384_Data(const uint8_t*, size_t, char[SHA384_DIGEST_STRING_LENGTH]);
void SHA512_Init(SHA512_CTX*);
void SHA512_Update(SHA512_CTX*, const uint8_t*, size_t);
void SHA512_Final(uint8_t[SHA512_DIGEST_LENGTH], SHA512_CTX*);
char* SHA512_End(SHA512_CTX*, char[SHA512_DIGEST_STRING_LENGTH]);
char* SHA512_Data(const uint8_t*, size_t, char[SHA512_DIGEST_STRING_LENGTH]);
#else /* SHA2_USE_INTTYPES_H */
void SHA256_Init(SHA256_CTX *);
void SHA256_Update(SHA256_CTX*, const u_int8_t*, size_t);
void SHA256_Final(u_int8_t[SHA256_DIGEST_LENGTH], SHA256_CTX*);
char* SHA256_End(SHA256_CTX*, char[SHA256_DIGEST_STRING_LENGTH]);
char* SHA256_Data(const u_int8_t*, size_t, char[SHA256_DIGEST_STRING_LENGTH]);
void SHA384_Init(SHA384_CTX*);
void SHA384_Update(SHA384_CTX*, const u_int8_t*, size_t);
void SHA384_Final(u_int8_t[SHA384_DIGEST_LENGTH], SHA384_CTX*);
char* SHA384_End(SHA384_CTX*, char[SHA384_DIGEST_STRING_LENGTH]);
char* SHA384_Data(const u_int8_t*, size_t, char[SHA384_DIGEST_STRING_LENGTH]);
void SHA512_Init(SHA512_CTX*);
void SHA512_Update(SHA512_CTX*, const u_int8_t*, size_t);
void SHA512_Final(u_int8_t[SHA512_DIGEST_LENGTH], SHA512_CTX*);
char* SHA512_End(SHA512_CTX*, char[SHA512_DIGEST_STRING_LENGTH]);
char* SHA512_Data(const u_int8_t*, size_t, char[SHA512_DIGEST_STRING_LENGTH]);
#endif /* SHA2_USE_INTTYPES_H */
#else /* NOPROTO */
void SHA256_Init();
void SHA256_Update();
void SHA256_Final();
char* SHA256_End();
char* SHA256_Data();
void SHA384_Init();
void SHA384_Update();
void SHA384_Final();
char* SHA384_End();
char* SHA384_Data();
void SHA512_Init();
void SHA512_Update();
void SHA512_Final();
char* SHA512_End();
char* SHA512_Data();
#endif /* NOPROTO */
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* __SHA2_H__ */

View File

@ -12,6 +12,7 @@ SET ( TESTS_SRCS
EventBaseTests.cc
PhysicsTests.cc
ControllerBaseTests.cc
UtilsTests.cc
)
FIND_PACKAGE (UnitTest++)

Binary file not shown.

204
server/highscore.php Normal file
View File

@ -0,0 +1,204 @@
<?php
$database_file = './data/global_highscore.db';
$submission_salt = hash ("sha256", "asteroids rule");
$player_name = "";
$score_value = 0;
$key = "";
$valid_name_characters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890-_!. ";
$raw_format = false;
if (isset ($_REQUEST["format"])) {
if ($_REQUEST["format"] == "raw") {
$raw_format = true;
}
}
function print_raw_scores () {
global $database_file;
try {
$db = new SQlite3($database_file);
} catch (Exception $e) {
print ("<h3>[Error] " . $e->getMessage() . "</h3>\n");
die();
}
$query = $db->query('SELECT * FROM submissions ORDER BY score_value DESC LIMIT 10');
while ($row = $query->fetchArray(SQLITE3_ASSOC)) {
print ($row['player_name'] . "\t" . $row['score_value'] . "\n");
}
$db->close();
die();
}
function print_scores () {
global $database_file;
try {
$db = new SQlite3($database_file);
} catch (Exception $e) {
print ("<h3>[Error] " . $e->getMessage() . "</h3>\n");
die();
}
$query = $db->query('SELECT * FROM submissions ORDER BY score_value DESC');
print ("<table border=1>\n");
print ("<tr><td>id</td><td>playername</td><td>score</td><td>date</td><td>ip</td></tr>\n");
while ($row = $query->fetchArray(SQLITE3_ASSOC)) {
print ("<tr>");
print ("<td>" . $row['id'] . "</td>");
print ("<td>" . $row['player_name'] . "</td>");
print ("<td>" . $row['score_value'] . "</td>");
print ("<td>" . $row['date'] . "</td>");
print ("<td>" . $row['source_ip'] . "</td>");
print ("</tr>\n");
}
print ("</table>\n");
print ("</br>\n");
$db->close();
}
function check_is_submission () {
global $player_name, $score_value, $key, $valid_name_characters, $raw_format;
if (isset ($_REQUEST["player_name"])
&& isset ($_REQUEST["score_value"])
&& isset ($_REQUEST["key"] )) {
$player_name = $_REQUEST["player_name"];
// check whether the name only contains valid characters
foreach (str_split ($player_name) as $c) {
if (strpos ($valid_name_characters, $c) === FALSE) {
if ($raw_format) {
print ("ERROR: Invalid characters found in name!");
die();
}
print ("<h3>ERROR: Invalid characters found in name!</h3>");
return false;
}
}
$score_value = (int) $_REQUEST["score_value"];
$key = $_REQUEST["key"];
return true;
}
return false;
}
function validate_submission () {
if (!check_is_submission()) {
return false;
}
global $player_name, $score_value, $key, $submission_salt, $raw_format;
$verification_string = $player_name . ":" . (int) $score_value . ":" . $submission_salt;
$verification_hash = hash ("sha256", $verification_string);
if ($verification_hash == $key) {
return true;
}
if (!$raw_format)
print ("verification_hash = " . $verification_hash . "</br>\n");
return false;
}
function dispatch_submission () {
if (!validate_submission()) {
die ("This is not a valid submission!");
}
global $database_file, $player_name, $score_value, $raw_format;
try {
$db = new SQlite3($database_file, SQLITE3_OPEN_READWRITE);
} catch (Exception $e) {
print ("ERROR: " . $e->getMessage() . "</h3>\n");
die();
}
// check whether we already have an entry with the same data
$query = $db->query('SELECT * FROM submissions WHERE player_name="' . $player_name . '" AND score_value=' . $score_value . ';');
// if it already exists we just return as if it was accepted
if ($query->fetchArray()) {
if ($raw_format) {
print ("OK\n");
die();
} else {
print ("<h3>OK</h3>\n");
return;
}
}
while ($row = $query->fetchArray(SQLITE3_ASSOC)) {
print ($row['player_name'] . "\t" . $row['score_value'] . "\n");
}
$submit_statement = 'INSERT INTO submissions (player_name, score_value, date, source_ip)
VALUES (\'' . $player_name . '\', ' . (int) $score_value . ', DATETIME(\'NOW\'), \'' . $_SERVER['REMOTE_ADDR'] . '\');';
$result = $db->exec($submit_statement);
if ($result) {
if ($raw_format)
print ("OK\n");
else
print ("<h3>OK</h3>\n");
} else {
if ($raw_format)
print ("ERROR: Database error when submitting value\n");
else
print ("<h3>ERROR: Database error when submitting value</h3>\n");
}
$db->close();
}
if ($raw_format) {
if (check_is_submission()) {
if (validate_submission()) {
dispatch_submission();
} else {
print ("ERROR: invalid submission!");
}
} else {
print_raw_scores();
}
die();
}
print ("<h1>Asteroids Highscores</h1>\n");
print_scores();
if (check_is_submission()) {
print ("player_name = " . $player_name . "</br>\n");
print ("score_value = " . $score_value . "</br>\n");
print ("key = " . $key . "</br>\n");
dispatch_submission();
}
?>
<h2>Submit Entry</h2>
<form action="highscore.php" method="post">
<table>
<tr><td>Name:</td><td><input type="text" name="player_name" /></td></tr>
<tr><td>Score:</td><td><input type="text" name="score_value" /></td></tr>
<tr><td>Key:</td><td><input type="text" name="key" /></td></tr>
</table>
<input type="submit" />
</form>