Print all libcurl calls if -DDEBUG_CURLIO. Don't create static lib for cwdebug.

Basically, cmake doesn't support linking static libs into a shared lib.
The correct way is to just specify source files in subdirectories
directly as source files of the shared library. This patch changes that.

Also, after this commit, when DEBUG_CURLIO is defined, every call to
libcurl is printed to llinfos (or to dc::curl when using libcwd).
This commit is contained in:
Aleric Inglewood
2012-08-05 18:51:21 +02:00
parent 98c740f204
commit caef97ad36
16 changed files with 878 additions and 59 deletions

View File

@@ -46,7 +46,6 @@ endif(NOT STANDALONE)
add_custom_target(prepare DEPENDS ${prepare_depends})
add_subdirectory(cmake)
add_subdirectory(${LIBS_OPEN_PREFIX}cwdebug)
add_subdirectory(${LIBS_OPEN_PREFIX}llaudio)
add_subdirectory(${LIBS_OPEN_PREFIX}llcharacter)
add_subdirectory(${LIBS_OPEN_PREFIX}llcommon)

View File

@@ -1 +1,20 @@
set(CWDEBUG_LIBRARIES cwdebug)
include_directories (${CMAKE_SOURCE_DIR}/cwdebug)
set(cwdebug_SOURCE_FILES
${CMAKE_SOURCE_DIR}/cwdebug/debug.cc
${CMAKE_SOURCE_DIR}/cwdebug/debug_libcurl.cc
)
set(cwdebug_HEADER_FILES
${CMAKE_SOURCE_DIR}/cwdebug/cwdebug.h
${CMAKE_SOURCE_DIR}/cwdebug/sys.h
${CMAKE_SOURCE_DIR}/cwdebug/debug.h
${CMAKE_SOURCE_DIR}/cwdebug/debug_ostream_operators.h
${CMAKE_SOURCE_DIR}/cwdebug/debug_libcurl.h
)
set_source_files_properties(${cwdebug_HEADER_FILES}
PROPERTIES HEADER_FILE_ONLY TRUE)
list(APPEND cwdebug_SOURCE_FILES ${cwdebug_HEADER_FILES})

View File

@@ -1,41 +0,0 @@
# -*- cmake -*-
project(cwdebug)
include(00-Common)
include(LLCommon)
include(LLMath)
include(LLMessage)
include(LLVFS)
include_directories (${CMAKE_CURRENT_SOURCE_DIR})
set(cwdebug_SOURCE_FILES
debug.cc
)
set(cwdebug_HEADER_FILES
CMakeLists.txt
cwdebug.h
sys.h
debug.h
debug_ostream_operators.h
)
set_source_files_properties(${cwdebug_HEADER_FILES}
PROPERTIES HEADER_FILE_ONLY TRUE)
if(NOT WORD_SIZE EQUAL 32)
if(WINDOWS)
add_definitions(/FIXED:NO)
else(WINDOWS) # not windows therefore gcc LINUX and DARWIN
add_definitions(-fPIC)
endif(WINDOWS)
endif (NOT WORD_SIZE EQUAL 32)
add_definitions(-Dcwdebug_EXPORTS)
list(APPEND cwdebug_SOURCE_FILES ${cwdebug_HEADER_FILES})
add_library (cwdebug ${cwdebug_SOURCE_FILES})

View File

@@ -41,7 +41,7 @@
#endif // LL_WINDOWS
#if LL_COMMON_LINK_SHARED
#if defined(cwdebug_EXPORTS) || defined(llcommon_EXPORTS)
#if defined(llcommon_EXPORTS)
#define CWD_API CWD_DLLEXPORT
#else // cwdebug_EXPORTS
#define CWD_API CWD_DLLIMPORT

View File

