Skip to content

Commit fc1f08d

Browse files
committed
Check for updates at startup
1 parent 33a159e commit fc1f08d

File tree

15 files changed

+370
-285
lines changed

15 files changed

+370
-285
lines changed

src/base.cpp

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
#include "base.hpp"
22
#include "redlua.hpp"
3+
#include "nativedb.hpp"
34
#include "settingsctl.hpp"
5+
#include "updatesctl.hpp"
46
#include "menus\main.hpp"
7+
#include "menus\updalert.hpp"
58
#include "constants.hpp"
69

710
#include "thirdparty\easyloggingpp.h"
@@ -51,14 +54,34 @@ void RedLuaMain(void) {
5154
}
5255

5356
LOG(INFO) << "Logger initialized";
54-
srand(GetTickCount());
55-
RedLuaScanScripts();
56-
5757
auto menuController = new MenuController();
5858
auto mainMenu = CreateMainMenu(menuController);
5959
menuController->SetCurrentPosition(
6060
Settings.Read("menu_position", 0)
6161
);
62+
LOG(DEBUG) << "RedLua menu initialized";
63+
64+
if(Settings.Read("auto_updates", false)) {
65+
LOG(DEBUG) << "Starting updates checker...";
66+
std::string data;
67+
if(UpdatesCtl.CheckRedLua(data))
68+
CreateUpdateAlert(menuController, data);
69+
else
70+
LOG(DEBUG) << "RedLua updater: " << data;
71+
if(UpdatesCtl.CheckNativeDB(data))
72+
LOG(INFO) << "NativeDB updated successfully";
73+
else
74+
LOG(DEBUG) << "NativeDB updater: " << data;
75+
LOG(DEBUG) << "Updates checker finished";
76+
}
77+
78+
if(Natives.GetMethodCount() == 0) {
79+
NativeDB::Returns ret;
80+
if((ret = Natives.Load()) != NativeDB::Returns::NLOAD_OK)
81+
LOG(ERROR) << "Failed to load " REDLUA_NATIVES_FILE ": " << ret;
82+
}
83+
84+
RedLuaScanScripts();
6285

