Add new function ParseServerReturn, try to properly display all http errors

Also fix crash with invalid ptsave link, and fix some cases where it wouldn't ever tell you it errored
This commit is contained in:
jacob1 2015-08-29 13:14:17 -04:00
parent 052681ef2b
commit 9f9fef6cad
16 changed files with 288 additions and 581 deletions

View File

@ -945,8 +945,9 @@ int main(int argc, char * argv[])
std::string ptsaveArg = arguments["ptsave"]; std::string ptsaveArg = arguments["ptsave"];
try try
{ {
if(!ptsaveArg.find("ptsave:")) if (ptsaveArg.find("ptsave:"))
{ throw std::runtime_error("Invalid save link");
std::string saveIdPart = ""; std::string saveIdPart = "";
int saveId; int saveId;
size_t hashPos = ptsaveArg.find('#'); size_t hashPos = ptsaveArg.find('#');
@ -958,33 +959,30 @@ int main(int argc, char * argv[])
{ {
saveIdPart = ptsaveArg.substr(7); saveIdPart = ptsaveArg.substr(7);
} }
if (saveIdPart.length()) if (!saveIdPart.length())
{
#ifdef DEBUG
std::cout << "Got Ptsave: id: " << saveIdPart << std::endl;
#endif
saveId = format::StringToNumber<int>(saveIdPart);
if(!saveId)
throw std::runtime_error("Invalid Save ID");
SaveInfo * newSave = Client::Ref().GetSave(saveId, 0);
if (!newSave)
throw std::runtime_error("Could not load save");
GameSave * newGameSave = new GameSave(Client::Ref().GetSaveData(saveId, 0));
newSave->SetGameSave(newGameSave);
gameController->LoadSave(newSave);
delete newSave;
}
else
{
throw std::runtime_error("No Save ID"); throw std::runtime_error("No Save ID");
} #ifdef DEBUG
} std::cout << "Got Ptsave: id: " << saveIdPart << std::endl;
#endif
saveId = format::StringToNumber<int>(saveIdPart);
if (!saveId)
throw std::runtime_error("Invalid Save ID");
SaveInfo * newSave = Client::Ref().GetSave(saveId, 0);
if (!newSave)
throw std::runtime_error("Could not load save info");
std::vector<unsigned char> saveData = Client::Ref().GetSaveData(saveId, 0);
if (!saveData.size())
throw std::runtime_error("Could not load save\n" + Client::Ref().GetLastError());
GameSave * newGameSave = new GameSave(saveData);
newSave->SetGameSave(newGameSave);
gameController->LoadSave(newSave);
delete newSave;
} }
catch (std::exception & e) catch (std::exception & e)
{ {
new ErrorMessage("Error", "Invalid save link"); new ErrorMessage("Error", e.what());
} }
} }

View File

