00001
00032 #include "llviewerprecompiledheaders.h"
00033
00034 #include "llviewermenufile.h"
00035
00036
00037 #include "llagent.h"
00038 #include "llfilepicker.h"
00039 #include "llfloateranimpreview.h"
00040 #include "llfloaterbuycurrency.h"
00041 #include "llfloaterimagepreview.h"
00042 #include "llfloaternamedesc.h"
00043 #include "llfloatersnapshot.h"
00044 #include "llinventorymodel.h"
00045 #include "llresourcedata.h"
00046 #include "llstatusbar.h"
00047 #include "llviewercontrol.h"
00048 #include "llviewerimagelist.h"
00049 #include "lluictrlfactory.h"
00050 #include "llviewermenu.h"
00051 #include "llviewerregion.h"
00052 #include "llviewerstats.h"
00053 #include "llviewerwindow.h"
00054 #include "llappviewer.h"
00055 #include "lluploaddialog.h"
00056
00057
00058
00059 #include "llassetuploadresponders.h"
00060 #include "lleconomy.h"
00061 #include "llhttpclient.h"
00062 #include "llmemberlistener.h"
00063 #include "llsdserialize.h"
00064 #include "llstring.h"
00065 #include "lltransactiontypes.h"
00066 #include "lluuid.h"
00067 #include "vorbisencode.h"
00068
00069
00070 #include <boost/tokenizer.hpp>
00071
00072 typedef LLMemberListener<LLView> view_listener_t;
00073
00074
00075 class LLFileEnableSaveAs : public view_listener_t
00076 {
00077 bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
00078 {
00079 bool new_value = gFloaterView->getFrontmost() && gFloaterView->getFrontmost()->canSaveAs();
00080 gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value);
00081 return true;
00082 }
00083 };
00084
00085 class LLFileEnableUpload : public view_listener_t
00086 {
00087 bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
00088 {
00089 bool new_value = gStatusBar && LLGlobalEconomy::Singleton::getInstance() && (gStatusBar->getBalance() >= LLGlobalEconomy::Singleton::getInstance()->getPriceUpload());
00090 gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value);
00091 return true;
00092 }
00093 };
00094
00103 const char* upload_pick(void* data)
00104 {
00105 if( gAgent.cameraMouselook() )
00106 {
00107 gAgent.changeCameraToDefault();
00108
00109
00110 }
00111
00112 LLFilePicker::ELoadFilter type;
00113 if(data)
00114 {
00115 type = (LLFilePicker::ELoadFilter)((intptr_t)data);
00116 }
00117 else
00118 {
00119 type = LLFilePicker::FFLOAD_ALL;
00120 }
00121
00122 LLFilePicker& picker = LLFilePicker::instance();
00123 if (!picker.getOpenFile(type))
00124 {
00125 llinfos << "Couldn't import objects from file" << llendl;
00126 return NULL;
00127 }
00128
00129 const char* filename = picker.getFirstFile();
00130 const char* ext = strrchr(filename, '.');
00131
00132
00133 if (ext == NULL)
00134 {
00135 const char* short_name = strrchr(filename,
00136 *gDirUtilp->getDirDelimiter().c_str());
00137
00138
00139 LLStringBase<char>::format_map_t args;
00140 args["[FILE]"] = LLString(short_name + 1);
00141 gViewerWindow->alertXml("NoFileExtension", args);
00142 return NULL;
00143 }
00144 else
00145 {
00146
00147
00148
00149
00150
00151 const char* valids = build_extensions_string(type);
00152 std::string valid_extensions = std::string(valids);
00153
00154 BOOL ext_valid = FALSE;
00155
00156 typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
00157 boost::char_separator<char> sep(" ");
00158 tokenizer tokens(valid_extensions, sep);
00159 tokenizer::iterator token_iter;
00160
00161
00162
00163
00164 for( token_iter = tokens.begin();
00165 token_iter != tokens.end() && ext_valid != TRUE;
00166 ++token_iter)
00167 {
00168 const char* cur_token = token_iter->c_str();
00169
00170 if (0 == strnicmp(cur_token, ext, strlen(cur_token)) ||
00171 0 == strnicmp(cur_token, "*.*", strlen(cur_token)))
00172 {
00173
00174
00175 ext_valid = TRUE;
00176 }
00177 }
00178
00179 if (ext_valid == FALSE)
00180 {
00181
00182
00183 LLStringBase<char>::format_map_t args;
00184 args["[EXTENSION]"] = ext;
00185 args["[VALIDS]"] = valids;
00186 gViewerWindow->alertXml("InvalidFileExtension", args);
00187 return NULL;
00188 }
00189 }
00190
00191
00192
00193
00194
00195 if (type == LLFilePicker::FFLOAD_WAV)
00196 {
00197
00198 char error_msg[MAX_STRING];
00199 if (check_for_invalid_wav_formats(filename,error_msg))
00200 {
00201 llinfos << error_msg << ": " << filename << llendl;
00202 LLStringBase<char>::format_map_t args;
00203 args["[FILE]"] = filename;
00204 gViewerWindow->alertXml( error_msg, args );
00205 return NULL;
00206 }
00207 }
00208
00209
00210 return filename;
00211 }
00212
00213 class LLFileUploadImage : public view_listener_t
00214 {
00215 bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
00216 {
00217 const char* filename = upload_pick((void *)LLFilePicker::FFLOAD_IMAGE);
00218 if (filename)
00219 {
00220 LLFloaterImagePreview* floaterp = new LLFloaterImagePreview(filename);
00221 LLUICtrlFactory::getInstance()->buildFloater(floaterp, "floater_image_preview.xml");
00222 }
00223 return TRUE;
00224 }
00225 };
00226
00227 class LLFileUploadSound : public view_listener_t
00228 {
00229 bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
00230 {
00231 const char* filename = upload_pick((void*)LLFilePicker::FFLOAD_WAV);
00232 if (filename)
00233 {
00234 LLFloaterNameDesc* floaterp = new LLFloaterNameDesc(filename);
00235 LLUICtrlFactory::getInstance()->buildFloater(floaterp, "floater_sound_preview.xml");
00236 }
00237 return true;
00238 }
00239 };
00240
00241 class LLFileUploadAnim : public view_listener_t
00242 {
00243 bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
00244 {
00245 const char* filename = upload_pick((void*)LLFilePicker::FFLOAD_ANIM);
00246 if (filename)
00247 {
00248 LLFloaterAnimPreview* floaterp = new LLFloaterAnimPreview(filename);
00249 LLUICtrlFactory::getInstance()->buildFloater(floaterp, "floater_animation_preview.xml");
00250 }
00251 return true;
00252 }
00253 };
00254
00255 class LLFileUploadBulk : public view_listener_t
00256 {
00257 bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
00258 {
00259 if( gAgent.cameraMouselook() )
00260 {
00261 gAgent.changeCameraToDefault();
00262 }
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274 LLFilePicker& picker = LLFilePicker::instance();
00275 if (picker.getMultipleOpenFiles())
00276 {
00277 const char* filename = picker.getFirstFile();
00278 const char* name = picker.getDirname();
00279
00280 LLString asset_name = name;
00281 LLString::replaceNonstandardASCII( asset_name, '?' );
00282 LLString::replaceChar(asset_name, '|', '?');
00283 LLString::stripNonprintable(asset_name);
00284 LLString::trim(asset_name);
00285
00286 char* asset_name_str = (char*)asset_name.c_str();
00287 char* end_p = strrchr(asset_name_str, '.');
00288 if( !end_p )
00289 {
00290 end_p = asset_name_str + strlen( asset_name_str );
00291 }
00292
00293 S32 len = llmin( (S32) (DB_INV_ITEM_NAME_STR_LEN), (S32) (end_p - asset_name_str) );
00294
00295 asset_name = asset_name.substr( 0, len );
00296
00297 upload_new_resource(filename, asset_name, asset_name, 0, LLAssetType::AT_NONE, LLInventoryType::IT_NONE);
00298 }
00299 else
00300 {
00301 llinfos << "Couldn't import objects from file" << llendl;
00302 }
00303 return true;
00304 }
00305 };
00306
00307 void upload_error(const char* error_message, const char* label, const std::string filename, const LLStringBase<char>::format_map_t args)
00308 {
00309 llwarns << error_message << llendl;
00310 gViewerWindow->alertXml(label, args);
00311 if(remove(filename.c_str()) == -1)
00312 {
00313 lldebugs << "unable to remove temp file" << llendl;
00314 }
00315 LLFilePicker::instance().reset();
00316 }
00317
00318 class LLFileEnableCloseWindow : public view_listener_t
00319 {
00320 bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
00321 {
00322 bool new_value = gFloaterView->getFocusedFloater() != NULL || gSnapshotFloaterView->getFocusedFloater() != NULL;
00323
00324 gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value);
00325 return true;
00326 }
00327 };
00328
00329 class LLFileCloseWindow : public view_listener_t
00330 {
00331 bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
00332 {
00333 LLFloater::closeFocusedFloater();
00334
00335 return true;
00336 }
00337 };
00338
00339 class LLFileEnableCloseAllWindows : public view_listener_t
00340 {
00341 bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
00342 {
00343 bool open_children = gFloaterView->allChildrenClosed();
00344 gMenuHolder->findControl(userdata["control"].asString())->setValue(!open_children);
00345 return true;
00346 }
00347 };
00348
00349 class LLFileCloseAllWindows : public view_listener_t
00350 {
00351 bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
00352 {
00353 bool app_quitting = false;
00354 gFloaterView->closeAllChildren(app_quitting);
00355
00356 return true;
00357 }
00358 };
00359
00360 class LLFileSaveTexture : public view_listener_t
00361 {
00362 bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
00363 {
00364 LLFloater* top = gFloaterView->getFrontmost();
00365 if (top)
00366 {
00367 top->saveAs();
00368 }
00369 return true;
00370 }
00371 };
00372
00373 class LLFileTakeSnapshot : public view_listener_t
00374 {
00375 bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
00376 {
00377 LLFloaterSnapshot::show(NULL);
00378 return true;
00379 }
00380 };
00381
00382 class LLFileTakeSnapshotToDisk : public view_listener_t
00383 {
00384 bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
00385 {
00386 LLPointer<LLImageRaw> raw = new LLImageRaw;
00387
00388 S32 width = gViewerWindow->getWindowDisplayWidth();
00389 S32 height = gViewerWindow->getWindowDisplayHeight();
00390
00391 if (gSavedSettings.getBOOL("HighResSnapshot"))
00392 {
00393 width *= 2;
00394 height *= 2;
00395 }
00396
00397 if (gViewerWindow->rawSnapshot(raw,
00398 width,
00399 height,
00400 TRUE,
00401 FALSE,
00402 gSavedSettings.getBOOL("RenderUIInSnapshot"),
00403 FALSE))
00404 {
00405 if (!gSavedSettings.getBOOL("QuietSnapshotsToDisk"))
00406 {
00407 gViewerWindow->playSnapshotAnimAndSound();
00408 }
00409 LLImageBase::setSizeOverride(TRUE);
00410 gViewerWindow->saveImageNumbered(raw);
00411 LLImageBase::setSizeOverride(FALSE);
00412 }
00413 return true;
00414 }
00415 };
00416
00417 class LLFileQuit : public view_listener_t
00418 {
00419 bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
00420 {
00421 LLAppViewer::instance()->userQuit();
00422 return true;
00423 }
00424 };
00425
00426 void handle_upload(void* data)
00427 {
00428 const char* filename = upload_pick(data);
00429 if (filename)
00430 {
00431 LLFloaterNameDesc* floaterp = new LLFloaterNameDesc(filename);
00432 LLUICtrlFactory::getInstance()->buildFloater(floaterp, "floater_name_description.xml");
00433 }
00434 }
00435
00436 void handle_compress_image(void*)
00437 {
00438 LLFilePicker& picker = LLFilePicker::instance();
00439 if (picker.getMultipleOpenFiles(LLFilePicker::FFLOAD_IMAGE))
00440 {
00441 const char* input_file = picker.getFirstFile();
00442 while (input_file)
00443 {
00444 std::string infile(input_file);
00445 std::string outfile = infile + ".j2c";
00446
00447 llinfos << "Input: " << infile << llendl;
00448 llinfos << "Output: " << outfile << llendl;
00449
00450 BOOL success;
00451
00452 success = LLViewerImageList::createUploadFile(infile, outfile, IMG_CODEC_TGA);
00453
00454 if (success)
00455 {
00456 llinfos << "Compression complete" << llendl;
00457 }
00458 else
00459 {
00460 llinfos << "Compression failed: " << LLImageBase::getLastError() << llendl;
00461 }
00462
00463 input_file = picker.getNextFile();
00464 }
00465 }
00466 }
00467
00468 void upload_new_resource(const LLString& src_filename, std::string name,
00469 std::string desc, S32 compression_info,
00470 LLAssetType::EType destination_folder_type,
00471 LLInventoryType::EType inv_type,
00472 U32 next_owner_perm,
00473 const LLString& display_name,
00474 LLAssetStorage::LLStoreAssetCallback callback,
00475 void *userdata)
00476 {
00477
00478 LLString filename = gDirUtilp->getTempFilename();
00479 LLTransactionID tid;
00480 LLAssetID uuid;
00481
00482 LLStringBase<char>::format_map_t args;
00483
00484 LLString ext = src_filename.substr(src_filename.find_last_of('.'));
00485 LLAssetType::EType asset_type = LLAssetType::AT_NONE;
00486 char error_message[MAX_STRING];
00487 error_message[0] = '\0';
00488 LLString temp_str;
00489
00490 BOOL error = FALSE;
00491
00492 if (ext.empty())
00493 {
00494 LLString::size_type offset = filename.find_last_of(gDirUtilp->getDirDelimiter());
00495 if (offset != LLString::npos)
00496 offset++;
00497 LLString short_name = filename.substr(offset);
00498
00499
00500 snprintf(error_message,
00501 MAX_STRING,
00502 "No file extension for the file: '%s'\nPlease make sure the file has a correct file extension",
00503 short_name.c_str());
00504 args["[FILE]"] = short_name;
00505 upload_error(error_message, "NofileExtension", filename, args);
00506 return;
00507 }
00508 else if( LLString::compareInsensitive(ext.c_str(),".bmp") == 0 )
00509 {
00510 asset_type = LLAssetType::AT_TEXTURE;
00511 if (!LLViewerImageList::createUploadFile(src_filename,
00512 filename,
00513 IMG_CODEC_BMP ))
00514 {
00515 snprintf(error_message, MAX_STRING, "Problem with file %s:\n\n%s\n",
00516 src_filename.c_str(), LLImageBase::getLastError().c_str());
00517 args["[FILE]"] = src_filename;
00518 args["[ERROR]"] = LLImageBase::getLastError();
00519 upload_error(error_message, "ProblemWithFile", filename, args);
00520 return;
00521 }
00522 }
00523 else if( LLString::compareInsensitive(ext.c_str(),".tga") == 0 )
00524 {
00525 asset_type = LLAssetType::AT_TEXTURE;
00526 if (!LLViewerImageList::createUploadFile(src_filename,
00527 filename,
00528 IMG_CODEC_TGA ))
00529 {
00530 snprintf(error_message, MAX_STRING, "Problem with file %s:\n\n%s\n",
00531 src_filename.c_str(), LLImageBase::getLastError().c_str());
00532 args["[FILE]"] = src_filename;
00533 args["[ERROR]"] = LLImageBase::getLastError();
00534 upload_error(error_message, "ProblemWithFile", filename, args);
00535 return;
00536 }
00537 }
00538 else if( LLString::compareInsensitive(ext.c_str(),".jpg") == 0 || LLString::compareInsensitive(ext.c_str(),".jpeg") == 0)
00539 {
00540 asset_type = LLAssetType::AT_TEXTURE;
00541 if (!LLViewerImageList::createUploadFile(src_filename,
00542 filename,
00543 IMG_CODEC_JPEG ))
00544 {
00545 snprintf(error_message, MAX_STRING, "Problem with file %s:\n\n%s\n",
00546 src_filename.c_str(), LLImageBase::getLastError().c_str());
00547 args["[FILE]"] = src_filename;
00548 args["[ERROR]"] = LLImageBase::getLastError();
00549 upload_error(error_message, "ProblemWithFile", filename, args);
00550 return;
00551 }
00552 }
00553 else if( LLString::compareInsensitive(ext.c_str(),".png") == 0 )
00554 {
00555 asset_type = LLAssetType::AT_TEXTURE;
00556 if (!LLViewerImageList::createUploadFile(src_filename,
00557 filename,
00558 IMG_CODEC_PNG ))
00559 {
00560 sprintf(error_message, "Problem with file %s:\n\n%s\n",
00561 src_filename.c_str(), LLImageBase::getLastError().c_str());
00562 args["[FILE]"] = src_filename;
00563 args["[ERROR]"] = LLImageBase::getLastError();
00564 upload_error(error_message, "ProblemWithFile", filename, args);
00565 return;
00566 }
00567 }
00568 else if(LLString::compareInsensitive(ext.c_str(),".wav") == 0)
00569 {
00570 asset_type = LLAssetType::AT_SOUND;
00571 S32 encode_result = 0;
00572
00573 llinfos << "Attempting to encode wav as an ogg file" << llendl;
00574
00575 encode_result = encode_vorbis_file(src_filename.c_str(), filename.c_str());
00576
00577 if (LLVORBISENC_NOERR != encode_result)
00578 {
00579 switch(encode_result)
00580 {
00581 case LLVORBISENC_DEST_OPEN_ERR:
00582 snprintf(error_message, MAX_STRING, "Couldn't open temporary compressed sound file for writing: %s\n", filename.c_str());
00583 args["[FILE]"] = filename;
00584 upload_error(error_message, "CannotOpenTemporarySoundFile", filename, args);
00585 break;
00586
00587 default:
00588 snprintf(error_message, MAX_STRING, "Unknown vorbis encode failure on: %s\n", src_filename.c_str());
00589 args["[FILE]"] = src_filename;
00590 upload_error(error_message, "UnknownVorbisEncodeFailure", filename, args);
00591 break;
00592 }
00593 return;
00594 }
00595 }
00596 else if(LLString::compareInsensitive(ext.c_str(),".tmp") == 0)
00597 {
00598
00599 asset_type = LLAssetType::AT_OBJECT;
00600 LLFILE* in = LLFile::fopen(src_filename.c_str(), "rb");
00601 if (in)
00602 {
00603
00604 char buf[16384];
00605 S32 read;
00606 S32 version;
00607 if (fscanf(in, "LindenResource\nversion %d\n", &version))
00608 {
00609 if (2 == version)
00610 {
00611
00612 char label[MAX_STRING];
00613 char value[MAX_STRING];
00614 S32 tokens_read;
00615 while (fgets(buf, 1024, in))
00616 {
00617 label[0] = '\0';
00618 value[0] = '\0';
00619 tokens_read = sscanf(
00620 buf,
00621 "%254s %254s\n",
00622 label, value);
00623
00624 llinfos << "got: " << label << " = " << value
00625 << llendl;
00626
00627 if (EOF == tokens_read)
00628 {
00629 fclose(in);
00630 snprintf(error_message, MAX_STRING, "corrupt resource file: %s", src_filename.c_str());
00631 args["[FILE]"] = src_filename;
00632 upload_error(error_message, "CorruptResourceFile", filename, args);
00633 return;
00634 }
00635
00636 if (2 == tokens_read)
00637 {
00638 if (! strcmp("type", label))
00639 {
00640 asset_type = (LLAssetType::EType)(atoi(value));
00641 }
00642 }
00643 else
00644 {
00645 if (! strcmp("_DATA_", label))
00646 {
00647
00648 break;
00649 }
00650 }
00651
00652 }
00653
00654 }
00655 else
00656 {
00657 fclose(in);
00658 snprintf(error_message, MAX_STRING, "unknown linden resource file version in file: %s", src_filename.c_str());
00659 args["[FILE]"] = src_filename;
00660 upload_error(error_message, "UnknownResourceFileVersion", filename, args);
00661 return;
00662 }
00663 }
00664 else
00665 {
00666
00667
00668 fseek(in, 0, SEEK_SET);
00669
00670 const S32 MAX_ASSET_DESCRIPTION_LENGTH = 256;
00671 const S32 MAX_ASSET_NAME_LENGTH = 64;
00672 S32 header_size = 34 + MAX_ASSET_DESCRIPTION_LENGTH + MAX_ASSET_NAME_LENGTH;
00673 S16 type_num;
00674
00675
00676 if (fread(buf, header_size, 1, in) != 1)
00677 {
00678 llwarns << "Short read" << llendl;
00679 }
00680 memcpy(&type_num, buf + 16, sizeof(S16));
00681 asset_type = (LLAssetType::EType)type_num;
00682 }
00683
00684
00685 LLFILE* out = LLFile::fopen(filename.c_str(), "wb");
00686 if (out)
00687 {
00688 while((read = fread(buf, 1, 16384, in)))
00689 {
00690 if (fwrite(buf, 1, read, out) != read)
00691 {
00692 llwarns << "Short write" << llendl;
00693 }
00694 }
00695 fclose(out);
00696 }
00697 else
00698 {
00699 fclose(in);
00700 snprintf(error_message, MAX_STRING, "Unable to create output file: %s", filename.c_str());
00701 args["[FILE]"] = filename;
00702 upload_error(error_message, "UnableToCreateOutputFile", filename, args);
00703 return;
00704 }
00705
00706 fclose(in);
00707 }
00708 else
00709 {
00710 llinfos << "Couldn't open .lin file " << src_filename << llendl;
00711 }
00712 }
00713 else if (LLString::compareInsensitive(ext.c_str(),".bvh") == 0)
00714 {
00715 snprintf(error_message, MAX_STRING, "We do not currently support bulk upload of animation files\n");
00716 upload_error(error_message, "DoNotSupportBulkAnimationUpload", filename, args);
00717 return;
00718 }
00719 else
00720 {
00721
00722 snprintf(error_message, MAX_STRING, "Unknown file extension %s\nExpected .wav, .tga, .bmp, .jpg, .jpeg, or .bvh", ext.c_str());
00723 error = TRUE;;
00724 }
00725
00726
00727 tid.generate();
00728
00729 if (!error)
00730 {
00731 uuid = tid.makeAssetID(gAgent.getSecureSessionID());
00732
00733 S32 file_size;
00734 apr_file_t* fp = ll_apr_file_open(filename, LL_APR_RB, &file_size);
00735 if (fp)
00736 {
00737 LLVFile file(gVFS, uuid, asset_type, LLVFile::WRITE);
00738
00739 file.setMaxSize(file_size);
00740
00741 const S32 buf_size = 65536;
00742 U8 copy_buf[buf_size];
00743 while ((file_size = ll_apr_file_read(fp, copy_buf, buf_size)))
00744 {
00745 file.write(copy_buf, file_size);
00746 }
00747 apr_file_close(fp);
00748 }
00749 else
00750 {
00751 snprintf(error_message, MAX_STRING, "Unable to access output file: %s", filename.c_str());
00752 error = TRUE;
00753 }
00754 }
00755
00756 if (!error)
00757 {
00758 LLString t_disp_name = display_name;
00759 if (t_disp_name.empty())
00760 {
00761 t_disp_name = src_filename;
00762 }
00763 upload_new_resource(tid, asset_type, name, desc, compression_info,
00764 destination_folder_type, inv_type, next_owner_perm,
00765 display_name, callback, userdata);
00766 }
00767 else
00768 {
00769 llwarns << error_message << llendl;
00770 LLStringBase<char>::format_map_t args;
00771 args["[ERROR_MESSAGE]"] = error_message;
00772 gViewerWindow->alertXml("ErrorMessage", args);
00773 if(LLFile::remove(filename.c_str()) == -1)
00774 {
00775 lldebugs << "unable to remove temp file" << llendl;
00776 }
00777 LLFilePicker::instance().reset();
00778 }
00779 }
00780
00781 void upload_done_callback(const LLUUID& uuid, void* user_data, S32 result, LLExtStat ext_status)
00782 {
00783 LLResourceData* data = (LLResourceData*)user_data;
00784
00785 BOOL is_balance_sufficient = TRUE;
00786 if(result >= 0)
00787 {
00788 LLAssetType::EType dest_loc = (data->mPreferredLocation == LLAssetType::AT_NONE) ? data->mAssetInfo.mType : data->mPreferredLocation;
00789
00790 if (LLAssetType::AT_SOUND == data->mAssetInfo.mType ||
00791 LLAssetType::AT_TEXTURE == data->mAssetInfo.mType ||
00792 LLAssetType::AT_ANIMATION == data->mAssetInfo.mType)
00793 {
00794
00795 LLViewerRegion* region = gAgent.getRegion();
00796 S32 upload_cost = LLGlobalEconomy::Singleton::getInstance()->getPriceUpload();
00797
00798 if(!(can_afford_transaction(upload_cost)))
00799 {
00800 LLFloaterBuyCurrency::buyCurrency(
00801 llformat("Uploading %s costs",
00802 data->mAssetInfo.getName().c_str()),
00803 upload_cost);
00804 is_balance_sufficient = FALSE;
00805 }
00806 else if(region)
00807 {
00808
00809 gStatusBar->debitBalance(upload_cost);
00810
00811 LLMessageSystem* msg = gMessageSystem;
00812 msg->newMessageFast(_PREHASH_MoneyTransferRequest);
00813 msg->nextBlockFast(_PREHASH_AgentData);
00814 msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
00815 msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
00816 msg->nextBlockFast(_PREHASH_MoneyData);
00817 msg->addUUIDFast(_PREHASH_SourceID, gAgent.getID());
00818 msg->addUUIDFast(_PREHASH_DestID, LLUUID::null);
00819 msg->addU8("Flags", 0);
00820 msg->addS32Fast(_PREHASH_Amount, upload_cost);
00821 msg->addU8Fast(_PREHASH_AggregatePermNextOwner, (U8)LLAggregatePermissions::AP_EMPTY);
00822 msg->addU8Fast(_PREHASH_AggregatePermInventory, (U8)LLAggregatePermissions::AP_EMPTY);
00823 msg->addS32Fast(_PREHASH_TransactionType, TRANS_UPLOAD_CHARGE);
00824 msg->addStringFast(_PREHASH_Description, NULL);
00825 msg->sendReliable(region->getHost());
00826 }
00827 }
00828
00829 if(is_balance_sufficient)
00830 {
00831
00832 llinfos << "Adding " << uuid << " to inventory." << llendl;
00833 LLUUID folder_id(gInventory.findCategoryUUIDForType(dest_loc));
00834 if(folder_id.notNull())
00835 {
00836 U32 next_owner_perm = data->mNextOwnerPerm;
00837 if(PERM_NONE == next_owner_perm)
00838 {
00839 next_owner_perm = PERM_MOVE | PERM_TRANSFER;
00840 }
00841 create_inventory_item(gAgent.getID(), gAgent.getSessionID(),
00842 folder_id, data->mAssetInfo.mTransactionID, data->mAssetInfo.getName(),
00843 data->mAssetInfo.getDescription(), data->mAssetInfo.mType,
00844 data->mInventoryType, NOT_WEARABLE, next_owner_perm,
00845 LLPointer<LLInventoryCallback>(NULL));
00846 }
00847 else
00848 {
00849 llwarns << "Can't find a folder to put it in" << llendl;
00850 }
00851 }
00852 }
00853 else
00854 {
00855 LLStringBase<char>::format_map_t args;
00856 args["[FILE]"] = LLInventoryType::lookupHumanReadable(data->mInventoryType);
00857 args["[REASON]"] = LLString(LLAssetStorage::getErrorString(result));
00858 gViewerWindow->alertXml("CannotUploadReason", args);
00859 }
00860
00861 LLUploadDialog::modalUploadFinished();
00862 delete data;
00863
00864
00865
00866
00867 const char* next_file = LLFilePicker::instance().getNextFile();
00868 if(is_balance_sufficient && next_file)
00869 {
00870 const char* name = LLFilePicker::instance().getDirname();
00871
00872 LLString asset_name = name;
00873 LLString::replaceNonstandardASCII( asset_name, '?' );
00874 LLString::replaceChar(asset_name, '|', '?');
00875 LLString::stripNonprintable(asset_name);
00876 LLString::trim(asset_name);
00877
00878 char* asset_name_str = (char*)asset_name.c_str();
00879 char* end_p = strrchr(asset_name_str, '.');
00880 if( !end_p )
00881 {
00882 end_p = asset_name_str + strlen( asset_name_str );
00883 }
00884
00885 S32 len = llmin( (S32) (DB_INV_ITEM_NAME_STR_LEN), (S32) (end_p - asset_name_str) );
00886
00887 asset_name = asset_name.substr( 0, len );
00888
00889 upload_new_resource(next_file, asset_name, asset_name,
00890 0, LLAssetType::AT_NONE, LLInventoryType::IT_NONE);
00891 }
00892 }
00893
00894 void upload_new_resource(const LLTransactionID &tid, LLAssetType::EType asset_type,
00895 std::string name,
00896 std::string desc, S32 compression_info,
00897 LLAssetType::EType destination_folder_type,
00898 LLInventoryType::EType inv_type,
00899 U32 next_owner_perm,
00900 const LLString& display_name,
00901 LLAssetStorage::LLStoreAssetCallback callback,
00902 void *userdata)
00903 {
00904 LLAssetID uuid = tid.makeAssetID(gAgent.getSecureSessionID());
00905
00906 if( LLAssetType::AT_SOUND == asset_type )
00907 {
00908 LLViewerStats::getInstance()->incStat(LLViewerStats::ST_UPLOAD_SOUND_COUNT );
00909 }
00910 else
00911 if( LLAssetType::AT_TEXTURE == asset_type )
00912 {
00913 LLViewerStats::getInstance()->incStat(LLViewerStats::ST_UPLOAD_TEXTURE_COUNT );
00914 }
00915 else
00916 if( LLAssetType::AT_ANIMATION == asset_type)
00917 {
00918 LLViewerStats::getInstance()->incStat(LLViewerStats::ST_UPLOAD_ANIM_COUNT );
00919 }
00920
00921 if(LLInventoryType::IT_NONE == inv_type)
00922 {
00923 inv_type = LLInventoryType::defaultForAssetType(asset_type);
00924 }
00925 LLString::stripNonprintable(name);
00926 LLString::stripNonprintable(desc);
00927 if(name.empty())
00928 {
00929 name = "(No Name)";
00930 }
00931 if(desc.empty())
00932 {
00933 desc = "(No Description)";
00934 }
00935
00936
00937 LLString upload_message = "Uploading...\n\n";
00938 upload_message.append(display_name);
00939 LLUploadDialog::modalUploadDialog(upload_message);
00940
00941 llinfos << "*** Uploading: " << llendl;
00942 llinfos << "Type: " << LLAssetType::lookup(asset_type) << llendl;
00943 llinfos << "UUID: " << uuid << llendl;
00944 llinfos << "Name: " << name << llendl;
00945 llinfos << "Desc: " << desc << llendl;
00946 lldebugs << "Folder: " << gInventory.findCategoryUUIDForType((destination_folder_type == LLAssetType::AT_NONE) ? asset_type : destination_folder_type) << llendl;
00947 lldebugs << "Asset Type: " << LLAssetType::lookup(asset_type) << llendl;
00948 std::string url = gAgent.getRegion()->getCapability("NewFileAgentInventory");
00949 if (!url.empty())
00950 {
00951 llinfos << "New Agent Inventory via capability" << llendl;
00952 LLSD body;
00953 body["folder_id"] = gInventory.findCategoryUUIDForType((destination_folder_type == LLAssetType::AT_NONE) ? asset_type : destination_folder_type);
00954 body["asset_type"] = LLAssetType::lookup(asset_type);
00955 body["inventory_type"] = LLInventoryType::lookup(inv_type);
00956 body["name"] = name;
00957 body["description"] = desc;
00958
00959 std::ostringstream llsdxml;
00960 LLSDSerialize::toXML(body, llsdxml);
00961 lldebugs << "posting body to capability: " << llsdxml.str() << llendl;
00962 LLHTTPClient::post(url, body, new LLNewAgentInventoryResponder(body, uuid, asset_type));
00963 }
00964 else
00965 {
00966 llinfos << "NewAgentInventory capability not found, new agent inventory via asset system." << llendl;
00967
00968
00969 if (LLAssetType::AT_SOUND == asset_type ||
00970 LLAssetType::AT_TEXTURE == asset_type ||
00971 LLAssetType::AT_ANIMATION == asset_type)
00972 {
00973 S32 upload_cost = LLGlobalEconomy::Singleton::getInstance()->getPriceUpload();
00974 S32 balance = gStatusBar->getBalance();
00975 if (balance < upload_cost)
00976 {
00977
00978 LLFloaterBuyCurrency::buyCurrency("Uploading costs", upload_cost);
00979 return;
00980 }
00981 }
00982
00983 LLResourceData* data = new LLResourceData;
00984 data->mAssetInfo.mTransactionID = tid;
00985 data->mAssetInfo.mUuid = uuid;
00986 data->mAssetInfo.mType = asset_type;
00987 data->mAssetInfo.mCreatorID = gAgentID;
00988 data->mInventoryType = inv_type;
00989 data->mNextOwnerPerm = next_owner_perm;
00990 data->mUserData = userdata;
00991 data->mAssetInfo.setName(name);
00992 data->mAssetInfo.setDescription(desc);
00993 data->mPreferredLocation = destination_folder_type;
00994
00995 LLAssetStorage::LLStoreAssetCallback asset_callback = &upload_done_callback;
00996 if (callback)
00997 {
00998 asset_callback = callback;
00999 }
01000 gAssetStorage->storeAssetData(data->mAssetInfo.mTransactionID, data->mAssetInfo.mType,
01001 asset_callback,
01002 (void*)data,
01003 FALSE);
01004 }
01005 }
01006
01007
01008 void init_menu_file()
01009 {
01010 (new LLFileUploadImage())->registerListener(gMenuHolder, "File.UploadImage");
01011 (new LLFileUploadSound())->registerListener(gMenuHolder, "File.UploadSound");
01012 (new LLFileUploadAnim())->registerListener(gMenuHolder, "File.UploadAnim");
01013 (new LLFileUploadBulk())->registerListener(gMenuHolder, "File.UploadBulk");
01014 (new LLFileCloseWindow())->registerListener(gMenuHolder, "File.CloseWindow");
01015 (new LLFileCloseAllWindows())->registerListener(gMenuHolder, "File.CloseAllWindows");
01016 (new LLFileEnableCloseWindow())->registerListener(gMenuHolder, "File.EnableCloseWindow");
01017 (new LLFileEnableCloseAllWindows())->registerListener(gMenuHolder, "File.EnableCloseAllWindows");
01018 (new LLFileSaveTexture())->registerListener(gMenuHolder, "File.SaveTexture");
01019 (new LLFileTakeSnapshot())->registerListener(gMenuHolder, "File.TakeSnapshot");
01020 (new LLFileTakeSnapshotToDisk())->registerListener(gMenuHolder, "File.TakeSnapshotToDisk");
01021 (new LLFileQuit())->registerListener(gMenuHolder, "File.Quit");
01022
01023 (new LLFileEnableUpload())->registerListener(gMenuHolder, "File.EnableUpload");
01024 (new LLFileEnableSaveAs())->registerListener(gMenuHolder, "File.EnableSaveAs");
01025 }