highscores can now be submitted to and retrieved from a server
parent
f57a4e9fb9
commit
21239c9962
|
@ -9,8 +9,6 @@ namespace asteroids {
|
||||||
int Controller::OnInit (int argc, char *argv[]) {
|
int Controller::OnInit (int argc, char *argv[]) {
|
||||||
Engine::ControllerBase::OnInit (argc, argv);
|
Engine::ControllerBase::OnInit (argc, argv);
|
||||||
|
|
||||||
mBindings[SDLK_q] = "quit";
|
|
||||||
|
|
||||||
mBindings[SDLK_UP] = "+forward";
|
mBindings[SDLK_UP] = "+forward";
|
||||||
mBindings[SDLK_LEFT] = "+turnleft";
|
mBindings[SDLK_LEFT] = "+turnleft";
|
||||||
mBindings[SDLK_RIGHT] = "+turnright";
|
mBindings[SDLK_RIGHT] = "+turnright";
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <boost/filesystem.hpp>
|
#include <boost/filesystem.hpp>
|
||||||
|
#include <SDL/SDL_net.h>
|
||||||
|
|
||||||
#include "Model.h"
|
#include "Model.h"
|
||||||
#include "Physics.h"
|
#include "Physics.h"
|
||||||
|
@ -17,6 +18,10 @@ namespace asteroids {
|
||||||
|
|
||||||
static Model* ModelInstance = NULL;
|
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
|
* Inherited Module functions
|
||||||
*/
|
*/
|
||||||
|
@ -40,20 +45,20 @@ int Model::OnInit (int argc, char* argv[]) {
|
||||||
// First we reset the highscore list
|
// First we reset the highscore list
|
||||||
mHighscoreList.clear();
|
mHighscoreList.clear();
|
||||||
// then we try to load values from the file
|
// 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 we have less than the usual number of entries we add default values
|
||||||
if (mHighscoreList.size() < 10) {
|
if (mHighscoreList.size() < 10) {
|
||||||
AddHighscoreEntry ("Imperator", 1000000);
|
AddLocalHighscoreEntry ("Imperator", 1000000);
|
||||||
AddHighscoreEntry ("Darth Vader", 800000);
|
AddLocalHighscoreEntry ("Darth Vader", 800000);
|
||||||
AddHighscoreEntry ("Luke Skywalker", 600000);
|
AddLocalHighscoreEntry ("Luke Skywalker", 600000);
|
||||||
AddHighscoreEntry ("Han Solo", 400000);
|
AddLocalHighscoreEntry ("Han Solo", 400000);
|
||||||
AddHighscoreEntry ("Princess Leia", 200000);
|
AddLocalHighscoreEntry ("Princess Leia", 200000);
|
||||||
AddHighscoreEntry ("C3PO", 100000);
|
AddLocalHighscoreEntry ("C3PO", 100000);
|
||||||
AddHighscoreEntry ("R2-D2", 50000);
|
AddLocalHighscoreEntry ("R2-D2", 50000);
|
||||||
AddHighscoreEntry ("Chewy", 10000);
|
AddLocalHighscoreEntry ("Chewy", 10000);
|
||||||
AddHighscoreEntry ("Mr. Ewok", 5000);
|
AddLocalHighscoreEntry ("Mr. Ewok", 5000);
|
||||||
AddHighscoreEntry ("Jabba the Hutt", 1000);
|
AddLocalHighscoreEntry ("Jabba the Hutt", 1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reset the newest highscore entry index which may be used for highlighting
|
// Reset the newest highscore entry index which may be used for highlighting
|
||||||
|
@ -69,12 +74,28 @@ int Model::OnInit (int argc, char* argv[]) {
|
||||||
mLevelAuthor = "";
|
mLevelAuthor = "";
|
||||||
mLevelTitle = "";
|
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, EventAccelerateStart);
|
||||||
Engine::RegisterListener (this, EventAccelerateStop);
|
Engine::RegisterListener (this, EventAccelerateStop);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Model::OnDestroy() {
|
||||||
|
Engine::ModelBase::OnDestroy();
|
||||||
|
mAsteroids.clear();
|
||||||
|
mLevelList.clear();
|
||||||
|
SaveLocalHighscoreList();
|
||||||
|
|
||||||
|
SDLNet_Quit();
|
||||||
|
}
|
||||||
|
|
||||||
bool Model::OnReceiveEvent (const Engine::EventBasePtr &event) {
|
bool Model::OnReceiveEvent (const Engine::EventBasePtr &event) {
|
||||||
switch (event->mEventType) {
|
switch (event->mEventType) {
|
||||||
case EventAccelerateStart:
|
case EventAccelerateStart:
|
||||||
|
@ -151,27 +172,13 @@ unsigned int Model::InitLevelList () {
|
||||||
return mLevelList.size();
|
return mLevelList.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Model::LoadHighscoreList () {
|
void Model::ParseHighscoreStream (std::istream &highscore_stream) {
|
||||||
Engine::LogDebug ("Loading highscore file");
|
std::string line;
|
||||||
boost::filesystem::path highscore_file(Engine::GetUserDirFullPath("/highscore.dat"));
|
|
||||||
|
|
||||||
// if the file does not exist, we create it and write standard values into
|
while (getline(highscore_stream, line)) {
|
||||||
// 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()) {
|
|
||||||
std::string name;
|
std::string name;
|
||||||
unsigned int points;
|
unsigned int points;
|
||||||
|
|
||||||
std::string line;
|
|
||||||
getline (score_stream, line);
|
|
||||||
|
|
||||||
std::string::size_type delimiter = line.find ('\t');
|
std::string::size_type delimiter = line.find ('\t');
|
||||||
if (delimiter == std::string::npos)
|
if (delimiter == std::string::npos)
|
||||||
break;
|
break;
|
||||||
|
@ -182,11 +189,48 @@ void Model::LoadHighscoreList () {
|
||||||
points_stream >> points;
|
points_stream >> points;
|
||||||
|
|
||||||
Engine::LogDebug ("Read Highscore Entry Name: %s Points: %d", name.c_str(), 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::ofstream highscore_file (Engine::GetUserDirFullPath("/highscore.dat").c_str());
|
||||||
|
|
||||||
std::list<HighscoreEntry>::iterator iter = mHighscoreList.begin();
|
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
|
* \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;
|
HighscoreEntry entry;
|
||||||
entry.name = name;
|
entry.name = name;
|
||||||
entry.points = points;
|
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
|
// if we have all 10 entries then we can save
|
||||||
// the highscore
|
// the highscore
|
||||||
SaveHighscoreList();
|
SaveLocalHighscoreList();
|
||||||
|
|
||||||
mNewestHighscoreEntryIndex = 99999;
|
mNewestHighscoreEntryIndex = 99999;
|
||||||
|
|
||||||
return 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) {
|
int Model::DoLoadLevel (const char* filename) {
|
||||||
Engine::LogMessage ("Loading level from %s", filename);
|
Engine::LogMessage ("Loading level from %s", filename);
|
||||||
std::fstream level_file (filename, std::ios::in);
|
std::fstream level_file (filename, std::ios::in);
|
||||||
|
@ -403,11 +626,11 @@ void Model::SetGameState (const unsigned int &state) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Model::OnGameOver() {
|
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) {
|
if (mPoints > mHighscoreList.back().points) {
|
||||||
Engine::LogMessage ("New Highscore!");
|
Engine::LogMessage ("New Highscore!");
|
||||||
AddHighscoreEntry (mPlayerName, mPoints);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
@ -425,7 +648,7 @@ void Model::OnNewGame() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Model::OnShipExplode () {
|
void Model::OnShipExplode () {
|
||||||
Engine::PlaySound(Engine::GetResourceFullPath("/data/sounds/rock_destroyed.wav"));
|
Engine::PlaySound(Engine::GetResourceFullPath("/data/sounds/ship_destroyed.wav"));
|
||||||
|
|
||||||
mPlayerLives --;
|
mPlayerLives --;
|
||||||
|
|
||||||
|
|
|
@ -63,22 +63,22 @@ class Model : public Engine::ModelBase {
|
||||||
unsigned int points;
|
unsigned int points;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void ParseHighscoreStream (std::istream &highscore_stream);
|
||||||
void LoadHighscoreList ();
|
void LoadHighscoreList ();
|
||||||
void SaveHighscoreList ();
|
bool PullGlobalHighscore (std::stringstream &highscore_stream);
|
||||||
unsigned int AddHighscoreEntry(const std::string &name, const unsigned int points);
|
bool SubmitGlobalHigscoreEntry (const std::string &name, const unsigned int points);
|
||||||
bool HighscoreCmp (HighscoreEntry a, HighscoreEntry b);
|
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;
|
std::list<HighscoreEntry> mHighscoreList;
|
||||||
unsigned int mNewestHighscoreEntryIndex;
|
unsigned int mNewestHighscoreEntryIndex;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/** \brief Initializes the system */
|
/** \brief Initializes the system */
|
||||||
virtual int OnInit (int argc, char* argv[]);
|
virtual int OnInit (int argc, char* argv[]);
|
||||||
virtual void OnDestroy() {
|
virtual void OnDestroy();
|
||||||
Engine::ModelBase::OnDestroy();
|
|
||||||
mAsteroids.clear();
|
|
||||||
mLevelList.clear();
|
|
||||||
SaveHighscoreList();
|
|
||||||
};
|
|
||||||
virtual void OnRegisterCommands ();
|
virtual void OnRegisterCommands ();
|
||||||
|
|
||||||
virtual void OnCreateEntity (const int type, const unsigned int id);
|
virtual void OnCreateEntity (const int type, const unsigned int id);
|
||||||
|
@ -100,6 +100,11 @@ class Model : public Engine::ModelBase {
|
||||||
std::string mLevelAuthor;
|
std::string mLevelAuthor;
|
||||||
std::string mLevelTitle;
|
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);
|
virtual bool OnReceiveEvent (const Engine::EventBasePtr &event);
|
||||||
|
|
||||||
friend class View;
|
friend class View;
|
||||||
|
|
|
@ -710,8 +710,8 @@ void View::DrawUiHighscore() {
|
||||||
while (highscore_iter != GetModel()->mHighscoreList.end()) {
|
while (highscore_iter != GetModel()->mHighscoreList.end()) {
|
||||||
// Check whether we have to highlight an entry (such as when entering
|
// Check whether we have to highlight an entry (such as when entering
|
||||||
// the name)
|
// the name)
|
||||||
if (GetModel()->mNewestHighscoreEntryIndex < GetModel()->mHighscoreList.size()
|
if (GetModel()->GetPlayerName() == highscore_iter->name
|
||||||
&& GetModel()->mNewestHighscoreEntryIndex == i) {
|
&& GetModel()->GetPoints() == highscore_iter->points) {
|
||||||
// we highlight the newest entry
|
// we highlight the newest entry
|
||||||
SelectFont("console.ttf color=#e8d500 size=23");
|
SelectFont("console.ttf color=#e8d500 size=23");
|
||||||
} else {
|
} else {
|
||||||
|
@ -726,7 +726,8 @@ void View::DrawUiHighscore() {
|
||||||
highscore_iter++;
|
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();
|
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();
|
PopViewState();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -773,7 +775,7 @@ _Music\r\
|
||||||
DJad - Space Exploration\r\
|
DJad - Space Exploration\r\
|
||||||
\r\
|
\r\
|
||||||
_Sounds\r\
|
_Sounds\r\
|
||||||
Marcus Zetterquist\r\
|
Martin Felis\r\
|
||||||
\r\
|
\r\
|
||||||
_Libraries\r\
|
_Libraries\r\
|
||||||
libSDL\r\
|
libSDL\r\
|
||||||
|
@ -782,11 +784,15 @@ _Libraries\r\
|
||||||
freetype2\r\
|
freetype2\r\
|
||||||
boost\r\
|
boost\r\
|
||||||
libpng\r\
|
libpng\r\
|
||||||
|
\r\
|
||||||
|
Aaron D. Gifford's sha2 code\r\
|
||||||
\r\
|
\r\
|
||||||
_Tools\r\
|
_Tools\r\
|
||||||
GIMP\r\
|
GIMP\r\
|
||||||
Blender\r\
|
Blender\r\
|
||||||
CMake\r\
|
CMake\r\
|
||||||
|
sfxr-sdl\r\
|
||||||
|
Audacity\r\
|
||||||
\r\
|
\r\
|
||||||
_Special Thanks\r\
|
_Special Thanks\r\
|
||||||
to my wonderful wife Katrina\r\
|
to my wonderful wife Katrina\r\
|
||||||
|
@ -795,7 +801,6 @@ _Special Thanks\r\
|
||||||
\r\
|
\r\
|
||||||
\r\
|
\r\
|
||||||
\r\
|
\r\
|
||||||
\r\
|
|
||||||
_http://www.fysx.org\r\
|
_http://www.fysx.org\r\
|
||||||
\r\
|
\r\
|
||||||
\r\
|
\r\
|
||||||
|
@ -804,6 +809,7 @@ _http://www.fysx.org\r\
|
||||||
\r\
|
\r\
|
||||||
\r\
|
\r\
|
||||||
\r\
|
\r\
|
||||||
|
\r\
|
||||||
:created with vim.\r\
|
:created with vim.\r\
|
||||||
::wq\r\
|
::wq\r\
|
||||||
\r\
|
\r\
|
||||||
|
@ -876,7 +882,9 @@ void View::DrawUiEnterPlayername() {
|
||||||
SelectFont("console.ttf size=23");
|
SelectFont("console.ttf size=23");
|
||||||
Engine::GUI::Label (1, "Enter your name: ", screen_right * 0.5 - 220, 250);
|
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);
|
GetModel()->SetPlayerName(player_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -887,7 +895,8 @@ void View::DrawUiEnterPlayername() {
|
||||||
GetModel()->SetGameState(GameStateRunning);
|
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();
|
PopViewState();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
#include "Model.h"
|
#include "Model.h"
|
||||||
#include "Physics.h"
|
#include "Physics.h"
|
||||||
#include "EntityFactory.h"
|
#include "EntityFactory.h"
|
||||||
|
#include "Game.h"
|
||||||
|
|
||||||
#include <boost/filesystem.hpp>
|
#include <boost/filesystem.hpp>
|
||||||
|
|
||||||
|
@ -164,12 +165,15 @@ int main (int argc, char* argv[]) {
|
||||||
|
|
||||||
Engine::PlayMusic (Engine::GetResourceFullPath("/data/sounds/intro_music.ogg"));
|
Engine::PlayMusic (Engine::GetResourceFullPath("/data/sounds/intro_music.ogg"));
|
||||||
|
|
||||||
|
asteroids::GetModel()->LoadHighscoreList();
|
||||||
|
|
||||||
engine.MainLoop ();
|
engine.MainLoop ();
|
||||||
|
|
||||||
// save the configuration
|
// save the configuration
|
||||||
std::ofstream config_file (engine.GetUserDirFullPath("/config.rc").c_str());
|
std::ofstream config_file (engine.GetUserDirFullPath("/config.rc").c_str());
|
||||||
config_file << "set effects_volume " << Engine::GetEffectsVolume() << std::endl;
|
config_file << "set effects_volume " << Engine::GetEffectsVolume() << std::endl;
|
||||||
config_file << "set music_volume " << Engine::GetMusicVolume() << 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();
|
config_file.close();
|
||||||
|
|
||||||
SDL_WM_SetIcon(NULL,NULL);
|
SDL_WM_SetIcon(NULL,NULL);
|
||||||
|
|
|
@ -4,6 +4,7 @@ LIST( APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/CMake )
|
||||||
|
|
||||||
FIND_PACKAGE (SDL REQUIRED)
|
FIND_PACKAGE (SDL REQUIRED)
|
||||||
FIND_PACKAGE (SDL_mixer REQUIRED)
|
FIND_PACKAGE (SDL_mixer REQUIRED)
|
||||||
|
FIND_PACKAGE (SDL_net REQUIRED)
|
||||||
FIND_PACKAGE (OpenGL REQUIRED)
|
FIND_PACKAGE (OpenGL REQUIRED)
|
||||||
FIND_PACKAGE (PNG REQUIRED)
|
FIND_PACKAGE (PNG REQUIRED)
|
||||||
FIND_PACKAGE (FreeType2 REQUIRED)
|
FIND_PACKAGE (FreeType2 REQUIRED)
|
||||||
|
@ -43,10 +44,12 @@ SET ( ENGINE_SRCS
|
||||||
INCLUDE_DIRECTORIES (
|
INCLUDE_DIRECTORIES (
|
||||||
${Boost_INCLUDE_DIRS}
|
${Boost_INCLUDE_DIRS}
|
||||||
${SDLMIXER_INCLUDE_DIRS}
|
${SDLMIXER_INCLUDE_DIRS}
|
||||||
|
${SDLNET_INCLUDE_DIRS}
|
||||||
${PROJECT_SOURCE_DIR}
|
${PROJECT_SOURCE_DIR}
|
||||||
libraries/mathlib/
|
libraries/mathlib/
|
||||||
libraries/coll2d/include
|
libraries/coll2d/include
|
||||||
libraries/oglft/liboglft
|
libraries/oglft/liboglft
|
||||||
|
libraries/sha2/
|
||||||
${FREETYPE2_INCLUDE_DIR}
|
${FREETYPE2_INCLUDE_DIR}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -55,12 +58,14 @@ ADD_LIBRARY ( Engine STATIC ${ENGINE_SRCS} )
|
||||||
TARGET_LINK_LIBRARIES ( Engine
|
TARGET_LINK_LIBRARIES ( Engine
|
||||||
${SDL_LIBRARY}
|
${SDL_LIBRARY}
|
||||||
${SDLMIXER_LIBRARY}
|
${SDLMIXER_LIBRARY}
|
||||||
|
${SDLNET_LIBRARY}
|
||||||
${OPENGL_LIBRARIES}
|
${OPENGL_LIBRARIES}
|
||||||
${PNG_LIBRARIES}
|
${PNG_LIBRARIES}
|
||||||
${Boost_LIBRARIES}
|
${Boost_LIBRARIES}
|
||||||
mathlib
|
mathlib
|
||||||
oglft
|
oglft
|
||||||
coll2d
|
coll2d
|
||||||
|
sha2
|
||||||
)
|
)
|
||||||
|
|
||||||
ADD_SUBDIRECTORY ( tests )
|
ADD_SUBDIRECTORY ( tests )
|
||||||
|
|
|
@ -37,6 +37,8 @@ int Engine::OnInit (int argc, char* argv[]) {
|
||||||
EngineInstance = this;
|
EngineInstance = this;
|
||||||
mStatus = EngineStatusUndefined;
|
mStatus = EngineStatusUndefined;
|
||||||
|
|
||||||
|
/* Phase 0: Logging, Events, Variables, Commands, SDL */
|
||||||
|
|
||||||
/* Initialization of the base modules */
|
/* Initialization of the base modules */
|
||||||
if (mLogging == NULL)
|
if (mLogging == NULL)
|
||||||
mLogging = new Logging ();
|
mLogging = new Logging ();
|
||||||
|
@ -77,6 +79,13 @@ int Engine::OnInit (int argc, char* argv[]) {
|
||||||
}
|
}
|
||||||
SDL_WM_SetCaption("Engine Initializing","Engine Initializing");
|
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 */
|
/* Sound */
|
||||||
mSoundManager = new SoundBase();
|
mSoundManager = new SoundBase();
|
||||||
mSoundManager->Init (argc, argv);
|
mSoundManager->Init (argc, argv);
|
||||||
|
@ -96,7 +105,6 @@ int Engine::OnInit (int argc, char* argv[]) {
|
||||||
|
|
||||||
mModel->mEntityFactory = mEntityFactory;
|
mModel->mEntityFactory = mEntityFactory;
|
||||||
|
|
||||||
|
|
||||||
/* Physics */
|
/* Physics */
|
||||||
if (mPhysics == NULL) {
|
if (mPhysics == NULL) {
|
||||||
mPhysics = new PhysicsBase ();
|
mPhysics = new PhysicsBase ();
|
||||||
|
@ -142,10 +150,6 @@ int Engine::OnInit (int argc, char* argv[]) {
|
||||||
|
|
||||||
mController->Init (argc, argv);
|
mController->Init (argc, argv);
|
||||||
|
|
||||||
/* Now register the commands */
|
|
||||||
mLogging->RegisterCommands ();
|
|
||||||
mVariables->RegisterCommands ();
|
|
||||||
mCommands->RegisterCommands ();
|
|
||||||
|
|
||||||
mModel->mPhysics->RegisterCommands ();
|
mModel->mPhysics->RegisterCommands ();
|
||||||
mModel->RegisterCommands ();
|
mModel->RegisterCommands ();
|
||||||
|
|
|
@ -546,6 +546,151 @@ bool LineEdit (int id, int x, int y, std::string &text_value, const int &maxleng
|
||||||
return false;
|
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) {
|
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_width = 16;
|
||||||
const int knob_height = h * 2;
|
const int knob_height = h * 2;
|
||||||
|
|
|
@ -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 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);
|
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
|
/** \brief Checks whether a given key is currently pressed
|
||||||
|
|
|
@ -7,7 +7,12 @@
|
||||||
#include <boost/filesystem.hpp>
|
#include <boost/filesystem.hpp>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
|
|
||||||
|
#include <sha2.h>
|
||||||
|
|
||||||
std::string strip_whitespaces (const std::string input_str) {
|
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());
|
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);
|
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;
|
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);
|
||||||
|
}
|
||||||
|
|
|
@ -5,5 +5,6 @@
|
||||||
|
|
||||||
std::string strip_whitespaces (const std::string input_str);
|
std::string strip_whitespaces (const std::string input_str);
|
||||||
bool create_dir (const std::string &dir_str);
|
bool create_dir (const std::string &dir_str);
|
||||||
|
std::string sha256_hash (std::string input);
|
||||||
|
|
||||||
#endif /* _UTILS_H */
|
#endif /* _UTILS_H */
|
||||||
|
|
|
@ -63,6 +63,7 @@ Variable::Variable (const std::string &name, const std::string &value) {
|
||||||
mName = name;
|
mName = name;
|
||||||
mStringValue = value;
|
mStringValue = value;
|
||||||
mFloatValue = atof (value.c_str());
|
mFloatValue = atof (value.c_str());
|
||||||
|
mBoolValue = ParseBoolValue (value);
|
||||||
|
|
||||||
if (VariablesInstance == NULL) {
|
if (VariablesInstance == NULL) {
|
||||||
delayed_variables.push_back (this);
|
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) {
|
void Variable::RegisterVariable (const std::string &name) {
|
||||||
if (! VariablesInstance ) {
|
if (! VariablesInstance ) {
|
||||||
LogError ("Unable to register Variable '%s': Variables System not initialized!", name.c_str());
|
LogError ("Unable to register Variable '%s': Variables System not initialized!", name.c_str());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -89,6 +90,23 @@ void Variable::RegisterVariable (const std::string &name) {
|
||||||
VariablesInstance->RegisterVariable (name, this);
|
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
|
* Global functions
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -26,6 +26,7 @@ bool Cmd_Set (const std::vector<std::string> args) {
|
||||||
if (test) {
|
if (test) {
|
||||||
test->SetStringValue (args[1]);
|
test->SetStringValue (args[1]);
|
||||||
test->SetFloatValue (atof (args[1].c_str()));
|
test->SetFloatValue (atof (args[1].c_str()));
|
||||||
|
test->SetBoolValueFromString (args[1]);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -29,12 +29,22 @@ class Variable {
|
||||||
float& GetFloatValue () {
|
float& GetFloatValue () {
|
||||||
return mFloatValue;
|
return mFloatValue;
|
||||||
}
|
}
|
||||||
|
/** \brief Returns the float value of the Variable */
|
||||||
|
bool& GetBoolValue () {
|
||||||
|
return mBoolValue;
|
||||||
|
}
|
||||||
void SetStringValue (const std::string &value) {
|
void SetStringValue (const std::string &value) {
|
||||||
mStringValue = value;
|
mStringValue = value;
|
||||||
}
|
}
|
||||||
void SetFloatValue (float value) {
|
void SetFloatValue (float value) {
|
||||||
mFloatValue = value;
|
mFloatValue = value;
|
||||||
}
|
}
|
||||||
|
void SetBoolValue (bool value) {
|
||||||
|
mBoolValue = value;
|
||||||
|
}
|
||||||
|
void SetBoolValueFromString (std::string str_value) {
|
||||||
|
mBoolValue = ParseBoolValue (str_value);
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/** \brief The default constructor must not be used.
|
/** \brief The default constructor must not be used.
|
||||||
|
@ -48,9 +58,21 @@ class Variable {
|
||||||
/** \brief Registeres this Variable with the Variables System */
|
/** \brief Registeres this Variable with the Variables System */
|
||||||
void RegisterVariable (const std::string &name);
|
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 mName;
|
||||||
std::string mStringValue;
|
std::string mStringValue;
|
||||||
float mFloatValue;
|
float mFloatValue;
|
||||||
|
bool mBoolValue;
|
||||||
|
|
||||||
friend class Variables;
|
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 = "");
|
std::string& GetVariableString (const std::string &name, std::string def = "");
|
||||||
/** \brief Returns the float value of the Variable with the given name */
|
/** \brief Returns the float value of the Variable with the given name */
|
||||||
float& GetVariableFloat (const std::string &name, float def = 0.);
|
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
|
#endif // _VARIABLESGLOBAL_H
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
ADD_SUBDIRECTORY ( mathlib )
|
ADD_SUBDIRECTORY ( mathlib )
|
||||||
ADD_SUBDIRECTORY ( coll2d )
|
ADD_SUBDIRECTORY ( coll2d )
|
||||||
ADD_SUBDIRECTORY ( oglft )
|
ADD_SUBDIRECTORY ( oglft )
|
||||||
|
ADD_SUBDIRECTORY ( sha2 )
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
PROJECT (SHA2 CXX)
|
||||||
|
|
||||||
|
SET ( SRCS
|
||||||
|
sha2.c
|
||||||
|
)
|
||||||
|
ADD_LIBRARY ( sha2 STATIC sha2.c)
|
|
@ -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.
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -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__ */
|
||||||
|
|
|
@ -12,6 +12,7 @@ SET ( TESTS_SRCS
|
||||||
EventBaseTests.cc
|
EventBaseTests.cc
|
||||||
PhysicsTests.cc
|
PhysicsTests.cc
|
||||||
ControllerBaseTests.cc
|
ControllerBaseTests.cc
|
||||||
|
UtilsTests.cc
|
||||||
)
|
)
|
||||||
|
|
||||||
FIND_PACKAGE (UnitTest++)
|
FIND_PACKAGE (UnitTest++)
|
||||||
|
|
Binary file not shown.
|
@ -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>
|
Loading…
Reference in New Issue