summaryrefslogtreecommitdiff
path: root/indra/newview/llviewerassetupload.cpp
diff options
context:
space:
mode:
authorAnsariel <ansariel.hiller@phoenixviewer.com>2024-05-22 19:04:52 +0200
committerAnsariel <ansariel.hiller@phoenixviewer.com>2024-05-22 19:04:52 +0200
commit1b67dd855c41f5a0cda7ec2a68d98071986ca703 (patch)
treeab243607f74f78200787bba5b9b88f07ef1b966f /indra/newview/llviewerassetupload.cpp
parent6d6eabca44d08d5b97bfe3e941d2b9687c2246ea (diff)
parente1623bb276f83a43ce7a197e388720c05bdefe61 (diff)
Merge remote-tracking branch 'origin/main' into DRTVWR-600-maint-A
# Conflicts: # autobuild.xml # indra/cmake/CMakeLists.txt # indra/cmake/GoogleMock.cmake # indra/llaudio/llaudioengine_fmodstudio.cpp # indra/llaudio/llaudioengine_fmodstudio.h # indra/llaudio/lllistener_fmodstudio.cpp # indra/llaudio/lllistener_fmodstudio.h # indra/llaudio/llstreamingaudio_fmodstudio.cpp # indra/llaudio/llstreamingaudio_fmodstudio.h # indra/llcharacter/llmultigesture.cpp # indra/llcharacter/llmultigesture.h # indra/llimage/llimage.cpp # indra/llimage/llimagepng.cpp # indra/llimage/llimageworker.cpp # indra/llimage/tests/llimageworker_test.cpp # indra/llmessage/tests/llmockhttpclient.h # indra/llprimitive/llgltfmaterial.h # indra/llrender/llfontfreetype.cpp # indra/llui/llcombobox.cpp # indra/llui/llfolderview.cpp # indra/llui/llfolderviewmodel.h # indra/llui/lllineeditor.cpp # indra/llui/lllineeditor.h # indra/llui/lltextbase.cpp # indra/llui/lltextbase.h # indra/llui/lltexteditor.cpp # indra/llui/lltextvalidate.cpp # indra/llui/lltextvalidate.h # indra/llui/lluictrl.h # indra/llui/llview.cpp # indra/llwindow/llwindowmacosx.cpp # indra/newview/app_settings/settings.xml # indra/newview/llappearancemgr.cpp # indra/newview/llappearancemgr.h # indra/newview/llavatarpropertiesprocessor.cpp # indra/newview/llavatarpropertiesprocessor.h # indra/newview/llbreadcrumbview.cpp # indra/newview/llbreadcrumbview.h # indra/newview/llbreastmotion.cpp # indra/newview/llbreastmotion.h # indra/newview/llconversationmodel.h # indra/newview/lldensityctrl.cpp # indra/newview/lldensityctrl.h # indra/newview/llface.inl # indra/newview/llfloatereditsky.cpp # indra/newview/llfloatereditwater.cpp # indra/newview/llfloateremojipicker.h # indra/newview/llfloaterimsessiontab.cpp # indra/newview/llfloaterprofiletexture.cpp # indra/newview/llfloaterprofiletexture.h # indra/newview/llgesturemgr.cpp # indra/newview/llgesturemgr.h # indra/newview/llimpanel.cpp # indra/newview/llimpanel.h # indra/newview/llinventorybridge.cpp # indra/newview/llinventorybridge.h # indra/newview/llinventoryclipboard.cpp # indra/newview/llinventoryclipboard.h # indra/newview/llinventoryfunctions.cpp # indra/newview/llinventoryfunctions.h # indra/newview/llinventorygallery.cpp # indra/newview/lllistbrowser.cpp # indra/newview/lllistbrowser.h # indra/newview/llpanelobjectinventory.cpp # indra/newview/llpanelprofile.cpp # indra/newview/llpanelprofile.h # indra/newview/llpreviewgesture.cpp # indra/newview/llsavedsettingsglue.cpp # indra/newview/llsavedsettingsglue.h # indra/newview/lltooldraganddrop.cpp # indra/newview/llurllineeditorctrl.cpp # indra/newview/llvectorperfoptions.cpp # indra/newview/llvectorperfoptions.h # indra/newview/llviewerparceloverlay.cpp # indra/newview/llviewertexlayer.cpp # indra/newview/llviewertexturelist.cpp # indra/newview/macmain.h # indra/test/test.cpp
Diffstat (limited to 'indra/newview/llviewerassetupload.cpp')
-rw-r--r--indra/newview/llviewerassetupload.cpp2064
1 files changed, 1032 insertions, 1032 deletions
diff --git a/indra/newview/llviewerassetupload.cpp b/indra/newview/llviewerassetupload.cpp
index 1bf0c9ac66..76592fd67b 100644
--- a/indra/newview/llviewerassetupload.cpp
+++ b/indra/newview/llviewerassetupload.cpp
@@ -1,1032 +1,1032 @@
-/**
-* @file llviewerassetupload.cpp
-* @author optional
-* @brief brief description of the file
-*
-* $LicenseInfo:firstyear=2011&license=viewerlgpl$
-* Second Life Viewer Source Code
-* Copyright (C) 2011, Linden Research, Inc.
-*
-* This library is free software; you can redistribute it and/or
-* modify it under the terms of the GNU Lesser General Public
-* License as published by the Free Software Foundation;
-* version 2.1 of the License only.
-*
-* This library is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-* Lesser General Public License for more details.
-*
-* You should have received a copy of the GNU Lesser General Public
-* License along with this library; if not, write to the Free Software
-* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-*
-* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
-* $/LicenseInfo$
-*/
-
-#include "llviewerprecompiledheaders.h"
-
-#include "linden_common.h"
-#include "llviewertexturelist.h"
-#include "llimage.h"
-#include "lltrans.h"
-#include "lluuid.h"
-#include "llvorbisencode.h"
-#include "lluploaddialog.h"
-#include "llnotificationsutil.h"
-#include "llagent.h"
-#include "llfloaterreg.h"
-#include "llfloatersnapshot.h"
-#include "llstatusbar.h"
-#include "llinventorypanel.h"
-#include "llsdutil.h"
-#include "llviewerassetupload.h"
-#include "llappviewer.h"
-#include "llviewerstats.h"
-#include "llfilesystem.h"
-#include "llgesturemgr.h"
-#include "llpreviewnotecard.h"
-#include "llpreviewgesture.h"
-#include "llcoproceduremanager.h"
-#include "llthread.h"
-#include "llkeyframemotion.h"
-#include "lldatapacker.h"
-#include "llvoavatarself.h"
-
-void dialog_refresh_all();
-
-static const U32 LL_ASSET_UPLOAD_TIMEOUT_SEC = 60;
-
-LLResourceUploadInfo::LLResourceUploadInfo(LLTransactionID transactId,
- LLAssetType::EType assetType, std::string name, std::string description,
- S32 compressionInfo, LLFolderType::EType destinationType,
- LLInventoryType::EType inventoryType, U32 nextOWnerPerms,
- U32 groupPerms, U32 everyonePerms, S32 expectedCost, bool showInventory) :
- mTransactionId(transactId),
- mAssetType(assetType),
- mName(name),
- mDescription(description),
- mCompressionInfo(compressionInfo),
- mDestinationFolderType(destinationType),
- mInventoryType(inventoryType),
- mNextOwnerPerms(nextOWnerPerms),
- mGroupPerms(groupPerms),
- mEveryonePerms(everyonePerms),
- mExpectedUploadCost(expectedCost),
- mShowInventory(showInventory),
- mFolderId(LLUUID::null),
- mItemId(LLUUID::null),
- mAssetId(LLAssetID::null)
-{ }
-
-
-LLResourceUploadInfo::LLResourceUploadInfo(std::string name,
- std::string description, S32 compressionInfo,
- LLFolderType::EType destinationType, LLInventoryType::EType inventoryType,
- U32 nextOWnerPerms, U32 groupPerms, U32 everyonePerms, S32 expectedCost, bool showInventory) :
- mName(name),
- mDescription(description),
- mCompressionInfo(compressionInfo),
- mDestinationFolderType(destinationType),
- mInventoryType(inventoryType),
- mNextOwnerPerms(nextOWnerPerms),
- mGroupPerms(groupPerms),
- mEveryonePerms(everyonePerms),
- mExpectedUploadCost(expectedCost),
- mShowInventory(showInventory),
- mTransactionId(),
- mAssetType(LLAssetType::AT_NONE),
- mFolderId(LLUUID::null),
- mItemId(LLUUID::null),
- mAssetId(LLAssetID::null)
-{
- mTransactionId.generate();
-}
-
-LLResourceUploadInfo::LLResourceUploadInfo(LLAssetID assetId, LLAssetType::EType assetType, std::string name) :
- mAssetId(assetId),
- mAssetType(assetType),
- mName(name),
- mDescription(),
- mCompressionInfo(0),
- mDestinationFolderType(LLFolderType::FT_NONE),
- mInventoryType(LLInventoryType::IT_NONE),
- mNextOwnerPerms(0),
- mGroupPerms(0),
- mEveryonePerms(0),
- mExpectedUploadCost(0),
- mShowInventory(true),
- mTransactionId(),
- mFolderId(LLUUID::null),
- mItemId(LLUUID::null)
-{
-}
-
-LLSD LLResourceUploadInfo::prepareUpload()
-{
- if (mAssetId.isNull())
- generateNewAssetId();
-
- incrementUploadStats();
- assignDefaults();
-
- return LLSD().with("success", LLSD::Boolean(true));
-}
-
-std::string LLResourceUploadInfo::getAssetTypeString() const
-{
- return LLAssetType::lookup(mAssetType);
-}
-
-std::string LLResourceUploadInfo::getInventoryTypeString() const
-{
- return LLInventoryType::lookup(mInventoryType);
-}
-
-LLSD LLResourceUploadInfo::generatePostBody()
-{
- LLSD body;
-
- body["folder_id"] = mFolderId;
- body["asset_type"] = getAssetTypeString();
- body["inventory_type"] = getInventoryTypeString();
- body["name"] = mName;
- body["description"] = mDescription;
- body["next_owner_mask"] = LLSD::Integer(mNextOwnerPerms);
- body["group_mask"] = LLSD::Integer(mGroupPerms);
- body["everyone_mask"] = LLSD::Integer(mEveryonePerms);
-
- return body;
-
-}
-
-void LLResourceUploadInfo::logPreparedUpload()
-{
- LL_INFOS() << "*** Uploading: " << std::endl <<
- "Type: " << LLAssetType::lookup(mAssetType) << std::endl <<
- "UUID: " << mAssetId.asString() << std::endl <<
- "Name: " << mName << std::endl <<
- "Desc: " << mDescription << std::endl <<
- "Expected Upload Cost: " << mExpectedUploadCost << std::endl <<
- "Folder: " << mFolderId << std::endl <<
- "Asset Type: " << LLAssetType::lookup(mAssetType) << LL_ENDL;
-}
-
-LLUUID LLResourceUploadInfo::finishUpload(LLSD &result)
-{
- if (getFolderId().isNull())
- {
- return LLUUID::null;
- }
-
- U32 permsEveryone = PERM_NONE;
- U32 permsGroup = PERM_NONE;
- U32 permsNextOwner = PERM_ALL;
-
- if (result.has("new_next_owner_mask"))
- {
- // The server provided creation perms so use them.
- // Do not assume we got the perms we asked for in
- // since the server may not have granted them all.
- permsEveryone = result["new_everyone_mask"].asInteger();
- permsGroup = result["new_group_mask"].asInteger();
- permsNextOwner = result["new_next_owner_mask"].asInteger();
- }
- else
- {
- // The server doesn't provide creation perms
- // so use old assumption-based perms.
- if (getAssetTypeString() != "snapshot")
- {
- permsNextOwner = PERM_MOVE | PERM_TRANSFER;
- }
- }
-
- LLPermissions new_perms;
- new_perms.init(
- gAgent.getID(),
- gAgent.getID(),
- LLUUID::null,
- LLUUID::null);
-
- new_perms.initMasks(
- PERM_ALL,
- PERM_ALL,
- permsEveryone,
- permsGroup,
- permsNextOwner);
-
- U32 flagsInventoryItem = 0;
- if (result.has("inventory_flags"))
- {
- flagsInventoryItem = static_cast<U32>(result["inventory_flags"].asInteger());
- if (flagsInventoryItem != 0)
- {
- LL_INFOS() << "inventory_item_flags " << flagsInventoryItem << LL_ENDL;
- }
- }
- S32 creationDate = time_corrected();
-
- LLUUID serverInventoryItem = result["new_inventory_item"].asUUID();
- LLUUID serverAssetId = result["new_asset"].asUUID();
-
- LLPointer<LLViewerInventoryItem> item = new LLViewerInventoryItem(
- serverInventoryItem,
- getFolderId(),
- new_perms,
- serverAssetId,
- getAssetType(),
- getInventoryType(),
- getName(),
- getDescription(),
- LLSaleInfo::DEFAULT,
- flagsInventoryItem,
- creationDate);
-
- gInventory.updateItem(item);
- gInventory.notifyObservers();
-
- return serverInventoryItem;
-}
-
-
-LLAssetID LLResourceUploadInfo::generateNewAssetId()
-{
- if (gDisconnected)
- {
- LLAssetID rv;
-
- rv.setNull();
- return rv;
- }
- mAssetId = mTransactionId.makeAssetID(gAgent.getSecureSessionID());
-
- return mAssetId;
-}
-
-void LLResourceUploadInfo::incrementUploadStats() const
-{
- if (LLAssetType::AT_SOUND == mAssetType)
- {
- add(LLStatViewer::UPLOAD_SOUND, 1);
- }
- else if (LLAssetType::AT_TEXTURE == mAssetType)
- {
- add(LLStatViewer::UPLOAD_TEXTURE, 1);
- }
- else if (LLAssetType::AT_ANIMATION == mAssetType)
- {
- add(LLStatViewer::ANIMATION_UPLOADS, 1);
- }
-}
-
-void LLResourceUploadInfo::assignDefaults()
-{
- if (LLInventoryType::IT_NONE == mInventoryType)
- {
- mInventoryType = LLInventoryType::defaultForAssetType(mAssetType);
- }
- LLStringUtil::stripNonprintable(mName);
- LLStringUtil::stripNonprintable(mDescription);
-
- if (mName.empty())
- {
- mName = "(No Name)";
- }
- if (mDescription.empty())
- {
- mDescription = "(No Description)";
- }
-
- mFolderId = gInventory.findUserDefinedCategoryUUIDForType(
- (mDestinationFolderType == LLFolderType::FT_NONE) ?
- (LLFolderType::EType)mAssetType : mDestinationFolderType);
-}
-
-std::string LLResourceUploadInfo::getDisplayName() const
-{
- return (mName.empty()) ? mAssetId.asString() : mName;
-};
-
-bool LLResourceUploadInfo::findAssetTypeOfExtension(const std::string& exten, LLAssetType::EType& asset_type)
-{
- U32 codec;
- return findAssetTypeAndCodecOfExtension(exten, asset_type, codec, false);
-}
-
-// static
-bool LLResourceUploadInfo::findAssetTypeAndCodecOfExtension(const std::string& exten, LLAssetType::EType& asset_type, U32& codec, bool bulk_upload)
-{
- bool succ = false;
- std::string exten_lc(exten);
- LLStringUtil::toLower(exten_lc);
- codec = LLImageBase::getCodecFromExtension(exten_lc);
- if (codec != IMG_CODEC_INVALID)
- {
- asset_type = LLAssetType::AT_TEXTURE;
- succ = true;
- }
- else if (exten_lc == "wav")
- {
- asset_type = LLAssetType::AT_SOUND;
- succ = true;
- }
- else if (exten_lc == "anim")
- {
- asset_type = LLAssetType::AT_ANIMATION;
- succ = true;
- }
- else if (!bulk_upload && (exten_lc == "bvh"))
- {
- asset_type = LLAssetType::AT_ANIMATION;
- succ = true;
- }
-
- return succ;
-}
-
-//=========================================================================
-LLNewFileResourceUploadInfo::LLNewFileResourceUploadInfo(
- std::string fileName,
- std::string name,
- std::string description,
- S32 compressionInfo,
- LLFolderType::EType destinationType,
- LLInventoryType::EType inventoryType,
- U32 nextOWnerPerms,
- U32 groupPerms,
- U32 everyonePerms,
- S32 expectedCost,
- bool show_inventory) :
- LLResourceUploadInfo(name, description, compressionInfo,
- destinationType, inventoryType,
- nextOWnerPerms, groupPerms, everyonePerms, expectedCost, show_inventory),
- mFileName(fileName)
-{
-}
-
-LLSD LLNewFileResourceUploadInfo::prepareUpload()
-{
- if (getAssetId().isNull())
- generateNewAssetId();
-
- LLSD result = exportTempFile();
- if (result.has("error"))
- return result;
-
- return LLResourceUploadInfo::prepareUpload();
-}
-
-LLSD LLNewFileResourceUploadInfo::exportTempFile()
-{
- std::string filename = gDirUtilp->getTempFilename();
-
- std::string exten = gDirUtilp->getExtension(getFileName());
-
- LLAssetType::EType assetType = LLAssetType::AT_NONE;
- U32 codec = IMG_CODEC_INVALID;
- bool found_type = findAssetTypeAndCodecOfExtension(exten, assetType, codec);
-
- std::string errorMessage;
- std::string errorLabel;
-
- bool error = false;
-
- if (exten.empty())
- {
- std::string shortName = gDirUtilp->getBaseFileName(filename);
-
- // No extension
- errorMessage = llformat(
- "No file extension for the file: '%s'\nPlease make sure the file has a correct file extension",
- shortName.c_str());
- errorLabel = "NoFileExtension";
- error = true;
- }
- else if (!found_type)
- {
- // Unknown extension
- errorMessage = llformat(LLTrans::getString("UnknownFileExtension").c_str(), exten.c_str());
- errorLabel = "ErrorMessage";
- error = true;;
- }
- else if (assetType == LLAssetType::AT_TEXTURE)
- {
- // It's an image file, the upload procedure is the same for all
- if (!LLViewerTextureList::createUploadFile(getFileName(), filename, codec))
- {
- errorMessage = llformat("Problem with file %s:\n\n%s\n",
- getFileName().c_str(), LLImage::getLastError().c_str());
- errorLabel = "ProblemWithFile";
- error = true;
- }
- }
- else if (assetType == LLAssetType::AT_SOUND)
- {
- S32 encodeResult = 0;
-
- LL_INFOS() << "Attempting to encode wav as an ogg file" << LL_ENDL;
-
- encodeResult = encode_vorbis_file(getFileName(), filename);
-
- if (LLVORBISENC_NOERR != encodeResult)
- {
- switch (encodeResult)
- {
- case LLVORBISENC_DEST_OPEN_ERR:
- errorMessage = llformat("Couldn't open temporary compressed sound file for writing: %s\n", filename.c_str());
- errorLabel = "CannotOpenTemporarySoundFile";
- break;
-
- default:
- errorMessage = llformat("Unknown vorbis encode failure on: %s\n", getFileName().c_str());
- errorLabel = "UnknownVorbisEncodeFailure";
- break;
- }
- error = true;
- }
- }
- else if (exten == "bvh")
- {
- errorMessage = llformat("We do not currently support bulk upload of animation files\n");
- errorLabel = "DoNotSupportBulkAnimationUpload";
- error = true;
- }
- else if (exten == "anim")
- {
- // Default unless everything succeeds
- errorLabel = "ProblemWithFile";
- error = true;
-
- // read from getFileName()
- LLAPRFile infile;
- infile.open(getFileName(),LL_APR_RB);
- if (!infile.getFileHandle())
- {
- LL_WARNS() << "Couldn't open file for reading: " << getFileName() << LL_ENDL;
- errorMessage = llformat("Failed to open animation file %s\n", getFileName().c_str());
- }
- else
- {
- S32 size = LLAPRFile::size(getFileName());
- U8* buffer = new U8[size];
- S32 size_read = infile.read(buffer,size);
- if (size_read != size)
- {
- errorMessage = llformat("Failed to read animation file %s: wanted %d bytes, got %d\n", getFileName().c_str(), size, size_read);
- }
- else
- {
- LLDataPackerBinaryBuffer dp(buffer, size);
- LLKeyframeMotion *motionp = new LLKeyframeMotion(getAssetId());
- motionp->setCharacter(gAgentAvatarp);
- if (motionp->deserialize(dp, getAssetId(), false))
- {
- // write to temp file
- bool succ = motionp->dumpToFile(filename);
- if (succ)
- {
- assetType = LLAssetType::AT_ANIMATION;
- errorLabel = "";
- error = false;
- }
- else
- {
- errorMessage = "Failed saving temporary animation file";
- }
- }
- else
- {
- errorMessage = "Failed reading animation file";
- }
- }
- }
- }
- else
- {
- // Unknown extension
- errorMessage = llformat(LLTrans::getString("UnknownFileExtension").c_str(), exten.c_str());
- errorLabel = "ErrorMessage";
- error = true;;
- }
-
- if (error)
- {
- LLSD errorResult(LLSD::emptyMap());
-
- errorResult["error"] = LLSD::Binary(true);
- errorResult["message"] = errorMessage;
- errorResult["label"] = errorLabel;
- return errorResult;
- }
-
- setAssetType(assetType);
-
- // copy this file into the cache for upload
- S32 file_size;
- LLAPRFile infile;
- infile.open(filename, LL_APR_RB, NULL, &file_size);
- if (infile.getFileHandle())
- {
- LLFileSystem file(getAssetId(), assetType, LLFileSystem::APPEND);
-
- const S32 buf_size = 65536;
- U8 copy_buf[buf_size];
- while ((file_size = infile.read(copy_buf, buf_size)))
- {
- file.write(copy_buf, file_size);
- }
- }
- else
- {
- errorMessage = llformat("Unable to access output file: %s", filename.c_str());
- LLSD errorResult(LLSD::emptyMap());
-
- errorResult["error"] = LLSD::Binary(true);
- errorResult["message"] = errorMessage;
- return errorResult;
- }
-
- return LLSD();
-
-}
-
-//=========================================================================
-LLNewBufferedResourceUploadInfo::LLNewBufferedResourceUploadInfo(
- const std::string& buffer,
- const LLAssetID& asset_id,
- std::string name,
- std::string description,
- S32 compressionInfo,
- LLFolderType::EType destinationType,
- LLInventoryType::EType inventoryType,
- LLAssetType::EType assetType,
- U32 nextOWnerPerms,
- U32 groupPerms,
- U32 everyonePerms,
- S32 expectedCost,
- bool show_inventory,
- uploadFinish_f finish,
- uploadFailure_f failure)
- : LLResourceUploadInfo(name, description, compressionInfo,
- destinationType, inventoryType,
- nextOWnerPerms, groupPerms, everyonePerms, expectedCost, show_inventory)
- , mBuffer(buffer)
- , mFinishFn(finish)
- , mFailureFn(failure)
-{
- setAssetType(assetType);
- setAssetId(asset_id);
-}
-
-LLSD LLNewBufferedResourceUploadInfo::prepareUpload()
-{
- if (getAssetId().isNull())
- generateNewAssetId();
-
- LLSD result = exportTempFile();
- if (result.has("error"))
- return result;
-
- return LLResourceUploadInfo::prepareUpload();
-}
-
-LLSD LLNewBufferedResourceUploadInfo::exportTempFile()
-{
- std::string filename = gDirUtilp->getTempFilename();
-
- // copy buffer to the cache for upload
- LLFileSystem file(getAssetId(), getAssetType(), LLFileSystem::APPEND);
- file.write((U8*) mBuffer.c_str(), mBuffer.size());
-
- return LLSD();
-}
-
-LLUUID LLNewBufferedResourceUploadInfo::finishUpload(LLSD &result)
-{
- LLUUID newItemId = LLResourceUploadInfo::finishUpload(result);
-
- if (mFinishFn)
- {
- mFinishFn(result["new_asset"].asUUID(), result);
- }
-
- return newItemId;
-}
-
-bool LLNewBufferedResourceUploadInfo::failedUpload(LLSD &result, std::string &reason)
-{
- if (mFailureFn)
- {
- return mFailureFn(getAssetId(), result, reason);
- }
-
- return false; // Not handled
-}
-
-//=========================================================================
-LLBufferedAssetUploadInfo::LLBufferedAssetUploadInfo(LLUUID itemId, LLAssetType::EType assetType, std::string buffer, invnUploadFinish_f finish, uploadFailed_f failed) :
- LLResourceUploadInfo(std::string(), std::string(), 0, LLFolderType::FT_NONE, LLInventoryType::IT_NONE,
- 0, 0, 0, 0),
- mTaskUpload(false),
- mTaskId(LLUUID::null),
- mContents(buffer),
- mInvnFinishFn(finish),
- mTaskFinishFn(nullptr),
- mFailureFn(failed),
- mStoredToCache(false)
-{
- setItemId(itemId);
- setAssetType(assetType);
-}
-
-LLBufferedAssetUploadInfo::LLBufferedAssetUploadInfo(LLUUID itemId, LLPointer<LLImageFormatted> image, invnUploadFinish_f finish) :
- LLResourceUploadInfo(std::string(), std::string(), 0, LLFolderType::FT_NONE, LLInventoryType::IT_NONE,
- 0, 0, 0, 0),
- mTaskUpload(false),
- mTaskId(LLUUID::null),
- mContents(),
- mInvnFinishFn(finish),
- mTaskFinishFn(nullptr),
- mFailureFn(nullptr),
- mStoredToCache(false)
-{
- setItemId(itemId);
-
- LLImageDataSharedLock lock(image);
-
- EImageCodec codec = static_cast<EImageCodec>(image->getCodec());
-
- switch (codec)
- {
- case IMG_CODEC_JPEG:
- setAssetType(LLAssetType::AT_IMAGE_JPEG);
- LL_INFOS() << "Upload Asset type set to JPEG." << LL_ENDL;
- break;
- case IMG_CODEC_TGA:
- setAssetType(LLAssetType::AT_IMAGE_TGA);
- LL_INFOS() << "Upload Asset type set to TGA." << LL_ENDL;
- break;
- default:
- LL_WARNS() << "Unknown codec to asset type transition. Codec=" << (int)codec << "." << LL_ENDL;
- break;
- }
-
- size_t imageSize = image->getDataSize();
- mContents.reserve(imageSize);
- mContents.assign((char *)image->getData(), imageSize);
-}
-
-LLBufferedAssetUploadInfo::LLBufferedAssetUploadInfo(LLUUID taskId, LLUUID itemId, LLAssetType::EType assetType, std::string buffer, taskUploadFinish_f finish, uploadFailed_f failed) :
- LLResourceUploadInfo(std::string(), std::string(), 0, LLFolderType::FT_NONE, LLInventoryType::IT_NONE,
- 0, 0, 0, 0),
- mTaskUpload(true),
- mTaskId(taskId),
- mContents(buffer),
- mInvnFinishFn(nullptr),
- mTaskFinishFn(finish),
- mFailureFn(failed),
- mStoredToCache(false)
-{
- setItemId(itemId);
- setAssetType(assetType);
-}
-
-LLSD LLBufferedAssetUploadInfo::prepareUpload()
-{
- if (getAssetId().isNull())
- generateNewAssetId();
-
- LLFileSystem file(getAssetId(), getAssetType(), LLFileSystem::APPEND);
-
- S32 size = mContents.length() + 1;
- file.write((U8*)mContents.c_str(), size);
-
- mStoredToCache = true;
-
- return LLSD().with("success", LLSD::Boolean(true));
-}
-
-LLSD LLBufferedAssetUploadInfo::generatePostBody()
-{
- LLSD body;
-
- if (!getTaskId().isNull())
- {
- body["task_id"] = getTaskId();
- }
- body["item_id"] = getItemId();
-
- return body;
-}
-
-LLUUID LLBufferedAssetUploadInfo::finishUpload(LLSD &result)
-{
- LLUUID newAssetId = result["new_asset"].asUUID();
- LLUUID itemId = getItemId();
-
- if (mStoredToCache)
- {
- LLAssetType::EType assetType(getAssetType());
- LLFileSystem::renameFile(getAssetId(), assetType, newAssetId, assetType);
- }
-
- if (mTaskUpload)
- {
- LLUUID taskId = getTaskId();
-
- dialog_refresh_all();
-
- if (mTaskFinishFn)
- {
- mTaskFinishFn(itemId, taskId, newAssetId, result);
- }
- }
- else
- {
- LLUUID newItemId(LLUUID::null);
-
- if (itemId.notNull())
- {
- LLViewerInventoryItem* item = (LLViewerInventoryItem*)gInventory.getItem(itemId);
- if (!item)
- {
- LL_WARNS() << "Inventory item for " << getDisplayName() << " is no longer in agent inventory." << LL_ENDL;
- return newAssetId;
- }
-
- // Update viewer inventory item
- LLPointer<LLViewerInventoryItem> newItem = new LLViewerInventoryItem(item);
- newItem->setAssetUUID(newAssetId);
-
- gInventory.updateItem(newItem);
-
- newItemId = newItem->getUUID();
- LL_INFOS() << "Inventory item " << item->getName() << " saved into " << newAssetId.asString() << LL_ENDL;
- }
-
- if (mInvnFinishFn)
- {
- mInvnFinishFn(itemId, newAssetId, newItemId, result);
- }
- gInventory.notifyObservers();
- }
-
- return newAssetId;
-}
-
-bool LLBufferedAssetUploadInfo::failedUpload(LLSD &result, std::string &reason)
-{
- if (mFailureFn)
- {
- return mFailureFn(getItemId(), getTaskId(), result, reason);
- }
- return false;
-}
-
-//=========================================================================
-
-LLScriptAssetUpload::LLScriptAssetUpload(LLUUID itemId, std::string buffer, invnUploadFinish_f finish, uploadFailed_f failed):
- LLBufferedAssetUploadInfo(itemId, LLAssetType::AT_LSL_TEXT, buffer, finish, failed),
- mExerienceId(),
- mTargetType(MONO),
- mIsRunning(false)
-{
-}
-
-LLScriptAssetUpload::LLScriptAssetUpload(LLUUID taskId, LLUUID itemId, TargetType_t targetType,
- bool isRunning, LLUUID exerienceId, std::string buffer, taskUploadFinish_f finish, uploadFailed_f failed):
- LLBufferedAssetUploadInfo(taskId, itemId, LLAssetType::AT_LSL_TEXT, buffer, finish, failed),
- mExerienceId(exerienceId),
- mTargetType(targetType),
- mIsRunning(isRunning)
-{
-}
-
-LLSD LLScriptAssetUpload::generatePostBody()
-{
- LLSD body;
-
- if (getTaskId().isNull())
- {
- body["item_id"] = getItemId();
- body["target"] = "mono";
- }
- else
- {
- body["task_id"] = getTaskId();
- body["item_id"] = getItemId();
- body["is_script_running"] = getIsRunning();
- body["target"] = (getTargetType() == MONO) ? "mono" : "lsl2";
- body["experience"] = getExerienceId();
- }
-
- return body;
-}
-
-//=========================================================================
-/*static*/
-LLUUID LLViewerAssetUpload::EnqueueInventoryUpload(const std::string &url, const LLResourceUploadInfo::ptr_t &uploadInfo)
-{
- std::string procName("LLViewerAssetUpload::AssetInventoryUploadCoproc(");
-
- LLUUID queueId = LLCoprocedureManager::instance().enqueueCoprocedure("Upload",
- procName + LLAssetType::lookup(uploadInfo->getAssetType()) + ")",
- boost::bind(&LLViewerAssetUpload::AssetInventoryUploadCoproc, _1, _2, url, uploadInfo));
-
- return queueId;
-}
-
-//=========================================================================
-/*static*/
-void LLViewerAssetUpload::AssetInventoryUploadCoproc(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t &httpAdapter,
- const LLUUID &id, std::string url, LLResourceUploadInfo::ptr_t uploadInfo)
-{
- LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
- LLCore::HttpOptions::ptr_t httpOptions(new LLCore::HttpOptions);
- httpOptions->setTimeout(LL_ASSET_UPLOAD_TIMEOUT_SEC);
-
- LLSD result = uploadInfo->prepareUpload();
- uploadInfo->logPreparedUpload();
-
- if (result.has("error"))
- {
- HandleUploadError(LLCore::HttpStatus(499), result, uploadInfo);
- return;
- }
-
- llcoro::suspend();
-
- if (uploadInfo->showUploadDialog())
- {
- std::string uploadMessage = "Uploading...\n\n";
- uploadMessage.append(uploadInfo->getDisplayName());
- LLUploadDialog::modalUploadDialog(uploadMessage);
- }
-
- LLSD body = uploadInfo->generatePostBody();
-
- result = httpAdapter->postAndSuspend(httpRequest, url, body, httpOptions);
-
- LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
- LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
-
- if ((!status) || (result.has("error")))
- {
- HandleUploadError(status, result, uploadInfo);
- if (uploadInfo->showUploadDialog())
- LLUploadDialog::modalUploadFinished();
- return;
- }
-
- std::string uploader = result["uploader"].asString();
-
- bool success = false;
- if (!uploader.empty() && uploadInfo->getAssetId().notNull())
- {
- result = httpAdapter->postFileAndSuspend(httpRequest, uploader, uploadInfo->getAssetId(), uploadInfo->getAssetType(), httpOptions);
- httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
- status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
-
- std::string ulstate = result["state"].asString();
-
- if ((!status) || (ulstate != "complete"))
- {
- HandleUploadError(status, result, uploadInfo);
- if (uploadInfo->showUploadDialog())
- LLUploadDialog::modalUploadFinished();
- return;
- }
- if (!result.has("success"))
- {
- result["success"] = LLSD::Boolean((ulstate == "complete") && status);
- }
-
- S32 uploadPrice = result["upload_price"].asInteger();
-
- if (uploadPrice > 0)
- {
- // this upload costed us L$, update our balance
- // and display something saying that it cost L$
- LLStatusBar::sendMoneyBalanceRequest();
-
- LLSD args;
- args["AMOUNT"] = llformat("%d", uploadPrice);
- LLNotificationsUtil::add("UploadPayment", args);
- }
- }
- else
- {
- LL_WARNS() << "No upload url provided. Nothing uploaded, responding with previous result." << LL_ENDL;
- }
- LLUUID serverInventoryItem = uploadInfo->finishUpload(result);
-
- if (uploadInfo->showInventoryPanel())
- {
- if (serverInventoryItem.notNull())
- {
- success = true;
-
- LLFocusableElement* focus = gFocusMgr.getKeyboardFocus();
-
- // Show the preview panel for textures and sounds to let
- // user know that the image (or snapshot) arrived intact.
- LLInventoryPanel* panel = LLInventoryPanel::getActiveInventoryPanel(false);
- LLInventoryPanel::openInventoryPanelAndSetSelection(true, serverInventoryItem, false, false, !panel);
-
- // restore keyboard focus
- gFocusMgr.setKeyboardFocus(focus);
- }
- else
- {
- LL_WARNS() << "Can't find a folder to put it in" << LL_ENDL;
- }
- }
-
- // remove the "Uploading..." message
- if (uploadInfo->showUploadDialog())
- LLUploadDialog::modalUploadFinished();
-
- // Let the Snapshot floater know we have finished uploading a snapshot to inventory
- LLFloater* floater_snapshot = LLFloaterReg::findInstance("snapshot");
- if (uploadInfo->getAssetType() == LLAssetType::AT_TEXTURE && floater_snapshot && floater_snapshot->isShown())
- {
- floater_snapshot->notify(LLSD().with("set-finished", LLSD().with("ok", success).with("msg", "inventory")));
- }
-}
-
-//=========================================================================
-/*static*/
-void LLViewerAssetUpload::HandleUploadError(LLCore::HttpStatus status, LLSD &result, LLResourceUploadInfo::ptr_t &uploadInfo)
-{
- std::string reason;
- std::string label("CannotUploadReason");
-
- LL_WARNS() << ll_pretty_print_sd(result) << LL_ENDL;
-
- if (result.has("label"))
- {
- label = result["label"].asString();
- }
-
- if (result.has("message"))
- {
- reason = result["message"].asString();
- }
- else
- {
- switch (status.getType())
- {
- case 404:
- reason = LLTrans::getString("AssetUploadServerUnreacheble");
- break;
- case 499:
- reason = LLTrans::getString("AssetUploadServerDifficulties");
- break;
- case 503:
- reason = LLTrans::getString("AssetUploadServerUnavaliable");
- break;
- default:
- reason = LLTrans::getString("AssetUploadRequestInvalid");
- }
- }
-
- LLSD args;
- if(label == "ErrorMessage")
- {
- args["ERROR_MESSAGE"] = reason;
- }
- else
- {
- args["FILE"] = uploadInfo->getDisplayName();
- args["REASON"] = reason;
- args["ERROR"] = reason;
- }
-
- LLNotificationsUtil::add(label, args);
-
- if (uploadInfo->failedUpload(result, reason))
- {
- // no further action required, already handled by a callback
- // ex: do not trigger snapshot floater when failing material texture
- return;
- }
-
- // Todo: move these floater specific actions into proper callbacks
-
- // Let the Snapshot floater know we have failed uploading.
- LLFloaterSnapshot* floater_snapshot = LLFloaterSnapshot::findInstance();
- if (floater_snapshot && floater_snapshot->isWaitingState())
- {
- if (uploadInfo->getAssetType() == LLAssetType::AT_IMAGE_JPEG)
- {
- floater_snapshot->notify(LLSD().with("set-finished", LLSD().with("ok", false).with("msg", "postcard")));
- }
- if (uploadInfo->getAssetType() == LLAssetType::AT_TEXTURE)
- {
- floater_snapshot->notify(LLSD().with("set-finished", LLSD().with("ok", false).with("msg", "inventory")));
- }
- }
-}
-
+/**
+* @file llviewerassetupload.cpp
+* @author optional
+* @brief brief description of the file
+*
+* $LicenseInfo:firstyear=2011&license=viewerlgpl$
+* Second Life Viewer Source Code
+* Copyright (C) 2011, Linden Research, Inc.
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License as published by the Free Software Foundation;
+* version 2.1 of the License only.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this library; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*
+* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+* $/LicenseInfo$
+*/
+
+#include "llviewerprecompiledheaders.h"
+
+#include "linden_common.h"
+#include "llviewertexturelist.h"
+#include "llimage.h"
+#include "lltrans.h"
+#include "lluuid.h"
+#include "llvorbisencode.h"
+#include "lluploaddialog.h"
+#include "llnotificationsutil.h"
+#include "llagent.h"
+#include "llfloaterreg.h"
+#include "llfloatersnapshot.h"
+#include "llstatusbar.h"
+#include "llinventorypanel.h"
+#include "llsdutil.h"
+#include "llviewerassetupload.h"
+#include "llappviewer.h"
+#include "llviewerstats.h"
+#include "llfilesystem.h"
+#include "llgesturemgr.h"
+#include "llpreviewnotecard.h"
+#include "llpreviewgesture.h"
+#include "llcoproceduremanager.h"
+#include "llthread.h"
+#include "llkeyframemotion.h"
+#include "lldatapacker.h"
+#include "llvoavatarself.h"
+
+void dialog_refresh_all();
+
+static const U32 LL_ASSET_UPLOAD_TIMEOUT_SEC = 60;
+
+LLResourceUploadInfo::LLResourceUploadInfo(LLTransactionID transactId,
+ LLAssetType::EType assetType, std::string name, std::string description,
+ S32 compressionInfo, LLFolderType::EType destinationType,
+ LLInventoryType::EType inventoryType, U32 nextOWnerPerms,
+ U32 groupPerms, U32 everyonePerms, S32 expectedCost, bool showInventory) :
+ mTransactionId(transactId),
+ mAssetType(assetType),
+ mName(name),
+ mDescription(description),
+ mCompressionInfo(compressionInfo),
+ mDestinationFolderType(destinationType),
+ mInventoryType(inventoryType),
+ mNextOwnerPerms(nextOWnerPerms),
+ mGroupPerms(groupPerms),
+ mEveryonePerms(everyonePerms),
+ mExpectedUploadCost(expectedCost),
+ mShowInventory(showInventory),
+ mFolderId(LLUUID::null),
+ mItemId(LLUUID::null),
+ mAssetId(LLAssetID::null)
+{ }
+
+
+LLResourceUploadInfo::LLResourceUploadInfo(std::string name,
+ std::string description, S32 compressionInfo,
+ LLFolderType::EType destinationType, LLInventoryType::EType inventoryType,
+ U32 nextOWnerPerms, U32 groupPerms, U32 everyonePerms, S32 expectedCost, bool showInventory) :
+ mName(name),
+ mDescription(description),
+ mCompressionInfo(compressionInfo),
+ mDestinationFolderType(destinationType),
+ mInventoryType(inventoryType),
+ mNextOwnerPerms(nextOWnerPerms),
+ mGroupPerms(groupPerms),
+ mEveryonePerms(everyonePerms),
+ mExpectedUploadCost(expectedCost),
+ mShowInventory(showInventory),
+ mTransactionId(),
+ mAssetType(LLAssetType::AT_NONE),
+ mFolderId(LLUUID::null),
+ mItemId(LLUUID::null),
+ mAssetId(LLAssetID::null)
+{
+ mTransactionId.generate();
+}
+
+LLResourceUploadInfo::LLResourceUploadInfo(LLAssetID assetId, LLAssetType::EType assetType, std::string name) :
+ mAssetId(assetId),
+ mAssetType(assetType),
+ mName(name),
+ mDescription(),
+ mCompressionInfo(0),
+ mDestinationFolderType(LLFolderType::FT_NONE),
+ mInventoryType(LLInventoryType::IT_NONE),
+ mNextOwnerPerms(0),
+ mGroupPerms(0),
+ mEveryonePerms(0),
+ mExpectedUploadCost(0),
+ mShowInventory(true),
+ mTransactionId(),
+ mFolderId(LLUUID::null),
+ mItemId(LLUUID::null)
+{
+}
+
+LLSD LLResourceUploadInfo::prepareUpload()
+{
+ if (mAssetId.isNull())
+ generateNewAssetId();
+
+ incrementUploadStats();
+ assignDefaults();
+
+ return LLSD().with("success", LLSD::Boolean(true));
+}
+
+std::string LLResourceUploadInfo::getAssetTypeString() const
+{
+ return LLAssetType::lookup(mAssetType);
+}
+
+std::string LLResourceUploadInfo::getInventoryTypeString() const
+{
+ return LLInventoryType::lookup(mInventoryType);
+}
+
+LLSD LLResourceUploadInfo::generatePostBody()
+{
+ LLSD body;
+
+ body["folder_id"] = mFolderId;
+ body["asset_type"] = getAssetTypeString();
+ body["inventory_type"] = getInventoryTypeString();
+ body["name"] = mName;
+ body["description"] = mDescription;
+ body["next_owner_mask"] = LLSD::Integer(mNextOwnerPerms);
+ body["group_mask"] = LLSD::Integer(mGroupPerms);
+ body["everyone_mask"] = LLSD::Integer(mEveryonePerms);
+
+ return body;
+
+}
+
+void LLResourceUploadInfo::logPreparedUpload()
+{
+ LL_INFOS() << "*** Uploading: " << std::endl <<
+ "Type: " << LLAssetType::lookup(mAssetType) << std::endl <<
+ "UUID: " << mAssetId.asString() << std::endl <<
+ "Name: " << mName << std::endl <<
+ "Desc: " << mDescription << std::endl <<
+ "Expected Upload Cost: " << mExpectedUploadCost << std::endl <<
+ "Folder: " << mFolderId << std::endl <<
+ "Asset Type: " << LLAssetType::lookup(mAssetType) << LL_ENDL;
+}
+
+LLUUID LLResourceUploadInfo::finishUpload(LLSD &result)
+{
+ if (getFolderId().isNull())
+ {
+ return LLUUID::null;
+ }
+
+ U32 permsEveryone = PERM_NONE;
+ U32 permsGroup = PERM_NONE;
+ U32 permsNextOwner = PERM_ALL;
+
+ if (result.has("new_next_owner_mask"))
+ {
+ // The server provided creation perms so use them.
+ // Do not assume we got the perms we asked for in
+ // since the server may not have granted them all.
+ permsEveryone = result["new_everyone_mask"].asInteger();
+ permsGroup = result["new_group_mask"].asInteger();
+ permsNextOwner = result["new_next_owner_mask"].asInteger();
+ }
+ else
+ {
+ // The server doesn't provide creation perms
+ // so use old assumption-based perms.
+ if (getAssetTypeString() != "snapshot")
+ {
+ permsNextOwner = PERM_MOVE | PERM_TRANSFER;
+ }
+ }
+
+ LLPermissions new_perms;
+ new_perms.init(
+ gAgent.getID(),
+ gAgent.getID(),
+ LLUUID::null,
+ LLUUID::null);
+
+ new_perms.initMasks(
+ PERM_ALL,
+ PERM_ALL,
+ permsEveryone,
+ permsGroup,
+ permsNextOwner);
+
+ U32 flagsInventoryItem = 0;
+ if (result.has("inventory_flags"))
+ {
+ flagsInventoryItem = static_cast<U32>(result["inventory_flags"].asInteger());
+ if (flagsInventoryItem != 0)
+ {
+ LL_INFOS() << "inventory_item_flags " << flagsInventoryItem << LL_ENDL;
+ }
+ }
+ S32 creationDate = time_corrected();
+
+ LLUUID serverInventoryItem = result["new_inventory_item"].asUUID();
+ LLUUID serverAssetId = result["new_asset"].asUUID();
+
+ LLPointer<LLViewerInventoryItem> item = new LLViewerInventoryItem(
+ serverInventoryItem,
+ getFolderId(),
+ new_perms,
+ serverAssetId,
+ getAssetType(),
+ getInventoryType(),
+ getName(),
+ getDescription(),
+ LLSaleInfo::DEFAULT,
+ flagsInventoryItem,
+ creationDate);
+
+ gInventory.updateItem(item);
+ gInventory.notifyObservers();
+
+ return serverInventoryItem;
+}
+
+
+LLAssetID LLResourceUploadInfo::generateNewAssetId()
+{
+ if (gDisconnected)
+ {
+ LLAssetID rv;
+
+ rv.setNull();
+ return rv;
+ }
+ mAssetId = mTransactionId.makeAssetID(gAgent.getSecureSessionID());
+
+ return mAssetId;
+}
+
+void LLResourceUploadInfo::incrementUploadStats() const
+{
+ if (LLAssetType::AT_SOUND == mAssetType)
+ {
+ add(LLStatViewer::UPLOAD_SOUND, 1);
+ }
+ else if (LLAssetType::AT_TEXTURE == mAssetType)
+ {
+ add(LLStatViewer::UPLOAD_TEXTURE, 1);
+ }
+ else if (LLAssetType::AT_ANIMATION == mAssetType)
+ {
+ add(LLStatViewer::ANIMATION_UPLOADS, 1);
+ }
+}
+
+void LLResourceUploadInfo::assignDefaults()
+{
+ if (LLInventoryType::IT_NONE == mInventoryType)
+ {
+ mInventoryType = LLInventoryType::defaultForAssetType(mAssetType);
+ }
+ LLStringUtil::stripNonprintable(mName);
+ LLStringUtil::stripNonprintable(mDescription);
+
+ if (mName.empty())
+ {
+ mName = "(No Name)";
+ }
+ if (mDescription.empty())
+ {
+ mDescription = "(No Description)";
+ }
+
+ mFolderId = gInventory.findUserDefinedCategoryUUIDForType(
+ (mDestinationFolderType == LLFolderType::FT_NONE) ?
+ (LLFolderType::EType)mAssetType : mDestinationFolderType);
+}
+
+std::string LLResourceUploadInfo::getDisplayName() const
+{
+ return (mName.empty()) ? mAssetId.asString() : mName;
+};
+
+bool LLResourceUploadInfo::findAssetTypeOfExtension(const std::string& exten, LLAssetType::EType& asset_type)
+{
+ U32 codec;
+ return findAssetTypeAndCodecOfExtension(exten, asset_type, codec, false);
+}
+
+// static
+bool LLResourceUploadInfo::findAssetTypeAndCodecOfExtension(const std::string& exten, LLAssetType::EType& asset_type, U32& codec, bool bulk_upload)
+{
+ bool succ = false;
+ std::string exten_lc(exten);
+ LLStringUtil::toLower(exten_lc);
+ codec = LLImageBase::getCodecFromExtension(exten_lc);
+ if (codec != IMG_CODEC_INVALID)
+ {
+ asset_type = LLAssetType::AT_TEXTURE;
+ succ = true;
+ }
+ else if (exten_lc == "wav")
+ {
+ asset_type = LLAssetType::AT_SOUND;
+ succ = true;
+ }
+ else if (exten_lc == "anim")
+ {
+ asset_type = LLAssetType::AT_ANIMATION;
+ succ = true;
+ }
+ else if (!bulk_upload && (exten_lc == "bvh"))
+ {
+ asset_type = LLAssetType::AT_ANIMATION;
+ succ = true;
+ }
+
+ return succ;
+}
+
+//=========================================================================
+LLNewFileResourceUploadInfo::LLNewFileResourceUploadInfo(
+ std::string fileName,
+ std::string name,
+ std::string description,
+ S32 compressionInfo,
+ LLFolderType::EType destinationType,
+ LLInventoryType::EType inventoryType,
+ U32 nextOWnerPerms,
+ U32 groupPerms,
+ U32 everyonePerms,
+ S32 expectedCost,
+ bool show_inventory) :
+ LLResourceUploadInfo(name, description, compressionInfo,
+ destinationType, inventoryType,
+ nextOWnerPerms, groupPerms, everyonePerms, expectedCost, show_inventory),
+ mFileName(fileName)
+{
+}
+
+LLSD LLNewFileResourceUploadInfo::prepareUpload()
+{
+ if (getAssetId().isNull())
+ generateNewAssetId();
+
+ LLSD result = exportTempFile();
+ if (result.has("error"))
+ return result;
+
+ return LLResourceUploadInfo::prepareUpload();
+}
+
+LLSD LLNewFileResourceUploadInfo::exportTempFile()
+{
+ std::string filename = gDirUtilp->getTempFilename();
+
+ std::string exten = gDirUtilp->getExtension(getFileName());
+
+ LLAssetType::EType assetType = LLAssetType::AT_NONE;
+ U32 codec = IMG_CODEC_INVALID;
+ bool found_type = findAssetTypeAndCodecOfExtension(exten, assetType, codec);
+
+ std::string errorMessage;
+ std::string errorLabel;
+
+ bool error = false;
+
+ if (exten.empty())
+ {
+ std::string shortName = gDirUtilp->getBaseFileName(filename);
+
+ // No extension
+ errorMessage = llformat(
+ "No file extension for the file: '%s'\nPlease make sure the file has a correct file extension",
+ shortName.c_str());
+ errorLabel = "NoFileExtension";
+ error = true;
+ }
+ else if (!found_type)
+ {
+ // Unknown extension
+ errorMessage = llformat(LLTrans::getString("UnknownFileExtension").c_str(), exten.c_str());
+ errorLabel = "ErrorMessage";
+ error = true;;
+ }
+ else if (assetType == LLAssetType::AT_TEXTURE)
+ {
+ // It's an image file, the upload procedure is the same for all
+ if (!LLViewerTextureList::createUploadFile(getFileName(), filename, codec))
+ {
+ errorMessage = llformat("Problem with file %s:\n\n%s\n",
+ getFileName().c_str(), LLImage::getLastThreadError().c_str());
+ errorLabel = "ProblemWithFile";
+ error = true;
+ }
+ }
+ else if (assetType == LLAssetType::AT_SOUND)
+ {
+ S32 encodeResult = 0;
+
+ LL_INFOS() << "Attempting to encode wav as an ogg file" << LL_ENDL;
+
+ encodeResult = encode_vorbis_file(getFileName(), filename);
+
+ if (LLVORBISENC_NOERR != encodeResult)
+ {
+ switch (encodeResult)
+ {
+ case LLVORBISENC_DEST_OPEN_ERR:
+ errorMessage = llformat("Couldn't open temporary compressed sound file for writing: %s\n", filename.c_str());
+ errorLabel = "CannotOpenTemporarySoundFile";
+ break;
+
+ default:
+ errorMessage = llformat("Unknown vorbis encode failure on: %s\n", getFileName().c_str());
+ errorLabel = "UnknownVorbisEncodeFailure";
+ break;
+ }
+ error = true;
+ }
+ }
+ else if (exten == "bvh")
+ {
+ errorMessage = llformat("We do not currently support bulk upload of animation files\n");
+ errorLabel = "DoNotSupportBulkAnimationUpload";
+ error = true;
+ }
+ else if (exten == "anim")
+ {
+ // Default unless everything succeeds
+ errorLabel = "ProblemWithFile";
+ error = true;
+
+ // read from getFileName()
+ LLAPRFile infile;
+ infile.open(getFileName(),LL_APR_RB);
+ if (!infile.getFileHandle())
+ {
+ LL_WARNS() << "Couldn't open file for reading: " << getFileName() << LL_ENDL;
+ errorMessage = llformat("Failed to open animation file %s\n", getFileName().c_str());
+ }
+ else
+ {
+ S32 size = LLAPRFile::size(getFileName());
+ U8* buffer = new U8[size];
+ S32 size_read = infile.read(buffer,size);
+ if (size_read != size)
+ {
+ errorMessage = llformat("Failed to read animation file %s: wanted %d bytes, got %d\n", getFileName().c_str(), size, size_read);
+ }
+ else
+ {
+ LLDataPackerBinaryBuffer dp(buffer, size);
+ LLKeyframeMotion *motionp = new LLKeyframeMotion(getAssetId());
+ motionp->setCharacter(gAgentAvatarp);
+ if (motionp->deserialize(dp, getAssetId(), false))
+ {
+ // write to temp file
+ bool succ = motionp->dumpToFile(filename);
+ if (succ)
+ {
+ assetType = LLAssetType::AT_ANIMATION;
+ errorLabel = "";
+ error = false;
+ }
+ else
+ {
+ errorMessage = "Failed saving temporary animation file";
+ }
+ }
+ else
+ {
+ errorMessage = "Failed reading animation file";
+ }
+ }
+ }
+ }
+ else
+ {
+ // Unknown extension
+ errorMessage = llformat(LLTrans::getString("UnknownFileExtension").c_str(), exten.c_str());
+ errorLabel = "ErrorMessage";
+ error = true;;
+ }
+
+ if (error)
+ {
+ LLSD errorResult(LLSD::emptyMap());
+
+ errorResult["error"] = LLSD::Binary(true);
+ errorResult["message"] = errorMessage;
+ errorResult["label"] = errorLabel;
+ return errorResult;
+ }
+
+ setAssetType(assetType);
+
+ // copy this file into the cache for upload
+ S32 file_size;
+ LLAPRFile infile;
+ infile.open(filename, LL_APR_RB, NULL, &file_size);
+ if (infile.getFileHandle())
+ {
+ LLFileSystem file(getAssetId(), assetType, LLFileSystem::APPEND);
+
+ const S32 buf_size = 65536;
+ U8 copy_buf[buf_size];
+ while ((file_size = infile.read(copy_buf, buf_size)))
+ {
+ file.write(copy_buf, file_size);
+ }
+ }
+ else
+ {
+ errorMessage = llformat("Unable to access output file: %s", filename.c_str());
+ LLSD errorResult(LLSD::emptyMap());
+
+ errorResult["error"] = LLSD::Binary(true);
+ errorResult["message"] = errorMessage;
+ return errorResult;
+ }
+
+ return LLSD();
+
+}
+
+//=========================================================================
+LLNewBufferedResourceUploadInfo::LLNewBufferedResourceUploadInfo(
+ const std::string& buffer,
+ const LLAssetID& asset_id,
+ std::string name,
+ std::string description,
+ S32 compressionInfo,
+ LLFolderType::EType destinationType,
+ LLInventoryType::EType inventoryType,
+ LLAssetType::EType assetType,
+ U32 nextOWnerPerms,
+ U32 groupPerms,
+ U32 everyonePerms,
+ S32 expectedCost,
+ bool show_inventory,
+ uploadFinish_f finish,
+ uploadFailure_f failure)
+ : LLResourceUploadInfo(name, description, compressionInfo,
+ destinationType, inventoryType,
+ nextOWnerPerms, groupPerms, everyonePerms, expectedCost, show_inventory)
+ , mBuffer(buffer)
+ , mFinishFn(finish)
+ , mFailureFn(failure)
+{
+ setAssetType(assetType);
+ setAssetId(asset_id);
+}
+
+LLSD LLNewBufferedResourceUploadInfo::prepareUpload()
+{
+ if (getAssetId().isNull())
+ generateNewAssetId();
+
+ LLSD result = exportTempFile();
+ if (result.has("error"))
+ return result;
+
+ return LLResourceUploadInfo::prepareUpload();
+}
+
+LLSD LLNewBufferedResourceUploadInfo::exportTempFile()
+{
+ std::string filename = gDirUtilp->getTempFilename();
+
+ // copy buffer to the cache for upload
+ LLFileSystem file(getAssetId(), getAssetType(), LLFileSystem::APPEND);
+ file.write((U8*) mBuffer.c_str(), mBuffer.size());
+
+ return LLSD();
+}
+
+LLUUID LLNewBufferedResourceUploadInfo::finishUpload(LLSD &result)
+{
+ LLUUID newItemId = LLResourceUploadInfo::finishUpload(result);
+
+ if (mFinishFn)
+ {
+ mFinishFn(result["new_asset"].asUUID(), result);
+ }
+
+ return newItemId;
+}
+
+bool LLNewBufferedResourceUploadInfo::failedUpload(LLSD &result, std::string &reason)
+{
+ if (mFailureFn)
+ {
+ return mFailureFn(getAssetId(), result, reason);
+ }
+
+ return false; // Not handled
+}
+
+//=========================================================================
+LLBufferedAssetUploadInfo::LLBufferedAssetUploadInfo(LLUUID itemId, LLAssetType::EType assetType, std::string buffer, invnUploadFinish_f finish, uploadFailed_f failed) :
+ LLResourceUploadInfo(std::string(), std::string(), 0, LLFolderType::FT_NONE, LLInventoryType::IT_NONE,
+ 0, 0, 0, 0),
+ mTaskUpload(false),
+ mTaskId(LLUUID::null),
+ mContents(buffer),
+ mInvnFinishFn(finish),
+ mTaskFinishFn(nullptr),
+ mFailureFn(failed),
+ mStoredToCache(false)
+{
+ setItemId(itemId);
+ setAssetType(assetType);
+}
+
+LLBufferedAssetUploadInfo::LLBufferedAssetUploadInfo(LLUUID itemId, LLPointer<LLImageFormatted> image, invnUploadFinish_f finish) :
+ LLResourceUploadInfo(std::string(), std::string(), 0, LLFolderType::FT_NONE, LLInventoryType::IT_NONE,
+ 0, 0, 0, 0),
+ mTaskUpload(false),
+ mTaskId(LLUUID::null),
+ mContents(),
+ mInvnFinishFn(finish),
+ mTaskFinishFn(nullptr),
+ mFailureFn(nullptr),
+ mStoredToCache(false)
+{
+ setItemId(itemId);
+
+ LLImageDataSharedLock lock(image);
+
+ EImageCodec codec = static_cast<EImageCodec>(image->getCodec());
+
+ switch (codec)
+ {
+ case IMG_CODEC_JPEG:
+ setAssetType(LLAssetType::AT_IMAGE_JPEG);
+ LL_INFOS() << "Upload Asset type set to JPEG." << LL_ENDL;
+ break;
+ case IMG_CODEC_TGA:
+ setAssetType(LLAssetType::AT_IMAGE_TGA);
+ LL_INFOS() << "Upload Asset type set to TGA." << LL_ENDL;
+ break;
+ default:
+ LL_WARNS() << "Unknown codec to asset type transition. Codec=" << (int)codec << "." << LL_ENDL;
+ break;
+ }
+
+ size_t imageSize = image->getDataSize();
+ mContents.reserve(imageSize);
+ mContents.assign((char *)image->getData(), imageSize);
+}
+
+LLBufferedAssetUploadInfo::LLBufferedAssetUploadInfo(LLUUID taskId, LLUUID itemId, LLAssetType::EType assetType, std::string buffer, taskUploadFinish_f finish, uploadFailed_f failed) :
+ LLResourceUploadInfo(std::string(), std::string(), 0, LLFolderType::FT_NONE, LLInventoryType::IT_NONE,
+ 0, 0, 0, 0),
+ mTaskUpload(true),
+ mTaskId(taskId),
+ mContents(buffer),
+ mInvnFinishFn(nullptr),
+ mTaskFinishFn(finish),
+ mFailureFn(failed),
+ mStoredToCache(false)
+{
+ setItemId(itemId);
+ setAssetType(assetType);
+}
+
+LLSD LLBufferedAssetUploadInfo::prepareUpload()
+{
+ if (getAssetId().isNull())
+ generateNewAssetId();
+
+ LLFileSystem file(getAssetId(), getAssetType(), LLFileSystem::APPEND);
+
+ S32 size = mContents.length() + 1;
+ file.write((U8*)mContents.c_str(), size);
+
+ mStoredToCache = true;
+
+ return LLSD().with("success", LLSD::Boolean(true));
+}
+
+LLSD LLBufferedAssetUploadInfo::generatePostBody()
+{
+ LLSD body;
+
+ if (!getTaskId().isNull())
+ {
+ body["task_id"] = getTaskId();
+ }
+ body["item_id"] = getItemId();
+
+ return body;
+}
+
+LLUUID LLBufferedAssetUploadInfo::finishUpload(LLSD &result)
+{
+ LLUUID newAssetId = result["new_asset"].asUUID();
+ LLUUID itemId = getItemId();
+
+ if (mStoredToCache)
+ {
+ LLAssetType::EType assetType(getAssetType());
+ LLFileSystem::renameFile(getAssetId(), assetType, newAssetId, assetType);
+ }
+
+ if (mTaskUpload)
+ {
+ LLUUID taskId = getTaskId();
+
+ dialog_refresh_all();
+
+ if (mTaskFinishFn)
+ {
+ mTaskFinishFn(itemId, taskId, newAssetId, result);
+ }
+ }
+ else
+ {
+ LLUUID newItemId(LLUUID::null);
+
+ if (itemId.notNull())
+ {
+ LLViewerInventoryItem* item = (LLViewerInventoryItem*)gInventory.getItem(itemId);
+ if (!item)
+ {
+ LL_WARNS() << "Inventory item for " << getDisplayName() << " is no longer in agent inventory." << LL_ENDL;
+ return newAssetId;
+ }
+
+ // Update viewer inventory item
+ LLPointer<LLViewerInventoryItem> newItem = new LLViewerInventoryItem(item);
+ newItem->setAssetUUID(newAssetId);
+
+ gInventory.updateItem(newItem);
+
+ newItemId = newItem->getUUID();
+ LL_INFOS() << "Inventory item " << item->getName() << " saved into " << newAssetId.asString() << LL_ENDL;
+ }
+
+ if (mInvnFinishFn)
+ {
+ mInvnFinishFn(itemId, newAssetId, newItemId, result);
+ }
+ gInventory.notifyObservers();
+ }
+
+ return newAssetId;
+}
+
+bool LLBufferedAssetUploadInfo::failedUpload(LLSD &result, std::string &reason)
+{
+ if (mFailureFn)
+ {
+ return mFailureFn(getItemId(), getTaskId(), result, reason);
+ }
+ return false;
+}
+
+//=========================================================================
+
+LLScriptAssetUpload::LLScriptAssetUpload(LLUUID itemId, std::string buffer, invnUploadFinish_f finish, uploadFailed_f failed):
+ LLBufferedAssetUploadInfo(itemId, LLAssetType::AT_LSL_TEXT, buffer, finish, failed),
+ mExerienceId(),
+ mTargetType(MONO),
+ mIsRunning(false)
+{
+}
+
+LLScriptAssetUpload::LLScriptAssetUpload(LLUUID taskId, LLUUID itemId, TargetType_t targetType,
+ bool isRunning, LLUUID exerienceId, std::string buffer, taskUploadFinish_f finish, uploadFailed_f failed):
+ LLBufferedAssetUploadInfo(taskId, itemId, LLAssetType::AT_LSL_TEXT, buffer, finish, failed),
+ mExerienceId(exerienceId),
+ mTargetType(targetType),
+ mIsRunning(isRunning)
+{
+}
+
+LLSD LLScriptAssetUpload::generatePostBody()
+{
+ LLSD body;
+
+ if (getTaskId().isNull())
+ {
+ body["item_id"] = getItemId();
+ body["target"] = "mono";
+ }
+ else
+ {
+ body["task_id"] = getTaskId();
+ body["item_id"] = getItemId();
+ body["is_script_running"] = getIsRunning();
+ body["target"] = (getTargetType() == MONO) ? "mono" : "lsl2";
+ body["experience"] = getExerienceId();
+ }
+
+ return body;
+}
+
+//=========================================================================
+/*static*/
+LLUUID LLViewerAssetUpload::EnqueueInventoryUpload(const std::string &url, const LLResourceUploadInfo::ptr_t &uploadInfo)
+{
+ std::string procName("LLViewerAssetUpload::AssetInventoryUploadCoproc(");
+
+ LLUUID queueId = LLCoprocedureManager::instance().enqueueCoprocedure("Upload",
+ procName + LLAssetType::lookup(uploadInfo->getAssetType()) + ")",
+ boost::bind(&LLViewerAssetUpload::AssetInventoryUploadCoproc, _1, _2, url, uploadInfo));
+
+ return queueId;
+}
+
+//=========================================================================
+/*static*/
+void LLViewerAssetUpload::AssetInventoryUploadCoproc(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t &httpAdapter,
+ const LLUUID &id, std::string url, LLResourceUploadInfo::ptr_t uploadInfo)
+{
+ LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
+ LLCore::HttpOptions::ptr_t httpOptions(new LLCore::HttpOptions);
+ httpOptions->setTimeout(LL_ASSET_UPLOAD_TIMEOUT_SEC);
+
+ LLSD result = uploadInfo->prepareUpload();
+ uploadInfo->logPreparedUpload();
+
+ if (result.has("error"))
+ {
+ HandleUploadError(LLCore::HttpStatus(499), result, uploadInfo);
+ return;
+ }
+
+ llcoro::suspend();
+
+ if (uploadInfo->showUploadDialog())
+ {
+ std::string uploadMessage = "Uploading...\n\n";
+ uploadMessage.append(uploadInfo->getDisplayName());
+ LLUploadDialog::modalUploadDialog(uploadMessage);
+ }
+
+ LLSD body = uploadInfo->generatePostBody();
+
+ result = httpAdapter->postAndSuspend(httpRequest, url, body, httpOptions);
+
+ LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
+ LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
+
+ if ((!status) || (result.has("error")))
+ {
+ HandleUploadError(status, result, uploadInfo);
+ if (uploadInfo->showUploadDialog())
+ LLUploadDialog::modalUploadFinished();
+ return;
+ }
+
+ std::string uploader = result["uploader"].asString();
+
+ bool success = false;
+ if (!uploader.empty() && uploadInfo->getAssetId().notNull())
+ {
+ result = httpAdapter->postFileAndSuspend(httpRequest, uploader, uploadInfo->getAssetId(), uploadInfo->getAssetType(), httpOptions);
+ httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
+ status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
+
+ std::string ulstate = result["state"].asString();
+
+ if ((!status) || (ulstate != "complete"))
+ {
+ HandleUploadError(status, result, uploadInfo);
+ if (uploadInfo->showUploadDialog())
+ LLUploadDialog::modalUploadFinished();
+ return;
+ }
+ if (!result.has("success"))
+ {
+ result["success"] = LLSD::Boolean((ulstate == "complete") && status);
+ }
+
+ S32 uploadPrice = result["upload_price"].asInteger();
+
+ if (uploadPrice > 0)
+ {
+ // this upload costed us L$, update our balance
+ // and display something saying that it cost L$
+ LLStatusBar::sendMoneyBalanceRequest();
+
+ LLSD args;
+ args["AMOUNT"] = llformat("%d", uploadPrice);
+ LLNotificationsUtil::add("UploadPayment", args);
+ }
+ }
+ else
+ {
+ LL_WARNS() << "No upload url provided. Nothing uploaded, responding with previous result." << LL_ENDL;
+ }
+ LLUUID serverInventoryItem = uploadInfo->finishUpload(result);
+
+ if (uploadInfo->showInventoryPanel())
+ {
+ if (serverInventoryItem.notNull())
+ {
+ success = true;
+
+ LLFocusableElement* focus = gFocusMgr.getKeyboardFocus();
+
+ // Show the preview panel for textures and sounds to let
+ // user know that the image (or snapshot) arrived intact.
+ LLInventoryPanel* panel = LLInventoryPanel::getActiveInventoryPanel(false);
+ LLInventoryPanel::openInventoryPanelAndSetSelection(true, serverInventoryItem, false, false, !panel);
+
+ // restore keyboard focus
+ gFocusMgr.setKeyboardFocus(focus);
+ }
+ else
+ {
+ LL_WARNS() << "Can't find a folder to put it in" << LL_ENDL;
+ }
+ }
+
+ // remove the "Uploading..." message
+ if (uploadInfo->showUploadDialog())
+ LLUploadDialog::modalUploadFinished();
+
+ // Let the Snapshot floater know we have finished uploading a snapshot to inventory
+ LLFloater* floater_snapshot = LLFloaterReg::findInstance("snapshot");
+ if (uploadInfo->getAssetType() == LLAssetType::AT_TEXTURE && floater_snapshot && floater_snapshot->isShown())
+ {
+ floater_snapshot->notify(LLSD().with("set-finished", LLSD().with("ok", success).with("msg", "inventory")));
+ }
+}
+
+//=========================================================================
+/*static*/
+void LLViewerAssetUpload::HandleUploadError(LLCore::HttpStatus status, LLSD &result, LLResourceUploadInfo::ptr_t &uploadInfo)
+{
+ std::string reason;
+ std::string label("CannotUploadReason");
+
+ LL_WARNS() << ll_pretty_print_sd(result) << LL_ENDL;
+
+ if (result.has("label"))
+ {
+ label = result["label"].asString();
+ }
+
+ if (result.has("message"))
+ {
+ reason = result["message"].asString();
+ }
+ else
+ {
+ switch (status.getType())
+ {
+ case 404:
+ reason = LLTrans::getString("AssetUploadServerUnreacheble");
+ break;
+ case 499:
+ reason = LLTrans::getString("AssetUploadServerDifficulties");
+ break;
+ case 503:
+ reason = LLTrans::getString("AssetUploadServerUnavaliable");
+ break;
+ default:
+ reason = LLTrans::getString("AssetUploadRequestInvalid");
+ }
+ }
+
+ LLSD args;
+ if(label == "ErrorMessage")
+ {
+ args["ERROR_MESSAGE"] = reason;
+ }
+ else
+ {
+ args["FILE"] = uploadInfo->getDisplayName();
+ args["REASON"] = reason;
+ args["ERROR"] = reason;
+ }
+
+ LLNotificationsUtil::add(label, args);
+
+ if (uploadInfo->failedUpload(result, reason))
+ {
+ // no further action required, already handled by a callback
+ // ex: do not trigger snapshot floater when failing material texture
+ return;
+ }
+
+ // Todo: move these floater specific actions into proper callbacks
+
+ // Let the Snapshot floater know we have failed uploading.
+ LLFloaterSnapshot* floater_snapshot = LLFloaterSnapshot::findInstance();
+ if (floater_snapshot && floater_snapshot->isWaitingState())
+ {
+ if (uploadInfo->getAssetType() == LLAssetType::AT_IMAGE_JPEG)
+ {
+ floater_snapshot->notify(LLSD().with("set-finished", LLSD().with("ok", false).with("msg", "postcard")));
+ }
+ if (uploadInfo->getAssetType() == LLAssetType::AT_TEXTURE)
+ {
+ floater_snapshot->notify(LLSD().with("set-finished", LLSD().with("ok", false).with("msg", "inventory")));
+ }
+ }
+}
+