@ -666,20 +666,86 @@ std::vector<std::pair<std::string, std::string> > Client::GetServerNotifications
return serverNotifications; return serverNotifications;
} }
RequestStatus Client::ParseServerReturn(char *result, int status, bool json)
{
// no server response, return "Malformed Response"
if (status == 200 && !result)
{
status = 603;
}
if (status == 302)
return RequestOkay;
if (status != 200)
{
std::stringstream httperror;
httperror << "HTTP Error " << status << ": " << http_ret_text(status);
lastError = httperror.str();
return RequestFailure;
}
if (json)
{
std::istringstream datastream(result);
json::Object root;
try
{
json::Reader::Read(root, datastream);
// assume everything is fine if an empty [] is returned
if (root.Size() == 0)
{
return RequestOkay;
}
json::Number status = root["Status"];
if (status != 1)
{
json::String error = root["Error"];
lastError = std::string(error);
if (lastError == "")
lastError = "Unspecified Error";
return RequestFailure;
}
}
catch (std::exception &e)
{
// sometimes the server returns a 200 with the text "Error: 401"
if (!strncmp((const char *)result, "Error: ", 7))
{
status = atoi(result+7);
std::stringstream httperror;
httperror << "HTTP Error " << status << ": " << http_ret_text(status);
lastError = httperror.str();
return RequestFailure;
}
lastError = "Could not read response";
return RequestFailure;
}
}
else
{
if (strncmp((const char *)result, "OK", 2))
{
lastError = std::string(result);
return RequestFailure;
}
}
return RequestOkay;
}
void Client::Tick() void Client::Tick()
{ {
//Check thumbnail queue //Check thumbnail queue
RequestBroker::Ref().FlushThumbQueue(); RequestBroker::Ref().FlushThumbQueue();
//Check status on version check request //Check status on version check request
if(versionCheckRequest && http_async_req_status(versionCheckRequest)) if (versionCheckRequest && http_async_req_status(versionCheckRequest))
{ {
int status; int status;
int dataLength; int dataLength;
char * data = http_async_req_stop(versionCheckRequest, &status, &dataLength); char * data = http_async_req_stop(versionCheckRequest, &status, &dataLength);
versionCheckRequest = NULL; versionCheckRequest = NULL;
if(status != 200) if (status != 200)
{ {
free(data); free(data);
} }
@ -725,7 +791,7 @@ void Client::Tick()
json::Number stableMinor = stableVersion["Minor"]; json::Number stableMinor = stableVersion["Minor"];
json::Number stableBuild = stableVersion["Build"]; json::Number stableBuild = stableVersion["Build"];
json::String stableFile = stableVersion["File"]; json::String stableFile = stableVersion["File"];
if(stableMajor.Value()>SAVE_VERSION || (stableMinor.Value()>MINOR_VERSION && stableMajor.Value()==SAVE_VERSION) || stableBuild.Value()>BUILD_NUM) if (stableMajor.Value()>SAVE_VERSION || (stableMinor.Value()>MINOR_VERSION && stableMajor.Value()==SAVE_VERSION) || stableBuild.Value()>BUILD_NUM)
{ {
updateAvailable = true; updateAvailable = true;
updateInfo = UpdateInfo(stableMajor.Value(), stableMinor.Value(), stableBuild.Value(), stableFile.Value(), UpdateInfo::Stable); updateInfo = UpdateInfo(stableMajor.Value(), stableMinor.Value(), stableBuild.Value(), stableFile.Value(), UpdateInfo::Stable);
@ -738,7 +804,7 @@ void Client::Tick()
json::Number betaMinor = betaVersion["Minor"]; json::Number betaMinor = betaVersion["Minor"];
json::Number betaBuild = betaVersion["Build"]; json::Number betaBuild = betaVersion["Build"];
json::String betaFile = betaVersion["File"]; json::String betaFile = betaVersion["File"];
if(betaMajor.Value()>SAVE_VERSION || (betaMinor.Value()>MINOR_VERSION && betaMajor.Value()==SAVE_VERSION) || betaBuild.Value()>BUILD_NUM) if (betaMajor.Value()>SAVE_VERSION || (betaMinor.Value()>MINOR_VERSION && betaMajor.Value()==SAVE_VERSION) || betaBuild.Value()>BUILD_NUM)
{ {
updateAvailable = true; updateAvailable = true;
updateInfo = UpdateInfo(betaMajor.Value(), betaMinor.Value(), betaBuild.Value(), betaFile.Value(), UpdateInfo::Beta); updateInfo = UpdateInfo(betaMajor.Value(), betaMinor.Value(), betaBuild.Value(), betaFile.Value(), UpdateInfo::Beta);
@ -749,7 +815,7 @@ void Client::Tick()
json::Object snapshotVersion = versions["Snapshot"]; json::Object snapshotVersion = versions["Snapshot"];
json::Number snapshotSnapshot = snapshotVersion["Snapshot"]; json::Number snapshotSnapshot = snapshotVersion["Snapshot"];
json::String snapshotFile = snapshotVersion["File"]; json::String snapshotFile = snapshotVersion["File"];
if(snapshotSnapshot.Value() > SNAPSHOT_ID) if (snapshotSnapshot.Value() > SNAPSHOT_ID)
{ {
updateAvailable = true; updateAvailable = true;
updateInfo = UpdateInfo(snapshotSnapshot.Value(), snapshotFile.Value(), UpdateInfo::Snapshot); updateInfo = UpdateInfo(snapshotSnapshot.Value(), snapshotFile.Value(), UpdateInfo::Snapshot);
@ -835,9 +901,9 @@ void Client::WritePrefs()
configFile.open("powder.pref", std::ios::trunc); configFile.open("powder.pref", std::ios::trunc);
#endif #endif
if(configFile) if (configFile)
{ {
if(authUser.ID) if (authUser.ID)
{ {
configDocument["User"]["ID"] = json::Number(authUser.ID); configDocument["User"]["ID"] = json::Number(authUser.ID);
configDocument["User"]["SessionID"] = json::String(authUser.SessionID); configDocument["User"]["SessionID"] = json::String(authUser.SessionID);
@ -904,9 +970,9 @@ RequestStatus Client::UploadSave(SaveInfo & save)
int dataLength = 0; int dataLength = 0;
std::stringstream userIDStream; std::stringstream userIDStream;
userIDStream << authUser.ID; userIDStream << authUser.ID;
if(authUser.ID) if (authUser.ID)
{ {
if(!save.GetGameSave()) if (!save.GetGameSave())
{ {
lastError = "Empty game save"; lastError = "Empty game save";
return RequestFailure; return RequestFailure;
@ -915,7 +981,7 @@ RequestStatus Client::UploadSave(SaveInfo & save)
gameData = save.GetGameSave()->Serialise(gameDataLength); gameData = save.GetGameSave()->Serialise(gameDataLength);
if(!gameData) if (!gameData)
{ {
lastError = "Cannot upload game save"; lastError = "Cannot upload game save";
return RequestFailure; return RequestFailure;
@ -933,7 +999,6 @@ RequestStatus Client::UploadSave(SaveInfo & save)
const char *const postNames[] = { "Name", "Description", "Data:save.bin", "Publish", NULL }; const char *const postNames[] = { "Name", "Description", "Data:save.bin", "Publish", NULL };
const char *const postDatas[] = { saveName, saveDescription, gameData, (char *)(save.GetPublished()?"Public":"Private") }; const char *const postDatas[] = { saveName, saveDescription, gameData, (char *)(save.GetPublished()?"Public":"Private") };
size_t postLengths[] = { save.GetName().length(), save.GetDescription().length(), gameDataLength, (size_t)(save.GetPublished()?6:7) }; size_t postLengths[] = { save.GetName().length(), save.GetDescription().length(), gameDataLength, (size_t)(save.GetPublished()?6:7) };
//std::cout << postNames[0] << " " << postDatas[0] << " " << postLengths[0] << std::endl;
data = http_multipart_post("http://" SERVER "/Save.api", postNames, postDatas, postLengths, userid, NULL, session, &dataStatus, &dataLength); data = http_multipart_post("http://" SERVER "/Save.api", postNames, postDatas, postLengths, userid, NULL, session, &dataStatus, &dataLength);
delete[] saveDescription; delete[] saveDescription;
@ -946,40 +1011,22 @@ RequestStatus Client::UploadSave(SaveInfo & save)
lastError = "Not authenticated"; lastError = "Not authenticated";
return RequestFailure; return RequestFailure;
} }
if(data && dataStatus == 200)
RequestStatus ret = ParseServerReturn(data, dataStatus, false);
if (ret == RequestOkay)
{ {
if(strncmp((const char *)data, "OK", 2)!=0) int saveID = format::StringToNumber<int>(data+3);
if (!saveID)
{ {
delete[] gameData; lastError = "Server did not return Save ID";
lastError = std::string((const char *)data); ret = RequestFailure;
free(data);
return RequestFailure;
} }
else else
{ save.SetID(saveID);
int tempID;
std::stringstream saveIDStream((char *)(data+3));
saveIDStream >> tempID;
if(!tempID)
{
lastError = "Server did not return Save ID";
return RequestFailure;
}
else
{
save.SetID(tempID);
}
}
free(data);
delete[] gameData;
return RequestOkay;
}
else if(data)
{
free(data);
} }
free(data);
delete[] gameData; delete[] gameData;
return RequestFailure; return ret;
} }
void Client::MoveStampToFront(std::string stampID) void Client::MoveStampToFront(std::string stampID)
@ -1140,26 +1187,23 @@ RequestStatus Client::ExecVote(int saveID, int direction)
int dataStatus; int dataStatus;
char * data; char * data;
int dataLength = 0; int dataLength = 0;
std::stringstream idStream;
idStream << saveID;
if(authUser.ID) if (authUser.ID)
{ {
char * directionText = (char*)(direction==1?"Up":"Down"); char * directionText = (char*)(direction==1?"Up":"Down");
std::string saveIDText = format::NumberToString<int>(saveID); std::string saveIDText = format::NumberToString<int>(saveID);
std::string userIDText = format::NumberToString<int>(authUser.ID); std::string userIDText = format::NumberToString<int>(authUser.ID);
char *id = new char[saveIDText.length() + 1]; char *id = new char[saveIDText.length() + 1];
std::strcpy (id, saveIDText.c_str()); std::strcpy(id, saveIDText.c_str());
char *userid = new char[userIDText.length() + 1]; char *userid = new char[userIDText.length() + 1];
std::strcpy (userid, userIDText.c_str()); std::strcpy(userid, userIDText.c_str());
char *session = new char[authUser.SessionID.length() + 1]; char *session = new char[authUser.SessionID.length() + 1];
std::strcpy (session, authUser.SessionID.c_str()); std::strcpy(session, authUser.SessionID.c_str());
const char *const postNames[] = { "ID", "Action", NULL }; const char *const postNames[] = { "ID", "Action", NULL };
const char *const postDatas[] = { id, directionText }; const char *const postDatas[] = { id, directionText };
size_t postLengths[] = { saveIDText.length(), strlen(directionText) }; size_t postLengths[] = { saveIDText.length(), strlen(directionText) };
//std::cout << postNames[0] << " " << postDatas[0] << " " << postLengths[0] << std::endl;
data = http_multipart_post("http://" SERVER "/Vote.api", postNames, postDatas, postLengths, userid, NULL, session, &dataStatus, &dataLength); data = http_multipart_post("http://" SERVER "/Vote.api", postNames, postDatas, postLengths, userid, NULL, session, &dataStatus, &dataLength);
delete[] id; delete[] id;
@ -1171,54 +1215,32 @@ RequestStatus Client::ExecVote(int saveID, int direction)
lastError = "Not authenticated"; lastError = "Not authenticated";
return RequestFailure; return RequestFailure;
} }
if(data && dataStatus == 200) RequestStatus ret = ParseServerReturn(data, dataStatus, false);
{ return ret;
if(strncmp((const char *)data, "OK", 2)!=0)
{
lastError = std::string((const char *)data);
free(data);
return RequestFailure;
}
free(data);
return RequestOkay;
}
else if(data)
{
free(data);
}
lastError = http_ret_text(dataStatus);
return RequestFailure;
} }
unsigned char * Client::GetSaveData(int saveID, int saveDate, int & dataLength) unsigned char * Client::GetSaveData(int saveID, int saveDate, int & dataLength)
{ {
lastError = ""; lastError = "";
int dataStatus; int dataStatus;
unsigned char * data; char *data;
dataLength = 0; dataLength = 0;
std::stringstream urlStream; std::stringstream urlStream;
if(saveDate) if (saveDate)
{
urlStream << "http://" << STATICSERVER << "/" << saveID << "_" << saveDate << ".cps"; urlStream << "http://" << STATICSERVER << "/" << saveID << "_" << saveDate << ".cps";
}
else else
{
urlStream << "http://" << STATICSERVER << "/" << saveID << ".cps"; urlStream << "http://" << STATICSERVER << "/" << saveID << ".cps";
}
char *url = new char[urlStream.str().length() + 1]; char *url = new char[urlStream.str().length() + 1];
std::strcpy (url, urlStream.str().c_str()); std::strcpy(url, urlStream.str().c_str());
data = (unsigned char *)http_simple_get(url, &dataStatus, &dataLength); data = http_simple_get(url, &dataStatus, &dataLength);
delete[] url; delete[] url;
if(data && dataStatus == 200) // will always return failure
{ ParseServerReturn(data, dataStatus, false);
return data; if (data && dataStatus == 200)
} return (unsigned char *)data;
else if(data) free(data);
{
free(data);
}
return NULL; return NULL;
} }
@ -1226,9 +1248,10 @@ std::vector<unsigned char> Client::GetSaveData(int saveID, int saveDate)
{ {
int dataSize; int dataSize;
unsigned char * data = GetSaveData(saveID, saveDate, dataSize); unsigned char * data = GetSaveData(saveID, saveDate, dataSize);
if (!data)
return std::vector<unsigned char>();
std::vector<unsigned char> saveData(data, data+dataSize); std::vector<unsigned char> saveData(data, data+dataSize);
delete[] data; delete[] data;
return saveData; return saveData;
} }
@ -1241,7 +1264,7 @@ RequestBroker::Request * Client::GetSaveDataAsync(int saveID, int saveDate)
} else { } else {
urlStream << "http://" << STATICSERVER << "/" << saveID << ".cps"; urlStream << "http://" << STATICSERVER << "/" << saveID << ".cps";
} }
return new WebRequest(urlStream.str()); return new WebRequest(urlStream.str());
} }
RequestBroker::Request * Client::SaveUserInfoAsync(UserInfo info) RequestBroker::Request * Client::SaveUserInfoAsync(UserInfo info)
@ -1273,7 +1296,7 @@ RequestBroker::Request * Client::SaveUserInfoAsync(UserInfo info)
std::map<std::string, std::string> postData; std::map<std::string, std::string> postData;
postData.insert(std::pair<std::string, std::string>("Location", info.location)); postData.insert(std::pair<std::string, std::string>("Location", info.location));
postData.insert(std::pair<std::string, std::string>("Biography", info.biography)); postData.insert(std::pair<std::string, std::string>("Biography", info.biography));
return new APIRequest("http://" SERVER "/Profile.json", postData, new StatusParser()); return new APIRequest("http://" SERVER "/Profile.json", postData, new StatusParser());
} }
RequestBroker::Request * Client::GetUserInfoAsync(std::string username) RequestBroker::Request * Client::GetUserInfoAsync(std::string username)
@ -1340,52 +1363,43 @@ LoginStatus Client::Login(std::string username, std::string password, User & use
const char *const postDatas[] = { (char*)username.c_str(), totalHash }; const char *const postDatas[] = { (char*)username.c_str(), totalHash };
size_t postLengths[] = { username.length(), 32 }; size_t postLengths[] = { username.length(), 32 };
data = http_multipart_post("http://" SERVER "/Login.json", postNames, postDatas, postLengths, NULL, NULL, NULL, &dataStatus, &dataLength); data = http_multipart_post("http://" SERVER "/Login.json", postNames, postDatas, postLengths, NULL, NULL, NULL, &dataStatus, &dataLength);
if(dataStatus == 200 && data) RequestStatus ret = ParseServerReturn(data, dataStatus, true);
if (ret == RequestOkay)
{ {
try try
{ {
std::istringstream dataStream(data); std::istringstream dataStream(data);
json::Object objDocument; json::Object objDocument;
json::Reader::Read(objDocument, dataStream); json::Reader::Read(objDocument, dataStream);
json::Number tempStatus = objDocument["Status"];
free(data); free(data);
if(tempStatus.Value() == 1)
json::Number userIDTemp = objDocument["UserID"];
json::String sessionIDTemp = objDocument["SessionID"];
json::String sessionKeyTemp = objDocument["SessionKey"];
json::String userElevationTemp = objDocument["Elevation"];
json::Array notificationsArray = objDocument["Notifications"];
for (size_t j = 0; j < notificationsArray.Size(); j++)
{ {
json::Number userIDTemp = objDocument["UserID"]; json::String notificationLink = notificationsArray[j]["Link"];
json::String sessionIDTemp = objDocument["SessionID"]; json::String notificationText = notificationsArray[j]["Text"];
json::String sessionKeyTemp = objDocument["SessionKey"];
json::String userElevationTemp = objDocument["Elevation"];
json::Array notificationsArray = objDocument["Notifications"];
for (size_t j = 0; j < notificationsArray.Size(); j++)
{
json::String notificationLink = notificationsArray[j]["Link"];
json::String notificationText = notificationsArray[j]["Text"];
std::pair<std::string, std::string> item = std::pair<std::string, std::string>(notificationText.Value(), notificationLink.Value()); std::pair<std::string, std::string> item = std::pair<std::string, std::string>(notificationText.Value(), notificationLink.Value());
AddServerNotification(item); AddServerNotification(item);
}
user.Username = username;
user.ID = userIDTemp.Value();
user.SessionID = sessionIDTemp.Value();
user.SessionKey = sessionKeyTemp.Value();
std::string userElevation = userElevationTemp.Value();
if(userElevation == "Admin")
user.UserElevation = User::ElevationAdmin;
else if(userElevation == "Mod")
user.UserElevation = User::ElevationModerator;
else
user.UserElevation= User::ElevationNone;
return LoginOkay;
} }
user.Username = username;
user.ID = userIDTemp.Value();
user.SessionID = sessionIDTemp.Value();
user.SessionKey = sessionKeyTemp.Value();
std::string userElevation = userElevationTemp.Value();
if(userElevation == "Admin")
user.UserElevation = User::ElevationAdmin;
else if(userElevation == "Mod")
user.UserElevation = User::ElevationModerator;
else else
{ user.UserElevation= User::ElevationNone;
json::String tempError = objDocument["Error"]; return LoginOkay;
lastError = tempError.Value();
return LoginError;
}
} }
catch (json::Exception &e) catch (json::Exception &e)
{ {
@ -1393,10 +1407,6 @@ LoginStatus Client::Login(std::string username, std::string password, User & use
return LoginError; return LoginError;
} }
} }
else
{
lastError = http_ret_text(dataStatus);
}
free(data); free(data);
return LoginError; return LoginError;
} }
@ -1419,35 +1429,9 @@ RequestStatus Client::DeleteSave(int saveID)
lastError = "Not authenticated"; lastError = "Not authenticated";
return RequestFailure; return RequestFailure;
} }
if(dataStatus == 200 && data) RequestStatus ret = ParseServerReturn(data, dataStatus, true);
{
try
{
std::istringstream dataStream(data);
json::Object objDocument;
json::Reader::Read(objDocument, dataStream);
int status = ((json::Number)objDocument["Status"]).Value();
if(status!=1)
goto failure;
}
catch (json::Exception &e)
{
lastError = "Could not read response";
goto failure;
}
}
else
{
lastError = http_ret_text(dataStatus);
goto failure;
}
free(data); free(data);
return RequestOkay; return ret;
failure:
free(data);
return RequestFailure;
} }
RequestStatus Client::AddComment(int saveID, std::string comment) RequestStatus Client::AddComment(int saveID, std::string comment)
@ -1472,40 +1456,9 @@ RequestStatus Client::AddComment(int saveID, std::string comment)
lastError = "Not authenticated"; lastError = "Not authenticated";
return RequestFailure; return RequestFailure;
} }
if(dataStatus == 200 && data) RequestStatus ret = ParseServerReturn(data, dataStatus, true);
{
try
{
std::istringstream dataStream(data);
json::Object objDocument;
json::Reader::Read(objDocument, dataStream);
int status = ((json::Number)objDocument["Status"]).Value();
if(status!=1)
{
lastError = ((json::String)objDocument["Error"]).Value();
}
if(status!=1)
goto failure;
}
catch (json::Exception &e)
{
lastError = "Could not read response";
goto failure;
}
}
else
{
lastError = http_ret_text(dataStatus);
goto failure;
}
free(data); free(data);
return RequestOkay; return ret;
failure:
free(data);
return RequestFailure;
} }
RequestStatus Client::FavouriteSave(int saveID, bool favourite) RequestStatus Client::FavouriteSave(int saveID, bool favourite)
@ -1528,38 +1481,9 @@ RequestStatus Client::FavouriteSave(int saveID, bool favourite)
lastError = "Not authenticated"; lastError = "Not authenticated";
return RequestFailure; return RequestFailure;
} }
if(dataStatus == 200 && data) RequestStatus ret = ParseServerReturn(data, dataStatus, true);
{
try
{
std::istringstream dataStream(data);
json::Object objDocument;
json::Reader::Read(objDocument, dataStream);
int status = ((json::Number)objDocument["Status"]).Value();
if(status!=1)
{
lastError = ((json::String)objDocument["Error"]).Value();
goto failure;
}
}
catch (json::Exception &e)
{
lastError = "Could not read response";
goto failure;
}
}
else
{
lastError = http_ret_text(dataStatus);
goto failure;
}
free(data); free(data);
return RequestOkay; return ret;
failure:
free(data);
return RequestFailure;
} }
RequestStatus Client::ReportSave(int saveID, std::string message) RequestStatus Client::ReportSave(int saveID, std::string message)
@ -1584,38 +1508,9 @@ RequestStatus Client::ReportSave(int saveID, std::string message)
lastError = "Not authenticated"; lastError = "Not authenticated";
return RequestFailure; return RequestFailure;
} }
if(dataStatus == 200 && data) RequestStatus ret = ParseServerReturn(data, dataStatus, true);
{
try
{
std::istringstream dataStream(data);
json::Object objDocument;
json::Reader::Read(objDocument, dataStream);
int status = ((json::Number)objDocument["Status"]).Value();
if(status!=1)
{
lastError = ((json::String)objDocument["Error"]).Value();
goto failure;
}
}
catch (json::Exception &e)
{
lastError = "Could not read response";
goto failure;
}
}
else
{
lastError = http_ret_text(dataStatus);
goto failure;
}
free(data); free(data);
return RequestOkay; return ret;
failure:
free(data);
return RequestFailure;
} }
RequestStatus Client::UnpublishSave(int saveID) RequestStatus Client::UnpublishSave(int saveID)
@ -1636,44 +1531,16 @@ RequestStatus Client::UnpublishSave(int saveID)
lastError = "Not authenticated"; lastError = "Not authenticated";
return RequestFailure; return RequestFailure;
} }
if(dataStatus == 200 && data) RequestStatus ret = ParseServerReturn(data, dataStatus, true);
{
try
{
std::istringstream dataStream(data);
json::Object objDocument;
json::Reader::Read(objDocument, dataStream);
int status = ((json::Number)objDocument["Status"]).Value();
if(status!=1)
{
lastError = ((json::String)objDocument["Error"]).Value();
goto failure;
}
}
catch (json::Exception &e)
{
lastError = "Could not read response";
goto failure;
}
}
else
{
lastError = http_ret_text(dataStatus);
goto failure;
}
free(data); free(data);
return RequestOkay; return ret;
failure:
free(data);
return RequestFailure;
} }
RequestStatus Client::PublishSave(int saveID) RequestStatus Client::PublishSave(int saveID)
{ {
lastError = ""; lastError = "";
std::stringstream urlStream; std::stringstream urlStream;
char *data;
int dataStatus; int dataStatus;
urlStream << "http://" << SERVER << "/Browse/View.html?ID=" << saveID << "&Key=" << authUser.SessionKey; urlStream << "http://" << SERVER << "/Browse/View.html?ID=" << saveID << "&Key=" << authUser.SessionKey;
if (authUser.ID) if (authUser.ID)
@ -1683,20 +1550,15 @@ RequestStatus Client::PublishSave(int saveID)
const char *const postNames[] = { "ActionPublish", NULL }; const char *const postNames[] = { "ActionPublish", NULL };
const char *const postDatas[] = { "" }; const char *const postDatas[] = { "" };
size_t postLengths[] = { 1 }; size_t postLengths[] = { 1 };
char *data = http_multipart_post(urlStream.str().c_str(), postNames, postDatas, postLengths, userIDStream.str().c_str(), NULL, authUser.SessionID.c_str(), &dataStatus, NULL); data = http_multipart_post(urlStream.str().c_str(), postNames, postDatas, postLengths, userIDStream.str().c_str(), NULL, authUser.SessionID.c_str(), &dataStatus, NULL); }
free(data);
}
else else
{ {
lastError = "Not authenticated"; lastError = "Not authenticated";
return RequestFailure; return RequestFailure;
} }
if (dataStatus != 302) RequestStatus ret = ParseServerReturn(data, dataStatus, false);
{ free(data);
lastError = http_ret_text(dataStatus); return ret;
return RequestFailure;
}
return RequestOkay;
} }
SaveInfo * Client::GetSave(int saveID, int saveDate) SaveInfo * Client::GetSave(int saveID, int saveDate)
@ -1710,7 +1572,6 @@ SaveInfo * Client::GetSave(int saveID, int saveDate)
} }
char * data; char * data;
int dataStatus, dataLength; int dataStatus, dataLength;
//Save(int _id, int _votesUp, int _votesDown, string _userName, string _name, string description_, string date_, bool published_):
if(authUser.ID) if(authUser.ID)
{ {
std::stringstream userIDStream; std::stringstream userIDStream;
@ -1860,48 +1721,6 @@ RequestBroker::Request * Client::GetSaveAsync(int saveID, int saveDate)
return new APIRequest(urlStream.str(), new SaveInfoParser()); return new APIRequest(urlStream.str(), new SaveInfoParser());
} }
Thumbnail * Client::GetPreview(int saveID, int saveDate)
{
std::stringstream urlStream;
urlStream << "http://" << STATICSERVER << "/" << saveID;
if(saveDate)
{
urlStream << "_" << saveDate;
}
urlStream << "_large.pti";
pixel * thumbData;
char * data;
int status, data_size, imgw, imgh;
data = http_simple_get((char *)urlStream.str().c_str(), &status, &data_size);
if (status == 200 && data)
{
thumbData = Graphics::ptif_unpack(data, data_size, &imgw, &imgh);
if(data)
{
free(data);
}
if(thumbData)
{
return new Thumbnail(saveID, saveDate, thumbData, ui::Point(imgw, imgh));
free(thumbData);
}
else
{
thumbData = (pixel *)malloc((128*128) * PIXELSIZE);
return new Thumbnail(saveID, saveDate, thumbData, ui::Point(128, 128));
free(thumbData);
}
}
else
{
if(data)
{
free(data);
}
}
return new Thumbnail(saveID, saveDate, (pixel *)malloc((128*128) * PIXELSIZE), ui::Point(128, 128));
}
RequestBroker::Request * Client::GetCommentsAsync(int saveID, int start, int count) RequestBroker::Request * Client::GetCommentsAsync(int saveID, int start, int count)
{ {
class CommentsParser: public APIResultParser class CommentsParser: public APIResultParser
@ -1950,53 +1769,6 @@ RequestBroker::Request * Client::GetCommentsAsync(int saveID, int start, int cou
return new APIRequest(urlStream.str(), new CommentsParser()); return new APIRequest(urlStream.str(), new CommentsParser());
} }
std::vector<SaveComment*> * Client::GetComments(int saveID, int start, int count)
{
lastError = "";
std::vector<SaveComment*> * commentArray = new std::vector<SaveComment*>();
std::stringstream urlStream;
char * data;
int dataStatus, dataLength;
urlStream << "http://" << SERVER << "/Browse/Comments.json?ID=" << saveID << "&Start=" << start << "&Count=" << count;
data = http_simple_get((char *)urlStream.str().c_str(), &dataStatus, &dataLength);
if(dataStatus == 200 && data)
{
try
{
std::istringstream dataStream(data);
json::Array commentsArray;
json::Reader::Read(commentsArray, dataStream);
for (size_t j = 0; j < commentsArray.Size(); j++)
{
json::Number tempUserID = commentsArray[j]["UserID"];
json::String tempUsername = commentsArray[j]["Username"];
json::String tempFormattedUsername = commentsArray[j]["FormattedUsername"];
json::String tempComment = commentsArray[j]["Text"];
commentArray->push_back(
new SaveComment(
tempUserID.Value(),
tempUsername.Value(),
tempFormattedUsername.Value(),
tempComment.Value()
)
);
}
}
catch (json::Exception &e)
{
lastError = "Could not read response";
}
}
else
{
lastError = http_ret_text(dataStatus);
}
free(data);
return commentArray;
}
std::vector<std::pair<std::string, int> > * Client::GetTags(int start, int count, std::string query, int & resultCount) std::vector<std::pair<std::string, int> > * Client::GetTags(int start, int count, std::string query, int & resultCount)
{ {
lastError = ""; lastError = "";
@ -2080,7 +1852,8 @@ std::vector<SaveInfo*> * Client::SearchSaves(int start, int count, std::string q
{ {
data = http_simple_get((char *)urlStream.str().c_str(), &dataStatus, &dataLength); data = http_simple_get((char *)urlStream.str().c_str(), &dataStatus, &dataLength);
} }
if(dataStatus == 200 && data) ParseServerReturn(data, dataStatus, true);
if (dataStatus == 200 && data)
{ {
try try
{ {
@ -2119,10 +1892,6 @@ std::vector<SaveInfo*> * Client::SearchSaves(int start, int count, std::string q
lastError = "Could not read response"; lastError = "Could not read response";
} }
} }
else
{
lastError = http_ret_text(dataStatus);
}
free(data); free(data);
return saveArray; return saveArray;
} }
@ -2141,120 +1910,6 @@ void Client::ClearThumbnailRequests()
} }
} }
Thumbnail * Client::GetThumbnail(int saveID, int saveDate)
{
std::stringstream urlStream;
std::stringstream idStream;
int i = 0, currentTime = time(NULL);
//Check active requests for any "forgotten" requests
for(i = 0; i < IMGCONNS; i++)
{
//If the request is active, and we've received a response
if(activeThumbRequests[i] && http_async_req_status(activeThumbRequests[i]))
{
//If we haven't already, mark the request as completed
if(!activeThumbRequestCompleteTimes[i])
{
activeThumbRequestCompleteTimes[i] = time(NULL);
}
else if(activeThumbRequestCompleteTimes[i] < (currentTime-2)) //Otherwise, if it completed more than 2 seconds ago, destroy it.
{
http_async_req_close(activeThumbRequests[i]);
activeThumbRequests[i] = NULL;
activeThumbRequestTimes[i] = 0;
activeThumbRequestCompleteTimes[i] = 0;
}
}
}
for(i = 0; i < THUMB_CACHE_SIZE; i++)
{
if(thumbnailCache[i] && thumbnailCache[i]->ID == saveID && thumbnailCache[i]->Datestamp == saveDate)
return thumbnailCache[i];
}
urlStream << "http://" << STATICSERVER << "/" << saveID;
if(saveDate)
{
urlStream << "_" << saveDate;
}
urlStream << "_small.pti";
idStream << saveID << ":" << saveDate;
std::string idString = idStream.str();
bool found = false;
for(i = 0; i < IMGCONNS; i++)
{
if(activeThumbRequests[i] && activeThumbRequestIDs[i] == idString)
{
found = true;
if(http_async_req_status(activeThumbRequests[i]))
{
pixel * thumbData;
char * data;
int status, data_size, imgw, imgh;
data = http_async_req_stop(activeThumbRequests[i], &status, &data_size);
free(activeThumbRequests[i]);
activeThumbRequests[i] = NULL;
if (status == 200 && data)
{
thumbData = Graphics::ptif_unpack(data, data_size, &imgw, &imgh);
if(data)
{
free(data);
}
thumbnailCacheNextID %= THUMB_CACHE_SIZE;
if(thumbnailCache[thumbnailCacheNextID])
{
delete thumbnailCache[thumbnailCacheNextID];
}
if(thumbData)
{
thumbnailCache[thumbnailCacheNextID] = new Thumbnail(saveID, saveDate, thumbData, ui::Point(imgw, imgh));
free(thumbData);
}
else
{
thumbData = (pixel *)malloc((128*128) * PIXELSIZE);
thumbnailCache[thumbnailCacheNextID] = new Thumbnail(saveID, saveDate, thumbData, ui::Point(128, 128));
free(thumbData);
}
return thumbnailCache[thumbnailCacheNextID++];
}
else
{
if(data)
{
free(data);
}
thumbnailCacheNextID %= THUMB_CACHE_SIZE;
if(thumbnailCache[thumbnailCacheNextID])
{
delete thumbnailCache[thumbnailCacheNextID];
}
thumbData = (pixel *)malloc((128*128) * PIXELSIZE);
thumbnailCache[thumbnailCacheNextID] = new Thumbnail(saveID, saveDate, thumbData, ui::Point(128, 128));
free(thumbData);
return thumbnailCache[thumbnailCacheNextID++];
}
}
}
}
if(!found)
{
for(i = 0; i < IMGCONNS; i++)
{
if(!activeThumbRequests[i])
{
activeThumbRequests[i] = http_async_req_start(NULL, (char *)urlStream.str().c_str(), NULL, 0, 0);
activeThumbRequestTimes[i] = currentTime;
activeThumbRequestCompleteTimes[i] = 0;
activeThumbRequestIDs[i] = idString;
return NULL;
}
}
}
//http_async_req_start(http, urlStream.str().c_str(), NULL, 0, 1);
return NULL;
}
std::list<std::string> * Client::RemoveTag(int saveID, std::string tag) std::list<std::string> * Client::RemoveTag(int saveID, std::string tag)
{ {
lastError = ""; lastError = "";
@ -2262,7 +1917,7 @@ std::list<std::string> * Client::RemoveTag(int saveID, std::string tag)
std::stringstream urlStream; std::stringstream urlStream;
char * data = NULL; char * data = NULL;
int dataStatus, dataLength; int dataStatus, dataLength;
urlStream << "http://" << SERVER << "/Browse/EditTag.json?Op=delete&ID=" << saveID << "&Tag=" << tag << "&Key=" << authUser.SessionKey;; urlStream << "http://" << SERVER << "/Browse/EditTag.json?Op=delete&ID=" << saveID << "&Tag=" << tag << "&Key=" << authUser.SessionKey;
if(authUser.ID) if(authUser.ID)
{ {
std::stringstream userIDStream; std::stringstream userIDStream;
@ -2274,7 +1929,8 @@ std::list<std::string> * Client::RemoveTag(int saveID, std::string tag)
lastError = "Not authenticated"; lastError = "Not authenticated";
return NULL; return NULL;
} }
if(dataStatus == 200 && data) RequestStatus ret = ParseServerReturn(data, dataStatus, true);
if (ret == RequestOkay)
{ {
try try
{ {
@ -2282,24 +1938,13 @@ std::list<std::string> * Client::RemoveTag(int saveID, std::string tag)
json::Object responseObject; json::Object responseObject;
json::Reader::Read(responseObject, dataStream); json::Reader::Read(responseObject, dataStream);
json::Number status = responseObject["Status"]; json::Array tagsArray = responseObject["Tags"];
tags = new std::list<std::string>();
if(status.Value()==0) for (size_t j = 0; j < tagsArray.Size(); j++)
{ {
json::String error = responseObject["Error"]; json::String tempTag = tagsArray[j];
lastError = error.Value(); tags->push_back(tempTag.Value());
}
else
{
json::Array tagsArray = responseObject["Tags"];
tags = new std::list<std::string>();
for (size_t j = 0; j < tagsArray.Size(); j++)
{
json::String tempTag = tagsArray[j];
tags->push_back(tempTag.Value());
}
} }
} }
catch (json::Exception &e) catch (json::Exception &e)
@ -2307,10 +1952,6 @@ std::list<std::string> * Client::RemoveTag(int saveID, std::string tag)
lastError = "Could not read response"; lastError = "Could not read response";
} }
} }
else
{
lastError = http_ret_text(dataStatus);
}
free(data); free(data);
return tags; return tags;
} }
@ -2334,7 +1975,8 @@ std::list<std::string> * Client::AddTag(int saveID, std::string tag)
lastError = "Not authenticated"; lastError = "Not authenticated";
return NULL; return NULL;
} }
if(dataStatus == 200 && data) RequestStatus ret = ParseServerReturn(data, dataStatus, true);
if (ret == RequestOkay)
{ {
try try
{ {
@ -2342,24 +1984,13 @@ std::list<std::string> * Client::AddTag(int saveID, std::string tag)
json::Object responseObject; json::Object responseObject;
json::Reader::Read(responseObject, dataStream); json::Reader::Read(responseObject, dataStream);
json::Number status = responseObject["Status"]; json::Array tagsArray = responseObject["Tags"];
tags = new std::list<std::string>();
if(status.Value()==0) for (size_t j = 0; j < tagsArray.Size(); j++)
{ {
json::String error = responseObject["Error"]; json::String tempTag = tagsArray[j];
lastError = error.Value(); tags->push_back(tempTag.Value());
}
else
{
json::Array tagsArray = responseObject["Tags"];
tags = new std::list<std::string>();
for (size_t j = 0; j < tagsArray.Size(); j++)
{
json::String tempTag = tagsArray[j];
tags->push_back(tempTag.Value());
}
} }
} }
catch (json::Exception &e) catch (json::Exception &e)
@ -2367,10 +1998,6 @@ std::list<std::string> * Client::AddTag(int saveID, std::string tag)
lastError = "Could not read response"; lastError = "Could not read response";
} }
} }
else
{
lastError = http_ret_text(dataStatus);
}
free(data); free(data);
return tags; return tags;
} }