@@ -0,0 +1,769 @@
#ifdef DEBUG_CURLIO
#include "sys.h"
#include <iostream>
#include <iomanip>
#include <stdarg.h>
#define COMPILING_DEBUG_LIBCURL_CC
#include "debug_libcurl.h"
#include "../llcommon/llerror.h"
static struct curl_slist unchanged_slist;
std::ostream& operator<<(std::ostream& os, struct curl_slist const& slist)
{
struct curl_slist const* ptr = &slist;
if (ptr == &unchanged_slist)
os << " <unchanged> ";
else
{
os << "(curl_slist)@0x" << std::hex << (size_t)ptr << std::dec << "{";
do
{
os << '"' << ptr->data << '"';
ptr = ptr->next;
if (ptr)
os << ", ";
}
while(ptr);
os << "}";
}
return os;
}
#define CASEPRINT(x) case x: os << #x; break
std::ostream& operator<<(std::ostream& os, CURLINFO info)
{
switch (info)
{
CASEPRINT(CURLINFO_EFFECTIVE_URL);
CASEPRINT(CURLINFO_RESPONSE_CODE);
CASEPRINT(CURLINFO_TOTAL_TIME);
CASEPRINT(CURLINFO_NAMELOOKUP_TIME);
CASEPRINT(CURLINFO_CONNECT_TIME);
CASEPRINT(CURLINFO_PRETRANSFER_TIME);
CASEPRINT(CURLINFO_SIZE_UPLOAD);
CASEPRINT(CURLINFO_SIZE_DOWNLOAD);
CASEPRINT(CURLINFO_SPEED_DOWNLOAD);
CASEPRINT(CURLINFO_SPEED_UPLOAD);
CASEPRINT(CURLINFO_HEADER_SIZE);
CASEPRINT(CURLINFO_REQUEST_SIZE);
CASEPRINT(CURLINFO_SSL_VERIFYRESULT);
CASEPRINT(CURLINFO_FILETIME);
CASEPRINT(CURLINFO_CONTENT_LENGTH_DOWNLOAD);
CASEPRINT(CURLINFO_CONTENT_LENGTH_UPLOAD);
CASEPRINT(CURLINFO_STARTTRANSFER_TIME);
CASEPRINT(CURLINFO_CONTENT_TYPE);
CASEPRINT(CURLINFO_REDIRECT_TIME);
CASEPRINT(CURLINFO_REDIRECT_COUNT);
CASEPRINT(CURLINFO_PRIVATE);
CASEPRINT(CURLINFO_HTTP_CONNECTCODE);
CASEPRINT(CURLINFO_HTTPAUTH_AVAIL);
CASEPRINT(CURLINFO_PROXYAUTH_AVAIL);
CASEPRINT(CURLINFO_OS_ERRNO);
CASEPRINT(CURLINFO_NUM_CONNECTS);
CASEPRINT(CURLINFO_SSL_ENGINES);
CASEPRINT(CURLINFO_COOKIELIST);
CASEPRINT(CURLINFO_LASTSOCKET);
CASEPRINT(CURLINFO_FTP_ENTRY_PATH);
CASEPRINT(CURLINFO_REDIRECT_URL);
CASEPRINT(CURLINFO_PRIMARY_IP);
CASEPRINT(CURLINFO_APPCONNECT_TIME);
CASEPRINT(CURLINFO_CERTINFO);
CASEPRINT(CURLINFO_CONDITION_UNMET);
CASEPRINT(CURLINFO_RTSP_SESSION_ID);
CASEPRINT(CURLINFO_RTSP_CLIENT_CSEQ);
CASEPRINT(CURLINFO_RTSP_SERVER_CSEQ);
CASEPRINT(CURLINFO_RTSP_CSEQ_RECV);
CASEPRINT(CURLINFO_PRIMARY_PORT);
CASEPRINT(CURLINFO_LOCAL_IP);
CASEPRINT(CURLINFO_LOCAL_PORT);
default:
os << "<unknown" << " CURLINFO value (" << (int)info << ")>";
}
return os;
}
std::ostream& operator<<(std::ostream& os, CURLcode code)
{
switch(code)
{
CASEPRINT(CURLE_OK);
CASEPRINT(CURLE_UNSUPPORTED_PROTOCOL);
CASEPRINT(CURLE_FAILED_INIT);
CASEPRINT(CURLE_URL_MALFORMAT);
CASEPRINT(CURLE_NOT_BUILT_IN);
CASEPRINT(CURLE_COULDNT_RESOLVE_PROXY);
CASEPRINT(CURLE_COULDNT_RESOLVE_HOST);
CASEPRINT(CURLE_COULDNT_CONNECT);
CASEPRINT(CURLE_FTP_WEIRD_SERVER_REPLY);
CASEPRINT(CURLE_REMOTE_ACCESS_DENIED);
CASEPRINT(CURLE_FTP_ACCEPT_FAILED);
CASEPRINT(CURLE_FTP_WEIRD_PASS_REPLY);
CASEPRINT(CURLE_FTP_ACCEPT_TIMEOUT);
CASEPRINT(CURLE_FTP_WEIRD_PASV_REPLY);
CASEPRINT(CURLE_FTP_WEIRD_227_FORMAT);
CASEPRINT(CURLE_FTP_CANT_GET_HOST);
CASEPRINT(CURLE_OBSOLETE16);
CASEPRINT(CURLE_FTP_COULDNT_SET_TYPE);
CASEPRINT(CURLE_PARTIAL_FILE);
CASEPRINT(CURLE_FTP_COULDNT_RETR_FILE);
CASEPRINT(CURLE_OBSOLETE20);
CASEPRINT(CURLE_QUOTE_ERROR);
CASEPRINT(CURLE_HTTP_RETURNED_ERROR);
CASEPRINT(CURLE_WRITE_ERROR);
CASEPRINT(CURLE_OBSOLETE24);
CASEPRINT(CURLE_UPLOAD_FAILED);
CASEPRINT(CURLE_READ_ERROR);
CASEPRINT(CURLE_OUT_OF_MEMORY);
CASEPRINT(CURLE_OPERATION_TIMEDOUT);
CASEPRINT(CURLE_OBSOLETE29);
CASEPRINT(CURLE_FTP_PORT_FAILED);
CASEPRINT(CURLE_FTP_COULDNT_USE_REST);
CASEPRINT(CURLE_OBSOLETE32);
CASEPRINT(CURLE_RANGE_ERROR);
CASEPRINT(CURLE_HTTP_POST_ERROR);
CASEPRINT(CURLE_SSL_CONNECT_ERROR);
CASEPRINT(CURLE_BAD_DOWNLOAD_RESUME);
CASEPRINT(CURLE_FILE_COULDNT_READ_FILE);
CASEPRINT(CURLE_LDAP_CANNOT_BIND);
CASEPRINT(CURLE_LDAP_SEARCH_FAILED);
CASEPRINT(CURLE_OBSOLETE40);
CASEPRINT(CURLE_FUNCTION_NOT_FOUND);
CASEPRINT(CURLE_ABORTED_BY_CALLBACK);
CASEPRINT(CURLE_BAD_FUNCTION_ARGUMENT);
CASEPRINT(CURLE_OBSOLETE44);
CASEPRINT(CURLE_INTERFACE_FAILED);
CASEPRINT(CURLE_OBSOLETE46);
CASEPRINT(CURLE_TOO_MANY_REDIRECTS );
CASEPRINT(CURLE_UNKNOWN_OPTION);
CASEPRINT(CURLE_TELNET_OPTION_SYNTAX );
CASEPRINT(CURLE_OBSOLETE50);
CASEPRINT(CURLE_PEER_FAILED_VERIFICATION);
CASEPRINT(CURLE_GOT_NOTHING);
CASEPRINT(CURLE_SSL_ENGINE_NOTFOUND);
CASEPRINT(CURLE_SSL_ENGINE_SETFAILED);
CASEPRINT(CURLE_SEND_ERROR);
CASEPRINT(CURLE_RECV_ERROR);
CASEPRINT(CURLE_OBSOLETE57);
CASEPRINT(CURLE_SSL_CERTPROBLEM);
CASEPRINT(CURLE_SSL_CIPHER);
CASEPRINT(CURLE_SSL_CACERT);
CASEPRINT(CURLE_BAD_CONTENT_ENCODING);
CASEPRINT(CURLE_LDAP_INVALID_URL);
CASEPRINT(CURLE_FILESIZE_EXCEEDED);
CASEPRINT(CURLE_USE_SSL_FAILED);
CASEPRINT(CURLE_SEND_FAIL_REWIND);
CASEPRINT(CURLE_SSL_ENGINE_INITFAILED);
CASEPRINT(CURLE_LOGIN_DENIED);
CASEPRINT(CURLE_TFTP_NOTFOUND);
CASEPRINT(CURLE_TFTP_PERM);
CASEPRINT(CURLE_REMOTE_DISK_FULL);
CASEPRINT(CURLE_TFTP_ILLEGAL);
CASEPRINT(CURLE_TFTP_UNKNOWNID);
CASEPRINT(CURLE_REMOTE_FILE_EXISTS);
CASEPRINT(CURLE_TFTP_NOSUCHUSER);
CASEPRINT(CURLE_CONV_FAILED);
CASEPRINT(CURLE_CONV_REQD);
CASEPRINT(CURLE_SSL_CACERT_BADFILE);
CASEPRINT(CURLE_REMOTE_FILE_NOT_FOUND);
CASEPRINT(CURLE_SSH);
CASEPRINT(CURLE_SSL_SHUTDOWN_FAILED);
CASEPRINT(CURLE_AGAIN);
CASEPRINT(CURLE_SSL_CRL_BADFILE);
CASEPRINT(CURLE_SSL_ISSUER_ERROR);
CASEPRINT(CURLE_FTP_PRET_FAILED);
CASEPRINT(CURLE_RTSP_CSEQ_ERROR);
CASEPRINT(CURLE_RTSP_SESSION_ERROR);
CASEPRINT(CURLE_FTP_BAD_FILE_LIST);
CASEPRINT(CURLE_CHUNK_FAILED);
default:
os << (code == CURL_LAST ? "<illegal" : "<unknown") << " CURLcode value (" << (int)code << ")>";
}
return os;
}
struct AICURL;
struct AICURLM;
std::ostream& operator<<(std::ostream& os, AICURL* curl)
{
os << "(CURL*)0x" << std::hex << (size_t)curl << std::dec;
return os;
}
std::ostream& operator<<(std::ostream& os, AICURLM* curl)
{
os << "(CURLM*)0x" << std::hex << (size_t)curl << std::dec;
return os;
}
std::ostream& operator<<(std::ostream& os, CURLoption option)
{
switch(option)
{
CASEPRINT(CURLOPT_WRITEDATA);
CASEPRINT(CURLOPT_URL);
CASEPRINT(CURLOPT_PORT);
CASEPRINT(CURLOPT_PROXY);
CASEPRINT(CURLOPT_USERPWD);
CASEPRINT(CURLOPT_PROXYUSERPWD);
CASEPRINT(CURLOPT_RANGE);
CASEPRINT(CURLOPT_READDATA);
CASEPRINT(CURLOPT_ERRORBUFFER);
CASEPRINT(CURLOPT_WRITEFUNCTION);
CASEPRINT(CURLOPT_READFUNCTION);
CASEPRINT(CURLOPT_TIMEOUT);
CASEPRINT(CURLOPT_INFILESIZE);
CASEPRINT(CURLOPT_POSTFIELDS);
CASEPRINT(CURLOPT_REFERER);
CASEPRINT(CURLOPT_FTPPORT);
CASEPRINT(CURLOPT_USERAGENT);
CASEPRINT(CURLOPT_LOW_SPEED_LIMIT);
CASEPRINT(CURLOPT_LOW_SPEED_TIME);
CASEPRINT(CURLOPT_RESUME_FROM);
CASEPRINT(CURLOPT_COOKIE);
CASEPRINT(CURLOPT_RTSPHEADER);
CASEPRINT(CURLOPT_HTTPPOST);
CASEPRINT(CURLOPT_SSLCERT);
CASEPRINT(CURLOPT_KEYPASSWD);
CASEPRINT(CURLOPT_CRLF);
CASEPRINT(CURLOPT_QUOTE);
CASEPRINT(CURLOPT_HEADERDATA);
CASEPRINT(CURLOPT_COOKIEFILE);
CASEPRINT(CURLOPT_SSLVERSION);
CASEPRINT(CURLOPT_TIMECONDITION);
CASEPRINT(CURLOPT_TIMEVALUE);
CASEPRINT(CURLOPT_CUSTOMREQUEST);
CASEPRINT(CURLOPT_STDERR);
CASEPRINT(CURLOPT_POSTQUOTE);
CASEPRINT(CURLOPT_WRITEINFO);
CASEPRINT(CURLOPT_VERBOSE);
CASEPRINT(CURLOPT_HEADER);
CASEPRINT(CURLOPT_NOPROGRESS);
CASEPRINT(CURLOPT_NOBODY);
CASEPRINT(CURLOPT_FAILONERROR);
CASEPRINT(CURLOPT_UPLOAD);
CASEPRINT(CURLOPT_POST);
CASEPRINT(CURLOPT_DIRLISTONLY);
CASEPRINT(CURLOPT_APPEND);
CASEPRINT(CURLOPT_NETRC);
CASEPRINT(CURLOPT_FOLLOWLOCATION);
CASEPRINT(CURLOPT_TRANSFERTEXT);
CASEPRINT(CURLOPT_PUT);
CASEPRINT(CURLOPT_PROGRESSFUNCTION);
CASEPRINT(CURLOPT_PROGRESSDATA);
CASEPRINT(CURLOPT_AUTOREFERER);
CASEPRINT(CURLOPT_PROXYPORT);
CASEPRINT(CURLOPT_HTTPPROXYTUNNEL);
CASEPRINT(CURLOPT_INTERFACE);
CASEPRINT(CURLOPT_KRBLEVEL);
CASEPRINT(CURLOPT_SSL_VERIFYPEER);
CASEPRINT(CURLOPT_CAINFO);
CASEPRINT(CURLOPT_MAXREDIRS);
CASEPRINT(CURLOPT_FILETIME);
CASEPRINT(CURLOPT_TELNETOPTIONS);
CASEPRINT(CURLOPT_MAXCONNECTS);
CASEPRINT(CURLOPT_CLOSEPOLICY);
CASEPRINT(CURLOPT_FRESH_CONNECT);
CASEPRINT(CURLOPT_FORBID_REUSE);
CASEPRINT(CURLOPT_RANDOM_FILE);
CASEPRINT(CURLOPT_EGDSOCKET);
CASEPRINT(CURLOPT_CONNECTTIMEOUT);
CASEPRINT(CURLOPT_HEADERFUNCTION);
CASEPRINT(CURLOPT_HTTPGET);
CASEPRINT(CURLOPT_SSL_VERIFYHOST);
CASEPRINT(CURLOPT_COOKIEJAR);
CASEPRINT(CURLOPT_SSL_CIPHER_LIST);
CASEPRINT(CURLOPT_HTTP_VERSION);
CASEPRINT(CURLOPT_FTP_USE_EPSV);
CASEPRINT(CURLOPT_SSLCERTTYPE);
CASEPRINT(CURLOPT_SSLKEY);
CASEPRINT(CURLOPT_SSLKEYTYPE);
CASEPRINT(CURLOPT_SSLENGINE);
CASEPRINT(CURLOPT_SSLENGINE_DEFAULT);
CASEPRINT(CURLOPT_DNS_USE_GLOBAL_CACHE);
CASEPRINT(CURLOPT_DNS_CACHE_TIMEOUT);
CASEPRINT(CURLOPT_PREQUOTE);
CASEPRINT(CURLOPT_DEBUGFUNCTION);
CASEPRINT(CURLOPT_DEBUGDATA);
CASEPRINT(CURLOPT_COOKIESESSION);
CASEPRINT(CURLOPT_CAPATH);
CASEPRINT(CURLOPT_BUFFERSIZE);
CASEPRINT(CURLOPT_NOSIGNAL);
CASEPRINT(CURLOPT_SHARE);
CASEPRINT(CURLOPT_PROXYTYPE);
CASEPRINT(CURLOPT_ACCEPT_ENCODING);
CASEPRINT(CURLOPT_PRIVATE);
CASEPRINT(CURLOPT_HTTP200ALIASES);
CASEPRINT(CURLOPT_UNRESTRICTED_AUTH);
CASEPRINT(CURLOPT_FTP_USE_EPRT);
CASEPRINT(CURLOPT_HTTPAUTH);
CASEPRINT(CURLOPT_SSL_CTX_FUNCTION);
CASEPRINT(CURLOPT_SSL_CTX_DATA);
CASEPRINT(CURLOPT_FTP_CREATE_MISSING_DIRS);
CASEPRINT(CURLOPT_PROXYAUTH);
CASEPRINT(CURLOPT_FTP_RESPONSE_TIMEOUT);
CASEPRINT(CURLOPT_IPRESOLVE);
CASEPRINT(CURLOPT_MAXFILESIZE);
CASEPRINT(CURLOPT_INFILESIZE_LARGE);
CASEPRINT(CURLOPT_RESUME_FROM_LARGE);
CASEPRINT(CURLOPT_MAXFILESIZE_LARGE);
CASEPRINT(CURLOPT_NETRC_FILE);
CASEPRINT(CURLOPT_USE_SSL);
CASEPRINT(CURLOPT_POSTFIELDSIZE_LARGE);
CASEPRINT(CURLOPT_TCP_NODELAY);
CASEPRINT(CURLOPT_FTPSSLAUTH);
CASEPRINT(CURLOPT_IOCTLFUNCTION);
CASEPRINT(CURLOPT_IOCTLDATA);
CASEPRINT(CURLOPT_FTP_ACCOUNT);
CASEPRINT(CURLOPT_COOKIELIST);
CASEPRINT(CURLOPT_IGNORE_CONTENT_LENGTH);
CASEPRINT(CURLOPT_FTP_SKIP_PASV_IP);
CASEPRINT(CURLOPT_FTP_FILEMETHOD);
CASEPRINT(CURLOPT_LOCALPORT);
CASEPRINT(CURLOPT_LOCALPORTRANGE);
CASEPRINT(CURLOPT_CONNECT_ONLY);
CASEPRINT(CURLOPT_CONV_FROM_NETWORK_FUNCTION);
CASEPRINT(CURLOPT_CONV_TO_NETWORK_FUNCTION);
CASEPRINT(CURLOPT_CONV_FROM_UTF8_FUNCTION);
CASEPRINT(CURLOPT_MAX_SEND_SPEED_LARGE);
CASEPRINT(CURLOPT_MAX_RECV_SPEED_LARGE);
CASEPRINT(CURLOPT_FTP_ALTERNATIVE_TO_USER);
CASEPRINT(CURLOPT_SOCKOPTFUNCTION);
CASEPRINT(CURLOPT_SOCKOPTDATA);
CASEPRINT(CURLOPT_SSL_SESSIONID_CACHE);
CASEPRINT(CURLOPT_SSH_AUTH_TYPES);
CASEPRINT(CURLOPT_SSH_PUBLIC_KEYFILE);
CASEPRINT(CURLOPT_SSH_PRIVATE_KEYFILE);
CASEPRINT(CURLOPT_FTP_SSL_CCC);
CASEPRINT(CURLOPT_TIMEOUT_MS);
CASEPRINT(CURLOPT_CONNECTTIMEOUT_MS);
CASEPRINT(CURLOPT_HTTP_TRANSFER_DECODING);
CASEPRINT(CURLOPT_HTTP_CONTENT_DECODING);
CASEPRINT(CURLOPT_NEW_FILE_PERMS);
CASEPRINT(CURLOPT_NEW_DIRECTORY_PERMS);
CASEPRINT(CURLOPT_POSTREDIR);
CASEPRINT(CURLOPT_SSH_HOST_PUBLIC_KEY_MD5);
CASEPRINT(CURLOPT_OPENSOCKETFUNCTION);
CASEPRINT(CURLOPT_OPENSOCKETDATA);
CASEPRINT(CURLOPT_COPYPOSTFIELDS);
CASEPRINT(CURLOPT_PROXY_TRANSFER_MODE);
CASEPRINT(CURLOPT_SEEKFUNCTION);
CASEPRINT(CURLOPT_SEEKDATA);
CASEPRINT(CURLOPT_CRLFILE);
CASEPRINT(CURLOPT_ISSUERCERT);
CASEPRINT(CURLOPT_ADDRESS_SCOPE);
CASEPRINT(CURLOPT_CERTINFO);
CASEPRINT(CURLOPT_USERNAME);
CASEPRINT(CURLOPT_PASSWORD);
CASEPRINT(CURLOPT_PROXYUSERNAME);
CASEPRINT(CURLOPT_PROXYPASSWORD);
CASEPRINT(CURLOPT_NOPROXY);
CASEPRINT(CURLOPT_TFTP_BLKSIZE);
CASEPRINT(CURLOPT_SOCKS5_GSSAPI_SERVICE);
CASEPRINT(CURLOPT_SOCKS5_GSSAPI_NEC);
CASEPRINT(CURLOPT_PROTOCOLS);
CASEPRINT(CURLOPT_REDIR_PROTOCOLS);
CASEPRINT(CURLOPT_SSH_KNOWNHOSTS);
CASEPRINT(CURLOPT_SSH_KEYFUNCTION);
CASEPRINT(CURLOPT_SSH_KEYDATA);
CASEPRINT(CURLOPT_MAIL_FROM);
CASEPRINT(CURLOPT_MAIL_RCPT);
CASEPRINT(CURLOPT_FTP_USE_PRET);
CASEPRINT(CURLOPT_RTSP_REQUEST);
CASEPRINT(CURLOPT_RTSP_SESSION_ID);
CASEPRINT(CURLOPT_RTSP_STREAM_URI);
CASEPRINT(CURLOPT_RTSP_TRANSPORT);
CASEPRINT(CURLOPT_RTSP_CLIENT_CSEQ);
CASEPRINT(CURLOPT_RTSP_SERVER_CSEQ);
CASEPRINT(CURLOPT_INTERLEAVEDATA);
CASEPRINT(CURLOPT_INTERLEAVEFUNCTION);
CASEPRINT(CURLOPT_WILDCARDMATCH);
CASEPRINT(CURLOPT_CHUNK_BGN_FUNCTION);
CASEPRINT(CURLOPT_CHUNK_END_FUNCTION);
CASEPRINT(CURLOPT_FNMATCH_FUNCTION);
CASEPRINT(CURLOPT_CHUNK_DATA);
CASEPRINT(CURLOPT_FNMATCH_DATA);
CASEPRINT(CURLOPT_RESOLVE);
CASEPRINT(CURLOPT_TLSAUTH_USERNAME);
CASEPRINT(CURLOPT_TLSAUTH_PASSWORD);
CASEPRINT(CURLOPT_TLSAUTH_TYPE);
CASEPRINT(CURLOPT_TRANSFER_ENCODING);
CASEPRINT(CURLOPT_CLOSESOCKETFUNCTION);
CASEPRINT(CURLOPT_CLOSESOCKETDATA);
CASEPRINT(CURLOPT_GSSAPI_DELEGATION);
CASEPRINT(CURLOPT_DNS_SERVERS);
CASEPRINT(CURLOPT_ACCEPTTIMEOUT_MS);
CASEPRINT(CURLOPT_TCP_KEEPALIVE);
CASEPRINT(CURLOPT_TCP_KEEPIDLE);
CASEPRINT(CURLOPT_TCP_KEEPINTVL);
CASEPRINT(CURLOPT_SSL_OPTIONS);
CASEPRINT(CURLOPT_MAIL_AUTH);
default:
os << "<unknown CURLoption value (" << (int)option << ")>";
}
return os;
}
std::ostream& operator<<(std::ostream& os, CURLMoption option)
{
switch(option)
{
CASEPRINT(CURLMOPT_SOCKETFUNCTION);
CASEPRINT(CURLMOPT_SOCKETDATA);
CASEPRINT(CURLMOPT_PIPELINING);
CASEPRINT(CURLMOPT_TIMERFUNCTION);
CASEPRINT(CURLMOPT_TIMERDATA);
CASEPRINT(CURLMOPT_MAXCONNECTS);
default:
os << "<unknown CURLMoption value (" << (int)option << ")>";
}
return os;
}
std::ostream& operator<<(std::ostream& os, CURLMsg* msg)
{
if (msg)
{
os << "(CURLMsg*){";
if (msg->msg == CURLMSG_DONE)
os << "CURLMSG_DONE";
else
os << msg->msg;
os << ", " << (AICURL*)msg->easy_handle << ", 0x" << std::hex << (size_t)msg->data.whatever << std::dec << '}';
}
else
os << "(CURLMsg*)NULL";
return os;
}
struct EvBitmask {
int mBitmask;
EvBitmask(int mask) : mBitmask(mask) { }
};
std::ostream& operator<<(std::ostream& os, EvBitmask const& bitmask)
{
int m = bitmask.mBitmask;
if (m == 0)
os << '0';
if ((m & CURL_CSELECT_IN))
{
os << "CURL_CSELECT_IN";
if ((m & (CURL_CSELECT_OUT|CURL_CSELECT_ERR)))
os << '|';
}
if ((m & CURL_CSELECT_OUT))
{
os << "CURL_CSELECT_OUT";
if ((m & CURL_CSELECT_ERR))
os << '|';
}
if ((m & CURL_CSELECT_ERR))
{
os << "CURL_CSELECT_ERR";
}
return os;
}
extern "C" {
void debug_curl_easy_cleanup(CURL* handle)
{
curl_easy_cleanup(handle);
Dout(dc::curl, "curl_easy_cleanup(" << (AICURL*)handle << ")");
}
CURL* debug_curl_easy_duphandle(CURL* handle)
{
CURL* ret;
ret = curl_easy_duphandle(handle);
Dout(dc::curl, "curl_easy_duphandle(" << (AICURL*)handle << ") = " << (AICURL*)ret);
return ret;
}
char* debug_curl_easy_escape(CURL* curl, char* url, int length)
{
char* ret;
ret = curl_easy_escape(curl, url, length);
Dout(dc::curl, "curl_easy_escape(" << curl << ", \"" << url << "\", " << length << ") = \"" << ret << '"');
return ret;
}
CURLcode debug_curl_easy_getinfo(CURL* curl, CURLINFO info, ...)
{
CURLcode ret;
va_list ap;
union param_type {
long* long_ptr;
char* char_ptr;
curl_slist* curl_slist_ptr;
double* double_ptr;
} param;
va_start(ap, info);
param.long_ptr = va_arg(ap, long*);
va_end(ap);
ret = curl_easy_getinfo(curl, info, param.long_ptr);
if (info == CURLINFO_PRIVATE)
{
Dout(dc::curl, "curl_easy_getinfo(" << curl << ", " << info << ", 0x" << std::hex << (size_t)param.char_ptr << std::dec << ") = " << ret);
}
else
{
switch((info & CURLINFO_TYPEMASK))
{
case CURLINFO_STRING:
Dout(dc::curl, "curl_easy_getinfo(" << curl << ", " << info << ", (char*){ \"" << (ret == CURLE_OK ? param.char_ptr : " <unchanged> ") << "\" }) = " << ret);
break;
case CURLINFO_LONG:
Dout(dc::curl, "curl_easy_getinfo(" << curl << ", " << info << ", (long*){ " << (ret == CURLE_OK ? *param.long_ptr : 0L) << "L }) = " << ret);
break;
case CURLINFO_DOUBLE:
Dout(dc::curl, "curl_easy_getinfo(" << curl << ", " << info << ", (double*){" << (ret == CURLE_OK ? *param.double_ptr : 0.) << "}) = " << ret);
break;
case CURLINFO_SLIST:
Dout(dc::curl, "curl_easy_getinfo(" << curl << ", " << info << ", (curl_slist*){ " << (ret == CURLE_OK ? *param.curl_slist_ptr : unchanged_slist) << " }) = " << ret);
break;
}
}
return ret;
}
CURL* debug_curl_easy_init(void)
{
CURL* ret;
ret = curl_easy_init();
Dout(dc::curl, "curl_easy_init() = " << (AICURL*)ret);
return ret;
}
CURLcode debug_curl_easy_pause(CURL* handle, int bitmask)
{
CURLcode ret;
ret = curl_easy_pause(handle, bitmask);
Dout(dc::curl, "curl_easy_pause(" << (AICURL*)handle << ", 0x" << std::hex << bitmask << std::dec << ") = " << ret);
return ret;
}
CURLcode debug_curl_easy_perform(CURL* handle)
{
CURLcode ret;
ret = curl_easy_perform(handle);
Dout(dc::curl, "curl_easy_perform(" << (AICURL*)handle << ") = " << ret);
return ret;
}
void debug_curl_easy_reset(CURL* handle)
{
curl_easy_reset(handle);
Dout(dc::curl, "curl_easy_reset(" << (AICURL*)handle << ")");
}
CURLcode debug_curl_easy_setopt(CURL* handle, CURLoption option, ...)
{
CURLcode ret;
va_list ap;
union param_type {
long along;
void* ptr;
curl_off_t offset;
} param;
va_start(ap, option);
param.ptr = va_arg(ap, void*);
va_end(ap);
ret = curl_easy_setopt(handle, option, param.ptr);
switch ((option / 10000) * 10000)
{
case CURLOPTTYPE_LONG:
Dout(dc::curl, "curl_easy_setopt(" << (AICURL*)handle << ", " << option << ", " << param.along << "L) = " << ret);
break;
case CURLOPTTYPE_OBJECTPOINT:
Dout(dc::curl, "curl_easy_setopt(" << (AICURL*)handle << ", " << option << ", (object*)0x" << std::hex << (size_t)param.ptr << std::dec << ") = " << ret);
break;
case CURLOPTTYPE_FUNCTIONPOINT:
Dout(dc::curl, "curl_easy_setopt(" << (AICURL*)handle << ", " << option << ", (function*)0x" << std::hex << (size_t)param.ptr << std::dec << ") = " << ret);
break;
case CURLOPTTYPE_OFF_T:
Dout(dc::curl, "curl_easy_setopt(" << (AICURL*)handle << ", " << option << ", (curl_off_t)" << param.offset << ") = " << ret);
break;
}
return ret;
}
char const* debug_curl_easy_strerror(CURLcode errornum)
{
char const* ret;
ret = curl_easy_strerror(errornum);
Dout(dc::curl, "curl_easy_strerror(" << errornum << ") = \"" << ret << '"');
return ret;
}
char* debug_curl_easy_unescape(CURL* curl, char* url, int inlength, int* outlength)
{
char* ret;
ret = curl_easy_unescape(curl, url, inlength, outlength);
Dout(dc::curl, "curl_easy_unescape(" << curl << ", \"" << url << "\", " << inlength << ", " << ((ret && outlength) ? *outlength : 1) << ") = \"" << ret << '"');
return ret;
}
void debug_curl_free(char* ptr)
{
curl_free(ptr);
Dout(dc::curl, "curl_free(0x" << std::hex << (size_t)ptr << std::dec << ")");
}
time_t debug_curl_getdate(char const* datestring, time_t* now)
{
time_t ret;
ret = curl_getdate(datestring, now);
Dout(dc::curl, "curl_getdate(\"" << datestring << "\", " << (now == NULL ? "NULL" : "<erroneous non-NULL value for 'now'>") << ") = " << ret);
return ret;
}
void debug_curl_global_cleanup(void)
{
curl_global_cleanup();
Dout(dc::curl, "curl_global_cleanup()");
}
CURLcode debug_curl_global_init(long flags)
{
CURLcode ret;
ret = curl_global_init(flags);
Dout(dc::curl, "curl_global_init(0x" << std::hex << flags << std::dec << ") = " << ret);
return ret;
}
CURLMcode debug_curl_multi_add_handle(CURLM* multi_handle, CURL* easy_handle)
{
CURLMcode ret;
ret = curl_multi_add_handle(multi_handle, easy_handle);
Dout(dc::curl, "curl_multi_add_handle(" << (AICURLM*)multi_handle << ", " << (AICURL*)easy_handle << ") = " << ret);
return ret;
}
CURLMcode debug_curl_multi_assign(CURLM* multi_handle, curl_socket_t sockfd, void* sockptr)
{
CURLMcode ret;
ret = curl_multi_assign(multi_handle, sockfd, sockptr);
Dout(dc::curl, "curl_multi_assign(" << (AICURLM*)multi_handle << ", " << sockfd << ", " << sockptr << ") = " << ret);
return ret;
}
CURLMcode debug_curl_multi_cleanup(CURLM* multi_handle)
{
CURLMcode ret;
ret = curl_multi_cleanup(multi_handle);
Dout(dc::curl, "curl_multi_cleanup(" << (AICURLM*)multi_handle << ") = " << ret);
return ret;
}
CURLMsg* debug_curl_multi_info_read(CURLM* multi_handle, int* msgs_in_queue)
{
CURLMsg* ret;
ret = curl_multi_info_read(multi_handle, msgs_in_queue);
Dout(dc::curl, "curl_multi_info_read(" << (AICURLM*)multi_handle << ", {" << *msgs_in_queue << "}) = " << ret);
return ret;
}
CURLM* debug_curl_multi_init(void)
{
CURLM* ret;
ret = curl_multi_init();
Dout(dc::curl, "curl_multi_init() = " << (AICURLM*)ret);
return ret;
}
CURLMcode debug_curl_multi_remove_handle(CURLM* multi_handle, CURL* easy_handle)
{
CURLMcode ret;
ret = curl_multi_remove_handle(multi_handle, easy_handle);
Dout(dc::curl, "curl_multi_remove_handle(" << (AICURLM*)multi_handle << ", " << (AICURL*)easy_handle << ") = " << ret);
return ret;
}
CURLMcode debug_curl_multi_setopt(CURLM* multi_handle, CURLMoption option, ...)
{
CURLMcode ret;
va_list ap;
union param_type {
long along;
void* ptr;
curl_off_t offset;
} param;
va_start(ap, option);
param.ptr = va_arg(ap, void*);
va_end(ap);
ret = curl_multi_setopt(multi_handle, option, param.ptr);
switch ((option / 10000) * 10000)
{
case CURLOPTTYPE_LONG:
Dout(dc::curl, "curl_easy_setopt(" << (AICURLM*)multi_handle << ", " << option << ", " << param.along << "L) = " << ret);
break;
case CURLOPTTYPE_OBJECTPOINT:
Dout(dc::curl, "curl_easy_setopt(" << (AICURLM*)multi_handle << ", " << option << ", (object*)0x" << std::hex << (size_t)param.ptr << std::dec << ") = " << ret);
break;
case CURLOPTTYPE_FUNCTIONPOINT:
Dout(dc::curl, "curl_easy_setopt(" << (AICURLM*)multi_handle << ", " << option << ", (function*)0x" << std::hex << (size_t)param.ptr << std::dec << ") = " << ret);
break;
case CURLOPTTYPE_OFF_T:
Dout(dc::curl, "curl_easy_setopt(" << (AICURLM*)multi_handle << ", " << option << ", (curl_off_t)" << param.offset << ") = " << ret);
break;
}
return ret;
}
CURLMcode debug_curl_multi_socket_action(CURLM* multi_handle, curl_socket_t sockfd, int ev_bitmask, int* running_handles)
{
CURLMcode ret;
ret = curl_multi_socket_action(multi_handle, sockfd, ev_bitmask, running_handles);
Dout(dc::curl, "curl_multi_socket_action(" << (AICURLM*)multi_handle << ", " << sockfd <<
", " << EvBitmask(ev_bitmask) << ", {" << (ret == CURLM_OK ? *running_handles : 0) << "}) = " << ret);
return ret;
}
char const* debug_curl_multi_strerror(CURLMcode errornum)
{
char const* ret;
ret = curl_multi_strerror(errornum);
Dout(dc::curl, "curl_multi_strerror(" << errornum << ") = \"" << ret << '"');
return ret;
}
struct curl_slist* debug_curl_slist_append(struct curl_slist* list, char const* string)
{
struct curl_slist* ret;
ret = curl_slist_append(list, string);
Dout(dc::curl, "curl_slist_append((curl_slist)@0x" << std::hex << (size_t)list << std::dec << ", \"" << string << "\") = " << *ret);
return ret;
}
void debug_curl_slist_free_all(struct curl_slist* list)
{
curl_slist_free_all(list);
Dout(dc::curl, "curl_slist_free_all((curl_slist)@0x" << std::hex << (size_t)list << std::dec << ")");
}
char* debug_curl_unescape(char const* url, int length)
{
char* ret;
ret = curl_unescape(url, length);
Dout(dc::curl, "curl_unescape(\"" << url << "\", " << length << ") = \"" << ret << '"');
return ret;
}
char* debug_curl_version(void)
{
char* ret;
ret = curl_version();
Dout(dc::curl, "curl_version() = \"" << ret << '"');
return ret;
}
}
#else
int debug_libcurl_dummy; // I thought some OS didn't like empty source files.
#endif

