llviewerassetupload.cpp 45 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657
  1. /**
  2. * @file llviewerassetupload.cpp
  3. * @brief Asset upload requests.
  4. *
  5. * $LicenseInfo:firstyear=2007&license=viewergpl$
  6. *
  7. * Copyright (c) 2007-2009, 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 "llviewerassetupload.h"
  34. #include "llcoproceduremanager.h"
  35. #include "lldir.h"
  36. #include "lldatapacker.h"
  37. #include "lleconomy.h"
  38. #include "llfilesystem.h"
  39. #include "llkeyframemotion.h"
  40. #include "llnotifications.h"
  41. #include "lltransactiontypes.h" // For TRANS_UPLOAD_CHARGE
  42. #include "llsdutil.h"
  43. #include "lltrans.h"
  44. #include "lluploaddialog.h"
  45. #include "llvorbisencode.h"
  46. #include "llmessage.h"
  47. #include "llagent.h"
  48. #include "llappviewer.h" // For gDisconnected
  49. #include "llfloaterbuycurrency.h"
  50. #include "llfloaterinventory.h"
  51. #include "llfloaterperms.h"
  52. #include "llfolderview.h"
  53. #include "llgridmanager.h" // For gIsInSecondLife
  54. #include "llinventoryactions.h" // For open_texture()
  55. #include "llpreviewsound.h"
  56. #include "llpreviewtexture.h"
  57. #include "llselectmgr.h" // For dialog_refresh_all()
  58. #include "llstatusbar.h" // For money balance
  59. #include "llviewercontrol.h"
  60. #include "llviewerregion.h"
  61. #include "llviewerstats.h"
  62. #include "llviewertexturelist.h"
  63. #include "llvoavatarself.h"
  64. constexpr S32 MAX_PREVIEWS = 5;
  65. // Multiple uploads
  66. std::deque<std::string> gUploadQueue;
  67. LLMutex gUploadQueueMutex;
  68. // Helper function
  69. S32 upload_cost_for_asset_type(LLAssetType::EType type, bool is_2k_tex = false)
  70. {
  71. LLEconomy* economyp = LLEconomy::getInstance();
  72. if (type == LLAssetType::AT_TEXTURE)
  73. {
  74. return is_2k_tex ? economyp->get2KTextureUploadCost()
  75. : economyp->getTextureUploadCost();
  76. }
  77. if (type == LLAssetType::AT_SOUND)
  78. {
  79. return economyp->getSoundUploadCost();
  80. }
  81. if (type == LLAssetType::AT_ANIMATION)
  82. {
  83. return economyp->getAnimationUploadCost();
  84. }
  85. if (type == LLAssetType::AT_MESH || type == LLAssetType::AT_NONE)
  86. {
  87. return economyp->getPriceUpload();
  88. }
  89. return 0;
  90. }
  91. ///////////////////////////////////////////////////////////////////////////////
  92. // LLResourceUploadInfo class
  93. ///////////////////////////////////////////////////////////////////////////////
  94. constexpr U32 LL_ASSET_UPLOAD_TIMEOUT_SEC = 60;
  95. LLResourceUploadInfo::LLResourceUploadInfo(const LLTransactionID& tid,
  96. LLAssetType::EType asset_type,
  97. const std::string& name,
  98. const std::string& description,
  99. S32 compression_info,
  100. LLFolderType::EType dest_type,
  101. LLInventoryType::EType inv_type,
  102. U32 perms_next, U32 perms_group,
  103. U32 perms_everyone, S32 cost)
  104. : mTransactionId(tid),
  105. mAssetType(asset_type),
  106. mName(name),
  107. mDescription(description),
  108. mCompressionInfo(compression_info),
  109. mDestinationFolderType(dest_type),
  110. mInventoryType(inv_type),
  111. mNextOwnerPerms(perms_next),
  112. mGroupPerms(perms_group),
  113. mEveryonePerms(perms_everyone),
  114. mExpectedUploadCost(cost),
  115. mCapCallback(NULL),
  116. mUserData(NULL),
  117. mShowInventoryPanel(true)
  118. {
  119. }
  120. LLResourceUploadInfo::LLResourceUploadInfo(const std::string& name,
  121. const std::string& description,
  122. S32 compression_info,
  123. LLFolderType::EType dest_type,
  124. LLInventoryType::EType inv_type,
  125. U32 perms_next, U32 perms_group,
  126. U32 perms_everyone, S32 cost)
  127. : mName(name),
  128. mDescription(description),
  129. mCompressionInfo(compression_info),
  130. mDestinationFolderType(dest_type),
  131. mInventoryType(inv_type),
  132. mNextOwnerPerms(perms_next),
  133. mGroupPerms(perms_group),
  134. mEveryonePerms(perms_everyone),
  135. mExpectedUploadCost(cost),
  136. mAssetType(LLAssetType::AT_NONE),
  137. mCapCallback(NULL),
  138. mUserData(NULL),
  139. mShowInventoryPanel(true)
  140. {
  141. mTransactionId.generate();
  142. }
  143. LLResourceUploadInfo::LLResourceUploadInfo(const LLAssetID& asset_id,
  144. LLAssetType::EType asset_type,
  145. const std::string& name)
  146. : mAssetId(asset_id),
  147. mAssetType(asset_type),
  148. mName(name),
  149. mCompressionInfo(0),
  150. mDestinationFolderType(LLFolderType::FT_NONE),
  151. mInventoryType(LLInventoryType::IT_NONE),
  152. mNextOwnerPerms(0),
  153. mGroupPerms(0),
  154. mEveryonePerms(0),
  155. mExpectedUploadCost(0),
  156. mCapCallback(NULL),
  157. mUserData(NULL),
  158. mShowInventoryPanel(true)
  159. {
  160. }
  161. //virtual
  162. LLSD LLResourceUploadInfo::prepareUpload()
  163. {
  164. if (mAssetId.isNull())
  165. {
  166. generateNewAssetId();
  167. }
  168. incrementUploadStats();
  169. assignDefaults();
  170. return LLSD().with("success", LLSD::Boolean(true));
  171. }
  172. std::string LLResourceUploadInfo::getAssetTypeString() const
  173. {
  174. return LLAssetType::lookup(mAssetType);
  175. }
  176. std::string LLResourceUploadInfo::getInventoryTypeString() const
  177. {
  178. return LLInventoryType::lookup(mInventoryType);
  179. }
  180. //virtual
  181. LLSD LLResourceUploadInfo::generatePostBody()
  182. {
  183. LLSD body;
  184. body["folder_id"] = mFolderId;
  185. body["asset_type"] = getAssetTypeString();
  186. body["inventory_type"] = getInventoryTypeString();
  187. body["name"] = mName;
  188. body["description"] = mDescription;
  189. body["next_owner_mask"] = LLSD::Integer(mNextOwnerPerms);
  190. body["group_mask"] = LLSD::Integer(mGroupPerms);
  191. body["everyone_mask"] = LLSD::Integer(mEveryonePerms);
  192. body["expected_upload_cost"] = mExpectedUploadCost;
  193. return body;
  194. }
  195. //virtual
  196. void LLResourceUploadInfo::logPreparedUpload()
  197. {
  198. llinfos << "Uploading asset name: " << mName << " - Asset type: "
  199. << LLAssetType::lookup(mAssetType) << " - Asset Id: " << mAssetId
  200. << " - Description: " << mDescription
  201. << " - Expected upload Cost: " << mExpectedUploadCost
  202. << " - Folder Id: " << mFolderId << llendl;
  203. }
  204. //virtual
  205. S32 LLResourceUploadInfo::getExpectedUploadCost()
  206. {
  207. if (mExpectedUploadCost < 0) // Unknown cost
  208. {
  209. mExpectedUploadCost = upload_cost_for_asset_type(mAssetType);
  210. }
  211. return mExpectedUploadCost;
  212. }
  213. //virtual
  214. LLUUID LLResourceUploadInfo::finishUpload(const LLSD& result)
  215. {
  216. if (getFolderId().isNull())
  217. {
  218. return LLUUID::null;
  219. }
  220. U32 perms_everyone = PERM_NONE;
  221. U32 perms_group = PERM_NONE;
  222. U32 perms_next = PERM_ALL;
  223. if (result.has("new_next_owner_mask"))
  224. {
  225. // The server provided creation permissions so use them. Do not assume
  226. // we got the permissions we asked for in since the server may not have
  227. // granted them all.
  228. perms_everyone = result["new_everyone_mask"].asInteger();
  229. perms_group = result["new_group_mask"].asInteger();
  230. perms_next = result["new_next_owner_mask"].asInteger();
  231. }
  232. // The server does not provide creation permissions so use old assumption-
  233. // based permissions.
  234. else if (getAssetTypeString() != "snapshot")
  235. {
  236. perms_next = PERM_MOVE | PERM_TRANSFER;
  237. }
  238. LLPermissions new_perms;
  239. new_perms.init(gAgentID, gAgentID, LLUUID::null, LLUUID::null);
  240. new_perms.initMasks(PERM_ALL, PERM_ALL, perms_everyone, perms_group,
  241. perms_next);
  242. U32 inv_item_flags = 0;
  243. if (result.has("inventory_flags"))
  244. {
  245. inv_item_flags = (U32)result["inventory_flags"].asInteger();
  246. if (inv_item_flags)
  247. {
  248. llinfos << "Inventory item flags: " << inv_item_flags << llendl;
  249. }
  250. }
  251. S32 creation_date_now = time_corrected();
  252. LLUUID new_inv_item_id = result["new_inventory_item"].asUUID();
  253. LLPointer<LLViewerInventoryItem> item =
  254. new LLViewerInventoryItem(new_inv_item_id, getFolderId(), new_perms,
  255. result["new_asset"].asUUID(), getAssetType(),
  256. getInventoryType(), getName(),
  257. getDescription(), LLSaleInfo::DEFAULT,
  258. inv_item_flags, creation_date_now);
  259. gInventory.updateItem(item);
  260. gInventory.notifyObservers();
  261. return new_inv_item_id;
  262. }
  263. LLAssetID LLResourceUploadInfo::generateNewAssetId()
  264. {
  265. if (gDisconnected)
  266. {
  267. LLAssetID rv;
  268. rv.setNull();
  269. return rv;
  270. }
  271. mAssetId = mTransactionId.makeAssetID(gAgent.getSecureSessionID());
  272. return mAssetId;
  273. }
  274. void LLResourceUploadInfo::incrementUploadStats() const
  275. {
  276. if (mAssetType == LLAssetType::AT_SOUND)
  277. {
  278. gViewerStats.incStat(LLViewerStats::ST_UPLOAD_SOUND_COUNT);
  279. }
  280. else if (mAssetType == LLAssetType::AT_TEXTURE)
  281. {
  282. gViewerStats.incStat(LLViewerStats::ST_UPLOAD_TEXTURE_COUNT);
  283. }
  284. else if (mAssetType == LLAssetType::AT_ANIMATION)
  285. {
  286. gViewerStats.incStat(LLViewerStats::ST_UPLOAD_ANIM_COUNT);
  287. }
  288. }
  289. //virtual
  290. void LLResourceUploadInfo::assignDefaults()
  291. {
  292. if (mInventoryType == LLInventoryType::IT_NONE)
  293. {
  294. mInventoryType = LLInventoryType::defaultForAssetType(mAssetType);
  295. }
  296. LLStringUtil::stripNonprintable(mName);
  297. LLStringUtil::stripNonprintable(mDescription);
  298. if (mName.empty())
  299. {
  300. mName = "(No Name)";
  301. }
  302. if (mDescription.empty())
  303. {
  304. mDescription = "(No Description)";
  305. }
  306. LLFolderType::EType type;
  307. if (mDestinationFolderType == LLFolderType::FT_NONE)
  308. {
  309. type = (LLFolderType::EType)mAssetType;
  310. }
  311. else
  312. {
  313. type = mDestinationFolderType;
  314. }
  315. if (mAssetType == LLAssetType::AT_GLTF ||
  316. mAssetType == LLAssetType::AT_GLTF_BIN)
  317. {
  318. mFolderId.setNull();
  319. }
  320. else
  321. {
  322. mFolderId = gInventory.findChoosenCategoryUUIDForType(type);
  323. }
  324. }
  325. //virtual
  326. std::string LLResourceUploadInfo::getDisplayName() const
  327. {
  328. return mName.empty() ? mAssetId.asString() : mName;
  329. }
  330. void LLResourceUploadInfo::performCallback(const LLSD& result)
  331. {
  332. if (mCapCallback)
  333. {
  334. mCapCallback(result, mUserData);
  335. }
  336. }
  337. ///////////////////////////////////////////////////////////////////////////////
  338. // LLNewFileResourceUploadInfo class
  339. ///////////////////////////////////////////////////////////////////////////////
  340. LLNewFileResourceUploadInfo::LLNewFileResourceUploadInfo(const std::string& fname,
  341. const std::string& name,
  342. const std::string& desc,
  343. S32 compression_info,
  344. LLFolderType::EType dest_type,
  345. LLInventoryType::EType inv_type,
  346. U32 perms_next,
  347. U32 perms_group,
  348. U32 perms_everyone,
  349. S32 cost)
  350. : LLResourceUploadInfo(name, desc, compression_info, dest_type, inv_type,
  351. perms_next, perms_group, perms_everyone, cost),
  352. mFileName(fname),
  353. mIsBulkUpload(false)
  354. {
  355. }
  356. //virtual
  357. LLSD LLNewFileResourceUploadInfo::prepareUpload()
  358. {
  359. if (getAssetId().isNull())
  360. {
  361. generateNewAssetId();
  362. }
  363. LLSD result = exportTempFile();
  364. if (result.has("error"))
  365. {
  366. return result;
  367. }
  368. return LLResourceUploadInfo::prepareUpload();
  369. }
  370. //virtual
  371. LLSD LLNewFileResourceUploadInfo::exportTempFile()
  372. {
  373. std::string filename = gDirUtil.getTempFilename();
  374. const std::string& orig_filename = getFileName();
  375. std::string exten = gDirUtil.getExtension(orig_filename);
  376. EImageCodec codec = LLImageBase::getCodecFromExtension(exten);
  377. LLAssetType::EType asset_type = LLAssetType::AT_NONE;
  378. LLSD args;
  379. std::string error_msg, error_label;
  380. bool error = false;
  381. bool is_2k_texture = false;
  382. if (exten.empty())
  383. {
  384. std::string short_name = gDirUtil.getBaseFileName(filename);
  385. // No extension
  386. error_msg = "No file extension for the file: " + short_name + "\n";
  387. error_msg += "Please make sure the file has a correct file extension.\n";
  388. error_label = "NoFileExtension";
  389. args["FILE"] = short_name;
  390. error = true;
  391. }
  392. else if (codec != IMG_CODEC_INVALID)
  393. {
  394. // It is an image file, the upload procedure is the same for all
  395. asset_type = LLAssetType::AT_TEXTURE;
  396. if (!LLViewerTextureList::createUploadFile(orig_filename, filename,
  397. codec, &is_2k_texture))
  398. {
  399. error_msg = "Problem with file '" + orig_filename + "':\n\n";
  400. error_msg += LLImage::getLastError() + "\n";
  401. error_label = "ProblemWithFile";
  402. args["FILE"] = orig_filename;
  403. args["ERROR"] = LLImage::getLastError();
  404. error = true;
  405. }
  406. }
  407. else if (exten == "wav" || exten == "dsf")
  408. {
  409. asset_type = LLAssetType::AT_SOUND; // tag it as audio
  410. llinfos << "Attempting to encode wav as an ogg file" << llendl;
  411. F32 max_duration = LLVORBIS_CLIP_MAX_TIME; // SL default (30s)
  412. if (!gIsInSecondLife)
  413. {
  414. max_duration = llmax(LLVORBIS_CLIP_MAX_TIME,
  415. gSavedSettings.getU32("OSMaxSoundDuration"));
  416. }
  417. // Pre-qualify the wav file to make sure the format is acceptable
  418. if (check_for_invalid_wav_formats(orig_filename, error_label,
  419. max_duration) != LLVORBISENC_NOERR)
  420. {
  421. error = true;
  422. error_msg = "Invalid sound file (encoding or duration): ";
  423. error_msg += filename + "\n";
  424. args["FILE"] = filename;
  425. args["LENGTH"] = llformat("%d", (S32)max_duration);
  426. }
  427. else
  428. {
  429. S32 encode_result = encode_vorbis_file(orig_filename, filename,
  430. max_duration);
  431. if (encode_result != LLVORBISENC_NOERR)
  432. {
  433. error = true;
  434. args["FILE"] = filename;
  435. if (encode_result == LLVORBISENC_DEST_OPEN_ERR)
  436. {
  437. error_msg = "Could create temporary Vorbis sound file: ";
  438. error_msg += filename + "\n";
  439. error_label = "CannotOpenTemporarySoundFile";
  440. }
  441. else
  442. {
  443. error_msg ="Unknown vorbis encode failure on: ";
  444. error_msg += orig_filename + "\n";
  445. error_label = "UnknownVorbisEncodeFailure";
  446. }
  447. }
  448. }
  449. }
  450. else if (exten == "anim")
  451. {
  452. error_label = "GenericAlert";
  453. error = true;
  454. S64 size = 0;
  455. LLFile infile(orig_filename, "rb", &size);
  456. if (!infile)
  457. {
  458. error_msg = "Failed to open animation file: " + filename + "\n";
  459. }
  460. else if (size <= 0)
  461. {
  462. error_msg = "Animation file " + orig_filename + " is empty !\n";
  463. }
  464. else
  465. {
  466. U8* buffer = new U8[size];
  467. S64 size_read = infile.read(buffer, size);
  468. if (size_read != size)
  469. {
  470. error_msg =
  471. llformat("Failed to read animation file %s: wanted %d bytes, got %d\n",
  472. orig_filename.c_str(), size, size_read);
  473. }
  474. else
  475. {
  476. LLDataPackerBinaryBuffer dp(buffer, size);
  477. LLKeyframeMotion* motionp = new LLKeyframeMotion(getAssetId());
  478. motionp->setCharacter(gAgentAvatarp);
  479. if (motionp->deserialize(dp, getAssetId(), false))
  480. {
  481. // Write to temporary file
  482. if (motionp->dumpToFile(filename))
  483. {
  484. asset_type = LLAssetType::AT_ANIMATION;
  485. error_label.clear();
  486. error = false;
  487. }
  488. else
  489. {
  490. error_msg = "Failed saving temporary animation file\n";
  491. }
  492. }
  493. else
  494. {
  495. error_msg = "Failed reading animation file: " +
  496. orig_filename + "\n";
  497. }
  498. delete motionp;
  499. }
  500. delete[] buffer;
  501. }
  502. }
  503. else if (exten == "bvh")
  504. {
  505. error_msg = "Bulk upload of animation files is not supported.\n";
  506. error_label = "DoNotSupportBulkAnimationUpload";
  507. error = true;
  508. }
  509. else if (exten == "gltf" || exten == "glb")
  510. {
  511. error_msg = "Bulk upload of GLTF files is not supported.\n";
  512. error_label = "DoNotSupportBulkGLTFUpload";
  513. error = true;
  514. }
  515. else if (exten == "tmp")
  516. {
  517. // This is a generic .lin resource file
  518. asset_type = LLAssetType::AT_OBJECT;
  519. LLFILE* in = LLFile::open(orig_filename, "rb");
  520. if (in)
  521. {
  522. // Read in the file header
  523. char buf[16384];
  524. size_t readbytes;
  525. S32 version;
  526. if (fscanf(in, "LindenResource\nversion %d\n", &version))
  527. {
  528. if (version == 2)
  529. {
  530. // NOTE: This buffer size is hard coded into scanf() below.
  531. char label[MAX_STRING];
  532. char value[MAX_STRING];
  533. S32 tokens_read;
  534. while (fgets(buf, 1024, in))
  535. {
  536. label[0] = '\0';
  537. value[0] = '\0';
  538. tokens_read = sscanf(buf, "%254s %254s\n", label,
  539. value);
  540. llinfos << "got: " << label << " = " << value << llendl;
  541. if (tokens_read == EOF)
  542. {
  543. error_msg = "Corrupt resource file: " +
  544. orig_filename;
  545. error_label = "CorruptResourceFile";
  546. args["FILE"] = orig_filename;
  547. error = true;
  548. break;
  549. }
  550. else if (tokens_read == 2)
  551. {
  552. if (!strcmp("type", label))
  553. {
  554. asset_type = (LLAssetType::EType)(atoi(value));
  555. }
  556. }
  557. else if (!strcmp("_DATA_", label))
  558. {
  559. // Below is the data section
  560. break;
  561. }
  562. // Other values are currently discarded
  563. }
  564. }
  565. else
  566. {
  567. error_msg =
  568. "Unknown linden resource file version in file: " +
  569. orig_filename;
  570. error_label = "UnknownResourceFileVersion";
  571. args["FILE"] = orig_filename;
  572. error = true;
  573. }
  574. }
  575. else
  576. {
  577. // This is an original binary formatted .lin file; start over
  578. // at the beginning of the file
  579. fseek(in, 0, SEEK_SET);
  580. constexpr S32 MAX_ASSET_DESCRIPTION_LENGTH = 256;
  581. constexpr S32 MAX_ASSET_NAME_LENGTH = 64;
  582. S32 header_size = 34 + MAX_ASSET_DESCRIPTION_LENGTH +
  583. MAX_ASSET_NAME_LENGTH;
  584. // Read in and throw out most of the header except for the type
  585. if (fread(buf, header_size, 1, in) != 1)
  586. {
  587. llwarns << "Short read" << llendl;
  588. }
  589. S16 type_num;
  590. memcpy(&type_num, buf + 16, sizeof(S16));
  591. asset_type = (LLAssetType::EType)type_num;
  592. }
  593. if (!error)
  594. {
  595. // Copy the file's data segment into another file for uploading
  596. LLFILE* out = LLFile::open(filename, "wb");
  597. if (out)
  598. {
  599. while ((readbytes = fread(buf, 1, 16384, in)))
  600. {
  601. if (fwrite(buf, 1, readbytes, out) != readbytes)
  602. {
  603. llwarns << "Short write" << llendl;
  604. }
  605. }
  606. LLFile::close(out);
  607. }
  608. else
  609. {
  610. error_msg = "Unable to create temporary file: " + filename;
  611. error_label = "UnableToCreateOutputFile";
  612. args["FILE"] = filename;
  613. error = true;
  614. }
  615. }
  616. LLFile::close(in);
  617. }
  618. else
  619. {
  620. llinfos << "Could not open .lin file " << orig_filename << llendl;
  621. }
  622. }
  623. else // Unknown extension
  624. {
  625. error_msg = "Unsupported file extension ." + exten + "\n";
  626. error_msg += "Expected .wav, .tga, .bmp, .jpg, .jpeg, .bvh or .anim";
  627. error = true;
  628. }
  629. LLSD result(LLSD::emptyMap());
  630. if (error)
  631. {
  632. result["error"] = LLSD::Binary(true);
  633. result["message"] = error_msg;
  634. result["label"] = error_label;
  635. result["args"] = args;
  636. }
  637. else
  638. {
  639. setAssetType(asset_type);
  640. S32 cost = upload_cost_for_asset_type(asset_type, is_2k_texture);
  641. setExpectedUploadCost(cost);
  642. if (is_2k_texture && mIsBulkUpload &&
  643. cost > upload_cost_for_asset_type(LLAssetType::AT_TEXTURE) &&
  644. !gSavedPerAccountSettings.getBool("BulkUpload2KTextures"))
  645. {
  646. result["error"] = LLSD::Binary(true);
  647. error_msg = "File '" + orig_filename;
  648. error_msg += "' is a 2K texture for which bulk-upload is disabled.";
  649. result["message"] = error_msg;
  650. result["label"] = "BulkUpload2KTextureDisabled";
  651. args["FILE"] = orig_filename;
  652. result["args"] = args;
  653. }
  654. else
  655. {
  656. // Copy this file into the cache for upload
  657. S64 file_size;
  658. LLFile infile(filename, "rb", &file_size);
  659. if (infile)
  660. {
  661. LLFileSystem file(getAssetId(), LLFileSystem::APPEND);
  662. constexpr S32 buf_size = 65536;
  663. U8 copy_buf[buf_size];
  664. while ((file_size = infile.read(copy_buf, buf_size)))
  665. {
  666. file.write(copy_buf, file_size);
  667. }
  668. }
  669. else
  670. {
  671. error_msg = "Unable to access temporary file: " + filename;
  672. result["error"] = LLSD::Binary(true);
  673. result["message"] = error_msg;
  674. }
  675. }
  676. }
  677. if (!LLFile::remove(filename))
  678. {
  679. llwarns << "Unable to remove temporary file: " << filename << llendl;
  680. }
  681. return result;
  682. }
  683. ///////////////////////////////////////////////////////////////////////////////
  684. // LLNewBufferedResourceUploadInfo class
  685. ///////////////////////////////////////////////////////////////////////////////
  686. LLNewBufferedResourceUploadInfo::LLNewBufferedResourceUploadInfo(
  687. const std::string& buffer, const LLAssetID& asset_id,
  688. const std::string& name, const std::string& description,
  689. S32 compression_info, LLFolderType::EType dest_type,
  690. LLInventoryType::EType inv_type, LLAssetType::EType asset_type,
  691. U32 perms_next, U32 perms_group, U32 perms_everyone, S32 cost,
  692. uploaded_cb_t finish, failed_cb_t failure)
  693. : LLResourceUploadInfo(name, description, compression_info, dest_type,
  694. inv_type, perms_next, perms_group,perms_everyone,
  695. cost),
  696. mBuffer(buffer),
  697. mFinishFn(finish),
  698. mFailureFn(failure)
  699. {
  700. setAssetType(asset_type);
  701. setAssetId(asset_id);
  702. }
  703. //virtual
  704. LLSD LLNewBufferedResourceUploadInfo::prepareUpload()
  705. {
  706. if (getAssetId().isNull())
  707. {
  708. generateNewAssetId();
  709. }
  710. LLSD result = exportTempFile();
  711. if (result.has("error"))
  712. {
  713. return result;
  714. }
  715. return LLResourceUploadInfo::prepareUpload();
  716. }
  717. //virtual
  718. LLSD LLNewBufferedResourceUploadInfo::exportTempFile()
  719. {
  720. std::string filename = gDirUtil.getTempFilename();
  721. LLFileSystem file(getAssetId(), LLFileSystem::APPEND);
  722. file.write((U8*)mBuffer.c_str(), mBuffer.size());
  723. return LLSD();
  724. }
  725. //virtual
  726. LLUUID LLNewBufferedResourceUploadInfo::finishUpload(const LLSD& result)
  727. {
  728. LLUUID new_asset_id = LLResourceUploadInfo::finishUpload(result);
  729. if (mFinishFn)
  730. {
  731. mFinishFn(result["new_asset"].asUUID(), result);
  732. }
  733. return new_asset_id;
  734. }
  735. void LLNewBufferedResourceUploadInfo::failedUpload(const LLSD& result,
  736. std::string& reason)
  737. {
  738. if (!mFailureFn.empty())
  739. {
  740. mFailureFn(getAssetId(), result, reason);
  741. }
  742. }
  743. ///////////////////////////////////////////////////////////////////////////////
  744. // LLBufferedAssetUploadInfo class
  745. ///////////////////////////////////////////////////////////////////////////////
  746. LLBufferedAssetUploadInfo::LLBufferedAssetUploadInfo(const LLUUID& item_id,
  747. LLAssetType::EType atype,
  748. const std::string& buffer,
  749. inv_uploaded_cb_t finish,
  750. failed_cb_t failed)
  751. : LLResourceUploadInfo(LLStringUtil::null, LLStringUtil::null, 0,
  752. LLFolderType::FT_NONE, LLInventoryType::IT_NONE,
  753. 0, 0, 0, 0),
  754. mTaskUpload(false),
  755. mContents(buffer),
  756. mInvnFinishFn(finish),
  757. mTaskFinishFn(NULL),
  758. mFailureFn(failed),
  759. mStoredToCache(false)
  760. {
  761. setItemId(item_id);
  762. setAssetType(atype);
  763. setShowInventoryPanel(false);
  764. }
  765. LLBufferedAssetUploadInfo::LLBufferedAssetUploadInfo(const LLUUID& item_id,
  766. LLPointer<LLImageFormatted> image,
  767. inv_uploaded_cb_t finish)
  768. : LLResourceUploadInfo(LLStringUtil::null, LLStringUtil::null, 0,
  769. LLFolderType::FT_NONE, LLInventoryType::IT_NONE,
  770. 0, 0, 0, 0),
  771. mTaskUpload(false),
  772. mInvnFinishFn(finish),
  773. mTaskFinishFn(NULL),
  774. mFailureFn(NULL),
  775. mStoredToCache(false)
  776. {
  777. setItemId(item_id);
  778. setShowInventoryPanel(false);
  779. EImageCodec codec = (EImageCodec)image->getCodec();
  780. switch (codec)
  781. {
  782. case IMG_CODEC_JPEG:
  783. setAssetType(LLAssetType::AT_IMAGE_JPEG);
  784. llinfos << "Upload Asset type set to JPEG." << llendl;
  785. break;
  786. case IMG_CODEC_TGA:
  787. setAssetType(LLAssetType::AT_IMAGE_TGA);
  788. llinfos << "Upload Asset type set to TGA." << llendl;
  789. break;
  790. default:
  791. llwarns << "Unknown codec to asset type transition: " << (S32)codec
  792. << "." << llendl;
  793. break;
  794. }
  795. size_t image_size = image->getDataSize();
  796. mContents.reserve(image_size);
  797. mContents.assign((char*)image->getData(), image_size);
  798. }
  799. LLBufferedAssetUploadInfo::LLBufferedAssetUploadInfo(const LLUUID& task_id,
  800. const LLUUID& item_id,
  801. LLAssetType::EType atype,
  802. const std::string& buffer,
  803. task_uploaded_cb_t finish,
  804. failed_cb_t failed)
  805. : LLResourceUploadInfo(LLStringUtil::null, LLStringUtil::null, 0,
  806. LLFolderType::FT_NONE, LLInventoryType::IT_NONE,
  807. 0, 0, 0, 0),
  808. mTaskUpload(true),
  809. mTaskId(task_id),
  810. mContents(buffer),
  811. mInvnFinishFn(NULL),
  812. mTaskFinishFn(finish),
  813. mFailureFn(failed),
  814. mStoredToCache(false)
  815. {
  816. setItemId(item_id);
  817. setAssetType(atype);
  818. setShowInventoryPanel(false);
  819. }
  820. //virtual
  821. LLSD LLBufferedAssetUploadInfo::prepareUpload()
  822. {
  823. if (getAssetId().isNull())
  824. {
  825. generateNewAssetId();
  826. }
  827. LLFileSystem file(getAssetId(), LLFileSystem::APPEND);
  828. S32 size = mContents.length() + 1;
  829. file.write((U8*)mContents.c_str(), size);
  830. mStoredToCache = true;
  831. return LLSD().with("success", LLSD::Boolean(true));
  832. }
  833. //virtual
  834. LLSD LLBufferedAssetUploadInfo::generatePostBody()
  835. {
  836. LLSD body;
  837. if (!getTaskId().isNull())
  838. {
  839. body["task_id"] = getTaskId();
  840. }
  841. body["item_id"] = getItemId();
  842. return body;
  843. }
  844. //virtual
  845. LLUUID LLBufferedAssetUploadInfo::finishUpload(const LLSD& result)
  846. {
  847. LLUUID new_asset_id = result["new_asset"].asUUID();
  848. LLUUID item_id = getItemId();
  849. if (mStoredToCache)
  850. {
  851. LLFileSystem::renameFile(getAssetId(), new_asset_id);
  852. }
  853. if (mTaskUpload)
  854. {
  855. LLUUID task_id = getTaskId();
  856. dialog_refresh_all();
  857. if (mTaskFinishFn)
  858. {
  859. mTaskFinishFn(item_id, task_id, new_asset_id, result);
  860. }
  861. }
  862. else
  863. {
  864. LLUUID new_item_id;
  865. if (item_id.notNull())
  866. {
  867. LLViewerInventoryItem* item =
  868. (LLViewerInventoryItem*)gInventory.getItem(item_id);
  869. if (!item)
  870. {
  871. llwarns << "Inventory item for " << getDisplayName()
  872. << " is no longer in agent inventory." << llendl;
  873. return new_asset_id;
  874. }
  875. // Update viewer inventory item
  876. LLPointer<LLViewerInventoryItem> new_item =
  877. new LLViewerInventoryItem(item);
  878. new_item->setAssetUUID(new_asset_id);
  879. gInventory.updateItem(new_item);
  880. gInventory.notifyObservers();
  881. new_item_id = new_item->getUUID();
  882. llinfos << "Inventory item " << item->getName() << " saved into "
  883. << new_asset_id << llendl;
  884. }
  885. if (mInvnFinishFn)
  886. {
  887. mInvnFinishFn(item_id, new_asset_id, new_item_id, result);
  888. }
  889. }
  890. return new_asset_id;
  891. }
  892. void LLBufferedAssetUploadInfo::failedUpload(const LLSD& result,
  893. std::string& reason)
  894. {
  895. if (!mFailureFn.empty())
  896. {
  897. mFailureFn(getItemId(), getTaskId(), result, reason);
  898. }
  899. }
  900. ///////////////////////////////////////////////////////////////////////////////
  901. // LLScriptAssetUpload class
  902. ///////////////////////////////////////////////////////////////////////////////
  903. LLScriptAssetUpload::LLScriptAssetUpload(const LLUUID& item_id,
  904. const std::string& buffer,
  905. TargetType_t target_type,
  906. inv_uploaded_cb_t finish,
  907. failed_cb_t failed)
  908. : LLBufferedAssetUploadInfo(item_id, LLAssetType::AT_LSL_TEXT, buffer,
  909. finish, failed),
  910. mTargetType(target_type),
  911. mIsRunning(false)
  912. {
  913. }
  914. LLScriptAssetUpload::LLScriptAssetUpload(const LLUUID& task_id,
  915. const LLUUID& item_id,
  916. TargetType_t target_type,
  917. bool running, const LLUUID& exp_id,
  918. const std::string& buffer,
  919. task_uploaded_cb_t finish,
  920. failed_cb_t failed)
  921. : LLBufferedAssetUploadInfo(task_id, item_id, LLAssetType::AT_LSL_TEXT,
  922. buffer, finish, failed),
  923. mExerienceId(exp_id),
  924. mTargetType(target_type),
  925. mIsRunning(running)
  926. {
  927. }
  928. //virtual
  929. LLSD LLScriptAssetUpload::generatePostBody()
  930. {
  931. LLSD body;
  932. body["item_id"] = getItemId();
  933. body["target"] = getTargetType() == MONO ? "mono" : "lsl2";
  934. if (getTaskId().notNull())
  935. {
  936. body["task_id"] = getTaskId();
  937. // NOTE: old code had the running flag as a BOOL (it is now a real
  938. // bool) and a BOOL is actually an S32 (which translates into an
  939. // LLSD::Integer instead of an LLSD::Boolean)... OpenSim expects the
  940. // LLSD for is_script_running to be an Integer, while SL's servers
  941. // accept either an Integer or a Boolean. For compatibility with
  942. // OpenSim, let's pass is_script_running as an LLSD integer. HB
  943. body["is_script_running"] = (LLSD::Integer)getIsRunning();
  944. body["experience"] = getExerienceId();
  945. }
  946. return body;
  947. }
  948. ///////////////////////////////////////////////////////////////////////////////
  949. // LLViewerAssetUpload class
  950. ///////////////////////////////////////////////////////////////////////////////
  951. //static
  952. LLUUID LLViewerAssetUpload::enqueueInventoryUpload(const std::string& url,
  953. const LLResourceUploadInfo::ptr_t& info)
  954. {
  955. std::string name = "LLViewerAssetUpload::assetInventoryUploadCoproc(";
  956. name += LLAssetType::lookup(info->getAssetType());
  957. name += ")";
  958. LLCoprocedureManager* cpmgr = LLCoprocedureManager::getInstance();
  959. LLUUID id =
  960. cpmgr->enqueueCoprocedure("Upload", name,
  961. boost::bind(&LLViewerAssetUpload::assetInventoryUploadCoproc,
  962. _1, url, info));
  963. return id;
  964. }
  965. //static
  966. void LLViewerAssetUpload::assetInventoryUploadCoproc(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t& adapter,
  967. std::string url,
  968. LLResourceUploadInfo::ptr_t info)
  969. {
  970. if (!adapter || !info) return; // Paranoia
  971. LLSD result = info->prepareUpload();
  972. if (result.has("error"))
  973. {
  974. handleUploadError(gStatusInternalError, result, info);
  975. return;
  976. }
  977. info->logPreparedUpload();
  978. // Why is this here ???
  979. llcoro::suspend();
  980. if (info->showUploadDialog())
  981. {
  982. std::string upload_message = "Uploading...\n\n";
  983. upload_message.append(info->getDisplayName());
  984. LLUploadDialog::modalUploadDialog(upload_message);
  985. }
  986. LLCore::HttpOptions::ptr_t httpopt(new LLCore::HttpOptions);
  987. httpopt->setTimeout(LL_ASSET_UPLOAD_TIMEOUT_SEC);
  988. LLSD body = info->generatePostBody();
  989. result = adapter->postAndSuspend(url, body, httpopt);
  990. LLCore::HttpStatus status =
  991. LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(result);
  992. if (!status || result.has("error"))
  993. {
  994. handleUploadError(status, result, info);
  995. if (info->showUploadDialog())
  996. {
  997. LLUploadDialog::modalUploadFinished();
  998. }
  999. return;
  1000. }
  1001. std::string uploader = result["uploader"].asString();
  1002. if (!uploader.empty() && info->getAssetId().notNull())
  1003. {
  1004. result = adapter->postFileAndSuspend(uploader, info->getAssetId(),
  1005. info->getAssetType(), httpopt);
  1006. status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(result);
  1007. if (!status || result["state"].asString() != "complete")
  1008. {
  1009. handleUploadError(status, result, info);
  1010. if (info->showUploadDialog())
  1011. {
  1012. LLUploadDialog::modalUploadFinished();
  1013. }
  1014. return;
  1015. }
  1016. // At this point 'status' is OK and "complete" is here, so it is a
  1017. // success: mark it as such for the callback, if "success" is missing.
  1018. if (!result.has("success"))
  1019. {
  1020. result["success"] = LLSD::Boolean(true);
  1021. }
  1022. S32 upload_price = result["upload_price"].asInteger();
  1023. if (upload_price > 0)
  1024. {
  1025. // This upload costed us L$: update our balance and display
  1026. // something saying that it cost L$
  1027. LLStatusBar::sendMoneyBalanceRequest();
  1028. #if 0 // This should be useless: the balance request will trigger an
  1029. // appropriate server-triggered notification if actually needed...
  1030. LLSD args;
  1031. args["AMOUNT"] = llformat("%d", uploadPrice);
  1032. LLNotificationsUtil::add("UploadPayment", args);
  1033. #endif
  1034. }
  1035. }
  1036. else
  1037. {
  1038. llwarns << "No upload url provided. Nothing uploaded, responding with previous result."
  1039. << llendl;
  1040. }
  1041. LLUUID new_inv_item_id = info->finishUpload(result);
  1042. if (info->showInventoryPanel())
  1043. {
  1044. if (new_inv_item_id.notNull())
  1045. {
  1046. // Show the preview panel for textures and sounds to let the user
  1047. // know that the image (or snapshot) arrived intact.
  1048. LLFloaterInventory* inv = LLFloaterInventory::getActiveFloater();
  1049. if (inv)
  1050. {
  1051. LLFocusableElement* focus = gFocusMgr.getKeyboardFocus();
  1052. inv->getPanel()->setSelection(new_inv_item_id, TAKE_FOCUS_NO);
  1053. LLAssetType::EType asset_type = info->getAssetType();
  1054. if ((asset_type == LLAssetType::AT_TEXTURE &&
  1055. LLPreviewTexture::getPreviewCount() < MAX_PREVIEWS) ||
  1056. (asset_type == LLAssetType::AT_SOUND &&
  1057. LLPreviewSound::getPreviewCount() < MAX_PREVIEWS))
  1058. {
  1059. inv->getPanel()->openSelected();
  1060. }
  1061. // Restore keyboard focus
  1062. gFocusMgr.setKeyboardFocus(focus);
  1063. }
  1064. }
  1065. else
  1066. {
  1067. llwarns << "Cannot find a folder to put it in" << llendl;
  1068. }
  1069. }
  1070. // Remove the "Uploading..." message
  1071. if (info->showUploadDialog())
  1072. {
  1073. LLUploadDialog::modalUploadFinished();
  1074. }
  1075. info->performCallback(result);
  1076. }
  1077. //static
  1078. void LLViewerAssetUpload::handleUploadError(LLCore::HttpStatus status,
  1079. const LLSD& result,
  1080. LLResourceUploadInfo::ptr_t& info)
  1081. {
  1082. llwarns << ll_pretty_print_sd(result) << llendl;
  1083. LLSD args;
  1084. if (result.has("args"))
  1085. {
  1086. args = result["args"];
  1087. }
  1088. std::string reason;
  1089. if (result.has("message"))
  1090. {
  1091. reason = result["message"].asString();
  1092. }
  1093. else
  1094. {
  1095. switch (status.getType())
  1096. {
  1097. case 404:
  1098. reason = LLTrans::getString("ServerUnreachable");
  1099. break;
  1100. case 499:
  1101. reason = LLTrans::getString("ServerDifficulties");
  1102. break;
  1103. case 503:
  1104. reason = LLTrans::getString("ServerUnavailable");
  1105. break;
  1106. default:
  1107. reason = LLTrans::getString("UploadRequestInvalid");
  1108. }
  1109. }
  1110. std::string label;
  1111. if (result.has("label"))
  1112. {
  1113. label = result["label"].asString();
  1114. if (label == "ErrorMessage")
  1115. {
  1116. args["ERROR_MESSAGE"] = reason;
  1117. }
  1118. }
  1119. if (label.empty())
  1120. {
  1121. label = "CannotUploadReason";
  1122. args["FILE"] = info->getDisplayName();
  1123. args["REASON"] = reason;
  1124. }
  1125. gNotifications.add(label, args);
  1126. info->failedUpload(result, reason);
  1127. // Clear any remaining queued bulk upload assets
  1128. gUploadQueueMutex.lock();
  1129. gUploadQueue.clear();
  1130. gUploadQueueMutex.unlock();
  1131. }
  1132. ///////////////////////////////////////////////////////////////////////////////
  1133. // Global utlility functions for uploading assets
  1134. // This is called each time an upload happened via upload_new_resource(),
  1135. // unless an user-callback was specified. Also used in llviewermenu.cpp to
  1136. // initiate bulk uploads.
  1137. void process_bulk_upload_queue(const LLSD& result, void* userdata)
  1138. {
  1139. gUploadQueueMutex.lock();
  1140. if (gUploadQueue.empty())
  1141. {
  1142. gUploadQueueMutex.unlock();
  1143. return;
  1144. }
  1145. std::string next_file = gUploadQueue.front();
  1146. gUploadQueue.pop_front();
  1147. gUploadQueueMutex.unlock();
  1148. if (next_file.empty())
  1149. {
  1150. return;
  1151. }
  1152. std::string asset_name = gDirUtil.getBaseFileName(next_file, true);
  1153. LLStringUtil::replaceNonstandardASCII(asset_name, '?');
  1154. LLStringUtil::replaceChar(asset_name, '|', '?');
  1155. LLStringUtil::stripNonprintable(asset_name);
  1156. LLStringUtil::trim(asset_name);
  1157. LLNewFileResourceUploadInfo* infop =
  1158. new LLNewFileResourceUploadInfo(next_file,
  1159. asset_name, asset_name, 0,
  1160. LLFolderType::FT_NONE,
  1161. LLInventoryType::IT_NONE,
  1162. LLFloaterPerms::getNextOwnerPerms(),
  1163. LLFloaterPerms::getGroupPerms(),
  1164. LLFloaterPerms::getEveryonePerms(),
  1165. -1); // Unknown upload cost
  1166. infop->setIsBulkUpload();
  1167. LLResourceUploadInfo::ptr_t info(infop);
  1168. upload_new_resource(info);
  1169. }
  1170. // Local, default callbacks
  1171. void upload_done_callback(const LLUUID& uuid, void* user_data,
  1172. S32 result, LLExtStat ext_status)
  1173. {
  1174. LLResourceData* data = (LLResourceData*)user_data;
  1175. if (data)
  1176. {
  1177. if (result >= 0)
  1178. {
  1179. LLFolderType::EType dest_loc;
  1180. if (data->mPreferredLocation == LLFolderType::FT_NONE)
  1181. {
  1182. dest_loc =
  1183. LLFolderType::assetTypeToFolderType(data->mAssetInfo.mType);
  1184. }
  1185. else
  1186. {
  1187. dest_loc = data->mPreferredLocation;
  1188. }
  1189. LLAssetType::EType asset_type = data->mAssetInfo.mType;
  1190. if (data->mExpectedUploadCost < 0) // Unknown upload cost
  1191. {
  1192. data->mExpectedUploadCost =
  1193. upload_cost_for_asset_type(asset_type);
  1194. }
  1195. bool is_balance_sufficient = true;
  1196. if (asset_type == LLAssetType::AT_SOUND ||
  1197. asset_type == LLAssetType::AT_TEXTURE ||
  1198. asset_type == LLAssetType::AT_ANIMATION)
  1199. {
  1200. // Charge the user for the upload.
  1201. LLViewerRegion* region = gAgent.getRegion();
  1202. if (!can_afford_transaction(data->mExpectedUploadCost))
  1203. {
  1204. // *TODO: Translate
  1205. LLFloaterBuyCurrency::buyCurrency(llformat("Uploading %s costs",
  1206. data->mAssetInfo.getName().c_str()),
  1207. data->mExpectedUploadCost);
  1208. is_balance_sufficient = false;
  1209. }
  1210. else if (region)
  1211. {
  1212. // Charge user for upload
  1213. if (gStatusBarp)
  1214. {
  1215. gStatusBarp->debitBalance(data->mExpectedUploadCost);
  1216. }
  1217. LLMessageSystem* msg = gMessageSystemp;
  1218. msg->newMessageFast(_PREHASH_MoneyTransferRequest);
  1219. msg->nextBlockFast(_PREHASH_AgentData);
  1220. msg->addUUIDFast(_PREHASH_AgentID, gAgentID);
  1221. msg->addUUIDFast(_PREHASH_SessionID, gAgentSessionID);
  1222. msg->nextBlockFast(_PREHASH_MoneyData);
  1223. msg->addUUIDFast(_PREHASH_SourceID, gAgentID);
  1224. msg->addUUIDFast(_PREHASH_DestID, LLUUID::null);
  1225. msg->addU8("Flags", 0);
  1226. // we tell the sim how much we were expecting to pay so it
  1227. // can respond to any discrepancy
  1228. msg->addS32Fast(_PREHASH_Amount,
  1229. data->mExpectedUploadCost);
  1230. msg->addU8Fast(_PREHASH_AggregatePermNextOwner,
  1231. (U8)LLAggregatePermissions::AP_EMPTY);
  1232. msg->addU8Fast(_PREHASH_AggregatePermInventory,
  1233. (U8)LLAggregatePermissions::AP_EMPTY);
  1234. msg->addS32Fast(_PREHASH_TransactionType,
  1235. TRANS_UPLOAD_CHARGE);
  1236. msg->addStringFast(_PREHASH_Description, NULL);
  1237. msg->sendReliable(region->getHost());
  1238. }
  1239. }
  1240. if (is_balance_sufficient)
  1241. {
  1242. // Actually add the upload to inventory
  1243. llinfos << "Adding " << uuid << " to inventory." << llendl;
  1244. const LLUUID folder_id =
  1245. gInventory.findChoosenCategoryUUIDForType(dest_loc);
  1246. if (folder_id.notNull())
  1247. {
  1248. U32 next_owner_perms = data->mNextOwnerPerm;
  1249. if (next_owner_perms == PERM_NONE)
  1250. {
  1251. next_owner_perms = PERM_MOVE | PERM_TRANSFER;
  1252. }
  1253. create_inventory_item(folder_id,
  1254. data->mAssetInfo.mTransactionID,
  1255. data->mAssetInfo.getName(),
  1256. data->mAssetInfo.getDescription(),
  1257. data->mAssetInfo.mType,
  1258. data->mInventoryType,
  1259. NO_INV_SUBTYPE, next_owner_perms);
  1260. }
  1261. else
  1262. {
  1263. llwarns << "Cannot find an adequate inventory folder for: "
  1264. << data->mAssetInfo.getName() << llendl;
  1265. }
  1266. }
  1267. }
  1268. else
  1269. {
  1270. LLSD args;
  1271. args["FILE"] =
  1272. LLInventoryType::lookupHumanReadable(data->mInventoryType);
  1273. args["REASON"] =
  1274. std::string(LLAssetStorage::getErrorString(result));
  1275. gNotifications.add("CannotUploadReason", args);
  1276. }
  1277. delete data;
  1278. data = NULL;
  1279. }
  1280. LLUploadDialog::modalUploadFinished();
  1281. process_bulk_upload_queue();
  1282. }
  1283. void temp_upload_done_callback(const LLUUID& uuid, void* user_data,
  1284. S32 result, LLExtStat ext_status)
  1285. {
  1286. LLResourceData* data = (LLResourceData*)user_data;
  1287. if (data && result >= 0)
  1288. {
  1289. LLFolderType::EType dest_loc =
  1290. data->mPreferredLocation == LLFolderType::FT_NONE ?
  1291. LLFolderType::assetTypeToFolderType(data->mAssetInfo.mType) :
  1292. data->mPreferredLocation;
  1293. LLUUID folder_id(gInventory.findChoosenCategoryUUIDForType(dest_loc));
  1294. LLUUID item_id;
  1295. item_id.generate();
  1296. LLPermissions perm;
  1297. perm.init(gAgentID, gAgentID, gAgentID, gAgentID);
  1298. perm.setMaskBase(PERM_ALL);
  1299. perm.setMaskOwner(PERM_ALL);
  1300. perm.setMaskEveryone(PERM_ALL);
  1301. perm.setMaskGroup(PERM_ALL);
  1302. LLPointer<LLViewerInventoryItem> item =
  1303. new LLViewerInventoryItem(item_id, folder_id, perm,
  1304. data->mAssetInfo.mTransactionID.makeAssetID(gAgent.getSecureSessionID()),
  1305. data->mAssetInfo.mType,
  1306. data->mInventoryType,
  1307. data->mAssetInfo.getName(),
  1308. "Temporary asset", LLSaleInfo::DEFAULT,
  1309. LLInventoryItem::II_FLAGS_NONE,
  1310. time_corrected());
  1311. item->updateServer(true);
  1312. gInventory.updateItem(item);
  1313. gInventory.notifyObservers();
  1314. open_texture(item_id, std::string("Texture: ") + item->getName(), true,
  1315. LLUUID::null, false);
  1316. }
  1317. else
  1318. {
  1319. LLSD args;
  1320. args["FILE"] =
  1321. LLInventoryType::lookupHumanReadable(data->mInventoryType);
  1322. args["REASON"] = std::string(LLAssetStorage::getErrorString(result));
  1323. gNotifications.add("CannotUploadReason", args);
  1324. }
  1325. LLUploadDialog::modalUploadFinished();
  1326. delete data;
  1327. }
  1328. void upload_new_resource(LLResourceUploadInfo::ptr_t& info,
  1329. LLAssetStorage::LLStoreAssetCallback callback,
  1330. void* userdata, bool temp_upload)
  1331. {
  1332. if (gDisconnected || !info)
  1333. {
  1334. return;
  1335. }
  1336. const std::string& url =
  1337. gAgent.getRegionCapability("NewFileAgentInventory");
  1338. if (!url.empty() && !temp_upload)
  1339. {
  1340. llinfos << "New agent inventory via capability" << llendl;
  1341. if (!info->hasCapCallback())
  1342. {
  1343. info->setCapCallback(process_bulk_upload_queue, NULL);
  1344. }
  1345. LLViewerAssetUpload::enqueueInventoryUpload(url, info);
  1346. }
  1347. else
  1348. {
  1349. info->prepareUpload();
  1350. info->logPreparedUpload();
  1351. S32 expected_upload_cost = info->getExpectedUploadCost();
  1352. LLAssetType::EType asset_type = info->getAssetType();
  1353. if (temp_upload)
  1354. {
  1355. expected_upload_cost = 0;
  1356. info->setName("[temp] " + info->getName());
  1357. llinfos << "Uploading " << info->getName()
  1358. << " as a temporary (baked) texture via the asset system."
  1359. << llendl;
  1360. }
  1361. else
  1362. {
  1363. llinfos << "NewAgentInventory capability not found, new agent inventory via asset system."
  1364. << llendl;
  1365. // Check for adequate funds. *TODO: do this check on the sim.
  1366. if (asset_type == LLAssetType::AT_SOUND ||
  1367. asset_type == LLAssetType::AT_TEXTURE ||
  1368. asset_type == LLAssetType::AT_ANIMATION)
  1369. {
  1370. S32 balance = gStatusBarp->getBalance();
  1371. if (balance < expected_upload_cost)
  1372. {
  1373. // Insufficient funds, bail on this upload
  1374. LLFloaterBuyCurrency::buyCurrency("Uploading costs",
  1375. expected_upload_cost);
  1376. return;
  1377. }
  1378. }
  1379. }
  1380. LLResourceData* data = new LLResourceData;
  1381. data->mAssetInfo.mTransactionID = info->getTransactionId();
  1382. data->mAssetInfo.mUuid = info->getAssetId();
  1383. data->mAssetInfo.mType = asset_type;
  1384. data->mAssetInfo.mCreatorID = gAgentID;
  1385. data->mInventoryType = info->getInventoryType();
  1386. data->mNextOwnerPerm = info->getNextOwnerPerms();
  1387. data->mExpectedUploadCost = expected_upload_cost;
  1388. data->mUserData = userdata;
  1389. data->mAssetInfo.setName(info->getName());
  1390. data->mAssetInfo.setDescription(info->getDescription());
  1391. data->mPreferredLocation = info->getDestinationFolderType();
  1392. LLAssetStorage::LLStoreAssetCallback asset_callback;
  1393. asset_callback = temp_upload ? &temp_upload_done_callback
  1394. : &upload_done_callback;
  1395. if (callback)
  1396. {
  1397. asset_callback = callback;
  1398. }
  1399. gAssetStoragep->storeAssetData(data->mAssetInfo.mTransactionID,
  1400. data->mAssetInfo.mType,
  1401. asset_callback, (void*)data,
  1402. temp_upload, true, temp_upload);
  1403. }
  1404. }
  1405. void on_new_single_inventory_upload_complete(LLAssetType::EType asset_type,
  1406. LLInventoryType::EType inv_type,
  1407. const std::string inv_type_str,
  1408. const LLUUID& item_folder_id,
  1409. const std::string& item_name,
  1410. const std::string& item_description,
  1411. const LLSD& response,
  1412. S32 upload_price)
  1413. {
  1414. if (upload_price > 0)
  1415. {
  1416. // this upload costed us L$, update our balance and display something
  1417. // saying that it cost L$
  1418. LLStatusBar::sendMoneyBalanceRequest();
  1419. LLSD args;
  1420. args["AMOUNT"] = llformat("%d", upload_price);
  1421. gNotifications.add("UploadDone", args);
  1422. }
  1423. if (item_folder_id.notNull())
  1424. {
  1425. U32 everyone_perms = PERM_NONE;
  1426. U32 group_perms = PERM_NONE;
  1427. U32 next_owner_perms = PERM_ALL;
  1428. if (response.has("new_next_owner_mask"))
  1429. {
  1430. // The server provided creation perms so use them. Do not assume we
  1431. // got the perms we asked for since the server may not have granted
  1432. // them all.
  1433. everyone_perms = response["new_everyone_mask"].asInteger();
  1434. group_perms = response["new_group_mask"].asInteger();
  1435. next_owner_perms = response["new_next_owner_mask"].asInteger();
  1436. }
  1437. else
  1438. {
  1439. // The server does not provide creation perms, so use tha old
  1440. // assumption-based perms.
  1441. if (inv_type_str != "snapshot")
  1442. {
  1443. next_owner_perms = PERM_MOVE | PERM_TRANSFER;
  1444. }
  1445. }
  1446. LLPermissions new_perms;
  1447. new_perms.init(gAgentID, gAgentID, LLUUID::null, LLUUID::null);
  1448. new_perms.initMasks(PERM_ALL, PERM_ALL, everyone_perms, group_perms,
  1449. next_owner_perms);
  1450. U32 inv_item_flags = 0;
  1451. if (response.has("inventory_flags"))
  1452. {
  1453. inv_item_flags = response["inventory_flags"].asInteger();
  1454. if (inv_item_flags)
  1455. {
  1456. llinfos << "Inventory item flags: " << inv_item_flags
  1457. << llendl;
  1458. }
  1459. }
  1460. S32 creation_date_now = time_corrected();
  1461. LLPointer<LLViewerInventoryItem> item =
  1462. new LLViewerInventoryItem(response["new_inventory_item"].asUUID(),
  1463. item_folder_id, new_perms,
  1464. response["new_asset"].asUUID(),
  1465. asset_type, inv_type, item_name,
  1466. item_description, LLSaleInfo::DEFAULT,
  1467. inv_item_flags, creation_date_now);
  1468. gInventory.updateItem(item);
  1469. gInventory.notifyObservers();
  1470. // Show the preview panel for textures and sounds to let user know that
  1471. // the image (or snapshot) arrived intact.
  1472. LLFloaterInventory* inv = LLFloaterInventory::getActiveFloater();
  1473. if (inv)
  1474. {
  1475. LLFocusableElement* focus = gFocusMgr.getKeyboardFocus();
  1476. inv->getPanel()->setSelection(response["new_inventory_item"].asUUID(),
  1477. TAKE_FOCUS_NO);
  1478. if ((LLAssetType::AT_TEXTURE == asset_type &&
  1479. LLPreviewTexture::getPreviewCount() < MAX_PREVIEWS) ||
  1480. (LLAssetType::AT_SOUND == asset_type &&
  1481. LLPreviewSound::getPreviewCount() < MAX_PREVIEWS))
  1482. {
  1483. inv->getPanel()->openSelected();
  1484. }
  1485. // Restore keyboard focus
  1486. gFocusMgr.setKeyboardFocus(focus);
  1487. }
  1488. }
  1489. else
  1490. {
  1491. llwarns << "Cannot find a folder to put '" << item_name << "' into."
  1492. << llendl;
  1493. }
  1494. // Remove the "Uploading..." message
  1495. LLUploadDialog::modalUploadFinished();
  1496. }