View File

@ -146,11 +146,7 @@ public:
std::vector<SaveInfo*> * SearchSaves(int start, int count, std::string query, std::string sort, std::string category, int & resultCount); std::vector<SaveInfo*> * SearchSaves(int start, int count, std::string query, std::string sort, std::string category, int & resultCount);
std::vector<std::pair<std::string, int> > * GetTags(int start, int count, std::string query, int & resultCount); std::vector<std::pair<std::string, int> > * GetTags(int start, int count, std::string query, int & resultCount);
std::vector<SaveComment*> * GetComments(int saveID, int start, int count);
RequestBroker::Request * GetCommentsAsync(int saveID, int start, int count); RequestBroker::Request * GetCommentsAsync(int saveID, int start, int count);
Thumbnail * GetPreview(int saveID, int saveDate);
Thumbnail * GetThumbnail(int saveID, int saveDate);
SaveInfo * GetSave(int saveID, int saveDate); SaveInfo * GetSave(int saveID, int saveDate);
RequestBroker::Request * GetSaveAsync(int saveID, int saveDate); RequestBroker::Request * GetSaveAsync(int saveID, int saveDate);
@ -167,6 +163,7 @@ public:
std::string GetLastError() { std::string GetLastError() {
return lastError; return lastError;
} }
RequestStatus ParseServerReturn(char *result, int status, bool json);
void Tick(); void Tick();
void Shutdown(); void Shutdown();

