Bit of cleanup around Translation and remove httpassetstorage

master
Rider Linden 2015-09-11 17:34:53 -07:00
parent c8f41d200f
commit f2da6ec2ac
15 changed files with 388 additions and 2034 deletions

View File

@ -48,7 +48,6 @@ set(llmessage_SOURCE_FILES
llexperiencecache.cpp
llfiltersd2xmlrpc.cpp
llhost.cpp
llhttpassetstorage.cpp
llhttpclient.cpp
llhttpconstants.cpp
llhttpnode.cpp
@ -141,7 +140,6 @@ set(llmessage_HEADER_FILES
llfiltersd2xmlrpc.h
llfollowcamparams.h
llhost.h
llhttpassetstorage.h
llhttpclient.h
llhttpclientinterface.h
llhttpconstants.h

View File

@ -1609,3 +1609,4 @@ void LLAssetStorage::markAssetToxic( const LLUUID& uuid )
}
}

View File

@ -27,7 +27,6 @@
#ifndef LL_LLASSETSTORAGE_H
#define LL_LLASSETSTORAGE_H
#include <string>
#include "lluuid.h"

File diff suppressed because it is too large Load Diff

View File

@ -1,159 +0,0 @@
/**
* @file llhttpassetstorage.h
* @brief Class for loading asset data to/from an external source over http.
*
* $LicenseInfo:firstyear=2003&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#ifndef LLHTTPASSETSTORAGE_H
#define LLHTTPASSETSTORAGE_H
#include "llassetstorage.h"
#include "curl/curl.h"
class LLVFile;
class LLHTTPAssetRequest;
typedef void (*progress_callback)(void* userdata);
struct LLTempAssetData;
typedef std::map<LLUUID,LLTempAssetData> uuid_tempdata_map;
class LLHTTPAssetStorage : public LLAssetStorage
{
public:
LLHTTPAssetStorage(LLMessageSystem *msg, LLXferManager *xfer,
LLVFS *vfs, LLVFS *static_vfs,
const LLHost &upstream_host,
const std::string& web_host,
const std::string& local_web_host,
const std::string& host_name);
LLHTTPAssetStorage(LLMessageSystem *msg, LLXferManager *xfer,
LLVFS *vfs, LLVFS *static_vfs,
const std::string& web_host,
const std::string& local_web_host,
const std::string& host_name);
virtual ~LLHTTPAssetStorage();
using LLAssetStorage::storeAssetData; // Unhiding virtuals...
virtual void storeAssetData(
const LLUUID& uuid,
LLAssetType::EType atype,
LLStoreAssetCallback callback,
void* user_data,
bool temp_file = false,
bool is_priority = false,
bool store_local = false,
const LLUUID& requesting_agent_id = LLUUID::null,
bool user_waiting=FALSE,
F64Seconds timeout=LL_ASSET_STORAGE_TIMEOUT);
virtual void storeAssetData(
const std::string& filename,
const LLUUID& asset_id,
LLAssetType::EType atype,
LLStoreAssetCallback callback,
void* user_data,
bool temp_file,
bool is_priority,
bool user_waiting=FALSE,
F64Seconds timeout=LL_ASSET_STORAGE_TIMEOUT);
virtual LLSD getPendingDetails(ERequestType rt,
LLAssetType::EType asset_type,
const std::string& detail_prefix) const;
virtual LLSD getPendingRequest(ERequestType rt,
LLAssetType::EType asset_type,
const LLUUID& asset_id) const;
virtual bool deletePendingRequest(ERequestType rt,
LLAssetType::EType asset_type,
const LLUUID& asset_id);
// Hack. One off curl download an URL to a file. Probably should be elsewhere.
// Only used by lldynamicstate. The API is broken, and should be replaced with
// a generic HTTP file fetch - Doug 9/25/06
S32 getURLToFile(const LLUUID& uuid, LLAssetType::EType asset_type, const std::string &url, const std::string& filename, progress_callback callback, void *userdata);
LLAssetRequest* findNextRequest(request_list_t& pending, request_list_t& running);
void checkForTimeouts();
static size_t curlDownCallback(void *data, size_t size, size_t nmemb, void *user_data);
static size_t curlFileDownCallback(void *data, size_t size, size_t nmemb, void *user_data);
static size_t curlUpCallback(void *data, size_t size, size_t nmemb, void *user_data);
static size_t nullOutputCallback(void *data, size_t size, size_t nmemb, void *user_data);
// Should only be used by the LLHTTPAssetRequest
void addRunningRequest(ERequestType rt, LLHTTPAssetRequest* request);
void removeRunningRequest(ERequestType rt, LLHTTPAssetRequest* request);
request_list_t* getRunningList(ERequestType rt);
const request_list_t* getRunningList(ERequestType rt) const;
// Temp assets are stored on sim nodes, they have agent ID and location data associated with them.
virtual void addTempAssetData(const LLUUID& asset_id, const LLUUID& agent_id, const std::string& host_name);
virtual BOOL hasTempAssetData(const LLUUID& texture_id) const;
virtual std::string getTempAssetHostName(const LLUUID& texture_id) const;
virtual LLUUID getTempAssetAgentID(const LLUUID& texture_id) const;
virtual void removeTempAssetData(const LLUUID& asset_id);
virtual void removeTempAssetDataByAgentID(const LLUUID& agent_id);
// Pass LLUUID::null for all
virtual void dumpTempAssetData(const LLUUID& avatar_id) const;
virtual void clearTempAssetData();
protected:
void _queueDataRequest(const LLUUID& uuid, LLAssetType::EType type,
void (*callback)(LLVFS *vfs, const LLUUID&, LLAssetType::EType, void *, S32, LLExtStat),
void *user_data, BOOL duplicate, BOOL is_priority);
private:
void _init(const std::string& web_host, const std::string& local_web_host, const std::string& host_name);
// This will return the correct base URI for any http asset request
std::string getBaseURL(const LLUUID& asset_id, LLAssetType::EType asset_type);
// Check for running uploads that have timed out
// Bump these to the back of the line to let other uploads complete.
void bumpTimedOutUploads();
protected:
std::string mBaseURL;
std::string mLocalBaseURL;
std::string mHostName;
CURLM *mCurlMultiHandle;
request_list_t mRunningDownloads;
request_list_t mRunningUploads;
request_list_t mRunningLocalUploads;
uuid_tempdata_map mTempAssets;
};
#endif

View File

@ -2224,7 +2224,7 @@ if (LL_TESTS)
# llmediadataclient.cpp
lllogininstance.cpp
# llremoteparcelrequest.cpp
lltranslate.cpp
# lltranslate.cpp
llviewerhelputil.cpp
llversioninfo.cpp
llworldmap.cpp
@ -2245,11 +2245,11 @@ if (LL_TESTS)
${CURL_LIBRARIES}
)
set_source_files_properties(
lltranslate.cpp
PROPERTIES
LL_TEST_ADDITIONAL_LIBRARIES "${test_libs}"
)
# set_source_files_properties(
# lltranslate.cpp
# PROPERTIES
# LL_TEST_ADDITIONAL_LIBRARIES "${test_libs}"
# )
set_source_files_properties(
llmediadataclient.cpp

View File

@ -572,7 +572,7 @@ void LLFloaterMarketplaceListings::updateView()
std::string title;
std::string tooltip;
const LLSD& subs = getMarketplaceStringSubstitutions();
const LLSD& subs = LLMarketplaceData::getMarketplaceStringSubstitutions();
// Update the top message or flip to the tabs and folders view
// *TODO : check those messages and create better appropriate ones in strings.xml

View File

@ -397,7 +397,7 @@ void LLFloaterOutbox::updateView()
std::string outbox_title;
std::string outbox_tooltip;
const LLSD& subs = getMarketplaceStringSubstitutions();
const LLSD& subs = LLMarketplaceData::getMarketplaceStringSubstitutions();
U32 mkt_status = LLMarketplaceInventoryImporter::getInstance()->getMarketPlaceStatus();
if (mOutboxId.notNull())
@ -544,7 +544,7 @@ void LLFloaterOutbox::importReportResults(U32 status, const LLSD& content)
}
else if (status == MarketplaceErrorCodes::IMPORT_DONE_WITH_ERRORS)
{
const LLSD& subs = getMarketplaceStringSubstitutions();
const LLSD& subs = LLMarketplaceData::getMarketplaceStringSubstitutions();
LLNotificationsUtil::add("OutboxImportHadErrors", subs);
}

View File

@ -42,41 +42,6 @@
#include "llnotificationsutil.h"
#include "llradiogroup.h"
class EnteredKeyVerifier : public LLTranslate::KeyVerificationReceiver
{
public:
EnteredKeyVerifier(LLTranslate::EService service, bool alert)
: LLTranslate::KeyVerificationReceiver(service)
, mAlert(alert)
{
}
private:
/*virtual*/ void setVerificationStatus(bool ok)
{
LLFloaterTranslationSettings* floater =
LLFloaterReg::getTypedInstance<LLFloaterTranslationSettings>("prefs_translation");
if (!floater)
{
LL_WARNS() << "Cannot find translation settings floater" << LL_ENDL;
return;
}
switch (getService())
{
case LLTranslate::SERVICE_BING:
floater->setBingVerified(ok, mAlert);
break;
case LLTranslate::SERVICE_GOOGLE:
floater->setGoogleVerified(ok, mAlert);
break;
}
}
bool mAlert;
};
LLFloaterTranslationSettings::LLFloaterTranslationSettings(const LLSD& key)
: LLFloater(key)
, mMachineTranslationCB(NULL)
@ -231,11 +196,34 @@ void LLFloaterTranslationSettings::updateControlsEnabledState()
mOKBtn->setEnabled(!on || service_verified);
}
/*static*/
void LLFloaterTranslationSettings::setVerificationStatus(int service, bool ok, bool alert)
{
LLFloaterTranslationSettings* floater =
LLFloaterReg::getTypedInstance<LLFloaterTranslationSettings>("prefs_translation");
if (!floater)
{
LL_WARNS() << "Cannot find translation settings floater" << LL_ENDL;
return;
}
switch (service)
{
case LLTranslate::SERVICE_BING:
floater->setBingVerified(ok, alert);
break;
case LLTranslate::SERVICE_GOOGLE:
floater->setGoogleVerified(ok, alert);
break;
}
}
void LLFloaterTranslationSettings::verifyKey(int service, const std::string& key, bool alert)
{
LLTranslate::KeyVerificationReceiverPtr receiver =
new EnteredKeyVerifier((LLTranslate::EService) service, alert);
LLTranslate::verifyKey(receiver, key);
LLTranslate::verifyKey(static_cast<LLTranslate::EService>(service), key,
boost::bind(&LLFloaterTranslationSettings::setVerificationStatus, _1, _2, alert));
}
void LLFloaterTranslationSettings::onEditorFocused(LLFocusableElement* control)

