summaryrefslogtreecommitdiff
path: root/src/client
diff options
context:
space:
mode:
authorSimon Robertshaw <simon@hardwired.org.uk>2013-03-21 21:49:06 (GMT)
committer Simon Robertshaw <simon@hardwired.org.uk>2013-03-21 21:49:06 (GMT)
commit81a34222d1797f112a65c30f9ef7db07562ffdf1 (patch)
tree4a7500b25f58cf13a4744ea75ae855c0495d5613 /src/client
parentb4564f212a17539604e9fa63d649e157f8888eb1 (diff)
downloadpowder-81a34222d1797f112a65c30f9ef7db07562ffdf1.zip
powder-81a34222d1797f112a65c30f9ef7db07562ffdf1.tar.gz
POST requests for APIRequest, allow saving user details from within the game, Asynchronous HTTP POST
Diffstat (limited to 'src/client')
-rw-r--r--src/client/Client.cpp43
-rw-r--r--src/client/Client.h5
-rw-r--r--src/client/HTTP.cpp191
-rw-r--r--src/client/HTTP.h1
-rw-r--r--src/client/UserInfo.h7
-rw-r--r--src/client/requestbroker/APIRequest.cpp65
-rw-r--r--src/client/requestbroker/APIRequest.h4
7 files changed, 308 insertions, 8 deletions
diff --git a/src/client/Client.cpp b/src/client/Client.cpp
index dcd4903..ef457b9 100644
--- a/src/client/Client.cpp
+++ b/src/client/Client.cpp
@@ -3,6 +3,7 @@
#include <sstream>
#include <string>
#include <vector>
+#include <map>
#include <iomanip>
#include <time.h>
#include <stdio.h>
@@ -1181,6 +1182,40 @@ std::vector<unsigned char> Client::GetSaveData(int saveID, int saveDate)
return saveData;
}
+RequestBroker::Request * Client::SaveUserInfoAsync(UserInfo info)
+{
+ class StatusParser: public APIResultParser
+ {
+ virtual void * ProcessResponse(unsigned char * data, int dataLength)
+ {
+ try
+ {
+ std::istringstream dataStream((char*)data);
+ json::Object objDocument;
+ json::Reader::Read(objDocument, dataStream);
+ json::Number tempStatus = objDocument["Status"];
+
+ bool returnValue = tempStatus.Value() == 1;
+
+ return (void*)(returnValue ? 1 : 0);
+ }
+ catch (json::Exception &e)
+ {
+ return 0;
+ }
+ }
+ virtual void Cleanup(void * objectPtr)
+ {
+ //delete (UserInfo*)objectPtr;
+ }
+ virtual ~StatusParser() { }
+ };
+ 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>("Biography", info.Biography));
+ return new APIRequest("http://" SERVER "/Profile.json", postData, new StatusParser());
+}
+
RequestBroker::Request * Client::GetUserInfoAsync(std::string username)
{
class UserInfoParser: public APIResultParser
@@ -1197,13 +1232,15 @@ RequestBroker::Request * Client::GetUserInfoAsync(std::string username)
json::Number userIDTemp = tempUser["ID"];
json::String usernameTemp = tempUser["Username"];
json::String bioTemp = tempUser["Biography"];
- //json::Number ageTemp = tempUser["Age"];
+ json::String locationTemp = tempUser["Location"];
+ json::Number ageTemp = tempUser["Age"];
return new UserInfo(
userIDTemp.Value(),
- 0,//ageTemp.Value(),
+ ageTemp.Value(),
usernameTemp.Value(),
- bioTemp.Value());
+ bioTemp.Value(),
+ locationTemp.Value());
}
catch (json::Exception &e)
{
diff --git a/src/client/Client.h b/src/client/Client.h
index f00083d..085c60a 100644
--- a/src/client/Client.h
+++ b/src/client/Client.h
@@ -9,6 +9,7 @@
#include "Singleton.h"
#include "User.h"
+#include "UserInfo.h"
#include "cajun/elements.h"
@@ -93,6 +94,9 @@ public:
std::vector<std::string> DirectorySearch(std::string directory, std::string search, std::vector<std::string> extensions);
std::vector<std::string> DirectorySearch(std::string directory, std::string search, std::string extension);
+ std::string FileOpenDialogue();
+ //std::string FileSaveDialogue();
+
bool DoInstallation();
std::vector<unsigned char> ReadFile(std::string filename);
@@ -130,6 +134,7 @@ public:
//Retrieves a "UserInfo" object
RequestBroker::Request * GetUserInfoAsync(std::string username);
+ RequestBroker::Request * SaveUserInfoAsync(UserInfo info);
unsigned char * GetSaveData(int saveID, int saveDate, int & dataLength);
std::vector<unsigned char> GetSaveData(int saveID, int saveDate);
diff --git a/src/client/HTTP.cpp b/src/client/HTTP.cpp
index 5fc4d08..c3110f5 100644
--- a/src/client/HTTP.cpp
+++ b/src/client/HTTP.cpp
@@ -1102,3 +1102,194 @@ fail:
*len = 0;
return NULL;
}
+
+
+void *http_multipart_post_async(char *uri, char **names, char **parts, int *plens, char *user, char *pass, char *session_id)
+{
+ void *ctx;
+ char *data = NULL, *tmp, *p;
+ int dlen = 0, i, j;
+ unsigned char hash[16];
+ unsigned char boundary[32], ch;
+ int blen = 0;
+ unsigned int map[62], m;
+ struct md5_context md5;
+ //struct md5_context md52;
+ int own_plen = 0;
+
+ if (names)
+ {
+ if (!plens)
+ {
+ own_plen = 1;
+ for (i=0; names[i]; i++) ;
+ plens = (int *)calloc(i, sizeof(int));
+ for (i=0; names[i]; i++)
+ plens[i] = strlen(parts[i]);
+ }
+
+retry:
+ if (blen >= 31)
+ goto fail;
+ memset(map, 0, 62*sizeof(int));
+ for (i=0; names[i]; i++)
+ {
+ for (j=0; j<plens[i]-blen; j++)
+ if (!blen || !memcmp(parts[i]+j, boundary, blen))
+ {
+ ch = parts[i][j+blen];
+ if (ch>='0' && ch<='9')
+ map[ch-'0']++;
+ else if (ch>='A' && ch<='Z')
+ map[ch-'A'+10]++;
+ else if (ch>='a' && ch<='z')
+ map[ch-'a'+36]++;
+ }
+ }
+ m = ~0;
+ j = 61;
+ for (i=0; i<62; i++)
+ if (map[i]<m)
+ {
+ m = map[i];
+ j = i;
+ }
+ if (j<10)
+ boundary[blen] = '0'+j;
+ else if (j<36)
+ boundary[blen] = 'A'+(j-10);
+ else
+ boundary[blen] = 'a'+(j-36);
+ blen++;
+ if (map[j])
+ goto retry;
+ boundary[blen] = 0;
+
+ for (i=0; names[i]; i++)
+ dlen += blen+strlen(names[i])+plens[i]+128;
+ dlen += blen+8;
+ data = (char *)malloc(dlen);
+ dlen = 0;
+ for (i=0; names[i]; i++)
+ {
+ dlen += sprintf(data+dlen, "--%s\r\n", boundary);
+ dlen += sprintf(data+dlen, "Content-transfer-encoding: binary\r\n");
+ if (strchr(names[i], ':'))
+ {
+ tmp = mystrdup(names[i]);
+ p = strchr(tmp, ':');
+ *p = 0;
+ dlen += sprintf(data+dlen, "content-disposition: form-data; name=\"%s\"; ", tmp);
+ free(tmp);
+ p = strchr(names[i], ':');
+ dlen += sprintf(data+dlen, "filename=\"%s\"\r\n\r\n", p+1);
+ }
+ else
+ dlen += sprintf(data+dlen, "content-disposition: form-data; name=\"%s\"\r\n\r\n", names[i]);
+ memcpy(data+dlen, parts[i], plens[i]);
+ dlen += plens[i];
+ dlen += sprintf(data+dlen, "\r\n");
+ }
+ dlen += sprintf(data+dlen, "--%s--\r\n", boundary);
+ }
+
+ ctx = http_async_req_start(NULL, uri, data, dlen, 0);
+ if (!ctx)
+ goto fail;
+
+ if (user)
+ {
+ //http_async_add_header(ctx, "X-Auth-User", user);
+ if (pass)
+ {
+ md5_init(&md5);
+ md5_update(&md5, (unsigned char *)user, strlen(user));
+ md5_update(&md5, (unsigned char *)"-", 1);
+ m = 0;
+ if (names)
+ {
+ for (i=0; names[i]; i++)
+ {
+ //md5_update(&md5, (unsigned char *)parts[i], plens[i]); //WHY?
+ //md5_update(&md5, (unsigned char *)"-", 1);
+ p = strchr(names[i], ':');
+ if (p)
+ m += (p - names[i]) + 1;
+ else
+ m += strlen(names[i])+1;
+ }
+
+ tmp = (char *)malloc(m);
+ m = 0;
+ for (i=0; names[i]; i++)
+ {
+ p = strchr(names[i], ':');
+ if (m)
+ {
+ tmp[m] = ' ';
+ m ++;
+ }
+ if (p)
+ {
+ memcpy(tmp+m, names[i], p-names[i]);
+ m += p - names[i];
+ }
+ else
+ {
+ strcpy(tmp+m, names[i]);
+ m += strlen(names[i]);
+ }
+ }
+ tmp[m] = 0;
+ http_async_add_header(ctx, "X-Auth-Objects", tmp);
+ free(tmp);
+ }
+
+ md5_update(&md5, (unsigned char *)pass, strlen(pass));
+ md5_final(hash, &md5);
+ tmp = (char *)malloc(33);
+ for (i=0; i<16; i++)
+ {
+ tmp[i*2] = hexChars[hash[i]>>4];
+ tmp[i*2+1] = hexChars[hash[i]&15];
+ }
+ tmp[32] = 0;
+ http_async_add_header(ctx, "X-Auth-Hash", tmp);
+ free(tmp);
+ }
+ if (session_id)
+ {
+ http_async_add_header(ctx, "X-Auth-User-Id", user);
+ http_async_add_header(ctx, "X-Auth-Session-Key", session_id);
+ }
+ else
+ {
+ http_async_add_header(ctx, "X-Auth-User", user);
+ }
+ }
+
+ if (data)
+ {
+ tmp = (char *)malloc(32+strlen((char *)boundary));
+ sprintf(tmp, "multipart/form-data, boundary=%s", boundary);
+ http_async_add_header(ctx, "Content-type", tmp);
+ free(tmp);
+ free(data);
+ }
+
+ if (own_plen)
+ free(plens);
+
+ return ctx;
+
+fail:
+ if (data)
+ free(data);
+ if (own_plen)
+ free(plens);
+ //if (ret)
+ // *ret = 600;
+ //if (len)
+ // *len = 0;
+ return NULL;
+}
diff --git a/src/client/HTTP.h b/src/client/HTTP.h
index 51b9438..c83284a 100644
--- a/src/client/HTTP.h
+++ b/src/client/HTTP.h
@@ -39,6 +39,7 @@ char *http_async_req_stop(void *ctx, int *ret, int *len);
void http_async_req_close(void *ctx);
char *http_multipart_post(char *uri, char **names, char **parts, int *plens, char *user, char *pass, char * session_id, int *ret, int *len);
+void *http_multipart_post_async(char *uri, char **names, char **parts, int *plens, char *user, char *pass, char * session_id);
char *http_ret_text(int ret);
diff --git a/src/client/UserInfo.h b/src/client/UserInfo.h
index edd6659..2df0015 100644
--- a/src/client/UserInfo.h
+++ b/src/client/UserInfo.h
@@ -10,12 +10,15 @@ public:
int Age;
std::string Username;
std::string Biography;
- UserInfo(int id, int age, std::string username, std::string biography):
+ std::string Location;
+ UserInfo(int id, int age, std::string username, std::string biography, std::string location):
ID(id),
Age(age),
Username(username),
- Biography(biography)
+ Biography(biography),
+ Location(location)
{ }
+ UserInfo() {}
};
diff --git a/src/client/requestbroker/APIRequest.cpp b/src/client/requestbroker/APIRequest.cpp
index 71d683f..811096d 100644
--- a/src/client/requestbroker/APIRequest.cpp
+++ b/src/client/requestbroker/APIRequest.cpp
@@ -1,6 +1,10 @@
#include <iostream>
#include <typeinfo>
#include <cstdlib>
+#include <cstring>
+#include "Config.h"
+#include "Format.h"
+#include "client/Client.h"
#include "APIRequest.h"
#include "client/HTTP.h"
#include "APIResultParser.h"
@@ -8,6 +12,17 @@
APIRequest::APIRequest(std::string url, APIResultParser * parser, ListenerHandle listener):
RequestBroker::Request(API, listener)
{
+ Post = false;
+ HTTPContext = NULL;
+ Parser = parser;
+ URL = url;
+}
+
+APIRequest::APIRequest(std::string url, std::map<std::string, std::string> postData, APIResultParser * parser, ListenerHandle listener):
+ RequestBroker::Request(API, listener)
+{
+ Post = true;
+ PostData = postData;
HTTPContext = NULL;
Parser = parser;
URL = url;
@@ -26,17 +41,18 @@ RequestBroker::ProcessResponse APIRequest::Process(RequestBroker & rb)
if (status == 200 && data)
{
void * resultObject = Parser->ProcessResponse((unsigned char *)data, data_size);
- free(data);
if(resultObject)
{
this->ResultObject = resultObject;
rb.requestComplete(this);
+ free(data);
return RequestBroker::Finished;
}
else
{
- std::cout << typeid(*this).name() << " Request for " << URL << " could not be parsed" << status << std::endl;
+ std::cout << typeid(*this).name() << " Request for " << URL << " could not be parsed: " << data << std::endl;
+ free(data);
return RequestBroker::Failed;
}
}
@@ -55,7 +71,50 @@ RequestBroker::ProcessResponse APIRequest::Process(RequestBroker & rb)
else
{
std::cout << typeid(*this).name() << " New Request for " << URL << std::endl;
- HTTPContext = http_async_req_start(NULL, (char *)URL.c_str(), NULL, 0, 0);
+ if(Post)
+ {
+ char ** postNames = new char*[PostData.size() + 1];
+ char ** postData = new char*[PostData.size()];
+ int * postLength = new int[PostData.size()];
+
+ int i = 0;
+ std::map<std::string, std::string>::iterator iter = PostData.begin();
+ while(iter != PostData.end())
+ {
+ std::string name = iter->first;
+ std::string data = iter->second;
+ char * cName = new char[name.length() + 1];
+ char * cData = new char[data.length() + 1];
+ std::strcpy(cName, name.c_str());
+ std::strcpy(cData, data.c_str());
+ postNames[i] = cName;
+ postData[i] = cData;
+ postLength[i] = data.length();
+ i++;
+ iter++;
+ }
+ postNames[i] = NULL;
+
+ if(Client::Ref().GetAuthUser().ID)
+ {
+ std::cout << typeid(*this).name() << " Authenticated " << std::endl;
+ User user = Client::Ref().GetAuthUser();
+ char userName[12];
+ char userSession[user.SessionID.length() + 1];
+ std::strcpy(userName, format::NumberToString<int>(user.ID).c_str());
+ std::strcpy(userSession, user.SessionID.c_str());
+ HTTPContext = http_multipart_post_async((char*)URL.c_str(), postNames, postData, postLength, userName, NULL, userSession);
+ }
+ else
+ {
+ HTTPContext = http_multipart_post_async((char*)URL.c_str(), postNames, postData, postLength, NULL, NULL, NULL);
+ }
+
+ }
+ else
+ {
+ HTTPContext = http_async_req_start(NULL, (char *)URL.c_str(), NULL, 0, 0);
+ }
//RequestTime = time(NULL);
}
return RequestBroker::OK;
diff --git a/src/client/requestbroker/APIRequest.h b/src/client/requestbroker/APIRequest.h
index 2d41eb6..a20fc99 100644
--- a/src/client/requestbroker/APIRequest.h
+++ b/src/client/requestbroker/APIRequest.h
@@ -1,13 +1,17 @@
+#include <map>
#include "RequestBroker.h"
class APIResultParser;
class APIRequest: public RequestBroker::Request
{
public:
+ bool Post;
APIResultParser * Parser;
std::string URL;
+ std::map<std::string, std::string> PostData;
void * HTTPContext;
APIRequest(std::string url, APIResultParser * parser, ListenerHandle listener = ListenerHandle(0, 0));
+ APIRequest(std::string url, std::map<std::string, std::string>, APIResultParser * parser, ListenerHandle listener = ListenerHandle(0, 0));
virtual RequestBroker::ProcessResponse Process(RequestBroker & rb);
virtual ~APIRequest();
virtual void Cleanup();