View File

@ -38,6 +38,7 @@ RequestBroker::ProcessResponse APIRequest::Process(RequestBroker & rb)
int status, data_size; int status, data_size;
data = http_async_req_stop(HTTPContext, &status, &data_size); data = http_async_req_stop(HTTPContext, &status, &data_size);
Client::Ref().ParseServerReturn(data, status, true);
if (status == 200 && data) if (status == 200 && data)
{ {
void * resultObject = Parser->ProcessResponse((unsigned char *)data, data_size); void * resultObject = Parser->ProcessResponse((unsigned char *)data, data_size);
@ -51,25 +52,28 @@ RequestBroker::ProcessResponse APIRequest::Process(RequestBroker & rb)
} }
else else
{ {
#ifdef DEBUG
std::cout << typeid(*this).name() << " Request for " << URL << " could not be parsed: " << data << std::endl; std::cout << typeid(*this).name() << " Request for " << URL << " could not be parsed: " << data << std::endl;
#endif
free(data); free(data);
return RequestBroker::Failed; return RequestBroker::Failed;
} }
} }
else else
{ {
//#ifdef DEBUG #ifdef DEBUG
std::cout << typeid(*this).name() << " Request for " << URL << " failed with status " << status << std::endl; std::cout << typeid(*this).name() << " Request for " << URL << " failed with status " << status << std::endl;
//#endif #endif
free(data); free(data);
return RequestBroker::Failed; return RequestBroker::Failed;
} }
} }
} }
else else
{ {
#ifdef DEBUG
std::cout << typeid(*this).name() << " New Request for " << URL << std::endl; std::cout << typeid(*this).name() << " New Request for " << URL << std::endl;
#endif
if(Post) if(Post)
{ {
char ** postNames = new char*[PostData.size() + 1]; char ** postNames = new char*[PostData.size() + 1];

View File

@ -210,6 +210,8 @@ void RequestBroker::thumbnailQueueProcessTH()
resultStatus = r->Process(*this); resultStatus = r->Process(*this);
if(resultStatus == Duplicate || resultStatus == Failed || resultStatus == Finished) if(resultStatus == Duplicate || resultStatus == Failed || resultStatus == Finished)
{ {
if (resultStatus == Duplicate || resultStatus == Failed)
r->Listener.second->OnResponseFailed(r->Identifier);
req = activeRequests.erase(req); req = activeRequests.erase(req);
} }
else else

View File

@ -9,4 +9,5 @@ public:
virtual ~RequestListener() {} virtual ~RequestListener() {}
virtual void OnResponseReady(void * response, int identifier) {} virtual void OnResponseReady(void * response, int identifier) {}
virtual void OnResponseFailed(int identifier) {}
}; };

View File

@ -37,6 +37,7 @@ RequestBroker::ProcessResponse WebRequest::Process(RequestBroker & rb)
int status, data_size; int status, data_size;
data = http_async_req_stop(HTTPContext, &status, &data_size); data = http_async_req_stop(HTTPContext, &status, &data_size);
Client::Ref().ParseServerReturn(data, status, true);
if (status == 200 && data) if (status == 200 && data)
{ {
void * resultObject = new std::vector<unsigned char>(data, data+data_size); void * resultObject = new std::vector<unsigned char>(data, data+data_size);
@ -50,16 +51,18 @@ RequestBroker::ProcessResponse WebRequest::Process(RequestBroker & rb)
} }
else else
{ {
#ifdef DEBUG
std::cout << typeid(*this).name() << " Request for " << URL << " could not be parsed: " << data << std::endl; std::cout << typeid(*this).name() << " Request for " << URL << " could not be parsed: " << data << std::endl;
#endif
free(data); free(data);
return RequestBroker::Failed; return RequestBroker::Failed;
} }
} }
else else
{ {
//#ifdef DEBUG #ifdef DEBUG
std::cout << typeid(*this).name() << " Request for " << URL << " failed with status " << status << std::endl; std::cout << typeid(*this).name() << " Request for " << URL << " failed with status " << status << std::endl;
//#endif #endif
free(data); free(data);
return RequestBroker::Failed; return RequestBroker::Failed;
@ -68,7 +71,9 @@ RequestBroker::ProcessResponse WebRequest::Process(RequestBroker & rb)
} }
else else
{ {
#ifdef DEBUG
std::cout << typeid(*this).name() << " New Request for " << URL << std::endl; std::cout << typeid(*this).name() << " New Request for " << URL << std::endl;
#endif
if(Post) if(Post)
{ {
char ** postNames = new char*[PostData.size() + 1]; char ** postNames = new char*[PostData.size() + 1];
@ -95,7 +100,9 @@ RequestBroker::ProcessResponse WebRequest::Process(RequestBroker & rb)
if(Client::Ref().GetAuthUser().ID) if(Client::Ref().GetAuthUser().ID)
{ {
#ifdef DEBUG
std::cout << typeid(*this).name() << " Authenticated " << std::endl; std::cout << typeid(*this).name() << " Authenticated " << std::endl;
#endif
User user = Client::Ref().GetAuthUser(); User user = Client::Ref().GetAuthUser();
char userName[12]; char userName[12];
char *userSession = new char[user.SessionID.length() + 1]; char *userSession = new char[user.SessionID.length() + 1];

View File

@ -19,7 +19,7 @@ void LoginModel::Login(string username, string password)
loginStatus = true; loginStatus = true;
break; break;
case LoginError: case LoginError:
statusText = "Error: " + Client::Ref().GetLastError(); statusText = Client::Ref().GetLastError();
size_t banStart = statusText.find(". Ban expire in"); //TODO: temporary, remove this when the ban message is fixed size_t banStart = statusText.find(". Ban expire in"); //TODO: temporary, remove this when the ban message is fixed
if (banStart != statusText.npos) if (banStart != statusText.npos)
statusText.replace(banStart, 15, ". Login at http://powdertoy.co.uk in order to see the full ban reason. Ban expires in"); statusText.replace(banStart, 15, ". Login at http://powdertoy.co.uk in order to see the full ban reason. Ban expires in");

View File

@ -125,7 +125,7 @@ void PreviewController::Report(std::string message)
new ErrorMessage("Information", "Report submitted"); //TODO: InfoMessage new ErrorMessage("Information", "Report submitted"); //TODO: InfoMessage
} }
else else
new ErrorMessage("Error", "Unable file report"); new ErrorMessage("Error", "Unable file report: " + Client::Ref().GetLastError());
} }
void PreviewController::FavouriteSave() void PreviewController::FavouriteSave()

View File

@ -25,9 +25,9 @@ void PreviewModel::SetFavourite(bool favourite)
if (Client::Ref().FavouriteSave(save->id, favourite) == RequestOkay) if (Client::Ref().FavouriteSave(save->id, favourite) == RequestOkay)
save->Favourite = favourite; save->Favourite = favourite;
else if (favourite) else if (favourite)
throw PreviewModelException("Error, could not fav. the save, are you logged in?"); throw PreviewModelException("Error, could not fav. the save: " + Client::Ref().GetLastError());
else else
throw PreviewModelException("Error, could not unfav. the save, are you logged in?"); throw PreviewModelException("Error, could not unfav. the save: " + Client::Ref().GetLastError());
notifySaveChanged(); notifySaveChanged();
} }
} }
@ -158,7 +158,6 @@ void PreviewModel::OnResponseReady(void * object, int identifier)
saveComments = NULL; saveComments = NULL;
} }
saveComments = (std::vector<SaveComment*>*)object; saveComments = (std::vector<SaveComment*>*)object;
std::cout << object << std::endl;
commentsLoaded = true; commentsLoaded = true;
notifySaveCommentsChanged(); notifySaveCommentsChanged();
} }
@ -185,6 +184,30 @@ void PreviewModel::OnResponseReady(void * object, int identifier)
} }
} }
void PreviewModel::OnResponseFailed(int identifier)
{
if (identifier == 3)
{
if (saveComments)
{
for (size_t i = 0; i < saveComments->size(); i++)
delete saveComments->at(i);
saveComments->clear();
delete saveComments;
saveComments = NULL;
}
saveComments = NULL;
commentsLoaded = true;
notifySaveCommentsChanged();
}
else
{
for (size_t i = 0; i < observers.size(); i++)
{
observers[i]->SaveLoadingError(Client::Ref().GetLastError());
}
}
}
void PreviewModel::Update() void PreviewModel::Update()
{ {

View File

@ -55,6 +55,7 @@ public:
void SetDoOpen(bool doOpen); void SetDoOpen(bool doOpen);
void Update(); void Update();
virtual void OnResponseReady(void * object, int identifier); virtual void OnResponseReady(void * object, int identifier);
virtual void OnResponseFailed(int identifier);
virtual ~PreviewModel(); virtual ~PreviewModel();
}; };

