Browse Source

Added version checking

tags/v0.3.2
Andrew Belt 7 years ago
parent
commit
8088a0c7ec
9 changed files with 117 additions and 83 deletions
  1. +1
    -0
      include/gui.hpp
  2. +0
    -1
      include/plugin.hpp
  3. +4
    -0
      include/util.hpp
  4. +2
    -2
      src/app/PluginManagerWidget.cpp
  5. +1
    -1
      src/app/RackScene.cpp
  6. +4
    -0
      src/gui.cpp
  7. +94
    -66
      src/plugin.cpp
  8. +0
    -1
      src/util.cpp
  9. +11
    -12
      src/util/request.cpp

+ 1
- 0
include/gui.hpp View File

@@ -24,6 +24,7 @@ extern float gPixelRatio;
void guiInit();
void guiDestroy();
void guiRun();
void guiClose();
void guiCursorLock();
void guiCursorUnlock();
bool guiIsModPressed();


+ 0
- 1
include/plugin.hpp View File

@@ -37,7 +37,6 @@ extern std::string gToken;

void pluginInit();
void pluginDestroy();

void pluginLogIn(std::string email, std::string password);
void pluginLogOut();
void pluginRefresh();


+ 4
- 0
include/util.hpp View File

@@ -52,6 +52,10 @@ std::string stringf(const char *format, ...);
/** Truncates and adds "..." to a string, not exceeding `len` characters */
std::string ellipsize(std::string s, size_t len);

/** Opens a URL, also happens to work with PDFs and folders.
Shell injection is possible, so make sure the URL is trusted or hard coded.
May block, so open in a new thread.
*/
void openBrowser(std::string url);

