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
718class 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
13717public:
@@ -140,64 +20,16 @@ class MenuItemUpdateRL : public MenuItemDefault {
14020};
14121
14222class 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
20335public:
@@ -206,9 +38,9 @@ class MenuItemUpdateDB : public MenuItemDefault {
20638};
20739
20840MenuBase *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