View File

@ -15,6 +15,7 @@
#include "gui/interface/ScrollPanel.h" #include "gui/interface/ScrollPanel.h"
#include "gui/interface/AvatarButton.h" #include "gui/interface/AvatarButton.h"
#include "gui/interface/Keys.h" #include "gui/interface/Keys.h"
#include "gui/dialogues/ErrorMessage.h"
class PreviewView::LoginAction: public ui::ButtonAction class PreviewView::LoginAction: public ui::ButtonAction
{ {
@ -68,6 +69,8 @@ PreviewView::PreviewView():
submitCommentButton(NULL), submitCommentButton(NULL),
addCommentBox(NULL), addCommentBox(NULL),
doOpen(false), doOpen(false),
doError(false),
doErrorMessage(""),
showAvatars(true), showAvatars(true),
prevPage(false), prevPage(false),
commentBoxHeight(20) commentBoxHeight(20)
@ -365,6 +368,11 @@ void PreviewView::OnTick(float dt)
} }
c->Update(); c->Update();
if (doError)
{
ErrorMessage::Blocking("Error loading save", doErrorMessage);
c->Exit();
}
} }
void PreviewView::OnTryExit(ExitMethod method) void PreviewView::OnTryExit(ExitMethod method)
@ -528,6 +536,12 @@ void PreviewView::NotifyCommentBoxEnabledChanged(PreviewModel * sender)
} }
} }
void PreviewView::SaveLoadingError(std::string errorMessage)
{
doError = true;
doErrorMessage = errorMessage;
}
void PreviewView::NotifyCommentsPageChanged(PreviewModel * sender) void PreviewView::NotifyCommentsPageChanged(PreviewModel * sender)
{ {
std::stringstream pageInfoStream; std::stringstream pageInfoStream;
@ -609,6 +623,8 @@ void PreviewView::NotifyCommentsChanged(PreviewModel * sender)
commentsPanel->SetScrollPosition(currentY); commentsPanel->SetScrollPosition(currentY);
} }
} }
//else if (sender->GetCommentsLoaded())
// ErrorMessage::Blocking("Error loading comments", Client::Ref().GetLastError());
} }
PreviewView::~PreviewView() PreviewView::~PreviewView()