View File

@@ -0,0 +1,83 @@
#ifndef DEBUG_LIBCURL
#define DEBUG_LIBCURL
#ifdef DEBUG_CURLIO
#include <curl/curl.h>
#include "debug.h"
extern "C" {
extern CWD_API void debug_curl_easy_cleanup(CURL* handle);
extern CWD_API CURL* debug_curl_easy_duphandle(CURL* handle);
extern CWD_API char* debug_curl_easy_escape(CURL* curl, char* url, int length);
extern CWD_API CURLcode debug_curl_easy_getinfo(CURL* curl, CURLINFO info, ...);
extern CWD_API CURL* debug_curl_easy_init(void);
extern CWD_API CURLcode debug_curl_easy_pause(CURL* handle, int bitmask);
extern CWD_API CURLcode debug_curl_easy_perform(CURL* handle);
extern CWD_API void debug_curl_easy_reset(CURL* handle);
extern CWD_API CURLcode debug_curl_easy_setopt(CURL* handle, CURLoption option, ...);
extern CWD_API char const* debug_curl_easy_strerror(CURLcode errornum);
extern CWD_API char* debug_curl_easy_unescape(CURL* curl, char* url, int inlength, int* outlength);
extern CWD_API void debug_curl_free(char* ptr);
extern CWD_API time_t debug_curl_getdate(char const* datestring, time_t* now);
extern CWD_API void debug_curl_global_cleanup(void);
extern CWD_API CURLcode debug_curl_global_init(long flags);
extern CWD_API CURLMcode debug_curl_multi_add_handle(CURLM* multi_handle, CURL* easy_handle);
extern CWD_API CURLMcode debug_curl_multi_assign(CURLM* multi_handle, curl_socket_t sockfd, void* sockptr);
extern CWD_API CURLMcode debug_curl_multi_cleanup(CURLM* multi_handle);
extern CWD_API CURLMsg* debug_curl_multi_info_read(CURLM* multi_handle, int* msgs_in_queue);
extern CWD_API CURLM* debug_curl_multi_init(void);
extern CWD_API CURLMcode debug_curl_multi_remove_handle(CURLM* multi_handle, CURL* easy_handle);
extern CWD_API CURLMcode debug_curl_multi_setopt(CURLM* multi_handle, CURLMoption option, ...);
extern CWD_API CURLMcode debug_curl_multi_socket_action(CURLM* multi_handle, curl_socket_t sockfd, int ev_bitmask, int* running_handles);
extern CWD_API char const* debug_curl_multi_strerror(CURLMcode errornum);
extern CWD_API struct curl_slist* debug_curl_slist_append(struct curl_slist* list, char const* string);
extern CWD_API void debug_curl_slist_free_all(struct curl_slist* list);
extern CWD_API char* debug_curl_unescape(char const* url, int length);
extern CWD_API char* debug_curl_version(void);
}
#ifndef COMPILING_DEBUG_LIBCURL_CC
#ifdef curl_easy_setopt
#undef curl_easy_setopt
#undef curl_easy_getinfo
#undef curl_multi_setopt
#endif
#define curl_easy_cleanup(handle) debug_curl_easy_cleanup(handle)
#define curl_easy_duphandle(handle) debug_curl_easy_duphandle(handle)
#define curl_easy_escape(curl, url, length) debug_curl_easy_escape(curl, url, length)
#define curl_easy_getinfo(curl, info, param) debug_curl_easy_getinfo(curl, info, param)
#define curl_easy_init() debug_curl_easy_init()
#define curl_easy_pause(handle, bitmask) debug_curl_easy_pause(handle, bitmask)
#define curl_easy_perform(handle) debug_curl_easy_perform(handle)
#define curl_easy_reset(handle) debug_curl_easy_reset(handle)
#define curl_easy_setopt(handle, option, param) debug_curl_easy_setopt(handle, option, param)
#define curl_easy_strerror(errornum) debug_curl_easy_strerror(errornum)
#define curl_easy_unescape(curl, url, inlength, outlength) debug_curl_easy_unescape(curl, url, inlength, outlength)
#define curl_free(ptr) debug_curl_free(ptr)
#define curl_getdate(datestring, now) debug_curl_getdate(datestring, now)
#define curl_global_cleanup() debug_curl_global_cleanup()
#define curl_global_init(flags) debug_curl_global_init(flags)
#define curl_multi_add_handle(multi_handle, easy_handle) debug_curl_multi_add_handle(multi_handle, easy_handle)
#define curl_multi_assign(multi_handle, sockfd, sockptr) debug_curl_multi_assign(multi_handle, sockfd, sockptr)
#define curl_multi_cleanup(multi_handle) debug_curl_multi_cleanup(multi_handle)
#define curl_multi_info_read(multi_handle, msgs_in_queue) debug_curl_multi_info_read(multi_handle, msgs_in_queue)
#define curl_multi_init() debug_curl_multi_init()
#define curl_multi_remove_handle(multi_handle, easy_handle) debug_curl_multi_remove_handle(multi_handle, easy_handle)
#define curl_multi_setopt(multi_handle, option, param) debug_curl_multi_setopt(multi_handle, option, param)
#define curl_multi_socket_action(multi_handle, sockfd, ev_bitmask, running_handles) debug_curl_multi_socket_action(multi_handle, sockfd, ev_bitmask, running_handles)
#define curl_multi_strerror(errornum) debug_curl_multi_strerror(errornum)
#define curl_slist_append(list, string) debug_curl_slist_append(list, string)
#define curl_slist_free_all(list) debug_curl_slist_free_all(list)
#define curl_unescape(url, length) debug_curl_unescape(url, length)
#define curl_version() debug_curl_version()
#endif // !COMPILING_DEBUG_LIBCURL_CC
#endif // DEBUG_CURLIO
#endif // DEBUG_LIBCURL

