diff options
| author | Simon 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) |
| commit | 81a34222d1797f112a65c30f9ef7db07562ffdf1 (patch) | |
| tree | 4a7500b25f58cf13a4744ea75ae855c0495d5613 /src/client | |
| parent | b4564f212a17539604e9fa63d649e157f8888eb1 (diff) | |
| download | powder-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.cpp | 43 | ||||
| -rw-r--r-- | src/client/Client.h | 5 | ||||
| -rw-r--r-- | src/client/HTTP.cpp | 191 | ||||
| -rw-r--r-- | src/client/HTTP.h | 1 | ||||
| -rw-r--r-- | src/client/UserInfo.h | 7 | ||||
| -rw-r--r-- | src/client/requestbroker/APIRequest.cpp | 65 | ||||
| -rw-r--r-- | src/client/requestbroker/APIRequest.h | 4 |
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(); |
