Skip to content

Commit

Permalink
Created game suggestion form, 'add game' button, and working POST-bas…
Browse files Browse the repository at this point in the history
…ed backend
  • Loading branch information
korslund committed Jul 5, 2013
1 parent 8bdf858 commit 50752a4
Show file tree
Hide file tree
Showing 11 changed files with 373 additions and 5 deletions.
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ set(TLDIR ${TIG}/tiglib)
set(WDIR ${TIG}/wx)
set(AWDIR ${TIG}/app_wx)

set(MISC ${MIDIR}/dirfinder.cpp ${MIDIR}/lockfile.cpp ${MIDIR}/freespace.cpp ${MIDIR}/fetch.cpp)
set(MISC ${MIDIR}/dirfinder.cpp ${MIDIR}/lockfile.cpp ${MIDIR}/freespace.cpp ${MIDIR}/fetch.cpp ${MIDIR}/curl_post.cpp)
set(MANGLE ${MDIR}/stream/clients/io_stream.cpp)
set(GAMEINFO ${GIDIR}/stats_json.cpp ${GIDIR}/tigloader.cpp)
set(LIST ${LDIR}/sortlist.cpp ${LDIR}/listbase.cpp ${LDIR}/picklist.cpp ${LDIR}/parentbase.cpp)
Expand Down
42 changes: 42 additions & 0 deletions app_wx/gamedata.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@
#include <boost/filesystem.hpp>
#include <spread/misc/readjson.hpp>
#include "launcher/run.hpp"
#include "misc/curl_post.hpp"
#include <spread/tasks/download.hpp>
#include <spread/job/thread.hpp>

namespace bf = boost::filesystem;
using namespace TigData;
Expand Down Expand Up @@ -79,6 +82,45 @@ void wxTigApp::GameData::updateRunning(int64_t cur, int64_t total)
listener->displayProgress("Downloading data update:", cur, total);
}

struct PostJob : Spread::Job
{
cURL::PostRequest post;
std::string url;

void doJob()
{
setBusy("Uploading to " + url);
assert(url != "");
post.upload(url, Spread::DownloadTask::userAgent);
setDone();
}
};

void wxTigApp::GameData::submitGame(const std::string &title, const std::string &homepage,
const std::string &shot, const std::string &download,
const std::string &version, const std::string &devname,
const std::string &tags, const std::string &type,
const std::string &desc)
{
PostJob *job = new PostJob;

cURL::PostRequest::StrMap &v = job->post.fields;

job->url = "http://tiggit.net/suggest.php";

v["title"] = title;
v["homepage"] = homepage;
v["shot"] = shot;
v["download"] = download;
v["version"] = version;
v["devname"] = devname;
v["tags"] = tags;
v["type"] = type;
v["desc"] = desc;

Spread::Thread::run(job);
}

void wxTigApp::GameData::updateReady()
{
PRINT("GameData::updateReady()");
Expand Down
6 changes: 6 additions & 0 deletions app_wx/gamedata.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,12 @@ namespace wxTigApp

bool isActive();

void submitGame(const std::string &title, const std::string &homepage,
const std::string &shot, const std::string &download,
const std::string &version, const std::string &devname,
const std::string &tags, const std::string &type,
const std::string &desc);

// Notify us that the main dataset is currently updating
void updateRunning(int64_t cur, int64_t total);

Expand Down
101 changes: 101 additions & 0 deletions misc/curl_post.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
#include "curl_post.hpp"
#include <curl/curl.h>
#include <assert.h>
#include <stdexcept>

using namespace cURL;

/* Dummy writer that discards returned data from the server. May redo
this later to match spread/tasks/curl.cpp if we want to use
returned data at some point.
*/
static size_t streamWrite(void *buffer, size_t size, size_t num, void *strm)
{
return 0;
}

void PostRequest::upload(const std::string &url, const std::string &useragent, bool disableExpect100)
{
CURL *curl = curl_easy_init();
assert(curl);

curl_httppost *formpost=NULL;
curl_httppost *lastptr=NULL;
curl_slist *headerlist=NULL;
static const char buf[] = "Expect:";

for(StrMap::const_iterator it=fields.begin(); it != fields.end(); it++)
{
curl_formadd(&formpost, &lastptr,
CURLFORM_PTRNAME, it->first.c_str(),
CURLFORM_PTRCONTENTS, it->second.c_str(),
CURLFORM_END);
}

for(StrMap::const_iterator it=files.begin(); it != files.end(); it++)
{
curl_formadd(&formpost, &lastptr,
CURLFORM_PTRNAME, it->first.c_str(),
CURLFORM_FILE, it->second.c_str(),
CURLFORM_END);
}

for(BufMap::const_iterator it=buffers.begin(); it != buffers.end(); it++)
{
curl_formadd(&formpost, &lastptr,
CURLFORM_PTRNAME, it->first.c_str(),
CURLFORM_BUFFER, it->second.filename.c_str(),
CURLFORM_BUFFERPTR, it->second.ptr,
CURLFORM_BUFFERLENGTH, it->second.size,
CURLFORM_END);
}

if(disableExpect100)
{
headerlist = curl_slist_append(headerlist, buf);
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headerlist);
}

curl_easy_setopt(curl, CURLOPT_HTTPPOST, formpost);

// URL
curl_easy_setopt(curl, CURLOPT_URL, url.c_str());

// Set write function so CURL doesn't dump return data to stdout
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, streamWrite);

// For https. Ignore security and just trust the server blindly.
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0);
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0);

// This is required for multithreading
curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);

// We need to be able to follow redirects
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1);
curl_easy_setopt(curl, CURLOPT_MAXREDIRS, 30);

// Don't silently accept failed requests
curl_easy_setopt(curl, CURLOPT_FAILONERROR, 1);

// Pass along referer information whenever we're following a
// redirect.
curl_easy_setopt(curl, CURLOPT_AUTOREFERER, 1);

// Set user agent string
curl_easy_setopt(curl, CURLOPT_USERAGENT, useragent.c_str());

CURLcode res = curl_easy_perform(curl);

// Cleanup
curl_easy_cleanup(curl);
curl_formfree(formpost);
if(headerlist)
curl_slist_free_all(headerlist);

if(res != CURLE_OK && res != CURLE_ABORTED_BY_CALLBACK)
{
std::string msg = curl_easy_strerror(res);
throw std::runtime_error("Error fetching " + url + ":\n" + msg);
}
}
43 changes: 43 additions & 0 deletions misc/curl_post.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
#ifndef __CURL_POST_HPP_
#define __CURL_POST_HPP_

#include <string>
#include <map>

/* Send POST information to an online web form using libCURL.
*/
namespace cURL
{
struct PostRequest
{
struct FileBuf
{
std::string filename;
void *ptr; // NOTE: Data must be kept in memory until upload is
// finished.
long size;
};

typedef std::map<std::string, std::string> StrMap;
typedef std::map<std::string, FileBuf> BufMap;

StrMap fields; // Form fields listed in fieldname-value format
StrMap files; // Files to upload, in fieldname-filename format
BufMap buffers; // Alternative way to specify files using memory
// buffers.

/* Perform POST request. Fill out the above members before calling
this function. All referenced data must be kept available until
the function returns.
The disableExpect100 value, if set, disables the "Expect:
100-continue" header (by setting a blank "Expect:" header
instead.) Disabling it is apparently necessary on some servers
that do not implement HTTP 1.1 correctly.
*/
void upload(const std::string &url, const std::string &useragent,
bool disableExpect100=true);
};
}

#endif
Loading

0 comments on commit 50752a4

Please sign in to comment.