llassetuploadresponders.cpp
上传用户:king477883
上传日期:2021-03-01
资源大小:9553k
文件大小:19k
源码类别:

游戏引擎

开发平台:

C++ Builder

  1. /**
  2.  * @file llassetuploadresponders.cpp
  3.  * @brief Processes responses received for asset upload requests.
  4.  *
  5.  * $LicenseInfo:firstyear=2007&license=viewergpl$
  6.  * 
  7.  * Copyright (c) 2007-2010, Linden Research, Inc.
  8.  * 
  9.  * Second Life Viewer Source Code
  10.  * The source code in this file ("Source Code") is provided by Linden Lab
  11.  * to you under the terms of the GNU General Public License, version 2.0
  12.  * ("GPL"), unless you have obtained a separate licensing agreement
  13.  * ("Other License"), formally executed by you and Linden Lab.  Terms of
  14.  * the GPL can be found in doc/GPL-license.txt in this distribution, or
  15.  * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  16.  * 
  17.  * There are special exceptions to the terms and conditions of the GPL as
  18.  * it is applied to this Source Code. View the full text of the exception
  19.  * in the file doc/FLOSS-exception.txt in this software distribution, or
  20.  * online at
  21.  * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  22.  * 
  23.  * By copying, modifying or distributing this software, you acknowledge
  24.  * that you have read and understood your obligations described above,
  25.  * and agree to abide by those obligations.
  26.  * 
  27.  * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  28.  * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  29.  * COMPLETENESS OR PERFORMANCE.
  30.  * $/LicenseInfo$
  31.  */ 
  32. #include "llviewerprecompiledheaders.h"
  33. #include "llassetuploadresponders.h"
  34. // viewer includes
  35. #include "llagent.h"
  36. #include "llcompilequeue.h"
  37. #include "llfloaterbuycurrency.h"
  38. #include "llfilepicker.h"
  39. #include "llinventoryobserver.h"
  40. #include "llinventorypanel.h"
  41. #include "llpermissionsflags.h"
  42. #include "llpreviewnotecard.h"
  43. #include "llpreviewscript.h"
  44. #include "llpreviewgesture.h"
  45. #include "llgesturemgr.h"
  46. #include "llstatusbar.h" // sendMoneyBalanceRequest()
  47. #include "llsdserialize.h"
  48. #include "lluploaddialog.h"
  49. #include "llviewerobject.h"
  50. #include "llviewercontrol.h"
  51. #include "llviewerobjectlist.h"
  52. #include "llviewermenufile.h"
  53. #include "llviewerwindow.h"
  54. #include "lltexlayer.h"
  55. // library includes
  56. #include "lldir.h"
  57. #include "lleconomy.h"
  58. #include "llfloaterreg.h"
  59. #include "llfocusmgr.h"
  60. #include "llnotificationsutil.h"
  61. #include "llscrolllistctrl.h"
  62. #include "llsdserialize.h"
  63. #include "llvfs.h"
  64. // When uploading multiple files, don't display any of them when uploading more than this number.
  65. static const S32 FILE_COUNT_DISPLAY_THRESHOLD = 5;
  66. void dialog_refresh_all();
  67. LLAssetUploadResponder::LLAssetUploadResponder(const LLSD &post_data,
  68.    const LLUUID& vfile_id,
  69.    LLAssetType::EType asset_type)
  70. : LLHTTPClient::Responder(),
  71.   mPostData(post_data),
  72.   mVFileID(vfile_id),
  73.   mAssetType(asset_type)
  74. {
  75. if (!gVFS->getExists(vfile_id, asset_type))
  76. {
  77. llwarns << "LLAssetUploadResponder called with nonexistant vfile_id" << llendl;
  78. mVFileID.setNull();
  79. mAssetType = LLAssetType::AT_NONE;
  80. return;
  81. }
  82. }
  83. LLAssetUploadResponder::LLAssetUploadResponder(const LLSD &post_data,
  84.    const std::string& file_name, 
  85.    LLAssetType::EType asset_type)
  86. : LLHTTPClient::Responder(),
  87.   mPostData(post_data),
  88.   mFileName(file_name),
  89.   mAssetType(asset_type)
  90. {
  91. }
  92. LLAssetUploadResponder::~LLAssetUploadResponder()
  93. {
  94. if (!mFileName.empty())
  95. {
  96. // Delete temp file
  97. LLFile::remove(mFileName);
  98. }
  99. }
  100. // virtual
  101. void LLAssetUploadResponder::error(U32 statusNum, const std::string& reason)
  102. {
  103. llinfos << "LLAssetUploadResponder::error " << statusNum 
  104. << " reason: " << reason << llendl;
  105. LLSD args;
  106. switch(statusNum)
  107. {
  108. case 400:
  109. args["FILE"] = (mFileName.empty() ? mVFileID.asString() : mFileName);
  110. args["REASON"] = "Error in upload request.  Please visit "
  111. "http://secondlife.com/support for help fixing this problem.";
  112. LLNotificationsUtil::add("CannotUploadReason", args);
  113. break;
  114. case 500:
  115. default:
  116. args["FILE"] = (mFileName.empty() ? mVFileID.asString() : mFileName);
  117. args["REASON"] = "The server is experiencing unexpected "
  118. "difficulties.";
  119. LLNotificationsUtil::add("CannotUploadReason", args);
  120. break;
  121. }
  122. LLUploadDialog::modalUploadFinished();
  123. }
  124. //virtual 
  125. void LLAssetUploadResponder::result(const LLSD& content)
  126. {
  127. lldebugs << "LLAssetUploadResponder::result from capabilities" << llendl;
  128. std::string state = content["state"];
  129. if (state == "upload")
  130. {
  131. uploadUpload(content);
  132. }
  133. else if (state == "complete")
  134. {
  135. // rename file in VFS with new asset id
  136. if (mFileName.empty())
  137. {
  138. // rename the file in the VFS to the actual asset id
  139. // llinfos << "Changing uploaded asset UUID to " << content["new_asset"].asUUID() << llendl;
  140. gVFS->renameFile(mVFileID, mAssetType, content["new_asset"].asUUID(), mAssetType);
  141. }
  142. uploadComplete(content);
  143. }
  144. else
  145. {
  146. uploadFailure(content);
  147. }
  148. }
  149. void LLAssetUploadResponder::uploadUpload(const LLSD& content)
  150. {
  151. std::string uploader = content["uploader"];
  152. if (mFileName.empty())
  153. {
  154. LLHTTPClient::postFile(uploader, mVFileID, mAssetType, this);
  155. }
  156. else
  157. {
  158. LLHTTPClient::postFile(uploader, mFileName, this);
  159. }
  160. }
  161. void LLAssetUploadResponder::uploadFailure(const LLSD& content)
  162. {
  163. // remove the "Uploading..." message
  164. LLUploadDialog::modalUploadFinished();
  165. std::string reason = content["state"];
  166. // deal with L$ errors
  167. if (reason == "insufficient funds")
  168. {
  169. LLFloaterBuyCurrency::buyCurrency("Uploading costs", LLGlobalEconomy::Singleton::getInstance()->getPriceUpload());
  170. }
  171. else
  172. {
  173. LLSD args;
  174. args["FILE"] = (mFileName.empty() ? mVFileID.asString() : mFileName);
  175. args["REASON"] = content["message"].asString();
  176. LLNotificationsUtil::add("CannotUploadReason", args);
  177. }
  178. }
  179. void LLAssetUploadResponder::uploadComplete(const LLSD& content)
  180. {
  181. }
  182. LLNewAgentInventoryResponder::LLNewAgentInventoryResponder(const LLSD& post_data,
  183.    const LLUUID& vfile_id,
  184.    LLAssetType::EType asset_type)
  185. : LLAssetUploadResponder(post_data, vfile_id, asset_type)
  186. {
  187. }
  188. LLNewAgentInventoryResponder::LLNewAgentInventoryResponder(const LLSD& post_data, const std::string& file_name, LLAssetType::EType asset_type)
  189. : LLAssetUploadResponder(post_data, file_name, asset_type)
  190. {
  191. }
  192. //virtual 
  193. void LLNewAgentInventoryResponder::uploadComplete(const LLSD& content)
  194. {
  195. lldebugs << "LLNewAgentInventoryResponder::result from capabilities" << llendl;
  196. //std::ostringstream llsdxml;
  197. //LLSDSerialize::toXML(content, llsdxml);
  198. //llinfos << "upload complete content:n " << llsdxml.str() << llendl;
  199. LLAssetType::EType asset_type = LLAssetType::lookup(mPostData["asset_type"].asString());
  200. LLInventoryType::EType inventory_type = LLInventoryType::lookup(mPostData["inventory_type"].asString());
  201. S32 expected_upload_cost = LLGlobalEconomy::Singleton::getInstance()->getPriceUpload();
  202. // Update L$ and ownership credit information
  203. // since it probably changed on the server
  204. if (asset_type == LLAssetType::AT_TEXTURE ||
  205. asset_type == LLAssetType::AT_SOUND ||
  206. asset_type == LLAssetType::AT_ANIMATION)
  207. {
  208. LLStatusBar::sendMoneyBalanceRequest();
  209. LLSD args;
  210. args["AMOUNT"] = llformat("%d", expected_upload_cost);
  211. LLNotificationsUtil::add("UploadPayment", args);
  212. }
  213. // Actually add the upload to viewer inventory
  214. llinfos << "Adding " << content["new_inventory_item"].asUUID() << " "
  215. << content["new_asset"].asUUID() << " to inventory." << llendl;
  216. if(mPostData["folder_id"].asUUID().notNull())
  217. {
  218. //std::ostringstream out;
  219. //LLSDXMLFormatter *formatter = new LLSDXMLFormatter;
  220. //formatter->format(mPostData, out, LLSDFormatter::OPTIONS_PRETTY);
  221. //llinfos << "Post Data: " << out.str() << llendl;
  222. U32 everyone_perms = PERM_NONE;
  223. U32 group_perms = PERM_NONE;
  224. U32 next_owner_perms = PERM_ALL;
  225. if(content.has("new_next_owner_mask"))
  226. {
  227. // This is a new sim that provides creation perms so use them.
  228. // Do not assume we got the perms we asked for in mPostData 
  229. // since the sim may not have granted them all.
  230. everyone_perms = content["new_everyone_mask"].asInteger();
  231. group_perms = content["new_group_mask"].asInteger();
  232. next_owner_perms = content["new_next_owner_mask"].asInteger();
  233. }
  234. else 
  235. {
  236. // This old sim doesn't provide creation perms so use old assumption-based perms.
  237. if(mPostData["inventory_type"].asString() != "snapshot")
  238. {
  239. next_owner_perms = PERM_MOVE | PERM_TRANSFER;
  240. }
  241. }
  242. LLPermissions new_perms;
  243. new_perms.init(gAgent.getID(), gAgent.getID(), LLUUID::null, LLUUID::null);
  244. new_perms.initMasks(PERM_ALL, PERM_ALL, everyone_perms, group_perms, next_owner_perms);
  245. S32 creation_date_now = time_corrected();
  246. LLPointer<LLViewerInventoryItem> item
  247. = new LLViewerInventoryItem(content["new_inventory_item"].asUUID(),
  248. mPostData["folder_id"].asUUID(),
  249. new_perms,
  250. content["new_asset"].asUUID(),
  251. asset_type,
  252. inventory_type,
  253. mPostData["name"].asString(),
  254. mPostData["description"].asString(),
  255. LLSaleInfo::DEFAULT,
  256. LLInventoryItem::II_FLAGS_NONE,
  257. creation_date_now);
  258. gInventory.updateItem(item);
  259. gInventory.notifyObservers();
  260. // Show the preview panel for textures and sounds to let
  261. // user know that the image (or snapshot) arrived intact.
  262. LLInventoryPanel *active_panel = LLInventoryPanel::getActiveInventoryPanel();
  263. if (active_panel)
  264. {
  265. active_panel->setSelection(content["new_inventory_item"].asUUID(), TAKE_FOCUS_NO);
  266. if((LLAssetType::AT_TEXTURE == asset_type || LLAssetType::AT_SOUND == asset_type)
  267. && LLFilePicker::instance().getFileCount() <= FILE_COUNT_DISPLAY_THRESHOLD)
  268. {
  269. active_panel->openSelected();
  270. }
  271. //LLFloaterInventory::dumpSelectionInformation((void*)view);
  272. // restore keyboard focus
  273. LLFocusableElement* focus = gFocusMgr.getKeyboardFocus();
  274. gFocusMgr.setKeyboardFocus(focus);
  275. }
  276. }
  277. else
  278. {
  279. llwarns << "Can't find a folder to put it in" << llendl;
  280. }
  281. // remove the "Uploading..." message
  282. LLUploadDialog::modalUploadFinished();
  283. // *FIX: This is a pretty big hack. What this does is check the
  284. // file picker if there are any more pending uploads. If so,
  285. // upload that file.
  286. std::string next_file = LLFilePicker::instance().getNextFile();
  287. if(!next_file.empty())
  288. {
  289. std::string name = gDirUtilp->getBaseFileName(next_file, true);
  290. std::string asset_name = name;
  291. LLStringUtil::replaceNonstandardASCII( asset_name, '?' );
  292. LLStringUtil::replaceChar(asset_name, '|', '?');
  293. LLStringUtil::stripNonprintable(asset_name);
  294. LLStringUtil::trim(asset_name);
  295. // Continuing the horrible hack above, we need to extract the originally requested permissions data, if any,
  296. // and use them for each next file to be uploaded. Note the requested perms are not the same as the
  297. // granted ones found in the given "content" structure but can still be found in mPostData. -MG
  298. U32 everyone_perms   = mPostData.has("everyone_mask")   ? mPostData.get("everyone_mask"  ).asInteger() : PERM_NONE;
  299. U32 group_perms      = mPostData.has("group_mask")      ? mPostData.get("group_mask"     ).asInteger() : PERM_NONE;
  300. U32 next_owner_perms = mPostData.has("next_owner_mask") ? mPostData.get("next_owner_mask").asInteger() : PERM_NONE;
  301. std::string display_name = LLStringUtil::null;
  302. LLAssetStorage::LLStoreAssetCallback callback = NULL;
  303. void *userdata = NULL;
  304. upload_new_resource(next_file, asset_name, asset_name,
  305.     0, LLFolderType::FT_NONE, LLInventoryType::IT_NONE,
  306.     next_owner_perms, group_perms,
  307.     everyone_perms, display_name,
  308.     callback, expected_upload_cost, userdata);
  309. }
  310. }
  311. LLSendTexLayerResponder::LLSendTexLayerResponder(const LLSD& post_data,
  312.  const LLUUID& vfile_id,
  313.  LLAssetType::EType asset_type,
  314.  LLBakedUploadData * baked_upload_data) : 
  315. LLAssetUploadResponder(post_data, vfile_id, asset_type),
  316. mBakedUploadData(baked_upload_data)
  317. {
  318. }
  319. LLSendTexLayerResponder::~LLSendTexLayerResponder()
  320. {
  321. // mBakedUploadData is normally deleted by calls to LLTexLayerSetBuffer::onTextureUploadComplete() below
  322. if (mBakedUploadData)
  323. { // ...but delete it in the case where uploadComplete() is never called
  324. delete mBakedUploadData;
  325. mBakedUploadData = NULL;
  326. }
  327. }
  328. // Baked texture upload completed
  329. void LLSendTexLayerResponder::uploadComplete(const LLSD& content)
  330. {
  331. LLUUID item_id = mPostData["item_id"];
  332. std::string result = content["state"];
  333. LLUUID new_id = content["new_asset"];
  334. llinfos << "result: " << result << "new_id:" << new_id << llendl;
  335. if (result == "complete"
  336. && mBakedUploadData != NULL)
  337. { // Invoke 
  338. LLTexLayerSetBuffer::onTextureUploadComplete(new_id, (void*) mBakedUploadData, 0, LL_EXSTAT_NONE);
  339. mBakedUploadData = NULL; // deleted in onTextureUploadComplete()
  340. }
  341. else
  342. { // Invoke the original callback with an error result
  343. LLTexLayerSetBuffer::onTextureUploadComplete(new_id, (void*) mBakedUploadData, -1, LL_EXSTAT_NONE);
  344. mBakedUploadData = NULL; // deleted in onTextureUploadComplete()
  345. }
  346. }
  347. void LLSendTexLayerResponder::error(U32 statusNum, const std::string& reason)
  348. {
  349. llinfos << "status: " << statusNum << " reason: " << reason << llendl;
  350. // Invoke the original callback with an error result
  351. LLTexLayerSetBuffer::onTextureUploadComplete(LLUUID(), (void*) mBakedUploadData, -1, LL_EXSTAT_NONE);
  352. mBakedUploadData = NULL; // deleted in onTextureUploadComplete()
  353. }
  354. LLUpdateAgentInventoryResponder::LLUpdateAgentInventoryResponder(const LLSD& post_data,
  355.  const LLUUID& vfile_id,
  356.  LLAssetType::EType asset_type)
  357. : LLAssetUploadResponder(post_data, vfile_id, asset_type)
  358. {
  359. }
  360. LLUpdateAgentInventoryResponder::LLUpdateAgentInventoryResponder(const LLSD& post_data,
  361.  const std::string& file_name,
  362.  LLAssetType::EType asset_type)
  363. : LLAssetUploadResponder(post_data, file_name, asset_type)
  364. {
  365. }
  366. //virtual 
  367. void LLUpdateAgentInventoryResponder::uploadComplete(const LLSD& content)
  368. {
  369. llinfos << "LLUpdateAgentInventoryResponder::result from capabilities" << llendl;
  370. LLUUID item_id = mPostData["item_id"];
  371. LLViewerInventoryItem* item = (LLViewerInventoryItem*)gInventory.getItem(item_id);
  372. if(!item)
  373. {
  374. llwarns << "Inventory item for " << mVFileID
  375. << " is no longer in agent inventory." << llendl;
  376. return;
  377. }
  378. // Update viewer inventory item
  379. LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(item);
  380. new_item->setAssetUUID(content["new_asset"].asUUID());
  381. gInventory.updateItem(new_item);
  382. gInventory.notifyObservers();
  383. llinfos << "Inventory item " << item->getName() << " saved into "
  384. << content["new_asset"].asString() << llendl;
  385. LLInventoryType::EType inventory_type = new_item->getInventoryType();
  386. switch(inventory_type)
  387. {
  388.   case LLInventoryType::IT_NOTECARD:
  389.   {
  390.   // Update the UI with the new asset.
  391.   LLPreviewNotecard* nc = LLFloaterReg::findTypedInstance<LLPreviewNotecard>("preview_notecard", LLSD(item_id));
  392.   if(nc)
  393.   {
  394.   // *HACK: we have to delete the asset in the VFS so
  395.   // that the viewer will redownload it. This is only
  396.   // really necessary if the asset had to be modified by
  397.   // the uploader, so this can be optimized away in some
  398.   // cases. A better design is to have a new uuid if the
  399.   // script actually changed the asset.
  400.   if(nc->hasEmbeddedInventory())
  401.   {
  402.   gVFS->removeFile(content["new_asset"].asUUID(), LLAssetType::AT_NOTECARD);
  403.   }
  404.   nc->refreshFromInventory(new_item->getUUID());
  405.   }
  406.   break;
  407.   }
  408.   case LLInventoryType::IT_LSL:
  409.   {
  410.   // Find our window and close it if requested.
  411.   LLPreviewLSL* preview = LLFloaterReg::findTypedInstance<LLPreviewLSL>("preview_script", LLSD(item_id));
  412.   if (preview)
  413.   {
  414.   // Bytecode save completed
  415.   if (content["compiled"])
  416.   {
  417.   preview->callbackLSLCompileSucceeded();
  418.   }
  419.   else
  420.   {
  421.   preview->callbackLSLCompileFailed(content["errors"]);
  422.   }
  423.   }
  424.   break;
  425.   }
  426.   case LLInventoryType::IT_GESTURE:
  427.   {
  428.   // If this gesture is active, then we need to update the in-memory
  429.   // active map with the new pointer.
  430.   if (LLGestureManager::instance().isGestureActive(item_id))
  431.   {
  432.   LLUUID asset_id = new_item->getAssetUUID();
  433.   LLGestureManager::instance().replaceGesture(item_id, asset_id);
  434.   gInventory.notifyObservers();
  435.   }
  436.   //gesture will have a new asset_id
  437.   LLPreviewGesture* previewp = LLFloaterReg::findTypedInstance<LLPreviewGesture>("preview_gesture", LLSD(item_id));
  438.   if(previewp)
  439.   {
  440.   previewp->onUpdateSucceeded();
  441.   }
  442.   break;
  443.   }
  444.   case LLInventoryType::IT_WEARABLE:
  445.   default:
  446. break;
  447. }
  448. }
  449. LLUpdateTaskInventoryResponder::LLUpdateTaskInventoryResponder(const LLSD& post_data,
  450.  const LLUUID& vfile_id,
  451.  LLAssetType::EType asset_type)
  452. : LLAssetUploadResponder(post_data, vfile_id, asset_type)
  453. {
  454. }
  455. LLUpdateTaskInventoryResponder::LLUpdateTaskInventoryResponder(const LLSD& post_data,
  456.    const std::string& file_name, 
  457.    LLAssetType::EType asset_type)
  458. : LLAssetUploadResponder(post_data, file_name, asset_type)
  459. {
  460. }
  461. LLUpdateTaskInventoryResponder::LLUpdateTaskInventoryResponder(const LLSD& post_data,
  462.    const std::string& file_name,
  463.    const LLUUID& queue_id, 
  464.    LLAssetType::EType asset_type)
  465. : LLAssetUploadResponder(post_data, file_name, asset_type), mQueueId(queue_id)
  466. {
  467. }
  468. //virtual 
  469. void LLUpdateTaskInventoryResponder::uploadComplete(const LLSD& content)
  470. {
  471. llinfos << "LLUpdateTaskInventoryResponder::result from capabilities" << llendl;
  472. LLUUID item_id = mPostData["item_id"];
  473. LLUUID task_id = mPostData["task_id"];
  474. dialog_refresh_all();
  475. switch(mAssetType)
  476. {
  477.   case LLAssetType::AT_NOTECARD:
  478.   {
  479.   // Update the UI with the new asset.
  480.   LLPreviewNotecard* nc = LLFloaterReg::findTypedInstance<LLPreviewNotecard>("preview_notecard", LLSD(item_id));
  481.   if(nc)
  482.   {
  483.   // *HACK: we have to delete the asset in the VFS so
  484.   // that the viewer will redownload it. This is only
  485.   // really necessary if the asset had to be modified by
  486.   // the uploader, so this can be optimized away in some
  487.   // cases. A better design is to have a new uuid if the
  488.   // script actually changed the asset.
  489.   if(nc->hasEmbeddedInventory())
  490.   {
  491.   gVFS->removeFile(content["new_asset"].asUUID(),
  492.    LLAssetType::AT_NOTECARD);
  493.   }
  494.   nc->setAssetId(content["new_asset"].asUUID());
  495.   nc->refreshFromInventory();
  496.   }
  497.   break;
  498.   }
  499.   case LLAssetType::AT_LSL_TEXT:
  500.   {
  501.   if(mQueueId.notNull())
  502.   {
  503.   LLFloaterCompileQueue* queue = LLFloaterReg::findTypedInstance<LLFloaterCompileQueue>("compile_queue", mQueueId);
  504.   if(NULL != queue)
  505.   {
  506.   queue->removeItemByItemID(item_id);
  507.   }
  508.   }
  509.   else
  510.   {
  511.   LLLiveLSLEditor* preview = LLFloaterReg::findTypedInstance<LLLiveLSLEditor>("preview_scriptedit", LLSD(item_id));
  512.   if (preview)
  513.   {
  514.   // Bytecode save completed
  515.   if (content["compiled"])
  516.   {
  517.   preview->callbackLSLCompileSucceeded(task_id, item_id, mPostData["is_script_running"]);
  518.   }
  519.   else
  520.   {
  521.   preview->callbackLSLCompileFailed(content["errors"]);
  522.   }
  523.   }
  524.   }
  525.   break;
  526.   }
  527.   default:
  528. break;
  529. }
  530. }