View File

@ -61,6 +61,8 @@ private:
void onBtnGoogleVerify();
void onBtnOK();
static void setVerificationStatus(int service, bool alert, bool ok);
LLCheckBoxCtrl* mMachineTranslationCB;
LLComboBox* mLanguageCombo;
LLLineEditor* mBingAPIKeyEditor;

View File

@ -146,28 +146,6 @@ namespace {
}
LLSD getMarketplaceStringSubstitutions()
{
std::string marketplace_url = getMarketplaceURL("MarketplaceURL");
std::string marketplace_url_create = getMarketplaceURL("MarketplaceURL_CreateStore");
std::string marketplace_url_dashboard = getMarketplaceURL("MarketplaceURL_Dashboard");
std::string marketplace_url_imports = getMarketplaceURL("MarketplaceURL_Imports");
std::string marketplace_url_info = getMarketplaceURL("MarketplaceURL_LearnMore");
LLSD marketplace_sub_map;
marketplace_sub_map["[MARKETPLACE_URL]"] = marketplace_url;
marketplace_sub_map["[MARKETPLACE_CREATE_STORE_URL]"] = marketplace_url_create;
marketplace_sub_map["[MARKETPLACE_LEARN_MORE_URL]"] = marketplace_url_info;
marketplace_sub_map["[MARKETPLACE_DASHBOARD_URL]"] = marketplace_url_dashboard;
marketplace_sub_map["[MARKETPLACE_IMPORTS_URL]"] = marketplace_url_imports;
return marketplace_sub_map;
}
// SLM Responders End
///////////////////////////////////////////////////////////////////////////////
#if 1
namespace LLMarketplaceImport
@ -720,6 +698,26 @@ LLMarketplaceData::~LLMarketplaceData()
gInventory.removeObserver(mInventoryObserver);
}
LLSD LLMarketplaceData::getMarketplaceStringSubstitutions()
{
std::string marketplace_url = getMarketplaceURL("MarketplaceURL");
std::string marketplace_url_create = getMarketplaceURL("MarketplaceURL_CreateStore");
std::string marketplace_url_dashboard = getMarketplaceURL("MarketplaceURL_Dashboard");
std::string marketplace_url_imports = getMarketplaceURL("MarketplaceURL_Imports");
std::string marketplace_url_info = getMarketplaceURL("MarketplaceURL_LearnMore");
LLSD marketplace_sub_map;
marketplace_sub_map["[MARKETPLACE_URL]"] = marketplace_url;
marketplace_sub_map["[MARKETPLACE_CREATE_STORE_URL]"] = marketplace_url_create;
marketplace_sub_map["[MARKETPLACE_LEARN_MORE_URL]"] = marketplace_url_info;
marketplace_sub_map["[MARKETPLACE_DASHBOARD_URL]"] = marketplace_url_dashboard;
marketplace_sub_map["[MARKETPLACE_IMPORTS_URL]"] = marketplace_url_imports;
return marketplace_sub_map;
}
void LLMarketplaceData::initializeSLM(const status_updated_signal_t::slot_type& cb)
{
if (mStatusUpdatedSignal == NULL)

View File

@ -37,8 +37,6 @@
#include "llstring.h"
LLSD getMarketplaceStringSubstitutions();
namespace MarketplaceErrorCodes
{
@ -183,6 +181,8 @@ class LLSLMDeleteListingsResponder;
class LLMarketplaceData
: public LLSingleton<LLMarketplaceData>
{
friend class LLSingleton < LLMarketplaceData > ;
public:
friend class LLSLMGetMerchantResponder;
friend class LLSLMGetListingsResponder;
@ -192,9 +192,8 @@ public:
friend class LLSLMAssociateListingsResponder;
friend class LLSLMDeleteListingsResponder;
LLMarketplaceData();
virtual ~LLMarketplaceData();
static LLSD getMarketplaceStringSubstitutions();
// Public SLM API : Initialization and status
typedef boost::signals2::signal<void ()> status_updated_signal_t;
void initializeSLM(const status_updated_signal_t::slot_type& cb);
@ -241,8 +240,11 @@ public:
// Used to decide when to run a validation on listing folders
void setValidationWaiting(const LLUUID& folder_id, S32 count);
void decrementValidationWaiting(const LLUUID& folder_id, S32 count = 1);
private:
LLMarketplaceData();
virtual ~LLMarketplaceData();
// Modify Marketplace data set : each method returns true if the function succeeds, false if error
// Used internally only by SLM Responders when data are received from the SLM Server
bool addListing(const LLUUID& folder_id, S32 listing_id, const LLUUID& version_id, bool is_listed, const std::string& edit_url, S32 count);

View File

@ -35,31 +35,254 @@
#include "llui.h"
#include "llversioninfo.h"
#include "llviewercontrol.h"
#include "llcoros.h"
#include "reader.h"
#include "llcorehttputil.h"
/**
* Handler of an HTTP machine translation service.
*
* Derived classes know the service URL
* and how to parse the translation result.
*/
class LLTranslationAPIHandler
{
public:
typedef std::pair<std::string, std::string> LanguagePair_t;
/**
* Get URL for translation of the given string.
*
* Sending HTTP GET request to the URL will initiate translation.
*
* @param[out] url Place holder for the result.
* @param from_lang Source language. Leave empty for auto-detection.
* @param to_lang Target language.
* @param text Text to translate.
*/
virtual std::string getTranslateURL(
const std::string &from_lang,
const std::string &to_lang,
const std::string &text) const = 0;
/**
* Get URL to verify the given API key.
*
* Sending request to the URL verifies the key.
* Positive HTTP response (code 200) means that the key is valid.
*
* @param[out] url Place holder for the URL.
* @param[in] key Key to verify.
*/
virtual std::string getKeyVerificationURL(
const std::string &key) const = 0;
/**
* Parse translation response.
*
* @param[in,out] status HTTP status. May be modified while parsing.
* @param body Response text.
* @param[out] translation Translated text.
* @param[out] detected_lang Detected source language. May be empty.
* @param[out] err_msg Error message (in case of error).
*/
virtual bool parseResponse(
int& status,
const std::string& body,
std::string& translation,
std::string& detected_lang,
std::string& err_msg) const = 0;
/**
* @return if the handler is configured to function properly
*/
virtual bool isConfigured() const = 0;
virtual void verifyKey(const std::string &key, LLTranslate::KeyVerificationResult_fn fnc) = 0;
virtual void translateMessage(LanguagePair_t fromTo, std::string msg, LLTranslate::TranslationSuccess_fn success, LLTranslate::TranslationFailure_fn failure);
virtual ~LLTranslationAPIHandler() {}
void verifyKeyCoro(LLTranslate::EService service, std::string key, LLTranslate::KeyVerificationResult_fn fnc);
void translateMessageCoro(LanguagePair_t fromTo, std::string msg, LLTranslate::TranslationSuccess_fn success, LLTranslate::TranslationFailure_fn failure);
};
void LLTranslationAPIHandler::translateMessage(LanguagePair_t fromTo, std::string msg, LLTranslate::TranslationSuccess_fn success, LLTranslate::TranslationFailure_fn failure)
{
LLCoros::instance().launch("Translation", boost::bind(&LLTranslationAPIHandler::translateMessageCoro,
this, fromTo, msg, success, failure));
}
void LLTranslationAPIHandler::verifyKeyCoro(LLTranslate::EService service, std::string key, LLTranslate::KeyVerificationResult_fn fnc)
{
LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("getMerchantStatusCoro", httpPolicy));
LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
LLCore::HttpOptions::ptr_t httpOpts(new LLCore::HttpOptions);
LLCore::HttpHeaders::ptr_t httpHeaders(new LLCore::HttpHeaders);
std::string user_agent = llformat("%s %d.%d.%d (%d)",
LLVersionInfo::getChannel().c_str(),
LLVersionInfo::getMajor(),
LLVersionInfo::getMinor(),
LLVersionInfo::getPatch(),
LLVersionInfo::getBuild());
httpHeaders->append(HTTP_OUT_HEADER_ACCEPT, HTTP_CONTENT_TEXT_PLAIN);
httpHeaders->append(HTTP_OUT_HEADER_USER_AGENT, user_agent);
httpOpts->setFollowRedirects(true);
std::string url = this->getKeyVerificationURL(key);
if (url.empty())
{
LL_INFOS("Translate") << "No translation URL" << LL_ENDL;
return;
}
LLSD result = httpAdapter->getAndYield(httpRequest, url, httpOpts, httpHeaders);
LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
bool bOk = true;
if (!status)
bOk = false;
if (!fnc.empty())
fnc(service, bOk);
}
void LLTranslationAPIHandler::translateMessageCoro(LanguagePair_t fromTo, std::string msg,
LLTranslate::TranslationSuccess_fn success, LLTranslate::TranslationFailure_fn failure)
{
LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("getMerchantStatusCoro", httpPolicy));
LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
LLCore::HttpOptions::ptr_t httpOpts(new LLCore::HttpOptions);
LLCore::HttpHeaders::ptr_t httpHeaders(new LLCore::HttpHeaders);
std::string user_agent = llformat("%s %d.%d.%d (%d)",
LLVersionInfo::getChannel().c_str(),
LLVersionInfo::getMajor(),
LLVersionInfo::getMinor(),
LLVersionInfo::getPatch(),
LLVersionInfo::getBuild());
httpHeaders->append(HTTP_OUT_HEADER_ACCEPT, HTTP_CONTENT_TEXT_PLAIN);
httpHeaders->append(HTTP_OUT_HEADER_USER_AGENT, user_agent);
std::string url = this->getTranslateURL(fromTo.first, fromTo.second, msg);
if (url.empty())
{
LL_INFOS("Translate") << "No translation URL" << LL_ENDL;
return;
}
LLSD result = httpAdapter->getRawAndYield(httpRequest, url, httpOpts, httpHeaders);
LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
std::string translation, detected_lang, err_msg;
int parseResult = status.getType();
if (this->parseResponse(parseResult, result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS_RAW].asString(),
translation, detected_lang, err_msg))
{
// Fix up the response
LLStringUtil::replaceString(translation, "&lt;", "<");
LLStringUtil::replaceString(translation, "&gt;", ">");
LLStringUtil::replaceString(translation, "&quot;", "\"");
LLStringUtil::replaceString(translation, "&#39;", "'");
LLStringUtil::replaceString(translation, "&amp;", "&");
LLStringUtil::replaceString(translation, "&apos;", "'");
if (!success.empty())
success(translation, detected_lang);
}
else
{
if (err_msg.empty())
{
err_msg = LLTrans::getString("TranslationResponseParseError");
}
LL_WARNS() << "Translation request failed: " << err_msg << LL_ENDL;
if (!failure.empty())
failure(status, err_msg);
}
}
//=========================================================================
/// Google Translate v2 API handler.
class LLGoogleTranslationHandler : public LLTranslationAPIHandler
{
LOG_CLASS(LLGoogleTranslationHandler);
public:
/*virtual*/ std::string getTranslateURL(
const std::string &from_lang,
const std::string &to_lang,
const std::string &text) const;
/*virtual*/ std::string getKeyVerificationURL(
const std::string &key) const;
/*virtual*/ bool parseResponse(
int& status,
const std::string& body,
std::string& translation,
std::string& detected_lang,
std::string& err_msg) const;
/*virtual*/ bool isConfigured() const;
/*virtual*/ void verifyKey(const std::string &key, LLTranslate::KeyVerificationResult_fn fnc);
private:
static void parseErrorResponse(
const Json::Value& root,
int& status,
std::string& err_msg);
static bool parseTranslation(
const Json::Value& root,
std::string& translation,
std::string& detected_lang);
static std::string getAPIKey();
};
//-------------------------------------------------------------------------
// virtual
void LLGoogleTranslationHandler::getTranslateURL(
std::string &url,
std::string LLGoogleTranslationHandler::getTranslateURL(
const std::string &from_lang,
const std::string &to_lang,
const std::string &text) const
{
url = std::string("https://www.googleapis.com/language/translate/v2?key=")
std::string url = std::string("https://www.googleapis.com/language/translate/v2?key=")
+ getAPIKey() + "&q=" + LLURI::escape(text) + "&target=" + to_lang;
if (!from_lang.empty())
{
url += "&source=" + from_lang;
}
return url;
}
// virtual
void LLGoogleTranslationHandler::getKeyVerificationURL(
std::string& url,
std::string LLGoogleTranslationHandler::getKeyVerificationURL(
const std::string& key) const
{
url = std::string("https://www.googleapis.com/language/translate/v2/languages?key=")
std::string url = std::string("https://www.googleapis.com/language/translate/v2/languages?key=")
+ key + "&target=en";
return url;
}
// virtual
@ -154,28 +377,66 @@ std::string LLGoogleTranslationHandler::getAPIKey()
return gSavedSettings.getString("GoogleTranslateAPIKey");
}
/*virtual*/
void LLGoogleTranslationHandler::verifyKey(const std::string &key, LLTranslate::KeyVerificationResult_fn fnc)
{
LLCoros::instance().launch("Google /Verify Key", boost::bind(&LLTranslationAPIHandler::verifyKeyCoro,
this, LLTranslate::SERVICE_GOOGLE, key, fnc));
}
//=========================================================================
/// Microsoft Translator v2 API handler.
class LLBingTranslationHandler : public LLTranslationAPIHandler
{
LOG_CLASS(LLBingTranslationHandler);
public:
/*virtual*/ std::string getTranslateURL(
const std::string &from_lang,
const std::string &to_lang,
const std::string &text) const;
/*virtual*/ std::string getKeyVerificationURL(
const std::string &key) const;
/*virtual*/ bool parseResponse(
int& status,
const std::string& body,
std::string& translation,
std::string& detected_lang,
std::string& err_msg) const;
/*virtual*/ bool isConfigured() const;
/*virtual*/ void verifyKey(const std::string &key, LLTranslate::KeyVerificationResult_fn fnc);
private:
static std::string getAPIKey();
static std::string getAPILanguageCode(const std::string& lang);
};
//-------------------------------------------------------------------------
// virtual
void LLBingTranslationHandler::getTranslateURL(
std::string &url,
std::string LLBingTranslationHandler::getTranslateURL(
const std::string &from_lang,
const std::string &to_lang,
const std::string &text) const
{
url = std::string("http://api.microsofttranslator.com/v2/Http.svc/Translate?appId=")
std::string url = std::string("http://api.microsofttranslator.com/v2/Http.svc/Translate?appId=")
+ getAPIKey() + "&text=" + LLURI::escape(text) + "&to=" + getAPILanguageCode(to_lang);
if (!from_lang.empty())
{
url += "&from=" + getAPILanguageCode(from_lang);
}
return url;
}
// virtual
void LLBingTranslationHandler::getKeyVerificationURL(
std::string& url,
std::string LLBingTranslationHandler::getKeyVerificationURL(
const std::string& key) const
{
url = std::string("http://api.microsofttranslator.com/v2/Http.svc/GetLanguagesForTranslate?appId=")
std::string url = std::string("http://api.microsofttranslator.com/v2/Http.svc/GetLanguagesForTranslate?appId=")
+ key;
return url;
}
// virtual
@ -242,96 +503,31 @@ std::string LLBingTranslationHandler::getAPILanguageCode(const std::string& lang
return lang == "zh" ? "zh-CHT" : lang; // treat Chinese as Traditional Chinese
}
LLTranslate::TranslationReceiver::TranslationReceiver(const std::string& from_lang, const std::string& to_lang)
: mFromLang(from_lang)
, mToLang(to_lang)
, mHandler(LLTranslate::getPreferredHandler())
/*virtual*/
void LLBingTranslationHandler::verifyKey(const std::string &key, LLTranslate::KeyVerificationResult_fn fnc)
{
LLCoros::instance().launch("Bing /Verify Key", boost::bind(&LLTranslationAPIHandler::verifyKeyCoro,
this, LLTranslate::SERVICE_BING, key, fnc));
}
// virtual
void LLTranslate::TranslationReceiver::completedRaw(
const LLChannelDescriptors& channels,
const LLIOPipe::buffer_ptr_t& buffer)
//=========================================================================
/*static*/
void LLTranslate::translateMessage(const std::string &from_lang, const std::string &to_lang,
const std::string &mesg, TranslationSuccess_fn success, TranslationFailure_fn failure)
{
LLBufferStream istr(channels, buffer.get());
std::stringstream strstrm;
strstrm << istr.rdbuf();
LLTranslationAPIHandler& handler = getPreferredHandler();
const std::string body = strstrm.str();
std::string translation, detected_lang, err_msg;
int status = getStatus();
LL_DEBUGS("Translate") << "HTTP status: " << status << " " << getReason() << LL_ENDL;
LL_DEBUGS("Translate") << "Response body: " << body << LL_ENDL;
if (mHandler.parseResponse(status, body, translation, detected_lang, err_msg))
{
// Fix up the response
LLStringUtil::replaceString(translation, "&lt;", "<");
LLStringUtil::replaceString(translation, "&gt;",">");
LLStringUtil::replaceString(translation, "&quot;","\"");
LLStringUtil::replaceString(translation, "&#39;","'");
LLStringUtil::replaceString(translation, "&amp;","&");
LLStringUtil::replaceString(translation, "&apos;","'");
handleResponse(translation, detected_lang);
}
else
{
if (err_msg.empty())
{
err_msg = LLTrans::getString("TranslationResponseParseError");
}
LL_WARNS() << "Translation request failed: " << err_msg << LL_ENDL;
handleFailure(status, err_msg);
}
handler.translateMessage(LLTranslationAPIHandler::LanguagePair_t(from_lang, to_lang), mesg, success, failure);
}
LLTranslate::KeyVerificationReceiver::KeyVerificationReceiver(EService service)
: mService(service)
/*static*/
void LLTranslate::verifyKey(EService service, const std::string &key, KeyVerificationResult_fn fnc)
{
LLTranslationAPIHandler& handler = getHandler(service);
handler.verifyKey(key, fnc);
}
LLTranslate::EService LLTranslate::KeyVerificationReceiver::getService() const
{
return mService;
}
// virtual
void LLTranslate::KeyVerificationReceiver::completedRaw(
const LLChannelDescriptors& channels,
const LLIOPipe::buffer_ptr_t& buffer)
{
bool ok = (getStatus() == HTTP_OK);
setVerificationStatus(ok);
}
//static
void LLTranslate::translateMessage(
TranslationReceiverPtr &receiver,
const std::string &from_lang,
const std::string &to_lang,
const std::string &mesg)
{
std::string url;
receiver->mHandler.getTranslateURL(url, from_lang, to_lang, mesg);
LL_DEBUGS("Translate") << "Sending translation request: " << url << LL_ENDL;
sendRequest(url, receiver);
}
// static
void LLTranslate::verifyKey(
KeyVerificationReceiverPtr& receiver,
const std::string& key)
{
std::string url;
const LLTranslationAPIHandler& handler = getHandler(receiver->getService());
handler.getKeyVerificationURL(url, key);
LL_DEBUGS("Translate") << "Sending key verification request: " << url << LL_ENDL;
sendRequest(url, receiver);
}
//static
std::string LLTranslate::getTranslateLanguage()
@ -352,7 +548,7 @@ bool LLTranslate::isTranslationConfigured()
}
// static
const LLTranslationAPIHandler& LLTranslate::getPreferredHandler()
LLTranslationAPIHandler& LLTranslate::getPreferredHandler()
{
EService service = SERVICE_BING;
@ -366,7 +562,7 @@ const LLTranslationAPIHandler& LLTranslate::getPreferredHandler()
}
// static
const LLTranslationAPIHandler& LLTranslate::getHandler(EService service)
LLTranslationAPIHandler& LLTranslate::getHandler(EService service)
{
static LLGoogleTranslationHandler google;
static LLBingTranslationHandler bing;

View File

@ -29,134 +29,14 @@
#include "llhttpclient.h"
#include "llbufferstream.h"
#include <boost/function.hpp>
namespace Json
{
class Value;
}
/**
* Handler of an HTTP machine translation service.
*
* Derived classes know the service URL
* and how to parse the translation result.
*/
class LLTranslationAPIHandler
{
public:
/**
* Get URL for translation of the given string.
*
* Sending HTTP GET request to the URL will initiate translation.
*
* @param[out] url Place holder for the result.
* @param from_lang Source language. Leave empty for auto-detection.
* @param to_lang Target language.
* @param text Text to translate.
*/
virtual void getTranslateURL(
std::string &url,
const std::string &from_lang,
const std::string &to_lang,
const std::string &text) const = 0;
/**
* Get URL to verify the given API key.
*
* Sending request to the URL verifies the key.
* Positive HTTP response (code 200) means that the key is valid.
*
* @param[out] url Place holder for the URL.
* @param[in] key Key to verify.
*/
virtual void getKeyVerificationURL(
std::string &url,
const std::string &key) const = 0;
/**
* Parse translation response.
*
* @param[in,out] status HTTP status. May be modified while parsing.
* @param body Response text.
* @param[out] translation Translated text.
* @param[out] detected_lang Detected source language. May be empty.
* @param[out] err_msg Error message (in case of error).
*/
virtual bool parseResponse(
int& status,
const std::string& body,
std::string& translation,
std::string& detected_lang,
std::string& err_msg) const = 0;
/**
* @return if the handler is configured to function properly
*/
virtual bool isConfigured() const = 0;
virtual ~LLTranslationAPIHandler() {}
};
/// Google Translate v2 API handler.
class LLGoogleTranslationHandler : public LLTranslationAPIHandler
{
LOG_CLASS(LLGoogleTranslationHandler);
public:
/*virtual*/ void getTranslateURL(
std::string &url,
const std::string &from_lang,
const std::string &to_lang,
const std::string &text) const;
/*virtual*/ void getKeyVerificationURL(
std::string &url,
const std::string &key) const;
/*virtual*/ bool parseResponse(
int& status,
const std::string& body,
std::string& translation,
std::string& detected_lang,
std::string& err_msg) const;
/*virtual*/ bool isConfigured() const;
private:
static void parseErrorResponse(
const Json::Value& root,
int& status,
std::string& err_msg);
static bool parseTranslation(
const Json::Value& root,
std::string& translation,
std::string& detected_lang);
static std::string getAPIKey();
};
/// Microsoft Translator v2 API handler.
class LLBingTranslationHandler : public LLTranslationAPIHandler
{
LOG_CLASS(LLBingTranslationHandler);
public:
/*virtual*/ void getTranslateURL(
std::string &url,
const std::string &from_lang,
const std::string &to_lang,
const std::string &text) const;
/*virtual*/ void getKeyVerificationURL(
std::string &url,
const std::string &key) const;
/*virtual*/ bool parseResponse(
int& status,
const std::string& body,
std::string& translation,
std::string& detected_lang,
std::string& err_msg) const;
/*virtual*/ bool isConfigured() const;
private:
static std::string getAPIKey();
static std::string getAPILanguageCode(const std::string& lang);
};
class LLTranslationAPIHandler;
/**
* Entry point for machine translation services.
*
@ -180,84 +60,9 @@ public :
SERVICE_GOOGLE,
} EService;
/**
* Subclasses are supposed to handle translation results (e.g. show them in chat)
*/
class TranslationReceiver: public LLHTTPClient::Responder
{
public:
/**
* Using mHandler, parse incoming response.
*
* Calls either handleResponse() or handleFailure()
* depending on the HTTP status code and parsing success.
*
* @see handleResponse()
* @see handleFailure()
* @see mHandler
*/
/*virtual*/ void completedRaw(
const LLChannelDescriptors& channels,
const LLIOPipe::buffer_ptr_t& buffer);
protected:
friend class LLTranslate;
/// Remember source and target languages for subclasses to be able to filter inappropriate results.
TranslationReceiver(const std::string& from_lang, const std::string& to_lang);
/// Override point to handle successful translation.
virtual void handleResponse(const std::string &translation, const std::string &recognized_lang) = 0;
/// Override point to handle unsuccessful translation.
virtual void handleFailure(int status, const std::string& err_msg) = 0;
std::string mFromLang;
std::string mToLang;
const LLTranslationAPIHandler& mHandler;
};
/**
* Subclasses are supposed to handle API key verification result.
*/
class KeyVerificationReceiver: public LLHTTPClient::Responder
{
public:
EService getService() const;
protected:
/**
* Save the translation service the key belongs to.
*
* Subclasses need to know it.
*
* @see getService()
*/
KeyVerificationReceiver(EService service);
/**
* Parse verification response.
*
* Calls setVerificationStatus() with the verification status,
* which is true if HTTP status code is 200.
*
* @see setVerificationStatus()
*/
/*virtual*/ void completedRaw(
const LLChannelDescriptors& channels,
const LLIOPipe::buffer_ptr_t& buffer);
/**
* Override point for subclasses to handle key verification status.
*/
virtual void setVerificationStatus(bool ok) = 0;
EService mService;
};
typedef LLPointer<TranslationReceiver> TranslationReceiverPtr;
typedef LLPointer<KeyVerificationReceiver> KeyVerificationReceiverPtr;
typedef boost::function<void(EService, bool)> KeyVerificationResult_fn;
typedef boost::function<void(std::string , std::string )> TranslationSuccess_fn;
typedef boost::function<void(int, std::string)> TranslationFailure_fn;
/**
* Translate given text.
@ -267,15 +72,15 @@ public :
* @param to_lang Target language.
* @param mesg Text to translate.
*/
static void translateMessage(TranslationReceiverPtr &receiver, const std::string &from_lang, const std::string &to_lang, const std::string &mesg);
static void translateMessage(const std::string &from_lang, const std::string &to_lang, const std::string &mesg, TranslationSuccess_fn success, TranslationFailure_fn failure);
/**
/**
* Verify given API key of a translation service.
*
* @param receiver Object to pass verification result to.
* @param key Key to verify.
*/
static void verifyKey(KeyVerificationReceiverPtr& receiver, const std::string& key);
static void verifyKey(EService service, const std::string &key, KeyVerificationResult_fn fnc);
/**
* @return translation target language
@ -288,8 +93,8 @@ public :
static bool isTranslationConfigured();
private:
static const LLTranslationAPIHandler& getPreferredHandler();
static const LLTranslationAPIHandler& getHandler(EService service);
static LLTranslationAPIHandler& getPreferredHandler();
static LLTranslationAPIHandler& getHandler(EService service);
static void sendRequest(const std::string& url, LLHTTPClient::ResponderPtr responder);
};

View File

@ -3492,53 +3492,29 @@ void process_decline_callingcard(LLMessageSystem* msg, void**)
LLNotificationsUtil::add("CallingCardDeclined");
}
class ChatTranslationReceiver : public LLTranslate::TranslationReceiver
void translateSuccess(LLChat chat, LLSD toastArgs, std::string originalMsg, std::string expectLang, std::string translation, const std::string detected_language)
{
public :
ChatTranslationReceiver(const std::string &from_lang, const std::string &to_lang, const std::string &mesg,
const LLChat &chat, const LLSD &toast_args)
: LLTranslate::TranslationReceiver(from_lang, to_lang),
m_chat(chat),
m_toastArgs(toast_args),
m_origMesg(mesg)
{
}
// filter out non-interesting responses
if (!translation.empty()
&& (expectLang != detected_language)
&& (LLStringUtil::compareInsensitive(translation, originalMsg) != 0))
{
chat.mText += " (" + translation + ")";
}
static ChatTranslationReceiver* build(const std::string &from_lang, const std::string &to_lang, const std::string &mesg, const LLChat &chat, const LLSD &toast_args)
{
return new ChatTranslationReceiver(from_lang, to_lang, mesg, chat, toast_args);
}
LLNotificationsUI::LLNotificationManager::instance().onChat(chat, toastArgs);
}
protected:
void handleResponse(const std::string &translation, const std::string &detected_language)
{
// filter out non-interesting responeses
if ( !translation.empty()
&& (mToLang != detected_language)
&& (LLStringUtil::compareInsensitive(translation, m_origMesg) != 0) )
{
m_chat.mText += " (" + translation + ")";
}
void translateFailure(LLChat chat, LLSD toastArgs, int status, const std::string err_msg)
{
std::string msg = LLTrans::getString("TranslationFailed", LLSD().with("[REASON]", err_msg));
LLStringUtil::replaceString(msg, "\n", " "); // we want one-line error messages
chat.mText += " (" + msg + ")";
LLNotificationsUI::LLNotificationManager::instance().onChat(m_chat, m_toastArgs);
}
LLNotificationsUI::LLNotificationManager::instance().onChat(chat, toastArgs);
}
void handleFailure(int status, const std::string& err_msg)
{
LL_WARNS() << "Translation failed for mesg " << m_origMesg << " toLang " << mToLang << " fromLang " << mFromLang << LL_ENDL;
std::string msg = LLTrans::getString("TranslationFailed", LLSD().with("[REASON]", err_msg));
LLStringUtil::replaceString(msg, "\n", " "); // we want one-line error messages
m_chat.mText += " (" + msg + ")";
LLNotificationsUI::LLNotificationManager::instance().onChat(m_chat, m_toastArgs);
}
private:
LLChat m_chat;
std::string m_origMesg;
LLSD m_toastArgs;
};
void process_chat_from_simulator(LLMessageSystem *msg, void **user_data)
{
LLChat chat;
@ -3774,8 +3750,10 @@ void process_chat_from_simulator(LLMessageSystem *msg, void **user_data)
const std::string from_lang = ""; // leave empty to trigger autodetect
const std::string to_lang = LLTranslate::getTranslateLanguage();
LLTranslate::TranslationReceiverPtr result = ChatTranslationReceiver::build(from_lang, to_lang, mesg, chat, args);
LLTranslate::translateMessage(result, from_lang, to_lang, mesg);
LLTranslate::translateMessage(from_lang, to_lang, mesg,
boost::bind(&translateSuccess, chat, args, mesg, from_lang, _1, _2),
boost::bind(&translateFailure, chat, args, _1, _2));
}
else
{