llviewermenufile.cpp

Go to the documentation of this file.
00001 
00032 #include "llviewerprecompiledheaders.h"
00033 
00034 #include "llviewermenufile.h"
00035 
00036 // project includes
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"   // gInventory
00046 #include "llresourcedata.h"
00047 #include "llstatusbar.h"
00048 #include "llviewercontrol.h"    // gSavedSettings
00049 #include "llviewerimagelist.h"
00050 #include "llvieweruictrlfactory.h"
00051 #include "llviewermenu.h"       // gMenuHolder
00052 #include "llviewerregion.h"
00053 #include "llviewerstats.h"
00054 #include "llviewerwindow.h"
00055 #include "viewer.h"     // app_request_quit()
00056 
00057 // linden libraries
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 // system libraries
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                 // This doesn't seem necessary. JC
00108                 // display();
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         //strincmp doesn't like NULL pointers
00132         if (ext == NULL)
00133         {
00134                 const char* short_name = strrchr(filename,
00135                                                                                  *gDirUtilp->getDirDelimiter().c_str());
00136                 
00137                 // No extension
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                 //so there is an extension
00146                 //loop over the valid extensions and compare to see
00147                 //if the extension is valid
00148 
00149                 //now grab the set of valid file extensions
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                 //now loop over all valid file extensions
00161                 //and compare them to the extension of the file
00162                 //to be uploaded
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)) ||         /* Flawfinder: ignore */
00170                                 0 == strnicmp(cur_token, "*.*", strlen(cur_token)))             /* Flawfinder: ignore */
00171                         {
00172                                 //valid extension
00173                                 //or the acceptable extension is any
00174                                 ext_valid = TRUE;
00175                         }
00176                 }//end for (loop over all tokens)
00177 
00178                 if (ext_valid == FALSE)
00179                 {
00180                         //should only get here if the extension exists
00181                         //but is invalid
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         }//end else (non-null extension)
00189 
00190         //valid file extension
00191         
00192         //now we check to see
00193         //if the file is actually a valid image/sound/etc.
00194         if (type == LLFilePicker::FFLOAD_WAV)
00195         {
00196                 // pre-qualify wavs to make sure the format is acceptable
00197                 char error_msg[MAX_STRING];             /* Flawfinder: ignore */        
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         }//end if a wave/sound file
00207 
00208         
00209         return filename;
00210 }
00211 
00212 /*
00213 void handle_upload_object(void* data)
00214 {
00215         const char* filename = upload_pick(data);
00216         if (filename)
00217         {
00218                 // start the import
00219                 LLFloaterImport* floaterp = new LLFloaterImport(filename);
00220                 gUICtrlFactory->buildFloater(floaterp, "floater_import.xml");
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                 // TODO:
00276                 // Iterate over all files
00277                 // Check extensions for uploadability, cost
00278                 // Check user balance for entire cost
00279                 // Charge user entire cost
00280                 // Loop, uploading
00281                 // If an upload fails, refund the user for that one
00282                 //
00283                 // Also fix single upload to charge first, then refund
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, '.');              // strip extension if exists
00299                         if( !end_p )
00300                         {
00301                                 end_p = asset_name_str + strlen( asset_name_str );              /* Flawfinder: ignore */
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); // file
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                 // horrendously opaque, this code
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         // Generate the temporary UUID.
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];         /* Flawfinder: ignore */        
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                 // No extension
00515                 snprintf(error_message,         /* Flawfinder: ignore */
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",            /* Flawfinder: ignore */
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",            /* Flawfinder: ignore */
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",            /* Flawfinder: ignore */
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;  // tag it as audio
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());           /* Flawfinder: ignore */
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());          /* Flawfinder: ignore */
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                 // This is a generic .lin resource file         
00620          asset_type = LLAssetType::AT_OBJECT;           
00621          FILE* in = LLFile::fopen(src_filename.c_str(), "rb");          /* Flawfinder: ignore */                
00622          if (in)                
00623          {              
00624                  // read in the file header             
00625                  char buf[16384];               /* Flawfinder: ignore */        
00626                  S32 read;              /* Flawfinder: ignore */                
00627                  S32  version;          
00628                  if (fscanf(in, "LindenResource\nversion %d\n", &version))              
00629                  {              
00630                          if (2 == version)              
00631                          {
00632                                                                 // *NOTE: This buffer size is hard coded into scanf() below.
00633                                  char label[MAX_STRING];                /* Flawfinder: ignore */                
00634                                  char value[MAX_STRING];                /* Flawfinder: ignore */                
00635                                  S32  tokens_read;              
00636                                  while (fgets(buf, 1024, in))           
00637                                  {              
00638                                          label[0] = '\0';               
00639                                          value[0] = '\0';               
00640                                          tokens_read = sscanf(  /* Flawfinder: ignore */
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());                /* Flawfinder: ignore */
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                                                          // below is the data section           
00669                                                          break;         
00670                                                  }              
00671                                          }              
00672                                          // other values are currently discarded                
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());         /* Flawfinder: ignore */
00680                                                                  args["[FILE]"] = src_filename;
00681                                                                  upload_error(error_message, "UnknownResourceFileVersion", filename, args);
00682                                  return;
00683                          }              
00684                  }              
00685                  else           
00686                  {              
00687                          // this is an original binary formatted .lin file              
00688                          // start over at the beginning of the file             
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                          // read in and throw out most of the header except for the type                
00697                          if (fread(buf, header_size, 1, in) != 1)
00698                                                  {
00699                                                          llwarns << "Short read" << llendl;
00700                                                  }
00701                          memcpy(&type_num, buf + 16, sizeof(S16));              /* Flawfinder: ignore */                
00702                          asset_type = (LLAssetType::EType)type_num;             
00703                  }              
00704 
00705                  // copy the file's data segment into another file for uploading                
00706                  FILE* out = LLFile::fopen(filename.c_str(), "wb");             /* Flawfinder: ignore */        
00707                  if (out)               
00708                  {              
00709                          while((read = fread(buf, 1, 16384, in)))               /* Flawfinder: ignore */                
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());             /* Flawfinder: ignore */
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");            /* Flawfinder: ignore */
00737                 upload_error(error_message, "DoNotSupportBulkAnimationUpload", filename, args);
00738                 return;
00739         }
00740         else
00741         {
00742                 // Unknown extension
00743                 snprintf(error_message, MAX_STRING, "Unknown file extension %s\nExpected .wav, .tga, .bmp, .jpg, .jpeg, or .bvh", ext.c_str());         /* Flawfinder: ignore */
00744                 error = TRUE;;
00745         }
00746 
00747         // gen a new transaction ID for this asset
00748         tid.generate();
00749 
00750         if (!error)
00751         {
00752                 uuid = tid.makeAssetID(gAgent.getSecureSessionID());
00753                 // copy this file into the vfs for upload
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());              /* Flawfinder: ignore */
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, // tid
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) // StoreAssetData callback (fixed)
00803 {
00804         LLResourceData* data = (LLResourceData*)user_data;
00805         //LLAssetType::EType pref_loc = data->mPreferredLocation;
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                         // Charge the user for the upload.
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                                 // Charge user for upload
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                         // Actually add the upload to inventory
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 //         if(result >= 0)
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         // *NOTE: This is a pretty big hack. What this does is check the
00886         // file picker if there are any more pending uploads. If so,
00887         // upload that file.
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, '.');              // strip extension if exists
00901                 if( !end_p )
00902                 {
00903                         end_p = asset_name_str + strlen( asset_name_str );              /* Flawfinder: ignore */
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,  // file
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         // At this point, we're ready for the upload.
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                 // check for adequate funds
00989                 // TODO: do this check on the sim
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                                 // insufficient funds, bail on this upload
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 }

Generated on Thu Jul 1 06:09:31 2010 for Second Life Viewer by  doxygen 1.4.7