Merge branch 'master' of git://github.com/AlericInglewood/SingularityViewer
This commit is contained in:
@@ -4,9 +4,9 @@ include(Prebuilt)
|
||||
set(OpenSSL_FIND_QUIETLY ON)
|
||||
set(OpenSSL_FIND_REQUIRED ON)
|
||||
|
||||
if (STANDALONE)
|
||||
if (STANDALONE OR USE_SYSTEM_OPENSSL)
|
||||
include(FindOpenSSL)
|
||||
else (STANDALONE)
|
||||
else (STANDALONE OR USE_SYSTEM_OPENSSL)
|
||||
use_prebuilt_binary(openSSL)
|
||||
if (WINDOWS)
|
||||
set(OPENSSL_LIBRARIES ssleay32 libeay32)
|
||||
@@ -14,7 +14,7 @@ else (STANDALONE)
|
||||
set(OPENSSL_LIBRARIES ssl)
|
||||
endif (WINDOWS)
|
||||
set(OPENSSL_INCLUDE_DIRS ${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/include)
|
||||
endif (STANDALONE)
|
||||
endif (STANDALONE OR USE_SYSTEM_OPENSSL)
|
||||
|
||||
if (LINUX OR DARWIN)
|
||||
set(CRYPTO_LIBRARIES crypto)
|
||||
|
||||
@@ -236,8 +236,9 @@ void stop_recording_backtraces(void)
|
||||
channel_ct backtrace DDCN("BACKTRACE"); //!< This debug channel is used for backtraces.
|
||||
channel_ct statemachine DDCN("STATEMACHINE"); //!< This debug channel is used for output related to class AIStateMachine.
|
||||
channel_ct caps DDCN("CAPS"); //!< This debug channel is used for output related to Capabilities.
|
||||
channel_ct curl DDCN("CURL"); //!< This debug channel is used for output related to Curl.
|
||||
channel_ct curlio DDCN("CURLIO"); //!< This debug channel is used to print debug output of libcurl.
|
||||
channel_ct curl DDCN("CURL"); //!< This debug channel is used for output related to AICurl.
|
||||
channel_ct curlio DDCN("CURLIO"); //!< This debug channel is used to print debug output of libcurl. This includes all HTTP network traffic.
|
||||
channel_ct curltr DDCN("CURLTR"); //!< This debug channel is used to print libcurl API calls.
|
||||
|
||||
} // namespace dc
|
||||
} // namespace DEBUGCHANNELS
|
||||
|
||||
@@ -207,6 +207,7 @@ extern CWD_API channel_ct statemachine;
|
||||
extern CWD_API channel_ct caps;
|
||||
extern CWD_API channel_ct curl;
|
||||
extern CWD_API channel_ct curlio;
|
||||
extern CWD_API channel_ct curltr;
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -206,6 +206,19 @@ U8* LLImageBase::allocateData(S32 size)
|
||||
// virtual
|
||||
U8* LLImageBase::reallocateData(S32 size)
|
||||
{
|
||||
if (size == -1)
|
||||
{
|
||||
size = mWidth * mHeight * mComponents;
|
||||
if (size <= 0)
|
||||
{
|
||||
llerrs << llformat("LLImageBase::reallocateData called with bad dimensions: %dx%dx%d", mWidth, mHeight, (S32)mComponents) << llendl;
|
||||
}
|
||||
}
|
||||
else if (size <= 0 || (size > 4096 * 4096 * 16 && !mAllowOverSize))
|
||||
{
|
||||
llerrs << "LLImageBase::reallocateData: bad size: " << size << llendl;
|
||||
}
|
||||
|
||||
if(mData && (mDataSize == size))
|
||||
return mData;
|
||||
|
||||
@@ -300,6 +313,32 @@ LLImageRaw::LLImageRaw(U8 *data, U16 width, U16 height, S8 components)
|
||||
++sRawImageCount;
|
||||
}
|
||||
|
||||
LLImageRaw::LLImageRaw(LLImageRaw const* src, U16 width, U16 height, U16 crop_offset, bool crop_vertically) : mCacheEntries(0)
|
||||
{
|
||||
mMemType = LLMemType::MTYPE_IMAGERAW;
|
||||
llassert_always(src);
|
||||
S8 const components = src->getComponents();
|
||||
U8 const* const data = src->getData();
|
||||
if (allocateDataSize(width, height, components))
|
||||
{
|
||||
if (crop_vertically)
|
||||
{
|
||||
llassert_always(width == src->getWidth());
|
||||
memcpy(getData(), data + width * crop_offset * components, width * height * components);
|
||||
}
|
||||
else
|
||||
{
|
||||
llassert_always(height == src->getHeight());
|
||||
U16 const src_width = src->getWidth();
|
||||
for (U16 row = 0; row < height; ++row)
|
||||
{
|
||||
memcpy(getData() + width * row * components, data + (src_width * row + crop_offset) * components, width * components);
|
||||
}
|
||||
}
|
||||
}
|
||||
++sRawImageCount;
|
||||
}
|
||||
|
||||
/*LLImageRaw::LLImageRaw(const std::string& filename, bool j2c_lowest_mip_only)
|
||||
: LLImageBase(), mCacheEntries(0)
|
||||
{
|
||||
@@ -516,7 +555,7 @@ void LLImageRaw::contractToPowerOfTwo(S32 max_dim, BOOL scale_image)
|
||||
scale( new_width, new_height, scale_image );
|
||||
}
|
||||
|
||||
void LLImageRaw::biasedScaleToPowerOfTwo(S32 max_dim)
|
||||
void LLImageRaw::biasedScaleToPowerOfTwo(S32 target_width, S32 target_height, S32 max_dim)
|
||||
{
|
||||
// Strong bias towards rounding down (to save bandwidth)
|
||||
// No bias would mean THRESHOLD == 1.5f;
|
||||
@@ -525,22 +564,22 @@ void LLImageRaw::biasedScaleToPowerOfTwo(S32 max_dim)
|
||||
// Find new sizes
|
||||
S32 larger_w = max_dim; // 2^n >= mWidth
|
||||
S32 smaller_w = max_dim; // 2^(n-1) <= mWidth
|
||||
while( (smaller_w > getWidth()) && (smaller_w > MIN_IMAGE_SIZE) )
|
||||
while( (smaller_w > target_width) && (smaller_w > MIN_IMAGE_SIZE) )
|
||||
{
|
||||
larger_w = smaller_w;
|
||||
smaller_w >>= 1;
|
||||
}
|
||||
S32 new_width = ( (F32)getWidth() / smaller_w > THRESHOLD ) ? larger_w : smaller_w;
|
||||
S32 new_width = ( (F32)target_width / smaller_w > THRESHOLD ) ? larger_w : smaller_w;
|
||||
|
||||
|
||||
S32 larger_h = max_dim; // 2^m >= mHeight
|
||||
S32 smaller_h = max_dim; // 2^(m-1) <= mHeight
|
||||
while( (smaller_h > getHeight()) && (smaller_h > MIN_IMAGE_SIZE) )
|
||||
while( (smaller_h > target_height) && (smaller_h > MIN_IMAGE_SIZE) )
|
||||
{
|
||||
larger_h = smaller_h;
|
||||
smaller_h >>= 1;
|
||||
}
|
||||
S32 new_height = ( (F32)getHeight() / smaller_h > THRESHOLD ) ? larger_h : smaller_h;
|
||||
S32 new_height = ( (F32)target_height / smaller_h > THRESHOLD ) ? larger_h : smaller_h;
|
||||
|
||||
|
||||
scale( new_width, new_height );
|
||||
@@ -943,76 +982,66 @@ BOOL LLImageRaw::scale( S32 new_width, S32 new_height, BOOL scale_image_data )
|
||||
return TRUE; // Nothing to do.
|
||||
}
|
||||
|
||||
// Reallocate the data buffer.
|
||||
U8* old_buffer = NULL;
|
||||
U8* new_buffer;
|
||||
S32 const old_width_bytes = old_width * getComponents();
|
||||
S32 const new_width_bytes = new_width * getComponents();
|
||||
S32 const min_height = llmin(old_height, new_height);
|
||||
S32 const min_width_bytes = llmin(old_width_bytes, new_width_bytes);
|
||||
|
||||
if (scale_image_data)
|
||||
{
|
||||
// Vertical
|
||||
S32 temp_data_size = old_width * new_height * getComponents();
|
||||
llassert_always(temp_data_size > 0);
|
||||
U8* temp_buffer = new (std::nothrow) U8[ temp_data_size ];
|
||||
if (!temp_buffer )
|
||||
if (new_height != old_height)
|
||||
{
|
||||
llerrs << "Out of memory in LLImageRaw::scale()" << llendl;
|
||||
return FALSE;
|
||||
// Resize vertically.
|
||||
old_buffer = LLImageBase::release();
|
||||
new_buffer = allocateDataSize(old_width, new_height, getComponents());
|
||||
for (S32 col = 0; col < old_width; ++col)
|
||||
{
|
||||
copyLineScaled(old_buffer + getComponents() * col, new_buffer + getComponents() * col, old_height, new_height, old_width, old_width);
|
||||
}
|
||||
LLImageBase::deleteData(old_buffer);
|
||||
}
|
||||
for( S32 col = 0; col < old_width; col++ )
|
||||
if (new_width != old_width)
|
||||
{
|
||||
copyLineScaled( getData() + (getComponents() * col), temp_buffer + (getComponents() * col), old_height, new_height, old_width, old_width );
|
||||
// Resize horizontally.
|
||||
old_buffer = LLImageBase::release();
|
||||
new_buffer = allocateDataSize(new_width, new_height, getComponents());
|
||||
for (S32 row = 0; row < new_height; ++row)
|
||||
{
|
||||
copyLineScaled(old_buffer + old_width_bytes * row, new_buffer + new_width_bytes * row, old_width, new_width, 1, 1);
|
||||
}
|
||||
LLImageBase::deleteData(old_buffer);
|
||||
}
|
||||
|
||||
deleteData();
|
||||
|
||||
U8* new_buffer = allocateDataSize(new_width, new_height, getComponents());
|
||||
|
||||
// Horizontal
|
||||
for( S32 row = 0; row < new_height; row++ )
|
||||
{
|
||||
copyLineScaled( temp_buffer + (getComponents() * old_width * row), new_buffer + (getComponents() * new_width * row), old_width, new_width, 1, 1 );
|
||||
}
|
||||
|
||||
// Clean up
|
||||
delete[] temp_buffer;
|
||||
}
|
||||
else
|
||||
{
|
||||
// copy out existing image data
|
||||
S32 temp_data_size = old_width * old_height * getComponents();
|
||||
U8* temp_buffer = new (std::nothrow) U8[ temp_data_size ];
|
||||
if (!temp_buffer)
|
||||
if (new_width == old_width)
|
||||
{
|
||||
llwarns << "Out of memory in LLImageRaw::scale: old (w, h, c) = (" << old_width << ", " << old_height << ", " << (S32)getComponents() <<
|
||||
") ; new (w, h, c) = (" << new_width << ", " << new_height << ", " << (S32)getComponents() << ")" << llendl;
|
||||
|
||||
return FALSE ;
|
||||
setSize(new_width, new_height, getComponents());
|
||||
new_buffer = reallocateData();
|
||||
}
|
||||
memcpy(temp_buffer, getData(), temp_data_size); /* Flawfinder: ignore */
|
||||
|
||||
// allocate new image data, will delete old data
|
||||
U8* new_buffer = allocateDataSize(new_width, new_height, getComponents());
|
||||
|
||||
for( S32 row = 0; row < new_height; row++ )
|
||||
else
|
||||
{
|
||||
if (row < old_height)
|
||||
old_buffer = LLImageBase::release();
|
||||
new_buffer = allocateDataSize(new_width, new_height, getComponents());
|
||||
for (S32 row = 0; row < min_height; ++row)
|
||||
{
|
||||
memcpy(new_buffer + (new_width * row * getComponents()), temp_buffer + (old_width * row * getComponents()), getComponents() * llmin(old_width, new_width)); /* Flawfinder: ignore */
|
||||
if (old_width < new_width)
|
||||
memcpy(new_buffer + row * new_width_bytes, old_buffer + row * old_width_bytes, min_width_bytes);
|
||||
if (new_width_bytes > old_width_bytes)
|
||||
{
|
||||
// pad out rest of row with black
|
||||
memset(new_buffer + (getComponents() * ((new_width * row) + old_width)), 0, getComponents() * (new_width - old_width));
|
||||
// Pad out rest of row with black.
|
||||
memset(new_buffer + new_width_bytes * row + old_width_bytes, 0, new_width_bytes - old_width_bytes);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// pad remaining rows with black
|
||||
memset(new_buffer + (new_width * row * getComponents()), 0, new_width * getComponents());
|
||||
}
|
||||
LLImageBase::deleteData(old_buffer);
|
||||
}
|
||||
if (new_height > old_height)
|
||||
{
|
||||
// Pad remaining rows with black.
|
||||
memset(new_buffer + new_width_bytes * min_height, 0, new_width_bytes * (new_height - old_height));
|
||||
}
|
||||
|
||||
// Clean up
|
||||
delete[] temp_buffer;
|
||||
}
|
||||
|
||||
return TRUE ;
|
||||
}
|
||||
|
||||
|
||||
@@ -114,6 +114,8 @@ public:
|
||||
virtual void deleteData();
|
||||
virtual U8* allocateData(S32 size = -1);
|
||||
virtual U8* reallocateData(S32 size = -1);
|
||||
static void deleteData(U8* data) { FREE_MEM(sPrivatePoolp, data); }
|
||||
U8* release() { U8* data = mData; mData = NULL; mDataSize = 0; return data; } // Same as deleteData(), but returns old data. Call deleteData(old_data) to free it.
|
||||
|
||||
virtual void dump();
|
||||
virtual void sanityCheck();
|
||||
@@ -175,12 +177,13 @@ public:
|
||||
LLImageRaw();
|
||||
LLImageRaw(U16 width, U16 height, S8 components);
|
||||
LLImageRaw(U8 *data, U16 width, U16 height, S8 components);
|
||||
LLImageRaw(LLImageRaw const* src, U16 width, U16 height, U16 crop_offset, bool crop_vertically);
|
||||
// Construct using createFromFile (used by tools)
|
||||
//LLImageRaw(const std::string& filename, bool j2c_lowest_mip_only = false);
|
||||
|
||||
/*virtual*/ void deleteData();
|
||||
/*virtual*/ U8* allocateData(S32 size = -1);
|
||||
/*virtual*/ U8* reallocateData(S32 size);
|
||||
/*virtual*/ U8* reallocateData(S32 size = -1);
|
||||
|
||||
BOOL resize(U16 width, U16 height, S8 components);
|
||||
|
||||
@@ -194,7 +197,8 @@ public:
|
||||
|
||||
void expandToPowerOfTwo(S32 max_dim = MAX_IMAGE_SIZE, BOOL scale_image = TRUE);
|
||||
void contractToPowerOfTwo(S32 max_dim = MAX_IMAGE_SIZE, BOOL scale_image = TRUE);
|
||||
void biasedScaleToPowerOfTwo(S32 max_dim = MAX_IMAGE_SIZE);
|
||||
void biasedScaleToPowerOfTwo(S32 target_width, S32 target_height, S32 max_dim = MAX_IMAGE_SIZE);
|
||||
void biasedScaleToPowerOfTwo(S32 max_dim = MAX_IMAGE_SIZE) { biasedScaleToPowerOfTwo(getWidth(), getHeight(), max_dim); }
|
||||
BOOL scale( S32 new_width, S32 new_height, BOOL scale_image = TRUE );
|
||||
//BOOL scaleDownWithoutBlending( S32 new_width, S32 new_height) ;
|
||||
|
||||
@@ -287,7 +291,7 @@ public:
|
||||
// LLImageBase
|
||||
/*virtual*/ void deleteData();
|
||||
/*virtual*/ U8* allocateData(S32 size = -1);
|
||||
/*virtual*/ U8* reallocateData(S32 size);
|
||||
/*virtual*/ U8* reallocateData(S32 size = -1);
|
||||
|
||||
/*virtual*/ void dump();
|
||||
/*virtual*/ void sanityCheck();
|
||||
|
||||
@@ -545,6 +545,9 @@ void CurlEasyHandle::handle_easy_error(CURLcode code)
|
||||
|
||||
// Throws AICurlNoEasyHandle.
|
||||
CurlEasyHandle::CurlEasyHandle(void) : mActiveMultiHandle(NULL), mErrorBuffer(NULL), mQueuedForRemoval(false)
|
||||
#ifdef DEBUG_CURLIO
|
||||
, mDebug(false)
|
||||
#endif
|
||||
#ifdef SHOW_ASSERT
|
||||
, mRemovedPerCommand(true)
|
||||
#endif
|
||||
@@ -588,6 +591,12 @@ CurlEasyHandle::~CurlEasyHandle()
|
||||
llassert(!mActiveMultiHandle);
|
||||
curl_easy_cleanup(mEasyHandle);
|
||||
Stats::easy_cleanup_calls++;
|
||||
#ifdef DEBUG_CURLIO
|
||||
if (mDebug)
|
||||
{
|
||||
debug_curl_remove_easy(mEasyHandle);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
//static
|
||||
@@ -760,17 +769,17 @@ void CurlEasyRequest::setoptString(CURLoption option, std::string const& value)
|
||||
setopt(option, value.c_str());
|
||||
}
|
||||
|
||||
void CurlEasyRequest::setPost(AIPostFieldPtr const& postdata, U32 size)
|
||||
void CurlEasyRequest::setPost(AIPostFieldPtr const& postdata, U32 size, bool keepalive)
|
||||
{
|
||||
llassert_always(postdata->data());
|
||||
|
||||
DoutCurl("POST size is " << size << " bytes: \"" << libcwd::buf2str(postdata->data(), size) << "\".");
|
||||
setPostField(postdata); // Make sure the data stays around until we don't need it anymore.
|
||||
|
||||
setPost_raw(size, postdata->data());
|
||||
setPost_raw(size, postdata->data(), keepalive);
|
||||
}
|
||||
|
||||
void CurlEasyRequest::setPost_raw(U32 size, char const* data)
|
||||
void CurlEasyRequest::setPost_raw(U32 size, char const* data, bool keepalive)
|
||||
{
|
||||
if (!data)
|
||||
{
|
||||
@@ -780,7 +789,7 @@ void CurlEasyRequest::setPost_raw(U32 size, char const* data)
|
||||
|
||||
// The server never replies with 100-continue, so suppress the "Expect: 100-continue" header that libcurl adds by default.
|
||||
addHeader("Expect:");
|
||||
if (size > 0)
|
||||
if (size > 0 && keepalive)
|
||||
{
|
||||
addHeader("Connection: keep-alive");
|
||||
addHeader("Keep-alive: 300");
|
||||
@@ -1005,6 +1014,8 @@ CURLcode CurlEasyRequest::curlCtxCallback(CURL* curl, void* sslctx, void* parm)
|
||||
options |= SSL_OP_NO_TLSv1_1;
|
||||
}
|
||||
#else
|
||||
// This is expected when you compile against the headers of a version < 1.0.1 and then link at runtime with version >= 1.0.1.
|
||||
// Don't do that.
|
||||
llassert_always(!need_renegotiation_hack);
|
||||
#endif
|
||||
SSL_CTX_set_options(ctx, options);
|
||||
@@ -1225,6 +1236,20 @@ void CurlEasyRequest::removed_from_multi_handle(AICurlEasyRequest_wat& curl_easy
|
||||
mHandleEventsTarget->removed_from_multi_handle(curl_easy_request_w);
|
||||
}
|
||||
|
||||
void CurlEasyRequest::bad_file_descriptor(AICurlEasyRequest_wat& curl_easy_request_w)
|
||||
{
|
||||
if (mHandleEventsTarget)
|
||||
mHandleEventsTarget->bad_file_descriptor(curl_easy_request_w);
|
||||
}
|
||||
|
||||
#ifdef SHOW_ASSERT
|
||||
void CurlEasyRequest::queued_for_removal(AICurlEasyRequest_wat& curl_easy_request_w)
|
||||
{
|
||||
if (mHandleEventsTarget)
|
||||
mHandleEventsTarget->queued_for_removal(curl_easy_request_w);
|
||||
}
|
||||
#endif
|
||||
|
||||
PerHostRequestQueuePtr CurlEasyRequest::getPerHostPtr(void)
|
||||
{
|
||||
if (!mPerHostPtr)
|
||||
@@ -1288,7 +1313,17 @@ void BufferedCurlEasyRequest::timed_out(void)
|
||||
mResponder->finished(CURLE_OK, HTTP_INTERNAL_ERROR, "Request timeout, aborted.", sChannels, mOutput);
|
||||
if (mResponder->needsHeaders())
|
||||
{
|
||||
send_buffer_events_to(NULL); // Revoke buffer events: we sent them to the responder.
|
||||
send_buffer_events_to(NULL); // Revoke buffer events: we send them to the responder.
|
||||
}
|
||||
mResponder = NULL;
|
||||
}
|
||||
|
||||
void BufferedCurlEasyRequest::bad_socket(void)
|
||||
{
|
||||
mResponder->finished(CURLE_OK, HTTP_INTERNAL_ERROR, "File descriptor went bad! Aborted.", sChannels, mOutput);
|
||||
if (mResponder->needsHeaders())
|
||||
{
|
||||
send_buffer_events_to(NULL); // Revoke buffer events: we send them to the responder.
|
||||
}
|
||||
mResponder = NULL;
|
||||
}
|
||||
@@ -1408,3 +1443,16 @@ CurlMultiHandle::~CurlMultiHandle()
|
||||
}
|
||||
|
||||
} // namespace AICurlPrivate
|
||||
|
||||
extern "C" {
|
||||
|
||||
// Keep linker happy.
|
||||
SSL_METHOD *SSLv2_client_method(void)
|
||||
{
|
||||
// Never used.
|
||||
llassert_always(false);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -208,6 +208,10 @@ struct AICurlEasyHandleEvents {
|
||||
virtual void added_to_multi_handle(AICurlEasyRequest_wat& curl_easy_request_w) = 0;
|
||||
virtual void finished(AICurlEasyRequest_wat& curl_easy_request_w) = 0;
|
||||
virtual void removed_from_multi_handle(AICurlEasyRequest_wat& curl_easy_request_w) = 0;
|
||||
virtual void bad_file_descriptor(AICurlEasyRequest_wat& curl_easy_request_w) = 0;
|
||||
#ifdef SHOW_ASSERT
|
||||
virtual void queued_for_removal(AICurlEasyRequest_wat& curl_easy_request_w) = 0;
|
||||
#endif
|
||||
// Avoid compiler warning.
|
||||
virtual ~AICurlEasyHandleEvents() { }
|
||||
};
|
||||
@@ -271,6 +275,11 @@ class AICurlEasyRequest {
|
||||
// Queue a command to remove this request from the multi session (or cancel a queued command to add it).
|
||||
void removeRequest(void);
|
||||
|
||||
#ifdef DEBUG_CURLIO
|
||||
// Turn on/off debug output.
|
||||
void debug(bool debug) { AICurlEasyRequest_wat(*mBufferedCurlEasyRequest)->debug(debug); }
|
||||
#endif
|
||||
|
||||
private:
|
||||
// The actual pointer to the ThreadSafeBufferedCurlEasyRequest instance.
|
||||
AICurlPrivate::BufferedCurlEasyRequestPtr mBufferedCurlEasyRequest;
|
||||
|
||||
@@ -40,7 +40,8 @@ enum curleasyrequeststatemachine_state_type {
|
||||
AICurlEasyRequestStateMachine_timedOut, // This must be smaller than the rest, so they always overrule.
|
||||
AICurlEasyRequestStateMachine_finished,
|
||||
AICurlEasyRequestStateMachine_removed, // The removed states must be largest two, so they are never ignored.
|
||||
AICurlEasyRequestStateMachine_removed_after_finished
|
||||
AICurlEasyRequestStateMachine_removed_after_finished,
|
||||
AICurlEasyRequestStateMachine_bad_file_descriptor
|
||||
};
|
||||
|
||||
char const* AICurlEasyRequestStateMachine::state_str_impl(state_type run_state) const
|
||||
@@ -54,6 +55,7 @@ char const* AICurlEasyRequestStateMachine::state_str_impl(state_type run_state)
|
||||
AI_CASE_RETURN(AICurlEasyRequestStateMachine_finished);
|
||||
AI_CASE_RETURN(AICurlEasyRequestStateMachine_removed);
|
||||
AI_CASE_RETURN(AICurlEasyRequestStateMachine_removed_after_finished);
|
||||
AI_CASE_RETURN(AICurlEasyRequestStateMachine_bad_file_descriptor);
|
||||
}
|
||||
return "UNKNOWN STATE";
|
||||
}
|
||||
@@ -94,6 +96,24 @@ void AICurlEasyRequestStateMachine::removed_from_multi_handle(AICurlEasyRequest_
|
||||
set_state(mFinished ? AICurlEasyRequestStateMachine_removed_after_finished : AICurlEasyRequestStateMachine_removed);
|
||||
}
|
||||
|
||||
// CURL-THREAD
|
||||
void AICurlEasyRequestStateMachine::bad_file_descriptor(AICurlEasyRequest_wat&)
|
||||
{
|
||||
if (!mFinished)
|
||||
{
|
||||
mFinished = true;
|
||||
set_state(AICurlEasyRequestStateMachine_bad_file_descriptor);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef SHOW_ASSERT
|
||||
// CURL-THREAD
|
||||
void AICurlEasyRequestStateMachine::queued_for_removal(AICurlEasyRequest_wat&)
|
||||
{
|
||||
llassert(mFinished || mTimedOut); // See AICurlEasyRequestStateMachine::removed_from_multi_handle
|
||||
}
|
||||
#endif
|
||||
|
||||
void AICurlEasyRequestStateMachine::multiplex_impl(void)
|
||||
{
|
||||
mSetStateLock.lock();
|
||||
@@ -207,6 +227,11 @@ void AICurlEasyRequestStateMachine::multiplex_impl(void)
|
||||
|
||||
break;
|
||||
}
|
||||
case AICurlEasyRequestStateMachine_bad_file_descriptor:
|
||||
{
|
||||
AICurlEasyRequest_wat(*mCurlEasyRequest)->bad_socket();
|
||||
abort();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -81,6 +81,14 @@ class AICurlEasyRequestStateMachine : public AIStateMachine, public AICurlEasyHa
|
||||
// Called after this curl easy handle was removed from a multi handle.
|
||||
/*virtual*/ void removed_from_multi_handle(AICurlEasyRequest_wat&);
|
||||
|
||||
// Called when the curl thread detected that the socket of this handle has become unusable.
|
||||
/*virtual*/ void bad_file_descriptor(AICurlEasyRequest_wat&);
|
||||
|
||||
#ifdef SHOW_ASSERT
|
||||
// Called when a command was added to remove this easy handle.
|
||||
/*virtual*/ void queued_for_removal(AICurlEasyRequest_wat&);
|
||||
#endif
|
||||
|
||||
protected:
|
||||
// AIStateMachine implementations.
|
||||
|
||||
|
||||
@@ -201,12 +201,19 @@ class CurlEasyHandle : public boost::noncopyable, protected AICurlEasyHandleEven
|
||||
// In case it's added after being removed.
|
||||
void add_queued(void) { mQueuedForRemoval = false; }
|
||||
|
||||
#ifdef DEBUG_CURLIO
|
||||
void debug(bool debug) { if (mDebug) debug_curl_remove_easy(mEasyHandle); if (debug) debug_curl_add_easy(mEasyHandle); mDebug = debug; }
|
||||
#endif
|
||||
|
||||
private:
|
||||
CURL* mEasyHandle;
|
||||
CURLM* mActiveMultiHandle;
|
||||
mutable char* mErrorBuffer;
|
||||
AIPostFieldPtr mPostField; // This keeps the POSTFIELD data alive for as long as the easy handle exists.
|
||||
bool mQueuedForRemoval; // Set if the easy handle is (probably) added to the multi handle, but is queued for removal.
|
||||
#ifdef DEBUG_CURLIO
|
||||
bool mDebug;
|
||||
#endif
|
||||
#ifdef SHOW_ASSERT
|
||||
public:
|
||||
bool mRemovedPerCommand; // Set if mActiveMultiHandle was reset as per command from the main thread.
|
||||
@@ -270,11 +277,11 @@ class CurlEasyHandle : public boost::noncopyable, protected AICurlEasyHandleEven
|
||||
// and the CurlEasyRequest destructed.
|
||||
class CurlEasyRequest : public CurlEasyHandle {
|
||||
private:
|
||||
void setPost_raw(U32 size, char const* data);
|
||||
void setPost_raw(U32 size, char const* data, bool keepalive);
|
||||
public:
|
||||
void setPost(U32 size) { setPost_raw(size, NULL); }
|
||||
void setPost(AIPostFieldPtr const& postdata, U32 size);
|
||||
void setPost(char const* data, U32 size) { setPost(new AIPostField(data), size); }
|
||||
void setPost(U32 size, bool keepalive = true) { setPost_raw(size, NULL, keepalive); }
|
||||
void setPost(AIPostFieldPtr const& postdata, U32 size, bool keepalive = true);
|
||||
void setPost(char const* data, U32 size, bool keepalive = true) { setPost(new AIPostField(data), size, keepalive); }
|
||||
void setoptString(CURLoption option, std::string const& value);
|
||||
void addHeader(char const* str);
|
||||
void addHeaders(AIHTTPHeaders const& headers);
|
||||
@@ -413,6 +420,11 @@ class CurlEasyRequest : public CurlEasyHandle {
|
||||
/*virtual*/ void added_to_multi_handle(AICurlEasyRequest_wat& curl_easy_request_w);
|
||||
/*virtual*/ void finished(AICurlEasyRequest_wat& curl_easy_request_w);
|
||||
/*virtual*/ void removed_from_multi_handle(AICurlEasyRequest_wat& curl_easy_request_w);
|
||||
public:
|
||||
/*virtual*/ void bad_file_descriptor(AICurlEasyRequest_wat& curl_easy_request_w);
|
||||
#ifdef SHOW_ASSERT
|
||||
/*virtual*/ void queued_for_removal(AICurlEasyRequest_wat& curl_easy_request_w);
|
||||
#endif
|
||||
};
|
||||
|
||||
// This class adds input/output buffers to the request and hooks up the libcurl callbacks to use those buffers.
|
||||
@@ -431,6 +443,9 @@ class BufferedCurlEasyRequest : public CurlEasyRequest {
|
||||
// Called if libcurl doesn't deliver within AIHTTPTimeoutPolicy::mMaximumTotalDelay seconds.
|
||||
void timed_out(void);
|
||||
|
||||
// Called if the underlaying socket went bad (ie, when accidently closed by a buggy library).
|
||||
void bad_socket(void);
|
||||
|
||||
// Called after removed_from_multi_handle was called.
|
||||
void processOutput(void);
|
||||
|
||||
|
||||
@@ -286,14 +286,36 @@ enum refresh_t {
|
||||
empty_and_complete = complete|empty
|
||||
};
|
||||
|
||||
// A class with info for each socket that is in use by curl.
|
||||
class CurlSocketInfo
|
||||
{
|
||||
public:
|
||||
CurlSocketInfo(MultiHandle& multi_handle, CURL* easy, curl_socket_t s, int action, ThreadSafeBufferedCurlEasyRequest* lockobj);
|
||||
~CurlSocketInfo();
|
||||
|
||||
void set_action(int action);
|
||||
void mark_dead(void) { set_action(CURL_POLL_NONE); mDead = true; }
|
||||
curl_socket_t getSocketFd(void) const { return mSocketFd; }
|
||||
AICurlEasyRequest& getEasyRequest(void) { return mEasyRequest; }
|
||||
|
||||
private:
|
||||
MultiHandle& mMultiHandle;
|
||||
CURL const* mEasy;
|
||||
curl_socket_t mSocketFd;
|
||||
int mAction;
|
||||
bool mDead;
|
||||
AICurlEasyRequest mEasyRequest;
|
||||
LLPointer<HTTPTimeout> mTimeout;
|
||||
};
|
||||
|
||||
class PollSet
|
||||
{
|
||||
public:
|
||||
PollSet(void);
|
||||
|
||||
// Add/remove a filedescriptor to/from mFileDescriptors.
|
||||
void add(curl_socket_t s);
|
||||
void remove(curl_socket_t s);
|
||||
void add(CurlSocketInfo* sp);
|
||||
void remove(CurlSocketInfo* sp);
|
||||
|
||||
// Copy mFileDescriptors to an internal fd_set that is returned by access().
|
||||
// Returns if all fds could be copied (complete) and/or if the resulting fd_set is empty.
|
||||
@@ -307,8 +329,8 @@ class PollSet
|
||||
curl_socket_t get_max_fd(void) const { return mMaxFdSet; }
|
||||
#endif
|
||||
|
||||
// Return true if a filedescriptor is set in mFileDescriptors (used for debugging).
|
||||
bool contains(curl_socket_t s) const;
|
||||
// Return a pointer to the corresponding CurlSocketInfo if a filedescriptor is set in mFileDescriptors, or NULL if s is not set.
|
||||
CurlSocketInfo* contains(curl_socket_t s) const;
|
||||
|
||||
// Return true if a filedescriptor is set in mFdSet.
|
||||
bool is_set(curl_socket_t s) const;
|
||||
@@ -323,7 +345,7 @@ class PollSet
|
||||
void next(void); // Advance to next filedescriptor.
|
||||
|
||||
private:
|
||||
curl_socket_t* mFileDescriptors;
|
||||
CurlSocketInfo** mFileDescriptors;
|
||||
int mNrFds; // The number of filedescriptors in the array.
|
||||
int mNext; // The index of the first file descriptor to start copying, the next call to refresh().
|
||||
|
||||
@@ -332,8 +354,8 @@ class PollSet
|
||||
#if !WINDOWS_CODE
|
||||
curl_socket_t mMaxFd; // The largest filedescriptor in the array, or CURL_SOCKET_BAD when it is empty.
|
||||
curl_socket_t mMaxFdSet; // The largest filedescriptor set in mFdSet by refresh(), or CURL_SOCKET_BAD when it was empty.
|
||||
std::vector<curl_socket_t> mCopiedFileDescriptors; // Filedescriptors copied by refresh to mFdSet.
|
||||
std::vector<curl_socket_t>::iterator mIter; // Index into mCopiedFileDescriptors for next(); loop variable.
|
||||
std::vector<CurlSocketInfo*> mCopiedFileDescriptors; // Filedescriptors copied by refresh to mFdSet.
|
||||
std::vector<CurlSocketInfo*>::iterator mIter; // Index into mCopiedFileDescriptors for next(); loop variable.
|
||||
#else
|
||||
unsigned int mIter; // Index into fd_set::fd_array.
|
||||
#endif
|
||||
@@ -359,7 +381,7 @@ class PollSet
|
||||
static size_t const MAXSIZE = llmax(1024, FD_SETSIZE);
|
||||
|
||||
// Create an empty PollSet.
|
||||
PollSet::PollSet(void) : mFileDescriptors(new curl_socket_t [MAXSIZE]),
|
||||
PollSet::PollSet(void) : mFileDescriptors(new CurlSocketInfo* [MAXSIZE]),
|
||||
mNrFds(0), mNext(0)
|
||||
#if !WINDOWS_CODE
|
||||
, mMaxFd(-1), mMaxFdSet(-1)
|
||||
@@ -369,17 +391,17 @@ PollSet::PollSet(void) : mFileDescriptors(new curl_socket_t [MAXSIZE]),
|
||||
}
|
||||
|
||||
// Add filedescriptor s to the PollSet.
|
||||
void PollSet::add(curl_socket_t s)
|
||||
void PollSet::add(CurlSocketInfo* sp)
|
||||
{
|
||||
llassert_always(mNrFds < (int)MAXSIZE);
|
||||
mFileDescriptors[mNrFds++] = s;
|
||||
mFileDescriptors[mNrFds++] = sp;
|
||||
#if !WINDOWS_CODE
|
||||
mMaxFd = llmax(mMaxFd, s);
|
||||
mMaxFd = llmax(mMaxFd, sp->getSocketFd());
|
||||
#endif
|
||||
}
|
||||
|
||||
// Remove filedescriptor s from the PollSet.
|
||||
void PollSet::remove(curl_socket_t s)
|
||||
void PollSet::remove(CurlSocketInfo* sp)
|
||||
{
|
||||
// The number of open filedescriptors is relatively small,
|
||||
// and on top of that we rather do something CPU intensive
|
||||
@@ -391,15 +413,15 @@ void PollSet::remove(curl_socket_t s)
|
||||
// back, keeping it compact and keeping the filedescriptors
|
||||
// in the same order (which is supposedly their priority).
|
||||
//
|
||||
// The general case is where mFileDescriptors contains s at an index
|
||||
// The general case is where mFileDescriptors contains sp at an index
|
||||
// between 0 and mNrFds:
|
||||
// mNrFds = 6
|
||||
// v
|
||||
// index: 0 1 2 3 4 5
|
||||
// a b c s d e
|
||||
|
||||
// This function should never be called unless s is actually in mFileDescriptors,
|
||||
// as a result of a previous call to PollSet::add().
|
||||
// This function should never be called unless sp is actually in mFileDescriptors,
|
||||
// as a result of a previous call to PollSet::add(sp).
|
||||
llassert(mNrFds > 0);
|
||||
|
||||
// Correct mNrFds for when the descriptor is removed.
|
||||
@@ -409,17 +431,18 @@ void PollSet::remove(curl_socket_t s)
|
||||
// v
|
||||
// index: 0 1 2 3 4 5
|
||||
// a b c s d e
|
||||
curl_socket_t cur = mFileDescriptors[i]; // cur = 'e'
|
||||
curl_socket_t const s = sp->getSocketFd();
|
||||
CurlSocketInfo* cur = mFileDescriptors[i]; // cur = 'e'
|
||||
#if !WINDOWS_CODE
|
||||
curl_socket_t max = -1;
|
||||
#endif
|
||||
while (cur != s)
|
||||
while (cur != sp)
|
||||
{
|
||||
llassert(i > 0);
|
||||
curl_socket_t next = mFileDescriptors[--i]; // next = 'd'
|
||||
CurlSocketInfo* next = mFileDescriptors[--i]; // next = 'd'
|
||||
mFileDescriptors[i] = cur; // Overwrite 'd' with 'e'.
|
||||
#if !WINDOWS_CODE
|
||||
max = llmax(max, cur); // max is the maximum value in 'i' or higher.
|
||||
max = llmax(max, cur->getSocketFd()); // max is the maximum value in 'i' or higher.
|
||||
#endif
|
||||
cur = next; // cur = 'd'
|
||||
// i NrFds = 5
|
||||
@@ -427,21 +450,21 @@ void PollSet::remove(curl_socket_t s)
|
||||
// index: 0 1 2 3 4
|
||||
// a b c s e // cur = 'd'
|
||||
//
|
||||
// Next loop iteration: next = 's', overwrite 's' with 'd', cur = 's'; loop terminates.
|
||||
// Next loop iteration: next = 'sp', overwrite 'sp' with 'd', cur = 'sp'; loop terminates.
|
||||
// i NrFds = 5
|
||||
// v v
|
||||
// index: 0 1 2 3 4
|
||||
// a b c d e // cur = 's'
|
||||
// a b c d e // cur = 'sp'
|
||||
}
|
||||
llassert(cur == s);
|
||||
llassert(cur == sp);
|
||||
// At this point i was decremented once more and points to the element before the old s.
|
||||
// i NrFds = 5
|
||||
// v v
|
||||
// index: 0 1 2 3 4
|
||||
// a b c d e // max = llmax('d', 'e')
|
||||
|
||||
// If mNext pointed to an element before s, it should be left alone. Otherwise, if mNext pointed
|
||||
// to s it must now point to 'd', or if it pointed beyond 's' it must be decremented by 1.
|
||||
// If mNext pointed to an element before sp, it should be left alone. Otherwise, if mNext pointed
|
||||
// to sp it must now point to 'd', or if it pointed beyond 'sp' it must be decremented by 1.
|
||||
if (mNext > i) // i is where s was.
|
||||
--mNext;
|
||||
|
||||
@@ -451,8 +474,8 @@ void PollSet::remove(curl_socket_t s)
|
||||
{
|
||||
while (i > 0)
|
||||
{
|
||||
curl_socket_t next = mFileDescriptors[--i];
|
||||
max = llmax(max, next);
|
||||
CurlSocketInfo* next = mFileDescriptors[--i];
|
||||
max = llmax(max, next->getSocketFd());
|
||||
}
|
||||
mMaxFd = max;
|
||||
llassert(mMaxFd < s);
|
||||
@@ -487,12 +510,12 @@ void PollSet::remove(curl_socket_t s)
|
||||
#endif
|
||||
}
|
||||
|
||||
bool PollSet::contains(curl_socket_t fd) const
|
||||
CurlSocketInfo* PollSet::contains(curl_socket_t fd) const
|
||||
{
|
||||
for (int i = 0; i < mNrFds; ++i)
|
||||
if (mFileDescriptors[i] == fd)
|
||||
return true;
|
||||
return false;
|
||||
if (mFileDescriptors[i]->getSocketFd() == fd)
|
||||
return mFileDescriptors[i];
|
||||
return NULL;
|
||||
}
|
||||
|
||||
inline bool PollSet::is_set(curl_socket_t fd) const
|
||||
@@ -536,7 +559,7 @@ refresh_t PollSet::refresh(void)
|
||||
// Calculate mMaxFdSet.
|
||||
// Run over FD_SETSIZE - 1 elements, starting at mNext, wrapping to 0 when we reach the end.
|
||||
int max = -1, i = mNext, count = 0;
|
||||
while (++count < FD_SETSIZE) { max = llmax(max, mFileDescriptors[i]); if (++i == mNrFds) i = 0; }
|
||||
while (++count < FD_SETSIZE) { max = llmax(max, mFileDescriptors[i]->getSocketFd()); if (++i == mNrFds) i = 0; }
|
||||
mMaxFdSet = max;
|
||||
#endif
|
||||
}
|
||||
@@ -556,7 +579,7 @@ refresh_t PollSet::refresh(void)
|
||||
mNext = i;
|
||||
return not_complete_not_empty;
|
||||
}
|
||||
FD_SET(mFileDescriptors[i], &mFdSet);
|
||||
FD_SET(mFileDescriptors[i]->getSocketFd(), &mFdSet);
|
||||
#if !WINDOWS_CODE
|
||||
mCopiedFileDescriptors.push_back(mFileDescriptors[i]);
|
||||
#endif
|
||||
@@ -603,7 +626,7 @@ void PollSet::reset(void)
|
||||
else
|
||||
{
|
||||
mIter = mCopiedFileDescriptors.begin();
|
||||
if (!FD_ISSET(*mIter, &mFdSet))
|
||||
if (!FD_ISSET((*mIter)->getSocketFd(), &mFdSet))
|
||||
next();
|
||||
}
|
||||
#endif
|
||||
@@ -614,7 +637,7 @@ inline curl_socket_t PollSet::get(void) const
|
||||
#if WINDOWS_CODE
|
||||
return (mIter >= mFdSet.fd_count) ? CURL_SOCKET_BAD : mFdSet.fd_array[mIter];
|
||||
#else
|
||||
return (mIter == mCopiedFileDescriptors.end()) ? CURL_SOCKET_BAD : *mIter;
|
||||
return (mIter == mCopiedFileDescriptors.end()) ? CURL_SOCKET_BAD : (*mIter)->getSocketFd();
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -625,7 +648,7 @@ void PollSet::next(void)
|
||||
++mIter;
|
||||
#else
|
||||
llassert(mIter != mCopiedFileDescriptors.end()); // Only call next() if the last call to get() didn't return -1.
|
||||
while (++mIter != mCopiedFileDescriptors.end() && !FD_ISSET(*mIter, &mFdSet));
|
||||
while (++mIter != mCopiedFileDescriptors.end() && !FD_ISSET((*mIter)->getSocketFd(), &mFdSet));
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -743,26 +766,8 @@ std::ostream& operator<<(std::ostream& os, DebugFdSet const& s)
|
||||
}
|
||||
#endif
|
||||
|
||||
// A class with info for each socket that is in use by curl.
|
||||
class CurlSocketInfo
|
||||
{
|
||||
public:
|
||||
CurlSocketInfo(MultiHandle& multi_handle, CURL* easy, curl_socket_t s, int action, ThreadSafeBufferedCurlEasyRequest* lockobj);
|
||||
~CurlSocketInfo();
|
||||
|
||||
void set_action(int action);
|
||||
|
||||
private:
|
||||
MultiHandle& mMultiHandle;
|
||||
CURL const* mEasy;
|
||||
curl_socket_t mSocketFd;
|
||||
int mAction;
|
||||
AICurlEasyRequest mEasyRequest;
|
||||
LLPointer<HTTPTimeout> mTimeout;
|
||||
};
|
||||
|
||||
CurlSocketInfo::CurlSocketInfo(MultiHandle& multi_handle, CURL* easy, curl_socket_t s, int action, ThreadSafeBufferedCurlEasyRequest* lockobj) :
|
||||
mMultiHandle(multi_handle), mEasy(easy), mSocketFd(s), mAction(CURL_POLL_NONE), mEasyRequest(lockobj)
|
||||
mMultiHandle(multi_handle), mEasy(easy), mSocketFd(s), mAction(CURL_POLL_NONE), mDead(false), mEasyRequest(lockobj)
|
||||
{
|
||||
llassert(*AICurlEasyRequest_wat(*mEasyRequest) == easy);
|
||||
mMultiHandle.assign(s, this);
|
||||
@@ -785,23 +790,28 @@ CurlSocketInfo::~CurlSocketInfo()
|
||||
|
||||
void CurlSocketInfo::set_action(int action)
|
||||
{
|
||||
if (mDead)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Dout(dc::curl, "CurlSocketInfo::set_action(" << action_str(mAction) << " --> " << action_str(action) << ") [" << (void*)mEasyRequest.get_ptr().get() << "]");
|
||||
int toggle_action = mAction ^ action;
|
||||
mAction = action;
|
||||
if ((toggle_action & CURL_POLL_IN))
|
||||
{
|
||||
if ((action & CURL_POLL_IN))
|
||||
mMultiHandle.mReadPollSet->add(mSocketFd);
|
||||
mMultiHandle.mReadPollSet->add(this);
|
||||
else
|
||||
mMultiHandle.mReadPollSet->remove(mSocketFd);
|
||||
mMultiHandle.mReadPollSet->remove(this);
|
||||
}
|
||||
if ((toggle_action & CURL_POLL_OUT))
|
||||
{
|
||||
if ((action & CURL_POLL_OUT))
|
||||
mMultiHandle.mWritePollSet->add(mSocketFd);
|
||||
mMultiHandle.mWritePollSet->add(this);
|
||||
else
|
||||
{
|
||||
mMultiHandle.mWritePollSet->remove(mSocketFd);
|
||||
mMultiHandle.mWritePollSet->remove(this);
|
||||
|
||||
// The following is a bit of a hack, needed because of the lack of proper timeout callbacks in libcurl.
|
||||
// The removal of CURL_POLL_OUT could be part of the SSL handshake, therefore check if we're already connected:
|
||||
@@ -838,6 +848,9 @@ class AICurlThread : public LLThread
|
||||
// MAIN-THREAD
|
||||
void stop_thread(void) { mRunning = false; wakeup_thread(); }
|
||||
|
||||
// MAIN-THREAD
|
||||
apr_status_t join_thread(void);
|
||||
|
||||
protected:
|
||||
virtual void run(void);
|
||||
void wakeup(AICurlMultiHandle_wat const& multi_handle_w);
|
||||
@@ -1110,6 +1123,17 @@ void AICurlThread::wakeup_thread(void)
|
||||
#endif
|
||||
}
|
||||
|
||||
apr_status_t AICurlThread::join_thread(void)
|
||||
{
|
||||
apr_status_t retval = APR_SUCCESS;
|
||||
if (sInstance)
|
||||
{
|
||||
apr_thread_join(&retval, sInstance->mAPRThreadp);
|
||||
delete sInstance;
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
void AICurlThread::wakeup(AICurlMultiHandle_wat const& multi_handle_w)
|
||||
{
|
||||
DoutEntering(dc::curl, "AICurlThread::wakeup");
|
||||
@@ -1255,6 +1279,26 @@ void AICurlThread::process_commands(AICurlMultiHandle_wat const& multi_handle_w)
|
||||
}
|
||||
}
|
||||
|
||||
// Return true if fd is a 'bad' socket.
|
||||
static bool is_bad(curl_socket_t fd, bool for_writing)
|
||||
{
|
||||
fd_set tmp;
|
||||
FD_ZERO(&tmp);
|
||||
FD_SET(fd, &tmp);
|
||||
fd_set* readfds = for_writing ? NULL : &tmp;
|
||||
fd_set* writefds = for_writing ? &tmp : NULL;
|
||||
#if !WINDOWS_CODE
|
||||
int nfds = fd + 1;
|
||||
#else
|
||||
int nfds = 64;
|
||||
#endif
|
||||
struct timeval timeout;
|
||||
timeout.tv_sec = 0;
|
||||
timeout.tv_usec = 10;
|
||||
int ret = select(nfds, readfds, writefds, NULL, &timeout);
|
||||
return ret == -1;
|
||||
}
|
||||
|
||||
// The main loop of the curl thread.
|
||||
void AICurlThread::run(void)
|
||||
{
|
||||
@@ -1266,7 +1310,7 @@ void AICurlThread::run(void)
|
||||
{
|
||||
// If mRunning is true then we can only get here if mWakeUpFd != CURL_SOCKET_BAD.
|
||||
llassert(mWakeUpFd != CURL_SOCKET_BAD);
|
||||
// Copy the next batch of file descriptors from the PollSets mFiledescriptors into their mFdSet.
|
||||
// Copy the next batch of file descriptors from the PollSets mFileDescriptors into their mFdSet.
|
||||
multi_handle_w->mReadPollSet->refresh();
|
||||
refresh_t wres = multi_handle_w->mWritePollSet->refresh();
|
||||
// Add wake up fd if any, and pass NULL to select() if a set is empty.
|
||||
@@ -1383,6 +1427,51 @@ void AICurlThread::run(void)
|
||||
if (ready == -1)
|
||||
{
|
||||
llwarns << "select() failed: " << errno << ", " << strerror(errno) << llendl;
|
||||
if (errno == EBADF)
|
||||
{
|
||||
// Somewhere (fmodex?) one of our file descriptors was closed. Try to recover by finding out which.
|
||||
llassert_always(!is_bad(mWakeUpFd, false)); // We can't recover from this.
|
||||
PollSet* found = NULL;
|
||||
// Run over all read file descriptors.
|
||||
multi_handle_w->mReadPollSet->refresh();
|
||||
multi_handle_w->mReadPollSet->reset();
|
||||
curl_socket_t fd;
|
||||
while ((fd = multi_handle_w->mReadPollSet->get()) != CURL_SOCKET_BAD)
|
||||
{
|
||||
if (is_bad(fd, false))
|
||||
{
|
||||
found = multi_handle_w->mReadPollSet;
|
||||
break;
|
||||
}
|
||||
multi_handle_w->mReadPollSet->next();
|
||||
}
|
||||
if (!found)
|
||||
{
|
||||
// Try all write file descriptors.
|
||||
refresh_t wres = multi_handle_w->mWritePollSet->refresh();
|
||||
if (!(wres & empty))
|
||||
{
|
||||
multi_handle_w->mWritePollSet->reset();
|
||||
while ((fd = multi_handle_w->mWritePollSet->get()) != CURL_SOCKET_BAD)
|
||||
{
|
||||
if (is_bad(fd, true))
|
||||
{
|
||||
found = multi_handle_w->mWritePollSet;
|
||||
break;
|
||||
}
|
||||
multi_handle_w->mWritePollSet->next();
|
||||
}
|
||||
}
|
||||
}
|
||||
llassert_always(found); // It makes no sense to continue if we can't recover.
|
||||
// Find the corresponding CurlSocketInfo
|
||||
CurlSocketInfo* sp = found->contains(fd);
|
||||
llassert_always(sp); // fd was just *read* from this sp.
|
||||
sp->mark_dead(); // Make sure it's never used again.
|
||||
AICurlEasyRequest_wat curl_easy_request_w(*sp->getEasyRequest());
|
||||
curl_easy_request_w->pause(CURLPAUSE_ALL); // Keep libcurl at bay.
|
||||
curl_easy_request_w->bad_file_descriptor(curl_easy_request_w); // Make the main thread cleanly terminate this transaction.
|
||||
}
|
||||
continue;
|
||||
}
|
||||
// Clock count used for timeouts.
|
||||
@@ -1822,7 +1911,7 @@ bool HTTPTimeout::data_received(size_t n)
|
||||
// | | | | | | | | | | | | | |
|
||||
bool HTTPTimeout::lowspeed(size_t bytes)
|
||||
{
|
||||
DoutCurlEntering("HTTPTimeout::lowspeed(" << bytes << ")");
|
||||
//DoutCurlEntering("HTTPTimeout::lowspeed(" << bytes << ")"); commented out... too spammy for normal use.
|
||||
|
||||
// The algorithm to determine if we timed out if different from how libcurls CURLOPT_LOW_SPEED_TIME works.
|
||||
//
|
||||
@@ -2000,12 +2089,11 @@ void HTTPTimeout::print_diagnostics(CurlEasyRequest const* curl_easy_request, ch
|
||||
#if LOWRESTIMER
|
||||
llinfos << "Hostname seems to have been still in the DNS cache." << llendl;
|
||||
#else
|
||||
llwarns << "Huh? Curl returned CURLE_OPERATION_TIMEDOUT, but DNS lookup did not occur according to timings. Expected CURLE_COULDNT_RESOLVE_PROXY or CURLE_COULDNT_RESOLVE_HOST!" << llendl;
|
||||
llwarns << "Curl returned CURLE_OPERATION_TIMEDOUT and DNS lookup did not occur according to timings. Apparently the resolve attempt timed out (bad network?)" << llendl;
|
||||
llassert(connect_time == 0);
|
||||
llassert(appconnect_time == 0);
|
||||
llassert(pretransfer_time == 0);
|
||||
llassert(starttransfer_time == 0);
|
||||
// Fatal error for diagnostics.
|
||||
return;
|
||||
#endif
|
||||
}
|
||||
@@ -2028,11 +2116,10 @@ void HTTPTimeout::print_diagnostics(CurlEasyRequest const* curl_easy_request, ch
|
||||
#endif
|
||||
)
|
||||
{
|
||||
llwarns << "Huh? Curl returned CURLE_OPERATION_TIMEDOUT, but connection did not occur according to timings. Expected CURLE_COULDNT_CONNECT!" << llendl;
|
||||
llwarns << "Curl returned CURLE_OPERATION_TIMEDOUT and connection did not occur according to timings: apparently the connect attempt timed out (bad network?)" << llendl;
|
||||
llassert(appconnect_time == 0);
|
||||
llassert(pretransfer_time == 0);
|
||||
llassert(starttransfer_time == 0);
|
||||
// Fatal error for diagnostics.
|
||||
return;
|
||||
}
|
||||
// If connect_time is almost equal to namelookup_time, then it was just set because it was already connected.
|
||||
@@ -2148,12 +2235,22 @@ void stopCurlThread(void)
|
||||
if (AICurlThread::sInstance)
|
||||
{
|
||||
AICurlThread::sInstance->stop_thread();
|
||||
int count = 101;
|
||||
int count = 401;
|
||||
while(--count && !AICurlThread::sInstance->isStopped())
|
||||
{
|
||||
ms_sleep(10);
|
||||
}
|
||||
Dout(dc::curl, "Curl thread" << (curlThreadIsRunning() ? " not" : "") << " stopped after " << ((100 - count) * 10) << "ms.");
|
||||
if (AICurlThread::sInstance->isStopped())
|
||||
{
|
||||
// isStopped() returns true somewhere at the end of run(),
|
||||
// but that doesn't mean the thread really stopped: it still
|
||||
// needs to destroy it's static variables.
|
||||
// If we don't join here, then there is a chance that the
|
||||
// curl thread will crash when using globals that we (the
|
||||
// main thread) will have destroyed before it REALLY finished.
|
||||
AICurlThread::sInstance->join_thread(); // Wait till it is REALLY done.
|
||||
}
|
||||
llinfos << "Curl thread" << (curlThreadIsRunning() ? " not" : "") << " stopped after " << ((400 - count) * 10) << "ms." << llendl;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2174,7 +2271,7 @@ void BufferedCurlEasyRequest::setStatusAndReason(U32 status, std::string const&
|
||||
AICurlInterface::Stats::status_count[AICurlInterface::Stats::status2index(mStatus)]++;
|
||||
|
||||
// Sanity check. If the server replies with a redirect status then we better have that option turned on!
|
||||
if ((status >= 300 && status < 400) && mResponder && !mResponder->followRedir())
|
||||
if ((status >= 300 && status < 400) && mResponder && !mResponder->redirect_status_ok())
|
||||
{
|
||||
llerrs << "Received " << status << " (" << reason << ") for responder \"" << mTimeoutPolicy->name() << "\" which has no followRedir()!" << llendl;
|
||||
}
|
||||
@@ -2188,7 +2285,7 @@ void BufferedCurlEasyRequest::processOutput(void)
|
||||
CURLcode code;
|
||||
AITransferInfo info;
|
||||
getResult(&code, &info);
|
||||
if (code == CURLE_OK)
|
||||
if (code == CURLE_OK && mStatus != HTTP_INTERNAL_ERROR)
|
||||
{
|
||||
getinfo(CURLINFO_RESPONSE_CODE, &responseCode);
|
||||
// If getResult code is CURLE_OK then we should have decoded the first header line ourselves.
|
||||
@@ -2201,7 +2298,7 @@ void BufferedCurlEasyRequest::processOutput(void)
|
||||
else
|
||||
{
|
||||
responseCode = HTTP_INTERNAL_ERROR;
|
||||
responseReason = curl_easy_strerror(code);
|
||||
responseReason = (code == CURLE_OK) ? mReason : std::string(curl_easy_strerror(code));
|
||||
setopt(CURLOPT_FRESH_CONNECT, TRUE);
|
||||
}
|
||||
|
||||
@@ -2367,14 +2464,25 @@ size_t BufferedCurlEasyRequest::curlHeaderCallback(char* data, size_t size, size
|
||||
}
|
||||
|
||||
#if defined(CWDEBUG) || defined(DEBUG_CURLIO)
|
||||
int debug_callback(CURL*, curl_infotype infotype, char* buf, size_t size, void* user_ptr)
|
||||
int debug_callback(CURL* handle, curl_infotype infotype, char* buf, size_t size, void* user_ptr)
|
||||
{
|
||||
BufferedCurlEasyRequest* request = (BufferedCurlEasyRequest*)user_ptr;
|
||||
if (infotype == CURLINFO_HEADER_OUT && size >= 5 && (strncmp(buf, "GET ", 4) == 0 || strncmp(buf, "HEAD ", 5) == 0))
|
||||
{
|
||||
request->mDebugIsHeadOrGetMethod = true;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_CURLIO
|
||||
if (!debug_curl_print_debug(handle))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CWDEBUG
|
||||
using namespace ::libcwd;
|
||||
std::ostringstream marker;
|
||||
marker << (void*)request->get_lockobj();
|
||||
marker << (void*)request->get_lockobj() << ' ';
|
||||
libcw_do.push_marker();
|
||||
libcw_do.marker().assign(marker.str().data(), marker.str().size());
|
||||
if (!debug::channels::dc::curlio.is_on())
|
||||
@@ -2398,8 +2506,6 @@ int debug_callback(CURL*, curl_infotype infotype, char* buf, size_t size, void*
|
||||
break;
|
||||
case CURLINFO_HEADER_OUT:
|
||||
LibcwDoutStream << "H< ";
|
||||
if (size >= 5 && (strncmp(buf, "GET ", 4) == 0 || strncmp(buf, "HEAD ", 5) == 0))
|
||||
request->mDebugIsHeadOrGetMethod = true;
|
||||
break;
|
||||
case CURLINFO_DATA_IN:
|
||||
LibcwDoutStream << "D> ";
|
||||
@@ -2573,6 +2679,14 @@ void AICurlEasyRequest::removeRequest(void)
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
AICurlEasyRequest_wat curl_easy_request_w(*get());
|
||||
// As soon as the lock on the command queue is released, it could be picked up by
|
||||
// the curl thread and executed. At that point it (already) demands that the easy
|
||||
// request either timed out or is finished. So, to avoid race conditions that already
|
||||
// has to be true right now. The call to queued_for_removal() checks this.
|
||||
curl_easy_request_w->queued_for_removal(curl_easy_request_w);
|
||||
}
|
||||
#endif
|
||||
// Add a command to remove this request from the multi session to the command queue.
|
||||
command_queue_w->push_back(Command(*this, cmd_remove));
|
||||
|
||||
@@ -107,6 +107,20 @@ void AIHTTPReceivedHeaders::addHeader(std::string const& key, std::string const&
|
||||
{
|
||||
mContainer = new Container;
|
||||
}
|
||||
else if (equal(key, "set-cookie"))
|
||||
{
|
||||
// If a cookie with this name already exists, replace it.
|
||||
std::string const name = value.substr(0, value.find('='));
|
||||
container_t::iterator const end = mContainer->mKeyValuePairs.end();
|
||||
for (container_t::iterator header = mContainer->mKeyValuePairs.begin(); header != end; ++header)
|
||||
{
|
||||
if (equal(header->first, "set-cookie") && header->second.substr(0, header->second.find('=')) == name)
|
||||
{
|
||||
header->second = value;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
mContainer->mKeyValuePairs.insert(container_t::value_type(key, value));
|
||||
}
|
||||
|
||||
@@ -151,3 +165,20 @@ std::ostream& operator<<(std::ostream& os, AIHTTPReceivedHeaders const& headers)
|
||||
return os;
|
||||
}
|
||||
|
||||
//static
|
||||
bool AIHTTPReceivedHeaders::equal(std::string const& key1, std::string const& key2)
|
||||
{
|
||||
if (key1.length() != key2.length())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
for (std::string::const_iterator i1 = key1.begin(), i2 = key2.begin(); i1 != key1.end(); ++i1, ++i2)
|
||||
{
|
||||
if ((*i1 ^ *i2) & 0xdf != 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -132,6 +132,9 @@ class AIHTTPReceivedHeaders {
|
||||
// Add a header.
|
||||
void addHeader(std::string const& key, std::string const& value);
|
||||
|
||||
// Swap headers with another container.
|
||||
void swap(AIHTTPReceivedHeaders& headers) { LLPointer<Container>::swap(mContainer, headers.mContainer); }
|
||||
|
||||
// Return true if there are no headers associated with this object.
|
||||
bool empty(void) const { return !mContainer || mContainer->mKeyValuePairs.empty(); }
|
||||
|
||||
@@ -147,6 +150,9 @@ class AIHTTPReceivedHeaders {
|
||||
// For debug purposes.
|
||||
friend std::ostream& operator<<(std::ostream& os, AIHTTPReceivedHeaders const& headers);
|
||||
|
||||
// Returns true if the two keys compare equal (ie, "Set-Cookie" == "set-cookie").
|
||||
static bool equal(std::string const& key1, std::string const& key2);
|
||||
|
||||
private:
|
||||
struct Container : public LLThreadSafeRefCount {
|
||||
container_t mKeyValuePairs;
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include <cstdlib>
|
||||
#include <stdarg.h>
|
||||
#include <cstring>
|
||||
#include <algorithm>
|
||||
#include "llpreprocessor.h"
|
||||
#include <curl/curl.h>
|
||||
#define COMPILING_DEBUG_LIBCURL_CC
|
||||
@@ -528,19 +529,66 @@ std::ostream& operator<<(std::ostream& os, EvBitmask const& bitmask)
|
||||
return os;
|
||||
}
|
||||
|
||||
// Set this to limit the curl debug output to specific easy handles.
|
||||
bool gDebugCurlTerse = false;
|
||||
|
||||
namespace {
|
||||
|
||||
std::vector<CURL*> handles;
|
||||
|
||||
inline bool print_debug(CURL* handle)
|
||||
{
|
||||
if (!gDebugCurlTerse)
|
||||
return true;
|
||||
return std::find(handles.begin(), handles.end(), handle) != handles.end();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void debug_curl_add_easy(CURL* handle)
|
||||
{
|
||||
std::vector<CURL*>::iterator iter = std::find(handles.begin(), handles.end(), handle);
|
||||
if (iter == handles.end())
|
||||
{
|
||||
handles.push_back(handle);
|
||||
Dout(dc::warning, "debug_curl_add_easy(" << (void*)handle << "): added");
|
||||
}
|
||||
llassert(print_debug(handle));
|
||||
}
|
||||
|
||||
void debug_curl_remove_easy(CURL* handle)
|
||||
{
|
||||
std::vector<CURL*>::iterator iter = std::find(handles.begin(), handles.end(), handle);
|
||||
if (iter != handles.end())
|
||||
{
|
||||
handles.erase(iter);
|
||||
Dout(dc::warning, "debug_curl_remove_easy(" << (void*)handle << "): removed");
|
||||
}
|
||||
llassert(!print_debug(handle));
|
||||
}
|
||||
|
||||
bool debug_curl_print_debug(CURL* handle)
|
||||
{
|
||||
return print_debug(handle);
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
|
||||
void debug_curl_easy_cleanup(CURL* handle)
|
||||
{
|
||||
curl_easy_cleanup(handle);
|
||||
Dout(dc::curl, "curl_easy_cleanup(" << (AICURL*)handle << ")");
|
||||
if (print_debug(handle))
|
||||
{
|
||||
Dout(dc::curltr, "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);
|
||||
if (!print_debug(handle)) return ret;
|
||||
Dout(dc::curltr, "curl_easy_duphandle(" << (AICURL*)handle << ") = " << (AICURL*)ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -548,11 +596,12 @@ 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(" << (AICURL*)curl << ", \"" << url << "\", " << length << ") = \"" << ret << '"');
|
||||
if (!print_debug(curl)) return ret;
|
||||
Dout(dc::curltr, "curl_easy_escape(" << (AICURL*)curl << ", \"" << url << "\", " << length << ") = \"" << ret << '"');
|
||||
return ret;
|
||||
}
|
||||
|
||||
CURLcode debug_curl_easy_getinfo(CURL* curl, CURLINFO info, ...)
|
||||
CURLcode debug_curl_easy_getinfo(CURL* handle, CURLINFO info, ...)
|
||||
{
|
||||
CURLcode ret;
|
||||
va_list ap;
|
||||
@@ -566,26 +615,27 @@ CURLcode debug_curl_easy_getinfo(CURL* curl, CURLINFO info, ...)
|
||||
va_start(ap, info);
|
||||
param.some_ptr = va_arg(ap, void*);
|
||||
va_end(ap);
|
||||
ret = curl_easy_getinfo(curl, info, param.some_ptr);
|
||||
ret = curl_easy_getinfo(handle, info, param.some_ptr);
|
||||
if (!print_debug(handle)) return ret;
|
||||
if (info == CURLINFO_PRIVATE)
|
||||
{
|
||||
Dout(dc::curl, "curl_easy_getinfo(" << (AICURL*)curl << ", " << info << ", 0x" << std::hex << (size_t)param.some_ptr << std::dec << ") = " << ret);
|
||||
Dout(dc::curltr, "curl_easy_getinfo(" << (AICURL*)handle << ", " << info << ", 0x" << std::hex << (size_t)param.some_ptr << std::dec << ") = " << ret);
|
||||
}
|
||||
else
|
||||
{
|
||||
switch((info & CURLINFO_TYPEMASK))
|
||||
{
|
||||
case CURLINFO_STRING:
|
||||
Dout(dc::curl, "curl_easy_getinfo(" << (AICURL*)curl << ", " << info << ", (char**){ \"" << (ret == CURLE_OK ? *param.char_ptr : " <unchanged> ") << "\" }) = " << ret);
|
||||
Dout(dc::curltr, "curl_easy_getinfo(" << (AICURL*)handle << ", " << info << ", (char**){ \"" << (ret == CURLE_OK ? *param.char_ptr : " <unchanged> ") << "\" }) = " << ret);
|
||||
break;
|
||||
case CURLINFO_LONG:
|
||||
Dout(dc::curl, "curl_easy_getinfo(" << (AICURL*)curl << ", " << info << ", (long*){ " << (ret == CURLE_OK ? *param.long_ptr : 0L) << "L }) = " << ret);
|
||||
Dout(dc::curltr, "curl_easy_getinfo(" << (AICURL*)handle << ", " << info << ", (long*){ " << (ret == CURLE_OK ? *param.long_ptr : 0L) << "L }) = " << ret);
|
||||
break;
|
||||
case CURLINFO_DOUBLE:
|
||||
Dout(dc::curl, "curl_easy_getinfo(" << (AICURL*)curl << ", " << info << ", (double*){" << (ret == CURLE_OK ? *param.double_ptr : 0.) << "}) = " << ret);
|
||||
Dout(dc::curltr, "curl_easy_getinfo(" << (AICURL*)handle << ", " << info << ", (double*){" << (ret == CURLE_OK ? *param.double_ptr : 0.) << "}) = " << ret);
|
||||
break;
|
||||
case CURLINFO_SLIST:
|
||||
Dout(dc::curl, "curl_easy_getinfo(" << (AICURL*)curl << ", " << info << ", (curl_slist**){ " << (ret == CURLE_OK ? **param.curl_slist_ptr : unchanged_slist) << " }) = " << ret);
|
||||
Dout(dc::curltr, "curl_easy_getinfo(" << (AICURL*)handle << ", " << info << ", (curl_slist**){ " << (ret == CURLE_OK ? **param.curl_slist_ptr : unchanged_slist) << " }) = " << ret);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -596,7 +646,8 @@ CURL* debug_curl_easy_init(void)
|
||||
{
|
||||
CURL* ret;
|
||||
ret = curl_easy_init();
|
||||
Dout(dc::curl, "curl_easy_init() = " << (AICURL*)ret);
|
||||
if (gDebugCurlTerse) return ret;
|
||||
Dout(dc::curltr, "curl_easy_init() = " << (AICURL*)ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -604,7 +655,8 @@ 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);
|
||||
if (!print_debug(handle)) return ret;
|
||||
Dout(dc::curltr, "curl_easy_pause(" << (AICURL*)handle << ", 0x" << std::hex << bitmask << std::dec << ") = " << ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -612,19 +664,21 @@ CURLcode debug_curl_easy_perform(CURL* handle)
|
||||
{
|
||||
CURLcode ret;
|
||||
ret = curl_easy_perform(handle);
|
||||
Dout(dc::curl, "curl_easy_perform(" << (AICURL*)handle << ") = " << ret);
|
||||
if (!print_debug(handle)) return ret;
|
||||
Dout(dc::curltr, "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 << ")");
|
||||
if (!print_debug(handle)) return;
|
||||
Dout(dc::curltr, "curl_easy_reset(" << (AICURL*)handle << ")");
|
||||
}
|
||||
|
||||
CURLcode debug_curl_easy_setopt(CURL* handle, CURLoption option, ...)
|
||||
{
|
||||
CURLcode ret = CURLE_UNKNOWN_OPTION; // Suppress compiler warning.
|
||||
CURLcode ret = CURLE_OBSOLETE50; // Suppress compiler warning.
|
||||
va_list ap;
|
||||
union param_type {
|
||||
long along;
|
||||
@@ -656,7 +710,10 @@ CURLcode debug_curl_easy_setopt(CURL* handle, CURLoption option, ...)
|
||||
case CURLOPTTYPE_LONG:
|
||||
{
|
||||
ret = curl_easy_setopt(handle, option, param.along);
|
||||
Dout(dc::curl, "curl_easy_setopt(" << (AICURL*)handle << ", " << option << ", " << param.along << "L) = " << ret);
|
||||
if (print_debug(handle))
|
||||
{
|
||||
Dout(dc::curltr, "curl_easy_setopt(" << (AICURL*)handle << ", " << option << ", " << param.along << "L) = " << ret);
|
||||
}
|
||||
if (option == CURLOPT_POSTFIELDSIZE)
|
||||
{
|
||||
postfieldsize = param.along;
|
||||
@@ -666,7 +723,8 @@ CURLcode debug_curl_easy_setopt(CURL* handle, CURLoption option, ...)
|
||||
case CURLOPTTYPE_OBJECTPOINT:
|
||||
{
|
||||
ret = curl_easy_setopt(handle, option, param.ptr);
|
||||
LibcwDoutScopeBegin(LIBCWD_DEBUGCHANNELS, libcwd::libcw_do, dc::curl)
|
||||
if (!print_debug(handle)) break;
|
||||
LibcwDoutScopeBegin(LIBCWD_DEBUGCHANNELS, libcwd::libcw_do, dc::curltr)
|
||||
LibcwDoutStream << "curl_easy_setopt(" << (AICURL*)handle << ", " << option << ", ";
|
||||
// For a subset of all options that take a char*, print the string passed.
|
||||
if (option == CURLOPT_PROXY || // Set HTTP proxy to use. The parameter should be a char* to a zero terminated string holding the host name or dotted IP address.
|
||||
@@ -717,11 +775,11 @@ CURLcode debug_curl_easy_setopt(CURL* handle, CURLoption option, ...)
|
||||
if (option == CURLOPT_HTTPHEADER && param.ptr)
|
||||
{
|
||||
debug::Indent indent(2);
|
||||
Dout(dc::curl, "HTTP Headers:");
|
||||
Dout(dc::curltr, "HTTP Headers:");
|
||||
struct curl_slist* list = (struct curl_slist*)param.ptr;
|
||||
while (list)
|
||||
{
|
||||
Dout(dc::curl, '"' << list->data << '"');
|
||||
Dout(dc::curltr, '"' << list->data << '"');
|
||||
list = list->next;
|
||||
}
|
||||
}
|
||||
@@ -729,12 +787,18 @@ CURLcode debug_curl_easy_setopt(CURL* handle, CURLoption option, ...)
|
||||
}
|
||||
case CURLOPTTYPE_FUNCTIONPOINT:
|
||||
ret = curl_easy_setopt(handle, option, param.ptr);
|
||||
Dout(dc::curl, "curl_easy_setopt(" << (AICURL*)handle << ", " << option << ", (function*)0x" << std::hex << (size_t)param.ptr << std::dec << ") = " << ret);
|
||||
if (print_debug(handle))
|
||||
{
|
||||
Dout(dc::curltr, "curl_easy_setopt(" << (AICURL*)handle << ", " << option << ", (function*)0x" << std::hex << (size_t)param.ptr << std::dec << ") = " << ret);
|
||||
}
|
||||
break;
|
||||
case CURLOPTTYPE_OFF_T:
|
||||
{
|
||||
ret = curl_easy_setopt(handle, option, param.offset);
|
||||
Dout(dc::curl, "curl_easy_setopt(" << (AICURL*)handle << ", " << option << ", (curl_off_t)" << param.offset << ") = " << ret);
|
||||
if (print_debug(handle))
|
||||
{
|
||||
Dout(dc::curltr, "curl_easy_setopt(" << (AICURL*)handle << ", " << option << ", (curl_off_t)" << param.offset << ") = " << ret);
|
||||
}
|
||||
if (option == CURLOPT_POSTFIELDSIZE_LARGE)
|
||||
{
|
||||
postfieldsize = (long)param.offset;
|
||||
@@ -751,7 +815,8 @@ char const* debug_curl_easy_strerror(CURLcode errornum)
|
||||
{
|
||||
char const* ret;
|
||||
ret = curl_easy_strerror(errornum);
|
||||
Dout(dc::curl, "curl_easy_strerror(" << errornum << ") = \"" << ret << '"');
|
||||
if (gDebugCurlTerse) return ret;
|
||||
Dout(dc::curltr, "curl_easy_strerror(" << errornum << ") = \"" << ret << '"');
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -759,35 +824,38 @@ char* debug_curl_easy_unescape(CURL* curl, char* url, int inlength, int* outleng
|
||||
{
|
||||
char* ret;
|
||||
ret = curl_easy_unescape(curl, url, inlength, outlength);
|
||||
Dout(dc::curl, "curl_easy_unescape(" << (AICURL*)curl << ", \"" << url << "\", " << inlength << ", " << ((ret && outlength) ? *outlength : 1) << ") = \"" << ret << '"');
|
||||
if (!print_debug(curl)) return ret;
|
||||
Dout(dc::curltr, "curl_easy_unescape(" << (AICURL*)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 << ")");
|
||||
if (gDebugCurlTerse) return;
|
||||
Dout(dc::curltr, "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);
|
||||
if (gDebugCurlTerse) return ret;
|
||||
Dout(dc::curltr, "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()");
|
||||
Dout(dc::curltr, "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);
|
||||
Dout(dc::curltr, "curl_global_init(0x" << std::hex << flags << std::dec << ") = " << ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -795,7 +863,8 @@ 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);
|
||||
if (gDebugCurlTerse) return ret;
|
||||
Dout(dc::curltr, "curl_multi_add_handle(" << (AICURLM*)multi_handle << ", " << (AICURL*)easy_handle << ") = " << ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -803,7 +872,8 @@ CURLMcode debug_curl_multi_assign(CURLM* multi_handle, curl_socket_t sockfd, voi
|
||||
{
|
||||
CURLMcode ret;
|
||||
ret = curl_multi_assign(multi_handle, sockfd, sockptr);
|
||||
Dout(dc::curl, "curl_multi_assign(" << (AICURLM*)multi_handle << ", " << Socket(sockfd) << ", " << sockptr << ") = " << ret);
|
||||
if (gDebugCurlTerse) return ret;
|
||||
Dout(dc::curltr, "curl_multi_assign(" << (AICURLM*)multi_handle << ", " << Socket(sockfd) << ", " << sockptr << ") = " << ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -811,7 +881,8 @@ 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);
|
||||
if (gDebugCurlTerse) return ret;
|
||||
Dout(dc::curltr, "curl_multi_cleanup(" << (AICURLM*)multi_handle << ") = " << ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -819,7 +890,8 @@ 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);
|
||||
if (gDebugCurlTerse) return ret;
|
||||
Dout(dc::curltr, "curl_multi_info_read(" << (AICURLM*)multi_handle << ", {" << *msgs_in_queue << "}) = " << ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -827,7 +899,8 @@ CURLM* debug_curl_multi_init(void)
|
||||
{
|
||||
CURLM* ret;
|
||||
ret = curl_multi_init();
|
||||
Dout(dc::curl, "curl_multi_init() = " << (AICURLM*)ret);
|
||||
if (gDebugCurlTerse) return ret;
|
||||
Dout(dc::curltr, "curl_multi_init() = " << (AICURLM*)ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -835,7 +908,8 @@ 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);
|
||||
if (!print_debug(easy_handle)) return ret;
|
||||
Dout(dc::curltr, "curl_multi_remove_handle(" << (AICURLM*)multi_handle << ", " << (AICURL*)easy_handle << ") = " << ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -871,19 +945,23 @@ CURLMcode debug_curl_multi_setopt(CURLM* multi_handle, CURLMoption option, ...)
|
||||
{
|
||||
case CURLOPTTYPE_LONG:
|
||||
ret = curl_multi_setopt(multi_handle, option, param.along);
|
||||
Dout(dc::curl, "curl_easy_setopt(" << (AICURLM*)multi_handle << ", " << option << ", " << param.along << "L) = " << ret);
|
||||
if (gDebugCurlTerse) break;
|
||||
Dout(dc::curltr, "curl_easy_setopt(" << (AICURLM*)multi_handle << ", " << option << ", " << param.along << "L) = " << ret);
|
||||
break;
|
||||
case CURLOPTTYPE_OBJECTPOINT:
|
||||
ret = curl_multi_setopt(multi_handle, option, param.ptr);
|
||||
Dout(dc::curl, "curl_easy_setopt(" << (AICURLM*)multi_handle << ", " << option << ", (object*)0x" << std::hex << (size_t)param.ptr << std::dec << ") = " << ret);
|
||||
if (gDebugCurlTerse) break;
|
||||
Dout(dc::curltr, "curl_easy_setopt(" << (AICURLM*)multi_handle << ", " << option << ", (object*)0x" << std::hex << (size_t)param.ptr << std::dec << ") = " << ret);
|
||||
break;
|
||||
case CURLOPTTYPE_FUNCTIONPOINT:
|
||||
ret = curl_multi_setopt(multi_handle, option, param.ptr);
|
||||
Dout(dc::curl, "curl_easy_setopt(" << (AICURLM*)multi_handle << ", " << option << ", (function*)0x" << std::hex << (size_t)param.ptr << std::dec << ") = " << ret);
|
||||
if (gDebugCurlTerse) break;
|
||||
Dout(dc::curltr, "curl_easy_setopt(" << (AICURLM*)multi_handle << ", " << option << ", (function*)0x" << std::hex << (size_t)param.ptr << std::dec << ") = " << ret);
|
||||
break;
|
||||
case CURLOPTTYPE_OFF_T:
|
||||
ret = curl_multi_setopt(multi_handle, option, param.offset);
|
||||
Dout(dc::curl, "curl_easy_setopt(" << (AICURLM*)multi_handle << ", " << option << ", (curl_off_t)" << param.offset << ") = " << ret);
|
||||
if (gDebugCurlTerse) break;
|
||||
Dout(dc::curltr, "curl_easy_setopt(" << (AICURLM*)multi_handle << ", " << option << ", (curl_off_t)" << param.offset << ") = " << ret);
|
||||
break;
|
||||
default: // Stop compiler complaining about no default.
|
||||
break;
|
||||
@@ -895,7 +973,8 @@ CURLMcode debug_curl_multi_socket_action(CURLM* multi_handle, curl_socket_t sock
|
||||
{
|
||||
CURLMcode ret;
|
||||
ret = curl_multi_socket_action(multi_handle, sockfd, ev_bitmask, running_handles);
|
||||
Dout(dc::curl, "curl_multi_socket_action(" << (AICURLM*)multi_handle << ", " << Socket(sockfd) <<
|
||||
if (gDebugCurlTerse) return ret;
|
||||
Dout(dc::curltr, "curl_multi_socket_action(" << (AICURLM*)multi_handle << ", " << Socket(sockfd) <<
|
||||
", " << EvBitmask(ev_bitmask) << ", {" << (ret == CURLM_OK ? *running_handles : 0) << "}) = " << ret);
|
||||
return ret;
|
||||
}
|
||||
@@ -904,7 +983,8 @@ char const* debug_curl_multi_strerror(CURLMcode errornum)
|
||||
{
|
||||
char const* ret;
|
||||
ret = curl_multi_strerror(errornum);
|
||||
Dout(dc::curl, "curl_multi_strerror(" << errornum << ") = \"" << ret << '"');
|
||||
if (gDebugCurlTerse) return ret;
|
||||
Dout(dc::curltr, "curl_multi_strerror(" << errornum << ") = \"" << ret << '"');
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -912,21 +992,24 @@ struct curl_slist* debug_curl_slist_append(struct curl_slist* list, char const*
|
||||
{
|
||||
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);
|
||||
if (gDebugCurlTerse) return ret;
|
||||
Dout(dc::curltr, "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 << ")");
|
||||
if (gDebugCurlTerse) return;
|
||||
Dout(dc::curltr, "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 << '"');
|
||||
if (gDebugCurlTerse) return ret;
|
||||
Dout(dc::curltr, "curl_unescape(\"" << url << "\", " << length << ") = \"" << ret << '"');
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -934,7 +1017,8 @@ char* debug_curl_version(void)
|
||||
{
|
||||
char* ret;
|
||||
ret = curl_version();
|
||||
Dout(dc::curl, "curl_version() = \"" << ret << '"');
|
||||
if (gDebugCurlTerse) return ret;
|
||||
Dout(dc::curltr, "curl_version() = \"" << ret << '"');
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -86,4 +86,9 @@ extern char* debug_curl_version(void);
|
||||
|
||||
#endif // !COMPILING_DEBUG_LIBCURL_CC
|
||||
|
||||
extern bool gDebugCurlTerse; // With this set,
|
||||
void debug_curl_add_easy(CURL* handle); // only output debug output for easy handles added with this function.
|
||||
void debug_curl_remove_easy(CURL* handle);
|
||||
bool debug_curl_print_debug(CURL* handle);
|
||||
|
||||
#endif // DEBUG_LIBCURL
|
||||
|
||||
@@ -200,7 +200,9 @@ static void request(
|
||||
LLURLRequest::ERequestAction method,
|
||||
Injector* body_injector,
|
||||
LLHTTPClient::ResponderPtr responder,
|
||||
AIHTTPHeaders& headers,
|
||||
AIHTTPHeaders& headers/*,*/
|
||||
DEBUG_CURLIO_PARAM(EDebugCurl debug),
|
||||
EKeepAlive keepalive = keep_alive,
|
||||
bool is_auth = false,
|
||||
bool no_compression = false)
|
||||
{
|
||||
@@ -213,7 +215,10 @@ static void request(
|
||||
LLURLRequest* req;
|
||||
try
|
||||
{
|
||||
req = new LLURLRequest(method, url, body_injector, responder, headers, is_auth, no_compression);
|
||||
req = new LLURLRequest(method, url, body_injector, responder, headers, keepalive, is_auth, no_compression);
|
||||
#ifdef DEBUG_CURLIO
|
||||
req->mCurlEasyRequest.debug(debug);
|
||||
#endif
|
||||
}
|
||||
catch(AICurlNoEasyHandle& error)
|
||||
{
|
||||
@@ -225,36 +230,36 @@ static void request(
|
||||
req->run();
|
||||
}
|
||||
|
||||
void LLHTTPClient::getByteRange(std::string const& url, S32 offset, S32 bytes, ResponderPtr responder, AIHTTPHeaders& headers)
|
||||
void LLHTTPClient::getByteRange(std::string const& url, S32 offset, S32 bytes, ResponderPtr responder, AIHTTPHeaders& headers/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug))
|
||||
{
|
||||
if(offset > 0 || bytes > 0)
|
||||
{
|
||||
headers.addHeader("Range", llformat("bytes=%d-%d", offset, offset + bytes - 1));
|
||||
}
|
||||
request(url, LLURLRequest::HTTP_GET, NULL, responder, headers);
|
||||
request(url, LLURLRequest::HTTP_GET, NULL, responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug));
|
||||
}
|
||||
|
||||
void LLHTTPClient::head(std::string const& url, ResponderHeadersOnly* responder, AIHTTPHeaders& headers)
|
||||
void LLHTTPClient::head(std::string const& url, ResponderHeadersOnly* responder, AIHTTPHeaders& headers/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug))
|
||||
{
|
||||
request(url, LLURLRequest::HTTP_HEAD, NULL, responder, headers);
|
||||
request(url, LLURLRequest::HTTP_HEAD, NULL, responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug));
|
||||
}
|
||||
|
||||
void LLHTTPClient::get(std::string const& url, ResponderPtr responder, AIHTTPHeaders& headers)
|
||||
void LLHTTPClient::get(std::string const& url, ResponderPtr responder, AIHTTPHeaders& headers/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug))
|
||||
{
|
||||
request(url, LLURLRequest::HTTP_GET, NULL, responder, headers);
|
||||
request(url, LLURLRequest::HTTP_GET, NULL, responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug));
|
||||
}
|
||||
|
||||
void LLHTTPClient::getHeaderOnly(std::string const& url, ResponderHeadersOnly* responder, AIHTTPHeaders& headers)
|
||||
void LLHTTPClient::getHeaderOnly(std::string const& url, ResponderHeadersOnly* responder, AIHTTPHeaders& headers/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug))
|
||||
{
|
||||
request(url, LLURLRequest::HTTP_HEAD, NULL, responder, headers);
|
||||
request(url, LLURLRequest::HTTP_HEAD, NULL, responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug));
|
||||
}
|
||||
|
||||
void LLHTTPClient::get(std::string const& url, LLSD const& query, ResponderPtr responder, AIHTTPHeaders& headers)
|
||||
void LLHTTPClient::get(std::string const& url, LLSD const& query, ResponderPtr responder, AIHTTPHeaders& headers/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug))
|
||||
{
|
||||
LLURI uri;
|
||||
|
||||
uri = LLURI::buildHTTP(url, LLSD::emptyArray(), query);
|
||||
get(uri.asString(), responder, headers);
|
||||
get(uri.asString(), responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug));
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
@@ -362,6 +367,22 @@ void LLHTTPClient::ResponderBase::decode_raw_body(U32 status, std::string const&
|
||||
}
|
||||
}
|
||||
|
||||
std::string const& LLHTTPClient::ResponderBase::get_cookie(std::string const& key)
|
||||
{
|
||||
AIHTTPReceivedHeaders::range_type cookies;
|
||||
mReceivedHeaders.getValues("set-cookie", cookies);
|
||||
for (AIHTTPReceivedHeaders::iterator_type cookie = cookies.first; cookie != cookies.second; ++cookie)
|
||||
{
|
||||
if (key == cookie->second.substr(0, cookie->second.find('=')))
|
||||
{
|
||||
return cookie->second;
|
||||
}
|
||||
}
|
||||
// Not found.
|
||||
static std::string empty_dummy;
|
||||
return empty_dummy;
|
||||
}
|
||||
|
||||
// Called with HTML body.
|
||||
// virtual
|
||||
void LLHTTPClient::ResponderWithCompleted::completedRaw(U32 status, std::string const& reason, LLChannelDescriptors const& channels, buffer_ptr_t const& buffer)
|
||||
@@ -554,7 +575,8 @@ enum EBlockingRequestAction {
|
||||
static LLSD blocking_request(
|
||||
std::string const& url,
|
||||
EBlockingRequestAction method,
|
||||
LLSD const& body) // Only used for HTTP_LLSD_POST
|
||||
LLSD const& body/*,*/ // Only used for HTTP_LLSD_POST
|
||||
DEBUG_CURLIO_PARAM(EDebugCurl debug))
|
||||
{
|
||||
lldebugs << "blockingRequest of " << url << llendl;
|
||||
|
||||
@@ -563,17 +585,17 @@ static LLSD blocking_request(
|
||||
if (method == HTTP_LLSD_POST)
|
||||
{
|
||||
responder = new BlockingLLSDPostResponder;
|
||||
LLHTTPClient::post(url, body, responder, headers);
|
||||
LLHTTPClient::post(url, body, responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug));
|
||||
}
|
||||
else if (method == HTTP_LLSD_GET)
|
||||
{
|
||||
responder = new BlockingLLSDGetResponder;
|
||||
LLHTTPClient::get(url, responder, headers);
|
||||
LLHTTPClient::get(url, responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug));
|
||||
}
|
||||
else // method == HTTP_RAW_GET
|
||||
{
|
||||
responder = new BlockingRawGetResponder;
|
||||
LLHTTPClient::get(url, responder, headers);
|
||||
LLHTTPClient::get(url, responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug));
|
||||
}
|
||||
|
||||
responder->wait();
|
||||
@@ -635,39 +657,39 @@ static LLSD blocking_request(
|
||||
return response;
|
||||
}
|
||||
|
||||
LLSD LLHTTPClient::blockingPost(const std::string& url, const LLSD& body)
|
||||
LLSD LLHTTPClient::blockingPost(const std::string& url, const LLSD& body/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug))
|
||||
{
|
||||
return blocking_request(url, HTTP_LLSD_POST, body);
|
||||
return blocking_request(url, HTTP_LLSD_POST, body/*,*/ DEBUG_CURLIO_PARAM(debug));
|
||||
}
|
||||
|
||||
LLSD LLHTTPClient::blockingGet(const std::string& url)
|
||||
LLSD LLHTTPClient::blockingGet(const std::string& url/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug))
|
||||
{
|
||||
return blocking_request(url, HTTP_LLSD_GET, LLSD());
|
||||
return blocking_request(url, HTTP_LLSD_GET, LLSD()/*,*/ DEBUG_CURLIO_PARAM(debug));
|
||||
}
|
||||
|
||||
U32 LLHTTPClient::blockingGetRaw(const std::string& url, std::string& body)
|
||||
U32 LLHTTPClient::blockingGetRaw(const std::string& url, std::string& body/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug))
|
||||
{
|
||||
LLSD result = blocking_request(url, HTTP_RAW_GET, LLSD());
|
||||
LLSD result = blocking_request(url, HTTP_RAW_GET, LLSD()/*,*/ DEBUG_CURLIO_PARAM(debug));
|
||||
body = result["body"].asString();
|
||||
return result["status"].asInteger();
|
||||
}
|
||||
|
||||
void LLHTTPClient::put(std::string const& url, LLSD const& body, ResponderPtr responder, AIHTTPHeaders& headers)
|
||||
void LLHTTPClient::put(std::string const& url, LLSD const& body, ResponderPtr responder, AIHTTPHeaders& headers/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug))
|
||||
{
|
||||
request(url, LLURLRequest::HTTP_PUT, new LLSDInjector(body), responder, headers);
|
||||
request(url, LLURLRequest::HTTP_PUT, new LLSDInjector(body), responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug));
|
||||
}
|
||||
|
||||
void LLHTTPClient::post(std::string const& url, LLSD const& body, ResponderPtr responder, AIHTTPHeaders& headers)
|
||||
void LLHTTPClient::post(std::string const& url, LLSD const& body, ResponderPtr responder, AIHTTPHeaders& headers/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug), EKeepAlive keepalive)
|
||||
{
|
||||
request(url, LLURLRequest::HTTP_POST, new LLSDInjector(body), responder, headers);
|
||||
request(url, LLURLRequest::HTTP_POST, new LLSDInjector(body), responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug), keepalive);
|
||||
}
|
||||
|
||||
void LLHTTPClient::postXMLRPC(std::string const& url, XMLRPC_REQUEST xmlrpc_request, ResponderPtr responder, AIHTTPHeaders& headers)
|
||||
void LLHTTPClient::postXMLRPC(std::string const& url, XMLRPC_REQUEST xmlrpc_request, ResponderPtr responder, AIHTTPHeaders& headers/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug), EKeepAlive keepalive)
|
||||
{
|
||||
request(url, LLURLRequest::HTTP_POST, new XMLRPCInjector(xmlrpc_request), responder, headers, true, false); // Does use compression.
|
||||
request(url, LLURLRequest::HTTP_POST, new XMLRPCInjector(xmlrpc_request), responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug), keepalive, true, false); // Does use compression.
|
||||
}
|
||||
|
||||
void LLHTTPClient::postXMLRPC(std::string const& url, char const* method, XMLRPC_VALUE value, ResponderPtr responder, AIHTTPHeaders& headers)
|
||||
void LLHTTPClient::postXMLRPC(std::string const& url, char const* method, XMLRPC_VALUE value, ResponderPtr responder, AIHTTPHeaders& headers/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug), EKeepAlive keepalive)
|
||||
{
|
||||
XMLRPC_REQUEST xmlrpc_request = XMLRPC_RequestNew();
|
||||
XMLRPC_RequestSetMethodName(xmlrpc_request, method);
|
||||
@@ -675,33 +697,33 @@ void LLHTTPClient::postXMLRPC(std::string const& url, char const* method, XMLRPC
|
||||
XMLRPC_RequestSetData(xmlrpc_request, value);
|
||||
// XMLRPCInjector takes ownership of xmlrpc_request and will free it when done.
|
||||
// LLURLRequest takes ownership of the XMLRPCInjector object and will free it when done.
|
||||
request(url, LLURLRequest::HTTP_POST, new XMLRPCInjector(xmlrpc_request), responder, headers, true, true); // Does not use compression.
|
||||
request(url, LLURLRequest::HTTP_POST, new XMLRPCInjector(xmlrpc_request), responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug), keepalive, true, true); // Does not use compression.
|
||||
}
|
||||
|
||||
void LLHTTPClient::postRaw(std::string const& url, char const* data, S32 size, ResponderPtr responder, AIHTTPHeaders& headers)
|
||||
void LLHTTPClient::postRaw(std::string const& url, char const* data, S32 size, ResponderPtr responder, AIHTTPHeaders& headers/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug), EKeepAlive keepalive)
|
||||
{
|
||||
request(url, LLURLRequest::HTTP_POST, new RawInjector(data, size), responder, headers);
|
||||
request(url, LLURLRequest::HTTP_POST, new RawInjector(data, size), responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug), keepalive);
|
||||
}
|
||||
|
||||
void LLHTTPClient::postFile(std::string const& url, std::string const& filename, ResponderPtr responder, AIHTTPHeaders& headers)
|
||||
void LLHTTPClient::postFile(std::string const& url, std::string const& filename, ResponderPtr responder, AIHTTPHeaders& headers/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug), EKeepAlive keepalive)
|
||||
{
|
||||
request(url, LLURLRequest::HTTP_POST, new FileInjector(filename), responder, headers);
|
||||
request(url, LLURLRequest::HTTP_POST, new FileInjector(filename), responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug), keepalive);
|
||||
}
|
||||
|
||||
void LLHTTPClient::postFile(std::string const& url, LLUUID const& uuid, LLAssetType::EType asset_type, ResponderPtr responder, AIHTTPHeaders& headers)
|
||||
void LLHTTPClient::postFile(std::string const& url, LLUUID const& uuid, LLAssetType::EType asset_type, ResponderPtr responder, AIHTTPHeaders& headers/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug), EKeepAlive keepalive)
|
||||
{
|
||||
request(url, LLURLRequest::HTTP_POST, new VFileInjector(uuid, asset_type), responder, headers);
|
||||
request(url, LLURLRequest::HTTP_POST, new VFileInjector(uuid, asset_type), responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug), keepalive);
|
||||
}
|
||||
|
||||
// static
|
||||
void LLHTTPClient::del(std::string const& url, ResponderPtr responder, AIHTTPHeaders& headers)
|
||||
void LLHTTPClient::del(std::string const& url, ResponderPtr responder, AIHTTPHeaders& headers/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug))
|
||||
{
|
||||
request(url, LLURLRequest::HTTP_DELETE, NULL, responder, headers);
|
||||
request(url, LLURLRequest::HTTP_DELETE, NULL, responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug));
|
||||
}
|
||||
|
||||
// static
|
||||
void LLHTTPClient::move(std::string const& url, std::string const& destination, ResponderPtr responder, AIHTTPHeaders& headers)
|
||||
void LLHTTPClient::move(std::string const& url, std::string const& destination, ResponderPtr responder, AIHTTPHeaders& headers/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug))
|
||||
{
|
||||
headers.addHeader("Destination", destination);
|
||||
request(url, LLURLRequest::HTTP_MOVE, NULL, responder, headers);
|
||||
request(url, LLURLRequest::HTTP_MOVE, NULL, responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug));
|
||||
}
|
||||
|
||||
@@ -66,6 +66,21 @@ struct AIBufferedCurlEasyRequestEvents {
|
||||
virtual void completed_headers(U32 status, std::string const& reason, AITransferInfo* info) = 0; // Transaction completed.
|
||||
};
|
||||
|
||||
enum EKeepAlive {
|
||||
no_keep_alive = 0,
|
||||
keep_alive
|
||||
};
|
||||
|
||||
#ifdef DEBUG_CURLIO
|
||||
enum EDebugCurl {
|
||||
debug_off = 0,
|
||||
debug_on
|
||||
};
|
||||
#define DEBUG_CURLIO_PARAM(p) ,p
|
||||
#else
|
||||
#define DEBUG_CURLIO_PARAM(p)
|
||||
#endif
|
||||
|
||||
class LLHTTPClient {
|
||||
public:
|
||||
|
||||
@@ -140,7 +155,16 @@ public:
|
||||
{
|
||||
// It's possible that this page was moved (302), so we already saw headers
|
||||
// from the 302 page and are starting over on the new page now.
|
||||
mReceivedHeaders.clear();
|
||||
// Erase all headers EXCEPT the cookies.
|
||||
AIHTTPReceivedHeaders set_cookie_headers;
|
||||
AIHTTPReceivedHeaders::range_type cookies;
|
||||
mReceivedHeaders.getValues("set-cookie", cookies);
|
||||
for (AIHTTPReceivedHeaders::iterator_type cookie = cookies.first; cookie != cookies.second; ++cookie)
|
||||
{
|
||||
set_cookie_headers.addHeader(cookie->first, cookie->second);
|
||||
}
|
||||
// Replace headers with just the cookie headers.
|
||||
mReceivedHeaders.swap(set_cookie_headers);
|
||||
}
|
||||
|
||||
// Called for all remaining headers.
|
||||
@@ -155,6 +179,9 @@ public:
|
||||
completedHeaders(status, reason, mReceivedHeaders);
|
||||
}
|
||||
|
||||
// Extract cookie 'key' from mReceivedHeaders and return the string 'key=value', or an empty string if key does not exists.
|
||||
std::string const& get_cookie(std::string const& key);
|
||||
|
||||
public:
|
||||
// Derived classes that implement completed_headers()/completedHeaders() should return true here.
|
||||
virtual bool needsHeaders(void) const { return false; }
|
||||
@@ -163,6 +190,9 @@ public:
|
||||
// The default is not to follow redirections.
|
||||
virtual bool followRedir(void) const { return false; }
|
||||
|
||||
// If this function returns false then we generate an error when a redirect status (300..399) is received.
|
||||
virtual bool redirect_status_ok(void) const { return followRedir(); }
|
||||
|
||||
// Timeout policy to use.
|
||||
virtual AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy(void) const = 0;
|
||||
|
||||
@@ -358,59 +388,59 @@ public:
|
||||
|
||||
/** @name non-blocking API */
|
||||
//@{
|
||||
static void head(std::string const& url, ResponderHeadersOnly* responder, AIHTTPHeaders& headers);
|
||||
static void head(std::string const& url, ResponderHeadersOnly* responder)
|
||||
{ AIHTTPHeaders headers; head(url, responder, headers); }
|
||||
static void head(std::string const& url, ResponderHeadersOnly* responder, AIHTTPHeaders& headers/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off));
|
||||
static void head(std::string const& url, ResponderHeadersOnly* responder/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off))
|
||||
{ AIHTTPHeaders headers; head(url, responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug)); }
|
||||
|
||||
static void getByteRange(std::string const& url, S32 offset, S32 bytes, ResponderPtr responder, AIHTTPHeaders& headers);
|
||||
static void getByteRange(std::string const& url, S32 offset, S32 bytes, ResponderPtr responder)
|
||||
{ AIHTTPHeaders headers; getByteRange(url, offset, bytes, responder, headers); }
|
||||
static void getByteRange(std::string const& url, S32 offset, S32 bytes, ResponderPtr responder, AIHTTPHeaders& headers/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off));
|
||||
static void getByteRange(std::string const& url, S32 offset, S32 bytes, ResponderPtr responder/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off))
|
||||
{ AIHTTPHeaders headers; getByteRange(url, offset, bytes, responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug)); }
|
||||
|
||||
static void get(std::string const& url, ResponderPtr responder, AIHTTPHeaders& headers);
|
||||
static void get(std::string const& url, ResponderPtr responder)
|
||||
{ AIHTTPHeaders headers; get(url, responder, headers); }
|
||||
static void get(std::string const& url, ResponderPtr responder, AIHTTPHeaders& headers/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off));
|
||||
static void get(std::string const& url, ResponderPtr responder/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off))
|
||||
{ AIHTTPHeaders headers; get(url, responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug)); }
|
||||
|
||||
static void get(std::string const& url, LLSD const& query, ResponderPtr responder, AIHTTPHeaders& headers);
|
||||
static void get(std::string const& url, LLSD const& query, ResponderPtr responder)
|
||||
{ AIHTTPHeaders headers; get(url, query, responder, headers); }
|
||||
static void get(std::string const& url, LLSD const& query, ResponderPtr responder, AIHTTPHeaders& headers/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off));
|
||||
static void get(std::string const& url, LLSD const& query, ResponderPtr responder/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off))
|
||||
{ AIHTTPHeaders headers; get(url, query, responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug)); }
|
||||
|
||||
static void put(std::string const& url, LLSD const& body, ResponderPtr responder, AIHTTPHeaders& headers);
|
||||
static void put(std::string const& url, LLSD const& body, ResponderPtr responder)
|
||||
{ AIHTTPHeaders headers; put(url, body, responder, headers); }
|
||||
static void put(std::string const& url, LLSD const& body, ResponderPtr responder, AIHTTPHeaders& headers/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off));
|
||||
static void put(std::string const& url, LLSD const& body, ResponderPtr responder/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off))
|
||||
{ AIHTTPHeaders headers; put(url, body, responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug)); }
|
||||
|
||||
static void getHeaderOnly(std::string const& url, ResponderHeadersOnly* responder, AIHTTPHeaders& headers);
|
||||
static void getHeaderOnly(std::string const& url, ResponderHeadersOnly* responder)
|
||||
{ AIHTTPHeaders headers; getHeaderOnly(url, responder, headers); }
|
||||
static void getHeaderOnly(std::string const& url, ResponderHeadersOnly* responder, AIHTTPHeaders& headers/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off));
|
||||
static void getHeaderOnly(std::string const& url, ResponderHeadersOnly* responder/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off))
|
||||
{ AIHTTPHeaders headers; getHeaderOnly(url, responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug)); }
|
||||
|
||||
static void post(std::string const& url, LLSD const& body, ResponderPtr responder, AIHTTPHeaders& headers);
|
||||
static void post(std::string const& url, LLSD const& body, ResponderPtr responder)
|
||||
{ AIHTTPHeaders headers; post(url, body, responder, headers); }
|
||||
static void post(std::string const& url, LLSD const& body, ResponderPtr responder, AIHTTPHeaders& headers/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off), EKeepAlive keepalive = keep_alive);
|
||||
static void post(std::string const& url, LLSD const& body, ResponderPtr responder/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off), EKeepAlive keepalive = keep_alive)
|
||||
{ AIHTTPHeaders headers; post(url, body, responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug), keepalive); }
|
||||
|
||||
/** Takes ownership of request and deletes it when sent */
|
||||
static void postXMLRPC(std::string const& url, XMLRPC_REQUEST request, ResponderPtr responder, AIHTTPHeaders& headers);
|
||||
static void postXMLRPC(std::string const& url, XMLRPC_REQUEST request, ResponderPtr responder)
|
||||
{ AIHTTPHeaders headers; postXMLRPC(url, request, responder, headers); }
|
||||
static void postXMLRPC(std::string const& url, XMLRPC_REQUEST request, ResponderPtr responder, AIHTTPHeaders& headers/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off), EKeepAlive keepalive = keep_alive);
|
||||
static void postXMLRPC(std::string const& url, XMLRPC_REQUEST request, ResponderPtr responder/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off), EKeepAlive keepalive = keep_alive)
|
||||
{ AIHTTPHeaders headers; postXMLRPC(url, request, responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug), keepalive); }
|
||||
|
||||
static void postXMLRPC(std::string const& url, char const* method, XMLRPC_VALUE value, ResponderPtr responder, AIHTTPHeaders& headers);
|
||||
static void postXMLRPC(std::string const& url, char const* method, XMLRPC_VALUE value, ResponderPtr responder)
|
||||
{ AIHTTPHeaders headers; postXMLRPC(url, method, value, responder, headers); }
|
||||
static void postXMLRPC(std::string const& url, char const* method, XMLRPC_VALUE value, ResponderPtr responder, AIHTTPHeaders& headers/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off), EKeepAlive keepalive = keep_alive);
|
||||
static void postXMLRPC(std::string const& url, char const* method, XMLRPC_VALUE value, ResponderPtr responder/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off), EKeepAlive keepalive = keep_alive)
|
||||
{ AIHTTPHeaders headers; postXMLRPC(url, method, value, responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug), keepalive); }
|
||||
|
||||
/** Takes ownership of data and deletes it when sent */
|
||||
static void postRaw(std::string const& url, const char* data, S32 size, ResponderPtr responder, AIHTTPHeaders& headers);
|
||||
static void postRaw(std::string const& url, const char* data, S32 size, ResponderPtr responder)
|
||||
{ AIHTTPHeaders headers; postRaw(url, data, size, responder, headers); }
|
||||
static void postRaw(std::string const& url, const char* data, S32 size, ResponderPtr responder, AIHTTPHeaders& headers/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off), EKeepAlive keepalive = keep_alive);
|
||||
static void postRaw(std::string const& url, const char* data, S32 size, ResponderPtr responder/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off), EKeepAlive keepalive = keep_alive)
|
||||
{ AIHTTPHeaders headers; postRaw(url, data, size, responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug), keepalive); }
|
||||
|
||||
static void postFile(std::string const& url, std::string const& filename, ResponderPtr responder, AIHTTPHeaders& headers);
|
||||
static void postFile(std::string const& url, std::string const& filename, ResponderPtr responder)
|
||||
{ AIHTTPHeaders headers; postFile(url, filename, responder, headers); }
|
||||
static void postFile(std::string const& url, std::string const& filename, ResponderPtr responder, AIHTTPHeaders& headers/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off), EKeepAlive keepalive = keep_alive);
|
||||
static void postFile(std::string const& url, std::string const& filename, ResponderPtr responder/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off), EKeepAlive keepalive = keep_alive)
|
||||
{ AIHTTPHeaders headers; postFile(url, filename, responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug), keepalive); }
|
||||
|
||||
static void postFile(std::string const& url, const LLUUID& uuid, LLAssetType::EType asset_type, ResponderPtr responder, AIHTTPHeaders& headers);
|
||||
static void postFile(std::string const& url, const LLUUID& uuid, LLAssetType::EType asset_type, ResponderPtr responder)
|
||||
{ AIHTTPHeaders headers; postFile(url, uuid, asset_type, responder, headers); }
|
||||
static void postFile(std::string const& url, const LLUUID& uuid, LLAssetType::EType asset_type, ResponderPtr responder, AIHTTPHeaders& headers/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off), EKeepAlive keepalive = keep_alive);
|
||||
static void postFile(std::string const& url, const LLUUID& uuid, LLAssetType::EType asset_type, ResponderPtr responder/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off), EKeepAlive keepalive = keep_alive)
|
||||
{ AIHTTPHeaders headers; postFile(url, uuid, asset_type, responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug), keepalive); }
|
||||
|
||||
static void del(std::string const& url, ResponderPtr responder, AIHTTPHeaders& headers);
|
||||
static void del(std::string const& url, ResponderPtr responder)
|
||||
{ AIHTTPHeaders headers; del(url, responder, headers); }
|
||||
static void del(std::string const& url, ResponderPtr responder, AIHTTPHeaders& headers/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off));
|
||||
static void del(std::string const& url, ResponderPtr responder/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off))
|
||||
{ AIHTTPHeaders headers; del(url, responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug)); }
|
||||
|
||||
///< sends a DELETE method, but we can't call it delete in c++
|
||||
|
||||
@@ -423,9 +453,9 @@ public:
|
||||
* @param headers A map of key:value headers to pass to the request
|
||||
* @param timeout The number of seconds to give the server to respond.
|
||||
*/
|
||||
static void move(std::string const& url, std::string const& destination, ResponderPtr responder, AIHTTPHeaders& headers);
|
||||
static void move(std::string const& url, std::string const& destination, ResponderPtr responder)
|
||||
{ AIHTTPHeaders headers; move(url, destination, responder, headers); }
|
||||
static void move(std::string const& url, std::string const& destination, ResponderPtr responder, AIHTTPHeaders& headers/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off));
|
||||
static void move(std::string const& url, std::string const& destination, ResponderPtr responder/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off))
|
||||
{ AIHTTPHeaders headers; move(url, destination, responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug)); }
|
||||
|
||||
//@}
|
||||
|
||||
@@ -435,7 +465,7 @@ public:
|
||||
* @param url the complete serialized (and escaped) url to get
|
||||
* @return An LLSD of { 'status':status, 'body':payload }
|
||||
*/
|
||||
static LLSD blockingGet(std::string const& url);
|
||||
static LLSD blockingGet(std::string const& url/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off));
|
||||
|
||||
/**
|
||||
* @brief Blocking HTTP GET that returns the raw body.
|
||||
@@ -444,7 +474,7 @@ public:
|
||||
* @param result the target string to write the body to
|
||||
* @return HTTP status
|
||||
*/
|
||||
static U32 blockingGetRaw(const std::string& url, std::string& result);
|
||||
static U32 blockingGetRaw(const std::string& url, std::string& result/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off));
|
||||
|
||||
/**
|
||||
* @brief Blocking HTTP POST that returns an LLSD map of status and body.
|
||||
@@ -453,7 +483,7 @@ public:
|
||||
* @param body the LLSD post body
|
||||
* @return An LLSD of { 'status':status (an int), 'body':payload (an LLSD) }
|
||||
*/
|
||||
static LLSD blockingPost(std::string const& url, LLSD const& body);
|
||||
static LLSD blockingPost(std::string const& url, LLSD const& body/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off));
|
||||
};
|
||||
|
||||
#endif // LL_LLHTTPCLIENT_H
|
||||
|
||||
@@ -77,8 +77,8 @@ std::string LLURLRequest::actionAsVerb(LLURLRequest::ERequestAction action)
|
||||
|
||||
// This might throw AICurlNoEasyHandle.
|
||||
LLURLRequest::LLURLRequest(LLURLRequest::ERequestAction action, std::string const& url, Injector* body,
|
||||
LLHTTPClient::ResponderPtr responder, AIHTTPHeaders& headers, bool is_auth, bool no_compression) :
|
||||
mAction(action), mURL(url), mIsAuth(is_auth), mNoCompression(no_compression),
|
||||
LLHTTPClient::ResponderPtr responder, AIHTTPHeaders& headers, bool keepalive, bool is_auth, bool no_compression) :
|
||||
mAction(action), mURL(url), mKeepAlive(keepalive), mIsAuth(is_auth), mNoCompression(no_compression),
|
||||
mBody(body), mResponder(responder), mHeaders(headers)
|
||||
{
|
||||
}
|
||||
@@ -226,7 +226,7 @@ bool LLURLRequest::configure(AICurlEasyRequest_wat const& curlEasyRequest_w)
|
||||
case HTTP_POST:
|
||||
{
|
||||
// Set the handle for an http post
|
||||
curlEasyRequest_w->setPost(mBodySize);
|
||||
curlEasyRequest_w->setPost(mBodySize, mKeepAlive);
|
||||
|
||||
// Set Accept-Encoding to allow response compression
|
||||
curlEasyRequest_w->setoptString(CURLOPT_ENCODING, mNoCompression ? "identity" : "");
|
||||
|
||||
@@ -77,7 +77,7 @@ class LLURLRequest : public AICurlEasyRequestStateMachine {
|
||||
* @param action One of the ERequestAction enumerations.
|
||||
* @param url The url of the request. It should already be encoded.
|
||||
*/
|
||||
LLURLRequest(ERequestAction action, std::string const& url, Injector* body, LLHTTPClient::ResponderPtr responder, AIHTTPHeaders& headers, bool is_auth, bool no_compression);
|
||||
LLURLRequest(ERequestAction action, std::string const& url, Injector* body, LLHTTPClient::ResponderPtr responder, AIHTTPHeaders& headers, bool keepalive, bool is_auth, bool no_compression);
|
||||
|
||||
protected:
|
||||
// Call abort(), not delete.
|
||||
@@ -111,6 +111,7 @@ class LLURLRequest : public AICurlEasyRequestStateMachine {
|
||||
private:
|
||||
ERequestAction mAction;
|
||||
std::string mURL;
|
||||
bool mKeepAlive; // Set to false only when explicitely requested.
|
||||
bool mIsAuth; // Set for authentication messages (login, buy land, buy currency).
|
||||
bool mNoCompression; // Set to disable using gzip.
|
||||
Injector* mBody; // Non-zero iff the action is HTTP_POST and HTTP_PUT.
|
||||
|
||||
@@ -201,15 +201,13 @@ void gl_rect_2d(S32 left, S32 top, S32 right, S32 bottom, BOOL filled )
|
||||
gGL.begin( LLRender::LINES );
|
||||
|
||||
// Verticals
|
||||
gGL.vertex2i(left + 1, top);
|
||||
gGL.vertex2i(left + 1, bottom);
|
||||
gGL.vertex2i(left + 1, top + 1);
|
||||
gGL.vertex2i(left + 1, bottom + 1);
|
||||
|
||||
gGL.vertex2i(right, bottom);
|
||||
gGL.vertex2i(right, top);
|
||||
gGL.vertex2i(right + 1, bottom + 1);
|
||||
gGL.vertex2i(right + 1, top + 1);
|
||||
|
||||
// Horizontals
|
||||
top--;
|
||||
right--;
|
||||
gGL.vertex2i(left, bottom);
|
||||
gGL.vertex2i(right, bottom);
|
||||
|
||||
@@ -219,8 +217,6 @@ void gl_rect_2d(S32 left, S32 top, S32 right, S32 bottom, BOOL filled )
|
||||
}
|
||||
else
|
||||
{
|
||||
top--;
|
||||
right--;
|
||||
gGL.begin( LLRender::LINE_STRIP );
|
||||
gGL.vertex2i(left, top);
|
||||
gGL.vertex2i(left, bottom);
|
||||
|
||||
@@ -196,8 +196,9 @@ set(viewer_SOURCE_FILES
|
||||
llfloaterevent.cpp
|
||||
llfloaterexploreanimations.cpp
|
||||
llfloaterexploresounds.cpp
|
||||
llfloaterfriends.cpp
|
||||
llfloaterfeed.cpp
|
||||
llfloaterfonttest.cpp
|
||||
llfloaterfriends.cpp
|
||||
llfloatergesture.cpp
|
||||
llfloatergodtools.cpp
|
||||
llfloatergroupinfo.cpp
|
||||
@@ -704,6 +705,7 @@ set(viewer_HEADER_FILES
|
||||
llfloaterexploreanimations.h
|
||||
llfloaterexploresounds.h
|
||||
llfloaterevent.h
|
||||
llfloaterfeed.h
|
||||
llfloaterfonttest.h
|
||||
llfloaterfriends.h
|
||||
llfloatergesture.h
|
||||
|
||||
@@ -6776,6 +6776,22 @@ This should be as low as possible, but too low may break functionality</string>
|
||||
<integer>0</integer>
|
||||
</array>
|
||||
</map>
|
||||
<key>FloaterOutboxRect</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Rectangle for merchant outbox window</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>Rect</string>
|
||||
<key>Value</key>
|
||||
<array>
|
||||
<integer>0</integer>
|
||||
<integer>342</integer>
|
||||
<integer>310</integer>
|
||||
<integer>52</integer>
|
||||
</array>
|
||||
</map>
|
||||
<key>FloaterPayRectB</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
@@ -6856,6 +6872,38 @@ This should be as low as possible, but too low may break functionality</string>
|
||||
<integer>400</integer>
|
||||
</array>
|
||||
</map>
|
||||
<key>FloaterSnapshotFeedRect</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Rectangle for snapshot feed window</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>Rect</string>
|
||||
<key>Value</key>
|
||||
<array>
|
||||
<integer>0</integer>
|
||||
<integer>200</integer>
|
||||
<integer>200</integer>
|
||||
<integer>400</integer>
|
||||
</array>
|
||||
</map>
|
||||
<key>FloaterSnapshotPostcardRect</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Rectangle for snapshot postcard window</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>Rect</string>
|
||||
<key>Value</key>
|
||||
<array>
|
||||
<integer>0</integer>
|
||||
<integer>346</integer>
|
||||
<integer>450</integer>
|
||||
<integer>400</integer>
|
||||
</array>
|
||||
</map>
|
||||
<key>FloaterSoundsRect</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
@@ -8163,17 +8211,6 @@ This should be as low as possible, but too low may break functionality</string>
|
||||
<key>Value</key>
|
||||
<integer>64</integer>
|
||||
</map>
|
||||
<key>KeepAspectForSnapshot</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Use full window when taking snapshot, regardless of requested image size</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>Boolean</string>
|
||||
<key>Value</key>
|
||||
<integer>1</integer>
|
||||
</map>
|
||||
<key>LandBrushSize</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
@@ -8344,6 +8381,50 @@ This should be as low as possible, but too low may break functionality</string>
|
||||
<key>Value</key>
|
||||
<string>0.0.0</string>
|
||||
</map>
|
||||
<key>LastSnapshotToFeedAspect</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>The aspect ratio spinner value for snapshots uploaded to my.secondlife.com</string>
|
||||
<key>Persist</key>
|
||||
<integer>0</integer>
|
||||
<key>Type</key>
|
||||
<string>F32</string>
|
||||
<key>Value</key>
|
||||
<integer>1.33333</integer>
|
||||
</map>
|
||||
<key>LastSnapshotToFeedHeight</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>The height of the last my.secondlife.com feed snapshot, in px</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>S32</string>
|
||||
<key>Value</key>
|
||||
<integer>525</integer>
|
||||
</map>
|
||||
<key>LastSnapshotToFeedWidth</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>The width of the last my.secondlife.com feed snapshot, in px</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>S32</string>
|
||||
<key>Value</key>
|
||||
<integer>700</integer>
|
||||
</map>
|
||||
<key>LastSnapshotToEmailAspect</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>The aspect ratio spinner value for snapshots sent by email</string>
|
||||
<key>Persist</key>
|
||||
<integer>0</integer>
|
||||
<key>Type</key>
|
||||
<string>F32</string>
|
||||
<key>Value</key>
|
||||
<integer>0</integer>
|
||||
</map>
|
||||
<key>LastSnapshotToEmailHeight</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
@@ -8366,6 +8447,17 @@ This should be as low as possible, but too low may break functionality</string>
|
||||
<key>Value</key>
|
||||
<integer>1024</integer>
|
||||
</map>
|
||||
<key>LastSnapshotToDiskAspect</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>The aspect ratio spinner value for snapshots written to disk</string>
|
||||
<key>Persist</key>
|
||||
<integer>0</integer>
|
||||
<key>Type</key>
|
||||
<string>F32</string>
|
||||
<key>Value</key>
|
||||
<integer>0</integer>
|
||||
</map>
|
||||
<key>LastSnapshotToDiskHeight</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
@@ -8388,6 +8480,17 @@ This should be as low as possible, but too low may break functionality</string>
|
||||
<key>Value</key>
|
||||
<integer>1024</integer>
|
||||
</map>
|
||||
<key>LastSnapshotToInventoryAspect</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>The aspect ratio spinner value for snapshots uploaded to inventory</string>
|
||||
<key>Persist</key>
|
||||
<integer>0</integer>
|
||||
<key>Type</key>
|
||||
<string>F32</string>
|
||||
<key>Value</key>
|
||||
<integer>0</integer>
|
||||
</map>
|
||||
<key>LastSnapshotToInventoryHeight</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
@@ -8421,6 +8524,17 @@ This should be as low as possible, but too low may break functionality</string>
|
||||
<key>Value</key>
|
||||
<integer>0</integer>
|
||||
</map>
|
||||
<key>SnapshotFeedAddLocation</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Include your location in your uploads to profile feed.</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>Boolean</string>
|
||||
<key>Value</key>
|
||||
<integer>0</integer>
|
||||
</map>
|
||||
<key>LeftClickShowMenu</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
@@ -13686,6 +13800,28 @@ This should be as low as possible, but too low may break functionality</string>
|
||||
<key>Value</key>
|
||||
<integer>0</integer>
|
||||
</map>
|
||||
<key>SnapshotFeedLastAspect</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Take next feed snapshot at this aspect</string>
|
||||
<key>Persist</key>
|
||||
<integer>0</integer>
|
||||
<key>Type</key>
|
||||
<string>S32</string>
|
||||
<key>Value</key>
|
||||
<integer>0</integer>
|
||||
</map>
|
||||
<key>SnapshotFeedLastResolution</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Take next feed snapshot at this resolution</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>S32</string>
|
||||
<key>Value</key>
|
||||
<integer>0</integer>
|
||||
</map>
|
||||
<key>SnapshotFormat</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
@@ -13697,6 +13833,28 @@ This should be as low as possible, but too low may break functionality</string>
|
||||
<key>Value</key>
|
||||
<integer>0</integer>
|
||||
</map>
|
||||
<key>SnapshotLayerType</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Save snapshots in this format (0 = Colors, 1 = Depth)</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>S32</string>
|
||||
<key>Value</key>
|
||||
<integer>0</integer>
|
||||
</map>
|
||||
<key>SnapshotLocalLastAspect</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Take next local snapshot at this aspect</string>
|
||||
<key>Persist</key>
|
||||
<integer>0</integer>
|
||||
<key>Type</key>
|
||||
<string>S32</string>
|
||||
<key>Value</key>
|
||||
<integer>0</integer>
|
||||
</map>
|
||||
<key>SnapshotLocalLastResolution</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
@@ -13708,6 +13866,17 @@ This should be as low as possible, but too low may break functionality</string>
|
||||
<key>Value</key>
|
||||
<integer>0</integer>
|
||||
</map>
|
||||
<key>SnapshotPostcardLastAspect</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Take next postcard snapshot at this aspect</string>
|
||||
<key>Persist</key>
|
||||
<integer>0</integer>
|
||||
<key>Type</key>
|
||||
<string>S32</string>
|
||||
<key>Value</key>
|
||||
<integer>0</integer>
|
||||
</map>
|
||||
<key>SnapshotPostcardLastResolution</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
@@ -13730,6 +13899,17 @@ This should be as low as possible, but too low may break functionality</string>
|
||||
<key>Value</key>
|
||||
<integer>75</integer>
|
||||
</map>
|
||||
<key>SnapshotTextureLastAspect</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Take next texture snapshot at this aspect</string>
|
||||
<key>Persist</key>
|
||||
<integer>0</integer>
|
||||
<key>Type</key>
|
||||
<string>S32</string>
|
||||
<key>Value</key>
|
||||
<integer>0</integer>
|
||||
</map>
|
||||
<key>SnapshotTextureLastResolution</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
@@ -13741,6 +13921,17 @@ This should be as low as possible, but too low may break functionality</string>
|
||||
<key>Value</key>
|
||||
<integer>0</integer>
|
||||
</map>
|
||||
<key>SnapshotOpenFreezeTime</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>When opening the snapshot floater, immediately freeze time.</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>Boolean</string>
|
||||
<key>Value</key>
|
||||
<integer>0</integer>
|
||||
</map>
|
||||
<key>SpeakingColor</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
@@ -14453,12 +14644,12 @@ This should be as low as possible, but too low may break functionality</string>
|
||||
<key>Value</key>
|
||||
<integer>0</integer>
|
||||
</map>
|
||||
<key>UseFreezeFrame</key>
|
||||
<key>UseFreezeTime</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Freeze time when taking snapshots.</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<integer>0</integer>
|
||||
<key>Type</key>
|
||||
<string>Boolean</string>
|
||||
<key>Value</key>
|
||||
|
||||
@@ -2514,9 +2514,10 @@ void LLAgentCamera::setFocusObject(LLViewerObject* object)
|
||||
//-----------------------------------------------------------------------------
|
||||
void LLAgentCamera::setFocusGlobal(const LLPickInfo& pick)
|
||||
{
|
||||
static const LLCachedControl<bool> freeze_time("FreezeTime",false);
|
||||
LLViewerObject* objectp = gObjectList.findObject(pick.mObjectID);
|
||||
|
||||
if (objectp)
|
||||
if (objectp && !freeze_time)
|
||||
{
|
||||
// focus on object plus designated offset
|
||||
// which may or may not be same as pick.mPosGlobal
|
||||
|
||||
@@ -237,7 +237,10 @@ void LLDrawPoolWater::render(S32 pass)
|
||||
glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
|
||||
|
||||
// Slowly move over time.
|
||||
F32 offset = fmod(gFrameTimeSeconds*2.f, 100.f);
|
||||
static const LLCachedControl<bool> freeze_time("FreezeTime",false);
|
||||
static F32 frame_time;
|
||||
if (!freeze_time) frame_time = gFrameTimeSeconds;
|
||||
F32 offset = fmod(frame_time*2.f, 100.f);
|
||||
F32 tp0[4] = {16.f/256.f, 0.0f, 0.0f, offset*0.01f};
|
||||
F32 tp1[4] = {0.0f, 16.f/256.f, 0.0f, offset*0.01f};
|
||||
glTexGenfv(GL_S, GL_OBJECT_PLANE, tp0);
|
||||
@@ -418,11 +421,14 @@ void LLDrawPoolWater::renderOpaqueLegacyWater()
|
||||
// Use the fact that we know all water faces are the same size
|
||||
// to save some computation
|
||||
|
||||
// Slowly move texture coordinates over time so the watter appears
|
||||
// Slowly move texture coordinates over time so the water appears
|
||||
// to be moving.
|
||||
F32 movement_period_secs = 50.f;
|
||||
|
||||
F32 offset = fmod(gFrameTimeSeconds, movement_period_secs);
|
||||
static const LLCachedControl<bool> freeze_time("FreezeTime",false);
|
||||
static F32 frame_time;
|
||||
if (!freeze_time) frame_time = gFrameTimeSeconds;
|
||||
F32 offset = fmod(frame_time, movement_period_secs);
|
||||
|
||||
if (movement_period_secs != 0)
|
||||
{
|
||||
@@ -580,7 +586,11 @@ void LLDrawPoolWater::shade()
|
||||
shader->bind();
|
||||
}
|
||||
|
||||
sTime = (F32)LLFrameTimer::getElapsedSeconds()*0.5f;
|
||||
static const LLCachedControl<bool> freeze_time("FreezeTime",false);
|
||||
if (!freeze_time)
|
||||
{
|
||||
sTime = (F32)LLFrameTimer::getElapsedSeconds()*0.5f;
|
||||
}
|
||||
|
||||
S32 reftex = shader->enableTexture(LLViewerShaderMgr::WATER_REFTEX);
|
||||
|
||||
|
||||
@@ -180,7 +180,7 @@ void LLFloaterAuction::onClickSnapshot(void* data)
|
||||
BOOL success = gViewerWindow->rawSnapshot(raw,
|
||||
gViewerWindow->getWindowWidth(),
|
||||
gViewerWindow->getWindowHeight(),
|
||||
TRUE, FALSE,
|
||||
(F32)gViewerWindow->getWindowWidth() / gViewerWindow->getWindowHeight(),
|
||||
FALSE, FALSE);
|
||||
gForceRenderLandFence = FALSE;
|
||||
|
||||
|
||||
177
indra/newview/llfloaterfeed.cpp
Normal file
177
indra/newview/llfloaterfeed.cpp
Normal file
@@ -0,0 +1,177 @@
|
||||
/**
|
||||
* @file llfloaterfeed.cpp
|
||||
* @brief Feed send floater, allows setting caption and whether or to add location, etc.
|
||||
*
|
||||
* $LicenseInfo:firstyear=2012&license=viewergpl$
|
||||
*
|
||||
* Copyright (c) 2004-2009, Linden Research, Inc.
|
||||
* Copyright (c) 2012, Aleric Ingelwood.
|
||||
*
|
||||
* Second Life Viewer Source Code
|
||||
* The source code in this file ("Source Code") is provided by Linden Lab
|
||||
* to you under the terms of the GNU General Public License, version 2.0
|
||||
* ("GPL"), unless you have obtained a separate licensing agreement
|
||||
* ("Other License"), formally executed by you and Linden Lab. Terms of
|
||||
* the GPL can be found in doc/GPL-license.txt in this distribution, or
|
||||
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
|
||||
*
|
||||
* There are special exceptions to the terms and conditions of the GPL as
|
||||
* it is applied to this Source Code. View the full text of the exception
|
||||
* in the file doc/FLOSS-exception.txt in this software distribution, or
|
||||
* online at
|
||||
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
|
||||
*
|
||||
* By copying, modifying or distributing this software, you acknowledge
|
||||
* that you have read and understood your obligations described above,
|
||||
* and agree to abide by those obligations.
|
||||
*
|
||||
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
|
||||
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
|
||||
* COMPLETENESS OR PERFORMANCE.
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#include "llviewerprecompiledheaders.h"
|
||||
|
||||
#include "llfloaterfeed.h"
|
||||
|
||||
#include "llfloatersnapshot.h"
|
||||
#include "llimagepng.h"
|
||||
#include "llnotificationsutil.h"
|
||||
#include "lluictrlfactory.h"
|
||||
#include "llviewertexture.h"
|
||||
#include "llviewerwindow.h"
|
||||
#include "llwebprofile.h"
|
||||
|
||||
#include <boost/bind.hpp>
|
||||
|
||||
///----------------------------------------------------------------------------
|
||||
/// Class LLFloaterFeed
|
||||
///----------------------------------------------------------------------------
|
||||
|
||||
LLFloaterFeed::LLFloaterFeed(LLImagePNG* png, LLViewerTexture* img, LLVector2 const& img_scale, int index) :
|
||||
LLFloater(std::string("Feed Floater")),
|
||||
mPNGImage(png), mViewerImage(img), mImageScale(img_scale), mSnapshotIndex(index)
|
||||
{
|
||||
}
|
||||
|
||||
// Destroys the object
|
||||
LLFloaterFeed::~LLFloaterFeed()
|
||||
{
|
||||
mPNGImage = NULL;
|
||||
}
|
||||
|
||||
BOOL LLFloaterFeed::postBuild()
|
||||
{
|
||||
getChild<LLUICtrl>("cancel_btn")->setCommitCallback(boost::bind(&LLFloaterFeed::onClickCancel, this));
|
||||
getChild<LLUICtrl>("post_btn")->setCommitCallback(boost::bind(&LLFloaterFeed::onClickPost, this));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// static
|
||||
LLFloaterFeed* LLFloaterFeed::showFromSnapshot(LLImagePNG* png, LLViewerTexture* img, LLVector2 const& image_scale, int index)
|
||||
{
|
||||
// Take the images from the caller
|
||||
// It's now our job to clean them up
|
||||
LLFloaterFeed* instance = new LLFloaterFeed(png, img, image_scale, index);
|
||||
|
||||
LLUICtrlFactory::getInstance()->buildFloater(instance, "floater_snapshot_feed.xml");
|
||||
|
||||
S32 left, top;
|
||||
gFloaterView->getNewFloaterPosition(&left, &top);
|
||||
instance->setOrigin(left, top - instance->getRect().getHeight());
|
||||
|
||||
instance->open();
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
void LLFloaterFeed::draw(void)
|
||||
{
|
||||
LLGLSUIDefault gls_ui;
|
||||
LLFloater::draw();
|
||||
|
||||
if (!isMinimized() && mViewerImage.notNull() && mPNGImage.notNull())
|
||||
{
|
||||
LLRect rect(getRect());
|
||||
|
||||
// First set the max extents of our preview.
|
||||
rect.translate(-rect.mLeft, -rect.mBottom);
|
||||
rect.mLeft += 10;
|
||||
rect.mRight -= 10;
|
||||
rect.mTop -= 25;
|
||||
rect.mBottom = rect.mTop - 150;
|
||||
|
||||
// Then fix the aspect ratio.
|
||||
F32 ratio = (F32)mPNGImage->getWidth() / (F32)mPNGImage->getHeight();
|
||||
if ((F32)rect.getWidth() / (F32)rect.getHeight() >= ratio)
|
||||
{
|
||||
rect.mRight = (S32)((F32)rect.mLeft + ((F32)rect.getHeight() * ratio));
|
||||
}
|
||||
else
|
||||
{
|
||||
rect.mBottom = (S32)((F32)rect.mTop - ((F32)rect.getWidth() / ratio));
|
||||
}
|
||||
{
|
||||
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
|
||||
gl_rect_2d(rect, LLColor4(0.f, 0.f, 0.f, 1.f));
|
||||
rect.stretch(-1);
|
||||
}
|
||||
{
|
||||
gGL.matrixMode(LLRender::MM_TEXTURE);
|
||||
gGL.pushMatrix();
|
||||
{
|
||||
gGL.scalef(mImageScale.mV[VX], mImageScale.mV[VY], 1.f);
|
||||
gGL.matrixMode(LLRender::MM_MODELVIEW);
|
||||
gl_draw_scaled_image(rect.mLeft, rect.mBottom, rect.getWidth(), rect.getHeight(), mViewerImage, LLColor4::white);
|
||||
}
|
||||
gGL.matrixMode(LLRender::MM_TEXTURE);
|
||||
gGL.popMatrix();
|
||||
gGL.matrixMode(LLRender::MM_MODELVIEW);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LLFloaterFeed::onClickCancel()
|
||||
{
|
||||
// Return false on cancel, to enable the upload button again.
|
||||
LLFloaterSnapshot::saveFeedDone(false, mSnapshotIndex);
|
||||
close(false);
|
||||
}
|
||||
|
||||
void LLFloaterFeed::onClose(bool app_quitting)
|
||||
{
|
||||
LLFloaterSnapshot::saveFeedDone(false, mSnapshotIndex);
|
||||
destroy();
|
||||
}
|
||||
|
||||
void LLFloaterFeed::onClickPost()
|
||||
{
|
||||
if (mPNGImage.notNull())
|
||||
{
|
||||
static LLCachedControl<bool> add_location("SnapshotFeedAddLocation");
|
||||
const std::string caption = childGetValue("caption").asString();
|
||||
LLWebProfile::setImageUploadResultCallback(boost::bind(&LLFloaterSnapshot::saveFeedDone, _1, mPNGImage));
|
||||
LLWebProfile::uploadImage(mPNGImage, caption, add_location);
|
||||
|
||||
// give user feedback of the event
|
||||
gViewerWindow->playSnapshotAnimAndSound();
|
||||
|
||||
// don't destroy the window until the upload is done
|
||||
// this way we keep the information in the form
|
||||
setVisible(FALSE);
|
||||
|
||||
// remove any dependency on snapshot floater
|
||||
// so we outlive it during the upload.
|
||||
LLFloater* dependee = getDependee();
|
||||
if (dependee)
|
||||
{
|
||||
dependee->removeDependentFloater(this);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LLNotificationsUtil::add("ErrorProcessingSnapshot");
|
||||
}
|
||||
}
|
||||
64
indra/newview/llfloaterfeed.h
Normal file
64
indra/newview/llfloaterfeed.h
Normal file
@@ -0,0 +1,64 @@
|
||||
/**
|
||||
* @file llfloaterfeed.h
|
||||
* @brief Feed send floater, allows setting caption and whether or not to include location.
|
||||
*
|
||||
* Copyright (c) 2004-2009, Linden Research, Inc.
|
||||
* Copyright (c) 2012, Aleric Inglewood.
|
||||
*
|
||||
* Second Life Viewer Source Code
|
||||
* The source code in this file ("Source Code") is provided by Linden Lab
|
||||
* to you under the terms of the GNU General Public License, version 2.0
|
||||
* ("GPL"), unless you have obtained a separate licensing agreement
|
||||
* ("Other License"), formally executed by you and Linden Lab. Terms of
|
||||
* the GPL can be found in doc/GPL-license.txt in this distribution, or
|
||||
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
|
||||
*
|
||||
* There are special exceptions to the terms and conditions of the GPL as
|
||||
* it is applied to this Source Code. View the full text of the exception
|
||||
* in the file doc/FLOSS-exception.txt in this software distribution, or
|
||||
* online at
|
||||
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
|
||||
*
|
||||
* By copying, modifying or distributing this software, you acknowledge
|
||||
* that you have read and understood your obligations described above,
|
||||
* and agree to abide by those obligations.
|
||||
*
|
||||
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
|
||||
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
|
||||
* COMPLETENESS OR PERFORMANCE.
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#ifndef LL_LLFLOATERFEED_H
|
||||
#define LL_LLFLOATERFEED_H
|
||||
|
||||
#include "llfloater.h" // LLFloater
|
||||
#include "v2math.h" // LLVector2
|
||||
#include "llpointer.h" // LLPointer
|
||||
|
||||
class LLImagePNG;
|
||||
class LLViewerTexture;
|
||||
|
||||
class LLFloaterFeed : public LLFloater
|
||||
{
|
||||
public:
|
||||
LLFloaterFeed(LLImagePNG* png, LLViewerTexture* img, LLVector2 const& img_scale, int index);
|
||||
virtual ~LLFloaterFeed();
|
||||
|
||||
/*virtual*/ void onClose(bool app_quitting);
|
||||
/*virtual*/ BOOL postBuild();
|
||||
/*virtual*/ void draw();
|
||||
|
||||
static LLFloaterFeed* showFromSnapshot(LLImagePNG* png, LLViewerTexture* img, LLVector2 const& img_scale, int index);
|
||||
|
||||
void onClickCancel();
|
||||
void onClickPost();
|
||||
|
||||
protected:
|
||||
LLPointer<LLImagePNG> mPNGImage;
|
||||
LLPointer<LLViewerTexture> mViewerImage;
|
||||
LLVector2 const mImageScale;
|
||||
int mSnapshotIndex;
|
||||
};
|
||||
|
||||
#endif // LL_LLFLOATERFEED_H
|
||||
@@ -67,6 +67,7 @@
|
||||
#include "llassetuploadresponders.h"
|
||||
|
||||
#include "hippogridmanager.h"
|
||||
#include "llfloatersnapshot.h"
|
||||
|
||||
#if LL_MSVC
|
||||
#pragma warning( disable : 4265 ) // "class has virtual functions, but destructor is not virtual"
|
||||
@@ -84,13 +85,14 @@ LLFloaterPostcard::instance_list_t LLFloaterPostcard::sInstances;
|
||||
/// Class LLFloaterPostcard
|
||||
///----------------------------------------------------------------------------
|
||||
|
||||
LLFloaterPostcard::LLFloaterPostcard(LLImageJPEG* jpeg, LLViewerTexture *img, const LLVector2& img_scale, const LLVector3d& pos_taken_global)
|
||||
LLFloaterPostcard::LLFloaterPostcard(LLImageJPEG* jpeg, LLViewerTexture *img, const LLVector2& img_scale, const LLVector3d& pos_taken_global, int index)
|
||||
: LLFloater(std::string("Postcard Floater")),
|
||||
mJPEGImage(jpeg),
|
||||
mViewerImage(img),
|
||||
mImageScale(img_scale),
|
||||
mPosTakenGlobal(pos_taken_global),
|
||||
mHasFirstMsgFocus(false)
|
||||
mHasFirstMsgFocus(false),
|
||||
mSnapshotIndex(index)
|
||||
{
|
||||
init();
|
||||
}
|
||||
@@ -146,11 +148,11 @@ BOOL LLFloaterPostcard::postBuild()
|
||||
|
||||
|
||||
// static
|
||||
LLFloaterPostcard* LLFloaterPostcard::showFromSnapshot(LLImageJPEG *jpeg, LLViewerTexture *img, const LLVector2 &image_scale, const LLVector3d& pos_taken_global)
|
||||
LLFloaterPostcard* LLFloaterPostcard::showFromSnapshot(LLImageJPEG *jpeg, LLViewerTexture *img, const LLVector2 &image_scale, const LLVector3d& pos_taken_global, int index)
|
||||
{
|
||||
// Take the images from the caller
|
||||
// It's now our job to clean them up
|
||||
LLFloaterPostcard *instance = new LLFloaterPostcard(jpeg, img, image_scale, pos_taken_global);
|
||||
LLFloaterPostcard *instance = new LLFloaterPostcard(jpeg, img, image_scale, pos_taken_global, index);
|
||||
|
||||
LLUICtrlFactory::getInstance()->buildFloater(instance, "floater_postcard.xml");
|
||||
|
||||
@@ -221,25 +223,47 @@ void LLFloaterPostcard::onClickCancel(void* data)
|
||||
if (data)
|
||||
{
|
||||
LLFloaterPostcard *self = (LLFloaterPostcard *)data;
|
||||
|
||||
LLFloaterSnapshot::savePostcardDone(false, self->mSnapshotIndex);
|
||||
self->close(false);
|
||||
}
|
||||
}
|
||||
|
||||
void LLFloaterPostcard::onClose(bool app_quitting)
|
||||
{
|
||||
LLFloaterSnapshot::savePostcardDone(false, mSnapshotIndex);
|
||||
destroy();
|
||||
}
|
||||
|
||||
class LLSendPostcardResponder : public LLAssetUploadResponder
|
||||
{
|
||||
private:
|
||||
int mSnapshotIndex;
|
||||
|
||||
public:
|
||||
LLSendPostcardResponder(const LLSD &post_data,
|
||||
const LLUUID& vfile_id,
|
||||
LLAssetType::EType asset_type):
|
||||
LLAssetUploadResponder(post_data, vfile_id, asset_type)
|
||||
LLAssetType::EType asset_type,
|
||||
int index) :
|
||||
LLAssetUploadResponder(post_data, vfile_id, asset_type),
|
||||
mSnapshotIndex(index)
|
||||
{
|
||||
}
|
||||
// *TODO define custom uploadFailed here so it's not such a generic message
|
||||
void uploadComplete(const LLSD& content)
|
||||
/*virtual*/ void uploadComplete(const LLSD& content)
|
||||
{
|
||||
// we don't care about what the server returns from this post, just clean up the UI
|
||||
LLUploadDialog::modalUploadFinished();
|
||||
LLFloaterSnapshot::savePostcardDone(true, mSnapshotIndex);
|
||||
}
|
||||
/*virtual*/ void uploadFailure(const LLSD& content)
|
||||
{
|
||||
LLAssetUploadResponder::uploadFailure(content);
|
||||
LLFloaterSnapshot::savePostcardDone(false, mSnapshotIndex);
|
||||
}
|
||||
/*virtual*/ void error(U32 statusNum, const std::string& reason)
|
||||
{
|
||||
LLAssetUploadResponder::error(statusNum, reason);
|
||||
LLFloaterSnapshot::savePostcardDone(false, mSnapshotIndex);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -292,6 +316,8 @@ void LLFloaterPostcard::uploadCallback(const LLUUID& asset_id, void *user_data,
|
||||
|
||||
LLUploadDialog::modalUploadFinished();
|
||||
|
||||
LLFloaterSnapshot::savePostcardDone(!result, self->mSnapshotIndex);
|
||||
|
||||
if (result)
|
||||
{
|
||||
LLSD args;
|
||||
@@ -396,7 +422,7 @@ void LLFloaterPostcard::sendPostcard()
|
||||
body["name"] = childGetValue("name_form").asString();
|
||||
body["subject"] = childGetValue("subject_form").asString();
|
||||
body["msg"] = childGetValue("msg_form").asString();
|
||||
LLHTTPClient::post(url, body, new LLSendPostcardResponder(body, mAssetID, LLAssetType::AT_IMAGE_JPEG));
|
||||
LLHTTPClient::post(url, body, new LLSendPostcardResponder(body, mAssetID, LLAssetType::AT_IMAGE_JPEG, mSnapshotIndex));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -50,14 +50,15 @@ class LLFloaterPostcard
|
||||
: public LLFloater
|
||||
{
|
||||
public:
|
||||
LLFloaterPostcard(LLImageJPEG* jpeg, LLViewerTexture *img, const LLVector2& img_scale, const LLVector3d& pos_taken_global);
|
||||
virtual ~LLFloaterPostcard();
|
||||
LLFloaterPostcard(LLImageJPEG* jpeg, LLViewerTexture *img, const LLVector2& img_scale, const LLVector3d& pos_taken_global, int index);
|
||||
/*virtual*/ ~LLFloaterPostcard();
|
||||
|
||||
virtual void init();
|
||||
virtual BOOL postBuild();
|
||||
virtual void draw();
|
||||
/*virtual*/ void init();
|
||||
/*virtual*/ BOOL postBuild();
|
||||
/*virtual*/ void draw();
|
||||
/*virtual*/ void onClose(bool app_quitting);
|
||||
|
||||
static LLFloaterPostcard* showFromSnapshot(LLImageJPEG *jpeg, LLViewerTexture *img, const LLVector2& img_scale, const LLVector3d& pos_taken_global);
|
||||
static LLFloaterPostcard* showFromSnapshot(LLImageJPEG *jpeg, LLViewerTexture *img, const LLVector2& img_scale, const LLVector3d& pos_taken_global, int index);
|
||||
|
||||
static void onClickCancel(void* data);
|
||||
static void onClickSend(void* data);
|
||||
@@ -82,6 +83,7 @@ protected:
|
||||
LLVector2 mImageScale;
|
||||
LLVector3d mPosTakenGlobal;
|
||||
bool mHasFirstMsgFocus;
|
||||
int mSnapshotIndex;
|
||||
|
||||
typedef std::set<LLFloaterPostcard*> instance_list_t;
|
||||
static instance_list_t sInstances;
|
||||
|
||||
@@ -898,7 +898,8 @@ void LLFloaterReporter::takeScreenshot()
|
||||
const S32 IMAGE_HEIGHT = 768;
|
||||
|
||||
LLPointer<LLImageRaw> raw = new LLImageRaw;
|
||||
if( !gViewerWindow->rawSnapshot(raw, IMAGE_WIDTH, IMAGE_HEIGHT, TRUE, FALSE, TRUE, FALSE))
|
||||
// Warning: This crops left and right in case of wide-screen monitor:
|
||||
if( !gViewerWindow->rawSnapshot(raw, IMAGE_WIDTH, IMAGE_HEIGHT, (F32)IMAGE_WIDTH / IMAGE_HEIGHT, TRUE, FALSE))
|
||||
{
|
||||
llwarns << "Unable to take screenshot" << llendl;
|
||||
return;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -47,16 +47,22 @@ public:
|
||||
{
|
||||
SNAPSHOT_FORMAT_PNG,
|
||||
SNAPSHOT_FORMAT_JPEG,
|
||||
SNAPSHOT_FORMAT_BMP
|
||||
SNAPSHOT_FORMAT_BMP,
|
||||
SNAPSHOT_FORMAT_J2C
|
||||
} ESnapshotFormat;
|
||||
|
||||
LLFloaterSnapshot();
|
||||
virtual ~LLFloaterSnapshot();
|
||||
|
||||
LLRect getThumbnailAreaRect();
|
||||
|
||||
/*virtual*/ BOOL postBuild();
|
||||
/*virtual*/ void draw();
|
||||
/*virtual*/ void onClose(bool app_quitting);
|
||||
/*virtual*/ void onOpen();
|
||||
/*virtual*/ BOOL handleKeyHere(KEY key, MASK mask);
|
||||
/*virtual*/ BOOL handleMouseDown(S32 x, S32 y, MASK mask);
|
||||
/*virtual*/ BOOL handleMouseUp(S32 x, S32 y, MASK mask);
|
||||
|
||||
static void show(void*);
|
||||
static void hide(void*);
|
||||
@@ -66,6 +72,13 @@ public:
|
||||
static S32 getUIWinHeightShort() {return sUIWinHeightShort ;}
|
||||
static S32 getUIWinWidth() {return sUIWinWidth ;}
|
||||
|
||||
static void saveLocalDone(bool success, int index);
|
||||
static void saveFeedDone(bool success, int index);
|
||||
static void savePostcardDone(bool success, int index);
|
||||
|
||||
static void updateControls();
|
||||
static void resetFeedAndPostcardAspect();
|
||||
|
||||
private:
|
||||
class Impl;
|
||||
Impl& impl;
|
||||
|
||||
@@ -199,12 +199,19 @@ namespace LLMarketplaceImport
|
||||
/*virtual*/ bool followRedir(void) const { return true; }
|
||||
/*virtual*/ bool needsHeaders(void) const { return true; }
|
||||
|
||||
void completedHeaders(U32 status, std::string const& reason, AIHTTPReceivedHeaders const& headers)
|
||||
/*virtual*/ void completedHeaders(U32 status, std::string const& reason, AIHTTPReceivedHeaders const& headers)
|
||||
{
|
||||
std::string set_cookie_string;
|
||||
if (headers.getFirstValue("set-cookie", set_cookie_string) && !set_cookie_string.empty())
|
||||
if (status == HTTP_OK)
|
||||
{
|
||||
sMarketplaceCookie = set_cookie_string;
|
||||
std::string value = get_cookie("_slm_session");
|
||||
if (!value.empty())
|
||||
{
|
||||
sMarketplaceCookie = value;
|
||||
}
|
||||
else if (sMarketplaceCookie.empty())
|
||||
{
|
||||
llwarns << "No such cookie \"_slm_session\" received!" << llendl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -226,7 +233,7 @@ namespace LLMarketplaceImport
|
||||
{
|
||||
if (gSavedSettings.getBOOL("InventoryOutboxLogging"))
|
||||
{
|
||||
llinfos << " SLM GET clearing marketplace cookie due to authentication failure or timeout" << llendl;
|
||||
llinfos << " SLM GET clearing marketplace cookie due to authentication failure or timeout (" << status << " / " << reason << ")." << llendl;
|
||||
}
|
||||
|
||||
sMarketplaceCookie.clear();
|
||||
@@ -372,7 +379,7 @@ namespace LLMarketplaceImport
|
||||
// Interface class
|
||||
//
|
||||
|
||||
//static const F32 MARKET_IMPORTER_UPDATE_FREQUENCY = 300.0f; //1.0f;
|
||||
static const F32 MARKET_IMPORTER_UPDATE_FREQUENCY = 1.0f;
|
||||
|
||||
//static
|
||||
void LLMarketplaceInventoryImporter::update()
|
||||
@@ -383,7 +390,7 @@ void LLMarketplaceInventoryImporter::update()
|
||||
if (update_timer.hasExpired())
|
||||
{
|
||||
LLMarketplaceInventoryImporter::instance().updateImport();
|
||||
static LLCachedControl<F32> MARKET_IMPORTER_UPDATE_FREQUENCY("MarketImporterUpdateFreq", 10.0f);
|
||||
//static LLCachedControl<F32> MARKET_IMPORTER_UPDATE_FREQUENCY("MarketImporterUpdateFreq", 1.0f);
|
||||
update_timer.setTimerExpirySec(MARKET_IMPORTER_UPDATE_FREQUENCY);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -70,7 +70,6 @@ LLMenuOptionPathfindingRebakeNavmesh::~LLMenuOptionPathfindingRebakeNavmesh()
|
||||
|
||||
void LLMenuOptionPathfindingRebakeNavmesh::initialize()
|
||||
{
|
||||
llassert(!mIsInitialized);
|
||||
if (!mIsInitialized)
|
||||
{
|
||||
mIsInitialized = true;
|
||||
|
||||
@@ -162,10 +162,6 @@ public:
|
||||
|
||||
LLLoginRefreshHandler gLoginRefreshHandler;
|
||||
|
||||
// <edit>
|
||||
std::string gFullName;
|
||||
// </edit>
|
||||
|
||||
// helper class that trys to download a URL from a web site and calls a method
|
||||
// on parent class indicating if the web server is working or not
|
||||
class LLIamHereLogin : public LLHTTPClient::ResponderHeadersOnly
|
||||
|
||||
@@ -41,10 +41,6 @@
|
||||
class LLUIImage;
|
||||
class LLComboBox;
|
||||
|
||||
// <edit>
|
||||
extern std::string gFullName;
|
||||
// </edit>
|
||||
|
||||
class LLPanelLogin:
|
||||
public LLPanel,
|
||||
public LLViewerMediaObserver
|
||||
@@ -165,8 +161,4 @@ private:
|
||||
std::string load_password_from_disk(void);
|
||||
void save_password_to_disk(const char* hashed_password);
|
||||
|
||||
// <edit>
|
||||
extern std::string gFullName;
|
||||
// </edit>
|
||||
|
||||
#endif
|
||||
|
||||
@@ -4421,6 +4421,10 @@ public:
|
||||
}
|
||||
|
||||
}
|
||||
else if (avatar->isLangolier())
|
||||
{
|
||||
skip_check = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!skip_check && vobj->lineSegmentIntersect(mStart, mEnd, -1, mPickTransparent, mFaceHit, &intersection, mTexCoord, mNormal, mBinormal))
|
||||
|
||||
@@ -757,9 +757,6 @@ bool idle_startup()
|
||||
// We have at least some login information on a SLURL
|
||||
firstname = gLoginHandler.getFirstName();
|
||||
lastname = gLoginHandler.getLastName();
|
||||
// <edit>
|
||||
gFullName = utf8str_tolower(firstname + " " + lastname);
|
||||
// </edit>
|
||||
web_login_key = gLoginHandler.getWebLoginKey();
|
||||
|
||||
// Show the login screen if we don't have everything
|
||||
@@ -771,9 +768,6 @@ bool idle_startup()
|
||||
LLSD cmd_line_login = gSavedSettings.getLLSD("UserLoginInfo");
|
||||
firstname = cmd_line_login[0].asString();
|
||||
lastname = cmd_line_login[1].asString();
|
||||
// <edit>
|
||||
gFullName = utf8str_tolower(firstname + " " + lastname);
|
||||
// </edit>
|
||||
|
||||
LLMD5 pass((unsigned char*)cmd_line_login[2].asString().c_str());
|
||||
char md5pass[33]; /* Flawfinder: ignore */
|
||||
@@ -791,9 +785,6 @@ bool idle_startup()
|
||||
{
|
||||
firstname = gSavedSettings.getString("FirstName");
|
||||
lastname = gSavedSettings.getString("LastName");
|
||||
// <edit>
|
||||
gFullName = utf8str_tolower(firstname + " " + lastname);
|
||||
// </edit>
|
||||
password = LLStartUp::loadPasswordFromDisk();
|
||||
gSavedSettings.setBOOL("RememberPassword", TRUE);
|
||||
|
||||
@@ -809,9 +800,6 @@ bool idle_startup()
|
||||
// a valid grid is selected
|
||||
firstname = gSavedSettings.getString("FirstName");
|
||||
lastname = gSavedSettings.getString("LastName");
|
||||
// <edit>
|
||||
gFullName = utf8str_tolower(firstname + " " + lastname);
|
||||
// </edit>
|
||||
password = LLStartUp::loadPasswordFromDisk();
|
||||
show_connect_box = true;
|
||||
}
|
||||
@@ -895,9 +883,6 @@ bool idle_startup()
|
||||
else
|
||||
{
|
||||
LLPanelLogin::setFields(firstname, lastname, password);
|
||||
// <edit>
|
||||
gFullName = utf8str_tolower(firstname + " " + lastname);
|
||||
// </edit>
|
||||
LLPanelLogin::giveFocus();
|
||||
}
|
||||
display_startup();
|
||||
@@ -969,9 +954,6 @@ bool idle_startup()
|
||||
{
|
||||
firstname = gLoginHandler.getFirstName();
|
||||
lastname = gLoginHandler.getLastName();
|
||||
// <edit>
|
||||
gFullName = utf8str_tolower(firstname + " " + lastname);
|
||||
// </edit>
|
||||
web_login_key = gLoginHandler.getWebLoginKey();
|
||||
}
|
||||
|
||||
@@ -990,15 +972,21 @@ bool idle_startup()
|
||||
{
|
||||
gSavedSettings.setString("FirstName", firstname);
|
||||
gSavedSettings.setString("LastName", lastname);
|
||||
// <edit>
|
||||
gFullName = utf8str_tolower(firstname + " " + lastname);
|
||||
// </edit>
|
||||
if (!gSavedSettings.controlExists("RememberLogin")) gSavedSettings.declareBOOL("RememberLogin", false, "Remember login", false);
|
||||
gSavedSettings.setBOOL("RememberLogin", LLPanelLogin::getRememberLogin());
|
||||
|
||||
LL_INFOS("AppInit") << "Attempting login as: " << firstname << " " << lastname << LL_ENDL;
|
||||
gDebugInfo["LoginName"] = firstname + " " + lastname;
|
||||
}
|
||||
else
|
||||
{
|
||||
// User tried to login on a non-SecondLife grid with an empty lastname.
|
||||
LLSD subs;
|
||||
subs["GRIDNAME"] = gHippoGridManager->getConnectedGrid()->getGridName();
|
||||
LLNotificationsUtil::add(firstname.empty() ? "EmptyFirstNameMessage" : "EmptyLastNameMessage", subs);
|
||||
LLStartUp::setStartupState(STATE_LOGIN_SHOW);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
LLScriptEdCore::parseFunctions("lsl_functions_sl.xml"); //Singu Note: This parsing function essentially replaces the entirety of the lscript_library library
|
||||
|
||||
@@ -4099,9 +4087,6 @@ bool process_login_success_response(std::string& password)
|
||||
if(!text.empty()) lastname.assign(text);
|
||||
gSavedSettings.setString("FirstName", firstname);
|
||||
gSavedSettings.setString("LastName", lastname);
|
||||
// <edit>
|
||||
gFullName = utf8str_tolower(firstname + " " + lastname);
|
||||
// </edit>
|
||||
|
||||
if (gSavedSettings.getBOOL("RememberPassword"))
|
||||
{
|
||||
|
||||
@@ -188,7 +188,8 @@ void display_update_camera(bool tiling=false)
|
||||
// Cut draw distance in half when customizing avatar,
|
||||
// but on the viewer only.
|
||||
F32 final_far = gAgentCamera.mDrawDistance;
|
||||
if(tiling) //Don't animate clouds and water if tiling!
|
||||
static const LLCachedControl<bool> freeze_time("FreezeTime",false);
|
||||
if(freeze_time || tiling) //Don't animate clouds and water if tiling!
|
||||
{
|
||||
LLViewerCamera::getInstance()->setFar(final_far);
|
||||
gViewerWindow->setup3DRender();
|
||||
|
||||
@@ -55,6 +55,7 @@
|
||||
#include "llwindow.h"
|
||||
#include "llvieweraudio.h"
|
||||
#include "llweb.h"
|
||||
#include "llwebprofile.h"
|
||||
|
||||
#include "llfloateravatarinfo.h" // for getProfileURL() function
|
||||
//#include "viewerversion.h"
|
||||
@@ -140,12 +141,7 @@ public:
|
||||
{
|
||||
LL_DEBUGS("MediaAuth") << "status = " << status << ", reason = " << reason << LL_ENDL;
|
||||
LL_DEBUGS("MediaAuth") << headers << LL_ENDL;
|
||||
AIHTTPReceivedHeaders::range_type cookies;
|
||||
if (headers.getValues("set-cookie", cookies))
|
||||
{
|
||||
for (AIHTTPReceivedHeaders::iterator_type cookie = cookies.first; cookie != cookies.second; ++cookie)
|
||||
LLViewerMedia::openIDCookieResponse(cookie->second);
|
||||
}
|
||||
LLViewerMedia::openIDCookieResponse(get_cookie("agni_sl_session_id"));
|
||||
}
|
||||
|
||||
/* virtual */ void completedRaw(
|
||||
@@ -182,11 +178,29 @@ public:
|
||||
LL_INFOS("MediaAuth") << "status = " << status << ", reason = " << reason << LL_ENDL;
|
||||
LL_INFOS("MediaAuth") << headers << LL_ENDL;
|
||||
|
||||
bool found = false;
|
||||
AIHTTPReceivedHeaders::range_type cookies;
|
||||
if (headers.getValues("set-cookie", cookies))
|
||||
{
|
||||
for (AIHTTPReceivedHeaders::iterator_type cookie = cookies.first; cookie != cookies.second; ++cookie)
|
||||
{
|
||||
LLViewerMedia::getCookieStore()->setCookiesFromHost(cookie->second, mHost);
|
||||
|
||||
std::string key = cookie->second.substr(0, cookie->second.find('='));
|
||||
if (key == "_my_secondlife_session")
|
||||
{
|
||||
// Set cookie for snapshot publishing.
|
||||
std::string auth_cookie = cookie->second.substr(0, cookie->second.find(";")); // strip path
|
||||
LL_INFOS("MediaAuth") << "Setting openID auth cookie \"" << auth_cookie << "\"." << LL_ENDL;
|
||||
LLWebProfile::setAuthCookie(auth_cookie);
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!found)
|
||||
{
|
||||
llwarns << "LLViewerMediaWebProfileResponder did not receive a session ID cookie \"_my_secondlife_session\"! OpenID authentications will fail!" << llendl;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -527,6 +527,7 @@ class LLFileTakeSnapshotToDisk : public view_listener_t
|
||||
|
||||
S32 width = gViewerWindow->getWindowDisplayWidth();
|
||||
S32 height = gViewerWindow->getWindowDisplayHeight();
|
||||
F32 ratio = (F32)width / height;
|
||||
|
||||
F32 supersample = 1.f;
|
||||
if (gSavedSettings.getBOOL("HighResSnapshot"))
|
||||
@@ -546,8 +547,7 @@ class LLFileTakeSnapshotToDisk : public view_listener_t
|
||||
if (gViewerWindow->rawSnapshot(raw,
|
||||
width,
|
||||
height,
|
||||
TRUE,
|
||||
FALSE,
|
||||
ratio,
|
||||
gSavedSettings.getBOOL("RenderUIInSnapshot"),
|
||||
FALSE,
|
||||
LLViewerWindow::SNAPSHOT_TYPE_COLOR,
|
||||
@@ -574,7 +574,7 @@ class LLFileTakeSnapshotToDisk : public view_listener_t
|
||||
formatted->enableOverSize() ;
|
||||
formatted->encode(raw, 0);
|
||||
formatted->disableOverSize();
|
||||
gViewerWindow->saveImageNumbered(formatted);
|
||||
gViewerWindow->saveImageNumbered(formatted, -1);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1340,7 +1340,7 @@ void LLViewerObjectList::killAllObjects()
|
||||
|
||||
killObject(objectp);
|
||||
// Object must be dead, or it's the LLVOAvatarSelf which never dies.
|
||||
llassert((objectp == gAgentAvatarp) || objectp->isDead());
|
||||
llassert((objectp == gAgentAvatarp) || objectp->isDead() || (objectp->asAvatar() && objectp->asAvatar()->isFrozenDead()));
|
||||
}
|
||||
|
||||
cleanDeadObjects(FALSE);
|
||||
|
||||
@@ -3990,10 +3990,11 @@ BOOL LLViewerWindow::mousePointOnLandGlobal(const S32 x, const S32 y, LLVector3d
|
||||
}
|
||||
|
||||
// Saves an image to the harddrive as "SnapshotX" where X >= 1.
|
||||
void LLViewerWindow::saveImageNumbered(LLPointer<LLImageFormatted> image)
|
||||
void LLViewerWindow::saveImageNumbered(LLPointer<LLImageFormatted> image, int index)
|
||||
{
|
||||
if (!image)
|
||||
{
|
||||
LLFloaterSnapshot::saveLocalDone(false, index);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -4022,15 +4023,15 @@ void LLViewerWindow::saveImageNumbered(LLPointer<LLImageFormatted> image)
|
||||
// pick a directory in which to save
|
||||
AIFilePicker* filepicker = AIFilePicker::create(); // Deleted in LLViewerWindow::saveImageNumbered_continued1
|
||||
filepicker->open(proposed_name, pick_type, "", "snapshot");
|
||||
filepicker->run(boost::bind(&LLViewerWindow::saveImageNumbered_continued1, this, image, extension, filepicker));
|
||||
filepicker->run(boost::bind(&LLViewerWindow::saveImageNumbered_continued1, this, image, extension, filepicker, index));
|
||||
return;
|
||||
}
|
||||
|
||||
// LLViewerWindow::sSnapshotBaseName and LLViewerWindow::sSnapshotDir already known. Go straight to saveImageNumbered_continued2.
|
||||
saveImageNumbered_continued2(image, extension);
|
||||
saveImageNumbered_continued2(image, extension, index);
|
||||
}
|
||||
|
||||
void LLViewerWindow::saveImageNumbered_continued1(LLPointer<LLImageFormatted> image, std::string const& extension, AIFilePicker* filepicker)
|
||||
void LLViewerWindow::saveImageNumbered_continued1(LLPointer<LLImageFormatted> image, std::string const& extension, AIFilePicker* filepicker, int index)
|
||||
{
|
||||
if (filepicker->hasFilename())
|
||||
{
|
||||
@@ -4040,11 +4041,15 @@ void LLViewerWindow::saveImageNumbered_continued1(LLPointer<LLImageFormatted> im
|
||||
LLViewerWindow::sSnapshotBaseName = gDirUtilp->getBaseFileName(filepath, true);
|
||||
LLViewerWindow::sSnapshotDir = gDirUtilp->getDirName(filepath);
|
||||
|
||||
saveImageNumbered_continued2(image, extension);
|
||||
saveImageNumbered_continued2(image, extension, index);
|
||||
}
|
||||
else
|
||||
{
|
||||
LLFloaterSnapshot::saveLocalDone(false, index);
|
||||
}
|
||||
}
|
||||
|
||||
void LLViewerWindow::saveImageNumbered_continued2(LLPointer<LLImageFormatted> image, std::string const& extension)
|
||||
void LLViewerWindow::saveImageNumbered_continued2(LLPointer<LLImageFormatted> image, std::string const& extension, int index)
|
||||
{
|
||||
// Look for an unused file name
|
||||
std::string filepath;
|
||||
@@ -4068,6 +4073,11 @@ void LLViewerWindow::saveImageNumbered_continued2(LLPointer<LLImageFormatted> im
|
||||
if (image->save(filepath))
|
||||
{
|
||||
playSnapshotAnimAndSound();
|
||||
LLFloaterSnapshot::saveLocalDone(true, index);
|
||||
}
|
||||
else
|
||||
{
|
||||
LLFloaterSnapshot::saveLocalDone(false, index);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4118,7 +4128,7 @@ BOOL LLViewerWindow::saveSnapshot( const std::string& filepath, S32 image_width,
|
||||
llinfos << "Saving snapshot to: " << filepath << llendl;
|
||||
|
||||
LLPointer<LLImageRaw> raw = new LLImageRaw;
|
||||
BOOL success = rawSnapshot(raw, image_width, image_height, TRUE, FALSE, show_ui, do_rebuild);
|
||||
BOOL success = rawSnapshot(raw, image_width, image_height, (F32)image_width / image_height, show_ui, do_rebuild);
|
||||
|
||||
if (success)
|
||||
{
|
||||
@@ -4154,7 +4164,7 @@ void LLViewerWindow::playSnapshotAnimAndSound()
|
||||
|
||||
BOOL LLViewerWindow::thumbnailSnapshot(LLImageRaw *raw, S32 preview_width, S32 preview_height, BOOL show_ui, BOOL do_rebuild, ESnapshotType type)
|
||||
{
|
||||
return rawSnapshot(raw, preview_width, preview_height, FALSE, FALSE, show_ui, do_rebuild, type);
|
||||
return rawSnapshot(raw, preview_width, preview_height, (F32)gViewerWindow->getWindowWidthRaw() / gViewerWindow->getWindowHeightRaw(), show_ui, do_rebuild, type);
|
||||
|
||||
// *TODO below code was broken in deferred pipeline
|
||||
/*
|
||||
@@ -4293,25 +4303,29 @@ BOOL LLViewerWindow::thumbnailSnapshot(LLImageRaw *raw, S32 preview_width, S32 p
|
||||
return TRUE;*/
|
||||
}
|
||||
|
||||
// Saves the image from the screen to the specified filename and path.
|
||||
BOOL LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_height,
|
||||
BOOL keep_window_aspect, BOOL is_texture, BOOL show_ui, BOOL do_rebuild, ESnapshotType type, S32 max_size, F32 supersample)
|
||||
// Saves the image from the screen to the image pointed to by raw.
|
||||
// This function does NOT yet scale the snapshot down to the requested size
|
||||
// if that is smaller than the current window (scale_factor < 1) or if
|
||||
// the aspect of the snapshot is unequal to the aspect of requested image.
|
||||
bool LLViewerWindow::rawRawSnapshot(LLImageRaw *raw,
|
||||
S32 image_width, S32 image_height, F32 snapshot_aspect, BOOL show_ui,
|
||||
BOOL do_rebuild, ESnapshotType type, S32 max_size, F32 supersample)
|
||||
{
|
||||
if (!raw)
|
||||
{
|
||||
return FALSE;
|
||||
return false;
|
||||
}
|
||||
//check if there is enough memory for the snapshot image
|
||||
if(LLPipeline::sMemAllocationThrottled)
|
||||
{
|
||||
return FALSE ; //snapshot taking is disabled due to memory restriction.
|
||||
return false; //snapshot taking is disabled due to memory restriction.
|
||||
}
|
||||
if(image_width * image_height > (1 << 22)) //if snapshot image is larger than 2K by 2K
|
||||
{
|
||||
if(!LLMemory::tryToAlloc(NULL, image_width * image_height * 3))
|
||||
{
|
||||
llwarns << "No enough memory to take the snapshot with size (w : h): " << image_width << " : " << image_height << llendl ;
|
||||
return FALSE ; //there is no enough memory for taking this snapshot.
|
||||
return false; //there is no enough memory for taking this snapshot.
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4335,27 +4349,13 @@ BOOL LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_hei
|
||||
LLPipeline::sShowHUDAttachments = FALSE;
|
||||
}
|
||||
|
||||
|
||||
// Copy screen to a buffer
|
||||
// crop sides or top and bottom, if taking a snapshot of different aspect ratio
|
||||
// from window
|
||||
LLRect window_rect = show_ui ? getWindowRectRaw() : getWorldViewRectRaw();
|
||||
|
||||
S32 snapshot_width = window_rect.getWidth();
|
||||
S32 snapshot_height = window_rect.getHeight();
|
||||
LLRect const window_rect = show_ui ? getWindowRectRaw() : getWorldViewRectRaw();
|
||||
S32 const window_width = window_rect.getWidth();
|
||||
S32 const window_height = window_rect.getHeight();
|
||||
|
||||
// SNAPSHOT
|
||||
S32 window_width = snapshot_width;
|
||||
S32 window_height = snapshot_height;
|
||||
|
||||
|
||||
F32 scale_factor = 1.0f ;
|
||||
|
||||
bool is_tiling = false;
|
||||
|
||||
//fbo method no longer supported. Good riddance
|
||||
/*LLRenderTarget target;
|
||||
bool use_fbo = false;
|
||||
static const LLCachedControl<bool> force_tile("SHHighResSnapshotForceTile",false);*/
|
||||
|
||||
#if 1//SHY_MOD // screenshot improvement
|
||||
F32 internal_scale = llmin(llmax(supersample,1.f),3.f);
|
||||
@@ -4379,86 +4379,79 @@ BOOL LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_hei
|
||||
}
|
||||
}
|
||||
|
||||
if(!keep_window_aspect) //image cropping
|
||||
{
|
||||
F32 ratio = llmin( (F32)window_width / image_width , (F32)window_height / image_height) ;
|
||||
snapshot_width = (S32)(ratio * image_width) ;
|
||||
snapshot_height = (S32)(ratio * image_height) ;
|
||||
scale_factor = llmax(1.0f, 1.0f / ratio) ;
|
||||
}
|
||||
else //the scene(window) proportion needs to be maintained.
|
||||
S32 buffer_x_offset = 0;
|
||||
S32 buffer_y_offset = 0;
|
||||
F32 scale_factor;
|
||||
S32 image_buffer_x;
|
||||
S32 image_buffer_y;
|
||||
|
||||
F32 const window_aspect = (F32)window_width / window_height;
|
||||
// snapshot fits precisely inside window, it is the portion of the window with the correct aspect.
|
||||
F32 snapshot_width = (snapshot_aspect > window_aspect) ? (F32)window_width : window_height * snapshot_aspect;
|
||||
F32 snapshot_height = (snapshot_aspect < window_aspect) ? (F32)window_height : window_width / snapshot_aspect;
|
||||
// ratio is the ratio snapshot/image', where image' is a rectangle with aspect snapshot_aspect that precisely contains image.
|
||||
// Thus image_width' / image_height' == aspect ==> snapshot_width / image_width' == snapshot_height / image_height'.
|
||||
// Since image' precisely contains image, one of them is equal (ie, image_height' = image_height) and the other is larger
|
||||
// (or equal) (ie, image_width' >= image_width), and therefore one of snapshot_width / image_width and
|
||||
// snapshot_height / image_height is correct, and the other is larger. Therefore, the smallest value of the
|
||||
// following equals the ratio we're looking for.
|
||||
F32 ratio = llmin(snapshot_width / image_width, snapshot_height / image_height);
|
||||
// buffer equals the largest of image' and snapshot. This is because in the first case we need the higher
|
||||
// resolution because of the size of the target image, and in the second case there is no reason to go
|
||||
// smaller because it takes the same amount of time (and a slightly better quality should result after
|
||||
// the final scaling). Thus, if ratio < 1 then buffer equals image', otherwise it equals snapshot.
|
||||
// scale_factor is the ratio buffer/snapshot, and is initiallly equal to the ratio between buffer
|
||||
// and snapshot (which have the same aspect).
|
||||
for(scale_factor = llmax(1.0f, 1.0f / ratio);; // Initial attempt.
|
||||
// However, if the buffer turns out to be too large, then clamp it to max_size.
|
||||
scale_factor = llmin(max_size / snapshot_width, max_size / snapshot_height)) // Clamp
|
||||
{
|
||||
if(image_width > window_width || image_height > window_height) //need to enlarge the scene
|
||||
image_buffer_x = llround(snapshot_width * scale_factor);
|
||||
image_buffer_y = llround(snapshot_height * scale_factor);
|
||||
if (llmax(image_buffer_x, image_buffer_y) > max_size && // Boundary check to avoid memory overflow.
|
||||
internal_scale <= 1.f) // SHY_MOD: If supersampling... Don't care about max_size.
|
||||
{
|
||||
//Unsupported
|
||||
/*if (!force_tile && gGLManager.mHasFramebufferObject && !show_ui)
|
||||
{
|
||||
GLint max_size = 0;
|
||||
glGetIntegerv(GL_MAX_RENDERBUFFER_SIZE_EXT, &max_size);
|
||||
|
||||
if (image_width <= max_size && image_height <= max_size) //re-project the scene
|
||||
{
|
||||
use_fbo = TRUE;
|
||||
|
||||
snapshot_width = image_width;
|
||||
snapshot_height = image_height;
|
||||
target.allocate(snapshot_width, snapshot_height, GL_RGBA, TRUE, TRUE, LLTexUnit::TT_RECT_TEXTURE, TRUE);
|
||||
window_width = snapshot_width;
|
||||
window_height = snapshot_height;
|
||||
scale_factor = 1.f;
|
||||
mWindowRectRaw.set(0, snapshot_height, snapshot_width, 0);
|
||||
target.bindTarget();
|
||||
}
|
||||
}
|
||||
|
||||
if(!use_fbo) //no re-projection, so tiling the scene*/
|
||||
{
|
||||
F32 ratio = llmin( (F32)window_width / image_width , (F32)window_height / image_height) ;
|
||||
snapshot_width = (S32)(ratio * image_width) ;
|
||||
snapshot_height = (S32)(ratio * image_height) ;
|
||||
scale_factor = llmax(1.0f, 1.0f / ratio) ;
|
||||
is_tiling = true;
|
||||
}
|
||||
// Too big, clamp.
|
||||
continue;
|
||||
}
|
||||
//else: keep the current scene scale, re-scale it if necessary after reading out.
|
||||
// Done.
|
||||
break;
|
||||
}
|
||||
|
||||
S32 buffer_x_offset = llfloor(((window_width - snapshot_width) * scale_factor) / 2.f);
|
||||
S32 buffer_y_offset = llfloor(((window_height - snapshot_height) * scale_factor) / 2.f);
|
||||
// Center the buffer.
|
||||
buffer_x_offset = llfloor(((window_width - snapshot_width) * scale_factor) / 2.f);
|
||||
buffer_y_offset = llfloor(((window_height - snapshot_height) * scale_factor) / 2.f);
|
||||
Dout(dc::notice, "rawSnapshot(" << image_width << ", " << image_height << ", " << snapshot_aspect << "): image_buffer_x = " << image_buffer_x << "; image_buffer_y = " << image_buffer_y);
|
||||
|
||||
S32 image_buffer_x = llfloor(snapshot_width*scale_factor) ;
|
||||
S32 image_buffer_y = llfloor(snapshot_height*scale_factor) ;
|
||||
#if 1//SHY_MOD // screenshot improvement
|
||||
if(internal_scale <= 1.f) //If supersampling... Don't care about max_size.
|
||||
#endif //shy_mod
|
||||
if(image_buffer_x > max_size || image_buffer_y > max_size) //boundary check to avoid memory overflow
|
||||
bool error = !(image_buffer_x > 0 && image_buffer_y > 0);
|
||||
if (!error)
|
||||
{
|
||||
scale_factor *= llmin((F32)max_size / image_buffer_x, (F32)max_size / image_buffer_y) ;
|
||||
image_buffer_x = llfloor(snapshot_width*scale_factor) ;
|
||||
image_buffer_y = llfloor(snapshot_height *scale_factor) ;
|
||||
raw->resize(image_buffer_x, image_buffer_y, 3);
|
||||
error = raw->isBufferInvalid();
|
||||
}
|
||||
if (image_buffer_x > 0 && image_buffer_y > 0)
|
||||
if (error)
|
||||
{
|
||||
raw->resize(image_buffer_x, image_buffer_y, 3);
|
||||
}
|
||||
else
|
||||
{
|
||||
return FALSE ;
|
||||
}
|
||||
if(raw->isBufferInvalid())
|
||||
{
|
||||
return FALSE ;
|
||||
if (prev_draw_ui != gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI))
|
||||
{
|
||||
LLPipeline::toggleRenderDebugFeature((void*)LLPipeline::RENDER_DEBUG_FEATURE_UI);
|
||||
}
|
||||
if (hide_hud)
|
||||
{
|
||||
LLPipeline::sShowHUDAttachments = TRUE;
|
||||
}
|
||||
setCursor(UI_CURSOR_ARROW);
|
||||
return false;
|
||||
}
|
||||
|
||||
BOOL high_res = scale_factor > 1.f;
|
||||
if (high_res)
|
||||
BOOL is_tiling = scale_factor > 1.f;
|
||||
if (is_tiling)
|
||||
{
|
||||
Dout(dc::warning, "USING TILING FOR SNAPSHOT!");
|
||||
send_agent_pause();
|
||||
if (show_ui || !hide_hud)
|
||||
{
|
||||
//rescale fonts
|
||||
initFonts(scale_factor);
|
||||
LLHUDObject::reshapeAll();
|
||||
//rescale fonts
|
||||
initFonts(scale_factor);
|
||||
LLHUDObject::reshapeAll();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4471,7 +4464,7 @@ BOOL LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_hei
|
||||
|
||||
for (int subimage_y = 0; subimage_y < scale_factor; ++subimage_y)
|
||||
{
|
||||
S32 subimage_y_offset = llclamp(buffer_y_offset - (subimage_y * window_height), 0, window_height);;
|
||||
S32 subimage_y_offset = llclamp(buffer_y_offset - (subimage_y * window_height), 0, window_height);
|
||||
// handle fractional columns
|
||||
U32 read_height = llmax(0, (window_height - subimage_y_offset) -
|
||||
llmax(0, (window_height * (subimage_y + 1)) - (buffer_y_offset + raw->getHeight())));
|
||||
@@ -4513,7 +4506,7 @@ BOOL LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_hei
|
||||
// Ping the watchdog thread every 100 lines to keep us alive (arbitrary number, feel free to change)
|
||||
if (out_y % 100 == 0)
|
||||
{
|
||||
LLAppViewer::instance()->pingMainloopTimeout("LLViewerWindow::rawSnapshot");
|
||||
LLAppViewer::instance()->pingMainloopTimeout("LLViewerWindow::rawRawSnapshot");
|
||||
}
|
||||
|
||||
if (type == SNAPSHOT_TYPE_COLOR)
|
||||
@@ -4556,12 +4549,6 @@ BOOL LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_hei
|
||||
output_buffer_offset_y += subimage_y_offset;
|
||||
}
|
||||
|
||||
/*if (use_fbo)
|
||||
{
|
||||
mWindowRect = window_rect;
|
||||
target.flush();
|
||||
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
|
||||
}*/
|
||||
gDisplaySwapBuffers = FALSE;
|
||||
gDepthDirty = TRUE;
|
||||
|
||||
@@ -4576,36 +4563,12 @@ BOOL LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_hei
|
||||
LLPipeline::sShowHUDAttachments = TRUE;
|
||||
}
|
||||
|
||||
if (high_res && (show_ui || !hide_hud))
|
||||
if (is_tiling && (show_ui || !hide_hud))
|
||||
{
|
||||
initFonts(1.f);
|
||||
LLHUDObject::reshapeAll();
|
||||
}
|
||||
|
||||
// Pre-pad image to number of pixels such that the line length is a multiple of 4 bytes (for BMP encoding)
|
||||
// Note: this formula depends on the number of components being 3. Not obvious, but it's correct.
|
||||
image_width += (image_width * 3) % 4;
|
||||
|
||||
BOOL ret = TRUE ;
|
||||
// Resize image
|
||||
if(llabs(image_width - image_buffer_x) > 4 || llabs(image_height - image_buffer_y) > 4)
|
||||
{
|
||||
ret = raw->scale( image_width, image_height );
|
||||
}
|
||||
else if(image_width != image_buffer_x || image_height != image_buffer_y)
|
||||
{
|
||||
ret = raw->scale( image_width, image_height, FALSE );
|
||||
}
|
||||
|
||||
#if 1//SHY_MOD // screenshot improvement
|
||||
if(raw->isBufferInvalid()) //Just checking!
|
||||
return FALSE;
|
||||
if(internal_scale != 1.f) //Scale down our render to the desired dimensions.
|
||||
raw->scale( image_width/internal_scale, image_height/internal_scale );
|
||||
if(raw->isBufferInvalid()) //Just checking!
|
||||
return FALSE;
|
||||
#endif //shy_mod
|
||||
|
||||
setCursor(UI_CURSOR_ARROW);
|
||||
|
||||
if (do_rebuild)
|
||||
@@ -4618,11 +4581,50 @@ BOOL LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_hei
|
||||
gPipeline.resetDrawOrders();
|
||||
}
|
||||
|
||||
if (high_res)
|
||||
if (is_tiling)
|
||||
{
|
||||
send_agent_resume();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Same as the above, but does the resizing.
|
||||
bool LLViewerWindow::rawSnapshot(LLImageRaw *raw,
|
||||
S32 image_width, S32 image_height, F32 snapshot_aspect, BOOL show_ui,
|
||||
BOOL do_rebuild, ESnapshotType type, S32 max_size, F32 supersample)
|
||||
{
|
||||
bool ret = rawRawSnapshot(raw, image_width, image_height, snapshot_aspect, show_ui, do_rebuild, type, max_size, supersample);
|
||||
|
||||
#if 1
|
||||
|
||||
if (ret && !raw->scale(image_width, image_height))
|
||||
{
|
||||
ret = false; // Failure.
|
||||
}
|
||||
|
||||
#else // This was the old behavior.. but I don't think this is needed here.
|
||||
|
||||
if (ret)
|
||||
{
|
||||
// Pad image width such that the line length is a multiple of 4 bytes (for BMP encoding).
|
||||
int n = 4;
|
||||
for (int c = raw->getComponents(); c % 2 == 0 && n > 1; c /= 2) { n /= 2; } // n /= gcd(n, components)
|
||||
image_width += (image_width * (n - 1)) % n; // Now n divides image_width, and thus four divides image_width * components, the line length.
|
||||
|
||||
// Resize image
|
||||
if (llabs(image_width - image_buffer_x) > 4 || llabs(image_height - image_buffer_y) > 4)
|
||||
{
|
||||
ret = raw->scale( image_width, image_height );
|
||||
}
|
||||
else if (image_width != image_buffer_x || image_height != image_buffer_y)
|
||||
{
|
||||
ret = raw->scale( image_width, image_height, FALSE );
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -308,17 +308,21 @@ public:
|
||||
enum ESnapshotType
|
||||
{
|
||||
SNAPSHOT_TYPE_COLOR,
|
||||
SNAPSHOT_TYPE_DEPTH,
|
||||
SNAPSHOT_TYPE_DEPTH
|
||||
};
|
||||
BOOL saveSnapshot(const std::string& filename, S32 image_width, S32 image_height, BOOL show_ui = TRUE, BOOL do_rebuild = FALSE, ESnapshotType type = SNAPSHOT_TYPE_COLOR);
|
||||
BOOL rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_height, BOOL keep_window_aspect = TRUE, BOOL is_texture = FALSE,
|
||||
BOOL show_ui = TRUE, BOOL do_rebuild = FALSE, ESnapshotType type = SNAPSHOT_TYPE_COLOR, S32 max_size = MAX_SNAPSHOT_IMAGE_SIZE, F32 supersample = 1.f );
|
||||
bool rawRawSnapshot(LLImageRaw* raw, S32 image_width, S32 image_height, F32 aspect,
|
||||
BOOL show_ui = TRUE, BOOL do_rebuild = FALSE, ESnapshotType type = SNAPSHOT_TYPE_COLOR,
|
||||
S32 max_size = MAX_SNAPSHOT_IMAGE_SIZE, F32 supersample = 1.f);
|
||||
bool rawSnapshot(LLImageRaw* raw, S32 image_width, S32 image_height, F32 aspect,
|
||||
BOOL show_ui = TRUE, BOOL do_rebuild = FALSE, ESnapshotType type = SNAPSHOT_TYPE_COLOR,
|
||||
S32 max_size = MAX_SNAPSHOT_IMAGE_SIZE, F32 supersample = 1.f);
|
||||
BOOL thumbnailSnapshot(LLImageRaw *raw, S32 preview_width, S32 preview_height, BOOL show_ui, BOOL do_rebuild, ESnapshotType type) ;
|
||||
BOOL isSnapshotLocSet() const { return ! sSnapshotDir.empty(); }
|
||||
void resetSnapshotLoc() const { sSnapshotDir.clear(); }
|
||||
void saveImageNumbered(LLPointer<LLImageFormatted> image);
|
||||
void saveImageNumbered_continued1(LLPointer<LLImageFormatted> image, std::string const& extension, AIFilePicker* filepicker);
|
||||
void saveImageNumbered_continued2(LLPointer<LLImageFormatted> image, std::string const& extension);
|
||||
void saveImageNumbered(LLPointer<LLImageFormatted> image, int index);
|
||||
void saveImageNumbered_continued1(LLPointer<LLImageFormatted> image, std::string const& extension, AIFilePicker* filepicker, int index);
|
||||
void saveImageNumbered_continued2(LLPointer<LLImageFormatted> image, std::string const& extension, int index);
|
||||
|
||||
// Reset the directory where snapshots are saved.
|
||||
// Client will open directory picker on next snapshot save.
|
||||
|
||||
@@ -993,6 +993,12 @@ EmeraldGlobalBoobConfig LLVOAvatar::sBoobConfig;
|
||||
static F32 calc_bouncy_animation(F32 x);
|
||||
static U32 calc_shame(LLVOVolume* volume, std::set<LLUUID> &textures);
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Debug setting caches.
|
||||
//-----------------------------------------------------------------------------
|
||||
static LLCachedControl<bool> const freeze_time("FreezeTime", false);
|
||||
static LLCachedControl<bool> const render_unloaded_avatar("RenderUnloadedAvatar", false);
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// LLVOAvatar()
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -1005,6 +1011,8 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id,
|
||||
mAttachmentGeometryBytes(0),
|
||||
mAttachmentSurfaceArea(0.f),
|
||||
mTurning(FALSE),
|
||||
mFreezeTimeLangolier(freeze_time),
|
||||
mFreezeTimeDead(false),
|
||||
mPelvisToFoot(0.f),
|
||||
mLastSkeletonSerialNum( 0 ),
|
||||
mHeadOffset(),
|
||||
@@ -1045,7 +1053,7 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id,
|
||||
mSupportsAlphaLayers(FALSE),
|
||||
mLoadedCallbacksPaused(FALSE),
|
||||
mHasPelvisOffset( FALSE ),
|
||||
mRenderUnloadedAvatar(LLCachedControl<bool>(gSavedSettings, "RenderUnloadedAvatar")),
|
||||
mRenderUnloadedAvatar(render_unloaded_avatar),
|
||||
mLastRezzedStatus(-1),
|
||||
mFirstSetActualBoobGravRan( false ),
|
||||
mSupportsPhysics( false ),
|
||||
@@ -1229,6 +1237,13 @@ LLVOAvatar::~LLVOAvatar()
|
||||
|
||||
void LLVOAvatar::markDead()
|
||||
{
|
||||
static const LLCachedControl<bool> freeze_time("FreezeTime", false);
|
||||
if (freeze_time && !mFreezeTimeLangolier)
|
||||
{
|
||||
// Delay the call to this function until FreezeTime is reset, otherwise avatars disappear from the frozen scene.
|
||||
mFreezeTimeDead = true;
|
||||
return;
|
||||
}
|
||||
if (mNameText)
|
||||
{
|
||||
mNameText->markDead();
|
||||
@@ -3662,6 +3677,7 @@ void LLVOAvatar::idleUpdateNameTagText(BOOL new_name)
|
||||
}
|
||||
bool is_friend = LLAvatarTracker::instance().isBuddy(getID());
|
||||
bool is_cloud = getIsCloud();
|
||||
bool is_langolier = isLangolier();
|
||||
|
||||
if (is_appearance != mNameAppearance)
|
||||
{
|
||||
@@ -3687,7 +3703,8 @@ void LLVOAvatar::idleUpdateNameTagText(BOOL new_name)
|
||||
|| is_muted != mNameMute
|
||||
|| is_appearance != mNameAppearance
|
||||
|| is_friend != mNameFriend
|
||||
|| is_cloud != mNameCloud)
|
||||
|| is_cloud != mNameCloud
|
||||
|| is_langolier != mNameLangolier)
|
||||
{
|
||||
LLColor4 name_tag_color = getNameTagColor(is_friend);
|
||||
|
||||
@@ -3697,7 +3714,7 @@ void LLVOAvatar::idleUpdateNameTagText(BOOL new_name)
|
||||
std::string firstnameText;
|
||||
std::string lastnameText;
|
||||
|
||||
if (is_away || is_muted || is_busy || is_appearance || !idle_string.empty())
|
||||
if (is_away || is_muted || is_busy || is_appearance || is_langolier || !idle_string.empty())
|
||||
{
|
||||
std::string line;
|
||||
if (is_away)
|
||||
@@ -3720,7 +3737,12 @@ void LLVOAvatar::idleUpdateNameTagText(BOOL new_name)
|
||||
line += LLTrans::getString("AvatarEditingAppearance"); //"(Editing Appearance)"
|
||||
line += ", ";
|
||||
}
|
||||
if (is_cloud)
|
||||
if (is_langolier)
|
||||
{
|
||||
line += LLTrans::getString("AvatarLangolier"); //"Langolier"
|
||||
line += ", ";
|
||||
}
|
||||
else if (is_cloud)
|
||||
{
|
||||
line += LLTrans::getString("LoadingData"); //"Loading..."
|
||||
line += ", ";
|
||||
@@ -3847,6 +3869,7 @@ void LLVOAvatar::idleUpdateNameTagText(BOOL new_name)
|
||||
mNameAppearance = is_appearance;
|
||||
mNameFriend = is_friend;
|
||||
mNameCloud = is_cloud;
|
||||
mNameLangolier = is_langolier;
|
||||
mTitle = title ? title->getString() : "";
|
||||
LLStringFn::replace_ascii_controlchars(mTitle,LL_UNKNOWN_CHAR);
|
||||
new_name = TRUE;
|
||||
@@ -4084,7 +4107,18 @@ bool LLVOAvatar::isVisuallyMuted() const
|
||||
|
||||
return LLMuteList::getInstance()->isMuted(getID()) ||
|
||||
(mAttachmentGeometryBytes > max_attachment_bytes && max_attachment_bytes > 0) ||
|
||||
(mAttachmentSurfaceArea > max_attachment_area && max_attachment_area > 0.f);
|
||||
(mAttachmentSurfaceArea > max_attachment_area && max_attachment_area > 0.f) ||
|
||||
isLangolier();
|
||||
}
|
||||
|
||||
void LLVOAvatar::resetFreezeTime()
|
||||
{
|
||||
bool dead = mFreezeTimeDead;
|
||||
mFreezeTimeLangolier = mFreezeTimeDead = false;
|
||||
if (dead)
|
||||
{
|
||||
markDead();
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
@@ -4095,6 +4129,13 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent)
|
||||
{
|
||||
LLMemType mt(LLMemType::MTYPE_AVATAR);
|
||||
|
||||
// Frozen!
|
||||
if (areAnimationsPaused())
|
||||
{
|
||||
updateMotions(LLCharacter::NORMAL_UPDATE); // This is necessary to get unpaused again.
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// clear debug text
|
||||
mDebugText.clear();
|
||||
if (LLVOAvatar::sShowAnimationDebug)
|
||||
|
||||
@@ -341,6 +341,8 @@ public:
|
||||
BOOL hasGray() const;
|
||||
S32 getRezzedStatus() const; // 0 = cloud, 1 = gray, 2 = fully textured.
|
||||
void updateRezzedStatusTimers();
|
||||
bool isLangolier() const { return mFreezeTimeLangolier; }
|
||||
bool isFrozenDead() const { return mFreezeTimeDead; }
|
||||
|
||||
S32 mLastRezzedStatus;
|
||||
protected:
|
||||
@@ -358,6 +360,8 @@ private:
|
||||
S32 mVisualComplexity;
|
||||
LLFrameTimer mFullyLoadedTimer;
|
||||
LLFrameTimer mRuthTimer;
|
||||
bool mFreezeTimeLangolier; // True when this avatar was created during snapshot FreezeTime mode, and that mode is still active.
|
||||
bool mFreezeTimeDead; // True when the avatar was marked dead (ie, TP-ed away) while in FreezeTime mode.
|
||||
protected:
|
||||
LLFrameTimer mInvisibleTimer;
|
||||
|
||||
@@ -453,6 +457,7 @@ private:
|
||||
public:
|
||||
U32 renderImpostor(LLColor4U color = LLColor4U(255,255,255,255), S32 diffuse_channel = 0);
|
||||
bool isVisuallyMuted() const;
|
||||
void resetFreezeTime();
|
||||
|
||||
U32 renderRigid();
|
||||
U32 renderSkinned(EAvatarRenderPass pass);
|
||||
@@ -1012,6 +1017,7 @@ private:
|
||||
bool mNameAppearance;
|
||||
bool mNameFriend;
|
||||
bool mNameCloud;
|
||||
bool mNameLangolier;
|
||||
F32 mNameAlpha;
|
||||
BOOL mRenderGroupTitles;
|
||||
|
||||
|
||||
@@ -374,7 +374,7 @@ void LLWaterParamManager::updateShaderLinks()
|
||||
void LLWaterParamManager::update(LLViewerCamera * cam)
|
||||
{
|
||||
LLFastTimer ftm(FTM_UPDATE_WATERPARAM);
|
||||
|
||||
|
||||
// update the shaders and the menu
|
||||
propagateParameters();
|
||||
|
||||
|
||||
@@ -114,12 +114,13 @@ public:
|
||||
config["caption"] = data.get("caption", "").asString();
|
||||
|
||||
// Do the actual image upload using the configuration.
|
||||
LL_DEBUGS("Snapshots") << "Got upload config, POSTing image to " << upload_url << ", config=[" << config << "]" << llendl;
|
||||
LL_DEBUGS("Snapshots") << "Got upload config, POSTing image to " << upload_url << ", config=[" << config << "]" << LL_ENDL;
|
||||
LLWebProfile::post(mImagep, config, upload_url);
|
||||
}
|
||||
|
||||
protected:
|
||||
/*virtual*/ AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy(void) const { return webProfileResponders_timeout; }
|
||||
/*virtual*/ bool followRedir(void) const { return true; }
|
||||
|
||||
private:
|
||||
LLPointer<LLImageFormatted> mImagep;
|
||||
@@ -150,12 +151,13 @@ public:
|
||||
strstrm << istr.rdbuf();
|
||||
const std::string body = strstrm.str();
|
||||
llinfos << "Image uploaded." << llendl;
|
||||
LL_DEBUGS("Snapshots") << "Uploading image succeeded. Response: [" << body << "]" << llendl;
|
||||
LL_DEBUGS("Snapshots") << "Uploading image succeeded. Response: [" << body << "]" << LL_ENDL;
|
||||
LLWebProfile::reportImageUploadStatus(true);
|
||||
}
|
||||
|
||||
protected:
|
||||
/*virtual*/ AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy(void) const { return webProfileResponders_timeout; }
|
||||
/*virtual*/ bool followRedir(void) const { return true; }
|
||||
|
||||
private:
|
||||
LLPointer<LLImageFormatted> mImagep;
|
||||
@@ -171,10 +173,11 @@ class LLWebProfileResponders::PostImageResponder : public LLHTTPClient::Responde
|
||||
public:
|
||||
/*virtual*/ bool needsHeaders(void) const { return true; }
|
||||
|
||||
/*virtual*/ void completedHeader(U32 status, const std::string& reason, const LLSD& content)
|
||||
/*virtual*/ void completedHeaders(U32 status, std::string const& reason, AIHTTPReceivedHeaders const& received_headers)
|
||||
{
|
||||
// Viewer seems to fail to follow a 303 redirect on POST request
|
||||
// (URLRequest Error: 65, Send failed since rewinding of the data stream failed).
|
||||
// Server abuses 303 status; Curl can't handle it because it tries to resent
|
||||
// the just uploaded data, which fails
|
||||
// (CURLE_SEND_FAIL_REWIND: Send failed since rewinding of the data stream failed).
|
||||
// Handle it manually.
|
||||
if (status == 303)
|
||||
{
|
||||
@@ -182,14 +185,15 @@ public:
|
||||
headers.addHeader("Accept", "*/*");
|
||||
headers.addHeader("Cookie", LLWebProfile::getAuthCookie());
|
||||
headers.addHeader("User-Agent", LLViewerMedia::getCurrentUserAgent());
|
||||
const std::string& redir_url = content["location"];
|
||||
LL_DEBUGS("Snapshots") << "Got redirection URL: " << redir_url << llendl;
|
||||
std::string redir_url;
|
||||
received_headers.getFirstValue("location", redir_url);
|
||||
LL_DEBUGS("Snapshots") << "Got redirection URL: " << redir_url << LL_ENDL;
|
||||
LLHTTPClient::get(redir_url, new LLWebProfileResponders::PostImageRedirectResponder, headers);
|
||||
}
|
||||
else
|
||||
{
|
||||
llwarns << "Unexpected POST status: " << status << " " << reason << llendl;
|
||||
LL_DEBUGS("Snapshots") << "headers: [" << content << "]" << llendl;
|
||||
LL_DEBUGS("Snapshots") << "received_headers: [" << received_headers << "]" << LL_ENDL;
|
||||
LLWebProfile::reportImageUploadStatus(false);
|
||||
}
|
||||
}
|
||||
@@ -203,6 +207,7 @@ public:
|
||||
|
||||
protected:
|
||||
/*virtual*/ AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy(void) const { return webProfileResponders_timeout; }
|
||||
/*virtual*/ bool redirect_status_ok(void) const { return true; }
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
@@ -219,7 +224,7 @@ void LLWebProfile::uploadImage(LLPointer<LLImageFormatted> image, const std::str
|
||||
config_url += "?caption=" + LLURI::escape(caption);
|
||||
config_url += "&add_loc=" + std::string(add_location ? "1" : "0");
|
||||
|
||||
LL_DEBUGS("Snapshots") << "Requesting " << config_url << llendl;
|
||||
LL_DEBUGS("Snapshots") << "Requesting " << config_url << LL_ENDL;
|
||||
AIHTTPHeaders headers;
|
||||
headers.addHeader("Accept", "*/*");
|
||||
headers.addHeader("Cookie", LLWebProfile::getAuthCookie());
|
||||
@@ -230,7 +235,7 @@ void LLWebProfile::uploadImage(LLPointer<LLImageFormatted> image, const std::str
|
||||
// static
|
||||
void LLWebProfile::setAuthCookie(const std::string& cookie)
|
||||
{
|
||||
LL_DEBUGS("Snapshots") << "Setting auth cookie: " << cookie << llendl;
|
||||
LL_DEBUGS("Snapshots") << "Setting auth cookie: " << cookie << LL_ENDL;
|
||||
sAuthCookie = cookie;
|
||||
}
|
||||
|
||||
@@ -286,24 +291,22 @@ void LLWebProfile::post(LLPointer<LLImageFormatted> image, const LLSD& config, c
|
||||
body << "--" << boundary << "\r\n"
|
||||
<< "Content-Disposition: form-data; name=\"file\"; filename=\"snapshot.png\"\r\n"
|
||||
<< "Content-Type: image/png\r\n\r\n";
|
||||
size_t const body_size = body.str().size();
|
||||
|
||||
// Insert the image data.
|
||||
// *FIX: Treating this as a string will probably screw it up ...
|
||||
U8* image_data = image->getData();
|
||||
for (S32 i = 0; i < image->getDataSize(); ++i)
|
||||
{
|
||||
body << image_data[i];
|
||||
}
|
||||
|
||||
body << "\r\n--" << boundary << "--\r\n";
|
||||
std::ostringstream footer;
|
||||
footer << "\r\n--" << boundary << "--\r\n";
|
||||
size_t const footer_size = footer.str().size();
|
||||
|
||||
size_t size = body_size + image->getDataSize() + footer_size;
|
||||
// postRaw() takes ownership of the buffer and releases it later.
|
||||
size_t size = body.str().size();
|
||||
char* data = new char [size];
|
||||
memcpy(data, body.str().data(), size);
|
||||
memcpy(data, body.str().data(), body_size);
|
||||
// Insert the image data.
|
||||
memcpy(data + body_size, image->getData(), image->getDataSize());
|
||||
memcpy(data + body_size + image->getDataSize(), footer.str().data(), footer_size);
|
||||
|
||||
// Send request, successful upload will trigger posting metadata.
|
||||
LLHTTPClient::postRaw(url, data, size, new LLWebProfileResponders::PostImageResponder(), headers);
|
||||
LLHTTPClient::postRaw(url, data, size, new LLWebProfileResponders::PostImageResponder(), headers/*,*/ DEBUG_CURLIO_PARAM(debug_off), no_keep_alive);
|
||||
}
|
||||
|
||||
// static
|
||||
|
||||
@@ -475,7 +475,7 @@ void LLWLParamManager::propagateParameters(void)
|
||||
void LLWLParamManager::update(LLViewerCamera * cam)
|
||||
{
|
||||
LLFastTimer ftm(FTM_UPDATE_WLPARAM);
|
||||
|
||||
|
||||
// update clouds, sun, and general
|
||||
mCurParams.updateCloudScrolling();
|
||||
|
||||
|
||||
@@ -682,6 +682,12 @@ void LLWorld::updateRegions(F32 max_update_time)
|
||||
|
||||
void LLWorld::updateParticles()
|
||||
{
|
||||
static const LLCachedControl<bool> freeze_time("FreezeTime",false);
|
||||
if (freeze_time)
|
||||
{
|
||||
// don't move particles in snapshot mode
|
||||
return;
|
||||
}
|
||||
LLViewerPartSim::getInstance()->updateSimulation();
|
||||
}
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
name="floater_merchant_outbox"
|
||||
save_rect="true"
|
||||
save_visibility="false"
|
||||
rect_control="FloaterOutboxRect"
|
||||
reuse_instance="true"
|
||||
title="Merchant Outbox"
|
||||
width="333">
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
|
||||
<floater can_close="true" can_drag_on_left="false" can_minimize="false"
|
||||
can_resize="true" height="380" min_height="380" min_width="450"
|
||||
name="Postcard" title="Email Snapshot" width="450">
|
||||
can_resize="true" height="346" min_height="346" min_width="450"
|
||||
name="Postcard" title="Email Snapshot" width="450"
|
||||
rect_control="FloaterSnapshotPostcardRect">
|
||||
<text bottom="-35" follows="top|left" font="SansSerif" left="12" name="to_label">
|
||||
Recipient's Email:
|
||||
</text>
|
||||
@@ -34,10 +35,6 @@
|
||||
max_length="700" name="msg_form" width="420" spell_check="true">
|
||||
Type your message here.
|
||||
</text_editor>
|
||||
<text bottom_delta="-37" follows="left|bottom" font="SansSerifSmall" left="12"
|
||||
name="fine_print">
|
||||
If your recipient joins our universe, you'll get a referral bonus.
|
||||
</text>
|
||||
<button bottom_delta="-32" follows="right|bottom" height="20" label="Cancel"
|
||||
name="cancel_btn" right="-10" width="100" />
|
||||
<button bottom_delta="0" follows="right|bottom" height="20" label="Send"
|
||||
|
||||
@@ -1,58 +1,97 @@
|
||||
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
|
||||
<floater bottom="-300" can_close="true" can_drag_on_left="false" can_minimize="false"
|
||||
can_resize="false" follows="left|top" height="566" name="Snapshot"
|
||||
rect_control="FloaterSnapshotRect" title="Snapshot Preview" width="215">
|
||||
<text bottom_delta="-40" follows="top|left" height="15" left="10" name="type_label"
|
||||
width="195">
|
||||
Snapshot destination
|
||||
</text>
|
||||
<radio_group bottom_delta="-65" follows="left|top" height="60" label="Snapshot type"
|
||||
left="10" name="snapshot_type_radio" width="195">
|
||||
<radio_item bottom="-19" height="16" name="postcard">
|
||||
Send via email
|
||||
</radio_item>
|
||||
<radio_item bottom="-38" height="16" name="texture">
|
||||
Save to your inventory ([UPLOADFEE])
|
||||
</radio_item>
|
||||
<radio_item bottom="-57" height="16" name="local">
|
||||
Save to your hard drive
|
||||
</radio_item>
|
||||
</radio_group>
|
||||
<text bottom="-236" follows="left|top" height="25" left="10" name="file_size_label"
|
||||
width="195">
|
||||
can_resize="false" follows="left|top" height="629" name="Snapshot"
|
||||
rect_control="FloaterSnapshotRect" title="Snapshot Preview" width="219">
|
||||
<text bottom="-201" right="-6" height="25" name="file_size_label" halign="right" width="120">
|
||||
File size: [SIZE] KB
|
||||
</text>
|
||||
<button bottom="-246" follows="left|top" height="20" label="Refresh Snapshot" left="10"
|
||||
name="new_snapshot_btn" width="195" />
|
||||
<button bottom_delta="-22" follows="left|top" height="20" label="Send" left="10"
|
||||
<text bottom="-195" height="15" left="10" name="type_label" halign="left">
|
||||
Target
|
||||
</text>
|
||||
<radio_group bottom_delta="-79" follows="left|top" height="79" label="Snapshot type"
|
||||
left="10" name="snapshot_type_radio" width="200">
|
||||
<radio_item bottom="-19" height="16" name="feed">
|
||||
Post to my.secondlife.com feed
|
||||
</radio_item>
|
||||
<radio_item bottom="-38" height="16" name="postcard">
|
||||
Send via email
|
||||
</radio_item>
|
||||
<radio_item bottom="-57" height="16" name="texture">
|
||||
Save to my inventory ([UPLOADFEE])
|
||||
</radio_item>
|
||||
<radio_item bottom="-76" height="16" name="local">
|
||||
Save to my hard drive
|
||||
</radio_item>
|
||||
</radio_group>
|
||||
<button bottom_delta="-28" follows="left|top" height="20" label="Refresh snapshot" left="10"
|
||||
name="new_snapshot_btn" width="115" tool_tip="Make a snapshot of the current view. Use the save and/or upload button to actually save it. The latest snapshot is shown in the thumbnail. In Freeze Time mode a preview of the new snapshot is also shown full screen (note that this has NOT the same quality as the real thing that will be saved: it is downscaled from the actual formatted image to a power of two with a max. resolution of 1024x1024, in order to be displayed in openGL and then probably stretched again to fill your screen). Press ESC to go back to Freeze Time." />
|
||||
<button bottom_delta="0" follows="left|top" height="20" label="Freeze time" left="129"
|
||||
name="freeze_time_btn" width="80" tool_tip="Freeze time and show a fullscreen preview. Allows to cam around as if time is frozen and make multiple snapshots of the same scene. Press ESC to undo!" />
|
||||
<button bottom_delta="-22" follows="left|top" height="20" label="Upload" left="10"
|
||||
name="feed_btn" width="105" />
|
||||
<button bottom_delta="0" follows="left|top" height="20" label="Send" left="10"
|
||||
name="send_btn" width="105" />
|
||||
<button bottom_delta="0" follows="left|top" height="20" label="Save ([UPLOADFEE])" left="10"
|
||||
<button bottom_delta="0" follows="left|top" height="20" label="Upload ([UPLOADFEE])" left="10"
|
||||
name="upload_btn" width="105" />
|
||||
<flyout_button bottom_delta="0" follows="left|top" height="20" label="Save" left="10"
|
||||
list_position="below" mouse_opaque="true" name="save_btn" tool_tip="Save image to a file"
|
||||
width="105">
|
||||
<flyout_button bottom_delta="-2" follows="left|top" height="20" label="Save" left="10"
|
||||
list_position="below" mouse_opaque="true" name="save_btn" tool_tip="Save image to a file" width="105">
|
||||
<flyout_button_item value="save" name="save_item">Save</flyout_button_item>
|
||||
<flyout_button_item value="saveas" name="saveas_item">Save As...</flyout_button_item>
|
||||
</flyout_button>
|
||||
<button bottom_delta="0" follows="left|top" height="20" label="Cancel" left="120"
|
||||
name="discard_btn" width="85" />
|
||||
<button bottom="-290" follows="left|top" font="SansSerifSmall" halign="center"
|
||||
height="20" label="More >>" left="10"
|
||||
</flyout_button>
|
||||
<combo_box bottom_delta="-4" follows="left|top" height="20" label="Format" left="139"
|
||||
name="local_format_combo" width="70">
|
||||
<combo_item name="PNG">
|
||||
PNG
|
||||
</combo_item>
|
||||
<combo_item name="JPEG">
|
||||
JPEG
|
||||
</combo_item>
|
||||
<combo_item name="BMP">
|
||||
BMP
|
||||
</combo_item>
|
||||
</combo_box>
|
||||
<button bottom_delta="-22" follows="left|top" font="SansSerifSmall" halign="center"
|
||||
height="20" label="Advanced>>" left="10"
|
||||
mouse_opaque="true" name="more_btn" scale_image="TRUE"
|
||||
tool_tip="Advanced Options" width="80" />
|
||||
tool_tip="Advanced Options. Default uses current window size (500x375 for profile feed)." width="72" />
|
||||
<button bottom_delta="0" follows="left|top" font="SansSerifSmall" halign="center"
|
||||
height="20" label="<< Less" left_delta="0"
|
||||
height="20" label="<<Default" left_delta="0"
|
||||
mouse_opaque="true" name="less_btn" scale_image="TRUE"
|
||||
tool_tip="Advanced Options" width="80" />
|
||||
<text bottom_delta="-20" follows="top|left" height="15" left="10" name="type_label2"
|
||||
width="115">
|
||||
Size
|
||||
</text>
|
||||
<text bottom_delta="0" follows="top|left" height="15" left="130" name="format_label"
|
||||
width="70">
|
||||
Format
|
||||
</text>
|
||||
tool_tip="Advanced Options. Default uses current window size (500x375 for profile feed)." width="72" />
|
||||
<slider bottom_delta="0" decimal_digits="0" follows="left|top" height="15"
|
||||
increment="1" initial_val="75" left="80"
|
||||
max_val="100" min_val="0" name="image_quality_slider" width="150" />
|
||||
<text bottom_delta="-20" follows="top|left" height="15" left="10" name="type_label2" width="115">
|
||||
Target size
|
||||
</text>
|
||||
<combo_box bottom_delta="-22" follows="left|top" height="20" label="Resolution" left="10"
|
||||
name="feed_size_combo" width="125">
|
||||
<combo_item name="CurrentWindow" value="[i0,i0]">
|
||||
Current Window
|
||||
</combo_item>
|
||||
<combo_item name="500x500" value="[i500,i500]">
|
||||
500x500 (1:1)
|
||||
</combo_item>
|
||||
<combo_item name="500x375" value="[i500,i375]">
|
||||
500x375 (4:3)
|
||||
</combo_item>
|
||||
<combo_item name="500x350" value="[i500,i350]">
|
||||
500x350 (10:7)
|
||||
</combo_item>
|
||||
<combo_item name="500x313" value="[i500,i313]">
|
||||
500x313 (16:10)
|
||||
</combo_item>
|
||||
<combo_item name="500x281" value="[i500,i281]">
|
||||
500x281 (16:9)
|
||||
</combo_item>
|
||||
<combo_item name="500x250" value="[i500,i250]">
|
||||
500x250 (2:1)
|
||||
</combo_item>
|
||||
<combo_item name="Custom" value="[i-1,i-1]">
|
||||
Custom
|
||||
</combo_item>
|
||||
</combo_box>
|
||||
<combo_box bottom_delta="0" follows="left|top" height="20" label="Resolution" left="10"
|
||||
name="postcard_size_combo" width="115">
|
||||
<combo_item name="CurrentWindow" value="[i0,i0]">
|
||||
Current Window
|
||||
@@ -60,6 +99,9 @@
|
||||
<combo_item name="640x480" value="[i640,i480]">
|
||||
640x480
|
||||
</combo_item>
|
||||
<combo_item name="700x525" value="[i700,i525]">
|
||||
700x525
|
||||
</combo_item>
|
||||
<combo_item name="800x600" value="[i800,i600]">
|
||||
800x600
|
||||
</combo_item>
|
||||
@@ -72,20 +114,32 @@
|
||||
</combo_box>
|
||||
<combo_box bottom_delta="0" follows="left|top" height="20" label="Resolution" left="10"
|
||||
name="texture_size_combo" width="115">
|
||||
<combo_item name="CurrentWindow" value="[i0,i0]">
|
||||
Current Window
|
||||
<combo_item name="512x512" value="[i512,i512]">
|
||||
512x512 (1:1)
|
||||
</combo_item>
|
||||
<combo_item name="Small(128x128)" value="[i128,i128]">
|
||||
Small (128x128)
|
||||
<combo_item name="256x256" value="[i256,i256]">
|
||||
256x256 (1:1)
|
||||
</combo_item>
|
||||
<combo_item name="Medium(256x256)" value="[i256,i256]">
|
||||
Medium (256x256)
|
||||
<combo_item name="128x128" value="[i128,i128]">
|
||||
128x128 (1:1)
|
||||
</combo_item>
|
||||
<combo_item name="Large(512x512)" value="[i512,i512]">
|
||||
Large (512x512)
|
||||
<combo_item name="512x256" value="[i512,i256]">
|
||||
512x256 (2:1)
|
||||
</combo_item>
|
||||
<combo_item name="Custom" value="[i-1,i-1]">
|
||||
Custom
|
||||
<combo_item name="256x128" value="[i256,i128]">
|
||||
256x128 (2:1)
|
||||
</combo_item>
|
||||
<combo_item name="256x512" value="[i256,i512]">
|
||||
256x512 (1:2)
|
||||
</combo_item>
|
||||
<combo_item name="128x256" value="[i128,i256]">
|
||||
128x256 (1:2)
|
||||
</combo_item>
|
||||
<combo_item name="512x128" value="[i512,i128]">
|
||||
512x128 (4:1)
|
||||
</combo_item>
|
||||
<combo_item name="128x512" value="[i128,i512]">
|
||||
128x512 (1:4)
|
||||
</combo_item>
|
||||
</combo_box>
|
||||
<combo_box bottom_delta="0" follows="left|top" height="20" label="Resolution" left="10"
|
||||
@@ -105,45 +159,122 @@
|
||||
<combo_item name="1024x768" value="[i1024,i768]">
|
||||
1024x768
|
||||
</combo_item>
|
||||
<combo_item name="1280x960" value="[i1280,i960]">
|
||||
1280x960
|
||||
</combo_item>
|
||||
<combo_item name="1280x1024" value="[i1280,i1024]">
|
||||
1280x1024
|
||||
</combo_item>
|
||||
<combo_item name="1600x1200" value="[i1600,i1200]">
|
||||
1600x1200
|
||||
</combo_item>
|
||||
<combo_item name="1680x1050" value="[i1680,i1050]">
|
||||
1680x1050
|
||||
</combo_item>
|
||||
<combo_item name="Custom" value="[i-1,i-1]">
|
||||
Custom
|
||||
</combo_item>
|
||||
</combo_box>
|
||||
<combo_box bottom_delta="0" follows="left|top" height="20" label="Format" left="130"
|
||||
name="local_format_combo" width="70">
|
||||
<combo_item name="PNG">
|
||||
PNG
|
||||
</combo_item>
|
||||
<combo_item name="JPEG">
|
||||
JPEG
|
||||
</combo_item>
|
||||
<combo_item name="BMP">
|
||||
BMP
|
||||
</combo_item>
|
||||
</combo_box>
|
||||
|
||||
<spinner bottom_delta="-25" decimal_digits="0" follows="left|top" height="20"
|
||||
increment="32" label="Width" label_width="30" left="10" max_val="6016"
|
||||
min_val="32" name="snapshot_width" width="95" allow_text_entry="false"/>
|
||||
<spinner bottom_delta="0" decimal_digits="0" follows="left|top" height="20"
|
||||
increment="32" label="Height" label_width="35" left="110" max_val="6016"
|
||||
min_val="32" name="snapshot_height" width="95" allow_text_entry="false"/>
|
||||
<check_box bottom_delta="-20" follows="left|top" label="Constrain Proportions" left="10"
|
||||
name="keep_aspect_check" />
|
||||
<slider bottom_delta="-20" decimal_digits="0" follows="left|top" height="15"
|
||||
increment="1" initial_val="75" label="Image Quality" left="10"
|
||||
max_val="100" min_val="0" name="image_quality_slider" width="210" />
|
||||
<text bottom_delta="-28" follows="left|top" height="20" left="10"
|
||||
<text bottom_delta="-18" follows="top|left" height="15" left="10" name="type_label3"
|
||||
width="115">
|
||||
Target aspect ratio
|
||||
</text>
|
||||
<combo_box bottom_delta="-22" follows="left|top" height="20" label="Aspect" left="10"
|
||||
name="feed_aspect_combo" width="115">
|
||||
<combo_item name="Default" value="-2">
|
||||
Default
|
||||
</combo_item>
|
||||
<combo_item name="Custom" value="-1">
|
||||
Custom
|
||||
</combo_item>
|
||||
</combo_box>
|
||||
<combo_box bottom_delta="0" follows="left|top" height="20" label="Aspect" left="10"
|
||||
name="postcard_aspect_combo" width="115">
|
||||
<combo_item name="Default" value="-2">
|
||||
Default
|
||||
</combo_item>
|
||||
<combo_item name="Custom" value="-1">
|
||||
Custom
|
||||
</combo_item>
|
||||
</combo_box>
|
||||
<combo_box bottom_delta="0" follows="left|top" height="20" label="Aspect" left="10"
|
||||
name="texture_aspect_combo" width="115">
|
||||
<combo_item name="CurrentWindow" value="0">
|
||||
Current Window
|
||||
</combo_item>
|
||||
<combo_item name="1:1" value="1">
|
||||
1:1
|
||||
</combo_item>
|
||||
<combo_item name="4:3" value="1.33333">
|
||||
4:3 (profile)
|
||||
</combo_item>
|
||||
<combo_item name="10:7" value="1.42857">
|
||||
10:7
|
||||
</combo_item>
|
||||
<combo_item name="3:2" value="1.5">
|
||||
3:2
|
||||
</combo_item>
|
||||
<combo_item name="16:10" value="1.6">
|
||||
16:10
|
||||
</combo_item>
|
||||
<combo_item name="16:9" value="1.77778">
|
||||
16:9
|
||||
</combo_item>
|
||||
<combo_item name="2:1" value="2">
|
||||
2:1
|
||||
</combo_item>
|
||||
<combo_item name="Custom" value="-1">
|
||||
Custom
|
||||
</combo_item>
|
||||
</combo_box>
|
||||
<combo_box bottom_delta="0" follows="left|top" height="20" label="Aspect" left="10"
|
||||
name="local_aspect_combo" width="115">
|
||||
<combo_item name="Default" value="-2">
|
||||
Default
|
||||
</combo_item>
|
||||
<combo_item name="CurrentWindow" value="0">
|
||||
Current Window
|
||||
</combo_item>
|
||||
<combo_item name="1:1" value="1">
|
||||
1:1
|
||||
</combo_item>
|
||||
<combo_item name="4:3" value="1.33333">
|
||||
4:3 (profile)
|
||||
</combo_item>
|
||||
<combo_item name="10:7" value="1.42857">
|
||||
10:7
|
||||
</combo_item>
|
||||
<combo_item name="3:2" value="1.5">
|
||||
3:2
|
||||
</combo_item>
|
||||
<combo_item name="16:10" value="1.6">
|
||||
16:10
|
||||
</combo_item>
|
||||
<combo_item name="16:9" value="1.77778">
|
||||
16:9
|
||||
</combo_item>
|
||||
<combo_item name="2:1" value="2">
|
||||
2:1
|
||||
</combo_item>
|
||||
<combo_item name="Custom" value="-1">
|
||||
Custom
|
||||
</combo_item>
|
||||
</combo_box>
|
||||
<spinner bottom_delta="0" decimal_digits="5" follows="left|top" height="20"
|
||||
increment="0.01" label="" left="130" max_val="32"
|
||||
min_val="0.03125" name="aspect_ratio" width="64" allow_text_entry="false"/>
|
||||
<text bottom_delta="-10" height="20" left="196" name="aspect_one_label">:1</text>
|
||||
<text bottom_delta="-20" follows="left|top" height="20" left="15"
|
||||
name="layer_type_label" width="50">
|
||||
Capture:
|
||||
</text>
|
||||
<combo_box bottom_delta="3" follows="left|top" height="20" label="Image Layers" left="60"
|
||||
<combo_box bottom_delta="3" follows="left|top" height="20" label="Image Layers" left="61"
|
||||
name="layer_types" width="145">
|
||||
<combo_item name="Colors" value="colors">
|
||||
Colors
|
||||
@@ -152,19 +283,19 @@
|
||||
Depth
|
||||
</combo_item>
|
||||
</combo_box>
|
||||
<check_box bottom_delta="-20" follows="left|top" label="Show interface in snapshot"
|
||||
left="10" name="ui_check" />
|
||||
<check_box bottom_delta="-18" follows="left|top" label="Show interface in snapshot"
|
||||
left="10" name="ui_check" tool_tip="Show the UI in the snapshot. This enforces the resolution of the snapshot to that of your current window." />
|
||||
<check_box bottom_delta="-20" follows="left|top" label="Show HUD objects in snapshot"
|
||||
left="10" name="hud_check" />
|
||||
left="10" name="hud_check" tool_tip="Show your HUD objects in the snapshot. This enforces the resolution of the snapshot to that of your current window." />
|
||||
<check_box bottom_delta="-20" follows="left|top" label="Keep open after saving" left="10"
|
||||
name="keep_open_check" />
|
||||
<check_box bottom_delta="-20" follows="left|top" label="Freeze frame (fullscreen preview)"
|
||||
left="10" name="freeze_frame_check" />
|
||||
name="keep_open_check" tool_tip="Do not close the snapshot floater after saving or uploading. This allows you to save, upload or send the SAME snapshot again with different formats and/or to a different destination." />
|
||||
<check_box bottom_delta="-20" follows="left|top" label="Open floater in Freeze Time mode"
|
||||
left="10" name="freeze_time_check" tool_tip="This allows one to quickly press cntrl-shift-S and then take your time to choose the camera position and even make multiple shots of the frozen scene." />
|
||||
<check_box bottom_delta="-20" follows="left|top" label="Auto-refresh" left="10"
|
||||
name="auto_snapshot_check" />
|
||||
name="auto_snapshot_check" tool_tip="Handy in conjunction with Freeze Time: creates a new fullscreen preview whenever you stop camming." />
|
||||
<check_box bottom_delta="-20" follows="left|top" control_name="TemporaryUpload" enabled="true"
|
||||
initial_value="false" label="Temporary Image (Free)" left="10"
|
||||
name="temp_check" tooltip="Sets the asset to be temporary, meaning it's free, but in return, only good for a short time before it ceases to exist." />
|
||||
name="temp_check" tool_tip="Uploads the texture to the sim instead of the asset server, meaning it's free but only visible in the current sim and deleted when you leave the sim." />
|
||||
<string name="unknown">
|
||||
unknown
|
||||
</string>
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
|
||||
<floater
|
||||
can_minimize="false"
|
||||
title="Post to My Profile Feed"
|
||||
height="380"
|
||||
width="370"
|
||||
layout="topleft"
|
||||
name="floater_snapshot_profile"
|
||||
rect_control="FloaterSnapshotFeedRect">
|
||||
<text_editor
|
||||
follows="bottom|left"
|
||||
bottom="40"
|
||||
hide_scrollbar="true"
|
||||
length="1"
|
||||
max_length="700"
|
||||
name="caption"
|
||||
top="-180"
|
||||
left="10"
|
||||
right="-10"
|
||||
type="string"
|
||||
word_wrap="true"/>
|
||||
<check_box
|
||||
follows="left|bottom"
|
||||
initial_value="true"
|
||||
label="Include location"
|
||||
layout="topleft"
|
||||
left_delta="0"
|
||||
name="add_location_cb"
|
||||
control_name="SnapshotFeedAddLocation"
|
||||
bottom_delta="-25" />
|
||||
<button
|
||||
follows="right|bottom"
|
||||
height="23"
|
||||
label="Cancel"
|
||||
layout="topleft"
|
||||
name="cancel_btn"
|
||||
right="-10"
|
||||
bottom="10"
|
||||
width="100"/>
|
||||
<button
|
||||
follows="right|bottom"
|
||||
height="23"
|
||||
label="Post"
|
||||
layout="topleft"
|
||||
left_delta="-106"
|
||||
name="post_btn"
|
||||
bottom_delta="0"
|
||||
width="100"/>
|
||||
</floater>
|
||||
@@ -264,6 +264,22 @@ An error occurred while updating [APP_NAME]. Please download the latest version
|
||||
yestext="Ok"/>
|
||||
</notification>
|
||||
|
||||
<notification
|
||||
icon="alertmodal.tga"
|
||||
name="EmptyFirstNameMessage"
|
||||
type="alertmodal">
|
||||
[GRIDNAME] requires a non-empty first name to login.
|
||||
Please try again.
|
||||
</notification>
|
||||
|
||||
<notification
|
||||
icon="alertmodal.tga"
|
||||
name="EmptyLastNameMessage"
|
||||
type="alertmodal">
|
||||
[GRIDNAME] requires a non-empty last name to login.
|
||||
Please try again.
|
||||
</notification>
|
||||
|
||||
<notification
|
||||
icon="alertmodal.tga"
|
||||
name="LoginFailedNoNetwork"
|
||||
@@ -309,9 +325,9 @@ You don't have permission to copy one or more of these items to the Merchant Out
|
||||
</notification>
|
||||
|
||||
<notification
|
||||
icon="OutboxStatus_Success"
|
||||
icon="alert.tga"
|
||||
name="OutboxFolderCreated"
|
||||
type="outbox">
|
||||
type="alert">
|
||||
<unique/>
|
||||
A new folder has been created for each item you have transferred into the top level of your Merchant Outbox.
|
||||
|
||||
@@ -322,9 +338,9 @@ A new folder has been created for each item you have transferred into the top le
|
||||
</notification>
|
||||
|
||||
<notification
|
||||
icon="OutboxStatus_Success"
|
||||
icon="alert.tga"
|
||||
name="OutboxImportComplete"
|
||||
type="outbox">
|
||||
type="alert">
|
||||
Success
|
||||
|
||||
All folders were successfully sent to the Marketplace.
|
||||
@@ -336,9 +352,9 @@ All folders were successfully sent to the Marketplace.
|
||||
</notification>
|
||||
|
||||
<notification
|
||||
icon="OutboxStatus_Warning"
|
||||
icon="alert.tga"
|
||||
name="OutboxImportHadErrors"
|
||||
type="outbox">
|
||||
type="alert">
|
||||
Some folders did not transfer
|
||||
|
||||
Errors occurred when some folders were sent to the Marketplace. Those folders are still in your Merchant Outbox.
|
||||
@@ -351,9 +367,9 @@ See the [[MARKETPLACE_IMPORTS_URL] error log] for more information.
|
||||
</notification>
|
||||
|
||||
<notification
|
||||
icon="OutboxStatus_Error"
|
||||
icon="alertmodal.tga"
|
||||
name="OutboxImportFailed"
|
||||
type="outbox">
|
||||
type="alertmodal">
|
||||
Transfer failed
|
||||
|
||||
No folders were sent to the Marketplace because of a system or network error. Try again later.
|
||||
@@ -364,9 +380,9 @@ No folders were sent to the Marketplace because of a system or network error. T
|
||||
</notification>
|
||||
|
||||
<notification
|
||||
icon="OutboxStatus_Error"
|
||||
icon="alertmodal.tga"
|
||||
name="OutboxInitFailed"
|
||||
type="outbox">
|
||||
type="alertmodal">
|
||||
Marketplace initialization failed
|
||||
|
||||
Initialization with the Marketplace failed because of a system or network error. Try again later.
|
||||
@@ -405,6 +421,13 @@ There was a problem writing animation data. Please try again later.
|
||||
There was a problem uploading the auction snapshot due to the following reason: [REASON]
|
||||
</notification>
|
||||
|
||||
<notification
|
||||
icon="alertmodal.tga"
|
||||
name="UploadSnapshotFail"
|
||||
type="alertmodal">
|
||||
There was a problem uploading the snapshot due to the following reason: [REASON]
|
||||
</notification>
|
||||
|
||||
<notification
|
||||
icon="alertmodal.tga"
|
||||
name="UnableToViewContentsMoreThanOne"
|
||||
@@ -937,6 +960,14 @@ Error processing snapshot data
|
||||
Error encoding snapshot.
|
||||
</notification>
|
||||
|
||||
<notification
|
||||
icon="alertmodal.tga"
|
||||
name="ErrorSizeAspectSnapshot"
|
||||
type="alertmodal">
|
||||
It is not possible to make a snapshot with this size and aspect.
|
||||
Try a smaller size or a less stretched aspect.
|
||||
</notification>
|
||||
|
||||
<notification
|
||||
icon="alertmodal.tga"
|
||||
name="ErrorUploadingPostcard"
|
||||
|
||||
@@ -196,6 +196,7 @@
|
||||
<string name="AvatarAway">Away</string>
|
||||
<string name="AvatarBusy">Busy</string>
|
||||
<string name="AvatarMuted">Muted</string>
|
||||
<string name="AvatarLangolier">Langolier</string>
|
||||
|
||||
<!-- animations -->
|
||||
<string name="anim_express_afraid">Afraid</string>
|
||||
|
||||
@@ -163,14 +163,14 @@ Asegurate que tu conexión a internet funciona correctamente.
|
||||
<usetemplate name="okcancelbuttons" notext="No mover ítem(s)" yestext="Mover ítem(s)"/>
|
||||
</notification>
|
||||
|
||||
<notification name="OutboxFolderCreated" type="outbox">
|
||||
<notification name="OutboxFolderCreated" type="alert">
|
||||
<unique/>
|
||||
Una nueva carpeta ha sido creada por cada ítem que has transferido en el nivel superior de tu Merchant Outbox.
|
||||
|
||||
<usetemplate ignoretext="Una nueva carpeta ha sido creada en el Merchant Outbox" name="okignore" yestext="OK"/>
|
||||
</notification>
|
||||
|
||||
<notification name="OutboxImportComplete" type="outbox">
|
||||
<notification name="OutboxImportComplete" type="alert">
|
||||
Completado
|
||||
|
||||
Todas las carpetas ha sido enviadas satisfactoriamente al Marketplace.
|
||||
@@ -178,7 +178,7 @@ Todas las carpetas ha sido enviadas satisfactoriamente al Marketplace.
|
||||
<usetemplate ignoretext="Todas las carpetas se han enviado al Marketplace" name="okignore" yestext="OK"/>
|
||||
</notification>
|
||||
|
||||
<notification name="OutboxImportHadErrors" type="outbox">
|
||||
<notification name="OutboxImportHadErrors" type="alert">
|
||||
Algunas carpetas no fueron transferidas
|
||||
|
||||
Ha habido errores al enviar algunas carpetas al Markeplace. Estas carpetas aún están en tu Merchant Outbox.
|
||||
@@ -188,7 +188,7 @@ Mira en el [log de errores [[MARKETPLACE_IMPORTS_URL]] para mayor información.
|
||||
<usetemplate name="okbutton" yestext="OK"/>
|
||||
</notification>
|
||||
|
||||
<notification name="OutboxImportFailed" type="outbox">
|
||||
<notification name="OutboxImportFailed" type="alertmodal">
|
||||
La transferencia ha fallado
|
||||
|
||||
No se han enviado carpetas al Marketplace debido a un error de sistema o de red. Inténtalo nuevamente más tarde.
|
||||
@@ -196,7 +196,7 @@ No se han enviado carpetas al Marketplace debido a un error de sistema o de red.
|
||||
<usetemplate name="okbutton" yestext="OK"/>
|
||||
</notification>
|
||||
|
||||
<notification name="OutboxInitFailed" type="outbox">
|
||||
<notification name="OutboxInitFailed" type="alertmodal">
|
||||
Ha fallado la inicialización del Marketplace
|
||||
|
||||
La inicialización con el Marketplace ha fallado debido a un error de sistema o de red. Inténtalo nuevamente más tarde.
|
||||
|
||||
@@ -869,16 +869,16 @@ class Linux_x86_64Manifest(LinuxManifest):
|
||||
|
||||
self.end_prefix("lib64")
|
||||
|
||||
# Vivox runtimes and libs
|
||||
if self.prefix(src="vivox-runtime/i686-linux", dst="bin"):
|
||||
self.path("SLVoice")
|
||||
self.end_prefix("bin")
|
||||
# Vivox runtimes and libs
|
||||
if self.prefix(src="vivox-runtime/i686-linux", dst="bin"):
|
||||
self.path("SLVoice")
|
||||
self.end_prefix("bin")
|
||||
|
||||
if self.prefix(src="vivox-runtime/i686-linux", dst="lib32"):
|
||||
#self.path("libalut.so")
|
||||
self.path("libortp.so")
|
||||
self.path("libvivoxsdk.so")
|
||||
self.end_prefix("lib32")
|
||||
if self.prefix(src="vivox-runtime/i686-linux", dst="lib32"):
|
||||
#self.path("libalut.so")
|
||||
self.path("libortp.so")
|
||||
self.path("libvivoxsdk.so")
|
||||
self.end_prefix("lib32")
|
||||
|
||||
# 32bit libs needed for voice
|
||||
if self.prefix("../../libraries/x86_64-linux/lib/release/32bit-compat", dst="lib32"):
|
||||
|
||||
Reference in New Issue
Block a user