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

游戏引擎

开发平台:

C++ Builder

  1. /** 
  2.  * @file llviewermenufile.cpp
  3.  * @brief "File" menu in the main menu bar.
  4.  *
  5.  * $LicenseInfo:firstyear=2002&license=viewergpl$
  6.  * 
  7.  * Copyright (c) 2002-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 "llviewermenufile.h"
  34. // project includes
  35. #include "llagent.h"
  36. #include "llfilepicker.h"
  37. #include "llfloaterreg.h"
  38. #include "llfloaterbuycurrency.h"
  39. #include "llfloatersnapshot.h"
  40. #include "llimage.h"
  41. #include "llimagebmp.h"
  42. #include "llimagepng.h"
  43. #include "llimagej2c.h"
  44. #include "llimagejpeg.h"
  45. #include "llimagetga.h"
  46. #include "llinventorymodel.h" // gInventory
  47. #include "llresourcedata.h"
  48. #include "llfloaterperms.h"
  49. #include "llstatusbar.h"
  50. #include "llviewercontrol.h" // gSavedSettings
  51. #include "llviewertexturelist.h"
  52. #include "lluictrlfactory.h"
  53. #include "llvfile.h"
  54. #include "llvfs.h"
  55. #include "llviewerinventory.h"
  56. #include "llviewermenu.h" // gMenuHolder
  57. #include "llviewerregion.h"
  58. #include "llviewerstats.h"
  59. #include "llviewerwindow.h"
  60. #include "llappviewer.h"
  61. #include "lluploaddialog.h"
  62. #include "lltrans.h"
  63. // linden libraries
  64. #include "llassetuploadresponders.h"
  65. #include "lleconomy.h"
  66. #include "llhttpclient.h"
  67. #include "llnotificationsutil.h"
  68. #include "llsdserialize.h"
  69. #include "llstring.h"
  70. #include "lltransactiontypes.h"
  71. #include "lluuid.h"
  72. #include "llvorbisencode.h"
  73. #include "message.h"
  74. // system libraries
  75. #include <boost/tokenizer.hpp>
  76. class LLFileEnableUpload : public view_listener_t
  77. {
  78. bool handleEvent(const LLSD& userdata)
  79. {
  80. bool new_value = gStatusBar && LLGlobalEconomy::Singleton::getInstance() && (gStatusBar->getBalance() >= LLGlobalEconomy::Singleton::getInstance()->getPriceUpload());
  81. return new_value;
  82. }
  83. };
  84. //============================================================================
  85. #if LL_WINDOWS
  86. static std::string SOUND_EXTENSIONS = "wav";
  87. static std::string IMAGE_EXTENSIONS = "tga bmp jpg jpeg png";
  88. static std::string ANIM_EXTENSIONS =  "bvh";
  89. #ifdef _CORY_TESTING
  90. static std::string GEOMETRY_EXTENSIONS = "slg";
  91. #endif
  92. static std::string XML_EXTENSIONS = "xml";
  93. static std::string SLOBJECT_EXTENSIONS = "slobject";
  94. #endif
  95. static std::string ALL_FILE_EXTENSIONS = "*.*";
  96. std::string build_extensions_string(LLFilePicker::ELoadFilter filter)
  97. {
  98. switch(filter)
  99. {
  100. #if LL_WINDOWS
  101. case LLFilePicker::FFLOAD_IMAGE:
  102. return IMAGE_EXTENSIONS;
  103. case LLFilePicker::FFLOAD_WAV:
  104. return SOUND_EXTENSIONS;
  105. case LLFilePicker::FFLOAD_ANIM:
  106. return ANIM_EXTENSIONS;
  107. case LLFilePicker::FFLOAD_SLOBJECT:
  108. return SLOBJECT_EXTENSIONS;
  109. #ifdef _CORY_TESTING
  110. case LLFilePicker::FFLOAD_GEOMETRY:
  111. return GEOMETRY_EXTENSIONS;
  112. #endif
  113. case LLFilePicker::FFLOAD_XML:
  114.     return XML_EXTENSIONS;
  115. case LLFilePicker::FFLOAD_ALL:
  116. return ALL_FILE_EXTENSIONS;
  117. #endif
  118.     default:
  119. return ALL_FILE_EXTENSIONS;
  120. }
  121. }
  122. /**
  123.    char* upload_pick(void* data)
  124.    If applicable, brings up a file chooser in which the user selects a file
  125.    to upload for a particular task.  If the file is valid for the given action,
  126.    returns the string to the full path filename, else returns NULL.
  127.    Data is the load filter for the type of file as defined in LLFilePicker.
  128. **/
  129. const std::string upload_pick(void* data)
  130. {
  131.   if( gAgent.cameraMouselook() )
  132. {
  133. gAgent.changeCameraToDefault();
  134. // This doesn't seem necessary. JC
  135. // display();
  136. }
  137. LLFilePicker::ELoadFilter type;
  138. if(data)
  139. {
  140. type = (LLFilePicker::ELoadFilter)((intptr_t)data);
  141. }
  142. else
  143. {
  144. type = LLFilePicker::FFLOAD_ALL;
  145. }
  146. LLFilePicker& picker = LLFilePicker::instance();
  147. if (!picker.getOpenFile(type))
  148. {
  149. llinfos << "Couldn't import objects from file" << llendl;
  150. return std::string();
  151. }
  152. const std::string& filename = picker.getFirstFile();
  153. std::string ext = gDirUtilp->getExtension(filename);
  154. //strincmp doesn't like NULL pointers
  155. if (ext.empty())
  156. {
  157. std::string short_name = gDirUtilp->getBaseFileName(filename);
  158. // No extension
  159. LLSD args;
  160. args["FILE"] = short_name;
  161. LLNotificationsUtil::add("NoFileExtension", args);
  162. return std::string();
  163. }
  164. else
  165. {
  166. //so there is an extension
  167. //loop over the valid extensions and compare to see
  168. //if the extension is valid
  169. //now grab the set of valid file extensions
  170. std::string valid_extensions = build_extensions_string(type);
  171. BOOL ext_valid = FALSE;
  172. typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
  173. boost::char_separator<char> sep(" ");
  174. tokenizer tokens(valid_extensions, sep);
  175. tokenizer::iterator token_iter;
  176. //now loop over all valid file extensions
  177. //and compare them to the extension of the file
  178. //to be uploaded
  179. for( token_iter = tokens.begin();
  180.  token_iter != tokens.end() && ext_valid != TRUE;
  181.  ++token_iter)
  182. {
  183. const std::string& cur_token = *token_iter;
  184. if (cur_token == ext || cur_token == "*.*")
  185. {
  186. //valid extension
  187. //or the acceptable extension is any
  188. ext_valid = TRUE;
  189. }
  190. }//end for (loop over all tokens)
  191. if (ext_valid == FALSE)
  192. {
  193. //should only get here if the extension exists
  194. //but is invalid
  195. LLSD args;
  196. args["EXTENSION"] = ext;
  197. args["VALIDS"] = valid_extensions;
  198. LLNotificationsUtil::add("InvalidFileExtension", args);
  199. return std::string();
  200. }
  201. }//end else (non-null extension)
  202. //valid file extension
  203. //now we check to see
  204. //if the file is actually a valid image/sound/etc.
  205. if (type == LLFilePicker::FFLOAD_WAV)
  206. {
  207. // pre-qualify wavs to make sure the format is acceptable
  208. std::string error_msg;
  209. if (check_for_invalid_wav_formats(filename,error_msg))
  210. {
  211. llinfos << error_msg << ": " << filename << llendl;
  212. LLSD args;
  213. args["FILE"] = filename;
  214. LLNotificationsUtil::add( error_msg, args );
  215. return std::string();
  216. }
  217. }//end if a wave/sound file
  218. return filename;
  219. }
  220. class LLFileUploadImage : public view_listener_t
  221. {
  222. bool handleEvent(const LLSD& userdata)
  223. {
  224. std::string filename = upload_pick((void *)LLFilePicker::FFLOAD_IMAGE);
  225. if (!filename.empty())
  226. {
  227. LLFloaterReg::showInstance("upload_image", LLSD(filename));
  228. }
  229. return TRUE;
  230. }
  231. };
  232. class LLFileUploadSound : public view_listener_t
  233. {
  234. bool handleEvent(const LLSD& userdata)
  235. {
  236. std::string filename = upload_pick((void*)LLFilePicker::FFLOAD_WAV);
  237. if (!filename.empty())
  238. {
  239. LLFloaterReg::showInstance("upload_sound", LLSD(filename));
  240. }
  241. return true;
  242. }
  243. };
  244. class LLFileUploadAnim : public view_listener_t
  245. {
  246. bool handleEvent(const LLSD& userdata)
  247. {
  248. const std::string filename = upload_pick((void*)LLFilePicker::FFLOAD_ANIM);
  249. if (!filename.empty())
  250. {
  251. LLFloaterReg::showInstance("upload_anim", LLSD(filename));
  252. }
  253. return true;
  254. }
  255. };
  256. class LLFileUploadBulk : public view_listener_t
  257. {
  258. bool handleEvent(const LLSD& userdata)
  259. {
  260. if( gAgent.cameraMouselook() )
  261. {
  262. gAgent.changeCameraToDefault();
  263. }
  264. // TODO:
  265. // Iterate over all files
  266. // Check extensions for uploadability, cost
  267. // Check user balance for entire cost
  268. // Charge user entire cost
  269. // Loop, uploading
  270. // If an upload fails, refund the user for that one
  271. //
  272. // Also fix single upload to charge first, then refund
  273. LLFilePicker& picker = LLFilePicker::instance();
  274. if (picker.getMultipleOpenFiles())
  275. {
  276. const std::string& filename = picker.getFirstFile();
  277. std::string name = gDirUtilp->getBaseFileName(filename, true);
  278. std::string asset_name = name;
  279. LLStringUtil::replaceNonstandardASCII( asset_name, '?' );
  280. LLStringUtil::replaceChar(asset_name, '|', '?');
  281. LLStringUtil::stripNonprintable(asset_name);
  282. LLStringUtil::trim(asset_name);
  283. std::string display_name = LLStringUtil::null;
  284. LLAssetStorage::LLStoreAssetCallback callback = NULL;
  285. S32 expected_upload_cost = LLGlobalEconomy::Singleton::getInstance()->getPriceUpload();
  286. void *userdata = NULL;
  287. upload_new_resource(filename, asset_name, asset_name, 0, LLFolderType::FT_NONE, LLInventoryType::IT_NONE,
  288. LLFloaterPerms::getNextOwnerPerms(), LLFloaterPerms::getGroupPerms(), LLFloaterPerms::getEveryonePerms(),
  289.     display_name,
  290.     callback, expected_upload_cost, userdata);
  291. // *NOTE: Ew, we don't iterate over the file list here,
  292. // we handle the next files in upload_done_callback()
  293. }
  294. else
  295. {
  296. llinfos << "Couldn't import objects from file" << llendl;
  297. }
  298. return true;
  299. }
  300. };
  301. void upload_error(const std::string& error_message, const std::string& label, const std::string& filename, const LLSD& args) 
  302. {
  303. llwarns << error_message << llendl;
  304. LLNotificationsUtil::add(label, args);
  305. if(LLFile::remove(filename) == -1)
  306. {
  307. lldebugs << "unable to remove temp file" << llendl;
  308. }
  309. LLFilePicker::instance().reset();
  310. }
  311. class LLFileEnableCloseWindow : public view_listener_t
  312. {
  313. bool handleEvent(const LLSD& userdata)
  314. {
  315. bool new_value = NULL != LLFloater::getClosableFloaterFromFocus();
  316. return new_value;
  317. }
  318. };
  319. class LLFileCloseWindow : public view_listener_t
  320. {
  321. bool handleEvent(const LLSD& userdata)
  322. {
  323. LLFloater::closeFocusedFloater();
  324. return true;
  325. }
  326. };
  327. class LLFileEnableCloseAllWindows : public view_listener_t
  328. {
  329. bool handleEvent(const LLSD& userdata)
  330. {
  331. bool open_children = gFloaterView->allChildrenClosed();
  332. return !open_children;
  333. }
  334. };
  335. class LLFileCloseAllWindows : public view_listener_t
  336. {
  337. bool handleEvent(const LLSD& userdata)
  338. {
  339. bool app_quitting = false;
  340. gFloaterView->closeAllChildren(app_quitting);
  341. return true;
  342. }
  343. };
  344. class LLFileTakeSnapshotToDisk : public view_listener_t
  345. {
  346. bool handleEvent(const LLSD& userdata)
  347. {
  348. LLPointer<LLImageRaw> raw = new LLImageRaw;
  349. S32 width = gViewerWindow->getWindowWidthRaw();
  350. S32 height = gViewerWindow->getWindowHeightRaw();
  351. if (gSavedSettings.getBOOL("HighResSnapshot"))
  352. {
  353. width *= 2;
  354. height *= 2;
  355. }
  356. if (gViewerWindow->rawSnapshot(raw,
  357.    width,
  358.    height,
  359.    TRUE,
  360.    FALSE,
  361.    gSavedSettings.getBOOL("RenderUIInSnapshot"),
  362.    FALSE))
  363. {
  364. gViewerWindow->playSnapshotAnimAndSound();
  365. LLImageBase::setSizeOverride(TRUE);
  366. LLPointer<LLImageFormatted> formatted;
  367. switch(LLFloaterSnapshot::ESnapshotFormat(gSavedSettings.getS32("SnapshotFormat")))
  368. {
  369.   case LLFloaterSnapshot::SNAPSHOT_FORMAT_JPEG:
  370. formatted = new LLImageJPEG(gSavedSettings.getS32("SnapshotQuality"));
  371. break;
  372.   case LLFloaterSnapshot::SNAPSHOT_FORMAT_PNG:
  373. formatted = new LLImagePNG;
  374. break;
  375.   case LLFloaterSnapshot::SNAPSHOT_FORMAT_BMP: 
  376. formatted = new LLImageBMP;
  377. break;
  378.   default: 
  379. llwarns << "Unknown Local Snapshot format" << llendl;
  380. LLImageBase::setSizeOverride(FALSE);
  381. return true;
  382. }
  383. formatted->encode(raw, 0);
  384. LLImageBase::setSizeOverride(FALSE);
  385. gViewerWindow->saveImageNumbered(formatted);
  386. }
  387. return true;
  388. }
  389. };
  390. class LLFileQuit : public view_listener_t
  391. {
  392. bool handleEvent(const LLSD& userdata)
  393. {
  394. LLAppViewer::instance()->userQuit();
  395. return true;
  396. }
  397. };
  398. void handle_compress_image(void*)
  399. {
  400. LLFilePicker& picker = LLFilePicker::instance();
  401. if (picker.getMultipleOpenFiles(LLFilePicker::FFLOAD_IMAGE))
  402. {
  403. std::string infile = picker.getFirstFile();
  404. while (!infile.empty())
  405. {
  406. std::string outfile = infile + ".j2c";
  407. llinfos << "Input:  " << infile << llendl;
  408. llinfos << "Output: " << outfile << llendl;
  409. BOOL success;
  410. success = LLViewerTextureList::createUploadFile(infile, outfile, IMG_CODEC_TGA);
  411. if (success)
  412. {
  413. llinfos << "Compression complete" << llendl;
  414. }
  415. else
  416. {
  417. llinfos << "Compression failed: " << LLImage::getLastError() << llendl;
  418. }
  419. infile = picker.getNextFile();
  420. }
  421. }
  422. }
  423. void upload_new_resource(const std::string& src_filename, std::string name,
  424.  std::string desc, S32 compression_info,
  425.  LLFolderType::EType destination_folder_type,
  426.  LLInventoryType::EType inv_type,
  427.  U32 next_owner_perms,
  428.  U32 group_perms,
  429.  U32 everyone_perms,
  430.  const std::string& display_name,
  431.  LLAssetStorage::LLStoreAssetCallback callback,
  432.  S32 expected_upload_cost,
  433.  void *userdata)
  434. {
  435. // Generate the temporary UUID.
  436. std::string filename = gDirUtilp->getTempFilename();
  437. LLTransactionID tid;
  438. LLAssetID uuid;
  439. LLSD args;
  440. std::string exten = gDirUtilp->getExtension(src_filename);
  441. LLAssetType::EType asset_type = LLAssetType::AT_NONE;
  442. std::string error_message;
  443. BOOL error = FALSE;
  444. if (exten.empty())
  445. {
  446. std::string short_name = gDirUtilp->getBaseFileName(filename);
  447. // No extension
  448. error_message = llformat(
  449. "No file extension for the file: '%s'nPlease make sure the file has a correct file extension",
  450. short_name.c_str());
  451. args["FILE"] = short_name;
  452.   upload_error(error_message, "NofileExtension", filename, args);
  453. return;
  454. }
  455. else if( exten == "bmp")
  456. {
  457. asset_type = LLAssetType::AT_TEXTURE;
  458. if (!LLViewerTextureList::createUploadFile(src_filename,
  459.  filename,
  460.  IMG_CODEC_BMP ))
  461. {
  462. error_message = llformat( "Problem with file %s:nn%sn",
  463. src_filename.c_str(), LLImage::getLastError().c_str());
  464. args["FILE"] = src_filename;
  465. args["ERROR"] = LLImage::getLastError();
  466. upload_error(error_message, "ProblemWithFile", filename, args);
  467. return;
  468. }
  469. }
  470. else if( exten == "tga")
  471. {
  472. asset_type = LLAssetType::AT_TEXTURE;
  473. if (!LLViewerTextureList::createUploadFile(src_filename,
  474.  filename,
  475.  IMG_CODEC_TGA ))
  476. {
  477. error_message = llformat("Problem with file %s:nn%sn",
  478. src_filename.c_str(), LLImage::getLastError().c_str());
  479. args["FILE"] = src_filename;
  480. args["ERROR"] = LLImage::getLastError();
  481. upload_error(error_message, "ProblemWithFile", filename, args);
  482. return;
  483. }
  484. }
  485. else if( exten == "jpg" || exten == "jpeg")
  486. {
  487. asset_type = LLAssetType::AT_TEXTURE;
  488. if (!LLViewerTextureList::createUploadFile(src_filename,
  489.  filename,
  490.  IMG_CODEC_JPEG ))
  491. {
  492. error_message = llformat("Problem with file %s:nn%sn",
  493. src_filename.c_str(), LLImage::getLastError().c_str());
  494. args["FILE"] = src_filename;
  495. args["ERROR"] = LLImage::getLastError();
  496. upload_error(error_message, "ProblemWithFile", filename, args);
  497. return;
  498. }
  499. }
  500.   else if( exten == "png")
  501.   {
  502.   asset_type = LLAssetType::AT_TEXTURE;
  503.   if (!LLViewerTextureList::createUploadFile(src_filename,
  504.    filename,
  505.    IMG_CODEC_PNG ))
  506.   {
  507.   error_message = llformat("Problem with file %s:nn%sn",
  508.   src_filename.c_str(), LLImage::getLastError().c_str());
  509.   args["FILE"] = src_filename;
  510.   args["ERROR"] = LLImage::getLastError();
  511.   upload_error(error_message, "ProblemWithFile", filename, args);
  512.   return;
  513.   }
  514.   }
  515. else if(exten == "wav")
  516. {
  517. asset_type = LLAssetType::AT_SOUND;  // tag it as audio
  518. S32 encode_result = 0;
  519. llinfos << "Attempting to encode wav as an ogg file" << llendl;
  520. encode_result = encode_vorbis_file(src_filename, filename);
  521. if (LLVORBISENC_NOERR != encode_result)
  522. {
  523. switch(encode_result)
  524. {
  525. case LLVORBISENC_DEST_OPEN_ERR:
  526.     error_message = llformat( "Couldn't open temporary compressed sound file for writing: %sn", filename.c_str());
  527. args["FILE"] = filename;
  528. upload_error(error_message, "CannotOpenTemporarySoundFile", filename, args);
  529. break;
  530. default:
  531.   error_message = llformat("Unknown vorbis encode failure on: %sn", src_filename.c_str());
  532. args["FILE"] = src_filename;
  533. upload_error(error_message, "UnknownVorbisEncodeFailure", filename, args);
  534. break;
  535. }
  536. return;
  537. }
  538. }
  539. else if(exten == "tmp")  
  540. {  
  541. // This is a generic .lin resource file  
  542.          asset_type = LLAssetType::AT_OBJECT;  
  543.          LLFILE* in = LLFile::fopen(src_filename, "rb"); /* Flawfinder: ignore */  
  544.          if (in)  
  545.          {  
  546.                  // read in the file header  
  547.                  char buf[16384]; /* Flawfinder: ignore */ 
  548.                  size_t readbytes;
  549.                  S32  version;  
  550.                  if (fscanf(in, "LindenResourcenversion %dn", &version))  
  551.                  {  
  552.                          if (2 == version)  
  553.                          {
  554. // *NOTE: This buffer size is hard coded into scanf() below.
  555.                                  char label[MAX_STRING]; /* Flawfinder: ignore */  
  556.                                  char value[MAX_STRING]; /* Flawfinder: ignore */  
  557.                                  S32  tokens_read;  
  558.                                  while (fgets(buf, 1024, in))  
  559.                                  {  
  560.                                          label[0] = '';  
  561.                                          value[0] = '';  
  562.                                          tokens_read = sscanf( /* Flawfinder: ignore */
  563.  buf,
  564.  "%254s %254sn",
  565.  label, value);  
  566.                                          llinfos << "got: " << label << " = " << value  
  567.                                                          << llendl;  
  568.                                          if (EOF == tokens_read)  
  569.                                          {  
  570.                                                  fclose(in);  
  571.                                                  error_message = llformat("corrupt resource file: %s", src_filename.c_str());
  572.  args["FILE"] = src_filename;
  573.  upload_error(error_message, "CorruptResourceFile", filename, args);
  574.                                                  return;
  575.                                          }  
  576.                                          if (2 == tokens_read)  
  577.                                          {  
  578.                                                  if (! strcmp("type", label))  
  579.                                                  {  
  580.                                                          asset_type = (LLAssetType::EType)(atoi(value));  
  581.                                                  }  
  582.                                          }  
  583.                                          else  
  584.                                          {  
  585.                                                  if (! strcmp("_DATA_", label))  
  586.                                                  {  
  587.                                                          // below is the data section  
  588.                                                          break;  
  589.                                                  }  
  590.                                          }  
  591.                                          // other values are currently discarded  
  592.                                  }  
  593.                          }  
  594.                          else  
  595.                          {  
  596.                                  fclose(in);  
  597.                                  error_message = llformat("unknown linden resource file version in file: %s", src_filename.c_str());
  598.  args["FILE"] = src_filename;
  599.  upload_error(error_message, "UnknownResourceFileVersion", filename, args);
  600.                                  return;
  601.                          }  
  602.                  }  
  603.                  else  
  604.                  {  
  605.                          // this is an original binary formatted .lin file  
  606.                          // start over at the beginning of the file  
  607.                          fseek(in, 0, SEEK_SET);  
  608.                          const S32 MAX_ASSET_DESCRIPTION_LENGTH = 256;  
  609.                          const S32 MAX_ASSET_NAME_LENGTH = 64;  
  610.                          S32 header_size = 34 + MAX_ASSET_DESCRIPTION_LENGTH + MAX_ASSET_NAME_LENGTH;  
  611.                          S16     type_num;  
  612.                          // read in and throw out most of the header except for the type  
  613.                          if (fread(buf, header_size, 1, in) != 1)
  614.  {
  615.  llwarns << "Short read" << llendl;
  616.  }
  617.                          memcpy(&type_num, buf + 16, sizeof(S16)); /* Flawfinder: ignore */  
  618.                          asset_type = (LLAssetType::EType)type_num;  
  619.                  }  
  620.                  // copy the file's data segment into another file for uploading  
  621.                  LLFILE* out = LLFile::fopen(filename, "wb"); /* Flawfinder: ignore */
  622.                  if (out)  
  623.                  {  
  624.                          while((readbytes = fread(buf, 1, 16384, in))) /* Flawfinder: ignore */  
  625.                          {  
  626.  if (fwrite(buf, 1, readbytes, out) != readbytes)
  627.  {
  628.  llwarns << "Short write" << llendl;
  629.  }
  630.                          }  
  631.                          fclose(out);  
  632.                  }  
  633.                  else  
  634.                  {  
  635.                          fclose(in);  
  636.                          error_message = llformat( "Unable to create output file: %s", filename.c_str());
  637.  args["FILE"] = filename;
  638.  upload_error(error_message, "UnableToCreateOutputFile", filename, args);
  639.                          return;
  640.                  }  
  641.                  fclose(in);  
  642.          }  
  643.          else  
  644.          {  
  645.                  llinfos << "Couldn't open .lin file " << src_filename << llendl;  
  646.          }  
  647. }
  648. else if (exten == "bvh")
  649. {
  650. error_message = llformat("We do not currently support bulk upload of animation filesn");
  651. upload_error(error_message, "DoNotSupportBulkAnimationUpload", filename, args);
  652. return;
  653. }
  654. else
  655. {
  656. // Unknown extension
  657. error_message = llformat(LLTrans::getString("UnknownFileExtension").c_str(), exten.c_str());
  658. error = TRUE;;
  659. }
  660. // gen a new transaction ID for this asset
  661. tid.generate();
  662. if (!error)
  663. {
  664. uuid = tid.makeAssetID(gAgent.getSecureSessionID());
  665. // copy this file into the vfs for upload
  666. S32 file_size;
  667. LLAPRFile infile ;
  668. infile.open(filename, LL_APR_RB, NULL, &file_size);
  669. if (infile.getFileHandle())
  670. {
  671. LLVFile file(gVFS, uuid, asset_type, LLVFile::WRITE);
  672. file.setMaxSize(file_size);
  673. const S32 buf_size = 65536;
  674. U8 copy_buf[buf_size];
  675. while ((file_size = infile.read(copy_buf, buf_size)))
  676. {
  677. file.write(copy_buf, file_size);
  678. }
  679. }
  680. else
  681. {
  682. error_message = llformat( "Unable to access output file: %s", filename.c_str());
  683. error = TRUE;
  684. }
  685. }
  686. if (!error)
  687. {
  688. std::string t_disp_name = display_name;
  689. if (t_disp_name.empty())
  690. {
  691. t_disp_name = src_filename;
  692. }
  693. upload_new_resource(tid, asset_type, name, desc, compression_info, // tid
  694.     destination_folder_type, inv_type, next_owner_perms, group_perms, everyone_perms,
  695.     display_name, callback, expected_upload_cost, userdata);
  696. }
  697. else
  698. {
  699. llwarns << error_message << llendl;
  700. LLSD args;
  701. args["ERROR_MESSAGE"] = error_message;
  702. LLNotificationsUtil::add("ErrorMessage", args);
  703. if(LLFile::remove(filename) == -1)
  704. {
  705. lldebugs << "unable to remove temp file" << llendl;
  706. }
  707. LLFilePicker::instance().reset();
  708. }
  709. }
  710. void upload_done_callback(const LLUUID& uuid, void* user_data, S32 result, LLExtStat ext_status) // StoreAssetData callback (fixed)
  711. {
  712. LLResourceData* data = (LLResourceData*)user_data;
  713. S32 expected_upload_cost = data ? data->mExpectedUploadCost : 0;
  714. //LLAssetType::EType pref_loc = data->mPreferredLocation;
  715. BOOL is_balance_sufficient = TRUE;
  716. if(data)
  717. {
  718. if (result >= 0)
  719. {
  720. LLFolderType::EType dest_loc = (data->mPreferredLocation == LLFolderType::FT_NONE) ? LLFolderType::assetTypeToFolderType(data->mAssetInfo.mType) : data->mPreferredLocation;
  721. if (LLAssetType::AT_SOUND == data->mAssetInfo.mType ||
  722.     LLAssetType::AT_TEXTURE == data->mAssetInfo.mType ||
  723.     LLAssetType::AT_ANIMATION == data->mAssetInfo.mType)
  724. {
  725. // Charge the user for the upload.
  726. LLViewerRegion* region = gAgent.getRegion();
  727. if(!(can_afford_transaction(expected_upload_cost)))
  728. {
  729. LLFloaterBuyCurrency::buyCurrency(
  730.   llformat(LLTrans::getString("UploadingCosts").c_str(),
  731.    data->mAssetInfo.getName().c_str()),
  732.   expected_upload_cost);
  733. is_balance_sufficient = FALSE;
  734. }
  735. else if(region)
  736. {
  737. // Charge user for upload
  738. gStatusBar->debitBalance(expected_upload_cost);
  739. LLMessageSystem* msg = gMessageSystem;
  740. msg->newMessageFast(_PREHASH_MoneyTransferRequest);
  741. msg->nextBlockFast(_PREHASH_AgentData);
  742. msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
  743. msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
  744. msg->nextBlockFast(_PREHASH_MoneyData);
  745. msg->addUUIDFast(_PREHASH_SourceID, gAgent.getID());
  746. msg->addUUIDFast(_PREHASH_DestID, LLUUID::null);
  747. msg->addU8("Flags", 0);
  748. // we tell the sim how much we were expecting to pay so it
  749. // can respond to any discrepancy
  750. msg->addS32Fast(_PREHASH_Amount, expected_upload_cost);
  751. msg->addU8Fast(_PREHASH_AggregatePermNextOwner, (U8)LLAggregatePermissions::AP_EMPTY);
  752. msg->addU8Fast(_PREHASH_AggregatePermInventory, (U8)LLAggregatePermissions::AP_EMPTY);
  753. msg->addS32Fast(_PREHASH_TransactionType, TRANS_UPLOAD_CHARGE);
  754. msg->addStringFast(_PREHASH_Description, NULL);
  755. msg->sendReliable(region->getHost());
  756. }
  757. }
  758. if(is_balance_sufficient)
  759. {
  760. // Actually add the upload to inventory
  761. llinfos << "Adding " << uuid << " to inventory." << llendl;
  762. const LLUUID folder_id = gInventory.findCategoryUUIDForType(dest_loc);
  763. if(folder_id.notNull())
  764. {
  765. U32 next_owner_perms = data->mNextOwnerPerm;
  766. if(PERM_NONE == next_owner_perms)
  767. {
  768. next_owner_perms = PERM_MOVE | PERM_TRANSFER;
  769. }
  770. create_inventory_item(gAgent.getID(), gAgent.getSessionID(),
  771.       folder_id, data->mAssetInfo.mTransactionID, data->mAssetInfo.getName(),
  772.       data->mAssetInfo.getDescription(), data->mAssetInfo.mType,
  773.       data->mInventoryType, NOT_WEARABLE, next_owner_perms,
  774.       LLPointer<LLInventoryCallback>(NULL));
  775. }
  776. else
  777. {
  778. llwarns << "Can't find a folder to put it in" << llendl;
  779. }
  780. }
  781. }
  782. else //  if(result >= 0)
  783. {
  784. LLSD args;
  785. args["FILE"] = LLInventoryType::lookupHumanReadable(data->mInventoryType);
  786. args["REASON"] = std::string(LLAssetStorage::getErrorString(result));
  787. LLNotificationsUtil::add("CannotUploadReason", args);
  788. }
  789. }
  790. LLUploadDialog::modalUploadFinished();
  791. delete data;
  792. data = NULL;
  793. // *NOTE: This is a pretty big hack. What this does is check the
  794. // file picker if there are any more pending uploads. If so,
  795. // upload that file.
  796. const std::string& next_file = LLFilePicker::instance().getNextFile();
  797. if(is_balance_sufficient && !next_file.empty())
  798. {
  799. std::string asset_name = gDirUtilp->getBaseFileName(next_file, true);
  800. LLStringUtil::replaceNonstandardASCII( asset_name, '?' );
  801. LLStringUtil::replaceChar(asset_name, '|', '?');
  802. LLStringUtil::stripNonprintable(asset_name);
  803. LLStringUtil::trim(asset_name);
  804. std::string display_name = LLStringUtil::null;
  805. LLAssetStorage::LLStoreAssetCallback callback = NULL;
  806. void *userdata = NULL;
  807. upload_new_resource(next_file, asset_name, asset_name, // file
  808.     0, LLFolderType::FT_NONE, LLInventoryType::IT_NONE,
  809.     PERM_NONE, PERM_NONE, PERM_NONE,
  810.     display_name,
  811.     callback,
  812.     expected_upload_cost, // assuming next in a group of uploads is of roughly the same type, i.e. same upload cost
  813.     userdata);
  814. }
  815. }
  816. void upload_new_resource(const LLTransactionID &tid, LLAssetType::EType asset_type,
  817.  std::string name,
  818.  std::string desc, S32 compression_info,
  819.  LLFolderType::EType destination_folder_type,
  820.  LLInventoryType::EType inv_type,
  821.  U32 next_owner_perms,
  822.  U32 group_perms,
  823.  U32 everyone_perms,
  824.  const std::string& display_name,
  825.  LLAssetStorage::LLStoreAssetCallback callback,
  826.  S32 expected_upload_cost,
  827.  void *userdata)
  828. {
  829. if(gDisconnected)
  830. {
  831. return ;
  832. }
  833. LLAssetID uuid = tid.makeAssetID(gAgent.getSecureSessionID());
  834. if( LLAssetType::AT_SOUND == asset_type )
  835. {
  836. LLViewerStats::getInstance()->incStat(LLViewerStats::ST_UPLOAD_SOUND_COUNT );
  837. }
  838. else
  839. if( LLAssetType::AT_TEXTURE == asset_type )
  840. {
  841. LLViewerStats::getInstance()->incStat(LLViewerStats::ST_UPLOAD_TEXTURE_COUNT );
  842. }
  843. else
  844. if( LLAssetType::AT_ANIMATION == asset_type)
  845. {
  846. LLViewerStats::getInstance()->incStat(LLViewerStats::ST_UPLOAD_ANIM_COUNT );
  847. }
  848. if(LLInventoryType::IT_NONE == inv_type)
  849. {
  850. inv_type = LLInventoryType::defaultForAssetType(asset_type);
  851. }
  852. LLStringUtil::stripNonprintable(name);
  853. LLStringUtil::stripNonprintable(desc);
  854. if(name.empty())
  855. {
  856. name = "(No Name)";
  857. }
  858. if(desc.empty())
  859. {
  860. desc = "(No Description)";
  861. }
  862. // At this point, we're ready for the upload.
  863. std::string upload_message = "Uploading...nn";
  864. upload_message.append(display_name);
  865. LLUploadDialog::modalUploadDialog(upload_message);
  866. llinfos << "*** Uploading: " << llendl;
  867. llinfos << "Type: " << LLAssetType::lookup(asset_type) << llendl;
  868. llinfos << "UUID: " << uuid << llendl;
  869. llinfos << "Name: " << name << llendl;
  870. llinfos << "Desc: " << desc << llendl;
  871. llinfos << "Expected Upload Cost: " << expected_upload_cost << llendl;
  872. lldebugs << "Folder: " << gInventory.findCategoryUUIDForType((destination_folder_type == LLFolderType::FT_NONE) ? LLFolderType::assetTypeToFolderType(asset_type) : destination_folder_type) << llendl;
  873. lldebugs << "Asset Type: " << LLAssetType::lookup(asset_type) << llendl;
  874. std::string url = gAgent.getRegion()->getCapability("NewFileAgentInventory");
  875. if (!url.empty())
  876. {
  877. llinfos << "New Agent Inventory via capability" << llendl;
  878. LLSD body;
  879. body["folder_id"] = gInventory.findCategoryUUIDForType((destination_folder_type == LLFolderType::FT_NONE) ? LLFolderType::assetTypeToFolderType(asset_type) : destination_folder_type);
  880. body["asset_type"] = LLAssetType::lookup(asset_type);
  881. body["inventory_type"] = LLInventoryType::lookup(inv_type);
  882. body["name"] = name;
  883. body["description"] = desc;
  884. body["next_owner_mask"] = LLSD::Integer(next_owner_perms);
  885. body["group_mask"] = LLSD::Integer(group_perms);
  886. body["everyone_mask"] = LLSD::Integer(everyone_perms);
  887. body["expected_upload_cost"] = LLSD::Integer(expected_upload_cost);
  888. //std::ostringstream llsdxml;
  889. //LLSDSerialize::toPrettyXML(body, llsdxml);
  890. //llinfos << "posting body to capability: " << llsdxml.str() << llendl;
  891. LLHTTPClient::post(url, body, new LLNewAgentInventoryResponder(body, uuid, asset_type));
  892. }
  893. else
  894. {
  895. llinfos << "NewAgentInventory capability not found, new agent inventory via asset system." << llendl;
  896. // check for adequate funds
  897. // TODO: do this check on the sim
  898. if (LLAssetType::AT_SOUND == asset_type ||
  899. LLAssetType::AT_TEXTURE == asset_type ||
  900. LLAssetType::AT_ANIMATION == asset_type)
  901. {
  902. S32 balance = gStatusBar->getBalance();
  903. if (balance < expected_upload_cost)
  904. {
  905. // insufficient funds, bail on this upload
  906. LLFloaterBuyCurrency::buyCurrency("Uploading costs", expected_upload_cost);
  907. return;
  908. }
  909. }
  910. LLResourceData* data = new LLResourceData;
  911. data->mAssetInfo.mTransactionID = tid;
  912. data->mAssetInfo.mUuid = uuid;
  913. data->mAssetInfo.mType = asset_type;
  914. data->mAssetInfo.mCreatorID = gAgentID;
  915. data->mInventoryType = inv_type;
  916. data->mNextOwnerPerm = next_owner_perms;
  917. data->mExpectedUploadCost = expected_upload_cost;
  918. data->mUserData = userdata;
  919. data->mAssetInfo.setName(name);
  920. data->mAssetInfo.setDescription(desc);
  921. data->mPreferredLocation = destination_folder_type;
  922. LLAssetStorage::LLStoreAssetCallback asset_callback = &upload_done_callback;
  923. if (callback)
  924. {
  925. asset_callback = callback;
  926. }
  927. gAssetStorage->storeAssetData(data->mAssetInfo.mTransactionID, data->mAssetInfo.mType,
  928. asset_callback,
  929. (void*)data,
  930. FALSE);
  931. }
  932. }
  933. void init_menu_file()
  934. {
  935. view_listener_t::addCommit(new LLFileUploadImage(), "File.UploadImage");
  936. view_listener_t::addCommit(new LLFileUploadSound(), "File.UploadSound");
  937. view_listener_t::addCommit(new LLFileUploadAnim(), "File.UploadAnim");
  938. view_listener_t::addCommit(new LLFileUploadBulk(), "File.UploadBulk");
  939. view_listener_t::addCommit(new LLFileCloseWindow(), "File.CloseWindow");
  940. view_listener_t::addCommit(new LLFileCloseAllWindows(), "File.CloseAllWindows");
  941. view_listener_t::addEnable(new LLFileEnableCloseWindow(), "File.EnableCloseWindow");
  942. view_listener_t::addEnable(new LLFileEnableCloseAllWindows(), "File.EnableCloseAllWindows");
  943. view_listener_t::addCommit(new LLFileTakeSnapshotToDisk(), "File.TakeSnapshotToDisk");
  944. view_listener_t::addCommit(new LLFileQuit(), "File.Quit");
  945. view_listener_t::addEnable(new LLFileEnableUpload(), "File.EnableUpload");
  946. // "File.SaveTexture" moved to llpanelmaininventory so that it can be properly handled.
  947. }