1 // Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
2 // Copyright (C) 2010 Winch Gate Property Limited
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 Jan BOON (Kaetemi) <jan.boon@kaetemi.be>
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/>.
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"
41 using namespace NLMISC
;
43 // ***************************************************************************
44 class CHandlerBrowseHome
: public IActionHandler
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
));
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() +
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());
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()) +
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
)));
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());
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());
123 if (target
->isFauna())
125 else if (target
->isNPC())
127 else if (target
->isPlayer())
129 else if (target
->isUser())
131 strFindReplace(url
, "$ttype$", target
->sheetId().toString());
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);
157 str
.assign((char*)buffer
, size
*nmemb
);
162 class CWebigNotificationThread
: public NLMISC::IRunnable
171 CWebigNotificationThread()
175 curl_global_init(CURL_GLOBAL_ALL
);
178 //nlinfo("ctor CWebigNotificationThread");
188 Curl
= curl_easy_init();
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()
203 curl_easy_cleanup(Curl
);
208 _Thread
->terminate();
214 void get(const std::string
&url
)
218 //nlinfo("get '%s'", url.c_str());
219 curl_easy_setopt(Curl
, CURLOPT_URL
, url
.c_str());
220 CURLcode res
= curl_easy_perform(Curl
);
222 curl_easy_getinfo(Curl
, CURLINFO_RESPONSE_CODE
, &r
);
223 //nlwarning("result : '%s'", curlresult.c_str());
226 std::string contentType
;
227 res
= curl_easy_getinfo(Curl
, CURLINFO_CONTENT_TYPE
, &ch
);
228 if (res
== CURLE_OK
&& ch
!= NULL
)
233 // "text/lua; charset=utf8"
234 if (contentType
.find("text/lua") == 0)
237 script
= "\nlocal __WEBIG_NOTIF__= true\n" + curlresult
;
238 CInterfaceManager::getInstance()->queueLuaScript(script
);
242 nlwarning("Invalid content-type '%s', expected 'text/lua'", contentType
.c_str());
246 std::string
randomString()
248 std::string chars
= "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
250 for (int i
= 0; i
< 32; i
++)
252 s
+= chars
[uint(frand(float(chars
.size())))];
259 if (ClientCfg
.WebIgNotifInterval
== 0)
262 nlwarning("ClientCfg.WebIgNotifInterval == 0, notification thread not running");
266 std::string domain
= ClientCfg
.WebIgMainDomain
;
267 uint32 ms
= ClientCfg
.WebIgNotifInterval
*60*1000;
270 // first time, we wait a small amount of time to be sure everything is initialized
275 string url
= domain
+ "/index.php?app=notif&format=lua&rnd=" + randomString();
276 addWebIGParams(url
, true);
283 void sleepLoop(uint ms
)
285 // use smaller sleep time so stopThread() will not block too long
287 uint32 ticks
= ms
/ 100;
288 while (_Running
&& ticks
> 0) {
296 // initialize curl outside thread
301 _Thread
= IThread::create(this);
302 nlassert(_Thread
!= NULL
);
304 nlwarning("WebIgNotification thread started");
308 nlwarning("WebIgNotification thread already started");
320 nlwarning("WebIgNotification thread stopped");
324 nlwarning("WebIgNotification thread already stopped");
328 bool isRunning() const
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
¶m
)
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");
392 formfields
.add("cid", toString(cid
));
393 formfields
.add("authkey", getWebAuthKey());
397 // ***************************************************************************
399 string
CGroupHTMLAuth::home () const
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
¶m
)
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
450 // ***************************************************************************
452 void CGroupHTMLWebIG::handle ()
454 CGroupHTMLAuth::handle ();