View File

@@ -250,6 +250,7 @@ set(llcommon_HEADER_FILES
set_source_files_properties(${llcommon_HEADER_FILES}
PROPERTIES HEADER_FILE_ONLY TRUE)
list(APPEND llcommon_SOURCE_FILES ${cwdebug_SOURCE_FILES})
list(APPEND llcommon_SOURCE_FILES ${llcommon_HEADER_FILES})
add_library (llcommon SHARED ${llcommon_SOURCE_FILES})
@@ -262,15 +263,9 @@ target_link_libraries(
${ZLIB_LIBRARIES}
${WINDOWS_LIBRARIES}
${BOOST_REGEX_LIBRARY}
${CWDEBUG_LIBRARIES}
${CORESERVICES_LIBRARY}
)
if (LINUX)
# When linking with llcommon later, we do not want to link with cwdebug.a again.
set_property(TARGET llcommon PROPERTY LINK_INTERFACE_LIBRARIES "-lapr-1 -laprutil-1 -lz")
endif (LINUX)
if (DARWIN)
# Don't embed a full path in the library's install name
set_target_properties(

View File

@@ -37,7 +37,8 @@
#include <stdexcept>
#include <boost/intrusive_ptr.hpp>
#include <boost/utility.hpp>
#include <curl/curl.h> // CURL, CURLM, CURLMcode, CURLoption, curl_*_callback
#include <curl/curl.h> // Needed for files that include this header (also for aicurlprivate.h).
#include "debug_libcurl.h"
// Make sure we don't use this option: it is not thread-safe.
#undef CURLOPT_DNS_USE_GLOBAL_CACHE

View File

@@ -38,7 +38,6 @@
#include "lluri.h"
#include "message.h"
#include <curl/curl.h>
const F32 HTTP_REQUEST_EXPIRY_SECS = 60.0f;

View File

@@ -29,7 +29,6 @@
#include "llproxy.h"
#include <string>
#include <curl/curl.h>
#include "llapr.h"
#include "llcurl.h"

View File

@@ -6,7 +6,6 @@
#ifndef CURL_STATICLIB
#define CURL_STATICLIB 1
#endif
#include <curl/curl.h>
#include <stdtypes.h>
#include <llbufferstream.h>
@@ -15,6 +14,8 @@
#include <llurlrequest.h>
#include <llxmltree.h>
#include <curl/curl.h>
#include "debug_libcurl.h"
// ********************************************************************

View File

@@ -63,7 +63,6 @@
#include "llviewerjoystick.h"
#include "llfloaterjoystick.h"
#include "llares.h"
#include "llcurl.h"
#include "llfloatersnapshot.h"
#include "lltexturestats.h"
#include "llviewerwindow.h"

View File

@@ -49,7 +49,6 @@
#include "llcheckboxctrl.h"
#include "llcommandhandler.h" // for secondlife:///app/login/
#include "llcombobox.h"
#include "llcurl.h"
#include "llviewercontrol.h"
#include "llfloaterabout.h"
#include "llfloatertest.h"

View File

@@ -47,7 +47,6 @@
#include "stringize.h"
// NOTE: MUST include these after otherincludes since queue gets redefined!?!!
#include <curl/curl.h>
#include <xmlrpc-epi/xmlrpc.h>

View File

@@ -34,7 +34,6 @@
#define LLVIEWERASSETSTORAGE_H
#include "llassetstorage.h"
//#include "curl/curl.h"
class LLVFile;

View File

@@ -77,7 +77,6 @@
#include "llviewerregion.h"
#include "llassetuploadresponders.h"
#include "curl/curl.h"
#include "llstreamtools.h"
// [RLVa:KB] - Checked: 2011-09-04 (RLVa-1.4.1a) | Added: RLVa-1.4.1a