fixed: Bug #3933 - Plus signs in the email address cause premium login to fail
This commit is contained in:
parent
d5b25069be
commit
28a6b16875
|
@ -298,7 +298,7 @@ if (UNIX)
|
||||||
|
|
||||||
else() # not-unix
|
else() # not-unix
|
||||||
|
|
||||||
list(APPEND libs Wtsapi32 Userenv Wininet comsuppw)
|
list(APPEND libs Wtsapi32 Userenv Wininet comsuppw Shlwapi)
|
||||||
|
|
||||||
add_definitions(
|
add_definitions(
|
||||||
/DWIN32
|
/DWIN32
|
||||||
|
|
|
@ -24,6 +24,39 @@
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <curl/curl.h>
|
#include <curl/curl.h>
|
||||||
|
|
||||||
|
class CurlFacade {
|
||||||
|
public:
|
||||||
|
CurlFacade();
|
||||||
|
~CurlFacade();
|
||||||
|
CString get(const CString& url);
|
||||||
|
CString urlEncode(const CString& url);
|
||||||
|
|
||||||
|
private:
|
||||||
|
CURL* m_curl;
|
||||||
|
};
|
||||||
|
|
||||||
|
//
|
||||||
|
// CArchInternetUnix
|
||||||
|
//
|
||||||
|
|
||||||
|
CString
|
||||||
|
CArchInternetUnix::get(const CString& url)
|
||||||
|
{
|
||||||
|
CurlFacade curl;
|
||||||
|
return curl.get(url);
|
||||||
|
}
|
||||||
|
|
||||||
|
CString
|
||||||
|
CArchInternetUnix::urlEncode(const CString& url)
|
||||||
|
{
|
||||||
|
CurlFacade curl;
|
||||||
|
return curl.urlEncode(url);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// CurlFacade
|
||||||
|
//
|
||||||
|
|
||||||
static size_t
|
static size_t
|
||||||
curlWriteCallback(void *contents, size_t size, size_t nmemb, void *userp)
|
curlWriteCallback(void *contents, size_t size, size_t nmemb, void *userp)
|
||||||
{
|
{
|
||||||
|
@ -31,47 +64,64 @@ curlWriteCallback(void *contents, size_t size, size_t nmemb, void *userp)
|
||||||
return size * nmemb;
|
return size * nmemb;
|
||||||
}
|
}
|
||||||
|
|
||||||
CString
|
CurlFacade::CurlFacade() :
|
||||||
CArchInternetUnix::get(const CString& url)
|
m_curl(NULL)
|
||||||
{
|
{
|
||||||
std::string result;
|
CURLcode init = curl_global_init(CURL_GLOBAL_ALL);
|
||||||
curl_global_init(CURL_GLOBAL_DEFAULT);
|
if (init != CURLE_OK) {
|
||||||
|
throw XArch("CURL global init failed.");
|
||||||
try {
|
|
||||||
CURL *curl = curl_easy_init();
|
|
||||||
if (curl == NULL) {
|
|
||||||
throw XArch("CURL init failed.");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
m_curl = curl_easy_init();
|
||||||
|
if (m_curl == NULL) {
|
||||||
|
throw XArch("CURL easy init failed.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CurlFacade::~CurlFacade()
|
||||||
|
{
|
||||||
|
if (m_curl != NULL) {
|
||||||
|
curl_easy_cleanup(m_curl);
|
||||||
|
}
|
||||||
|
|
||||||
|
curl_global_cleanup();
|
||||||
|
}
|
||||||
|
|
||||||
|
CString
|
||||||
|
CurlFacade::get(const CString& url)
|
||||||
|
{
|
||||||
|
curl_easy_setopt(m_curl, CURLOPT_URL, url.c_str());
|
||||||
|
curl_easy_setopt(m_curl, CURLOPT_WRITEFUNCTION, curlWriteCallback);
|
||||||
|
|
||||||
std::stringstream userAgent;
|
std::stringstream userAgent;
|
||||||
userAgent << "Synergy ";
|
userAgent << "Synergy ";
|
||||||
userAgent << kVersion;
|
userAgent << kVersion;
|
||||||
|
curl_easy_setopt(m_curl, CURLOPT_USERAGENT, userAgent.str().c_str());
|
||||||
|
|
||||||
curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
|
std::string result;
|
||||||
curl_easy_setopt(curl, CURLOPT_USERAGENT, userAgent.str().c_str());
|
curl_easy_setopt(m_curl, CURLOPT_WRITEDATA, &result);
|
||||||
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, curlWriteCallback);
|
|
||||||
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &result);
|
|
||||||
|
|
||||||
CURLcode code = curl_easy_perform(curl);
|
CURLcode code = curl_easy_perform(m_curl);
|
||||||
if (code != CURLE_OK) {
|
if (code != CURLE_OK) {
|
||||||
LOG((CLOG_ERR "curl perform error: %s", curl_easy_strerror(code)));
|
LOG((CLOG_ERR "curl perform error: %s", curl_easy_strerror(code)));
|
||||||
throw XArch("CURL perform failed.");
|
throw XArch("CURL perform failed.");
|
||||||
}
|
}
|
||||||
|
|
||||||
curl_easy_cleanup(curl);
|
return result;
|
||||||
}
|
}
|
||||||
catch (...) {
|
|
||||||
curl_easy_cleanup(curl);
|
CString
|
||||||
throw;
|
CurlFacade::urlEncode(const CString& url)
|
||||||
|
{
|
||||||
|
char* resultCStr = curl_easy_escape(m_curl, url.c_str(), 0);
|
||||||
|
|
||||||
|
if (resultCStr == NULL) {
|
||||||
|
curl_free(resultCStr);
|
||||||
|
throw XArch("CURL escape failed.");
|
||||||
}
|
}
|
||||||
|
|
||||||
curl_global_cleanup();
|
std::string result(resultCStr);
|
||||||
}
|
curl_free(resultCStr);
|
||||||
catch (...) {
|
|
||||||
curl_global_cleanup();
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,4 +24,5 @@
|
||||||
class CArchInternetUnix {
|
class CArchInternetUnix {
|
||||||
public:
|
public:
|
||||||
CString get(const CString& url);
|
CString get(const CString& url);
|
||||||
|
CString urlEncode(const CString& url);
|
||||||
};
|
};
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
|
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <Wininet.h>
|
#include <Wininet.h>
|
||||||
|
#include <Shlwapi.h>
|
||||||
|
|
||||||
struct CWinINetUrl {
|
struct CWinINetUrl {
|
||||||
CString m_scheme;
|
CString m_scheme;
|
||||||
|
@ -60,6 +61,27 @@ CArchInternetWindows::get(const CString& url)
|
||||||
return request.send();
|
return request.send();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CString
|
||||||
|
CArchInternetWindows::urlEncode(const CString& url)
|
||||||
|
{
|
||||||
|
TCHAR buffer[1024];
|
||||||
|
DWORD bufferSize = sizeof(buffer);
|
||||||
|
|
||||||
|
if (UrlEscape(url.c_str(), buffer, &bufferSize, URL_ESCAPE_UNSAFE) != S_OK) {
|
||||||
|
throw XArch(new XArchEvalWindows());
|
||||||
|
}
|
||||||
|
|
||||||
|
CString result(buffer);
|
||||||
|
|
||||||
|
// the win32 url encoding funcitons are pretty useless (to us) and only
|
||||||
|
// escape "unsafe" chars, but not + or =, so we need to replace these
|
||||||
|
// manually (and probably many other chars).
|
||||||
|
find_replace_all(result, "+", "%2B");
|
||||||
|
find_replace_all(result, "=", "%3D");
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// CWinINetRequest
|
// CWinINetRequest
|
||||||
//
|
//
|
||||||
|
|
|
@ -24,4 +24,5 @@
|
||||||
class CArchInternetWindows {
|
class CArchInternetWindows {
|
||||||
public:
|
public:
|
||||||
CString get(const CString& url);
|
CString get(const CString& url);
|
||||||
|
CString urlEncode(const CString& url);
|
||||||
};
|
};
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
/*
|
||||||
|
* synergy -- mouse and keyboard sharing utility
|
||||||
|
* Copyright (C) 2014 Bolton Software Ltd.
|
||||||
|
*
|
||||||
|
* This package is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* found in the file COPYING that should have accompanied this file.
|
||||||
|
*
|
||||||
|
* This package 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 General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "base/String.h"
|
||||||
|
|
||||||
|
void
|
||||||
|
find_replace_all(
|
||||||
|
CString& subject,
|
||||||
|
const CString& find,
|
||||||
|
const CString& replace)
|
||||||
|
{
|
||||||
|
size_t pos = 0;
|
||||||
|
while ((pos = subject.find(find, pos)) != CString::npos) {
|
||||||
|
subject.replace(pos, find.length(), replace);
|
||||||
|
pos += replace.length();
|
||||||
|
}
|
||||||
|
}
|
|
@ -23,3 +23,5 @@
|
||||||
|
|
||||||
// use standard C++ string class for our string class
|
// use standard C++ string class for our string class
|
||||||
typedef std::string CString;
|
typedef std::string CString;
|
||||||
|
|
||||||
|
void find_replace_all(CString& subject, const CString& find, const CString& replace);
|
||||||
|
|
|
@ -44,7 +44,7 @@ CToolApp::run(int argc, char** argv)
|
||||||
|
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
ss << PREMIUM_AUTH_URL;
|
ss << PREMIUM_AUTH_URL;
|
||||||
ss << "?email=" << email;
|
ss << "?email=" << ARCH->internet().urlEncode(email);
|
||||||
ss << "&password=" << password;
|
ss << "&password=" << password;
|
||||||
|
|
||||||
std::cout << ARCH->internet().get(ss.str()) << std::endl;
|
std::cout << ARCH->internet().get(ss.str()) << std::endl;
|
||||||
|
|
|
@ -28,3 +28,10 @@ TEST(ArchInternetTests, get)
|
||||||
CString result = internet.get(TEST_URL);
|
CString result = internet.get(TEST_URL);
|
||||||
ASSERT_EQ("Hello world!", result);
|
ASSERT_EQ("Hello world!", result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(ArchInternetTests, urlEncode)
|
||||||
|
{
|
||||||
|
ARCH_INTERNET internet;
|
||||||
|
CString result = internet.urlEncode("hello=+&world");
|
||||||
|
ASSERT_EQ("hello%3D%2B%26world", result);
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue