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