6386
while(true) {
6487
if(MenuInput::MenuSwitchPressed()) {

src/luanative.cpp

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,6 @@
77
#include "native\call.hpp"
88
#include "nativedb.hpp"
99

10-
#include "thirdparty\easyloggingpp.h"
11-
1210
static int native_call(lua_State *L) {
1311
auto nspace = Natives.GetNamespace(luaL_checkstring(L, 1));
1412
luaL_argcheck(L, nspace != nullptr, 1, "Unknown namespace");
@@ -110,12 +108,6 @@ void luaclose_native(lua_State *L) {
110108
}
111109

112110
int luaopen_native(lua_State *L) {
113-
if(Natives.GetMethodCount() == 0) {
114-
NativeDB::Returns ret;
115-
if((ret = Natives.Load()) != NativeDB::Returns::NLOAD_OK)
116-
LOG(ERROR) << "Failed to load " REDLUA_NATIVES_FILE ": " << ret;
117-
}
118-
119111
call_init(L);
120112
nativeobj_init(L);
121113
luaL_newlib(L, nativelib);

src/menus/about.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#include "menus\link.hpp"
1+
#include "menus\helpers.hpp"
22
#include "menus\about.hpp"
33
#include "constants.hpp"
44

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,15 @@ class MenuItemLink : public MenuItemDefault {
1515
MenuItemLink(string caption, string link)
1616
: MenuItemDefault(caption), m_link(link) {}
1717
};
18+
19+
class MenuTemporary : public MenuBase
20+
{
21+
virtual void OnPop(void)
22+
{
23+
delete this;
24+
}
25+
26+
public:
27+
MenuTemporary(MenuItemTitle *title)
28+
: MenuBase(title) {}
29+
};

src/menus/scripts.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -118,8 +118,8 @@ class MenuItemScript : public MenuItemDefault {
118118
: MenuItemDefault(name), script(script) {}
119119
};
120120

121-
MenuScripts *CreateScriptsList(MenuController *controller) {
122-
auto menu = new MenuScripts(new MenuItemTitle("Scripts list"));
121+
MenuTemporary *CreateScriptsList(MenuController *controller) {
122+
auto menu = new MenuTemporary(new MenuItemTitle("Scripts list"));
123123
controller->RegisterMenu(menu);
124124

125125
if(Scripts.size() > 0) {

src/menus/scripts.hpp

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,7 @@
22

33
#ifndef REDLUA_STANDALONE
44
#include "thirdparty\scriptmenu.h"
5+
#include "menus\helpers.hpp"
56

6-
class MenuScripts : public MenuBase {
7-
virtual void OnPop(void) {
8-
delete this;
9-
}
10-
11-
public:
12-
MenuScripts(MenuItemTitle *title)
13-
: MenuBase(title) {}
14-
};
15-
16-
MenuScripts *CreateScriptsList(MenuController *controller);
7+
MenuTemporary *CreateScriptsList(MenuController *controller);
178
#endif

src/menus/settings.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ MenuBase *CreateSettings(MenuController *controller) {
7979
controller->RegisterMenu(menu);
8080

8181
menu->AddItem(new MenuItemSSwitch("Autorun feature enabled", "autorun", Settings.Read("autorun", true)));
82-
menu->AddItem(new MenuItemSSwitch("Check for updates at startup", "updates", Settings.Read("updates", false)));
82+
menu->AddItem(new MenuItemSSwitch("Check for updates at startup", "auto_updates", Settings.Read("auto_updates", false)));
8383
menu->AddItem(new MenuItemReloadDB("Reload NativeDB"));
8484
menu->AddItem(new MenuItemMenu("Change menu position", CreatePositionMenu(controller)));
8585
menu->AddItem(new MenuItemToggleAll("Toggle all scripts"));

src/menus/updalert.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#include "menus\helpers.hpp"
2+
#include "menus\updalert.hpp"
3+
#include "thirdparty\scriptmenu.h"
4+
#include "constants.hpp"
5+
6+
void CreateUpdateAlert(MenuController *controller, std::string &version) {
7+
auto menu = new MenuTemporary(new MenuItemTitle("RedLua update " + version + " found!"));
8+
controller->RegisterMenu(menu);
9+
10+
menu->AddItem(new MenuItemLink("Open download page", (std::string)REDLUA_RELS_URL + version));
11+
controller->PushMenu(menu);
12+
}

src/menus/updalert.hpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#pragma once
2+
3+
#ifndef REDLUA_STANDALONE
4+
#include "thirdparty\scriptmenu.h"
5+
#include <string>
6+
7+
void CreateUpdateAlert(MenuController *controller, std::string &title);
8+
#endif

src/menus/updates.cpp

Lines changed: 17 additions & 185 deletions
Original file line numberDiff line numberDiff line change
@@ -1,137 +1,17 @@
11
#include "menus\updates.hpp"
2-
#include "menus\link.hpp"
3-
#include "settingsctl.hpp"
2+
#include "menus\updalert.hpp"
3+
#include "menus\helpers.hpp"
4+
#include "updatesctl.hpp"
45
#include "constants.hpp"
5-
6-
#include "thirdparty\json.hpp"
7-
#include <Windows.h>
8-
9-
using json = nlohmann::json;
10-
11-
static const char *symlist[] = {
12-
"curl_easy_init", "curl_easy_setopt",
13-
"curl_easy_perform", "curl_easy_strerror",
14-
"curl_easy_getinfo", "curl_easy_cleanup",
15-
"curl_slist_append", "curl_slist_free_all",
16-
NULL
17-
};
18-
19-
static const char *liblist[] = {
20-
"libcurl-x64.dll",
21-
"libcurl.dll",
22-
"curl.dll",
23-
NULL
24-
};
25-
26-
static struct {
27-
HMODULE lib;
28-
29-
void *(*easy_init)(void);
30-
int (*easy_setopt)(void *, int, ...);
31-
int (*easy_perform)(void *);
32-
const char *(*easy_strerror)(int);
33-
void (*easy_getinfo)(void *, int, void *);
34-
void (*easy_cleanup)(void *);
35-
void *(*slist_append)(void *, const char *);
36-
void (*slist_free_all)(void *);
37-
} curl;
38-
39-
static bool load_curl(void) {
40-
for(int i = 0; !curl.lib && liblist[i]; i++) {
41-
curl.lib = LoadLibraryA(liblist[i]);
42-
for(int j = 0; curl.lib && symlist[j]; j++) {
43-
if((((void**)&curl)[j + 1] = GetProcAddress(curl.lib, symlist[j])) == NULL) {
44-
FreeLibrary(curl.lib);
45-
curl.lib = NULL;
46-
break;
47-
}
48-
}
49-
}
50-
51-
return curl.lib != NULL;
52-
}
53-
54-
class MenuUpdatePrompt : public MenuBase {
55-
virtual void OnPop(void) {
56-
delete this;
57-
}
58-
59-
public:
60-
MenuUpdatePrompt(MenuItemTitle *title)
61-
: MenuBase(title) {}
62-
};
63-
64-
static const std::string errors[] = {
65-
"Error: ~COLOR_RED~libcurl.dll not found!",
66-
"Server responded with error: ~COLOR_RED~",
67-
"HTTP request failed: ~COLOR_RED~",
68-
"Malformed server response"
69-
};
6+
#include "nativedb.hpp"
707

718
class MenuItemUpdateRL : public MenuItemDefault {
72-
static size_t __stdcall write_string(char *ptr, size_t sz, size_t nmemb, void *ud) {
73-
*(static_cast<std::string*>(ud)) += std::string{ptr, sz * nmemb};
74-
return sz * nmemb;
75-
}
76-
779
virtual void OnSelect(void) {
78-
if(!load_curl()) {
79-
SetStatusText(errors[0]);
80-
return;
81-
}
82-
8310
std::string data;
84-
void *slist = NULL;
85-
slist = curl.slist_append(slist, "User-Agent: RL/1.0");
86-
slist = curl.slist_append(slist, "Accept: application/json");
87-
88-
void *handle = curl.easy_init();
89-
curl.easy_setopt(handle, 42/*CURLOPT_HEADER*/, 0);
90-
curl.easy_setopt(handle, 52/*CURLOPT_FOLLOWLOCATION*/, 1);
91-
curl.easy_setopt(handle, 53/*CURLOPT_TRANSFERTEXT*/, 1);
92-
curl.easy_setopt(handle, 64/*CURLOPT_SSL_VERIFYPEER*/, 0);
93-
curl.easy_setopt(handle, 10002/*CURLOPT_URL*/, REDLUA_TAGS_URL);
94-
curl.easy_setopt(handle, 10023/*CURLOPT_HTTPHEADER*/, slist);
95-
curl.easy_setopt(handle, 20011/*CURLOPT_WRITEFUNCTION*/, write_string);
96-
curl.easy_setopt(handle, 10001/*CURLOPT_WRITEDATA*/, &data);
97-
98-
int res;
99-
if((res = curl.easy_perform(handle)) == 0) {
100-
json jdata = json::parse(data, nullptr, false);
101-
if(!jdata.is_discarded()) {
102-
std::string temp;
103-
std::string newest;
104-
int curr_rel = -1;
105-
106-
if(jdata.is_array()) {
107-
for(auto &x : jdata.items()) {
108-
json &jname = x.value()["name"];
109-
if(jname.is_string()) {
110-
int vidx = std::strtoul(x.key().c_str(), nullptr, 10);
111-
if(jname.get_to(temp) == REDLUA_VERSION)
112-
curr_rel = vidx;
113-
if(vidx == 0)
114-
newest = temp;
115-
}
116-
}
117-
} else if(jdata.is_object() && jdata["message"].is_string())
118-
SetStatusText(errors[1] + jdata["message"].get_to(temp));
119-
120-
if(newest != "" && curr_rel != 0) {
121-
auto menu = new MenuUpdatePrompt(new MenuItemTitle("New version " + newest + " found!"));
122-
auto controller = GetMenu()->GetController();
123-
controller->RegisterMenu(menu);
124-
125-
menu->AddItem(new MenuItemLink("Open download page", (std::string)REDLUA_RELS_URL + newest));
126-
controller->PushMenu(menu);
127-
}
128-
} else
129-
SetStatusText(errors[2] + errors[3]);
130-
} else
131-
SetStatusText(errors[2] + (std::string)curl.easy_strerror(res));
132-
133-
curl.slist_free_all(slist);
134-
curl.easy_cleanup(handle);
11+
if(UpdatesCtl.CheckRedLua(data))
12+
CreateUpdateAlert(GetMenu()->GetController(), data);
13+
else
14+
SetStatusText(data);
13515
}
13616

13717
public:
@@ -140,64 +20,16 @@ class MenuItemUpdateRL : public MenuItemDefault {
14020
};
14121

14222
class MenuItemUpdateDB : public MenuItemDefault {
143-
static size_t etag_extract(char *ptr, size_t sz, size_t nmemb, void *ud) {
144-
size_t out = sz * nmemb;
145-
if(out > 10 && _strnicmp(ptr, "etag: ", 6) == 0) {
146-
std::string *str = (std::string *)ud;
147-
// Вот такой вот странный, но действенный способ обрезать символы \r\n
148-
*str = std::string{ptr + 6, out - (ptr[out - 2] == '\r' ? 8 : (ptr[out - 1] == '\n' ? 7 : 6))};
149-
}
150-
151-
return out;
152-
}
153-
15423
virtual void OnSelect(void) {
155-
if(!load_curl()) {
156-
SetStatusText(errors[0]);
157-
return;
158-
}
159-
160-
FILE *file = fopen(REDLUA_NATIVES_FILE, "r+");
161-
if(!file && (file = fopen(REDLUA_NATIVES_FILE, "w")) == NULL) {
162-
SetStatusText("Failed to open " REDLUA_NATIVES_FILE " file!");
163-
return;
164-
}
165-
166-
std::string etag = "W/\"\"";
167-
void *slist = NULL;
168-
slist = curl.slist_append(slist, "User-Agent: RL/1.0");
169-
slist = curl.slist_append(slist, "Accept: application/json");
170-
slist = curl.slist_append(slist, ("If-None-Match: " + Settings.Read("nativedb_etag", etag)).c_str());
171-
172-
void *handle = curl.easy_init();
173-
curl.easy_setopt(handle, 42/*CURLOPT_HEADER*/, 0);
174-
curl.easy_setopt(handle, 52/*CURLOPT_FOLLOWLOCATION*/, 1);
175-
curl.easy_setopt(handle, 53/*CURLOPT_TRANSFERTEXT*/, 1);
176-
curl.easy_setopt(handle, 64/*CURLOPT_SSL_VERIFYPEER*/, 0);
177-
curl.easy_setopt(handle, 10002/*CURLOPT_URL*/, REDLUA_NATIVEDB_URL);
178-
curl.easy_setopt(handle, 10023/*CURLOPT_HTTPHEADER*/, slist);
179-
curl.easy_setopt(handle, 20011/*CURLOPT_WRITEFUNCTION*/, fwrite);
180-
curl.easy_setopt(handle, 10001/*CURLOPT_WRITEDATA*/, file);
181-
curl.easy_setopt(handle, 20079/*CURLOPT_HEADERFUNCTION*/, etag_extract);
182-
curl.easy_setopt(handle, 10029/*CURLOPT_WRITEDATA*/, &etag);
183-
184-
int res;
185-
if((res = curl.easy_perform(handle)) == 0) {
186-
long resp = 0;
187-
curl.easy_getinfo(handle, 0x200002/*CURLINFO_RESPONSE_CODE*/, &resp);
188-
if(resp >= 200 && resp < 300) {
189-
Settings.Write("nativedb_etag", "W/" + etag);
190-
SetStatusText("NativeDB updated, please hit \"Reload NativeDB\" button to apply changes!");
191-
} else if(resp == 304)
192-
SetStatusText("You already have the latest version of NativeDB");
24+
std::string err;
25+
if(UpdatesCtl.CheckNativeDB(err)) {
26+
NativeDB::Returns ret;
27+
if((ret = Natives.Load()) == NativeDB::Returns::NLOAD_OK)
28+
SetStatusText("NativeDB updated and reloaded successfully!");
19329
else
194-
SetStatusText(errors[2] + std::to_string(resp));
30+
SetStatusText("Failed to reload NativeDB, error code: " + std::to_string(ret));
19531
} else
196-
SetStatusText(errors[2] + (std::string)curl.easy_strerror(res));
197-
198-
curl.slist_free_all(slist);
199-
curl.easy_cleanup(handle);
200-
fclose(file);
32+
SetStatusText(err);
20133
}
20234

20335
public:
@@ -206,9 +38,9 @@ class MenuItemUpdateDB : public MenuItemDefault {
20638
};
20739

20840
MenuBase *CreateUpdatesMenu(MenuController *controller) {
209-
auto menu = new MenuBase(new MenuItemTitle("RedLua Settings"));
41+
auto menu = new MenuBase(new MenuItemTitle("Version manager"));
21042
controller->RegisterMenu(menu);
211-
43+
21244
menu->AddItem(new MenuItemUpdateRL("Check for RedLua updates"));
21345
menu->AddItem(new MenuItemUpdateDB("Check for NativeDB updates"));
21446

0 commit comments

Comments
 (0)