Linux multi-monitor fullscreen support
[ryzomcore.git] / ryzom / client / src / interface_v3 / group_html_webig.cpp
blob95ec3aa0e937c76d075e7462168d73209c22519c
1 // Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
2 // Copyright (C) 2010-2019 Winch Gate Property Limited
3 //
4 // This source file has been modified by the following contributors:
5 // Copyright (C) 2012 Matt RAYKOWSKI (sfb) <matt.raykowski@gmail.com>
6 // Copyright (C) 2013 Laszlo KIS-ADAM (dfighter) <dfighter1985@gmail.com>
7 // Copyright (C) 2019-2020 Jan BOON (Kaetemi) <jan.boon@kaetemi.be>
8 //
9 // This program is free software: you can redistribute it and/or modify
10 // it under the terms of the GNU Affero General Public License as
11 // published by the Free Software Foundation, either version 3 of the
12 // License, or (at your option) any later version.
14 // This program is distributed in the hope that it will be useful,
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 // GNU Affero General Public License for more details.
19 // You should have received a copy of the GNU Affero General Public License
20 // along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include "stdpch.h"
24 #include "group_html_webig.h"
25 #include "nel/misc/xml_auto_ptr.h"
26 #include "nel/gui/lua_manager.h"
27 #include "../client_cfg.h"
28 #include "../user_entity.h"
29 #include "../entities.h"
30 #include "interface_manager.h"
31 #include "user_agent.h"
33 // used for login cookie to be sent to the web server
34 #include "../net_manager.h"
35 #include "../connection.h"
37 #include <curl/curl.h>
38 #include "nel/web/curl_certificates.h"
40 using namespace std;
41 using namespace NLMISC;
43 // ***************************************************************************
44 class CHandlerBrowseHome : public IActionHandler
46 public:
47 void execute (CCtrlBase *pCaller, const std::string &sParams)
49 CInterfaceManager *pIM= CInterfaceManager::getInstance();
50 string container = getParam (sParams, "name");
51 CGroupHTML *groupHtml = dynamic_cast<CGroupHTML*>(CWidgetManager::getInstance()->getElementFromId(container));
52 if (groupHtml)
54 groupHtml->browse(groupHtml->Home.c_str());
58 REGISTER_ACTION_HANDLER( CHandlerBrowseHome, "browse_home");
60 // ***************************************************************************
62 static string getWebAuthKey()
64 if(!UserEntity || !NetMngr.getLoginCookie().isValid()) return "";
66 // authkey = <sharid><name><cid><cookie>
67 uint32 cid = NetMngr.getLoginCookie().getUserId() * 16 + PlayerSelectedSlot;
68 string rawKey = toString(CharacterHomeSessionId) +
69 UserEntity->getLoginName() +
70 toString(cid) +
71 NetMngr.getLoginCookie().toString();
72 string key = getMD5((const uint8*)rawKey.c_str(), (uint32)rawKey.size()).toString();
73 //nlinfo("rawkey = '%s'", rawKey.c_str());
74 //nlinfo("authkey = %s", key.c_str());
75 return key;
78 void addWebIGParams (string &url, bool trustedDomain)
80 // no extras parameters added to url if not in trusted domains list
81 if (!trustedDomain) return;
83 if(!UserEntity || !NetMngr.getLoginCookie().isValid()) return;
85 uint32 cid = NetMngr.getLoginCookie().getUserId() * 16 + PlayerSelectedSlot;
86 url += ((url.find('?') != string::npos) ? "&" : "?") +
87 string("shardid=") + toString(CharacterHomeSessionId) +
88 string("&name=") + UserEntity->getLoginName() + // FIXME: UrlEncode
89 string("&lang=") + CI18N::getCurrentLanguageCode() +
90 string("&datasetid=") + toString(UserEntity->dataSetId()) +
91 string("&ig=1");
92 if (trustedDomain)
94 url += string("&cid=") + toString(cid) +
95 string("&authkey=") + getWebAuthKey();
97 if (url.find('$') != string::npos)
99 strFindReplace(url, "$gender$", GSGENDER::toString(UserEntity->getGender()));
100 strFindReplace(url, "$displayName$", UserEntity->getDisplayName()); // FIXME: UrlEncode...
101 strFindReplace(url, "$posx$", toString(UserEntity->pos().x));
102 strFindReplace(url, "$posy$", toString(UserEntity->pos().y));
103 strFindReplace(url, "$posz$", toString(UserEntity->pos().z));
104 strFindReplace(url, "$post$", toString(atan2(UserEntity->front().y, UserEntity->front().x)));
106 // Target fields
107 const char *dbPath = "UI:VARIABLES:TARGET:SLOT";
108 CInterfaceManager *im = CInterfaceManager::getInstance();
109 CCDBNodeLeaf *node = NLGUI::CDBManager::getInstance()->getDbProp(dbPath, false);
110 if (node && (uint8)node->getValue32() != (uint8) CLFECOMMON::INVALID_SLOT)
112 CEntityCL *target = EntitiesMngr.entity((uint) node->getValue32());
113 if (target)
115 strFindReplace(url, "$tdatasetid$", toString(target->dataSetId()));
116 strFindReplace(url, "$tdisplayName$", target->getDisplayName()); // FIXME: UrlEncode...
117 strFindReplace(url, "$tposx$", toString(target->pos().x));
118 strFindReplace(url, "$tposy$", toString(target->pos().y));
119 strFindReplace(url, "$tposz$", toString(target->pos().z));
120 strFindReplace(url, "$tpost$", toString(atan2(target->front().y, target->front().x)));
121 strFindReplace(url, "$tsheet$", target->sheetId().toString());
122 string type;
123 if (target->isFauna())
124 type = "fauna";
125 else if (target->isNPC())
126 type = "npc";
127 else if (target->isPlayer())
128 type = "player";
129 else if (target->isUser())
130 type = "user";
131 strFindReplace(url, "$ttype$", target->sheetId().toString());
133 else
135 strFindReplace(url, "$tdatasetid$", "");
136 strFindReplace(url, "$tdisplayName$", "");
137 strFindReplace(url, "$tposx$", "");
138 strFindReplace(url, "$tposy$", "");
139 strFindReplace(url, "$tposz$", "");
140 strFindReplace(url, "$tpost$", "");
141 strFindReplace(url, "$tsheet$", "");
142 strFindReplace(url, "$ttype$", "");
149 // ***************************************************************************
150 // ***************************************************************************
151 static string curlresult;
153 size_t writeDataFromCurl(void *buffer, size_t size, size_t nmemb, void *pcl)
155 //CWebigNotificationThread *cl = static_cast<CWebigNotificationThread*>(pcl);
156 string str;
157 str.assign((char*)buffer, size*nmemb);
158 curlresult += str;
159 return size*nmemb;
162 class CWebigNotificationThread : public NLMISC::IRunnable
164 private:
165 CURL *Curl;
166 bool _Running;
167 IThread *_Thread;
169 public:
171 CWebigNotificationThread()
173 _Running = false;
174 _Thread = NULL;
175 curl_global_init(CURL_GLOBAL_ALL);
177 Curl = NULL;
178 //nlinfo("ctor CWebigNotificationThread");
181 void init()
183 if (Curl)
185 return;
188 Curl = curl_easy_init();
189 if(!Curl) return;
190 curl_easy_setopt(Curl, CURLOPT_COOKIEFILE, "");
191 curl_easy_setopt(Curl, CURLOPT_NOPROGRESS, 1);
192 curl_easy_setopt(Curl, CURLOPT_USERAGENT, getUserAgent().c_str());
193 curl_easy_setopt(Curl, CURLOPT_FOLLOWLOCATION, 1);
194 curl_easy_setopt(Curl, CURLOPT_WRITEFUNCTION, writeDataFromCurl);
196 NLWEB::CCurlCertificates::useCertificates(Curl);
199 ~CWebigNotificationThread()
201 if(Curl)
203 curl_easy_cleanup(Curl);
204 Curl = NULL;
206 if (_Thread)
208 _Thread->terminate();
209 delete _Thread;
210 _Thread = NULL;
214 void get(const std::string &url)
216 if(!Curl) return;
217 curlresult.clear();
218 //nlinfo("get '%s'", url.c_str());
219 curl_easy_setopt(Curl, CURLOPT_URL, url.c_str());
220 CURLcode res = curl_easy_perform(Curl);
221 long r;
222 curl_easy_getinfo(Curl, CURLINFO_RESPONSE_CODE, &r);
223 //nlwarning("result : '%s'", curlresult.c_str());
225 char *ch;
226 std::string contentType;
227 res = curl_easy_getinfo(Curl, CURLINFO_CONTENT_TYPE, &ch);
228 if (res == CURLE_OK && ch != NULL)
230 contentType = ch;
233 // "text/lua; charset=utf8"
234 if (contentType.find("text/lua") == 0)
236 std::string script;
237 script = "\nlocal __WEBIG_NOTIF__= true\n" + curlresult;
238 CInterfaceManager::getInstance()->queueLuaScript(script);
240 else
242 nlwarning("Invalid content-type '%s', expected 'text/lua'", contentType.c_str());
246 std::string randomString()
248 std::string chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
249 std::string s;
250 for (int i = 0; i < 32; i++)
252 s += chars[uint(frand(float(chars.size())))];
254 return s;
257 void run()
259 if (ClientCfg.WebIgNotifInterval == 0)
261 _Running = false;
262 nlwarning("ClientCfg.WebIgNotifInterval == 0, notification thread not running");
263 return;
266 std::string domain = ClientCfg.WebIgMainDomain;
267 uint32 ms = ClientCfg.WebIgNotifInterval*60*1000;
269 _Running = true;
270 // first time, we wait a small amount of time to be sure everything is initialized
271 nlSleep(30*1000);
272 uint c = 0;
273 while (_Running)
275 string url = domain + "/index.php?app=notif&format=lua&rnd=" + randomString();
276 addWebIGParams(url, true);
277 get(url);
279 sleepLoop(ms);
283 void sleepLoop(uint ms)
285 // use smaller sleep time so stopThread() will not block too long
286 // tick == 100ms
287 uint32 ticks = ms / 100;
288 while (_Running && ticks > 0) {
289 nlSleep(100);
290 ticks--;
294 void startThread()
296 // initialize curl outside thread
297 init();
299 if (!_Thread)
301 _Thread = IThread::create(this);
302 nlassert(_Thread != NULL);
303 _Thread->start();
304 nlwarning("WebIgNotification thread started");
306 else
308 nlwarning("WebIgNotification thread already started");
312 void stopThread()
314 _Running = false;
315 if (_Thread)
317 _Thread->wait();
318 delete _Thread;
319 _Thread = NULL;
320 nlwarning("WebIgNotification thread stopped");
322 else
324 nlwarning("WebIgNotification thread already stopped");
328 bool isRunning() const
330 return _Running;
334 static CWebigNotificationThread webigThread;
335 void startWebIgNotificationThread()
337 if (!webigThread.isRunning())
339 webigThread.startThread();
343 void stopWebIgNotificationThread()
345 if (webigThread.isRunning())
347 webigThread.stopThread();
351 // ***************************************************************************
352 // ***************************************************************************
355 // ***************************************************************************
356 NLMISC_REGISTER_OBJECT(CViewBase, CGroupHTMLAuth, std::string, "auth_html");
358 CGroupHTMLAuth::CGroupHTMLAuth(const TCtorParam &param)
359 : CGroupHTML(param)
363 // ***************************************************************************
365 CGroupHTMLAuth::~CGroupHTMLAuth()
369 void CGroupHTMLAuth::addHTTPGetParams (string &url, bool trustedDomain)
371 if(!UserEntity || !NetMngr.getLoginCookie().isValid()) return;
373 addWebIGParams(url, trustedDomain);
376 // ***************************************************************************
378 void CGroupHTMLAuth::addHTTPPostParams (SFormFields &formfields, bool trustedDomain)
380 // no extras parameters added to url if not in trusted domains list
381 if (!trustedDomain) return;
383 if(!UserEntity || !NetMngr.getLoginCookie().isValid()) return;
385 uint32 cid = NetMngr.getLoginCookie().getUserId() * 16 + PlayerSelectedSlot;
386 formfields.add("shardid", toString(CharacterHomeSessionId));
387 formfields.add("name", UserEntity->getLoginName());
388 formfields.add("lang", CI18N::getCurrentLanguageCode());
389 formfields.add("ig", "1");
390 if (trustedDomain)
392 formfields.add("cid", toString(cid));
393 formfields.add("authkey", getWebAuthKey());
397 // ***************************************************************************
399 string CGroupHTMLAuth::home () const
401 return Home;
404 // ***************************************************************************
406 void CGroupHTMLAuth::handle ()
408 CGroupHTML::handle ();
411 // ***************************************************************************
412 // ***************************************************************************
415 // ***************************************************************************
416 NLMISC_REGISTER_OBJECT(CViewBase, CGroupHTMLWebIG, std::string, "webig_html");
418 CGroupHTMLWebIG::CGroupHTMLWebIG(const TCtorParam &param)
419 : CGroupHTMLAuth(param)
423 // ***************************************************************************
425 CGroupHTMLWebIG::~CGroupHTMLWebIG()
429 // ***************************************************************************
431 void CGroupHTMLWebIG::addHTTPGetParams (string &url, bool trustedDomain)
433 CGroupHTMLAuth::addHTTPGetParams(url, trustedDomain);
436 // ***************************************************************************
438 void CGroupHTMLWebIG::addHTTPPostParams (SFormFields &formfields, bool trustedDomain)
440 CGroupHTMLAuth::addHTTPPostParams(formfields, trustedDomain);
443 // ***************************************************************************
445 string CGroupHTMLWebIG::home () const
447 return Home;
450 // ***************************************************************************
452 void CGroupHTMLWebIG::handle ()
454 CGroupHTMLAuth::handle ();