Merge with develop
--HG-- branch : compatibility-develop
This commit is contained in:
commit
30512804d5
16 changed files with 707 additions and 11 deletions
35
code/nel/include/nel/gui/curl_certificates.h
Normal file
35
code/nel/include/nel/gui/curl_certificates.h
Normal file
|
@ -0,0 +1,35 @@
|
|||
// Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
|
||||
// Copyright (C) 2010 Winch Gate Property Limited
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as
|
||||
// published by the Free Software Foundation, either version 3 of the
|
||||
// License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#ifndef CL_CURL_CERTIFICATES_HTML_H
|
||||
#define CL_CURL_CERTIFICATES_HTML_H
|
||||
|
||||
#include <curl/curl.h>
|
||||
|
||||
#include "nel/misc/types_nl.h"
|
||||
|
||||
namespace NLGUI
|
||||
{
|
||||
#if defined(NL_OS_WINDOWS)
|
||||
class CCurlCertificates {
|
||||
public:
|
||||
// cURL SSL certificate loading
|
||||
static CURLcode sslCtxFunction(CURL *curl, void *sslctx, void *parm);
|
||||
};
|
||||
#endif // NL_OS_WINDOWS
|
||||
|
||||
} // namespace
|
||||
#endif
|
|
@ -264,6 +264,7 @@ namespace NLGUI
|
|||
// because of multiline, thz parent container will be moved to top
|
||||
// The good position can be restored by a press on enter then
|
||||
bool _WantReturn : 1; // Want return char, don't call the enter action handler
|
||||
bool _ClearOnEscape : 1; // clear content when ESC is pressed?
|
||||
bool _Savable : 1; // should content be saved ?
|
||||
bool _DefaultInputString : 1; // Is the current input string the default one (should not be edited)
|
||||
bool _Frozen : 1; // is the control frozen? (cannot edit in it)
|
||||
|
|
|
@ -793,7 +793,7 @@ namespace NLGUI
|
|||
void doBrowseLocalFile(const std::string &filename);
|
||||
|
||||
// load remote content using either GET or POST
|
||||
void doBrowseRemoteUrl(const std::string &url, const std::string &referer, bool doPost = false, const SFormFields &formfields = SFormFields());
|
||||
void doBrowseRemoteUrl(std::string url, const std::string &referer, bool doPost = false, const SFormFields &formfields = SFormFields());
|
||||
|
||||
// render html string as new browser page
|
||||
bool renderHtmlString(const std::string &html);
|
||||
|
@ -861,7 +861,7 @@ namespace NLGUI
|
|||
// BnpDownload system
|
||||
void initBnpDownload();
|
||||
void checkBnpDownload();
|
||||
bool addBnpDownload(const std::string &url, const std::string &action, const std::string &script, const std::string &md5sum);
|
||||
bool addBnpDownload(std::string url, const std::string &action, const std::string &script, const std::string &md5sum);
|
||||
std::string localBnpName(const std::string &url);
|
||||
|
||||
void releaseDownloads();
|
||||
|
|
73
code/nel/include/nel/gui/http_hsts.h
Normal file
73
code/nel/include/nel/gui/http_hsts.h
Normal file
|
@ -0,0 +1,73 @@
|
|||
// Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
|
||||
// Copyright (C) 2010 Winch Gate Property Limited
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as
|
||||
// published by the Free Software Foundation, either version 3 of the
|
||||
// License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#ifndef CL_HTTP_HSTS_H
|
||||
#define CL_HTTP_HSTS_H
|
||||
|
||||
#include "nel/misc/types_nl.h"
|
||||
|
||||
namespace NLGUI
|
||||
{
|
||||
// ********************************************************************************
|
||||
struct SHSTSObject
|
||||
{
|
||||
public:
|
||||
SHSTSObject(uint64 expires = 0, bool includeSubDomains = false)
|
||||
: Expires(expires)
|
||||
, IncludeSubDomains(includeSubDomains)
|
||||
{ }
|
||||
|
||||
uint64 Expires;
|
||||
bool IncludeSubDomains;
|
||||
};
|
||||
|
||||
/**
|
||||
* Keeping track of HSTS header
|
||||
* \author Meelis Mägi (nimetu)
|
||||
* \date 2017
|
||||
*/
|
||||
class CStrictTransportSecurity
|
||||
{
|
||||
public:
|
||||
typedef std::map<std::string, SHSTSObject> THSTSObject;
|
||||
|
||||
static CStrictTransportSecurity* getInstance();
|
||||
static void release();
|
||||
|
||||
public:
|
||||
bool isSecureHost(const std::string &domain) const;
|
||||
|
||||
// ************************************************************************
|
||||
void init(const std::string& fname);
|
||||
void save();
|
||||
|
||||
void erase(const std::string &domain);
|
||||
void set(const std::string &domain, uint64 expires, bool includeSubDomains);
|
||||
bool get(const std::string &domain, SHSTSObject &hsts) const;
|
||||
void setFromHeader(const std::string &domain, const std::string &header);
|
||||
|
||||
void serial(NLMISC::IStream& f);
|
||||
private:
|
||||
static CStrictTransportSecurity* instance;
|
||||
|
||||
~CStrictTransportSecurity();
|
||||
|
||||
std::string _Filename;
|
||||
THSTSObject _Domains;
|
||||
};
|
||||
|
||||
}
|
||||
#endif
|
123
code/nel/src/gui/curl_certificates.cpp
Normal file
123
code/nel/src/gui/curl_certificates.cpp
Normal file
|
@ -0,0 +1,123 @@
|
|||
// Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
|
||||
// Copyright (C) 2010 Winch Gate Property Limited
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as
|
||||
// published by the Free Software Foundation, either version 3 of the
|
||||
// License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//#include <crtdbg.h>
|
||||
|
||||
#include "stdpch.h"
|
||||
#include "nel/gui/curl_certificates.h"
|
||||
|
||||
#include <openssl/x509.h>
|
||||
#include <openssl/ssl.h>
|
||||
|
||||
#if defined(NL_OS_WINDOWS)
|
||||
#pragma comment(lib, "crypt32.lib")
|
||||
#pragma comment(lib, "cryptui.lib")
|
||||
#endif
|
||||
|
||||
using namespace std;
|
||||
using namespace NLMISC;
|
||||
|
||||
#ifdef DEBUG_NEW
|
||||
#define new DEBUG_NEW
|
||||
#endif
|
||||
|
||||
namespace NLGUI
|
||||
{
|
||||
#if defined(NL_OS_WINDOWS)
|
||||
static std::vector<X509 *> x509CertList;
|
||||
|
||||
//
|
||||
// x509CertList lifetime manager
|
||||
//
|
||||
class SX509Certificates {
|
||||
public:
|
||||
SX509Certificates()
|
||||
{
|
||||
curl_version_info_data *data;
|
||||
data = curl_version_info(CURLVERSION_NOW);
|
||||
if (!(data && data->features & CURL_VERSION_SSPI))
|
||||
{
|
||||
addCertificatesFrom("CA");
|
||||
addCertificatesFrom("AuthRoot");
|
||||
addCertificatesFrom("ROOT");
|
||||
}
|
||||
}
|
||||
|
||||
~SX509Certificates()
|
||||
{
|
||||
for (uint i = 0; i < x509CertList.size(); ++i)
|
||||
{
|
||||
X509_free(x509CertList[i]);
|
||||
}
|
||||
|
||||
x509CertList.clear();
|
||||
}
|
||||
|
||||
void addCertificatesFrom(LPCSTR root)
|
||||
{
|
||||
HCERTSTORE hStore;
|
||||
PCCERT_CONTEXT pContext = NULL;
|
||||
X509 *x509;
|
||||
hStore = CertOpenSystemStore(NULL, root);
|
||||
if (hStore)
|
||||
{
|
||||
while (pContext = CertEnumCertificatesInStore(hStore, pContext))
|
||||
{
|
||||
x509 = NULL;
|
||||
x509 = d2i_X509(NULL, (const unsigned char **)&pContext->pbCertEncoded, pContext->cbCertEncoded);
|
||||
if (x509)
|
||||
{
|
||||
x509CertList.push_back(x509);
|
||||
}
|
||||
}
|
||||
CertFreeCertificateContext(pContext);
|
||||
CertCloseStore(hStore, 0);
|
||||
}
|
||||
|
||||
// this is called before debug context is set and log ends up in log.log
|
||||
//nlinfo("Loaded %d certificates from '%s' certificate store", List.size(), root);
|
||||
}
|
||||
};
|
||||
|
||||
/// this will be initialized on startup and cleared on exit
|
||||
static SX509Certificates x509CertListManager;
|
||||
|
||||
// ***************************************************************************
|
||||
// static
|
||||
CURLcode CCurlCertificates::sslCtxFunction(CURL *curl, void *sslctx, void *parm)
|
||||
{
|
||||
if (x509CertList.size() > 0)
|
||||
{
|
||||
SSL_CTX *ctx = (SSL_CTX*)sslctx;
|
||||
X509_STORE *x509store = SSL_CTX_get_cert_store(ctx);
|
||||
if (x509store)
|
||||
{
|
||||
for (uint i = 0; i < x509CertList.size(); ++i)
|
||||
{
|
||||
X509_STORE_add_cert(x509store, x509CertList[i]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
nlwarning("SSL_CTX_get_cert_store returned NULL");
|
||||
}
|
||||
}
|
||||
return CURLE_OK;
|
||||
}
|
||||
#endif // NL_OS_WINDOWS
|
||||
|
||||
}// namespace
|
||||
|
|
@ -77,6 +77,7 @@ namespace NLGUI
|
|||
_ResetFocusOnHide(false),
|
||||
_BackupFatherContainerPos(false),
|
||||
_WantReturn(false),
|
||||
_ClearOnEscape(false),
|
||||
_Savable(true),
|
||||
_DefaultInputString(false),
|
||||
_Frozen(false),
|
||||
|
@ -239,6 +240,11 @@ namespace NLGUI
|
|||
return toString( _WantReturn );
|
||||
}
|
||||
else
|
||||
if( name == "clear_on_escape" )
|
||||
{
|
||||
return toString( _ClearOnEscape );
|
||||
}
|
||||
else
|
||||
if( name == "savable" )
|
||||
{
|
||||
return toString( _Savable );
|
||||
|
@ -413,6 +419,14 @@ namespace NLGUI
|
|||
return;
|
||||
}
|
||||
else
|
||||
if( name == "clear_on_escape" )
|
||||
{
|
||||
bool b;
|
||||
if( fromString( value, b ) )
|
||||
_ClearOnEscape = b;
|
||||
return;
|
||||
}
|
||||
else
|
||||
if( name == "savable" )
|
||||
{
|
||||
bool b;
|
||||
|
@ -514,6 +528,7 @@ namespace NLGUI
|
|||
xmlSetProp( node, BAD_CAST "backup_father_container_pos",
|
||||
BAD_CAST toString( _BackupFatherContainerPos ).c_str() );
|
||||
xmlSetProp( node, BAD_CAST "want_return", BAD_CAST toString( _WantReturn ).c_str() );
|
||||
xmlSetProp( node, BAD_CAST "clear_on_escape", BAD_CAST toString( _ClearOnEscape ).c_str() );
|
||||
xmlSetProp( node, BAD_CAST "savable", BAD_CAST toString( _Savable ).c_str() );
|
||||
xmlSetProp( node, BAD_CAST "max_float_prec", BAD_CAST toString( _MaxFloatPrec ).c_str() );
|
||||
|
||||
|
@ -620,6 +635,9 @@ namespace NLGUI
|
|||
prop = (char*) xmlGetProp( cur, (xmlChar*)"want_return" );
|
||||
if (prop) _WantReturn = convertBool(prop);
|
||||
|
||||
prop = (char*) xmlGetProp( cur, (xmlChar*)"clear_on_escape" );
|
||||
if (prop) _ClearOnEscape = convertBool(prop);
|
||||
|
||||
prop = (char*) xmlGetProp( cur, (xmlChar*)"savable" );
|
||||
if (prop) _Savable = convertBool(prop);
|
||||
|
||||
|
@ -991,6 +1009,11 @@ namespace NLGUI
|
|||
// stop selection
|
||||
_CurrSelection = NULL;
|
||||
_CursorAtPreviousLineEnd = false;
|
||||
if (_ClearOnEscape)
|
||||
{
|
||||
setInputString(ucstring(""));
|
||||
triggerOnChangeAH();
|
||||
}
|
||||
break;
|
||||
case KeyTAB:
|
||||
makeTopWindow();
|
||||
|
|
|
@ -46,6 +46,8 @@
|
|||
#include "nel/misc/big_file.h"
|
||||
#include "nel/gui/url_parser.h"
|
||||
#include "nel/gui/http_cache.h"
|
||||
#include "nel/gui/http_hsts.h"
|
||||
#include "nel/gui/curl_certificates.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace NLMISC;
|
||||
|
@ -70,6 +72,25 @@ namespace NLGUI
|
|||
|
||||
CGroupHTML::SWebOptions CGroupHTML::options;
|
||||
|
||||
// Return URL with https is host is in HSTS list
|
||||
static std::string upgradeInsecureUrl(const std::string &url)
|
||||
{
|
||||
if (toLower(url.substr(0, 7)) != "http://") {
|
||||
return url;
|
||||
}
|
||||
|
||||
CUrlParser uri(url);
|
||||
if (!CStrictTransportSecurity::getInstance()->isSecureHost(uri.host)){
|
||||
return url;
|
||||
}
|
||||
|
||||
#ifdef LOG_DL
|
||||
nlwarning("HSTS url : '%s', using https", url.c_str());
|
||||
#endif
|
||||
uri.scheme = "https";
|
||||
|
||||
return uri.toString();
|
||||
}
|
||||
|
||||
// Active cURL www transfer
|
||||
class CCurlWWWData
|
||||
|
@ -149,6 +170,27 @@ namespace NLGUI
|
|||
return "";
|
||||
}
|
||||
|
||||
bool hasHSTSHeader()
|
||||
{
|
||||
// ignore header if not secure connection
|
||||
if (toLower(Url.substr(0, 8)) != "https://")
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return HeadersRecv.count("strict-transport-security") > 0;
|
||||
}
|
||||
|
||||
const std::string getHSTSHeader()
|
||||
{
|
||||
if (hasHSTSHeader())
|
||||
{
|
||||
return HeadersRecv["strict-transport-security"];
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
public:
|
||||
CURL *Request;
|
||||
|
||||
|
@ -356,6 +398,14 @@ namespace NLGUI
|
|||
return false;
|
||||
}
|
||||
|
||||
#if defined(NL_OS_WINDOWS)
|
||||
// https://
|
||||
if (toLower(download.url.substr(0, 8)) == "https://")
|
||||
{
|
||||
curl_easy_setopt(curl, CURLOPT_SSL_CTX_FUNCTION, &CCurlCertificates::sslCtxFunction);
|
||||
}
|
||||
#endif
|
||||
|
||||
download.data = new CCurlWWWData(curl, download.url);
|
||||
download.fp = fp;
|
||||
|
||||
|
@ -398,7 +448,7 @@ namespace NLGUI
|
|||
// Add a image download request in the multi_curl
|
||||
void CGroupHTML::addImageDownload(const string &url, CViewBase *img, const CStyleParams &style, TImageType type)
|
||||
{
|
||||
string finalUrl = getAbsoluteUrl(url);
|
||||
string finalUrl = upgradeInsecureUrl(getAbsoluteUrl(url));
|
||||
|
||||
// Search if we are not already downloading this url.
|
||||
for(uint i = 0; i < Curls.size(); i++)
|
||||
|
@ -413,7 +463,7 @@ namespace NLGUI
|
|||
}
|
||||
}
|
||||
|
||||
// use requested url for local name
|
||||
// use requested url for local name (cache)
|
||||
string dest = localImageName(url);
|
||||
#ifdef LOG_DL
|
||||
nlwarning("add to download '%s' dest '%s' img %p", finalUrl.c_str(), dest.c_str(), img);
|
||||
|
@ -459,8 +509,10 @@ namespace NLGUI
|
|||
}
|
||||
|
||||
// Add a bnp download request in the multi_curl, return true if already downloaded
|
||||
bool CGroupHTML::addBnpDownload(const string &url, const string &action, const string &script, const string &md5sum)
|
||||
bool CGroupHTML::addBnpDownload(string url, const string &action, const string &script, const string &md5sum)
|
||||
{
|
||||
url = upgradeInsecureUrl(getAbsoluteUrl(url));
|
||||
|
||||
// Search if we are not already downloading this url.
|
||||
for(uint i = 0; i < Curls.size(); i++)
|
||||
{
|
||||
|
@ -569,6 +621,12 @@ namespace NLGUI
|
|||
#ifdef LOG_DL
|
||||
nlwarning("(%s) web transfer '%p' completed with status %d, http %d, url (len %d) '%s'", _Id.c_str(), _CurlWWW->Request, res, code, _CurlWWW->Url.size(), _CurlWWW->Url.c_str());
|
||||
#endif
|
||||
// save HSTS header from all requests regardless of HTTP code
|
||||
if (res == CURLE_OK && _CurlWWW->hasHSTSHeader())
|
||||
{
|
||||
CUrlParser uri(_CurlWWW->Url);
|
||||
CStrictTransportSecurity::getInstance()->setFromHeader(uri.host, _CurlWWW->getHSTSHeader());
|
||||
}
|
||||
|
||||
if (res != CURLE_OK)
|
||||
{
|
||||
|
@ -655,6 +713,12 @@ namespace NLGUI
|
|||
#endif
|
||||
curl_multi_remove_handle(MultiCurl, it->data->Request);
|
||||
|
||||
// save HSTS header from all requests regardless of HTTP code
|
||||
if (res == CURLE_OK && it->data->hasHSTSHeader())
|
||||
{
|
||||
CStrictTransportSecurity::getInstance()->setFromHeader(uri.host, it->data->getHSTSHeader());
|
||||
}
|
||||
|
||||
string tmpfile = it->dest + ".tmp";
|
||||
if(res != CURLE_OK || r < 200 || r >= 300 || (!it->md5sum.empty() && (it->md5sum != getMD5(tmpfile).toString())))
|
||||
{
|
||||
|
@ -5231,7 +5295,7 @@ namespace NLGUI
|
|||
}
|
||||
|
||||
// ***************************************************************************
|
||||
void CGroupHTML::doBrowseRemoteUrl(const std::string &url, const std::string &referer, bool doPost, const SFormFields &formfields)
|
||||
void CGroupHTML::doBrowseRemoteUrl(std::string url, const std::string &referer, bool doPost, const SFormFields &formfields)
|
||||
{
|
||||
// Stop previous request and remove content
|
||||
stopBrowse ();
|
||||
|
@ -5245,6 +5309,8 @@ namespace NLGUI
|
|||
else
|
||||
setTitle (_TitlePrefix + " - " + CI18N::get("uiPleaseWait"));
|
||||
|
||||
url = upgradeInsecureUrl(url);
|
||||
|
||||
#if LOG_DL
|
||||
nlwarning("(%s) browse url (trusted=%s) '%s', referer='%s', post='%s', nb form values %d",
|
||||
_Id.c_str(), (_TrustedDomain ? "true" :"false"), url.c_str(), referer.c_str(), (doPost ? "true" : "false"), formfields.Values.size());
|
||||
|
@ -5264,6 +5330,14 @@ namespace NLGUI
|
|||
return;
|
||||
}
|
||||
|
||||
#if defined(NL_OS_WINDOWS)
|
||||
// https://
|
||||
if (toLower(url.substr(0, 8)) == "https://")
|
||||
{
|
||||
curl_easy_setopt(curl, CURLOPT_SSL_CTX_FUNCTION, &CCurlCertificates::sslCtxFunction);
|
||||
}
|
||||
#endif
|
||||
|
||||
// do not follow redirects, we have own handler
|
||||
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 0);
|
||||
// after redirect
|
||||
|
|
245
code/nel/src/gui/http_hsts.cpp
Normal file
245
code/nel/src/gui/http_hsts.cpp
Normal file
|
@ -0,0 +1,245 @@
|
|||
// Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
|
||||
// Copyright (C) 2010 Winch Gate Property Limited
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as
|
||||
// published by the Free Software Foundation, either version 3 of the
|
||||
// License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#include "stdpch.h"
|
||||
#include "nel/gui/http_hsts.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace NLMISC;
|
||||
|
||||
#ifdef DEBUG_NEW
|
||||
#define new DEBUG_NEW
|
||||
#endif
|
||||
|
||||
namespace NLGUI {
|
||||
CStrictTransportSecurity* CStrictTransportSecurity::instance = NULL;
|
||||
CStrictTransportSecurity* CStrictTransportSecurity::getInstance()
|
||||
{
|
||||
if (!instance)
|
||||
{
|
||||
instance= new CStrictTransportSecurity();
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
void CStrictTransportSecurity::release()
|
||||
{
|
||||
delete instance;
|
||||
instance = NULL;
|
||||
}
|
||||
|
||||
CStrictTransportSecurity::~CStrictTransportSecurity()
|
||||
{
|
||||
save();
|
||||
}
|
||||
|
||||
// ************************************************************************
|
||||
bool CStrictTransportSecurity::isSecureHost(const std::string &domain) const
|
||||
{
|
||||
SHSTSObject hsts;
|
||||
if (get(domain, hsts))
|
||||
{
|
||||
time_t currentTime;
|
||||
time(¤tTime);
|
||||
|
||||
return (hsts.Expires < currentTime);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// ************************************************************************
|
||||
void CStrictTransportSecurity::erase(const std::string &domain)
|
||||
{
|
||||
if (_Domains.count(domain) > 0)
|
||||
{
|
||||
_Domains.erase(domain);
|
||||
}
|
||||
}
|
||||
|
||||
void CStrictTransportSecurity::set(const std::string &domain, uint64 expires, bool includeSubDomains)
|
||||
{
|
||||
if (expires == 0)
|
||||
{
|
||||
erase(domain);
|
||||
return;
|
||||
}
|
||||
|
||||
_Domains[domain].Expires = expires;
|
||||
_Domains[domain].IncludeSubDomains = includeSubDomains;
|
||||
}
|
||||
|
||||
bool CStrictTransportSecurity::get(const std::string &domain, SHSTSObject &hsts) const
|
||||
{
|
||||
if (domain.empty() || _Domains.empty())
|
||||
return false;
|
||||
|
||||
if (_Domains.count(domain) > 0)
|
||||
{
|
||||
hsts = _Domains.at(domain);
|
||||
return true;
|
||||
}
|
||||
|
||||
size_t firstOf = domain.find_first_of(".");
|
||||
size_t lastOf = domain.find_last_of(".");
|
||||
while(firstOf != lastOf)
|
||||
{
|
||||
std::string tmp;
|
||||
tmp = domain.substr(firstOf+1);
|
||||
if (_Domains.count(tmp))
|
||||
{
|
||||
if (_Domains.at(tmp).IncludeSubDomains)
|
||||
{
|
||||
hsts = _Domains.at(tmp);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
firstOf = domain.find_first_of(".", firstOf + 1);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void CStrictTransportSecurity::init(const std::string &fname)
|
||||
{
|
||||
_Domains.clear();
|
||||
_Filename = fname;
|
||||
|
||||
if (_Filename.empty() || !CFile::fileExists(_Filename))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
CIFile in;
|
||||
if (!in.open(_Filename))
|
||||
{
|
||||
nlwarning("Unable to open %s for reading", _Filename.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
serial(in);
|
||||
}
|
||||
|
||||
void CStrictTransportSecurity::save()
|
||||
{
|
||||
if (_Filename.empty())
|
||||
return;
|
||||
|
||||
if (_Domains.empty())
|
||||
{
|
||||
CFile::deleteFile(_Filename);
|
||||
return;
|
||||
}
|
||||
|
||||
COFile out;
|
||||
if (!out.open(_Filename))
|
||||
{
|
||||
nlwarning("Unable to open %s for writing", _Filename.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
serial(out);
|
||||
out.close();
|
||||
}
|
||||
|
||||
void CStrictTransportSecurity::serial(NLMISC::IStream& f)
|
||||
{
|
||||
try
|
||||
{
|
||||
f.serialVersion(1);
|
||||
// HSTS
|
||||
f.serialCheck(NELID("STSH"));
|
||||
|
||||
if (f.isReading())
|
||||
{
|
||||
uint32 nbItems;
|
||||
f.serial(nbItems);
|
||||
for(uint32 k = 0; k < nbItems; ++k)
|
||||
{
|
||||
std::string domain;
|
||||
f.serial(domain);
|
||||
f.serial(_Domains[domain].Expires);
|
||||
f.serial(_Domains[domain].IncludeSubDomains);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
uint32 nbItems = _Domains.size();
|
||||
f.serial(nbItems);
|
||||
for (THSTSObject::iterator it = _Domains.begin(); it != _Domains.end(); ++it)
|
||||
{
|
||||
std::string domain(it->first);
|
||||
f.serial(domain);
|
||||
f.serial(_Domains[domain].Expires);
|
||||
f.serial(_Domains[domain].IncludeSubDomains);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
_Domains.clear();
|
||||
nlwarning("Invalid HTST file format (%s)", _Filename.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
// ***************************************************************************
|
||||
void CStrictTransportSecurity::setFromHeader(const std::string &domain, const std::string &header)
|
||||
{
|
||||
// max-age=<seconds>; includeSubdomains; preload;
|
||||
std::vector<std::string> elements;
|
||||
NLMISC::splitString(toLower(header), ";", elements);
|
||||
if (elements.empty()) return;
|
||||
|
||||
time_t currentTime;
|
||||
time(¤tTime);
|
||||
|
||||
uint64 expire = 0;
|
||||
bool includeSubDomains = false;
|
||||
|
||||
for(uint i=0; i< elements.size(); ++i)
|
||||
{
|
||||
std::string str(trim(elements[i]));
|
||||
if (str.substr(0, 8) == "max-age=")
|
||||
{
|
||||
uint64 ttl;
|
||||
if (fromString(str.substr(8), ttl))
|
||||
{
|
||||
if (ttl > 0)
|
||||
{
|
||||
expire = currentTime + ttl;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (str == "includesubdomains")
|
||||
{
|
||||
includeSubDomains = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (expire == 0)
|
||||
{
|
||||
erase(domain);
|
||||
}
|
||||
else
|
||||
{
|
||||
set(domain, expire, includeSubDomains);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -549,7 +549,7 @@
|
|||
pop_min_h="240"
|
||||
pop_max_w="920"
|
||||
pop_max_h="1600"
|
||||
w="300"
|
||||
w="400"
|
||||
h="400"
|
||||
movable="true"
|
||||
active="false"
|
||||
|
|
|
@ -2655,6 +2655,7 @@
|
|||
fontsize="10"
|
||||
backup_father_container_pos="false"
|
||||
want_return="false"
|
||||
clear_on_escape="false"
|
||||
color="255 255 255 255"
|
||||
continuous_text_update="false"
|
||||
bg_texture="W_box_blank.tga"
|
||||
|
@ -2695,6 +2696,7 @@
|
|||
menu_r="#menu_r"
|
||||
max_historic="#max_historic"
|
||||
want_return="#want_return"
|
||||
clear_on_escape="#clear_on_escape"
|
||||
backup_father_container_pos="#backup_father_container_pos"
|
||||
on_focus_lost="#on_focus_lost"
|
||||
on_focus_lost_params="#on_focus_lost_params"
|
||||
|
@ -6587,6 +6589,18 @@
|
|||
dblink="UI:SAVE:#inv_type:FILTER_ARMOR"
|
||||
texture="filter_armor.tga"
|
||||
tooltip="uittFilterArmor" />
|
||||
<instance template="edit_box_widget"
|
||||
id="inv_query_eb"
|
||||
posref="BR BR"
|
||||
x="-190"
|
||||
y="1"
|
||||
w="100"
|
||||
clear_on_escape="true"
|
||||
enter_recover_focus="false"
|
||||
max_num_chars="20"
|
||||
max_historic="0"
|
||||
onenter="inv_set_search"
|
||||
onchange="inv_set_search" onchange_params="#inv_type" />
|
||||
<!-- details -->
|
||||
<instance template="tinv_item_list_icon_swap"
|
||||
id="detail"
|
||||
|
|
|
@ -69,6 +69,7 @@
|
|||
#include "interface_v3/sbrick_manager.h"
|
||||
#include "nel/gui/widget_manager.h"
|
||||
#include "nel/gui/http_cache.h"
|
||||
#include "nel/gui/http_hsts.h"
|
||||
//
|
||||
#include "gabarit.h"
|
||||
#include "hair_set.h"
|
||||
|
@ -1370,6 +1371,8 @@ void prelogInit()
|
|||
CHttpCache::getInstance()->setCacheIndex("cache/cache.index");
|
||||
CHttpCache::getInstance()->init();
|
||||
|
||||
CStrictTransportSecurity::getInstance()->init("save/hsts-list.save");
|
||||
|
||||
// Register the reflected classes
|
||||
registerInterfaceElements();
|
||||
|
||||
|
|
|
@ -2960,6 +2960,8 @@ void CDBCtrlSheet::swapSheet(CDBCtrlSheet *other)
|
|||
swapDBProps(getItemRMClassTypePtr(), other->getItemRMClassTypePtr());
|
||||
swapDBProps(getItemRMFaberStatTypePtr(), other->getItemRMFaberStatTypePtr());
|
||||
swapDBProps(getItemPrerequisitValidPtr(), other->getItemPrerequisitValidPtr());
|
||||
swapDBProps(getItemSerialPtr(), other->getItemSerialPtr());
|
||||
swapDBProps(getItemCreateTimePtr(), other->getItemCreateTimePtr());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3539,6 +3541,10 @@ void CDBCtrlSheet::copyAspect(CDBCtrlSheet *dest)
|
|||
dest->setItemRMFaberStatType(getItemRMFaberStatType());
|
||||
// copy prerequisit valid flag
|
||||
dest->setItemPrerequisitValid(getItemPrerequisitValid());
|
||||
// copy item serial
|
||||
dest->setItemSerial(getItemSerial());
|
||||
// copy item create time
|
||||
dest->setItemCreateTime(getItemCreateTime());
|
||||
}
|
||||
// if brick, sphrase or sphraseId
|
||||
if(isSBrick() || isSPhrase() || isSPhraseId())
|
||||
|
|
|
@ -39,6 +39,7 @@
|
|||
|
||||
// For handlers
|
||||
#include "nel/gui/action_handler.h"
|
||||
#include "nel/gui/group_editbox.h"
|
||||
#include "dbctrl_sheet.h"
|
||||
|
||||
#include "../sheet_manager.h"
|
||||
|
@ -2010,6 +2011,18 @@ bool SBagOptions::parse(xmlNodePtr cur, CInterfaceGroup * /* parentGroup */)
|
|||
return true;
|
||||
}
|
||||
|
||||
// ***************************************************************************
|
||||
void SBagOptions::setSearchFilter(const ucstring &s)
|
||||
{
|
||||
SearchFilter.clear();
|
||||
SearchFilterChanged = true;
|
||||
|
||||
if (!s.empty())
|
||||
{
|
||||
splitUCString(toLower(s), ucstring(" "), SearchFilter);
|
||||
}
|
||||
}
|
||||
|
||||
// ***************************************************************************
|
||||
bool SBagOptions::isSomethingChanged()
|
||||
{
|
||||
|
@ -2057,6 +2070,12 @@ bool SBagOptions::isSomethingChanged()
|
|||
LastDbFilterTP = (DbFilterTP->getValue8() != 0);
|
||||
}
|
||||
|
||||
if (SearchFilterChanged)
|
||||
{
|
||||
bRet = true;
|
||||
SearchFilterChanged = false;
|
||||
}
|
||||
|
||||
return bRet;
|
||||
}
|
||||
|
||||
|
@ -2075,6 +2094,26 @@ bool SBagOptions::canDisplay(CDBCtrlSheet *pCS) const
|
|||
const CItemSheet *pIS = pCS->asItemSheet();
|
||||
if (pIS != NULL)
|
||||
{
|
||||
if (SearchFilter.size() > 0)
|
||||
{
|
||||
bool match = true;
|
||||
ucstring lcName = toLower(pCS->getItemActualName());
|
||||
|
||||
// add item quality as a keyword to match
|
||||
if (pCS->getQuality() > 1)
|
||||
{
|
||||
lcName += ucstring(" " + toString(pCS->getQuality()));
|
||||
}
|
||||
|
||||
for (uint i = 0; i< SearchFilter.size(); ++i)
|
||||
{
|
||||
if (lcName.find(SearchFilter[i]) == ucstring::npos)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Armor
|
||||
if ((pIS->Family == ITEMFAMILY::ARMOR) ||
|
||||
(pIS->Family == ITEMFAMILY::JEWELRY))
|
||||
|
@ -2455,6 +2494,30 @@ class CHandlerInvDrag : public IActionHandler
|
|||
};
|
||||
REGISTER_ACTION_HANDLER( CHandlerInvDrag, "inv_drag" );
|
||||
|
||||
// **********************************************************************************************************
|
||||
class CHandlerInvSetSearch : public IActionHandler
|
||||
{
|
||||
void execute (CCtrlBase *pCaller, const std::string &sParams)
|
||||
{
|
||||
if (!pCaller) return;
|
||||
|
||||
CGroupEditBox *eb = dynamic_cast<CGroupEditBox *>(pCaller);
|
||||
if (!eb) return;
|
||||
|
||||
CInterfaceManager *pIM = CInterfaceManager::getInstance();
|
||||
|
||||
// ui:interface:inventory:content:bag:iil:inv_query_eb:eb
|
||||
string invId = pCaller->getParent()->getParent()->getId();
|
||||
|
||||
CDBGroupListSheetBag *pList = dynamic_cast<CDBGroupListSheetBag*>(CWidgetManager::getInstance()->getElementFromId(invId + ":bag_list"));
|
||||
if (pList != NULL) pList->setSearchFilter(eb->getInputString());
|
||||
|
||||
CDBGroupIconListBag *pIcons = dynamic_cast<CDBGroupIconListBag*>(CWidgetManager::getInstance()->getElementFromId(invId + ":bag_icons"));
|
||||
if (pIcons != NULL) pIcons->setSearchFilter(eb->getInputString());
|
||||
}
|
||||
};
|
||||
REGISTER_ACTION_HANDLER( CHandlerInvSetSearch, "inv_set_search" );
|
||||
|
||||
// ***************************************************************************
|
||||
// COMMON INVENTORIES Test if we can drop an item to a slot or a list
|
||||
class CHandlerInvCanDropTo : public IActionHandler
|
||||
|
|
|
@ -519,18 +519,26 @@ struct SBagOptions
|
|||
bool LastDbFilterMP;
|
||||
bool LastDbFilterMissMP;
|
||||
bool LastDbFilterTP;
|
||||
|
||||
bool SearchFilterChanged;
|
||||
std::vector<ucstring> SearchFilter;
|
||||
|
||||
// -----------------------
|
||||
SBagOptions()
|
||||
{
|
||||
InvType = CInventoryManager::InvUnknown;
|
||||
DbFilterArmor = DbFilterWeapon = DbFilterTool = DbFilterMP = DbFilterMissMP = DbFilterTP = NULL;
|
||||
LastDbFilterArmor = LastDbFilterWeapon = LastDbFilterTool = LastDbFilterMP = LastDbFilterMissMP = LastDbFilterTP = false;
|
||||
SearchFilterChanged = false;
|
||||
}
|
||||
|
||||
bool parse (xmlNodePtr cur, CInterfaceGroup *parentGroup);
|
||||
|
||||
bool isSomethingChanged(); // From last call ?
|
||||
|
||||
bool isSearchFilterChanged() const { return SearchFilterChanged; }
|
||||
void setSearchFilter(const ucstring &s);
|
||||
|
||||
bool getFilterArmor() const
|
||||
{
|
||||
if (DbFilterArmor == NULL) return true;
|
||||
|
@ -621,6 +629,8 @@ public:
|
|||
// Return true if the sheet can be displayed due to filters
|
||||
bool canDisplay(CDBCtrlSheet *pCS) { return _BO.canDisplay(pCS); }
|
||||
|
||||
void setSearchFilter(const ucstring &s) { _BO.setSearchFilter(s); }
|
||||
|
||||
private:
|
||||
|
||||
SBagOptions _BO;
|
||||
|
@ -652,6 +662,8 @@ public:
|
|||
// Return true if the sheet can be displayed due to filters
|
||||
bool canDisplay(CDBCtrlSheet *pCS) const { return _BO.canDisplay(pCS); }
|
||||
|
||||
void setSearchFilter(const ucstring &s) { _BO.setSearchFilter(s); }
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// A child node
|
||||
|
|
|
@ -73,14 +73,29 @@ bool CItemGroup::contains(CDBCtrlSheet *other, SLOT_EQUIPMENT::TSlotEquipment &s
|
|||
|
||||
void CItemGroup::addItem(sint32 createTime, sint32 serial, SLOT_EQUIPMENT::TSlotEquipment slot)
|
||||
{
|
||||
//Don't add an item if it already exists, this could cause issue
|
||||
// It's happening either if we are creating a group with a 2 hands items (and the item is found both in handR and handL)
|
||||
// Or if an user incorrectly edit his group file
|
||||
for(int i=0; i<Items.size(); i++)
|
||||
{
|
||||
if( Items[i].createTime == createTime && Items[i].serial == serial)
|
||||
{
|
||||
nldebug("Not adding duplicate item, createTime: %d, serial: %d", createTime, serial);
|
||||
//In this case, we are adding the duplicate item for a 2 hands item
|
||||
//If it's saved as a left hand item, save it as a right hand item instead (so we have only 1 correct item)
|
||||
if(Items[i].slot == SLOT_EQUIPMENT::TSlotEquipment::HANDL && slot == SLOT_EQUIPMENT::TSlotEquipment::HANDR)
|
||||
Items[i].slot = SLOT_EQUIPMENT::TSlotEquipment::HANDR;
|
||||
return;
|
||||
}
|
||||
}
|
||||
Items.push_back(CItem(createTime, serial, slot));
|
||||
}
|
||||
|
||||
void CItemGroup::addRemove(std::string slotName)
|
||||
{
|
||||
SLOT_EQUIPMENT::TSlotEquipment slot = SLOT_EQUIPMENT::stringToSlotEquipment(NLMISC::toUpper(slotName));
|
||||
if(slot)
|
||||
removeBeforeEquip.push_back(slot);
|
||||
if(slot != SLOT_EQUIPMENT::UNDEFINED)
|
||||
addRemove(slot);
|
||||
}
|
||||
|
||||
void CItemGroup::addRemove(SLOT_EQUIPMENT::TSlotEquipment slot)
|
||||
|
@ -158,9 +173,16 @@ void CItemGroup::readFrom(xmlNodePtr node)
|
|||
ptrName = (char*) xmlGetProp(curNode, (xmlChar*)"maxPrice");
|
||||
if (ptrName) NLMISC::fromString((const char*)ptrName, item.maxPrice);
|
||||
item.usePrice = (item.minPrice != 0 || item.maxPrice != std::numeric_limits<uint32>::max());
|
||||
|
||||
if(item.createTime != 0)
|
||||
{
|
||||
addItem(item.createTime, item.serial, item.slot);
|
||||
}
|
||||
// Old load : keep for compatibility / migration reasons
|
||||
else
|
||||
{
|
||||
Items.push_back(item);
|
||||
}
|
||||
}
|
||||
if (strcmp((char*)curNode->name, "remove") == 0)
|
||||
{
|
||||
std::string slot;
|
||||
|
|
|
@ -95,6 +95,7 @@
|
|||
#include "nel/gui/lua_manager.h"
|
||||
#include "item_group_manager.h"
|
||||
#include "nel/gui/http_cache.h"
|
||||
#include "nel/gui/http_hsts.h"
|
||||
|
||||
///////////
|
||||
// USING //
|
||||
|
@ -688,6 +689,7 @@ void release()
|
|||
CViewRenderer::release();
|
||||
CIXml::releaseLibXml();
|
||||
CHttpCache::release();
|
||||
CStrictTransportSecurity::release();
|
||||
|
||||
#if FINAL_VERSION
|
||||
// openURL ("http://ryzom.com/exit/");
|
||||
|
|
Loading…
Reference in a new issue