/** Threads which obtain a VIPLock will cause wait() to block for other less important threads.


+ 2
- 2
src/app/PluginManagerWidget.cpp View File

@@ -16,7 +16,7 @@ PluginManagerWidget::PluginManagerWidget() {

struct RegisterButton : Button {
void onAction() {
std::thread t(openBrowser, "http://vcvrack.com/");
std::thread t(openBrowser, "https://vcvrack.com/");
t.detach();
}
};
@@ -80,7 +80,7 @@ PluginManagerWidget::PluginManagerWidget() {

struct ManageButton : Button {
void onAction() {
std::thread t(openBrowser, "http://vcvrack.com/");
std::thread t(openBrowser, "https://vcvrack.com/");
t.detach();
}
};


+ 1
- 1
src/app/RackScene.cpp View File

@@ -39,7 +39,7 @@ Widget *RackScene::onHoverKey(Vec pos, int key) {
break;
case GLFW_KEY_Q:
if (guiIsModPressed()) {
glfwSetWindowShouldClose(gWindow, GLFW_TRUE);
guiClose();
return this;
}
break;


+ 4
- 0
src/gui.cpp View File

@@ -301,6 +301,10 @@ void guiRun() {
}
}

void guiClose() {
glfwSetWindowShouldClose(gWindow, GLFW_TRUE);
}

void guiCursorLock() {
#ifdef ARCH_MAC
glfwSetInputMode(gWindow, GLFW_CURSOR, GLFW_CURSOR_HIDDEN);


+ 94
- 66
src/plugin.cpp View File

@@ -3,6 +3,7 @@
#include <assert.h>
#include <string.h>
#include <unistd.h>
#include <thread>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/param.h> // for MAXPATHLEN
@@ -21,7 +22,9 @@
#include <dirent.h>

#include "plugin.hpp"
#include "gui.hpp" // for guiClose
#include "util/request.hpp"
#include "../ext/osdialog/osdialog.h"


namespace rack {
@@ -34,6 +37,8 @@ static float downloadProgress = 0.0;
static std::string downloadName;
static std::string loginStatus;

static std::string apiHost = "http://api.vcvrack.com";


Plugin::~Plugin() {
for (Model *model : models) {
@@ -41,7 +46,6 @@ Plugin::~Plugin() {
}
}


static int loadPlugin(std::string slug) {
#if ARCH_LIN
std::string path = "./plugins/" + slug + "/plugin.so";
@@ -91,35 +95,8 @@ static int loadPlugin(std::string slug) {
return 0;
}

void pluginInit() {
// Load core
// This function is defined in core.cpp
Plugin *corePlugin = init();
gPlugins.push_back(corePlugin);

// Search for plugin libraries
DIR *dir = opendir("plugins");
if (dir) {
struct dirent *d;
while ((d = readdir(dir))) {
if (d->d_name[0] == '.')
continue;
loadPlugin(d->d_name);
}
closedir(dir);
}
}

void pluginDestroy() {
for (Plugin *plugin : gPlugins) {
// TODO free shared library handle with `dlclose` or `FreeLibrary`
delete plugin;
}
gPlugins.clear();
}

////////////////////
// CURL and libzip helpers
// plugin helpers
////////////////////

static int extractZipHandle(zip_t *za, const char *dir) {
@@ -179,42 +156,7 @@ static int extractZip(const char *filename, const char *dir) {
return err;
}

////////////////////
// plugin manager
////////////////////

static std::string apiHost = "http://api.vcvrack.com";

void pluginLogIn(std::string email, std::string password) {
json_t *reqJ = json_object();
json_object_set(reqJ, "email", json_string(email.c_str()));
json_object_set(reqJ, "password", json_string(password.c_str()));
json_t *resJ = requestJson(POST_METHOD, apiHost + "/token", reqJ);
json_decref(reqJ);

if (resJ) {
json_t *errorJ = json_object_get(resJ, "error");
if (errorJ) {
const char *errorStr = json_string_value(errorJ);
loginStatus = errorStr;
}
else {
json_t *tokenJ = json_object_get(resJ, "token");
if (tokenJ) {
const char *tokenStr = json_string_value(tokenJ);
gToken = tokenStr;
loginStatus = "";
}
}
json_decref(resJ);
}
}

void pluginLogOut() {
gToken = "";
}

static void pluginRefreshPlugin(json_t *pluginJ) {
static void refreshPurchase(json_t *pluginJ) {
json_t *slugJ = json_object_get(pluginJ, "slug");
if (!slugJ) return;
const char *slug = json_string_value(slugJ);
@@ -258,6 +200,92 @@ static void pluginRefreshPlugin(json_t *pluginJ) {
downloadName = "";
}

static void checkVersion() {
json_t *resJ = requestJson(GET_METHOD, apiHost + "/version", NULL);

if (resJ) {
json_t *versionJ = json_object_get(resJ, "version");
if (versionJ) {
const char *version = json_string_value(versionJ);
if (version && version != gApplicationVersion) {
char text[1024];
snprintf(text, sizeof(text), "Rack %s is available.\n\nYou have Rack %s.\n\nWould you like to download the new version on the website?", version, gApplicationVersion.c_str());
if (osdialog_message(OSDIALOG_INFO, OSDIALOG_YES_NO, text)) {
std::thread t(openBrowser, "https://vcvrack.com/");
t.detach();
guiClose();
}
}
}
json_decref(resJ);
}
}

////////////////////
// plugin API
////////////////////

void pluginInit() {
if (gApplicationVersion != "dev") {
std::thread versionThread(checkVersion);
versionThread.detach();
}

// Load core
// This function is defined in core.cpp
Plugin *corePlugin = init();
gPlugins.push_back(corePlugin);

// Search for plugin libraries
DIR *dir = opendir("plugins");
if (dir) {
struct dirent *d;
while ((d = readdir(dir))) {
if (d->d_name[0] == '.')
continue;
loadPlugin(d->d_name);
}
closedir(dir);
}
}

void pluginDestroy() {
for (Plugin *plugin : gPlugins) {
// TODO free shared library handle with `dlclose` or `FreeLibrary`
delete plugin;
}
gPlugins.clear();
}

void pluginLogIn(std::string email, std::string password) {
json_t *reqJ = json_object();
json_object_set(reqJ, "email", json_string(email.c_str()));
json_object_set(reqJ, "password", json_string(password.c_str()));
json_t *resJ = requestJson(POST_METHOD, apiHost + "/token", reqJ);
json_decref(reqJ);

if (resJ) {
json_t *errorJ = json_object_get(resJ, "error");
if (errorJ) {
const char *errorStr = json_string_value(errorJ);
loginStatus = errorStr;
}
else {
json_t *tokenJ = json_object_get(resJ, "token");
if (tokenJ) {
const char *tokenStr = json_string_value(tokenJ);
gToken = tokenStr;
loginStatus = "";
}
}
json_decref(resJ);
}
}

void pluginLogOut() {
gToken = "";
}

void pluginRefresh() {
if (gToken.empty())
return;
@@ -282,7 +310,7 @@ void pluginRefresh() {
size_t index;
json_t *purchaseJ;
json_array_foreach(purchasesJ, index, purchaseJ) {
pluginRefreshPlugin(purchaseJ);
refreshPurchase(purchaseJ);
}
}
json_decref(resJ);


+ 0
- 1
src/util.cpp View File

@@ -54,7 +54,6 @@ std::string ellipsize(std::string s, size_t len) {
}

void openBrowser(std::string url) {
// shell injection is possible, so make sure the URL is trusted or hard coded
#if ARCH_LIN
std::string command = "xdg-open " + url;
(void)system(command.c_str());


+ 11
- 12
src/util/request.cpp View File

@@ -17,18 +17,13 @@ static size_t writeStringCallback(char *ptr, size_t size, size_t nmemb, void *us

json_t *requestJson(RequestMethod method, std::string url, json_t *dataJ) {
CURL *curl = curl_easy_init();
if (!curl)
return NULL;
assert(curl);

assert(dataJ);
char *reqStr;
if (method != GET_METHOD) {
reqStr = json_dumps(dataJ, 0);
}
char *reqStr = NULL;

// Set URL
if (method == GET_METHOD) {
if (dataJ) {
// Process data
if (dataJ) {
if (method == GET_METHOD) {
// Append ?key=value&... to url
url += "?";
bool isFirst = true;
@@ -49,7 +44,11 @@ json_t *requestJson(RequestMethod method, std::string url, json_t *dataJ) {
}
}
}
else {
reqStr = json_dumps(dataJ, 0);
}
}

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

// Set HTTP method
@@ -75,7 +74,7 @@ json_t *requestJson(RequestMethod method, std::string url, json_t *dataJ) {
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);

// Body callbacks
if (method != GET_METHOD)
if (reqStr)
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, reqStr);

std::string resText;
@@ -88,7 +87,7 @@ json_t *requestJson(RequestMethod method, std::string url, json_t *dataJ) {
CURLcode res = curl_easy_perform(curl);

// Cleanup
if (method != GET_METHOD)
if (reqStr)
free(reqStr);
curl_easy_cleanup(curl);
curl_slist_free_all(headers);


Loading…
Cancel
Save