View File

@ -48,6 +48,8 @@ class PreviewView: public ui::Window {
int votesUp; int votesUp;
int votesDown; int votesDown;
bool doOpen; bool doOpen;
bool doError;
std::string doErrorMessage;
bool showAvatars; bool showAvatars;
bool prevPage; bool prevPage;
@ -67,6 +69,7 @@ public:
void NotifyCommentsChanged(PreviewModel * sender); void NotifyCommentsChanged(PreviewModel * sender);
void NotifyCommentsPageChanged(PreviewModel * sender); void NotifyCommentsPageChanged(PreviewModel * sender);
void NotifyCommentBoxEnabledChanged(PreviewModel * sender); void NotifyCommentBoxEnabledChanged(PreviewModel * sender);
void SaveLoadingError(std::string errorMessage);
virtual void OnDraw(); virtual void OnDraw();
virtual void DoDraw(); virtual void DoDraw();
virtual void OnTick(float dt); virtual void OnTick(float dt);

View File

@ -6,6 +6,7 @@
#include "gui/interface/AvatarButton.h" #include "gui/interface/AvatarButton.h"
#include "gui/interface/ScrollPanel.h" #include "gui/interface/ScrollPanel.h"
#include "gui/interface/Keys.h" #include "gui/interface/Keys.h"
#include "gui/dialogues/ErrorMessage.h"
#include "gui/Style.h" #include "gui/Style.h"
#include "client/Client.h" #include "client/Client.h"
#include "client/UserInfo.h" #include "client/UserInfo.h"
@ -15,7 +16,9 @@
ProfileActivity::ProfileActivity(std::string username) : ProfileActivity::ProfileActivity(std::string username) :
WindowActivity(ui::Point(-1, -1), ui::Point(236, 300)), WindowActivity(ui::Point(-1, -1), ui::Point(236, 300)),
loading(false), loading(false),
saving(false) saving(false),
doError(false),
doErrorMessage("")
{ {
editable = Client::Ref().GetAuthUser().ID && Client::Ref().GetAuthUser().Username == username; editable = Client::Ref().GetAuthUser().ID && Client::Ref().GetAuthUser().Username == username;
@ -241,6 +244,24 @@ void ProfileActivity::OnResponseReady(void * userDataPtr, int identifier)
} }
} }
void ProfileActivity::OnResponseFailed(int identifier)
{
doError = true;
if (loading)
doErrorMessage = "Could not load user info: " + Client::Ref().GetLastError();
else if (saving)
doErrorMessage = "Could not save user info: " + Client::Ref().GetLastError();
}
void ProfileActivity::OnTick(float dt)
{
if (doError)
{
ErrorMessage::Blocking("Error", doErrorMessage);
Exit();
}
}
void ProfileActivity::OnDraw() void ProfileActivity::OnDraw()
{ {
Graphics * g = ui::Engine::Ref().g; Graphics * g = ui::Engine::Ref().g;

View File

@ -20,11 +20,15 @@ class ProfileActivity: public WindowActivity, public RequestListener {
bool editable; bool editable;
bool loading; bool loading;
bool saving; bool saving;
bool doError;
std::string doErrorMessage;
void setUserInfo(UserInfo newInfo); void setUserInfo(UserInfo newInfo);
public: public:
ProfileActivity(std::string username); ProfileActivity(std::string username);
virtual ~ProfileActivity(); virtual ~ProfileActivity();
virtual void OnResponseReady(void * userDataPtr, int identifier); virtual void OnResponseReady(void * userDataPtr, int identifier);
virtual void OnResponseFailed(int identifier);
virtual void OnTick(float dt);
virtual void OnDraw(); virtual void OnDraw();
virtual void OnTryExit(ExitMethod method); virtual void OnTryExit(ExitMethod method);

View File

@ -268,8 +268,8 @@ void SearchController::removeSelectedC()
if (Client::Ref().DeleteSave(saves[i])!=RequestOkay) if (Client::Ref().DeleteSave(saves[i])!=RequestOkay)
{ {
std::stringstream saveIDF; std::stringstream saveIDF;
saveIDF << "\boFailed to delete [" << saves[i] << "] ..."; saveIDF << "\boFailed to delete [" << saves[i] << "]: " << Client::Ref().GetLastError();
notifyStatus(saveIDF.str()); notifyError(saveIDF.str());
c->Refresh(); c->Refresh();
return false; return false;
} }
@ -350,7 +350,10 @@ void SearchController::unpublishSelectedC(bool publish)
if (!ret) if (!ret)
{ {
std::stringstream error; std::stringstream error;
error << "\boFailed to " << (publish ? "Publish" : "Unpublish") << " [" << saves[i] << "], is this save yours?"; if (publish) // uses html page so error message will be spam
error << "\boFailed to publish [" << saves[i] << "], is this save yours?";
else
error << "\boFailed to unpublish [" << saves[i] << "]: " + Client::Ref().GetLastError();
notifyError(error.str()); notifyError(error.str());
c->Refresh(); c->Refresh();
return false; return false;
@ -383,7 +386,7 @@ void SearchController::FavouriteSelected()
if (Client::Ref().FavouriteSave(saves[i], true)!=RequestOkay) if (Client::Ref().FavouriteSave(saves[i], true)!=RequestOkay)
{ {
std::stringstream saveIDF; std::stringstream saveIDF;
saveIDF << "\boFailed to favourite [" << saves[i] << "], are you logged in?"; saveIDF << "\boFailed to favourite [" << saves[i] << "]: " + Client::Ref().GetLastError();
notifyError(saveIDF.str()); notifyError(saveIDF.str());
return false; return false;
} }
@ -408,7 +411,7 @@ void SearchController::FavouriteSelected()
if (Client::Ref().FavouriteSave(saves[i], false)!=RequestOkay) if (Client::Ref().FavouriteSave(saves[i], false)!=RequestOkay)
{ {
std::stringstream saveIDF; std::stringstream saveIDF;
saveIDF << "\boFailed to unfavourite [" << saves[i] << "], are you logged in?"; saveIDF << "\boFailed to unfavourite [" << saves[i] << "]: " + Client::Ref().GetLastError();
notifyError(saveIDF.str()); notifyError(saveIDF.str());
return false; return false;
} }