From a03b654797f80ebc4b3660930acbed55a7fc2ce2 Mon Sep 17 00:00:00 2001 From: Aura Linden Date: Mon, 12 Nov 2012 16:21:07 -0800 Subject: [PATCH 01/32] Mac updater changes ported from another branch. --- indra/mac_updater/AutoUpdater.xib | 520 ++++++ indra/mac_updater/CMakeLists.txt | 23 +- indra/mac_updater/MacUpdater-Info.plist | 30 + indra/mac_updater/MacUpdaterAppDelegate.h | 58 + indra/mac_updater/MacUpdaterAppDelegate.mm | 274 ++++ indra/mac_updater/mac_updater.cpp | 1664 +++++++------------- indra/mac_updater/mac_updater.h | 89 ++ indra/mac_updater/main.m | 34 + 8 files changed, 1556 insertions(+), 1136 deletions(-) create mode 100644 indra/mac_updater/AutoUpdater.xib create mode 100644 indra/mac_updater/MacUpdater-Info.plist create mode 100644 indra/mac_updater/MacUpdaterAppDelegate.h create mode 100644 indra/mac_updater/MacUpdaterAppDelegate.mm create mode 100644 indra/mac_updater/mac_updater.h create mode 100644 indra/mac_updater/main.m diff --git a/indra/mac_updater/AutoUpdater.xib b/indra/mac_updater/AutoUpdater.xib new file mode 100644 index 0000000000..b29fffba3a --- /dev/null +++ b/indra/mac_updater/AutoUpdater.xib @@ -0,0 +1,520 @@ + + + + 1070 + 11G63 + 2182 + 1138.51 + 569.00 + + com.apple.InterfaceBuilder.CocoaPlugin + 2182 + + + NSTextField + NSView + NSWindowTemplate + NSProgressIndicator + NSCustomObject + IBNSLayoutConstraint + NSButtonCell + NSButton + NSUserDefaultsController + NSTextFieldCell + + + com.apple.InterfaceBuilder.CocoaPlugin + + + PluginDependencyRecalculationVersion + + + + + NSObject + + + FirstResponder + + + NSApplication + + + 15 + 2 + {{196, 240}, {402, 120}} + 544735232 + Window + NSWindow + + + + + 256 + + + + 268 + {{17, 83}, {79, 17}} + + + + _NS:1505 + YES + + 68288064 + 272630784 + Initalizing... + + LucidaGrande + 13 + 1044 + + _NS:1505 + + + 6 + System + controlColor + + 3 + MC42NjY2NjY2NjY3AA + + + + 6 + System + controlTextColor + + 3 + MAA + + + + + + + 268 + {{18, 55}, {366, 20}} + + + + _NS:9 + {250, 250} + 16399 + 100 + + + + 268 + {{308, 19}, {74, 19}} + + + + _NS:9 + YES + + -2080244224 + 134217728 + Cancel + + LucidaGrande + 12 + 16 + + _NS:9 + + -2038152961 + 164 + + + 400 + 75 + + + + {402, 120} + + + + + {{0, 0}, {1680, 1028}} + {10000000000000, 10000000000000} + YES + + + MacUpdaterAppDelegate + + + YES + + + + + + + title: values + + + + + + title: values + title + values + 2 + + + 41 + + + + + + 0 + + + + + + -2 + + + File's Owner + + + -1 + + + First Responder + + + -3 + + + Application + + + 1 + + + + + + + + 2 + + + + + + + 5 + 0 + + 5 + 1 + + 20 + + 1000 + 8 + 29 + 3 + + + + + 5 + 0 + + 5 + 1 + + 20 + + 1000 + 8 + 29 + 3 + + + + + 6 + 0 + + 6 + 1 + + 20 + + 1000 + 8 + 29 + 3 + + + + + + 6 + 0 + + 6 + 1 + + 20 + + 1000 + 8 + 29 + 3 + + + + + 3 + 0 + + 3 + 1 + + 20 + + 1000 + 8 + 29 + 3 + + + + + 3 + 0 + + 4 + 1 + + 8 + + 1000 + 6 + 24 + 3 + + + + + 4 + 0 + + 4 + 1 + + 20 + + 1000 + 8 + 29 + 3 + + + + + + + 3 + + + + + + + + 4 + + + + + 8 + + + + + + 20 + + + + + 22 + + + + + + 7 + 0 + + 0 + 1 + + 74 + + 1000 + 3 + 9 + 1 + + + + + + + 23 + + + + + 31 + + + + + 32 + + + + + 35 + + + + + 36 + + + + + 37 + + + + + 38 + + + + + 39 + + + + + 40 + + + + + 42 + + + + + + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + {{357, 418}, {480, 270}} + + + + + + + + + + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + + + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + + + + + 42 + + + + + MacUpdaterAppDelegate + NSObject + + cancel: + id + + + cancel: + + cancel: + id + + + + NSProgressIndicator + NSTextField + NSWindow + + + + mProgressBar + NSProgressIndicator + + + mProgressText + NSTextField + + + window + NSWindow + + + + IBProjectSource + ./Classes/MacUpdaterAppDelegate.h + + + + + 0 + IBCocoaFramework + YES + 3 + YES + + diff --git a/indra/mac_updater/CMakeLists.txt b/indra/mac_updater/CMakeLists.txt index 00dcedecaa..aa70e64b71 100644 --- a/indra/mac_updater/CMakeLists.txt +++ b/indra/mac_updater/CMakeLists.txt @@ -18,10 +18,14 @@ include_directories( ) set(mac_updater_SOURCE_FILES - mac_updater.cpp + main.m + MacUpdaterAppDelegate.mm + mac_updater.cpp ) set(mac_updater_HEADER_FILES + MacUpdaterAppDelegate.h + mac_updater.h CMakeLists.txt ) @@ -32,7 +36,7 @@ list(APPEND mac_updater_SOURCE_FILES ${mac_updater_HEADER_FILES}) set(mac_updater_RESOURCE_FILES - AutoUpdater.nib/ + AutoUpdater.nib ) set_source_files_properties( ${mac_updater_RESOURCE_FILES} @@ -48,13 +52,18 @@ add_executable(mac-updater set_target_properties(mac-updater PROPERTIES - MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_SOURCE_DIR}/Info.plist + MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_SOURCE_DIR}/MacUpdater-Info.plist ) +find_library(COCOA_LIBRARY Cocoa) +find_library(IOKIT_LIBRARY IOKit) + target_link_libraries(mac-updater ${LLVFS_LIBRARIES} ${OPENSSL_LIBRARIES} ${CRYPTO_LIBRARIES} + ${COCOA_LIBRARIES} + ${IOKIT_LIBRARY} ${CURL_LIBRARIES} ${CARES_LIBRARIES} ${LLCOMMON_LIBRARIES} @@ -62,10 +71,16 @@ target_link_libraries(mac-updater add_custom_command( TARGET mac-updater POST_BUILD +# COMMAND ${CMAKE_COMMAND} +# ARGS +# -E +# copy_directory +# ${CMAKE_CURRENT_SOURCE_DIR}/AutoUpdater.nib +# ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/mac-updater.app/Contents/Resources/AutoUpdater.nib COMMAND ${CMAKE_COMMAND} ARGS -E - copy_directory + copy ${CMAKE_CURRENT_SOURCE_DIR}/AutoUpdater.nib ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/mac-updater.app/Contents/Resources/AutoUpdater.nib ) diff --git a/indra/mac_updater/MacUpdater-Info.plist b/indra/mac_updater/MacUpdater-Info.plist new file mode 100644 index 0000000000..92137095ff --- /dev/null +++ b/indra/mac_updater/MacUpdater-Info.plist @@ -0,0 +1,30 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + mac-updater + CFBundleGetInfoString + + CFBundleIconFile + + CFBundleIdentifier + com.secondlife.indra.autoupdater + CFBundleInfoDictionaryVersion + 6.0 + CFBundlePackageType + APPL + CFBundleShortVersionString + + CFBundleSignature + ???? + CFBundleVersion + 1.0.0 + NSMainNibFile + AutoUpdater + NSPrincipalClass + NSApplication + + diff --git a/indra/mac_updater/MacUpdaterAppDelegate.h b/indra/mac_updater/MacUpdaterAppDelegate.h new file mode 100644 index 0000000000..ba5744b398 --- /dev/null +++ b/indra/mac_updater/MacUpdaterAppDelegate.h @@ -0,0 +1,58 @@ +/** + * @file MacUpdaterAppDelegate.h + * @brief + * + * $LicenseInfo:firstyear=2006&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + + +#import +#include +#include "mac_updater.h" + +#ifndef LL_MAC_UPDATE_DELEGATE_H +#define LL_MAC_UPDATE_DELEGATE_H + +@interface MacUpdaterAppDelegate : NSObject +{ + IBOutlet NSProgressIndicator *mProgressBar; + IBOutlet NSTextField *mProgressText; +} +- (void)setWindow:(NSWindow *)newWindow; +- (NSWindow *)window; +- (IBAction)cancel:(id)sender; +- (void) setProgress:(int)cur max:(int) max; +- (void) setProgressText:(const std::string&)str; +- (int) parse_args:(NSArray *) args; +- (void)stopAlert; +- (void)stopAlertDidEnd:(NSAlert *)alert returnCode:(int)returnCode contextInfo:(void *)contextInfo; + + +NSWindow *_window; +bool mAnimated; +double mProgressPercentage; +@property (assign) IBOutlet NSWindow *window; +LLMacUpdater mUpdater; + +@end + +#endif //LL_MAC_UPDATE_DELEGATE_H \ No newline at end of file diff --git a/indra/mac_updater/MacUpdaterAppDelegate.mm b/indra/mac_updater/MacUpdaterAppDelegate.mm new file mode 100644 index 0000000000..80206cb508 --- /dev/null +++ b/indra/mac_updater/MacUpdaterAppDelegate.mm @@ -0,0 +1,274 @@ +/** + * @file MacUpdaterAppDelegate.mm + * @brief + * + * $LicenseInfo:firstyear=2006&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#import "MacUpdaterAppDelegate.h" +#include "llvfs_objc.h" +#include +#include + +@implementation MacUpdaterAppDelegate + +MacUpdaterAppDelegate *gWindow; +bool gCancelled = false; +bool gFailure =false; + + +//@synthesize window = _window; +- (void)setWindow:(NSWindow *)window +{ + _window = window; +} + +- (NSWindow *)window +{ + return _window; +} + +- (id)init +{ + self = [super init]; + if (self) { + + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + mAnimated = false; + mProgressPercentage = 0.0; + NSArray *arguments = [[NSProcessInfo processInfo] arguments]; + + [self parse_args:arguments]; + gWindow = self; + + mUpdater.doUpdate(); + [pool drain]; + [pool release]; + } + return self; +} + +- (void)dealloc +{ + [super dealloc]; +} + +std::string* NSToString( NSString *ns_str ) +{ + return ( new std::string([ns_str UTF8String]) ); +} + + +- (void) setProgress:(int)cur max:(int) max +{ + bool indeterminate = false; + if (max==0) + { + indeterminate = true; + } + else + { + double percentage = ((double)cur / (double)max) * 100.0; + [mProgressBar setDoubleValue:percentage]; + } + [mProgressBar setIndeterminate:indeterminate]; +} + +- (void) setProgressText:(const std::string& )str +{ + [mProgressText setStringValue:[NSString stringWithUTF8String:str.c_str()]]; +} + +void sendDone() +{ + [ [ (id) gWindow window ] close]; +} + +void sendStopAlert() +{ + [ gWindow stopAlert ]; +} + +void setProgress(int cur, int max) +{ + [ (id) gWindow setProgress:cur max:max]; +} + +void setProgressText(const std::string& str) +{ + [ (id) gWindow setProgressText:str]; +} + +void sendProgress(int cur, int max, const std::string str) +{ + setProgress(cur,max); + setProgressText(str); +} + +bool mkTempDir(boost::filesystem::path& temp_dir) +{ + NSString * tempDir = NSTemporaryDirectory(); + if (tempDir == nil) + tempDir = @"/tmp/"; + + std::string* temp_str = NSToString(tempDir); + *temp_str += std::string("SecondLifeUpdate_XXXXXX"); + + std::cout << "tempDir is " << temp_str << std::endl; + + char temp[PATH_MAX] = ""; /* Flawfinder: ignore */ + strncpy(temp, temp_str->c_str(), temp_str->length()); + + if(mkdtemp(temp) == NULL) + { + return false; + } + + temp_dir = boost::filesystem::path(temp); + + delete temp_str; + + return true; +} + +bool copyDir(const std::string& src_dir, const std::string& dest_dir) +{ + NSString* file = [NSString stringWithCString:src_dir.c_str() + encoding:[NSString defaultCStringEncoding]]; + NSString* toParent = [NSString stringWithCString:dest_dir.c_str() + encoding:[NSString defaultCStringEncoding]]; + NSError* error = nil; + + bool result = [[NSFileManager defaultManager] copyItemAtPath: file toPath: toParent error:&error]; + + if (!result) { + NSLog(@"Error during copy: %@", [error localizedDescription]); + } + return result; +} + +- (int) parse_args:(NSArray *) args +{ + int i; + int argc = [args count]; + + mUpdater.mApplicationPath = NSToString( [args objectAtIndex:0] ); + + for( i = 1; i < argc; i++ ) + { + NSString* ns_arg = [args objectAtIndex:i]; + const char *arg = [ns_arg UTF8String]; + + if ((!strcmp(arg, "-url")) && (i < argc)) + { + mUpdater.mUpdateURL = NSToString( [args objectAtIndex:(++i)] ); + } + else if ((!strcmp(arg, "-name")) && (i < argc)) + { + mUpdater.mProductName = NSToString( [args objectAtIndex:(++i)] ); + } + else if ((!strcmp(arg, "-bundleid")) && (i < argc)) + { + mUpdater.mBundleID = NSToString( [args objectAtIndex:(++i)] ); + } + else if ((!strcmp(arg, "-dmg")) && (i < argc)) + { + mUpdater.mDmgFile = NSToString( [args objectAtIndex:(++i)] ); + } + else if ((!strcmp(arg, "-marker")) && (i < argc)) + { + mUpdater.mMarkerPath = NSToString( [args objectAtIndex:(++i)] ); + } + } + return 0; +} + +bool isDirWritable(const std::string& dir_name) +{ + + NSString *fullPath = [NSString stringWithCString:dir_name.c_str() + encoding:[NSString defaultCStringEncoding]]; + + NSFileManager *fm = [NSFileManager defaultManager]; + bool result = [fm isWritableFileAtPath:fullPath]; + + return result; +} + +std::string* getUserTrashFolder() +{ + NSString *trash_str=[NSHomeDirectory() stringByAppendingPathComponent:@".Trash"]; + return NSToString( trash_str ); + +} + +bool isFSRefViewerBundle(const std::string& targetURL) +{ + bool result = false; + + NSString *fullPath = [NSString stringWithCString:targetURL.c_str() + encoding:[NSString defaultCStringEncoding]]; + NSBundle *targetBundle = [NSBundle bundleWithPath:fullPath]; + NSString *targetBundleStr = [targetBundle bundleIdentifier]; + NSString *sourceBundleStr = [NSString stringWithCString:mUpdater.mBundleID->c_str() + encoding:[NSString defaultCStringEncoding]]; + + result = [targetBundleStr isEqualToString:sourceBundleStr]; + + if(!result) + { + std::cout << "Target bundle ID mismatch." << std::endl; + } + + return result; +} + + +- (IBAction)cancel:(id)sender +{ + gCancelled = true; + sendDone(); +} + +- (void)stopAlert +{ + NSAlert *alert = [[NSAlert alloc] init]; + [alert setAlertStyle:NSInformationalAlertStyle]; + [alert setMessageText:@"Error"]; + [alert setInformativeText:@"An error occurred while updating Second Life. Please download the latest version from www.secondlife.com."]; + + [alert beginSheetModalForWindow:_window + modalDelegate:self + + didEndSelector:@selector(stopAlertDidEnd:returnCode: + contextInfo:) + contextInfo:nil]; + } + + - (void)stopAlertDidEnd:(NSAlert *)alert + returnCode:(int)returnCode contextInfo:(void *)contextInfo +{ + [alert release]; +} + + +@end diff --git a/indra/mac_updater/mac_updater.cpp b/indra/mac_updater/mac_updater.cpp index aa45c5d23f..379e69e033 100644 --- a/indra/mac_updater/mac_updater.cpp +++ b/indra/mac_updater/mac_updater.cpp @@ -27,6 +27,8 @@ #include "linden_common.h" #include +#include +#include #include #include @@ -34,7 +36,6 @@ #include #include -#include #include "llerror.h" #include "lltimer.h" @@ -43,267 +44,123 @@ #include "llstring.h" -#include - #include "llerrorcontrol.h" - -enum -{ - kEventClassCustom = 'Cust', - kEventCustomProgress = 'Prog', - kEventParamCustomCurValue = 'Cur ', - kEventParamCustomMaxValue = 'Max ', - kEventParamCustomText = 'Text', - kEventCustomDone = 'Done', -}; - -WindowRef gWindow = NULL; -EventHandlerRef gEventHandler = NULL; -OSStatus gFailure = noErr; -Boolean gCancelled = false; - -const char *gUpdateURL; -const char *gProductName; -const char *gBundleID; -const char *gDmgFile; -const char *gMarkerPath; - -void *updatethreadproc(void*); +#include "mac_updater.h" +#include pthread_t updatethread; -OSStatus setProgress(int cur, int max) +LLMacUpdater* LLMacUpdater::sInstance = NULL; + +LLMacUpdater::LLMacUpdater(): + mUpdateURL (NULL), + mProductName (NULL), + mBundleID (NULL), + mDmgFile (NULL), + mMarkerPath (NULL) { - OSStatus err; - ControlRef progressBar = NULL; - ControlID id; + sInstance = this; +} - id.signature = 'prog'; - id.id = 0; - - err = GetControlByID(gWindow, &id, &progressBar); - if(err == noErr) +void LLMacUpdater::doUpdate() +{ + // We assume that all the logs we're looking for reside on the current drive + gDirUtilp->initAppDirs("SecondLife"); + + LLError::initForApplication( gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "")); + + // Rename current log file to ".old" + std::string old_log_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "updater.log.old"); + std::string log_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "updater.log"); + LLFile::rename(log_file.c_str(), old_log_file.c_str()); + + // Set the log file to updater.log + LLError::logToFile(log_file); + + if ((mUpdateURL == NULL) && (mDmgFile == NULL)) { - Boolean indeterminate; - - if(max == 0) + llinfos << "Usage: mac_updater -url | -dmg [-name ] [-program ]" << llendl; + exit(1); + } + else + { + llinfos << "Update url is: " << mUpdateURL << llendl; + if (mProductName) { - indeterminate = true; - err = SetControlData(progressBar, kControlEntireControl, kControlProgressBarIndeterminateTag, sizeof(Boolean), (Ptr)&indeterminate); + llinfos << "Product name is: " << *mProductName << llendl; } else { - double percentage = (double)cur / (double)max; - SetControlMinimum(progressBar, 0); - SetControlMaximum(progressBar, 100); - SetControlValue(progressBar, (SInt16)(percentage * 100)); - - indeterminate = false; - err = SetControlData(progressBar, kControlEntireControl, kControlProgressBarIndeterminateTag, sizeof(Boolean), (Ptr)&indeterminate); - - Draw1Control(progressBar); + mProductName = new std::string("Second Life"); } - } - - return(err); -} - -OSStatus setProgressText(CFStringRef text) -{ - OSStatus err; - ControlRef progressText = NULL; - ControlID id; - - id.signature = 'what'; - id.id = 0; - - err = GetControlByID(gWindow, &id, &progressText); - if(err == noErr) - { - err = SetControlData(progressText, kControlEntireControl, kControlStaticTextCFStringTag, sizeof(CFStringRef), (Ptr)&text); - Draw1Control(progressText); - } - - return(err); -} - -OSStatus sendProgress(long cur, long max, CFStringRef text = NULL) -{ - OSStatus result; - EventRef evt; - - result = CreateEvent( - NULL, - kEventClassCustom, - kEventCustomProgress, - 0, - kEventAttributeNone, - &evt); - - // This event needs to be targeted at the window so it goes to the window's handler. - if(result == noErr) - { - EventTargetRef target = GetWindowEventTarget(gWindow); - result = SetEventParameter ( - evt, - kEventParamPostTarget, - typeEventTargetRef, - sizeof(target), - &target); - } - - if(result == noErr) - { - result = SetEventParameter ( - evt, - kEventParamCustomCurValue, - typeLongInteger, - sizeof(cur), - &cur); - } - - if(result == noErr) - { - result = SetEventParameter ( - evt, - kEventParamCustomMaxValue, - typeLongInteger, - sizeof(max), - &max); - } - - if(result == noErr) - { - if(text != NULL) + if (mBundleID) { - result = SetEventParameter ( - evt, - kEventParamCustomText, - typeCFStringRef, - sizeof(text), - &text); + llinfos << "Bundle ID is: " << *mBundleID << llendl; } - } - - if(result == noErr) - { - // Send the event - PostEventToQueue( - GetMainEventQueue(), - evt, - kEventPriorityStandard); - - } - - return(result); -} - -OSStatus sendDone(void) -{ - OSStatus result; - EventRef evt; - - result = CreateEvent( - NULL, - kEventClassCustom, - kEventCustomDone, - 0, - kEventAttributeNone, - &evt); - - // This event needs to be targeted at the window so it goes to the window's handler. - if(result == noErr) - { - EventTargetRef target = GetWindowEventTarget(gWindow); - result = SetEventParameter ( - evt, - kEventParamPostTarget, - typeEventTargetRef, - sizeof(target), - &target); - } - - if(result == noErr) - { - // Send the event - PostEventToQueue( - GetMainEventQueue(), - evt, - kEventPriorityStandard); - - } - - return(result); -} - -OSStatus dialogHandler(EventHandlerCallRef handler, EventRef event, void *userdata) -{ - OSStatus result = eventNotHandledErr; - OSStatus err; - UInt32 evtClass = GetEventClass(event); - UInt32 evtKind = GetEventKind(event); - - if((evtClass == kEventClassCommand) && (evtKind == kEventCommandProcess)) - { - HICommand cmd; - err = GetEventParameter(event, kEventParamDirectObject, typeHICommand, NULL, sizeof(cmd), NULL, &cmd); - - if(err == noErr) + else { - switch(cmd.commandID) - { - case kHICommandCancel: - gCancelled = true; -// QuitAppModalLoopForWindow(gWindow); - result = noErr; - break; - } + mBundleID = new std::string("com.secondlife.indra.viewer"); } } - else if((evtClass == kEventClassCustom) && (evtKind == kEventCustomProgress)) - { - // Request to update the progress dialog - long cur = 0; - long max = 0; - CFStringRef text = NULL; - (void) GetEventParameter(event, kEventParamCustomCurValue, typeLongInteger, NULL, sizeof(cur), NULL, &cur); - (void) GetEventParameter(event, kEventParamCustomMaxValue, typeLongInteger, NULL, sizeof(max), NULL, &max); - (void) GetEventParameter(event, kEventParamCustomText, typeCFStringRef, NULL, sizeof(text), NULL, &text); - - err = setProgress(cur, max); - if(err == noErr) - { - if(text != NULL) - { - setProgressText(text); - } - } - - result = noErr; - } - else if((evtClass == kEventClassCustom) && (evtKind == kEventCustomDone)) - { - // We're done. Exit the modal loop. - QuitAppModalLoopForWindow(gWindow); - result = noErr; - } - return(result); + llinfos << "Starting " << *mProductName << " Updater" << llendl; + + pthread_create(&updatethread, + NULL, + &sUpdatethreadproc, + NULL); + + + void *threadresult; + + pthread_join(updatethread, &threadresult); + + if(gCancelled || gFailure) + { + sendStopAlert(); + + if(mMarkerPath != 0) + { + // Create a install fail marker that can be used by the viewer to + // detect install problems. + std::ofstream stream(mMarkerPath->c_str()); + if(stream) stream << -1; + } + exit(-1); + } else { + exit(0); + } + + return; } -#if 0 -size_t curl_download_callback(void *data, size_t size, size_t nmemb, - void *user_data) +//SPATTERS TODO this should be moved to lldir_mac.cpp +const std::string LLMacUpdater::walkParents( unsigned int depth, const std::string& childpath ) { - S32 bytes = size * nmemb; - char *cdata = (char *) data; - for (int i =0; i < bytes; i += 1) - { - gServerResponse.append(cdata[i]); - } - return bytes; + boost::filesystem::path fullpath(childpath.c_str()); + + while (depth >= 0 && fullpath.has_parent_path()) + { + fullpath = boost::filesystem::path(fullpath.parent_path()); + --depth; + } + + return fullpath.string(); } -#endif + +//#if 0 +//size_t curl_download_callback(void *data, size_t size, size_t nmemb, +// void *user_data) +//{ +// S32 bytes = size * nmemb; +// char *cdata = (char *) data; +// for (int i =0; i < bytes; i += 1) +// { +// gServerResponse.append(cdata[i]); +// } +// return bytes; +//} +//#endif int curl_progress_callback_func(void *clientp, double dltotal, @@ -313,7 +170,7 @@ int curl_progress_callback_func(void *clientp, { int max = (int)(dltotal / 1024.0); int cur = (int)(dlnow / 1024.0); - sendProgress(cur, max); + setProgress(cur, max); if(gCancelled) return(1); @@ -321,899 +178,416 @@ int curl_progress_callback_func(void *clientp, return(0); } -int parse_args(int argc, char **argv) +bool LLMacUpdater::isApplication(const std::string& app_str) { - int j; - - for (j = 1; j < argc; j++) - { - if ((!strcmp(argv[j], "-url")) && (++j < argc)) - { - gUpdateURL = argv[j]; - } - else if ((!strcmp(argv[j], "-name")) && (++j < argc)) - { - gProductName = argv[j]; - } - else if ((!strcmp(argv[j], "-bundleid")) && (++j < argc)) - { - gBundleID = argv[j]; - } - else if ((!strcmp(argv[j], "-dmg")) && (++j < argc)) - { - gDmgFile = argv[j]; - } - else if ((!strcmp(argv[j], "-marker")) && (++j < argc)) - { - gMarkerPath = argv[j];; - } - } - - return 0; + return !(bool) app_str.compare( app_str.length()-4, 4, ".app"); } - -int main(int argc, char **argv) -{ - // We assume that all the logs we're looking for reside on the current drive - gDirUtilp->initAppDirs("SecondLife"); - - LLError::initForApplication( gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "")); - - // Rename current log file to ".old" - std::string old_log_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "updater.log.old"); - std::string log_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "updater.log"); - LLFile::rename(log_file.c_str(), old_log_file.c_str()); - - // Set the log file to updater.log - LLError::logToFile(log_file); - - ///////////////////////////////////////// - // - // Process command line arguments - // - gUpdateURL = NULL; - gProductName = NULL; - gBundleID = NULL; - gDmgFile = NULL; - gMarkerPath = NULL; - parse_args(argc, argv); - if ((gUpdateURL == NULL) && (gDmgFile == NULL)) - { - llinfos << "Usage: mac_updater -url | -dmg [-name ] [-program ]" << llendl; - exit(1); - } - else - { - llinfos << "Update url is: " << gUpdateURL << llendl; - if (gProductName) - { - llinfos << "Product name is: " << gProductName << llendl; - } - else - { - gProductName = "Second Life"; - } - if (gBundleID) - { - llinfos << "Bundle ID is: " << gBundleID << llendl; - } - else - { - gBundleID = "com.secondlife.indra.viewer"; - } - } - - llinfos << "Starting " << gProductName << " Updater" << llendl; - - // Real UI... - OSStatus err; - IBNibRef nib = NULL; - - err = CreateNibReference(CFSTR("AutoUpdater"), &nib); - - char windowTitle[MAX_PATH]; /* Flawfinder: ignore */ - snprintf(windowTitle, sizeof(windowTitle), "%s Updater", gProductName); - CFStringRef windowTitleRef = NULL; - windowTitleRef = CFStringCreateWithCString(NULL, windowTitle, kCFStringEncodingUTF8); - - if(err == noErr) - { - err = CreateWindowFromNib(nib, CFSTR("Updater"), &gWindow); - } - - if (err == noErr) - { - err = SetWindowTitleWithCFString(gWindow, windowTitleRef); - } - CFRelease(windowTitleRef); - - if(err == noErr) - { - // Set up an event handler for the window. - EventTypeSpec handlerEvents[] = - { - { kEventClassCommand, kEventCommandProcess }, - { kEventClassCustom, kEventCustomProgress }, - { kEventClassCustom, kEventCustomDone } - }; - InstallStandardEventHandler(GetWindowEventTarget(gWindow)); - InstallWindowEventHandler( - gWindow, - NewEventHandlerUPP(dialogHandler), - GetEventTypeCount (handlerEvents), - handlerEvents, - 0, - &gEventHandler); - } - - if(err == noErr) - { - ShowWindow(gWindow); - SelectWindow(gWindow); - } - - if(err == noErr) - { - pthread_create(&updatethread, - NULL, - &updatethreadproc, - NULL); - - } - - if(err == noErr) - { - RunAppModalLoopForWindow(gWindow); - } - - void *threadresult; - - pthread_join(updatethread, &threadresult); - - if(!gCancelled && (gFailure != noErr)) - { - // Something went wrong. Since we always just tell the user to download a new version, we don't really care what. - AlertStdCFStringAlertParamRec params; - SInt16 retval_mac = 1; - DialogRef alert = NULL; - OSStatus err; - - params.version = kStdCFStringAlertVersionOne; - params.movable = false; - params.helpButton = false; - params.defaultText = (CFStringRef)kAlertDefaultOKText; - params.cancelText = 0; - params.otherText = 0; - params.defaultButton = 1; - params.cancelButton = 0; - params.position = kWindowDefaultPosition; - params.flags = 0; - - err = CreateStandardAlert( - kAlertStopAlert, - CFSTR("Error"), - CFSTR("An error occurred while updating Second Life. Please download the latest version from www.secondlife.com."), - ¶ms, - &alert); - - if(err == noErr) - { - err = RunStandardAlert( - alert, - NULL, - &retval_mac); - } - - if(gMarkerPath != 0) - { - // Create a install fail marker that can be used by the viewer to - // detect install problems. - std::ofstream stream(gMarkerPath); - if(stream) stream << -1; - } - exit(-1); - } else { - exit(0); - } - - if(gWindow != NULL) - { - DisposeWindow(gWindow); - } - - if(nib != NULL) - { - DisposeNibReference(nib); - } - - return 0; -} - -bool isDirWritable(FSRef &dir) -{ - bool result = false; - - // Test for a writable directory by creating a directory, then deleting it again. - // This is kinda lame, but will pretty much always give the right answer. - - OSStatus err = noErr; - char temp[PATH_MAX] = ""; /* Flawfinder: ignore */ - - err = FSRefMakePath(&dir, (UInt8*)temp, sizeof(temp)); - - if(err == noErr) - { - strncat(temp, "/.test_XXXXXX", (sizeof(temp) - strlen(temp)) - 1); - - if(mkdtemp(temp) != NULL) - { - // We were able to make the directory. This means the directory is writable. - result = true; - - // Clean up. - rmdir(temp); - } - } - -#if 0 - // This seemed like a good idea, but won't tell us if we're on a volume mounted read-only. - UInt8 perm; - err = FSGetUserPrivilegesPermissions(&targetParentRef, &perm, NULL); - if(err == noErr) - { - if(perm & kioACUserNoMakeChangesMask) - { - // Parent directory isn't writable. - llinfos << "Target parent directory not writable." << llendl; - err = -1; - replacingTarget = false; - } - } -#endif - - return result; -} - -static std::string HFSUniStr255_to_utf8str(const HFSUniStr255* src) -{ - llutf16string string16((U16*)&(src->unicode), src->length); - std::string result = utf16str_to_utf8str(string16); - return result; -} - -int restoreObject(const char* aside, const char* target, const char* path, const char* object) -{ - char source[PATH_MAX] = ""; /* Flawfinder: ignore */ - char dest[PATH_MAX] = ""; /* Flawfinder: ignore */ - snprintf(source, sizeof(source), "%s/%s/%s", aside, path, object); - snprintf(dest, sizeof(dest), "%s/%s", target, path); - FSRef sourceRef; - FSRef destRef; - OSStatus err; - err = FSPathMakeRef((UInt8 *)source, &sourceRef, NULL); - if(err != noErr) return false; - err = FSPathMakeRef((UInt8 *)dest, &destRef, NULL); - if(err != noErr) return false; - - llinfos << "Copying " << source << " to " << dest << llendl; - - err = FSCopyObjectSync( - &sourceRef, - &destRef, - NULL, - NULL, - kFSFileOperationOverwrite); - - if(err != noErr) return false; - return true; -} - -// Replace any mention of "Second Life" with the product name. -void filterFile(const char* filename) -{ - char temp[PATH_MAX] = ""; /* Flawfinder: ignore */ - // First copy the target's version, so we can run it through sed. - snprintf(temp, sizeof(temp), "cp '%s' '%s.tmp'", filename, filename); - system(temp); /* Flawfinder: ignore */ - - // Now run it through sed. - snprintf(temp, sizeof(temp), - "sed 's/Second Life/%s/g' '%s.tmp' > '%s'", gProductName, filename, filename); - system(temp); /* Flawfinder: ignore */ -} - -static bool isFSRefViewerBundle(FSRef *targetRef) -{ - bool result = false; - CFURLRef targetURL = NULL; - CFBundleRef targetBundle = NULL; - CFStringRef targetBundleID = NULL; - CFStringRef sourceBundleID = NULL; - - targetURL = CFURLCreateFromFSRef(NULL, targetRef); - - if(targetURL == NULL) - { - llinfos << "Error creating target URL." << llendl; - } - else - { - targetBundle = CFBundleCreate(NULL, targetURL); - } - - if(targetBundle == NULL) - { - llinfos << "Failed to create target bundle." << llendl; - } - else - { - targetBundleID = CFBundleGetIdentifier(targetBundle); - } - - if(targetBundleID == NULL) - { - llinfos << "Couldn't retrieve target bundle ID." << llendl; - } - else - { - sourceBundleID = CFStringCreateWithCString(NULL, gBundleID, kCFStringEncodingUTF8); - if(CFStringCompare(sourceBundleID, targetBundleID, 0) == kCFCompareEqualTo) - { - // This is the bundle we're looking for. - result = true; - } - else - { - llinfos << "Target bundle ID mismatch." << llendl; - } - } - - // Don't release targetBundleID -- since we don't retain it, it's released when targetBundle is released. - if(targetURL != NULL) - CFRelease(targetURL); - if(targetBundle != NULL) - CFRelease(targetBundle); - - return result; -} - + // Search through the directory specified by 'parent' for an item that appears to be a Second Life viewer. -static OSErr findAppBundleOnDiskImage(FSRef *parent, FSRef *app) +bool LLMacUpdater::findAppBundleOnDiskImage(const boost::filesystem::path& dir_path, + boost::filesystem::path& path_found) { - FSIterator iterator; - bool found = false; + if ( !exists( dir_path ) ) return false; - OSErr err = FSOpenIterator( parent, kFSIterateFlat, &iterator ); - if(!err) - { - do - { - ItemCount actualObjects = 0; - Boolean containerChanged = false; - FSCatalogInfo info; - FSRef ref; - HFSUniStr255 unicodeName; - err = FSGetCatalogInfoBulk( - iterator, - 1, - &actualObjects, - &containerChanged, - kFSCatInfoNodeFlags, - &info, - &ref, - NULL, - &unicodeName ); - - if(actualObjects == 0) - break; - - if(!err) - { - // Call succeeded and not done with the iteration. - std::string name = HFSUniStr255_to_utf8str(&unicodeName); + boost::filesystem::directory_iterator end_itr; + + for ( boost::filesystem::directory_iterator itr( dir_path ); + itr != end_itr; + ++itr ) + { + if ( boost::filesystem::is_directory(itr->status()) ) + { + std::string dir_name = itr->string(); + if ( isApplication(dir_name) ) + { + if(isFSRefViewerBundle(dir_name)) + { + llinfos << dir_name << " is the one" << llendl; - llinfos << "Considering \"" << name << "\"" << llendl; - - if(info.nodeFlags & kFSNodeIsDirectoryMask) - { - // This is a directory. See if it's a .app - if(name.find(".app") != std::string::npos) - { - // Looks promising. Check to see if it has the right bundle identifier. - if(isFSRefViewerBundle(&ref)) - { - llinfos << name << " is the one" << llendl; - // This is the one. Return it. - *app = ref; - found = true; - break; - } else { - llinfos << name << " is not the bundle we are looking for; move along" << llendl; - } - - } - } - } - } - while(!err); - - llinfos << "closing the iterator" << llendl; - - FSCloseIterator(iterator); - - llinfos << "closed" << llendl; - } - - if(!err && !found) - err = fnfErr; - - return err; + path_found = itr->path(); + return true; + } + } + } + } + return false; } -void *updatethreadproc(void*) +bool LLMacUpdater::verifyDirectory(const boost::filesystem::path* directory, bool isParent) +{ + bool replacingTarget; + std::string app_str = directory->string(); + + if (boost::filesystem::is_directory(*directory)) + { + // This is fine, just means we're not replacing anything. + replacingTarget = true; + } + else + { + replacingTarget = isParent; + } + + //Check that the directory is writeable. + if(!isDirWritable(app_str)) + { + // Parent directory isn't writable. + llinfos << "Target directory not writable." << llendl; + replacingTarget = false; + } + return replacingTarget; +} + +bool LLMacUpdater::getViewerDir(boost::filesystem::path &app_dir) +{ + std::string app_dir_str; + + //Walk up 6 levels from the App Updater's installation point. + app_dir_str = walkParents( 6, *mApplicationPath ); + + app_dir = boost::filesystem::path(app_dir_str); + + std::string app_str(app_dir.string()); + + //Check to see that the directory's name ends in .app Lame but it's the best thing we have to go on. + //If it's not there, we're going to default to /Applications/VIEWERNAME + if (!isApplication(app_str)) + { + llinfos << "Target search failed, defaulting to /Applications/" << *mProductName << ".app." << llendl; + std::string newpath = std::string("/Applications/") + mProductName->c_str(); + app_dir = boost::filesystem::path(newpath); + } + return verifyDirectory(&app_dir); +} + +bool LLMacUpdater::downloadDMG(const std::string& dmgName, boost::filesystem::path* temp_dir) { - char tempDir[PATH_MAX] = ""; /* Flawfinder: ignore */ - FSRef tempDirRef; - char temp[PATH_MAX] = ""; /* Flawfinder: ignore */ - // *NOTE: This buffer length is used in a scanf() below. - char deviceNode[1024] = ""; /* Flawfinder: ignore */ LLFILE *downloadFile = NULL; - OSStatus err; - ProcessSerialNumber psn; - char target[PATH_MAX] = ""; /* Flawfinder: ignore */ - FSRef targetRef; - FSRef targetParentRef; - FSVolumeRefNum targetVol; - FSRef trashFolderRef; - Boolean replacingTarget = false; + char temp[PATH_MAX] = ""; /* Flawfinder: ignore */ - memset(&tempDirRef, 0, sizeof(tempDirRef)); - memset(&targetRef, 0, sizeof(targetRef)); - memset(&targetParentRef, 0, sizeof(targetParentRef)); - - try - { - // Attempt to get a reference to the Second Life application bundle containing this updater. - // Any failures during this process will cause us to default to updating /Applications/Second Life.app - { - FSRef myBundle; - - err = GetCurrentProcess(&psn); - if(err == noErr) - { - err = GetProcessBundleLocation(&psn, &myBundle); - } - - if(err == noErr) - { - // Sanity check: Make sure the name of the item referenced by targetRef is "Second Life.app". - FSRefMakePath(&myBundle, (UInt8*)target, sizeof(target)); - - llinfos << "Updater bundle location: " << target << llendl; - } - - // Our bundle should be in Second Life.app/Contents/Resources/AutoUpdater.app - // so we need to go up 3 levels to get the path to the main application bundle. - if(err == noErr) - { - err = FSGetCatalogInfo(&myBundle, kFSCatInfoNone, NULL, NULL, NULL, &targetRef); - } - if(err == noErr) - { - err = FSGetCatalogInfo(&targetRef, kFSCatInfoNone, NULL, NULL, NULL, &targetRef); - } - if(err == noErr) - { - err = FSGetCatalogInfo(&targetRef, kFSCatInfoNone, NULL, NULL, NULL, &targetRef); - } - - // And once more to get the parent of the target - if(err == noErr) - { - err = FSGetCatalogInfo(&targetRef, kFSCatInfoNone, NULL, NULL, NULL, &targetParentRef); - } - - if(err == noErr) - { - FSRefMakePath(&targetRef, (UInt8*)target, sizeof(target)); - llinfos << "Path to target: " << target << llendl; - } - - // Sanity check: make sure the target is a bundle with the right identifier - if(err == noErr) - { - // Assume the worst... - err = -1; - - if(isFSRefViewerBundle(&targetRef)) - { - // This is the bundle we're looking for. - err = noErr; - replacingTarget = true; - } - } - - // Make sure the target's parent directory is writable. - if(err == noErr) - { - if(!isDirWritable(targetParentRef)) - { - // Parent directory isn't writable. - llinfos << "Target parent directory not writable." << llendl; - err = -1; - replacingTarget = false; - } - } - - if(err != noErr) - { - Boolean isDirectory; - llinfos << "Target search failed, defaulting to /Applications/" << gProductName << ".app." << llendl; - - // Set up the parent directory - err = FSPathMakeRef((UInt8*)"/Applications", &targetParentRef, &isDirectory); - if((err != noErr) || (!isDirectory)) - { - // We're so hosed. - llinfos << "Applications directory not found, giving up." << llendl; - throw 0; - } - - snprintf(target, sizeof(target), "/Applications/%s.app", gProductName); - - memset(&targetRef, 0, sizeof(targetRef)); - err = FSPathMakeRef((UInt8*)target, &targetRef, NULL); - if(err == fnfErr) - { - // This is fine, just means we're not replacing anything. - err = noErr; - replacingTarget = false; - } - else - { - replacingTarget = true; - } - - // Make sure the target's parent directory is writable. - if(err == noErr) - { - if(!isDirWritable(targetParentRef)) - { - // Parent directory isn't writable. - llinfos << "Target parent directory not writable." << llendl; - err = -1; - replacingTarget = false; - } - } - - } - - // If we haven't fixed all problems by this point, just bail. - if(err != noErr) - { - llinfos << "Unable to pick a target, giving up." << llendl; - throw 0; - } - } - - // Find the volID of the volume the target resides on - { - FSCatalogInfo info; - err = FSGetCatalogInfo( - &targetParentRef, - kFSCatInfoVolume, - &info, - NULL, - NULL, - NULL); - - if(err != noErr) - throw 0; - - targetVol = info.volume; - } - - // Find the temporary items and trash folders on that volume. - err = FSFindFolder( - targetVol, - kTrashFolderType, - true, - &trashFolderRef); - - if(err != noErr) - throw 0; - -#if 0 // *HACK for DEV-11935 see below for details. - - FSRef tempFolderRef; - - err = FSFindFolder( - targetVol, - kTemporaryFolderType, - true, - &tempFolderRef); - - if(err != noErr) - throw 0; - - err = FSRefMakePath(&tempFolderRef, (UInt8*)temp, sizeof(temp)); - - if(err != noErr) - throw 0; - -#else - - // *HACK for DEV-11935 the above kTemporaryFolderType query was giving - // back results with path names that seem to be too long to be used as - // mount points. I suspect this incompatibility was introduced in the - // Leopard 10.5.2 update, but I have not verified this. - char const HARDCODED_TMP[] = "/tmp"; - strncpy(temp, HARDCODED_TMP, sizeof(HARDCODED_TMP)); - -#endif // 0 *HACK for DEV-11935 - - // Skip downloading the file if the dmg was passed on the command line. - std::string dmgName; - if(gDmgFile != NULL) { - dmgName = basename((char *)gDmgFile); - char * dmgDir = dirname((char *)gDmgFile); - strncpy(tempDir, dmgDir, sizeof(tempDir)); - err = FSPathMakeRef((UInt8*)tempDir, &tempDirRef, NULL); - if(err != noErr) throw 0; - chdir(tempDir); - goto begin_install; - } else { - // Continue on to download file. - dmgName = "SecondLife.dmg"; - } - - - strncat(temp, "/SecondLifeUpdate_XXXXXX", (sizeof(temp) - strlen(temp)) - 1); - if(mkdtemp(temp) == NULL) - { - throw 0; - } - - strncpy(tempDir, temp, sizeof(tempDir)); - temp[sizeof(tempDir) - 1] = '\0'; - - llinfos << "tempDir is " << tempDir << llendl; - - err = FSPathMakeRef((UInt8*)tempDir, &tempDirRef, NULL); - - if(err != noErr) - throw 0; - - chdir(tempDir); - - snprintf(temp, sizeof(temp), "SecondLife.dmg"); - - downloadFile = LLFile::fopen(temp, "wb"); /* Flawfinder: ignore */ - if(downloadFile == NULL) - { - throw 0; - } - - { - CURL *curl = curl_easy_init(); - - curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1); - // curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &curl_download_callback); - curl_easy_setopt(curl, CURLOPT_FILE, downloadFile); - curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0); - curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, &curl_progress_callback_func); - curl_easy_setopt(curl, CURLOPT_URL, gUpdateURL); - curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1); - - sendProgress(0, 1, CFSTR("Downloading...")); - - CURLcode result = curl_easy_perform(curl); - - curl_easy_cleanup(curl); - - if(gCancelled) - { - llinfos << "User cancel, bailing out."<< llendl; - throw 0; - } - - if(result != CURLE_OK) - { - llinfos << "Error " << result << " while downloading disk image."<< llendl; - throw 0; - } - - fclose(downloadFile); - downloadFile = NULL; - } - - begin_install: - sendProgress(0, 0, CFSTR("Mounting image...")); - LLFile::mkdir("mnt", 0700); - - // NOTE: we could add -private at the end of this command line to keep the image from showing up in the Finder, - // but if our cleanup fails, this makes it much harder for the user to unmount the image. - std::string mountOutput; - boost::format cmdFormat("hdiutil attach %s -mountpoint mnt"); - cmdFormat % dmgName; - FILE* mounter = popen(cmdFormat.str().c_str(), "r"); /* Flawfinder: ignore */ - - if(mounter == NULL) - { - llinfos << "Failed to mount disk image, exiting."<< llendl; - throw 0; - } - - // We need to scan the output from hdiutil to find the device node it uses to attach the disk image. - // If we don't have this information, we can't detach it later. - while(mounter != NULL) - { - size_t len = fread(temp, 1, sizeof(temp)-1, mounter); - temp[len] = 0; - mountOutput.append(temp); - if(len < sizeof(temp)-1) - { - // End of file or error. - int result = pclose(mounter); - if(result != 0) - { - // NOTE: We used to abort here, but pclose() started returning - // -1, possibly when the size of the DMG passed a certain point - llinfos << "Unexpected result closing pipe: " << result << llendl; - } - mounter = NULL; - } - } - - if(!mountOutput.empty()) - { - const char *s = mountOutput.c_str(); - const char *prefix = "/dev/"; - char *sub = strstr(s, prefix); - - if(sub != NULL) - { - sub += strlen(prefix); /* Flawfinder: ignore */ - sscanf(sub, "%1023s", deviceNode); /* Flawfinder: ignore */ - } - } - - if(deviceNode[0] != 0) - { - llinfos << "Disk image attached on /dev/" << deviceNode << llendl; - } - else - { - llinfos << "Disk image device node not found!" << llendl; - throw 0; - } - - // Get an FSRef to the new application on the disk image - FSRef sourceRef; - FSRef mountRef; - snprintf(temp, sizeof(temp), "%s/mnt", tempDir); - - llinfos << "Disk image mount point is: " << temp << llendl; - - err = FSPathMakeRef((UInt8 *)temp, &mountRef, NULL); - if(err != noErr) - { - llinfos << "Couldn't make FSRef to disk image mount point." << llendl; - throw 0; - } - - sendProgress(0, 0, CFSTR("Searching for the app bundle...")); - err = findAppBundleOnDiskImage(&mountRef, &sourceRef); - if(err != noErr) - { - llinfos << "Couldn't find application bundle on mounted disk image." << llendl; - throw 0; - } - else - { - llinfos << "found the bundle." << llendl; - } - - sendProgress(0, 0, CFSTR("Preparing to copy files...")); - - FSRef asideRef; - char aside[MAX_PATH]; /* Flawfinder: ignore */ - - // this will hold the name of the destination target - CFStringRef appNameRef; - - if(replacingTarget) - { - // Get the name of the target we're replacing - HFSUniStr255 appNameUniStr; - err = FSGetCatalogInfo(&targetRef, 0, NULL, &appNameUniStr, NULL, NULL); - if(err != noErr) - throw 0; - appNameRef = FSCreateStringFromHFSUniStr(NULL, &appNameUniStr); - - // Move aside old version (into work directory) - err = FSMoveObject(&targetRef, &tempDirRef, &asideRef); - if(err != noErr) - { - llwarns << "failed to move aside old version (error code " << - err << ")" << llendl; - throw 0; - } - - // Grab the path for later use. - err = FSRefMakePath(&asideRef, (UInt8*)aside, sizeof(aside)); - } - else - { - // Construct the name of the target based on the product name - char appName[MAX_PATH]; /* Flawfinder: ignore */ - snprintf(appName, sizeof(appName), "%s.app", gProductName); - appNameRef = CFStringCreateWithCString(NULL, appName, kCFStringEncodingUTF8); - } - - sendProgress(0, 0, CFSTR("Copying files...")); - - llinfos << "Starting copy..." << llendl; - - // Copy the new version from the disk image to the target location. - err = FSCopyObjectSync( - &sourceRef, - &targetParentRef, - appNameRef, - &targetRef, - kFSFileOperationDefaultOptions); - - // Grab the path for later use. - err = FSRefMakePath(&targetRef, (UInt8*)target, sizeof(target)); - if(err != noErr) - throw 0; - - llinfos << "Copy complete. Target = " << target << llendl; - - if(err != noErr) - { - // Something went wrong during the copy. Attempt to put the old version back and bail. - (void)FSDeleteObject(&targetRef); - if(replacingTarget) - { - (void)FSMoveObject(&asideRef, &targetParentRef, NULL); - } - throw 0; - } - else - { - // The update has succeeded. Clear the cache directory. - - sendProgress(0, 0, CFSTR("Clearing cache...")); - - llinfos << "Clearing cache..." << llendl; - - gDirUtilp->deleteFilesInDir(gDirUtilp->getExpandedFilename(LL_PATH_CACHE,""), "*.*"); - - llinfos << "Clear complete." << llendl; - - } - } - catch(...) - { - if(!gCancelled) - if(gFailure == noErr) - gFailure = -1; - } - - // Failures from here on out are all non-fatal and not reported. - sendProgress(0, 3, CFSTR("Cleaning up...")); - - // Close disk image file if necessary + chdir(temp_dir->string().c_str()); + + snprintf(temp, sizeof(temp), "SecondLife.dmg"); + + downloadFile = LLFile::fopen(temp, "wb"); /* Flawfinder: ignore */ + if(downloadFile == NULL) + { + return false; + } + + bool success = false; + + CURL *curl = curl_easy_init(); + + curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1); + // curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &curl_download_callback); + curl_easy_setopt(curl, CURLOPT_FILE, downloadFile); + curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0); + curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, &curl_progress_callback_func); + curl_easy_setopt(curl, CURLOPT_URL, mUpdateURL); + curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1); + + sendProgress(0, 1, std::string("Downloading...")); + + CURLcode result = curl_easy_perform(curl); + + curl_easy_cleanup(curl); + + if(gCancelled) + { + llinfos << "User cancel, bailing out."<< llendl; + goto close_file; + } + + if(result != CURLE_OK) + { + llinfos << "Error " << result << " while downloading disk image."<< llendl; + goto close_file; + } + + fclose(downloadFile); + downloadFile = NULL; + + success = true; + +close_file: + // Close disk image file if necessary if(downloadFile != NULL) { llinfos << "Closing download file." << llendl; - + fclose(downloadFile); downloadFile = NULL; } - sendProgress(1, 3); + return success; +} + +bool LLMacUpdater::doMount(const std::string& dmgName, char* deviceNode, const boost::filesystem::path& temp_dir) +{ + char temp[PATH_MAX] = ""; /* Flawfinder: ignore */ + + sendProgress(0, 0, std::string("Mounting image...")); + chdir(temp_dir.string().c_str()); + std::string mnt_dir = temp_dir.string() + std::string("/mnt"); + LLFile::mkdir(mnt_dir.c_str(), 0700); + + // NOTE: we could add -private at the end of this command line to keep the image from showing up in the Finder, + // but if our cleanup fails, this makes it much harder for the user to unmount the image. + std::string mountOutput; + boost::format cmdFormat("hdiutil attach %s -mountpoint mnt"); + cmdFormat % dmgName; + FILE* mounter = popen(cmdFormat.str().c_str(), "r"); /* Flawfinder: ignore */ + + if(mounter == NULL) + { + llinfos << "Failed to mount disk image, exiting."<< llendl; + return false; + } + + // We need to scan the output from hdiutil to find the device node it uses to attach the disk image. + // If we don't have this information, we can't detach it later. + while(mounter != NULL) + { + size_t len = fread(temp, 1, sizeof(temp)-1, mounter); + temp[len] = 0; + mountOutput.append(temp); + if(len < sizeof(temp)-1) + { + // End of file or error. + int result = pclose(mounter); + if(result != 0) + { + // NOTE: We used to abort here, but pclose() started returning + // -1, possibly when the size of the DMG passed a certain point + llinfos << "Unexpected result closing pipe: " << result << llendl; + } + mounter = NULL; + } + } + + if(!mountOutput.empty()) + { + const char *s = mountOutput.c_str(); + const char *prefix = "/dev/"; + char *sub = strstr(s, prefix); + + if(sub != NULL) + { + sub += strlen(prefix); /* Flawfinder: ignore */ + sscanf(sub, "%1023s", deviceNode); /* Flawfinder: ignore */ + } + } + + if(deviceNode[0] != 0) + { + llinfos << "Disk image attached on /dev/" << deviceNode << llendl; + } + else + { + llinfos << "Disk image device node not found!" << llendl; + return false; + } + + return true; +} + +bool LLMacUpdater::moveApplication (const boost::filesystem::path& app_dir, + const boost::filesystem::path& temp_dir, + boost::filesystem::path& aside_dir) +{ + try + { + //Grab filename from installdir append to tempdir move set aside_dir to moved path. + std::string install_str = app_dir.parent_path().string(); + std::string temp_str = temp_dir.string(); + std::string app_str = app_dir.filename(); + aside_dir = boost::filesystem::path( boost::filesystem::operator/(temp_dir,app_str) ); + std::cout << "Attempting to move " << app_dir.string() << " to " << aside_dir.string() << std::endl; + + boost::filesystem::rename(app_dir, aside_dir); + } + catch(boost::filesystem::filesystem_error e) + { + llinfos << "Application move failed." << llendl; + return false; + } + return true; +} + +bool LLMacUpdater::doInstall(const boost::filesystem::path& app_dir, + const boost::filesystem::path& temp_dir, + boost::filesystem::path& mount_dir, + bool replacingTarget) +{ + std::string temp_name = temp_dir.string() + std::string("/mnt"); + + llinfos << "Disk image mount point is: " << temp_name << llendl; + + mount_dir = boost::filesystem::path(temp_name.c_str()); + + if (! boost::filesystem::exists ( mount_dir ) ) + { + llinfos << "Couldn't make FSRef to disk image mount point." << llendl; + return false; + } + + sendProgress(0, 0, std::string("Searching for the app bundle...")); + + boost::filesystem::path source_dir; + + if ( !findAppBundleOnDiskImage(mount_dir, source_dir) ) + { + llinfos << "Couldn't find application bundle on mounted disk image." << llendl; + return false; + } + else + { + llinfos << "found the bundle." << llendl; + } + + sendProgress(0, 0, std::string("Preparing to copy files...")); + + // this will hold the name of the destination target + boost::filesystem::path aside_dir; + + if(replacingTarget) + { + + if (! moveApplication (app_dir, temp_dir, aside_dir) ) + { + llwarns << "failed to move aside old version." << llendl; + return false; + } + } + + sendProgress(0, 0, std::string("Copying files...")); + + llinfos << "Starting copy..." << llendl; + // If we were replacingTarget, we've moved the app to a temp directory. + // Otherwise the destination should be empty. + // We have mounted the DMG as a volume so we should be able to just + // move the app from the volume to the destination and everything will just work. + + + // Copy the new version from the disk image to the target location. + + //The installer volume is mounted read-only so we can't move. Instead copy and then unmount. + if (! copyDir(source_dir.string(), app_dir.string()) ) + { + llwarns << "Failed to copy " << source_dir.string() << " to " << app_dir.string() << llendl; + + // Something went wrong during the copy. Attempt to put the old version back and bail. + boost::filesystem::rename(app_dir, aside_dir); + return false; + + } + + // The update has succeeded. Clear the cache directory. + + sendProgress(0, 0, std::string("Clearing cache...")); + + llinfos << "Clearing cache..." << llendl; + + gDirUtilp->deleteFilesInDir(gDirUtilp->getExpandedFilename(LL_PATH_CACHE,""), "*.*"); + + llinfos << "Clear complete." << llendl; + + return true; +} + +void* LLMacUpdater::updatethreadproc(void*) +{ + char tempDir[PATH_MAX] = ""; /* Flawfinder: ignore */ + char temp[PATH_MAX] = ""; /* Flawfinder: ignore */ + // *NOTE: This buffer length is used in a scanf() below. + char deviceNode[1024] = ""; /* Flawfinder: ignore */ + + bool replacingTarget = false; + + boost::filesystem::path install_dir; + boost::filesystem::path app_dir; + boost::filesystem::path temp_dir; + boost::filesystem::path mount_dir; + + // Attempt to get a reference to the Second Life application bundle containing this updater. + // Any failures during this process will cause us to default to updating /Applications/Second Life.app + + try + { + replacingTarget = getViewerDir( app_dir ); + install_dir = app_dir.parent_path(); + + if (!mkTempDir(temp_dir)) + { + throw 0; + } + + //In case the dir doesn't exist, try to create it. If create fails, verify it exists. + if (! boost::filesystem::create_directory(install_dir)) + { + + + if(isFSRefViewerBundle(install_dir.parent_path().string())) + { + // This is the bundle we're looking for. + replacingTarget = true; + } + } + + if ( !verifyDirectory(&install_dir, true) ) + { + // We're so hosed. + llinfos << "Applications directory not found, giving up." << llendl; + throw 0; + } + + + // Skip downloading the file if the dmg was passed on the command line. + std::string dmgName; + if(mDmgFile != NULL) { + //Create a string from the mDmgFile then a dir reference to that. + //change to that directory and begin install. + + boost::filesystem::path dmg_path(*mDmgFile); + + dmgName = dmg_path.string(); + std::string* dmgPath = new std::string(dmg_path.parent_path().string()); + if (!isDirWritable(*dmgPath)) throw 0; + + chdir(dmgPath->c_str()); + } else { + // Continue on to download file. + dmgName = "SecondLife.dmg"; + + + if (!downloadDMG(dmgName, &temp_dir)) + { + throw 0; + } + } + + if (!doMount(dmgName, deviceNode, temp_dir)) + { + throw 0; + } + + if (!doInstall( app_dir, temp_dir, mount_dir, replacingTarget )) + { + throw 0; + } + + } + catch(...) + { + if(!gCancelled) + gFailure = true; + } + + // Failures from here on out are all non-fatal and not reported. + sendProgress(0, 3, std::string("Cleaning up...")); + + setProgress(1, 3); // Unmount image if(deviceNode[0] != 0) { @@ -1223,35 +597,61 @@ void *updatethreadproc(void*) system(temp); /* Flawfinder: ignore */ } - sendProgress(2, 3); + setProgress(2, 3); + std::string *trash_str=getUserTrashFolder(); // Move work directory to the trash if(tempDir[0] != 0) { llinfos << "Moving work directory to the trash." << llendl; - - FSRef trashRef; - OSStatus err = FSMoveObjectToTrashSync(&tempDirRef, &trashRef, 0); - if(err != noErr) { - llwarns << "failed to move files to trash, (error code " << - err << ")" << llendl; - } + + try + { + boost::filesystem::path trash_dir(*trash_str); + boost::filesystem::rename(mount_dir, trash_dir); + } + catch(boost::filesystem::filesystem_error e) + { + llwarns << "Failed to move " << mount_dir.string() << " to " << *trash_str << llendl; + return (NULL); + } } - if(!gCancelled && !gFailure && (target[0] != 0)) - { - llinfos << "Touching application bundle." << llendl; + std::string app_name_str = app_dir.string(); - snprintf(temp, sizeof(temp), "touch '%s'", target); - system(temp); /* Flawfinder: ignore */ + if(!gCancelled && !gFailure && !app_name_str.empty()) + { + //SPATTERS todo is there no better way to do this than system calls? + llinfos << "Touching application bundle." << llendl; + + std::stringstream touch_str; + + touch_str << "touch '" << app_name_str << "'"; + + system(touch_str.str().c_str()); /* Flawfinder: ignore */ llinfos << "Launching updated application." << llendl; + + std::stringstream open_str; + + open_str << "open '" << app_name_str << "'"; - snprintf(temp, sizeof(temp), "open '%s'", target); - system(temp); /* Flawfinder: ignore */ + system(open_str.str().c_str()); /* Flawfinder: ignore */ } sendDone(); - return(NULL); + return (NULL); } + +//static +void* LLMacUpdater::sUpdatethreadproc(void* vptr) +{ + if (!sInstance) + { + llerrs << "LLMacUpdater not instantiated before use. Aborting." << llendl; + return (NULL); + } + return sInstance->updatethreadproc(vptr); +} + diff --git a/indra/mac_updater/mac_updater.h b/indra/mac_updater/mac_updater.h new file mode 100644 index 0000000000..756f46f996 --- /dev/null +++ b/indra/mac_updater/mac_updater.h @@ -0,0 +1,89 @@ +/** + * @file mac_updater.h + * @brief + * + * $LicenseInfo:firstyear=2006&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include +#include +#include + +#ifndef LL_MAC_UPDATER_H +#define LL_MAC_UPDATER_H +extern bool gCancelled; +extern bool gFailure; + +void *updatethreadproc(void*); +std::string* walkParents( unsigned int depth, std::string* childpath ); +std::string* getUserTrashFolder(); + +void setProgress(int cur, int max); +void setProgressText(const std::string& str); +void sendProgress(int cur, int max, std::string str); +void sendDone(); +void sendStopAlert(); + +bool isFSRefViewerBundle(const std::string& targetURL); +bool isDirWritable(const std::string& dir_name); +bool mkTempDir(boost::filesystem::path& temp_dir); +bool copyDir(const std::string& src_dir, const std::string& dest_dir); + +int oldmain(); + +class LLMacUpdater +{ +public: + LLMacUpdater(); + void doUpdate(); + const std::string walkParents( unsigned int depth, const std::string& childpath ); + bool isApplication(const std::string& app_str); + void filterFile(const char* filename); + + bool findAppBundleOnDiskImage(const boost::filesystem::path& dir_path, + boost::filesystem::path& path_found); + + bool verifyDirectory(const boost::filesystem::path* directory, bool isParent=false); + bool getViewerDir(boost::filesystem::path &app_dir); + bool downloadDMG(const std::string& dmgName, boost::filesystem::path* temp_dir); + bool doMount(const std::string& dmgName, char* deviceNode, const boost::filesystem::path& temp_dir); + bool moveApplication (const boost::filesystem::path& app_dir, + const boost::filesystem::path& temp_dir, + boost::filesystem::path& aside_dir); + bool doInstall(const boost::filesystem::path& app_dir, + const boost::filesystem::path& temp_dir, + boost::filesystem::path& mount_dir, + bool replacingTarget); + void* updatethreadproc(void*); + static void* sUpdatethreadproc(void*); + +public: + std::string *mUpdateURL; + std::string *mProductName; + std::string *mBundleID; + std::string *mDmgFile; + std::string *mMarkerPath; + std::string *mApplicationPath; + static LLMacUpdater *sInstance; + +}; +#endif \ No newline at end of file diff --git a/indra/mac_updater/main.m b/indra/mac_updater/main.m new file mode 100644 index 0000000000..aa3776a87d --- /dev/null +++ b/indra/mac_updater/main.m @@ -0,0 +1,34 @@ +/** + * @file main.m + * @brief + * + * $LicenseInfo:firstyear=2006&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#import + +int main(int argc, char *argv[]) +{ + int retVal = NSApplicationMain(argc, (const char **)argv); + + return retVal; +} From f52f10af269b211eea91a2d7fa984fc17ffc5b9b Mon Sep 17 00:00:00 2001 From: Aura Linden Date: Mon, 12 Nov 2012 16:22:04 -0800 Subject: [PATCH 02/32] Removed old nib to make way for the new. --- .../CrashReporter.nib/classes.nib | 8 --- .../CrashReporter.nib/info.nib | 18 ----- .../CrashReporter.nib/objects.xib | 68 ------------------- 3 files changed, 94 deletions(-) delete mode 100644 indra/mac_crash_logger/CrashReporter.nib/classes.nib delete mode 100644 indra/mac_crash_logger/CrashReporter.nib/info.nib delete mode 100644 indra/mac_crash_logger/CrashReporter.nib/objects.xib diff --git a/indra/mac_crash_logger/CrashReporter.nib/classes.nib b/indra/mac_crash_logger/CrashReporter.nib/classes.nib deleted file mode 100644 index c4b887e72b..0000000000 --- a/indra/mac_crash_logger/CrashReporter.nib/classes.nib +++ /dev/null @@ -1,8 +0,0 @@ - - - - - IBVersion - 1 - - diff --git a/indra/mac_crash_logger/CrashReporter.nib/info.nib b/indra/mac_crash_logger/CrashReporter.nib/info.nib deleted file mode 100644 index 06805c0e4f..0000000000 --- a/indra/mac_crash_logger/CrashReporter.nib/info.nib +++ /dev/null @@ -1,18 +0,0 @@ - - - - - IBFramework Version - 629 - IBLastKnownRelativeProjectPath - ../../build-darwin-i386/SecondLife.xcodeproj - IBOldestOS - 5 - IBOpenObjects - - IBSystem Version - 9E17 - targetFramework - IBCarbonFramework - - diff --git a/indra/mac_crash_logger/CrashReporter.nib/objects.xib b/indra/mac_crash_logger/CrashReporter.nib/objects.xib deleted file mode 100644 index 32647391b6..0000000000 --- a/indra/mac_crash_logger/CrashReporter.nib/objects.xib +++ /dev/null @@ -1,68 +0,0 @@ - - - - - - - ok - Send Report - 414 273 434 378 - - - not! - 2 - Don't Send - 414 390 434 487 - - - Second Life appears to have crashed or frozen the last time it ran. This crash reporter collects information about your computer's hardware configuration, operating system, and some Second Life logs, all of which are used for debugging purposes only. In the space below, please briefly describe what you were doing or trying to do just prior to the crash. Thank you for your help! This report is NOT read by Customer Support. If you have billing or other questions, please go to: http://www.secondlife.com/support/ If you don't wish to send Linden Lab a crash report, press Don't Send. - 20 20 231 487 - - - 2 - 3 - 7 - Second Life Crash Logger - - - - - - - text - TRUE - 242 23 391 484 - - - remb - Remember This Choice - 415 20 433 186 - - - 0 0 454 507 - - 257 653 711 1160 - 0 0 768 1024 - - - - - - - - - - - - - - - - CrashReporter - - File's Owner - - - IBCarbonFramework - 194 - From 44d511669ba85a0311dc8d0901f22a1f38c0790b Mon Sep 17 00:00:00 2001 From: Aura Linden Date: Mon, 12 Nov 2012 16:25:09 -0800 Subject: [PATCH 03/32] Pulled cocoa crash reporter changes from old branch. --- indra/mac_crash_logger/CMakeLists.txt | 7 +- indra/mac_crash_logger/CrashReporter.nib | Bin 0 -> 32288 bytes indra/mac_crash_logger/CrashReporter.xib | 3895 +++++++++++++++++ indra/mac_crash_logger/Info.plist | 8 +- indra/mac_crash_logger/llcrashloggermac.cpp | 167 +- indra/mac_crash_logger/llcrashloggermac.h | 1 - .../llcrashloggermacdelegate.h | 50 + .../llcrashloggermacdelegate.mm | 75 + indra/mac_crash_logger/mac_crash_logger.cpp | 18 +- 9 files changed, 4051 insertions(+), 170 deletions(-) create mode 100644 indra/mac_crash_logger/CrashReporter.nib create mode 100644 indra/mac_crash_logger/CrashReporter.xib create mode 100644 indra/mac_crash_logger/llcrashloggermacdelegate.h create mode 100644 indra/mac_crash_logger/llcrashloggermacdelegate.mm diff --git a/indra/mac_crash_logger/CMakeLists.txt b/indra/mac_crash_logger/CMakeLists.txt index 420e836e36..87ee344598 100644 --- a/indra/mac_crash_logger/CMakeLists.txt +++ b/indra/mac_crash_logger/CMakeLists.txt @@ -23,12 +23,14 @@ include_directories( set(mac_crash_logger_SOURCE_FILES mac_crash_logger.cpp llcrashloggermac.cpp - ) + llcrashloggermacdelegate.mm + ) set(mac_crash_logger_HEADER_FILES CMakeLists.txt llcrashloggermac.h + llcrashloggermacdelegate.h ) set_source_files_properties(${mac_crash_logger_HEADER_FILES} @@ -55,9 +57,12 @@ set_target_properties(mac-crash-logger MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_SOURCE_DIR}/Info.plist ) +find_library(COCOA_LIBRARY Cocoa) + target_link_libraries(mac-crash-logger ${LLCRASHLOGGER_LIBRARIES} ${LLVFS_LIBRARIES} + ${COCOA_LIBRARIES} ${LLXML_LIBRARIES} ${LLMESSAGE_LIBRARIES} ${LLVFS_LIBRARIES} diff --git a/indra/mac_crash_logger/CrashReporter.nib b/indra/mac_crash_logger/CrashReporter.nib new file mode 100644 index 0000000000000000000000000000000000000000..a30d8d205cf76f486649b9f9eee9e8f4928a4b97 GIT binary patch literal 32288 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 r(MLbvck_Grk$x|KkU!3! + + + 1070 + 11G63 + 2182 + 1138.51 + 569.00 + + com.apple.InterfaceBuilder.CocoaPlugin + 2182 + + + NSTextField + NSView + NSWindowTemplate + NSMenu + NSMenuItem + NSTextFieldCell + NSButtonCell + IBNSLayoutConstraint + NSButton + NSCustomObject + + + com.apple.InterfaceBuilder.CocoaPlugin + + + PluginDependencyRecalculationVersion + + + + + NSApplication + + + FirstResponder + + + NSApplication + + + AMainMenu + + + + Second Life Crash Logger + + 1048576 + 2147483647 + + NSImage + NSMenuCheckmark + + + NSImage + NSMenuMixedState + + submenuAction: + + Second Life Crash Logger + + + + About Second Life Crash Logger + + 2147483647 + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Preferences… + , + 1048576 + 2147483647 + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Services + + 1048576 + 2147483647 + + + submenuAction: + + Services + + _NSServicesMenu + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Hide Second Life Crash Logger + h + 1048576 + 2147483647 + + + + + + Hide Others + h + 1572864 + 2147483647 + + + + + + Show All + + 1048576 + 2147483647 + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Quit Second Life Crash Logger + q + 1048576 + 2147483647 + + + + + _NSAppleMenu + + + + + File + + 1048576 + 2147483647 + + + submenuAction: + + File + + + + New + n + 1048576 + 2147483647 + + + + + + Open… + o + 1048576 + 2147483647 + + + + + + Open Recent + + 1048576 + 2147483647 + + + submenuAction: + + Open Recent + + + + Clear Menu + + 1048576 + 2147483647 + + + + + _NSRecentDocumentsMenu + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Close + w + 1048576 + 2147483647 + + + + + + Save… + s + 1048576 + 2147483647 + + + + + + Revert to Saved + + 2147483647 + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Page Setup... + P + 1179648 + 2147483647 + + + + + + + Print… + p + 1048576 + 2147483647 + + + + + + + + + Edit + + 1048576 + 2147483647 + + + submenuAction: + + Edit + + + + Undo + z + 1048576 + 2147483647 + + + + + + Redo + Z + 1179648 + 2147483647 + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Cut + x + 1048576 + 2147483647 + + + + + + Copy + c + 1048576 + 2147483647 + + + + + + Paste + v + 1048576 + 2147483647 + + + + + + Paste and Match Style + V + 1572864 + 2147483647 + + + + + + Delete + + 1048576 + 2147483647 + + + + + + Select All + a + 1048576 + 2147483647 + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Find + + 1048576 + 2147483647 + + + submenuAction: + + Find + + + + Find… + f + 1048576 + 2147483647 + + + 1 + + + + Find and Replace… + f + 1572864 + 2147483647 + + + 12 + + + + Find Next + g + 1048576 + 2147483647 + + + 2 + + + + Find Previous + G + 1179648 + 2147483647 + + + 3 + + + + Use Selection for Find + e + 1048576 + 2147483647 + + + 7 + + + + Jump to Selection + j + 1048576 + 2147483647 + + + + + + + + + Spelling and Grammar + + 1048576 + 2147483647 + + + submenuAction: + + Spelling and Grammar + + + + Show Spelling and Grammar + : + 1048576 + 2147483647 + + + + + + Check Document Now + ; + 1048576 + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + Check Spelling While Typing + + 1048576 + 2147483647 + + + + + + Check Grammar With Spelling + + 1048576 + 2147483647 + + + + + + Correct Spelling Automatically + + 2147483647 + + + + + + + + + Substitutions + + 1048576 + 2147483647 + + + submenuAction: + + Substitutions + + + + Show Substitutions + + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + Smart Copy/Paste + f + 1048576 + 2147483647 + + + 1 + + + + Smart Quotes + g + 1048576 + 2147483647 + + + 2 + + + + Smart Dashes + + 2147483647 + + + + + + Smart Links + G + 1179648 + 2147483647 + + + 3 + + + + Text Replacement + + 2147483647 + + + + + + + + + Transformations + + 2147483647 + + + submenuAction: + + Transformations + + + + Make Upper Case + + 2147483647 + + + + + + Make Lower Case + + 2147483647 + + + + + + Capitalize + + 2147483647 + + + + + + + + + Speech + + 1048576 + 2147483647 + + + submenuAction: + + Speech + + + + Start Speaking + + 1048576 + 2147483647 + + + + + + Stop Speaking + + 1048576 + 2147483647 + + + + + + + + + + + + Format + + 2147483647 + + + submenuAction: + + Format + + + + Font + + 2147483647 + + + submenuAction: + + Font + + + + Show Fonts + t + 1048576 + 2147483647 + + + + + + Bold + b + 1048576 + 2147483647 + + + 2 + + + + Italic + i + 1048576 + 2147483647 + + + 1 + + + + Underline + u + 1048576 + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + Bigger + + + 1048576 + 2147483647 + + + 3 + + + + Smaller + - + 1048576 + 2147483647 + + + 4 + + + + YES + YES + + + 2147483647 + + + + + + Kern + + 2147483647 + + + submenuAction: + + Kern + + + + Use Default + + 2147483647 + + + + + + Use None + + 2147483647 + + + + + + Tighten + + 2147483647 + + + + + + Loosen + + 2147483647 + + + + + + + + + Ligature + + 2147483647 + + + submenuAction: + + Ligature + + + + Use Default + + 2147483647 + + + + + + Use None + + 2147483647 + + + + + + Use All + + 2147483647 + + + + + + + + + Baseline + + 2147483647 + + + submenuAction: + + Baseline + + + + Use Default + + 2147483647 + + + + + + Superscript + + 2147483647 + + + + + + Subscript + + 2147483647 + + + + + + Raise + + 2147483647 + + + + + + Lower + + 2147483647 + + + + + + + + + YES + YES + + + 2147483647 + + + + + + Show Colors + C + 1048576 + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + Copy Style + c + 1572864 + 2147483647 + + + + + + Paste Style + v + 1572864 + 2147483647 + + + + + _NSFontMenu + + + + + Text + + 2147483647 + + + submenuAction: + + Text + + + + Align Left + { + 1048576 + 2147483647 + + + + + + Center + | + 1048576 + 2147483647 + + + + + + Justify + + 2147483647 + + + + + + Align Right + } + 1048576 + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + Writing Direction + + 2147483647 + + + submenuAction: + + Writing Direction + + + + YES + Paragraph + + 2147483647 + + + + + + CURlZmF1bHQ + + 2147483647 + + + + + + CUxlZnQgdG8gUmlnaHQ + + 2147483647 + + + + + + CVJpZ2h0IHRvIExlZnQ + + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + YES + Selection + + 2147483647 + + + + + + CURlZmF1bHQ + + 2147483647 + + + + + + CUxlZnQgdG8gUmlnaHQ + + 2147483647 + + + + + + CVJpZ2h0IHRvIExlZnQ + + 2147483647 + + + + + + + + + YES + YES + + + 2147483647 + + + + + + Show Ruler + + 2147483647 + + + + + + Copy Ruler + c + 1310720 + 2147483647 + + + + + + Paste Ruler + v + 1310720 + 2147483647 + + + + + + + + + + + + View + + 1048576 + 2147483647 + + + submenuAction: + + View + + + + Show Toolbar + t + 1572864 + 2147483647 + + + + + + Customize Toolbar… + + 1048576 + 2147483647 + + + + + + + + + Window + + 1048576 + 2147483647 + + + submenuAction: + + Window + + + + Minimize + m + 1048576 + 2147483647 + + + + + + Zoom + + 1048576 + 2147483647 + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Bring All to Front + + 1048576 + 2147483647 + + + + + _NSWindowsMenu + + + + + Help + + 2147483647 + + + submenuAction: + + Help + + + + Second Life Crash Logger Help + ? + 1048576 + 2147483647 + + + + + _NSHelpMenu + + + + _NSMainMenu + + + 15 + 2 + {{335, 390}, {508, 477}} + 1954021376 + Second Life Crash Logger + NSWindow + + + + + 256 + + + + 268 + {{17, 228}, {474, 229}} + + + + _NS:9 + {250, 750} + YES + + 67239424 + 272891904 + + U2Vjb25kIExpZmUgYXBwZWFycyB0byBoYXZlIGNyYXNoZWQgb3IgZnJvemVuIHRoZSBsYXN0IHRpbWUg +aXQgcmFuLgoKVGhpcyBjcmFzaCByZXBvcnRlciBjb2xsZWN0cyBpbmZvcm1hdGlvbiBhYm91dCB5b3Vy +IGNvbXB1dGVyJ3MgaGFyZHdhcmUgY29uZmlndXJhdGlvbiwgb3BlcmF0aW5nIHN5c3RlbSwgYW5kIHNv +bWUgU2Vjb25kIExpZmUgbG9ncywgYWxsIG9mIHdoaWNoIGFyZSB1c2VkIGZvciBkZWJ1Z2dpbmcgcHVy +cG9zZXMgb25seS4KCkluIHRoZSBzcGFjZSBiZWxvdywgcGxlYXNlIGJyaWVmbHkgZGVzY3JpYmUgd2hh +dCB5b3Ugd2VyZSBkb2luZyBvciB0cnlpbmcgdG8gZG8ganVzdCBwcmlvciB0byB0aGUgY3Jhc2guICBU +aGFuayB5b3UgZm9yIHlvdXIgaGVscCEKClRoaXMgcmVwb3J0IGlzIE5PVCByZWFkIGJ5IEN1c3RvbWVy +IFN1cHBvcnQuICBJZiB5b3UgaGF2ZSBiaWxsaW5nIG9yIG90aGVyIHF1ZXN0aW9ucywgcGxlYXNlIGdv +IHRvOiBodHRwOi8vd3d3LnNlY29uZGxpZmUuY29tL3N1cHBvcnQvCgpJZiB5b3UgZG9uJ3Qgd2lzaCB0 +byBzZW5kIExpbmRlbiBMYWIgYSBjcmFzaCByZXBvcnQsIHByZXNzIENhbmNlbC4 + + + LucidaGrande + 13 + 16 + + _NS:9 + + + 6 + System + controlColor + + 3 + MC42NjY2NjY2NjY3AA + + + + 6 + System + controlTextColor + + 3 + MAA + + + + + + + 268 + {{20, 64}, {468, 163}} + + + + _NS:9 + {250, 750} + YES + + -1805517311 + 272891904 + + + LucidaGrande + 9 + 3614 + + _NS:9 + + YES + + 6 + System + textBackgroundColor + + 3 + MQA + + + + 6 + System + textColor + + + + + + + 268 + {{16, 18}, {189, 30}} + + + + _NS:9 + YES + + -2080244224 + 262144 + Remember This Choice + + _NS:9 + + 1211912703 + 2 + + NSImage + NSSwitch + + + NSSwitch + + + + 200 + 25 + + + + + 268 + {{285, 23}, {91, 17}} + + + + _NS:9 + YES + + -2080244224 + 134479872 + Send Report + + _NS:9 + + -2038152961 + 164 + + + 400 + 75 + + + + + 268 + {{388, 23}, {100, 17}} + + + + _NS:9 + YES + + -2080244224 + 134479872 + Don't Send + + _NS:9 + + -2038152961 + 164 + + + 400 + 75 + + + + {508, 477} + + + + + {{0, 0}, {1680, 1028}} + {10000000000000, 10000000000000} + YES + + + LLCrashLoggerMacDelegate + + + + + + + terminate: + + + + 449 + + + + orderFrontStandardAboutPanel: + + + + 142 + + + + delegate + + + + 495 + + + + performMiniaturize: + + + + 37 + + + + arrangeInFront: + + + + 39 + + + + print: + + + + 86 + + + + runPageLayout: + + + + 87 + + + + clearRecentDocuments: + + + + 127 + + + + performClose: + + + + 193 + + + + toggleContinuousSpellChecking: + + + + 222 + + + + undo: + + + + 223 + + + + copy: + + + + 224 + + + + checkSpelling: + + + + 225 + + + + paste: + + + + 226 + + + + stopSpeaking: + + + + 227 + + + + cut: + + + + 228 + + + + showGuessPanel: + + + + 230 + + + + redo: + + + + 231 + + + + selectAll: + + + + 232 + + + + startSpeaking: + + + + 233 + + + + delete: + + + + 235 + + + + performZoom: + + + + 240 + + + + performFindPanelAction: + + + + 241 + + + + centerSelectionInVisibleArea: + + + + 245 + + + + toggleGrammarChecking: + + + + 347 + + + + toggleSmartInsertDelete: + + + + 355 + + + + toggleAutomaticQuoteSubstitution: + + + + 356 + + + + toggleAutomaticLinkDetection: + + + + 357 + + + + saveDocument: + + + + 362 + + + + revertDocumentToSaved: + + + + 364 + + + + runToolbarCustomizationPalette: + + + + 365 + + + + toggleToolbarShown: + + + + 366 + + + + hide: + + + + 367 + + + + hideOtherApplications: + + + + 368 + + + + unhideAllApplications: + + + + 370 + + + + newDocument: + + + + 373 + + + + openDocument: + + + + 374 + + + + raiseBaseline: + + + + 426 + + + + lowerBaseline: + + + + 427 + + + + copyFont: + + + + 428 + + + + subscript: + + + + 429 + + + + superscript: + + + + 430 + + + + tightenKerning: + + + + 431 + + + + underline: + + + + 432 + + + + orderFrontColorPanel: + + + + 433 + + + + useAllLigatures: + + + + 434 + + + + loosenKerning: + + + + 435 + + + + pasteFont: + + + + 436 + + + + unscript: + + + + 437 + + + + useStandardKerning: + + + + 438 + + + + useStandardLigatures: + + + + 439 + + + + turnOffLigatures: + + + + 440 + + + + turnOffKerning: + + + + 441 + + + + toggleAutomaticSpellingCorrection: + + + + 456 + + + + orderFrontSubstitutionsPanel: + + + + 458 + + + + toggleAutomaticDashSubstitution: + + + + 461 + + + + toggleAutomaticTextReplacement: + + + + 463 + + + + uppercaseWord: + + + + 464 + + + + capitalizeWord: + + + + 467 + + + + lowercaseWord: + + + + 468 + + + + pasteAsPlainText: + + + + 486 + + + + performFindPanelAction: + + + + 487 + + + + performFindPanelAction: + + + + 488 + + + + performFindPanelAction: + + + + 489 + + + + showHelp: + + + + 493 + + + + alignCenter: + + + + 518 + + + + pasteRuler: + + + + 519 + + + + toggleRuler: + + + + 520 + + + + alignRight: + + + + 521 + + + + copyRuler: + + + + 522 + + + + alignJustified: + + + + 523 + + + + alignLeft: + + + + 524 + + + + makeBaseWritingDirectionNatural: + + + + 525 + + + + makeBaseWritingDirectionLeftToRight: + + + + 526 + + + + makeBaseWritingDirectionRightToLeft: + + + + 527 + + + + makeTextWritingDirectionNatural: + + + + 528 + + + + makeTextWritingDirectionLeftToRight: + + + + 529 + + + + makeTextWritingDirectionRightToLeft: + + + + 530 + + + + performFindPanelAction: + + + + 535 + + + + window + + + + 532 + + + + remember: + + + + 1176 + + + + send: + + + + 1177 + + + + cancel: + + + + 1178 + + + + crashText + + + + 1179 + + + + rememberCheck + + + + 1187 + + + + + + 0 + + + + + + -2 + + + File's Owner + + + -1 + + + First Responder + + + -3 + + + Application + + + 29 + + + + + + + + + + + + + + 19 + + + + + + + + 56 + + + + + + + + 217 + + + + + + + + 83 + + + + + + + + 81 + + + + + + + + + + + + + + + + + 75 + + + + + 78 + + + + + 72 + + + + + 82 + + + + + 124 + + + + + + + + 77 + + + + + 73 + + + + + 79 + + + + + 112 + + + + + 74 + + + + + 125 + + + + + + + + 126 + + + + + 205 + + + + + + + + + + + + + + + + + + + + + + 202 + + + + + 198 + + + + + 207 + + + + + 214 + + + + + 199 + + + + + 203 + + + + + 197 + + + + + 206 + + + + + 215 + + + + + 218 + + + + + + + + 216 + + + + + + + + 200 + + + + + + + + + + + + + 219 + + + + + 201 + + + + + 204 + + + + + 220 + + + + + + + + + + + + + 213 + + + + + 210 + + + + + 221 + + + + + 208 + + + + + 209 + + + + + 57 + + + + + + + + + + + + + + + + + + 58 + + + + + 134 + + + + + 150 + + + + + 136 + + + + + 144 + + + + + 129 + + + + + 143 + + + + + 236 + + + + + 131 + + + + + + + + 149 + + + + + 145 + + + + + 130 + + + + + 24 + + + + + + + + + + + 92 + + + + + 5 + + + + + 239 + + + + + 23 + + + + + 295 + + + + + + + + 296 + + + + + + + + + 297 + + + + + 298 + + + + + 211 + + + + + + + + 212 + + + + + + + + + 195 + + + + + 196 + + + + + 346 + + + + + 348 + + + + + + + + 349 + + + + + + + + + + + + + + 350 + + + + + 351 + + + + + 354 + + + + + 371 + + + + + + + + 372 + + + + + + + + 3 + 0 + + 3 + 1 + + 20 + + 1000 + 8 + 29 + 3 + + + + + + + 6 + 0 + + 6 + 1 + + 20 + + 1000 + 8 + 29 + 3 + + + + + 5 + 0 + + 5 + 1 + + 20 + + 1000 + 8 + 29 + 3 + + + + + 6 + 0 + + 6 + 1 + + 20 + + 1000 + 8 + 29 + 3 + + + + + 5 + 0 + + 5 + 1 + + 20 + + 1000 + 8 + 29 + 3 + + + + + 4 + 0 + + 4 + 1 + + 64 + + 1000 + 3 + 9 + 3 + + + + + 6 + 0 + + 6 + 1 + + 20 + + 1000 + 8 + 29 + 3 + + + + + 5 + 0 + + 5 + 1 + + 20 + + 1000 + 8 + 29 + 3 + + + + + 4 + 0 + + 4 + 1 + + 21 + + 1000 + 3 + 9 + 3 + + + + + 6 + 0 + + 6 + 1 + + 132 + + 1000 + 3 + 9 + 3 + + + + + 11 + 0 + + 11 + 1 + + 0.0 + + 1000 + 6 + 24 + 2 + + + + + 10 + 0 + + 10 + 1 + + 0.0 + + 1000 + 6 + 24 + 2 + + + + + + + 375 + + + + + + + + 376 + + + + + + + + + 377 + + + + + + + + 388 + + + + + + + + + + + + + + + + + + + + + + + 389 + + + + + 390 + + + + + 391 + + + + + 392 + + + + + 393 + + + + + 394 + + + + + 395 + + + + + 396 + + + + + 397 + + + + + + + + 398 + + + + + + + + 399 + + + + + + + + 400 + + + + + 401 + + + + + 402 + + + + + 403 + + + + + 404 + + + + + 405 + + + + + + + + + + + + 406 + + + + + 407 + + + + + 408 + + + + + 409 + + + + + 410 + + + + + 411 + + + + + + + + + + 412 + + + + + 413 + + + + + 414 + + + + + 415 + + + + + + + + + + + 416 + + + + + 417 + + + + + 418 + + + + + 419 + + + + + 450 + + + + + + + + 451 + + + + + + + + + + 452 + + + + + 453 + + + + + 454 + + + + + 457 + + + + + 459 + + + + + 460 + + + + + 462 + + + + + 465 + + + + + 466 + + + + + 485 + + + + + 490 + + + + + + + + 491 + + + + + + + + 492 + + + + + 494 + + + + + 496 + + + + + + + + 497 + + + + + + + + + + + + + + + + + 498 + + + + + 499 + + + + + 500 + + + + + 501 + + + + + 502 + + + + + 503 + + + + + + + + 504 + + + + + 505 + + + + + 506 + + + + + 507 + + + + + 508 + + + + + + + + + + + + + + + + 509 + + + + + 510 + + + + + 511 + + + + + 512 + + + + + 513 + + + + + 514 + + + + + 515 + + + + + 516 + + + + + 517 + + + + + 534 + + + + + 536 + + + + + + 8 + 0 + + 0 + 1 + + 229 + + 1000 + 3 + 9 + 1 + + + + + + + 537 + + + + + 593 + + + + + + 8 + 0 + + 0 + 1 + + 163 + + 1000 + 3 + 9 + 1 + + + + + + + 594 + + + + + 727 + + + + + + 7 + 0 + + 0 + 1 + + 183 + + 1000 + 3 + 9 + 1 + + + + + 8 + 0 + + 0 + 1 + + 22 + + 1000 + 3 + 9 + 1 + + + + + + + 728 + + + + + 775 + + + + + + + + 776 + + + + + 780 + + + + + + 7 + 0 + + 0 + 1 + + 100 + + 1000 + 3 + 9 + 1 + + + + + + + 781 + + + + + 884 + + + + + 981 + + + + + 982 + + + + + 1022 + + + + + 1026 + + + + + 979 + + + + + 985 + + + + + 977 + + + + + 1099 + + + + + 1093 + + + + + 1100 + + + + + 1098 + + + + + 1168 + + + + + 1167 + + + + + 1095 + + + + + 1166 + + + + + 1076 + + + + + + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + {{380, 496}, {480, 360}} + + + + + + + + + + + + + + + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + + + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + + + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + + + + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + + + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + + + + + 1187 + + + + + LLCrashLoggerMacDelegate + NSObject + + id + id + id + + + + cancel: + id + + + remember: + id + + + send: + id + + + + NSTextField + NSButton + NSWindow + + + + crashText + NSTextField + + + rememberCheck + NSButton + + + window + NSWindow + + + + IBProjectSource + ./Classes/LLCrashLoggerMacDelegate.h + + + + NSLayoutConstraint + NSObject + + IBProjectSource + ./Classes/NSLayoutConstraint.h + + + + + 0 + IBCocoaFramework + + com.apple.InterfaceBuilder.CocoaPlugin.macosx + + + YES + 3 + + {11, 11} + {10, 3} + {15, 15} + + YES + + diff --git a/indra/mac_crash_logger/Info.plist b/indra/mac_crash_logger/Info.plist index f48293e825..2ebed11c3f 100644 --- a/indra/mac_crash_logger/Info.plist +++ b/indra/mac_crash_logger/Info.plist @@ -1,5 +1,5 @@ - + CFBundleDevelopmentRegion @@ -10,8 +10,6 @@ CFBundleIconFile - CFBundleIdentifier - com.secondlife.indra.crashreporter CFBundleInfoDictionaryVersion 6.0 CFBundlePackageType @@ -22,5 +20,9 @@ ???? CFBundleVersion 1.0.0 + NSMainNibFile + CrashReporter + NSPrincipalClass + NSApplication diff --git a/indra/mac_crash_logger/llcrashloggermac.cpp b/indra/mac_crash_logger/llcrashloggermac.cpp index 8f1c1a2dd0..5d22b60136 100644 --- a/indra/mac_crash_logger/llcrashloggermac.cpp +++ b/indra/mac_crash_logger/llcrashloggermac.cpp @@ -27,7 +27,6 @@ #include "llcrashloggermac.h" -#include #include #include "indra_constants.h" // CRASH_BEHAVIOR_ASK, CRASH_SETTING_NAME @@ -38,102 +37,14 @@ #include "lldir.h" #include "llsdserialize.h" -#define MAX_LOADSTRING 100 -const char* const SETTINGS_FILE_HEADER = "version"; -const S32 SETTINGS_FILE_VERSION = 101; - // Windows Message Handlers -BOOL gFirstDialog = TRUE; // Are we currently handling the Send/Don't Send dialog? +BOOL gFirstDialog = TRUE; LLFILE *gDebugFile = NULL; -WindowRef gWindow = NULL; -EventHandlerRef gEventHandler = NULL; std::string gUserNotes = ""; bool gSendReport = false; bool gRememberChoice = false; -IBNibRef nib = NULL; - -OSStatus dialogHandler(EventHandlerCallRef handler, EventRef event, void *userdata) -{ - OSStatus result = eventNotHandledErr; - OSStatus err; - UInt32 evtClass = GetEventClass(event); - UInt32 evtKind = GetEventKind(event); - if((evtClass == kEventClassCommand) && (evtKind == kEventCommandProcess)) - { - HICommand cmd; - err = GetEventParameter(event, kEventParamDirectObject, typeHICommand, NULL, sizeof(cmd), NULL, &cmd); - - - - if(err == noErr) - { - //Get the value of the checkbox - ControlID id; - ControlRef checkBox = NULL; - id.signature = 'remb'; - id.id = 0; - err = GetControlByID(gWindow, &id, &checkBox); - - if(err == noErr) - { - if(GetControl32BitValue(checkBox) == kControlCheckBoxCheckedValue) - { - gRememberChoice = true; - } - else - { - gRememberChoice = false; - } - } - switch(cmd.commandID) - { - case kHICommandOK: - { - char buffer[65535]; /* Flawfinder: ignore */ - Size size = sizeof(buffer) - 1; - ControlRef textField = NULL; - - id.signature = 'text'; - id.id = 0; - - err = GetControlByID(gWindow, &id, &textField); - if(err == noErr) - { - // Get the user response text - err = GetControlData(textField, kControlNoPart, kControlEditTextTextTag, size, (Ptr)buffer, &size); - } - if(err == noErr) - { - // Make sure the string is terminated. - buffer[size] = 0; - gUserNotes = buffer; - - llinfos << buffer << llendl; - } - - // Send the report. - - QuitAppModalLoopForWindow(gWindow); - gSendReport = true; - result = noErr; - } - break; - - case kHICommandCancel: - QuitAppModalLoopForWindow(gWindow); - result = noErr; - break; - default: - result = eventNotHandledErr; - } - } - } - - return(result); -} - LLCrashLoggerMac::LLCrashLoggerMac(void) { @@ -146,73 +57,16 @@ LLCrashLoggerMac::~LLCrashLoggerMac(void) bool LLCrashLoggerMac::init(void) { bool ok = LLCrashLogger::init(); - if(!ok) return false; - if(mCrashBehavior != CRASH_BEHAVIOR_ASK) return true; - - // Real UI... - OSStatus err; - - err = CreateNibReference(CFSTR("CrashReporter"), &nib); - - if(err == noErr) - { - err = CreateWindowFromNib(nib, CFSTR("CrashReporter"), &gWindow); - } - - if(err == noErr) - { - // Set focus to the edit text area - ControlRef textField = NULL; - ControlID id; - - id.signature = 'text'; - id.id = 0; - - // Don't set err if any of this fails, since it's non-critical. - if(GetControlByID(gWindow, &id, &textField) == noErr) - { - SetKeyboardFocus(gWindow, textField, kControlFocusNextPart); - } - } - - if(err == noErr) - { - ShowWindow(gWindow); - } - - if(err == noErr) - { - // Set up an event handler for the window. - EventTypeSpec handlerEvents[] = - { - { kEventClassCommand, kEventCommandProcess } - }; - - InstallWindowEventHandler( - gWindow, - NewEventHandlerUPP(dialogHandler), - GetEventTypeCount (handlerEvents), - handlerEvents, - 0, - &gEventHandler); - } - return true; + return ok; } void LLCrashLoggerMac::gatherPlatformSpecificFiles() { - updateApplication("Gathering hardware information..."); } bool LLCrashLoggerMac::mainLoop() { - OSStatus err = noErr; - - if(err == noErr && mCrashBehavior == CRASH_BEHAVIOR_ASK) - { - RunAppModalLoopForWindow(gWindow); - } - else if (mCrashBehavior == CRASH_BEHAVIOR_ALWAYS_SEND) + if (mCrashBehavior == CRASH_BEHAVIOR_ALWAYS_SEND) { gSendReport = true; } @@ -229,24 +83,9 @@ bool LLCrashLoggerMac::mainLoop() sendCrashLogs(); } - if(gWindow != NULL) - { - DisposeWindow(gWindow); - } - - if(nib != NULL) - { - DisposeNibReference(nib); - } - return true; } -void LLCrashLoggerMac::updateApplication(const std::string& message) -{ - LLCrashLogger::updateApplication(message); -} - bool LLCrashLoggerMac::cleanup() { commonCleanup(); diff --git a/indra/mac_crash_logger/llcrashloggermac.h b/indra/mac_crash_logger/llcrashloggermac.h index 4b1d235f24..6d8f63ecac 100644 --- a/indra/mac_crash_logger/llcrashloggermac.h +++ b/indra/mac_crash_logger/llcrashloggermac.h @@ -38,7 +38,6 @@ public: ~LLCrashLoggerMac(void); virtual bool init(); virtual bool mainLoop(); - virtual void updateApplication(const std::string& message = LLStringUtil::null); virtual bool cleanup(); virtual void gatherPlatformSpecificFiles(); }; diff --git a/indra/mac_crash_logger/llcrashloggermacdelegate.h b/indra/mac_crash_logger/llcrashloggermacdelegate.h new file mode 100644 index 0000000000..8557b77e7d --- /dev/null +++ b/indra/mac_crash_logger/llcrashloggermacdelegate.h @@ -0,0 +1,50 @@ +/** + * @file llcrashloggermacdelegate.h + * @brief Mac OSX crash logger implementation + * + * $LicenseInfo:firstyear=2003&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +/* +#import + +@interface LLCrashLoggerMacDelegate : NSObject +{ + IBOutlet NSTextField *crashText; + IBOutlet NSButton *rememberCheck; + + NSWindow *_window; + bool mRemember; + +} + +- (void)setWindow:(NSWindow *)newWindow; +- (NSWindow *)window; + +- (IBAction)remember:(id)sender; +- (IBAction)send:(id)sender; +- (IBAction)cancel:(id)sender; + +@property (assign) IBOutlet NSWindow *window; + +@end +*/ \ No newline at end of file diff --git a/indra/mac_crash_logger/llcrashloggermacdelegate.mm b/indra/mac_crash_logger/llcrashloggermacdelegate.mm new file mode 100644 index 0000000000..b2af76a47c --- /dev/null +++ b/indra/mac_crash_logger/llcrashloggermacdelegate.mm @@ -0,0 +1,75 @@ +/** + * @file llcrashloggermacdelegate.mm + * @brief Mac OSX crash logger implementation + * + * $LicenseInfo:firstyear=2003&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + + +/* +#import "llcrashloggermacdelegate.h" +#include + +extern std::string gUserNotes; +extern bool gSendReport; +extern bool gRememberChoice; + +@implementation LLCrashLoggerMacDelegate + +- (void)setWindow:(NSWindow *)window +{ + _window = window; +} + +- (NSWindow *)window +{ + return _window; +} + +- (void)dealloc +{ + [super dealloc]; +} + +std::string* NSToString( NSString *ns_str ) +{ + return ( new std::string([ns_str UTF8String]) ); +} + +- (IBAction)remember:(id)sender +{ + gRememberChoice = [rememberCheck state]; +} + +- (IBAction)send:(id)sender +{ + std::string* user_input = NSToString([crashText stringValue]); + gUserNotes = *user_input; + gSendReport = true; +} + +- (IBAction)cancel:(id)sender +{ + [ _window close]; +} +@end +*/ \ No newline at end of file diff --git a/indra/mac_crash_logger/mac_crash_logger.cpp b/indra/mac_crash_logger/mac_crash_logger.cpp index 6571b35241..4d0a7af27f 100644 --- a/indra/mac_crash_logger/mac_crash_logger.cpp +++ b/indra/mac_crash_logger/mac_crash_logger.cpp @@ -26,9 +26,18 @@ #include "linden_common.h" #include "llcrashloggermac.h" +#include "indra_constants.h" +#include +#include + + int main(int argc, char **argv) { + std::ofstream outputFile; + outputFile.open("/tmp/aura.txt"); + outputFile << "TEstiNG" << std::endl; + llinfos << "SPATTERS ASDFSDFSDF" << llendl; llinfos << "Starting crash reporter." << llendl; LLCrashLoggerMac app; @@ -39,9 +48,16 @@ int main(int argc, char **argv) llwarns << "Unable to initialize application." << llendl; return 1; } - + if (app.getCrashBehavior() != CRASH_BEHAVIOR_ALWAYS_SEND) + { + +// return NSApplicationMain(argc, (const char **)argv); + } app.mainLoop(); app.cleanup(); llinfos << "Crash reporter finished normally." << llendl; + + outputFile.close(); + return 0; } From eca619985206462d39dc9ae665857e97948562da Mon Sep 17 00:00:00 2001 From: Aura Linden Date: Mon, 12 Nov 2012 18:06:32 -0800 Subject: [PATCH 04/32] Ported slplugin and some other missing components for cocoa. --- indra/llplugin/slplugin/CMakeLists.txt | 3 +- indra/llplugin/slplugin/slplugin-objc.h | 22 +- indra/llplugin/slplugin/slplugin-objc.mm | 101 +++++++- indra/llplugin/slplugin/slplugin.cpp | 131 ++-------- indra/llvfs/CMakeLists.txt | 6 +- indra/llvfs/lldir.h | 6 +- indra/llvfs/lldir_linux.cpp | 2 +- indra/llvfs/lldir_linux.h | 2 +- indra/llvfs/lldir_mac.cpp | 237 ++++++------------ indra/llvfs/lldir_mac.h | 10 +- indra/llvfs/lldir_solaris.cpp | 2 +- indra/llvfs/lldir_solaris.h | 2 +- indra/llvfs/lldir_win32.cpp | 2 +- indra/llvfs/lldir_win32.h | 2 +- indra/newview/tests/lldir_stub.cpp | 2 +- .../updater/tests/llupdaterservice_test.cpp | 2 +- 16 files changed, 226 insertions(+), 306 deletions(-) diff --git a/indra/llplugin/slplugin/CMakeLists.txt b/indra/llplugin/slplugin/CMakeLists.txt index 3fc54573a7..8183467dc5 100644 --- a/indra/llplugin/slplugin/CMakeLists.txt +++ b/indra/llplugin/slplugin/CMakeLists.txt @@ -15,7 +15,6 @@ include_directories( if (DARWIN) include(CMakeFindFrameworks) - find_library(CARBON_LIBRARY Carbon) find_library(COCOA_LIBRARY Cocoa) endif (DARWIN) @@ -68,7 +67,7 @@ add_dependencies(SLPlugin if (DARWIN) # Mac version needs to link against Carbon - target_link_libraries(SLPlugin ${CARBON_LIBRARY} ${COCOA_LIBRARY}) + target_link_libraries(SLPlugin ${COCOA_LIBRARY}) # Make sure the app bundle has a Resources directory (it will get populated by viewer-manifest.py later) add_custom_command( TARGET SLPlugin POST_BUILD diff --git a/indra/llplugin/slplugin/slplugin-objc.h b/indra/llplugin/slplugin/slplugin-objc.h index 602d848f7e..9a8e81873f 100644 --- a/indra/llplugin/slplugin/slplugin-objc.h +++ b/indra/llplugin/slplugin/slplugin-objc.h @@ -28,8 +28,24 @@ * @endcond */ +//Protos for ObjectiveC classes (cannot import cocoa here due to BOOL conflict) +class NSWindow; /* Defined in slplugin-objc.mm: */ -void setupCocoa(); -void createAutoReleasePool(); -void deleteAutoReleasePool(); + +class LLCocoaPlugin +{ +public: + LLCocoaPlugin(); + void setupCocoa(); + void createAutoReleasePool(); + void deleteAutoReleasePool(); + void setupGroup(); + void updateWindows(); + void processEvents(); +public: + //EventTargetRef mEventTarget; + NSWindow* mFrontWindow; + NSWindow* mPluginWindow; + int mHackState; +}; \ No newline at end of file diff --git a/indra/llplugin/slplugin/slplugin-objc.mm b/indra/llplugin/slplugin/slplugin-objc.mm index 646416b9d2..a434739350 100644 --- a/indra/llplugin/slplugin/slplugin-objc.mm +++ b/indra/llplugin/slplugin/slplugin-objc.mm @@ -30,11 +30,13 @@ #include +#import #include "slplugin-objc.h" +//Note: NSApp is a global defined by cocoa which is an id to the application. -void setupCocoa() +void LLCocoaPlugin::setupCocoa() { static bool inited = false; @@ -56,6 +58,8 @@ void setupCocoa() // Must first call [[[NSWindow alloc] init] release] to get the NSWindow machinery set up so that NSCursor can use a window to cache the cursor image [[[NSWindow alloc] init] release]; + mPluginWindow = [NSApp mainWindow]; + deleteAutoReleasePool(); inited = true; @@ -64,7 +68,7 @@ void setupCocoa() static NSAutoreleasePool *sPool = NULL; -void createAutoReleasePool() +void LLCocoaPlugin::createAutoReleasePool() { if(!sPool) { @@ -72,7 +76,7 @@ void createAutoReleasePool() } } -void deleteAutoReleasePool() +void LLCocoaPlugin::deleteAutoReleasePool() { if(sPool) { @@ -80,3 +84,94 @@ void deleteAutoReleasePool() sPool = NULL; } } + +LLCocoaPlugin::LLCocoaPlugin():mHackState(0) +{ + NSArray* window_list = [NSApp orderedWindows]; + mFrontWindow = [window_list objectAtIndex:0]; +} + +void LLCocoaPlugin::processEvents() +{ + // Some plugins (webkit at least) will want an event loop. This qualifies. + NSEvent * event; + event = [NSApp nextEventMatchingMask:NSAnyEventMask untilDate:[NSDate distantPast] inMode:NSDefaultRunLoopMode dequeue:YES]; + [NSApp sendEvent: event]; +} + + +//Turns out the window ordering stuff never gets hit with any of the current plugins. +//Leaving the following code here 'just in case' for the time being. + +void LLCocoaPlugin::setupGroup() +{ + // CreateWindowGroup(kWindowGroupAttrFixedLevel, &layer_group); + // if(layer_group) + // { + // // Start out with a window layer that's way out in front (fixes the problem with the menubar not getting hidden on first switch to fullscreen youtube) + // SetWindowGroupName(layer_group, CFSTR("SLPlugin Layer")); + // SetWindowGroupLevel(layer_group, kCGOverlayWindowLevel); + // } + +} + +void LLCocoaPlugin::updateWindows() //SPATTERS give this a better name. +{ +// NSArray* window_list = [NSApp orderedWindows]; +// NSWindow* current_window = [window_list objectAtIndex:0]; +// NSWindow* parent_window = [ current_window parentWindow ]; +// bool this_is_front_process = false; +// bool parent_is_front_process = false; +// +// +// // Check for a change in this process's frontmost window. +// if ( current_window != mFrontWindow ) +// { +// // and figure out whether this process or its parent are currently frontmost +// if ( current_window == parent_window ) parent_is_front_process = true; +// if ( current_window == mPluginWindow ) this_is_front_process = true; +// +// if (current_window != NULL && mFrontWindow == NULL) +// { +// // Opening the first window +// +// if(mHackState == 0) +// { +// // Next time through the event loop, lower the window group layer +// mHackState = 1; +// } +// +// if(parent_is_front_process) +// { +// // Bring this process's windows to the front. +// [mPluginWindow makeKeyAndOrderFront:NSApp]; +// [mPluginWindow setOrderedIndex:0]; +// } +// +// [NSApp activateIgnoringOtherApps:YES]; +// } +// +// else if (( current_window == NULL) && (mFrontWindow != NULL)) +// { +// // Closing the last window +// +// if(this_is_front_process) +// { +// // Try to bring this process's parent to the front +// [parent_window makeKeyAndOrderFront:NSApp]; +// [parent_window setOrderedIndex:0]; +// } +// } +// else if(mHackState == 1) +// { +//// if(layer_group) +//// { +//// // Set the window group level back to something less extreme +//// SetWindowGroupLevel(layer_group, kCGNormalWindowLevel); +//// } +// mHackState = 2; +// } +// +// mFrontWindow = [window_list objectAtIndex:0]; +// } + } diff --git a/indra/llplugin/slplugin/slplugin.cpp b/indra/llplugin/slplugin/slplugin.cpp index 516a58db88..6c9ba0ae52 100644 --- a/indra/llplugin/slplugin/slplugin.cpp +++ b/indra/llplugin/slplugin/slplugin.cpp @@ -37,8 +37,12 @@ #include "llapr.h" #include "llstring.h" +#include +#include +using namespace std; + + #if LL_DARWIN - #include #include "slplugin-objc.h" #endif @@ -176,6 +180,7 @@ int APIENTRY WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdL int main(int argc, char **argv) #endif { + ll_init_apr(); // Set up llerror logging @@ -216,26 +221,25 @@ int main(int argc, char **argv) // Catch signals that most kinds of crashes will generate, and exit cleanly so the system crash dialog isn't shown. signal(SIGILL, &crash_handler); // illegal instruction -# if LL_DARWIN - signal(SIGEMT, &crash_handler); // emulate instruction executed -# endif // LL_DARWIN signal(SIGFPE, &crash_handler); // floating-point exception signal(SIGBUS, &crash_handler); // bus error signal(SIGSEGV, &crash_handler); // segmentation violation signal(SIGSYS, &crash_handler); // non-existent system call invoked #endif +# if LL_DARWIN + signal(SIGEMT, &crash_handler); // emulate instruction executed -#if LL_DARWIN - setupCocoa(); - createAutoReleasePool(); -#endif + LLCocoaPlugin cocoa_interface; + cocoa_interface.setupCocoa(); + cocoa_interface.createAutoReleasePool(); +#endif //LL_DARWIN LLPluginProcessChild *plugin = new LLPluginProcessChild(); plugin->init(port); #if LL_DARWIN - deleteAutoReleasePool(); + cocoa_interface.deleteAutoReleasePool(); #endif LLTimer timer; @@ -246,114 +250,22 @@ int main(int argc, char **argv) #endif #if LL_DARWIN + // If the plugin opens a new window (such as the Flash plugin's fullscreen player), we may need to bring this plugin process to the foreground. // Use this to track the current frontmost window and bring this process to the front if it changes. - WindowRef front_window = NULL; - WindowGroupRef layer_group = NULL; - int window_hack_state = 0; - CreateWindowGroup(kWindowGroupAttrFixedLevel, &layer_group); - if(layer_group) - { - // Start out with a window layer that's way out in front (fixes the problem with the menubar not getting hidden on first switch to fullscreen youtube) - SetWindowGroupName(layer_group, CFSTR("SLPlugin Layer")); - SetWindowGroupLevel(layer_group, kCGOverlayWindowLevel); - } -#endif - -#if LL_DARWIN - EventTargetRef event_target = GetEventDispatcherTarget(); + // cocoa_interface.mEventTarget = GetEventDispatcherTarget(); #endif while(!plugin->isDone()) { #if LL_DARWIN - createAutoReleasePool(); + cocoa_interface.createAutoReleasePool(); #endif timer.reset(); plugin->idle(); #if LL_DARWIN { - // Some plugins (webkit at least) will want an event loop. This qualifies. - EventRef event; - if(ReceiveNextEvent(0, 0, kEventDurationNoWait, true, &event) == noErr) - { - SendEventToEventTarget (event, event_target); - ReleaseEvent(event); - } - - // Check for a change in this process's frontmost window. - if(GetFrontWindowOfClass(kAllWindowClasses, true) != front_window) - { - ProcessSerialNumber self = { 0, kCurrentProcess }; - ProcessSerialNumber parent = { 0, kNoProcess }; - ProcessSerialNumber front = { 0, kNoProcess }; - Boolean this_is_front_process = false; - Boolean parent_is_front_process = false; - { - // Get this process's parent - ProcessInfoRec info; - info.processInfoLength = sizeof(ProcessInfoRec); - info.processName = NULL; - info.processAppSpec = NULL; - if(GetProcessInformation( &self, &info ) == noErr) - { - parent = info.processLauncher; - } - - // and figure out whether this process or its parent are currently frontmost - if(GetFrontProcess(&front) == noErr) - { - (void) SameProcess(&self, &front, &this_is_front_process); - (void) SameProcess(&parent, &front, &parent_is_front_process); - } - } - - if((GetFrontWindowOfClass(kAllWindowClasses, true) != NULL) && (front_window == NULL)) - { - // Opening the first window - - if(window_hack_state == 0) - { - // Next time through the event loop, lower the window group layer - window_hack_state = 1; - } - - if(layer_group) - { - SetWindowGroup(GetFrontWindowOfClass(kAllWindowClasses, true), layer_group); - } - - if(parent_is_front_process) - { - // Bring this process's windows to the front. - (void) SetFrontProcess( &self ); - } - - ActivateWindow(GetFrontWindowOfClass(kAllWindowClasses, true), true); - } - else if((GetFrontWindowOfClass(kAllWindowClasses, true) == NULL) && (front_window != NULL)) - { - // Closing the last window - - if(this_is_front_process) - { - // Try to bring this process's parent to the front - (void) SetFrontProcess(&parent); - } - } - else if(window_hack_state == 1) - { - if(layer_group) - { - // Set the window group level back to something less extreme - SetWindowGroupLevel(layer_group, kCGNormalWindowLevel); - } - window_hack_state = 2; - } - - front_window = GetFrontWindowOfClass(kAllWindowClasses, true); - - } - } + cocoa_interface.processEvents(); + } #endif F64 elapsed = timer.getElapsedTimeF64(); F64 remaining = plugin->getSleepTime() - elapsed; @@ -377,7 +289,8 @@ int main(int argc, char **argv) // LL_INFOS("slplugin") << "slept for "<< timer.getElapsedTimeF64() * 1000.0f << " ms" << LL_ENDL; } - + + #if LL_WINDOWS // More agressive checking of interfering exception handlers. // Doesn't appear to be required so far - even for plugins @@ -387,14 +300,14 @@ int main(int argc, char **argv) #endif #if LL_DARWIN - deleteAutoReleasePool(); + cocoa_interface.deleteAutoReleasePool(); #endif } - delete plugin; ll_cleanup_apr(); + return 0; } diff --git a/indra/llvfs/CMakeLists.txt b/indra/llvfs/CMakeLists.txt index a819d12861..3c68b279f7 100644 --- a/indra/llvfs/CMakeLists.txt +++ b/indra/llvfs/CMakeLists.txt @@ -36,6 +36,8 @@ set(llvfs_HEADER_FILES if (DARWIN) LIST(APPEND llvfs_SOURCE_FILES lldir_mac.cpp) LIST(APPEND llvfs_HEADER_FILES lldir_mac.h) + LIST(APPEND llvfs_SOURCE_FILES llvfs_objc.mm) + LIST(APPEND llvfs_HEADER_FILES llvfs_objc.h) endif (DARWIN) if (LINUX) @@ -73,8 +75,8 @@ target_link_libraries(llvfs if (DARWIN) include(CMakeFindFrameworks) - find_library(CARBON_LIBRARY Carbon) - target_link_libraries(llvfs ${CARBON_LIBRARY}) + find_library(COCOA_LIBRARY Cocoa) + target_link_libraries(llvfs ${COCOA_LIBRARY}) endif (DARWIN) diff --git a/indra/llvfs/lldir.h b/indra/llvfs/lldir.h index 5ee8bdb542..35b2654ae7 100644 --- a/indra/llvfs/lldir.h +++ b/indra/llvfs/lldir.h @@ -1,4 +1,4 @@ -/** +/** * @file lldir.h * @brief Definition of directory utilities class * @@ -73,10 +73,8 @@ class LLDir virtual S32 deleteFilesInDir(const std::string &dirname, const std::string &mask); // pure virtual functions - virtual U32 countFilesInDir(const std::string &dirname, const std::string &mask) = 0; - virtual std::string getCurPath() = 0; - virtual BOOL fileExists(const std::string &filename) const = 0; + virtual bool fileExists(const std::string &filename) const = 0; const std::string findFile(const std::string& filename, const std::vector filenames) const; const std::string findFile(const std::string& filename, const std::string& searchPath1 = "", const std::string& searchPath2 = "", const std::string& searchPath3 = "") const; diff --git a/indra/llvfs/lldir_linux.cpp b/indra/llvfs/lldir_linux.cpp index 407f3b93fb..4edd078640 100644 --- a/indra/llvfs/lldir_linux.cpp +++ b/indra/llvfs/lldir_linux.cpp @@ -254,7 +254,7 @@ std::string LLDir_Linux::getCurPath() } -BOOL LLDir_Linux::fileExists(const std::string &filename) const +bool LLDir_Linux::fileExists(const std::string &filename) const { struct stat stat_data; // Check the age of the file diff --git a/indra/llvfs/lldir_linux.h b/indra/llvfs/lldir_linux.h index 7603239867..e83a020ba4 100644 --- a/indra/llvfs/lldir_linux.h +++ b/indra/llvfs/lldir_linux.h @@ -47,7 +47,7 @@ public: virtual std::string getCurPath(); virtual U32 countFilesInDir(const std::string &dirname, const std::string &mask); - /*virtual*/ BOOL fileExists(const std::string &filename) const; + /*virtual*/ bool fileExists(const std::string &filename) const; /*virtual*/ std::string getLLPluginLauncher(); /*virtual*/ std::string getLLPluginFilename(std::string base_name); diff --git a/indra/llvfs/lldir_mac.cpp b/indra/llvfs/lldir_mac.cpp index 489bc3e4a7..75b3d56ebc 100644 --- a/indra/llvfs/lldir_mac.cpp +++ b/indra/llvfs/lldir_mac.cpp @@ -22,7 +22,7 @@ * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ - */ + */ #if LL_DARWIN @@ -35,73 +35,27 @@ #include #include #include - -#include +#include +#include "llvfs_objc.h" // -------------------------------------------------------------------------------- -static OSStatus CFCreateDirectory(FSRef *parentRef, CFStringRef name, FSRef *newRef) +static bool CreateDirectory(const std::string &parent, + const std::string &child, + std::string *fullname) { - OSStatus result = noErr; - HFSUniStr255 uniStr; - - uniStr.length = CFStringGetLength(name); - CFStringGetCharacters(name, CFRangeMake(0, uniStr.length), uniStr.unicode); - result = FSMakeFSRefUnicode(parentRef, uniStr.length, uniStr.unicode, kTextEncodingMacRoman, newRef); - if (result != noErr) - { - result = FSCreateDirectoryUnicode(parentRef, uniStr.length, uniStr.unicode, 0, NULL, newRef, NULL, NULL); - } - - return result; -} - -// -------------------------------------------------------------------------------- - -static void CFStringRefToLLString(CFStringRef stringRef, std::string &llString, bool releaseWhenDone) -{ - if (stringRef) - { - long stringSize = CFStringGetLength(stringRef) + 1; - long bufferSize = CFStringGetMaximumSizeForEncoding(stringSize,kCFStringEncodingUTF8); - char* buffer = new char[bufferSize]; - memset(buffer, 0, bufferSize); - if (CFStringGetCString(stringRef, buffer, bufferSize, kCFStringEncodingUTF8)) - llString = buffer; - delete[] buffer; - if (releaseWhenDone) - CFRelease(stringRef); - } -} - -// -------------------------------------------------------------------------------- - -static void CFURLRefToLLString(CFURLRef urlRef, std::string &llString, bool releaseWhenDone) -{ - if (urlRef) - { - CFURLRef absoluteURLRef = CFURLCopyAbsoluteURL(urlRef); - if (absoluteURLRef) - { - CFStringRef stringRef = CFURLCopyFileSystemPath(absoluteURLRef, kCFURLPOSIXPathStyle); - CFStringRefToLLString(stringRef, llString, true); - CFRelease(absoluteURLRef); - } - if (releaseWhenDone) - CFRelease(urlRef); - } -} - -// -------------------------------------------------------------------------------- - -static void FSRefToLLString(FSRef *fsRef, std::string &llString) -{ - OSStatus error = noErr; - char path[MAX_PATH]; - - error = FSRefMakePath(fsRef, (UInt8*) path, sizeof(path)); - if (error == noErr) - llString = path; + + boost::filesystem::path p(parent); + p /= child; + + if (fullname) + *fullname = std::string(p.string()); + + if (! boost::filesystem::create_directory(p)) + { + return (boost::filesystem::is_directory(p)); + } + return true; } // -------------------------------------------------------------------------------- @@ -109,35 +63,26 @@ static void FSRefToLLString(FSRef *fsRef, std::string &llString) LLDir_Mac::LLDir_Mac() { mDirDelimiter = "/"; - mCurrentDirIndex = -1; - mCurrentDirCount = -1; - - CFBundleRef mainBundleRef = NULL; - CFURLRef executableURLRef = NULL; - CFStringRef stringRef = NULL; - OSStatus error = noErr; - FSRef fileRef; - CFStringRef secondLifeString = CFSTR("SecondLife"); - - mainBundleRef = CFBundleGetMainBundle(); - - executableURLRef = CFBundleCopyExecutableURL(mainBundleRef); - - if (executableURLRef != NULL) + + const std::string secondLifeString = "SecondLife"; + + std::string *executablepathstr = getSystemExecutableFolder(); + + //NOTE: LLINFOS/LLERRS will not output to log here. The streams are not initialized. + + if (executablepathstr) { // mExecutablePathAndName - CFURLRefToLLString(executableURLRef, mExecutablePathAndName, false); - - // mExecutableFilename - stringRef = CFURLCopyLastPathComponent(executableURLRef); - CFStringRefToLLString(stringRef, mExecutableFilename, true); - - // mExecutableDir - CFURLRef executableParentURLRef = CFURLCreateCopyDeletingLastPathComponent(NULL, executableURLRef); - CFURLRefToLLString(executableParentURLRef, mExecutableDir, true); + mExecutablePathAndName = *executablepathstr; + + boost::filesystem::path executablepath(*executablepathstr); + + mExecutableFilename = executablepath.filename(); + mExecutableDir = executablepath.parent_path().string(); // mAppRODataDir - + std::string *resourcepath = getSystemResourceFolder(); + mAppRODataDir = *resourcepath; // *NOTE: When running in a dev tree, use the copy of // skins in indra/newview/ rather than in the application bundle. This @@ -146,10 +91,7 @@ LLDir_Mac::LLDir_Mac() // MBW -- This keeps the mac application from finding other things. // If this is really for skins, it should JUST apply to skins. - - CFURLRef resourcesURLRef = CFBundleCopyResourcesDirectoryURL(mainBundleRef); - CFURLRefToLLString(resourcesURLRef, mAppRODataDir, true); - + U32 build_dir_pos = mExecutableDir.rfind("/build-darwin-"); if (build_dir_pos != std::string::npos) { @@ -166,55 +108,50 @@ LLDir_Mac::LLDir_Mac() } // mOSUserDir - error = FSFindFolder(kUserDomain, kApplicationSupportFolderType, true, &fileRef); - if (error == noErr) - { - FSRef newFileRef; - - // Create the directory - error = CFCreateDirectory(&fileRef, secondLifeString, &newFileRef); - if (error == noErr) - { - // Save the full path to the folder - FSRefToLLString(&newFileRef, mOSUserDir); - - // Create our sub-dirs - (void) CFCreateDirectory(&newFileRef, CFSTR("data"), NULL); - //(void) CFCreateDirectory(&newFileRef, CFSTR("cache"), NULL); - (void) CFCreateDirectory(&newFileRef, CFSTR("logs"), NULL); - (void) CFCreateDirectory(&newFileRef, CFSTR("user_settings"), NULL); - (void) CFCreateDirectory(&newFileRef, CFSTR("browser_profile"), NULL); - } - } - + std::string *appdir = getSystemApplicationSupportFolder(); + std::string rootdir; + + //Create root directory + if (CreateDirectory(*appdir, secondLifeString, &rootdir)) + { + + // Save the full path to the folder + mOSUserDir = rootdir; + + // Create our sub-dirs + CreateDirectory(rootdir, std::string("data"), NULL); + CreateDirectory(rootdir, std::string("logs"), NULL); + CreateDirectory(rootdir, std::string("user_settings"), NULL); + CreateDirectory(rootdir, std::string("browser_profile"), NULL); + } + //mOSCacheDir - FSRef cacheDirRef; - error = FSFindFolder(kUserDomain, kCachedDataFolderType, true, &cacheDirRef); - if (error == noErr) + std::string *cachedir = getSystemCacheFolder(); + + if (cachedir) + { - FSRefToLLString(&cacheDirRef, mOSCacheDir); - (void)CFCreateDirectory(&cacheDirRef, CFSTR("SecondLife"),NULL); + mOSCacheDir = *cachedir; + //SPATTERS TODO: This changes from ~/Library/Cache/Secondlife to ~/Library/Cache/com.app.secondlife/Secondlife. Last dir level could go away. + CreateDirectory(mOSCacheDir, secondLifeString, NULL); } // mOSUserAppDir mOSUserAppDir = mOSUserDir; // mTempDir - error = FSFindFolder(kOnAppropriateDisk, kTemporaryFolderType, true, &fileRef); - if (error == noErr) - { - FSRef tempRef; - error = CFCreateDirectory(&fileRef, secondLifeString, &tempRef); - if (error == noErr) - FSRefToLLString(&tempRef, mTempDir); - } + //Aura 120920 boost::filesystem::temp_directory_path() not yet implemented on mac. :( + std::string *tmpdir = getSystemTempFolder(); + if (tmpdir) + { + + CreateDirectory(*tmpdir, secondLifeString, &mTempDir); + if (tmpdir) delete tmpdir; + } mWorkingDir = getCurPath(); mLLPluginDir = mAppRODataDir + mDirDelimiter + "llplugin"; - - CFRelease(executableURLRef); - executableURLRef = NULL; } } @@ -235,52 +172,18 @@ void LLDir_Mac::initAppDirs(const std::string &app_name, mSkinBaseDir = mAppRODataDir + mDirDelimiter + "skins"; } mCAFile = getExpandedFilename(LL_PATH_APP_SETTINGS, "CA.pem"); - - //dumpCurrentDirectories(); -} - -U32 LLDir_Mac::countFilesInDir(const std::string &dirname, const std::string &mask) -{ - U32 file_count = 0; - glob_t g; - - std::string tmp_str; - tmp_str = dirname; - tmp_str += mask; - - if(glob(tmp_str.c_str(), GLOB_NOSORT, NULL, &g) == 0) - { - file_count = g.gl_pathc; - - globfree(&g); - } - - return (file_count); } std::string LLDir_Mac::getCurPath() { - char tmp_str[LL_MAX_PATH]; /* Flawfinder: ignore */ - getcwd(tmp_str, LL_MAX_PATH); - return tmp_str; + return boost::filesystem::path( boost::filesystem::current_path() ).string(); } -BOOL LLDir_Mac::fileExists(const std::string &filename) const +bool LLDir_Mac::fileExists(const std::string &filename) const { - struct stat stat_data; - // Check the age of the file - // Now, we see if the files we've gathered are recent... - int res = stat(filename.c_str(), &stat_data); - if (!res) - { - return TRUE; - } - else - { - return FALSE; - } + return boost::filesystem::exists(filename); } diff --git a/indra/llvfs/lldir_mac.h b/indra/llvfs/lldir_mac.h index d190d70be4..558727ebbc 100644 --- a/indra/llvfs/lldir_mac.h +++ b/indra/llvfs/lldir_mac.h @@ -22,7 +22,7 @@ * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ - */ + */ #if !LL_DARWIN #error This header must not be included when compiling for any target other than Mac OS. Consider including lldir.h instead. @@ -45,16 +45,10 @@ public: const std::string& app_read_only_data_dir); virtual std::string getCurPath(); - virtual U32 countFilesInDir(const std::string &dirname, const std::string &mask); - virtual BOOL fileExists(const std::string &filename) const; + virtual bool fileExists(const std::string &filename) const; /*virtual*/ std::string getLLPluginLauncher(); /*virtual*/ std::string getLLPluginFilename(std::string base_name); - -private: - int mCurrentDirIndex; - int mCurrentDirCount; - std::string mCurrentDir; }; #endif // LL_LLDIR_MAC_H diff --git a/indra/llvfs/lldir_solaris.cpp b/indra/llvfs/lldir_solaris.cpp index 21f8c3acdb..a97d72d539 100644 --- a/indra/llvfs/lldir_solaris.cpp +++ b/indra/llvfs/lldir_solaris.cpp @@ -272,7 +272,7 @@ std::string LLDir_Solaris::getCurPath() } -BOOL LLDir_Solaris::fileExists(const std::string &filename) const +bool LLDir_Solaris::fileExists(const std::string &filename) const { struct stat stat_data; // Check the age of the file diff --git a/indra/llvfs/lldir_solaris.h b/indra/llvfs/lldir_solaris.h index 0b58a45b15..c6dac57e14 100644 --- a/indra/llvfs/lldir_solaris.h +++ b/indra/llvfs/lldir_solaris.h @@ -47,7 +47,7 @@ public: virtual std::string getCurPath(); virtual U32 countFilesInDir(const std::string &dirname, const std::string &mask); - /*virtual*/ BOOL fileExists(const std::string &filename) const; + /*virtual*/ bool fileExists(const std::string &filename) const; private: DIR *mDirp; diff --git a/indra/llvfs/lldir_win32.cpp b/indra/llvfs/lldir_win32.cpp index 7709945123..462d1cce06 100644 --- a/indra/llvfs/lldir_win32.cpp +++ b/indra/llvfs/lldir_win32.cpp @@ -249,7 +249,7 @@ std::string LLDir_Win32::getCurPath() } -BOOL LLDir_Win32::fileExists(const std::string &filename) const +bool LLDir_Win32::fileExists(const std::string &filename) const { llstat stat_data; // Check the age of the file diff --git a/indra/llvfs/lldir_win32.h b/indra/llvfs/lldir_win32.h index 62fb4713ab..450efaf9da 100644 --- a/indra/llvfs/lldir_win32.h +++ b/indra/llvfs/lldir_win32.h @@ -44,7 +44,7 @@ public: /*virtual*/ std::string getCurPath(); /*virtual*/ U32 countFilesInDir(const std::string &dirname, const std::string &mask); - /*virtual*/ BOOL fileExists(const std::string &filename) const; + /*virtual*/ bool fileExists(const std::string &filename) const; /*virtual*/ std::string getLLPluginLauncher(); /*virtual*/ std::string getLLPluginFilename(std::string base_name); diff --git a/indra/newview/tests/lldir_stub.cpp b/indra/newview/tests/lldir_stub.cpp index 18cf4e7419..88f063f009 100644 --- a/indra/newview/tests/lldir_stub.cpp +++ b/indra/newview/tests/lldir_stub.cpp @@ -48,7 +48,7 @@ public: /*virtual*/ U32 countFilesInDir(const std::string &dirname, const std::string &mask) { return 42; } /*virtual*/ BOOL getNextFileInDir(const std::string &dirname, const std::string &mask, std::string &fname, BOOL wrap) { fname = fname + "_NEXT"; return false; } /*virtual*/ void getRandomFileInDir(const std::string &dirname, const std::string &mask, std::string &fname) { fname = "RANDOM_FILE"; } - /*virtual*/ BOOL fileExists(const std::string &filename) const { return false; } + /*virtual*/ bool fileExists(const std::string &filename) const { return false; } }; LLDir_stub gDirUtil; diff --git a/indra/viewer_components/updater/tests/llupdaterservice_test.cpp b/indra/viewer_components/updater/tests/llupdaterservice_test.cpp index 7c016fecf9..f0d3fcbd07 100644 --- a/indra/viewer_components/updater/tests/llupdaterservice_test.cpp +++ b/indra/viewer_components/updater/tests/llupdaterservice_test.cpp @@ -63,7 +63,7 @@ class LLDir_Mock : public LLDir const std::string &mask, std::string &fname) {} std::string getCurPath() { return ""; } - BOOL fileExists(const std::string &filename) const { return false; } + bool fileExists(const std::string &filename) const { return false; } std::string getLLPluginLauncher() { return ""; } std::string getLLPluginFilename(std::string base_name) { return ""; } From acc53a1c226999878d26b0b4bd58ac8df3256c06 Mon Sep 17 00:00:00 2001 From: Aura Linden Date: Tue, 27 Nov 2012 14:27:52 -0800 Subject: [PATCH 05/32] New VFS objects included in every bite! --- indra/llvfs/llvfs_objc.h | 43 ++++++++++++++++++ indra/llvfs/llvfs_objc.mm | 93 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 136 insertions(+) create mode 100644 indra/llvfs/llvfs_objc.h create mode 100644 indra/llvfs/llvfs_objc.mm diff --git a/indra/llvfs/llvfs_objc.h b/indra/llvfs/llvfs_objc.h new file mode 100644 index 0000000000..90101eb2e9 --- /dev/null +++ b/indra/llvfs/llvfs_objc.h @@ -0,0 +1,43 @@ +/** + * @file llvfs_objc.h + * @brief Definition of directory utilities class for Mac OS X + * + * $LicenseInfo:firstyear=2000&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#if !LL_DARWIN +#error This header must not be included when compiling for any target other than Mac OS. Consider including lldir.h instead. +#endif // !LL_DARWIN + +#ifndef LL_LLVFS_OBJC_H +#define LL_LLVFS_OBJC_H + +#include + +std::string* getSystemTempFolder(); +std::string* getSystemCacheFolder(); +std::string* getSystemApplicationSupportFolder(); +std::string* getSystemResourceFolder(); +std::string* getSystemExecutableFolder(); + + +#endif LL_LLVFS_OBJC_H diff --git a/indra/llvfs/llvfs_objc.mm b/indra/llvfs/llvfs_objc.mm new file mode 100644 index 0000000000..4d7cd3a93e --- /dev/null +++ b/indra/llvfs/llvfs_objc.mm @@ -0,0 +1,93 @@ +/** + * @file llvfs_objc.cpp + * @brief Cocoa implementation of directory utilities for Mac OS X + * + * $LicenseInfo:firstyear=2002&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ +#if LL_DARWIN + +//WARNING: This file CANNOT use standard linden includes due to conflicts between definitions of BOOL + +#include "llvfs_objc.h" +#import + +std::string* getSystemTempFolder() +{ + NSString * tempDir = NSTemporaryDirectory(); + if (tempDir == nil) + tempDir = @"/tmp"; + return ( new std::string([tempDir UTF8String]) ); +} + +//findSystemDirectory scoped exclusively to this file. +std::string* findSystemDirectory(NSSearchPathDirectory searchPathDirectory, + NSSearchPathDomainMask domainMask) +{ + std::string *result; + NSString *path = nil; + + // Search for the path + NSArray* paths = NSSearchPathForDirectoriesInDomains(searchPathDirectory, + domainMask, + YES); + if ([paths count]) + { + NSString *bundleName = + [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleIdentifier"]; + path = [[paths objectAtIndex:0] stringByAppendingPathComponent:bundleName]; + + //SPATTERS HACK: Always attempt to create directory, ignore errors. + NSError *error = nil; + + [[NSFileManager defaultManager] createDirectoryAtPath:path withIntermediateDirectories:YES attributes:nil error:&error]; + + + result = new std::string([path UTF8String]); + } + return result; +} + +std::string* getSystemExecutableFolder() +{ + NSString *bundlePath = [[NSBundle mainBundle] executablePath]; + return (new std::string([bundlePath UTF8String])); +} + +std::string* getSystemResourceFolder() +{ + NSString *bundlePath = [[NSBundle mainBundle] resourcePath]; + return (new std::string([bundlePath UTF8String])); +} + +std::string* getSystemCacheFolder() +{ + return findSystemDirectory (NSCachesDirectory, + NSUserDomainMask); +} + +std::string* getSystemApplicationSupportFolder() +{ + return findSystemDirectory (NSApplicationSupportDirectory, + NSUserDomainMask); +} + +#endif // LL_DARWIN From 1149c94c5b5008f6c076ce4b072f54e48c4783ae Mon Sep 17 00:00:00 2001 From: Aura Linden Date: Thu, 29 Nov 2012 23:33:31 -0800 Subject: [PATCH 06/32] Crashlogger only runs when it comes from teamcity so I must checkin debug and wait. What fun. --- indra/llcrashlogger/llcrashlogger.cpp | 2 +- indra/llvfs/lldir.cpp | 3 ++- indra/mac_crash_logger/mac_crash_logger.cpp | 8 -------- 3 files changed, 3 insertions(+), 10 deletions(-) diff --git a/indra/llcrashlogger/llcrashlogger.cpp b/indra/llcrashlogger/llcrashlogger.cpp index d6dcde4b9f..7ecb34eaf6 100644 --- a/indra/llcrashlogger/llcrashlogger.cpp +++ b/indra/llcrashlogger/llcrashlogger.cpp @@ -384,7 +384,7 @@ bool LLCrashLogger::init() LLCurl::initClass(false); // We assume that all the logs we're looking for reside on the current drive - gDirUtilp->initAppDirs("SecondLife"); + gDirUtilp->initAppDirs("com.secondlife.indra.viewer"); LLError::initForApplication(gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "")); diff --git a/indra/llvfs/lldir.cpp b/indra/llvfs/lldir.cpp index 32d081d552..bd5ce4acac 100644 --- a/indra/llvfs/lldir.cpp +++ b/indra/llvfs/lldir.cpp @@ -431,6 +431,7 @@ std::string LLDir::getExpandedFilename(ELLPath location, const std::string& subd llassert(0); } + llinfos << "SPATTERS got " << prefix << " for location " << location << llendl; std::string filename = in_filename; if (!subdir2.empty()) { @@ -471,7 +472,7 @@ std::string LLDir::getExpandedFilename(ELLPath location, const std::string& subd expanded_filename.assign(""); } - //llinfos << "*** EXPANDED FILENAME: <" << expanded_filename << ">" << llendl; + llinfos << "*** EXPANDED FILENAME: <" << expanded_filename << ">" << llendl; return expanded_filename; } diff --git a/indra/mac_crash_logger/mac_crash_logger.cpp b/indra/mac_crash_logger/mac_crash_logger.cpp index 4d0a7af27f..5e6806c08e 100644 --- a/indra/mac_crash_logger/mac_crash_logger.cpp +++ b/indra/mac_crash_logger/mac_crash_logger.cpp @@ -34,12 +34,6 @@ int main(int argc, char **argv) { - std::ofstream outputFile; - outputFile.open("/tmp/aura.txt"); - outputFile << "TEstiNG" << std::endl; - llinfos << "SPATTERS ASDFSDFSDF" << llendl; - llinfos << "Starting crash reporter." << llendl; - LLCrashLoggerMac app; app.parseCommandOptions(argc, argv); @@ -57,7 +51,5 @@ int main(int argc, char **argv) app.cleanup(); llinfos << "Crash reporter finished normally." << llendl; - outputFile.close(); - return 0; } From 9085dc3e84b66e9f3802ebaf23dedb5891c39065 Mon Sep 17 00:00:00 2001 From: Aura Linden Date: Fri, 30 Nov 2012 00:46:02 -0800 Subject: [PATCH 07/32] Removed logging. --- indra/llvfs/lldir.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/indra/llvfs/lldir.cpp b/indra/llvfs/lldir.cpp index bd5ce4acac..32d081d552 100644 --- a/indra/llvfs/lldir.cpp +++ b/indra/llvfs/lldir.cpp @@ -431,7 +431,6 @@ std::string LLDir::getExpandedFilename(ELLPath location, const std::string& subd llassert(0); } - llinfos << "SPATTERS got " << prefix << " for location " << location << llendl; std::string filename = in_filename; if (!subdir2.empty()) { @@ -472,7 +471,7 @@ std::string LLDir::getExpandedFilename(ELLPath location, const std::string& subd expanded_filename.assign(""); } - llinfos << "*** EXPANDED FILENAME: <" << expanded_filename << ">" << llendl; + //llinfos << "*** EXPANDED FILENAME: <" << expanded_filename << ">" << llendl; return expanded_filename; } From e21275f3562950ae5e5acde8e6f4f631d6c7f1b9 Mon Sep 17 00:00:00 2001 From: Aura Linden Date: Thu, 6 Dec 2012 21:00:37 -0800 Subject: [PATCH 08/32] Fixed several minor issues with validation. --- indra/mac_updater/AutoUpdater.nib/classes.nib | 4 -- indra/mac_updater/AutoUpdater.nib/info.nib | 14 ----- indra/mac_updater/AutoUpdater.nib/objects.xib | 56 ------------------- indra/mac_updater/MacUpdaterAppDelegate.mm | 5 +- indra/mac_updater/mac_updater.cpp | 30 +++++----- indra/mac_updater/mac_updater.h | 4 +- 6 files changed, 19 insertions(+), 94 deletions(-) delete mode 100644 indra/mac_updater/AutoUpdater.nib/classes.nib delete mode 100644 indra/mac_updater/AutoUpdater.nib/info.nib delete mode 100644 indra/mac_updater/AutoUpdater.nib/objects.xib diff --git a/indra/mac_updater/AutoUpdater.nib/classes.nib b/indra/mac_updater/AutoUpdater.nib/classes.nib deleted file mode 100644 index ea58db1189..0000000000 --- a/indra/mac_updater/AutoUpdater.nib/classes.nib +++ /dev/null @@ -1,4 +0,0 @@ -{ -IBClasses = (); -IBVersion = 1; -} diff --git a/indra/mac_updater/AutoUpdater.nib/info.nib b/indra/mac_updater/AutoUpdater.nib/info.nib deleted file mode 100644 index a49a92385b..0000000000 --- a/indra/mac_updater/AutoUpdater.nib/info.nib +++ /dev/null @@ -1,14 +0,0 @@ - - - - - IBDocumentLocation - 103 138 356 240 0 0 1280 1002 - IBFramework Version - 362.0 - IBSystem Version - 7D24 - targetFramework - IBCarbonFramework - - diff --git a/indra/mac_updater/AutoUpdater.nib/objects.xib b/indra/mac_updater/AutoUpdater.nib/objects.xib deleted file mode 100644 index 310411b711..0000000000 --- a/indra/mac_updater/AutoUpdater.nib/objects.xib +++ /dev/null @@ -1,56 +0,0 @@ - - - IBCarbonFramework - - NSApplication - - - - 405 222 533 663 - Second Life Updater - - 0 0 128 441 - - - 20 20 44 421 - what - Initializing… - - - 88 351 108 421 - Cancel - not! - 2 - - - 51 19 70 422 - prog - 50 - - - - FALSE - 2 - 3 - 7 - - - - - - - - - - - - - - - File's Owner - - Updater - - - 194 - diff --git a/indra/mac_updater/MacUpdaterAppDelegate.mm b/indra/mac_updater/MacUpdaterAppDelegate.mm index 80206cb508..179946a238 100644 --- a/indra/mac_updater/MacUpdaterAppDelegate.mm +++ b/indra/mac_updater/MacUpdaterAppDelegate.mm @@ -133,8 +133,6 @@ bool mkTempDir(boost::filesystem::path& temp_dir) std::string* temp_str = NSToString(tempDir); *temp_str += std::string("SecondLifeUpdate_XXXXXX"); - std::cout << "tempDir is " << temp_str << std::endl; - char temp[PATH_MAX] = ""; /* Flawfinder: ignore */ strncpy(temp, temp_str->c_str(), temp_str->length()); @@ -224,7 +222,6 @@ std::string* getUserTrashFolder() bool isFSRefViewerBundle(const std::string& targetURL) { bool result = false; - NSString *fullPath = [NSString stringWithCString:targetURL.c_str() encoding:[NSString defaultCStringEncoding]]; NSBundle *targetBundle = [NSBundle bundleWithPath:fullPath]; @@ -233,7 +230,7 @@ bool isFSRefViewerBundle(const std::string& targetURL) encoding:[NSString defaultCStringEncoding]]; result = [targetBundleStr isEqualToString:sourceBundleStr]; - + if(!result) { std::cout << "Target bundle ID mismatch." << std::endl; diff --git a/indra/mac_updater/mac_updater.cpp b/indra/mac_updater/mac_updater.cpp index 379e69e033..47fc16769c 100644 --- a/indra/mac_updater/mac_updater.cpp +++ b/indra/mac_updater/mac_updater.cpp @@ -135,11 +135,11 @@ void LLMacUpdater::doUpdate() } //SPATTERS TODO this should be moved to lldir_mac.cpp -const std::string LLMacUpdater::walkParents( unsigned int depth, const std::string& childpath ) +const std::string LLMacUpdater::walkParents( signed int depth, const std::string& childpath ) { boost::filesystem::path fullpath(childpath.c_str()); - while (depth >= 0 && fullpath.has_parent_path()) + while (depth > 0 && fullpath.has_parent_path()) { fullpath = boost::filesystem::path(fullpath.parent_path()); --depth; @@ -187,10 +187,10 @@ bool LLMacUpdater::isApplication(const std::string& app_str) bool LLMacUpdater::findAppBundleOnDiskImage(const boost::filesystem::path& dir_path, boost::filesystem::path& path_found) { - if ( !exists( dir_path ) ) return false; + if ( !boost::filesystem::exists( dir_path ) ) return false; boost::filesystem::directory_iterator end_itr; - + for ( boost::filesystem::directory_iterator itr( dir_path ); itr != end_itr; ++itr ) @@ -247,11 +247,9 @@ bool LLMacUpdater::getViewerDir(boost::filesystem::path &app_dir) app_dir = boost::filesystem::path(app_dir_str); - std::string app_str(app_dir.string()); - //Check to see that the directory's name ends in .app Lame but it's the best thing we have to go on. //If it's not there, we're going to default to /Applications/VIEWERNAME - if (!isApplication(app_str)) + if (!isApplication(app_dir_str)) { llinfos << "Target search failed, defaulting to /Applications/" << *mProductName << ".app." << llendl; std::string newpath = std::string("/Applications/") + mProductName->c_str(); @@ -505,7 +503,6 @@ void* LLMacUpdater::updatethreadproc(void*) bool replacingTarget = false; - boost::filesystem::path install_dir; boost::filesystem::path app_dir; boost::filesystem::path temp_dir; boost::filesystem::path mount_dir; @@ -516,7 +513,6 @@ void* LLMacUpdater::updatethreadproc(void*) try { replacingTarget = getViewerDir( app_dir ); - install_dir = app_dir.parent_path(); if (!mkTempDir(temp_dir)) { @@ -524,24 +520,27 @@ void* LLMacUpdater::updatethreadproc(void*) } //In case the dir doesn't exist, try to create it. If create fails, verify it exists. - if (! boost::filesystem::create_directory(install_dir)) + if (! boost::filesystem::create_directory(app_dir)) { - if(isFSRefViewerBundle(install_dir.parent_path().string())) + if(isFSRefViewerBundle(app_dir.string())) { // This is the bundle we're looking for. replacingTarget = true; } + else + { + throw 0; + } } - if ( !verifyDirectory(&install_dir, true) ) + if ( !verifyDirectory(&app_dir, true) ) { // We're so hosed. llinfos << "Applications directory not found, giving up." << llendl; throw 0; } - // Skip downloading the file if the dmg was passed on the command line. std::string dmgName; @@ -553,7 +552,10 @@ void* LLMacUpdater::updatethreadproc(void*) dmgName = dmg_path.string(); std::string* dmgPath = new std::string(dmg_path.parent_path().string()); - if (!isDirWritable(*dmgPath)) throw 0; + if ( !boost::filesystem::exists( dmg_path.parent_path() ) ) { + llinfos << "Path " << *dmgPath << " is not writeable. Aborting." << llendl; + throw 0; + } chdir(dmgPath->c_str()); } else { diff --git a/indra/mac_updater/mac_updater.h b/indra/mac_updater/mac_updater.h index 756f46f996..758d2750aa 100644 --- a/indra/mac_updater/mac_updater.h +++ b/indra/mac_updater/mac_updater.h @@ -34,7 +34,7 @@ extern bool gCancelled; extern bool gFailure; void *updatethreadproc(void*); -std::string* walkParents( unsigned int depth, std::string* childpath ); +std::string* walkParents( signed int depth, std::string* childpath ); std::string* getUserTrashFolder(); void setProgress(int cur, int max); @@ -55,7 +55,7 @@ class LLMacUpdater public: LLMacUpdater(); void doUpdate(); - const std::string walkParents( unsigned int depth, const std::string& childpath ); + const std::string walkParents( signed int depth, const std::string& childpath ); bool isApplication(const std::string& app_str); void filterFile(const char* filename); From 2b3bcdbcbb8359220e0026b84b8521197ad0cf50 Mon Sep 17 00:00:00 2001 From: Aura Linden Date: Thu, 6 Dec 2012 21:01:39 -0800 Subject: [PATCH 09/32] Added compiled AutoUpdater.nib made from new AutoUpdater.xib --- indra/mac_updater/AutoUpdater.nib | Bin 0 -> 5251 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100755 indra/mac_updater/AutoUpdater.nib diff --git a/indra/mac_updater/AutoUpdater.nib b/indra/mac_updater/AutoUpdater.nib new file mode 100755 index 0000000000000000000000000000000000000000..03883e2b86c2052210d544c47293202eb0730456 GIT binary patch literal 5251 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 literal 0 HcmV?d00001 From 53ea30af06f94b5462fada7c4bfea3122b50ff95 Mon Sep 17 00:00:00 2001 From: Aura Linden Date: Tue, 11 Dec 2012 06:56:14 -0800 Subject: [PATCH 10/32] Interim debug checkin to test from teamcity --- indra/llcrashlogger/llcrashlogger.cpp | 13 ++++++++++++- indra/llvfs/llvfs_objc.mm | 9 +++++---- indra/mac_crash_logger/llcrashloggermac.cpp | 11 ++++++++++- indra/mac_crash_logger/mac_crash_logger.cpp | 17 +++++++++++++++++ 4 files changed, 44 insertions(+), 6 deletions(-) diff --git a/indra/llcrashlogger/llcrashlogger.cpp b/indra/llcrashlogger/llcrashlogger.cpp index 7ecb34eaf6..008b0e04b5 100644 --- a/indra/llcrashlogger/llcrashlogger.cpp +++ b/indra/llcrashlogger/llcrashlogger.cpp @@ -339,6 +339,10 @@ bool LLCrashLogger::runCrashLogPost(std::string host, LLSD data, std::string msg bool LLCrashLogger::sendCrashLogs() { + std::ofstream wlog; + wlog.open("/Users/samantha/crashlogging2.txt"); + wlog << "SPATTERS sendingCrashLogs.!\n"; + gatherFiles(); LLSD post_data; @@ -350,6 +354,7 @@ bool LLCrashLogger::sendCrashLogs() "SecondLifeCrashReport"); std::string report_file = dump_path + ".log"; + wlog << "SPATTERS looking in dump_path " << dump_path << " report_file " << report_file << "\n"; std::ofstream out_file(report_file.c_str()); LLSDSerialize::toPrettyXML(post_data, out_file); out_file.close(); @@ -359,14 +364,18 @@ bool LLCrashLogger::sendCrashLogs() //*TODO: Translate if(mCrashHost != "") { + wlog << "SPATTERS sending to MAIN host " << mCrashHost << "\n"; sent = runCrashLogPost(mCrashHost, post_data, std::string("Sending to server"), 3, 5); } if(!sent) { + wlog << "SPATTERS sending to MAIN host " << mAltCrashHost << "\n"; sent = runCrashLogPost(mAltCrashHost, post_data, std::string("Sending to alternate server"), 3, 5); } + wlog.close(); + mSentCrashLogs = sent; return true; @@ -384,7 +393,7 @@ bool LLCrashLogger::init() LLCurl::initClass(false); // We assume that all the logs we're looking for reside on the current drive - gDirUtilp->initAppDirs("com.secondlife.indra.viewer"); + gDirUtilp->initAppDirs("SecondLife"); LLError::initForApplication(gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "")); @@ -394,6 +403,7 @@ bool LLCrashLogger::init() // Rename current log file to ".old" std::string old_log_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "crashreport.log.old"); std::string log_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "crashreport.log"); + llinfos << "SPATTERS moving " << log_file << " to " << old_log_file <prime(gAPRPoolp); LLHTTPClient::setPump(*gServicePump); diff --git a/indra/llvfs/llvfs_objc.mm b/indra/llvfs/llvfs_objc.mm index 4d7cd3a93e..61cfad99d6 100644 --- a/indra/llvfs/llvfs_objc.mm +++ b/indra/llvfs/llvfs_objc.mm @@ -51,10 +51,10 @@ std::string* findSystemDirectory(NSSearchPathDirectory searchPathDirectory, YES); if ([paths count]) { - NSString *bundleName = - [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleIdentifier"]; - path = [[paths objectAtIndex:0] stringByAppendingPathComponent:bundleName]; - + //NSString *bundleName = @"SecondLife"; + //[[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleIdentifier"]; + //path = [[paths objectAtIndex:0] stringByAppendingPathComponent:bundleName]; + path = [paths objectAtIndex:0]; //SPATTERS HACK: Always attempt to create directory, ignore errors. NSError *error = nil; @@ -88,6 +88,7 @@ std::string* getSystemApplicationSupportFolder() { return findSystemDirectory (NSApplicationSupportDirectory, NSUserDomainMask); + } #endif // LL_DARWIN diff --git a/indra/mac_crash_logger/llcrashloggermac.cpp b/indra/mac_crash_logger/llcrashloggermac.cpp index 5d22b60136..64064d9cee 100644 --- a/indra/mac_crash_logger/llcrashloggermac.cpp +++ b/indra/mac_crash_logger/llcrashloggermac.cpp @@ -66,22 +66,31 @@ void LLCrashLoggerMac::gatherPlatformSpecificFiles() bool LLCrashLoggerMac::mainLoop() { + std::ofstream wlog; + wlog.open("/Users/samantha/crashlogging1.txt"); + wlog << "SPATTERS mainloop.!\n"; + if (mCrashBehavior == CRASH_BEHAVIOR_ALWAYS_SEND) { + wlog << "sending\n"; gSendReport = true; } if(gRememberChoice) { + wlog << "momento\n"; if(gSendReport) saveCrashBehaviorSetting(CRASH_BEHAVIOR_ALWAYS_SEND); else saveCrashBehaviorSetting(CRASH_BEHAVIOR_NEVER_SEND); } if(gSendReport) { + wlog << "Send report!"; setUserText(gUserNotes); sendCrashLogs(); - } + } + + wlog.close(); return true; } diff --git a/indra/mac_crash_logger/mac_crash_logger.cpp b/indra/mac_crash_logger/mac_crash_logger.cpp index 5e6806c08e..0d4f2855c7 100644 --- a/indra/mac_crash_logger/mac_crash_logger.cpp +++ b/indra/mac_crash_logger/mac_crash_logger.cpp @@ -34,22 +34,39 @@ int main(int argc, char **argv) { + std::ofstream wlog; + wlog.open("/Users/samantha/crashlogging.txt"); + wlog << "SPATTERS starting crash reporter.!\n"; LLCrashLoggerMac app; + wlog << "SPATTERS created app instance.!\n"; + for (int x=0;x Date: Tue, 11 Dec 2012 07:40:26 -0800 Subject: [PATCH 11/32] Crash reporter fixed, debugging removed. --- indra/llcrashlogger/llcrashlogger.cpp | 13 +------------ indra/llvfs/llvfs_objc.mm | 3 --- indra/mac_crash_logger/llcrashloggermac.cpp | 11 +---------- indra/mac_crash_logger/mac_crash_logger.cpp | 17 ----------------- 4 files changed, 2 insertions(+), 42 deletions(-) diff --git a/indra/llcrashlogger/llcrashlogger.cpp b/indra/llcrashlogger/llcrashlogger.cpp index 008b0e04b5..34e25a8a71 100644 --- a/indra/llcrashlogger/llcrashlogger.cpp +++ b/indra/llcrashlogger/llcrashlogger.cpp @@ -339,10 +339,6 @@ bool LLCrashLogger::runCrashLogPost(std::string host, LLSD data, std::string msg bool LLCrashLogger::sendCrashLogs() { - std::ofstream wlog; - wlog.open("/Users/samantha/crashlogging2.txt"); - wlog << "SPATTERS sendingCrashLogs.!\n"; - gatherFiles(); LLSD post_data; @@ -354,7 +350,6 @@ bool LLCrashLogger::sendCrashLogs() "SecondLifeCrashReport"); std::string report_file = dump_path + ".log"; - wlog << "SPATTERS looking in dump_path " << dump_path << " report_file " << report_file << "\n"; std::ofstream out_file(report_file.c_str()); LLSDSerialize::toPrettyXML(post_data, out_file); out_file.close(); @@ -364,18 +359,14 @@ bool LLCrashLogger::sendCrashLogs() //*TODO: Translate if(mCrashHost != "") { - wlog << "SPATTERS sending to MAIN host " << mCrashHost << "\n"; sent = runCrashLogPost(mCrashHost, post_data, std::string("Sending to server"), 3, 5); } if(!sent) { - wlog << "SPATTERS sending to MAIN host " << mAltCrashHost << "\n"; sent = runCrashLogPost(mAltCrashHost, post_data, std::string("Sending to alternate server"), 3, 5); } - - wlog.close(); - + mSentCrashLogs = sent; return true; @@ -403,7 +394,6 @@ bool LLCrashLogger::init() // Rename current log file to ".old" std::string old_log_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "crashreport.log.old"); std::string log_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "crashreport.log"); - llinfos << "SPATTERS moving " << log_file << " to " << old_log_file <prime(gAPRPoolp); LLHTTPClient::setPump(*gServicePump); diff --git a/indra/llvfs/llvfs_objc.mm b/indra/llvfs/llvfs_objc.mm index 61cfad99d6..16cfefda26 100644 --- a/indra/llvfs/llvfs_objc.mm +++ b/indra/llvfs/llvfs_objc.mm @@ -51,9 +51,6 @@ std::string* findSystemDirectory(NSSearchPathDirectory searchPathDirectory, YES); if ([paths count]) { - //NSString *bundleName = @"SecondLife"; - //[[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleIdentifier"]; - //path = [[paths objectAtIndex:0] stringByAppendingPathComponent:bundleName]; path = [paths objectAtIndex:0]; //SPATTERS HACK: Always attempt to create directory, ignore errors. NSError *error = nil; diff --git a/indra/mac_crash_logger/llcrashloggermac.cpp b/indra/mac_crash_logger/llcrashloggermac.cpp index 64064d9cee..c5f660ca6e 100644 --- a/indra/mac_crash_logger/llcrashloggermac.cpp +++ b/indra/mac_crash_logger/llcrashloggermac.cpp @@ -66,32 +66,23 @@ void LLCrashLoggerMac::gatherPlatformSpecificFiles() bool LLCrashLoggerMac::mainLoop() { - std::ofstream wlog; - wlog.open("/Users/samantha/crashlogging1.txt"); - wlog << "SPATTERS mainloop.!\n"; - if (mCrashBehavior == CRASH_BEHAVIOR_ALWAYS_SEND) { - wlog << "sending\n"; gSendReport = true; } if(gRememberChoice) { - wlog << "momento\n"; if(gSendReport) saveCrashBehaviorSetting(CRASH_BEHAVIOR_ALWAYS_SEND); else saveCrashBehaviorSetting(CRASH_BEHAVIOR_NEVER_SEND); } if(gSendReport) { - wlog << "Send report!"; setUserText(gUserNotes); sendCrashLogs(); } - - wlog.close(); - + return true; } diff --git a/indra/mac_crash_logger/mac_crash_logger.cpp b/indra/mac_crash_logger/mac_crash_logger.cpp index 0d4f2855c7..6add74556f 100644 --- a/indra/mac_crash_logger/mac_crash_logger.cpp +++ b/indra/mac_crash_logger/mac_crash_logger.cpp @@ -29,44 +29,27 @@ #include "indra_constants.h" #include -#include - int main(int argc, char **argv) { - std::ofstream wlog; - wlog.open("/Users/samantha/crashlogging.txt"); - wlog << "SPATTERS starting crash reporter.!\n"; LLCrashLoggerMac app; - wlog << "SPATTERS created app instance.!\n"; - for (int x=0;x Date: Thu, 13 Dec 2012 12:24:17 -0800 Subject: [PATCH 12/32] Fixed whitespace issues for merge. --- indra/llplugin/slplugin/slplugin-objc.h | 4 +++- indra/mac_crash_logger/CMakeLists.txt | 6 +++--- indra/mac_crash_logger/llcrashloggermacdelegate.h | 4 +++- indra/mac_updater/CMakeLists.txt | 8 ++++---- indra/mac_updater/MacUpdaterAppDelegate.h | 4 +++- indra/mac_updater/mac_updater.h | 4 +++- 6 files changed, 19 insertions(+), 11 deletions(-) diff --git a/indra/llplugin/slplugin/slplugin-objc.h b/indra/llplugin/slplugin/slplugin-objc.h index 9a8e81873f..f2c2b3239c 100644 --- a/indra/llplugin/slplugin/slplugin-objc.h +++ b/indra/llplugin/slplugin/slplugin-objc.h @@ -48,4 +48,6 @@ public: NSWindow* mFrontWindow; NSWindow* mPluginWindow; int mHackState; -}; \ No newline at end of file +}; + + diff --git a/indra/mac_crash_logger/CMakeLists.txt b/indra/mac_crash_logger/CMakeLists.txt index 87ee344598..3906a3bb8c 100644 --- a/indra/mac_crash_logger/CMakeLists.txt +++ b/indra/mac_crash_logger/CMakeLists.txt @@ -23,14 +23,14 @@ include_directories( set(mac_crash_logger_SOURCE_FILES mac_crash_logger.cpp llcrashloggermac.cpp - llcrashloggermacdelegate.mm - ) + llcrashloggermacdelegate.mm + ) set(mac_crash_logger_HEADER_FILES CMakeLists.txt llcrashloggermac.h - llcrashloggermacdelegate.h + llcrashloggermacdelegate.h ) set_source_files_properties(${mac_crash_logger_HEADER_FILES} diff --git a/indra/mac_crash_logger/llcrashloggermacdelegate.h b/indra/mac_crash_logger/llcrashloggermacdelegate.h index 8557b77e7d..c998a8efe2 100644 --- a/indra/mac_crash_logger/llcrashloggermacdelegate.h +++ b/indra/mac_crash_logger/llcrashloggermacdelegate.h @@ -47,4 +47,6 @@ @property (assign) IBOutlet NSWindow *window; @end -*/ \ No newline at end of file +*/ + + diff --git a/indra/mac_updater/CMakeLists.txt b/indra/mac_updater/CMakeLists.txt index 4f39e941a1..7382e912bf 100644 --- a/indra/mac_updater/CMakeLists.txt +++ b/indra/mac_updater/CMakeLists.txt @@ -19,13 +19,13 @@ include_directories( set(mac_updater_SOURCE_FILES main.m - MacUpdaterAppDelegate.mm - mac_updater.cpp + MacUpdaterAppDelegate.mm + mac_updater.cpp ) set(mac_updater_HEADER_FILES MacUpdaterAppDelegate.h - mac_updater.h + mac_updater.h CMakeLists.txt ) @@ -63,7 +63,7 @@ target_link_libraries(mac-updater ${OPENSSL_LIBRARIES} ${CRYPTO_LIBRARIES} ${COCOA_LIBRARIES} - ${BOOST_FILESYSTEM_LIBRARY} + ${BOOST_FILESYSTEM_LIBRARY} ${IOKIT_LIBRARY} ${CURL_LIBRARIES} ${CARES_LIBRARIES} diff --git a/indra/mac_updater/MacUpdaterAppDelegate.h b/indra/mac_updater/MacUpdaterAppDelegate.h index ba5744b398..c051214bb8 100644 --- a/indra/mac_updater/MacUpdaterAppDelegate.h +++ b/indra/mac_updater/MacUpdaterAppDelegate.h @@ -55,4 +55,6 @@ LLMacUpdater mUpdater; @end -#endif //LL_MAC_UPDATE_DELEGATE_H \ No newline at end of file +#endif //LL_MAC_UPDATE_DELEGATE_H + + diff --git a/indra/mac_updater/mac_updater.h b/indra/mac_updater/mac_updater.h index 758d2750aa..f65b481cb6 100644 --- a/indra/mac_updater/mac_updater.h +++ b/indra/mac_updater/mac_updater.h @@ -86,4 +86,6 @@ public: static LLMacUpdater *sInstance; }; -#endif \ No newline at end of file +#endif + + From e2bd5f7a9d8f5b967954c3e0bc97e662f7149af7 Mon Sep 17 00:00:00 2001 From: Oz Linden Date: Thu, 13 Dec 2012 15:29:01 -0500 Subject: [PATCH 13/32] tag merge of DRTVWR-244 --- .hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags b/.hgtags index 11c544b106..a1df0f9fc4 100755 --- a/.hgtags +++ b/.hgtags @@ -372,3 +372,4 @@ ab0aa2f6ba22b52fed30a2337197f589156edc75 DRTVWR-253 c23d734065ed593b2413385aecd8366d8e0ee96b DRTVWR-257 452ce96d4046dc05a3ecaecc203e2cc8ddd72e76 DRTVWR-259 5cba5f39d0a81d659f24ebc4b5efd025a39e3db1 3.4.3-release +18c5f76ac07937e0b64bb874edba0d60a28cec56 DRTVWR-244 From 3a72577f397a3cd3ebcb2d3e80000716bf0befec Mon Sep 17 00:00:00 2001 From: Aura Linden Date: Thu, 13 Dec 2012 18:27:32 -0800 Subject: [PATCH 14/32] Fixes from Oz's merge. --- indra/llvfs/lldir_mac.cpp | 4 +++- indra/mac_updater/mac_updater.cpp | 4 ++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/indra/llvfs/lldir_mac.cpp b/indra/llvfs/lldir_mac.cpp index 75b3d56ebc..c5041d434c 100644 --- a/indra/llvfs/lldir_mac.cpp +++ b/indra/llvfs/lldir_mac.cpp @@ -77,7 +77,9 @@ LLDir_Mac::LLDir_Mac() boost::filesystem::path executablepath(*executablepathstr); - mExecutableFilename = executablepath.filename(); +# ifndef BOOST_SYSTEM_NO_DEPRECATED +#endif + mExecutableFilename = executablepath.filename().string(); mExecutableDir = executablepath.parent_path().string(); // mAppRODataDir diff --git a/indra/mac_updater/mac_updater.cpp b/indra/mac_updater/mac_updater.cpp index 34d2b07438..fc9565d63d 100644 --- a/indra/mac_updater/mac_updater.cpp +++ b/indra/mac_updater/mac_updater.cpp @@ -197,7 +197,7 @@ bool LLMacUpdater::findAppBundleOnDiskImage(const boost::filesystem::path& dir_p { if ( boost::filesystem::is_directory(itr->status()) ) { - std::string dir_name = itr->string(); + std::string dir_name = itr->path().string(); if ( isApplication(dir_name) ) { if(isFSRefViewerBundle(dir_name)) @@ -399,7 +399,7 @@ bool LLMacUpdater::moveApplication (const boost::filesystem::path& app_dir, //Grab filename from installdir append to tempdir move set aside_dir to moved path. std::string install_str = app_dir.parent_path().string(); std::string temp_str = temp_dir.string(); - std::string app_str = app_dir.filename(); + std::string app_str = app_dir.filename().string(); aside_dir = boost::filesystem::path( boost::filesystem::operator/(temp_dir,app_str) ); std::cout << "Attempting to move " << app_dir.string() << " to " << aside_dir.string() << std::endl; From d3293be2fe5b2bb04310ad1efc3801f724589654 Mon Sep 17 00:00:00 2001 From: Oz Linden Date: Fri, 14 Dec 2012 12:56:58 -0500 Subject: [PATCH 15/32] tag merge of DRTVWR-224 --- .hgtags | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.hgtags b/.hgtags index 740260312a..a016310d16 100755 --- a/.hgtags +++ b/.hgtags @@ -380,3 +380,5 @@ c23d734065ed593b2413385aecd8366d8e0ee96b DRTVWR-257 5cba5f39d0a81d659f24ebc4b5efd025a39e3db1 3.4.3-release 9aa1aa9f1fe13c194695a0b8f0af298296241dc2 DRTVWR-260 18c5f76ac07937e0b64bb874edba0d60a28cec56 DRTVWR-244 +dd23d4da3bcb2ffda58569e759feb7c119982973 DRTVWR-224 +12655fb818f3b0b08a4638d0cda1ad1f01e5f52f DRTVWR-224 From 5c9dd94e197a5db10fdf794ec1632e5586053df8 Mon Sep 17 00:00:00 2001 From: Aura Linden Date: Fri, 14 Dec 2012 21:41:02 +0000 Subject: [PATCH 16/32] BOOL vs bool FIGHT --- indra/llvfs/tests/lldir_test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/indra/llvfs/tests/lldir_test.cpp b/indra/llvfs/tests/lldir_test.cpp index 323f876c12..3cff622a4b 100644 --- a/indra/llvfs/tests/lldir_test.cpp +++ b/indra/llvfs/tests/lldir_test.cpp @@ -134,7 +134,7 @@ struct LLDir_Dummy: public LLDir return 0; } - virtual BOOL fileExists(const std::string& pathname) const + virtual bool fileExists(const std::string& pathname) const { // Record fileExists() calls so we can check whether caching is // working right. Certain LLDir calls should be able to make decisions From c1db961ab9b7aa9c0dd43cadf850b7527b77e95b Mon Sep 17 00:00:00 2001 From: Aura Linden Date: Sun, 16 Dec 2012 17:45:55 -0800 Subject: [PATCH 17/32] Fixed small one-time memory leaks. --- indra/llvfs/llvfs_objc.mm | 23 +++++++++++++++++++--- indra/mac_updater/MacUpdaterAppDelegate.mm | 22 +++++++++++++++++++-- 2 files changed, 40 insertions(+), 5 deletions(-) diff --git a/indra/llvfs/llvfs_objc.mm b/indra/llvfs/llvfs_objc.mm index 16cfefda26..4f9e2f81e9 100644 --- a/indra/llvfs/llvfs_objc.mm +++ b/indra/llvfs/llvfs_objc.mm @@ -32,16 +32,22 @@ std::string* getSystemTempFolder() { + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; NSString * tempDir = NSTemporaryDirectory(); if (tempDir == nil) tempDir = @"/tmp"; - return ( new std::string([tempDir UTF8String]) ); + std::string *result = ( new std::string([tempDir UTF8String]) ); + [pool release]; + + return result; } //findSystemDirectory scoped exclusively to this file. std::string* findSystemDirectory(NSSearchPathDirectory searchPathDirectory, NSSearchPathDomainMask domainMask) { + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + std::string *result; NSString *path = nil; @@ -60,19 +66,30 @@ std::string* findSystemDirectory(NSSearchPathDirectory searchPathDirectory, result = new std::string([path UTF8String]); } + [pool release]; return result; } std::string* getSystemExecutableFolder() { + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + NSString *bundlePath = [[NSBundle mainBundle] executablePath]; - return (new std::string([bundlePath UTF8String])); + std::string *result = (new std::string([bundlePath UTF8String])); + [pool release]; + + return result; } std::string* getSystemResourceFolder() { + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + NSString *bundlePath = [[NSBundle mainBundle] resourcePath]; - return (new std::string([bundlePath UTF8String])); + std::string *result = (new std::string([bundlePath UTF8String])); + [pool release]; + + return result; } std::string* getSystemCacheFolder() diff --git a/indra/mac_updater/MacUpdaterAppDelegate.mm b/indra/mac_updater/MacUpdaterAppDelegate.mm index 3ddf8f9274..b6f95eef7e 100644 --- a/indra/mac_updater/MacUpdaterAppDelegate.mm +++ b/indra/mac_updater/MacUpdaterAppDelegate.mm @@ -126,6 +126,8 @@ void sendProgress(int cur, int max, const std::string str) bool copyDir(const std::string& src_dir, const std::string& dest_dir) { + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + NSString* file = [NSString stringWithCString:src_dir.c_str() encoding:[NSString defaultCStringEncoding]]; NSString* toParent = [NSString stringWithCString:dest_dir.c_str() @@ -137,6 +139,8 @@ bool copyDir(const std::string& src_dir, const std::string& dest_dir) if (!result) { NSLog(@"Error during copy: %@", [error localizedDescription]); } + [pool release]; + return result; } @@ -178,26 +182,38 @@ bool copyDir(const std::string& src_dir, const std::string& dest_dir) bool isDirWritable(const std::string& dir_name) { - + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + NSString *fullPath = [NSString stringWithCString:dir_name.c_str() encoding:[NSString defaultCStringEncoding]]; NSFileManager *fm = [NSFileManager defaultManager]; bool result = [fm isWritableFileAtPath:fullPath]; + [pool release]; return result; } std::string* getUserTrashFolder() { + std::string *result; + + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + NSString *trash_str=[NSHomeDirectory() stringByAppendingPathComponent:@".Trash"]; - return NSToString( trash_str ); + + result = NSToString( trash_str ); + + [pool release]; + return result; } bool isFSRefViewerBundle(const std::string& targetURL) { bool result = false; + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + NSString *fullPath = [NSString stringWithCString:targetURL.c_str() encoding:[NSString defaultCStringEncoding]]; NSBundle *targetBundle = [NSBundle bundleWithPath:fullPath]; @@ -212,6 +228,8 @@ bool isFSRefViewerBundle(const std::string& targetURL) std::cout << "Target bundle ID mismatch." << std::endl; } + [pool release]; + return result; } From 7a6b073dcafc55838f9f1f82bd5f940052ec7690 Mon Sep 17 00:00:00 2001 From: Oz Linden Date: Mon, 17 Dec 2012 10:14:32 -0500 Subject: [PATCH 18/32] tag merge of DRTVWR-244 --- .hgtags | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.hgtags b/.hgtags index 740260312a..41cc6d7b03 100755 --- a/.hgtags +++ b/.hgtags @@ -380,3 +380,5 @@ c23d734065ed593b2413385aecd8366d8e0ee96b DRTVWR-257 5cba5f39d0a81d659f24ebc4b5efd025a39e3db1 3.4.3-release 9aa1aa9f1fe13c194695a0b8f0af298296241dc2 DRTVWR-260 18c5f76ac07937e0b64bb874edba0d60a28cec56 DRTVWR-244 +18c5f76ac07937e0b64bb874edba0d60a28cec56 DRTVWR-244 +84fbaf2d4141bd161731430e760949dc787ca206 DRTVWR-244 From 769336a72ef819b45bfabcb8608f70c9396f58ae Mon Sep 17 00:00:00 2001 From: Oz Linden Date: Mon, 17 Dec 2012 14:46:39 -0500 Subject: [PATCH 19/32] Added tag 3.4.4-beta1 for changeset 083d2d36b5bb --- .hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags b/.hgtags index 8dce366b7a..b1bd7cf117 100755 --- a/.hgtags +++ b/.hgtags @@ -384,3 +384,4 @@ daca610d840625b5bebb966a57cb49581852c417 DRTVWR-265 870e2d79e0063fda87187f17bbc2747766733194 3.4.3-beta3 0a2ca6546b499239afeb66d17b2fadbcdbe36ab1 3.4.3-release 84fbaf2d4141bd161731430e760949dc787ca206 DRTVWR-244 +083d2d36b5bb1c54fc3dd7caac0e7ac381a9cef0 3.4.4-beta1 From a9a21ecffa52ad0e53000c4fdd94569c50022889 Mon Sep 17 00:00:00 2001 From: Aura Linden Date: Tue, 18 Dec 2012 13:30:21 -0800 Subject: [PATCH 20/32] Switched mkTempDir back to using apple standard tempdir behavior instead of /tmp --- indra/mac_updater/MacUpdaterAppDelegate.mm | 23 ++++++++++++++++++++++ indra/mac_updater/mac_updater.cpp | 14 ------------- 2 files changed, 23 insertions(+), 14 deletions(-) diff --git a/indra/mac_updater/MacUpdaterAppDelegate.mm b/indra/mac_updater/MacUpdaterAppDelegate.mm index b6f95eef7e..4457419a94 100644 --- a/indra/mac_updater/MacUpdaterAppDelegate.mm +++ b/indra/mac_updater/MacUpdaterAppDelegate.mm @@ -124,6 +124,29 @@ void sendProgress(int cur, int max, const std::string str) setProgressText(str); } +bool mkTempDir(boost::filesystem::path& temp_dir) +{ + NSString * tempDir = NSTemporaryDirectory(); + if (tempDir == nil) + tempDir = @"/tmp/"; + + std::string* temp_str = NSToString(tempDir); + *temp_str += std::string("SecondLifeUpdate_XXXXXX"); + + std::cout << "tempDir is " << temp_str << std::endl; + + char temp[PATH_MAX] = ""; /* Flawfinder: ignore */ + strncpy(temp, temp_str->c_str(), temp_str->length()); + + if(mkdtemp(temp) == NULL) + { + return false; + } + + temp_dir = boost::filesystem::path(temp); + + return true; +} bool copyDir(const std::string& src_dir, const std::string& dest_dir) { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; diff --git a/indra/mac_updater/mac_updater.cpp b/indra/mac_updater/mac_updater.cpp index fc9565d63d..bc9fec3558 100644 --- a/indra/mac_updater/mac_updater.cpp +++ b/indra/mac_updater/mac_updater.cpp @@ -494,20 +494,6 @@ bool LLMacUpdater::doInstall(const boost::filesystem::path& app_dir, return true; } -bool mkTempDir(boost::filesystem::path& temp_dir) -{ - char temp_str[PATH_MAX] = "/tmp/SecondLifeUpdate_XXXXXX"; - - if(mkdtemp(temp_str) == NULL) - { - return false; - } - - temp_dir = boost::filesystem::path(temp_str); - - return true; -} - void* LLMacUpdater::updatethreadproc(void*) { char tempDir[PATH_MAX] = ""; /* Flawfinder: ignore */ From 0ed83541bff20d5bcefc374d702cf62b85727bba Mon Sep 17 00:00:00 2001 From: Oz Linden Date: Wed, 19 Dec 2012 09:41:59 -0500 Subject: [PATCH 21/32] upgrade boost build to use public build of icu4c --- autobuild.xml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/autobuild.xml b/autobuild.xml index fb0de9feb2..7e6192af6e 100644 --- a/autobuild.xml +++ b/autobuild.xml @@ -186,9 +186,9 @@ archive hash - 610d3c3790b39d44b45ed1e471f7b34d + ac37d0038c91b0672fa31a02731f0eac url - http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-boost/rev/267115/arch/Darwin/installer/boost-1.52.0-darwin-20121117.tar.bz2 + http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-boost/rev/268347/arch/Darwin/installer/boost-1.52.0-darwin-20121218.tar.bz2 name darwin @@ -198,9 +198,9 @@ archive hash - 86b9108ab71bd6551365d1706e2fb178 + 146ed8a8c2ef8ab3f0a6c4f214fc5c22 url - http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-boost/rev/267115/arch/Linux/installer/boost-1.52.0-linux-20121117.tar.bz2 + http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-boost/rev/268347/arch/Linux/installer/boost-1.52.0-linux-20121218.tar.bz2 name linux @@ -210,9 +210,9 @@ archive hash - a3bf306ebd14036a93f7894f898a862c + 3ea60f17d986b7e8a3351298734bdca4 url - http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-boost/rev/267115/arch/CYGWIN/installer/boost-1.52.0-windows-20121117.tar.bz2 + http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-boost/rev/268347/arch/CYGWIN/installer/boost-1.52.0-windows-20121218.tar.bz2 name windows From 1c7f19c8658b869bc0c3ebd06ad9129ef11dbd20 Mon Sep 17 00:00:00 2001 From: Oz Linden Date: Wed, 19 Dec 2012 09:45:28 -0500 Subject: [PATCH 22/32] change to use lindenlab repo for havok source, with new license --- autobuild.xml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/autobuild.xml b/autobuild.xml index 7e6192af6e..017427278e 100644 --- a/autobuild.xml +++ b/autobuild.xml @@ -918,9 +918,9 @@ archive hash - efaf5cb3e861d44518eb03f4c406f03c + e6feee3b452c2f70ce8558e30d6bc10a url - http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/falcon_3p-havok-source/rev/261536/arch/Darwin/installer/havok_source-2012.1-darwin-20120710.tar.bz2 + http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/lindenlab_3p-havok-source/rev/268409/arch/Darwin/installer/havok_source-2012.1-darwin-20121219.tar.bz2 name darwin @@ -930,9 +930,9 @@ archive hash - 50037fff3fd3356a073cdae88348c9ab + 0c0d2058ba48446e274d6595d1d8063e url - http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/falcon_3p-havok-source/rev/261536/arch/Linux/installer/havok_source-2012.1-linux-20120711.tar.bz2 + http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/lindenlab_3p-havok-source/rev/268409/arch/Linux/installer/havok_source-2012.1-linux-20121219.tar.bz2 name linux @@ -942,9 +942,9 @@ archive hash - cd6638f5a03469654615730c16889a60 + 88391b6e08d473506d406ca6f3e88cfb url - http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/falcon_3p-havok-source/rev/261536/arch/CYGWIN/installer/havok_source-2012.1-windows-20120710.tar.bz2 + http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/lindenlab_3p-havok-source/rev/268409/arch/CYGWIN/installer/havok_source-2012.1-windows-20121219.tar.bz2 name windows From 213be712b26119832ccc9f04a17c9013792b5044 Mon Sep 17 00:00:00 2001 From: Oz Linden Date: Wed, 19 Dec 2012 16:52:25 -0500 Subject: [PATCH 23/32] tag merge of DRTVWR-270 --- .hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags b/.hgtags index 740260312a..84457d6f0e 100755 --- a/.hgtags +++ b/.hgtags @@ -380,3 +380,4 @@ c23d734065ed593b2413385aecd8366d8e0ee96b DRTVWR-257 5cba5f39d0a81d659f24ebc4b5efd025a39e3db1 3.4.3-release 9aa1aa9f1fe13c194695a0b8f0af298296241dc2 DRTVWR-260 18c5f76ac07937e0b64bb874edba0d60a28cec56 DRTVWR-244 +b634dec987c16e8c9c938e11e52591d9ead8fa9b DRTVWR-270 From d8ac1c0f2f05e85a9a85547c0529734fc7d52d30 Mon Sep 17 00:00:00 2001 From: Oz Linden Date: Wed, 19 Dec 2012 17:49:16 -0500 Subject: [PATCH 24/32] Added tag 3.4.4-beta2 for changeset cd39255bd233 --- .hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags b/.hgtags index a00dde6543..0be54334a3 100755 --- a/.hgtags +++ b/.hgtags @@ -386,3 +386,4 @@ b418be80903520c492e1173f3afbc4021cad5d07 DRTVWR-255 18c5f76ac07937e0b64bb874edba0d60a28cec56 DRTVWR-244 083d2d36b5bb1c54fc3dd7caac0e7ac381a9cef0 3.4.4-beta1 b634dec987c16e8c9c938e11e52591d9ead8fa9b DRTVWR-270 +cd39255bd23330fd30c04105f2811e941d8524fe 3.4.4-beta2 From 867d00c68781b3a0fa8124f8040cede62e176442 Mon Sep 17 00:00:00 2001 From: Aura Linden Date: Thu, 20 Dec 2012 09:16:16 -0800 Subject: [PATCH 25/32] There goes a month of work --- indra/mac_updater/AutoUpdater.nib | Bin 5251 -> 0 bytes indra/mac_updater/AutoUpdater.xib | 520 --------------------- indra/mac_updater/MacUpdater-Info.plist | 30 -- indra/mac_updater/MacUpdaterAppDelegate.h | 60 --- indra/mac_updater/MacUpdaterAppDelegate.mm | 288 ------------ indra/mac_updater/main.m | 34 -- 6 files changed, 932 deletions(-) delete mode 100755 indra/mac_updater/AutoUpdater.nib delete mode 100644 indra/mac_updater/AutoUpdater.xib delete mode 100644 indra/mac_updater/MacUpdater-Info.plist delete mode 100644 indra/mac_updater/MacUpdaterAppDelegate.h delete mode 100644 indra/mac_updater/MacUpdaterAppDelegate.mm delete mode 100644 indra/mac_updater/main.m diff --git a/indra/mac_updater/AutoUpdater.nib b/indra/mac_updater/AutoUpdater.nib deleted file mode 100755 index 03883e2b86c2052210d544c47293202eb0730456..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5251 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 diff --git a/indra/mac_updater/AutoUpdater.xib b/indra/mac_updater/AutoUpdater.xib deleted file mode 100644 index b29fffba3a..0000000000 --- a/indra/mac_updater/AutoUpdater.xib +++ /dev/null @@ -1,520 +0,0 @@ - - - - 1070 - 11G63 - 2182 - 1138.51 - 569.00 - - com.apple.InterfaceBuilder.CocoaPlugin - 2182 - - - NSTextField - NSView - NSWindowTemplate - NSProgressIndicator - NSCustomObject - IBNSLayoutConstraint - NSButtonCell - NSButton - NSUserDefaultsController - NSTextFieldCell - - - com.apple.InterfaceBuilder.CocoaPlugin - - - PluginDependencyRecalculationVersion - - - - - NSObject - - - FirstResponder - - - NSApplication - - - 15 - 2 - {{196, 240}, {402, 120}} - 544735232 - Window - NSWindow - - - - - 256 - - - - 268 - {{17, 83}, {79, 17}} - - - - _NS:1505 - YES - - 68288064 - 272630784 - Initalizing... - - LucidaGrande - 13 - 1044 - - _NS:1505 - - - 6 - System - controlColor - - 3 - MC42NjY2NjY2NjY3AA - - - - 6 - System - controlTextColor - - 3 - MAA - - - - - - - 268 - {{18, 55}, {366, 20}} - - - - _NS:9 - {250, 250} - 16399 - 100 - - - - 268 - {{308, 19}, {74, 19}} - - - - _NS:9 - YES - - -2080244224 - 134217728 - Cancel - - LucidaGrande - 12 - 16 - - _NS:9 - - -2038152961 - 164 - - - 400 - 75 - - - - {402, 120} - - - - - {{0, 0}, {1680, 1028}} - {10000000000000, 10000000000000} - YES - - - MacUpdaterAppDelegate - - - YES - - - - - - - title: values - - - - - - title: values - title - values - 2 - - - 41 - - - - - - 0 - - - - - - -2 - - - File's Owner - - - -1 - - - First Responder - - - -3 - - - Application - - - 1 - - - - - - - - 2 - - - - - - - 5 - 0 - - 5 - 1 - - 20 - - 1000 - 8 - 29 - 3 - - - - - 5 - 0 - - 5 - 1 - - 20 - - 1000 - 8 - 29 - 3 - - - - - 6 - 0 - - 6 - 1 - - 20 - - 1000 - 8 - 29 - 3 - - - - - - 6 - 0 - - 6 - 1 - - 20 - - 1000 - 8 - 29 - 3 - - - - - 3 - 0 - - 3 - 1 - - 20 - - 1000 - 8 - 29 - 3 - - - - - 3 - 0 - - 4 - 1 - - 8 - - 1000 - 6 - 24 - 3 - - - - - 4 - 0 - - 4 - 1 - - 20 - - 1000 - 8 - 29 - 3 - - - - - - - 3 - - - - - - - - 4 - - - - - 8 - - - - - - 20 - - - - - 22 - - - - - - 7 - 0 - - 0 - 1 - - 74 - - 1000 - 3 - 9 - 1 - - - - - - - 23 - - - - - 31 - - - - - 32 - - - - - 35 - - - - - 36 - - - - - 37 - - - - - 38 - - - - - 39 - - - - - 40 - - - - - 42 - - - - - - - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - {{357, 418}, {480, 270}} - - - - - - - - - - - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - - - - - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - - com.apple.InterfaceBuilder.CocoaPlugin - - - - - - 42 - - - - - MacUpdaterAppDelegate - NSObject - - cancel: - id - - - cancel: - - cancel: - id - - - - NSProgressIndicator - NSTextField - NSWindow - - - - mProgressBar - NSProgressIndicator - - - mProgressText - NSTextField - - - window - NSWindow - - - - IBProjectSource - ./Classes/MacUpdaterAppDelegate.h - - - - - 0 - IBCocoaFramework - YES - 3 - YES - - diff --git a/indra/mac_updater/MacUpdater-Info.plist b/indra/mac_updater/MacUpdater-Info.plist deleted file mode 100644 index 92137095ff..0000000000 --- a/indra/mac_updater/MacUpdater-Info.plist +++ /dev/null @@ -1,30 +0,0 @@ - - - - - CFBundleDevelopmentRegion - en - CFBundleExecutable - mac-updater - CFBundleGetInfoString - - CFBundleIconFile - - CFBundleIdentifier - com.secondlife.indra.autoupdater - CFBundleInfoDictionaryVersion - 6.0 - CFBundlePackageType - APPL - CFBundleShortVersionString - - CFBundleSignature - ???? - CFBundleVersion - 1.0.0 - NSMainNibFile - AutoUpdater - NSPrincipalClass - NSApplication - - diff --git a/indra/mac_updater/MacUpdaterAppDelegate.h b/indra/mac_updater/MacUpdaterAppDelegate.h deleted file mode 100644 index c051214bb8..0000000000 --- a/indra/mac_updater/MacUpdaterAppDelegate.h +++ /dev/null @@ -1,60 +0,0 @@ -/** - * @file MacUpdaterAppDelegate.h - * @brief - * - * $LicenseInfo:firstyear=2006&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - - -#import -#include -#include "mac_updater.h" - -#ifndef LL_MAC_UPDATE_DELEGATE_H -#define LL_MAC_UPDATE_DELEGATE_H - -@interface MacUpdaterAppDelegate : NSObject -{ - IBOutlet NSProgressIndicator *mProgressBar; - IBOutlet NSTextField *mProgressText; -} -- (void)setWindow:(NSWindow *)newWindow; -- (NSWindow *)window; -- (IBAction)cancel:(id)sender; -- (void) setProgress:(int)cur max:(int) max; -- (void) setProgressText:(const std::string&)str; -- (int) parse_args:(NSArray *) args; -- (void)stopAlert; -- (void)stopAlertDidEnd:(NSAlert *)alert returnCode:(int)returnCode contextInfo:(void *)contextInfo; - - -NSWindow *_window; -bool mAnimated; -double mProgressPercentage; -@property (assign) IBOutlet NSWindow *window; -LLMacUpdater mUpdater; - -@end - -#endif //LL_MAC_UPDATE_DELEGATE_H - - diff --git a/indra/mac_updater/MacUpdaterAppDelegate.mm b/indra/mac_updater/MacUpdaterAppDelegate.mm deleted file mode 100644 index 4457419a94..0000000000 --- a/indra/mac_updater/MacUpdaterAppDelegate.mm +++ /dev/null @@ -1,288 +0,0 @@ -/** - * @file MacUpdaterAppDelegate.mm - * @brief - * - * $LicenseInfo:firstyear=2006&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#import "MacUpdaterAppDelegate.h" -#include "llvfs_objc.h" -#include -#include - -@implementation MacUpdaterAppDelegate - -MacUpdaterAppDelegate *gWindow; -bool gCancelled = false; -bool gFailure =false; - - -//@synthesize window = _window; -- (void)setWindow:(NSWindow *)window -{ - _window = window; -} - -- (NSWindow *)window -{ - return _window; -} - -- (id)init -{ - self = [super init]; - if (self) { - - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - mAnimated = false; - mProgressPercentage = 0.0; - NSArray *arguments = [[NSProcessInfo processInfo] arguments]; - - [self parse_args:arguments]; - gWindow = self; - - mUpdater.doUpdate(); - [pool drain]; - [pool release]; - } - return self; -} - -- (void)dealloc -{ - [super dealloc]; -} - -std::string* NSToString( NSString *ns_str ) -{ - return ( new std::string([ns_str UTF8String]) ); -} - - -- (void) setProgress:(int)cur max:(int) max -{ - bool indeterminate = false; - if (max==0) - { - indeterminate = true; - } - else - { - double percentage = ((double)cur / (double)max) * 100.0; - [mProgressBar setDoubleValue:percentage]; - } - [mProgressBar setIndeterminate:indeterminate]; -} - -- (void) setProgressText:(const std::string& )str -{ - [mProgressText setStringValue:[NSString stringWithUTF8String:str.c_str()]]; -} - -void sendDone() -{ - [ [ (id) gWindow window ] close]; -} - -void sendStopAlert() -{ - [ gWindow stopAlert ]; -} - -void setProgress(int cur, int max) -{ - [ (id) gWindow setProgress:cur max:max]; -} - -void setProgressText(const std::string& str) -{ - [ (id) gWindow setProgressText:str]; -} - -void sendProgress(int cur, int max, const std::string str) -{ - setProgress(cur,max); - setProgressText(str); -} - -bool mkTempDir(boost::filesystem::path& temp_dir) -{ - NSString * tempDir = NSTemporaryDirectory(); - if (tempDir == nil) - tempDir = @"/tmp/"; - - std::string* temp_str = NSToString(tempDir); - *temp_str += std::string("SecondLifeUpdate_XXXXXX"); - - std::cout << "tempDir is " << temp_str << std::endl; - - char temp[PATH_MAX] = ""; /* Flawfinder: ignore */ - strncpy(temp, temp_str->c_str(), temp_str->length()); - - if(mkdtemp(temp) == NULL) - { - return false; - } - - temp_dir = boost::filesystem::path(temp); - - return true; -} -bool copyDir(const std::string& src_dir, const std::string& dest_dir) -{ - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - - NSString* file = [NSString stringWithCString:src_dir.c_str() - encoding:[NSString defaultCStringEncoding]]; - NSString* toParent = [NSString stringWithCString:dest_dir.c_str() - encoding:[NSString defaultCStringEncoding]]; - NSError* error = nil; - - bool result = [[NSFileManager defaultManager] copyItemAtPath: file toPath: toParent error:&error]; - - if (!result) { - NSLog(@"Error during copy: %@", [error localizedDescription]); - } - [pool release]; - - return result; -} - -- (int) parse_args:(NSArray *) args -{ - int i; - int argc = [args count]; - - mUpdater.mApplicationPath = NSToString( [args objectAtIndex:0] ); - - for( i = 1; i < argc; i++ ) - { - NSString* ns_arg = [args objectAtIndex:i]; - const char *arg = [ns_arg UTF8String]; - - if ((!strcmp(arg, "-url")) && (i < argc)) - { - mUpdater.mUpdateURL = NSToString( [args objectAtIndex:(++i)] ); - } - else if ((!strcmp(arg, "-name")) && (i < argc)) - { - mUpdater.mProductName = NSToString( [args objectAtIndex:(++i)] ); - } - else if ((!strcmp(arg, "-bundleid")) && (i < argc)) - { - mUpdater.mBundleID = NSToString( [args objectAtIndex:(++i)] ); - } - else if ((!strcmp(arg, "-dmg")) && (i < argc)) - { - mUpdater.mDmgFile = NSToString( [args objectAtIndex:(++i)] ); - } - else if ((!strcmp(arg, "-marker")) && (i < argc)) - { - mUpdater.mMarkerPath = NSToString( [args objectAtIndex:(++i)] ); - } - } - return 0; -} - -bool isDirWritable(const std::string& dir_name) -{ - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - - NSString *fullPath = [NSString stringWithCString:dir_name.c_str() - encoding:[NSString defaultCStringEncoding]]; - - NSFileManager *fm = [NSFileManager defaultManager]; - bool result = [fm isWritableFileAtPath:fullPath]; - [pool release]; - - return result; -} - -std::string* getUserTrashFolder() -{ - std::string *result; - - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - - NSString *trash_str=[NSHomeDirectory() stringByAppendingPathComponent:@".Trash"]; - - result = NSToString( trash_str ); - - [pool release]; - return result; - -} - -bool isFSRefViewerBundle(const std::string& targetURL) -{ - bool result = false; - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - - NSString *fullPath = [NSString stringWithCString:targetURL.c_str() - encoding:[NSString defaultCStringEncoding]]; - NSBundle *targetBundle = [NSBundle bundleWithPath:fullPath]; - NSString *targetBundleStr = [targetBundle bundleIdentifier]; - NSString *sourceBundleStr = [NSString stringWithCString:mUpdater.mBundleID->c_str() - encoding:[NSString defaultCStringEncoding]]; - - result = [targetBundleStr isEqualToString:sourceBundleStr]; - - if(!result) - { - std::cout << "Target bundle ID mismatch." << std::endl; - } - - [pool release]; - - return result; -} - - -- (IBAction)cancel:(id)sender -{ - gCancelled = true; - sendDone(); -} - -- (void)stopAlert -{ - NSAlert *alert = [[NSAlert alloc] init]; - [alert setAlertStyle:NSInformationalAlertStyle]; - [alert setMessageText:@"Error"]; - [alert setInformativeText:@"An error occurred while updating Second Life. Please download the latest version from www.secondlife.com."]; - - [alert beginSheetModalForWindow:_window - modalDelegate:self - - didEndSelector:@selector(stopAlertDidEnd:returnCode: - contextInfo:) - contextInfo:nil]; - } - - - (void)stopAlertDidEnd:(NSAlert *)alert - returnCode:(int)returnCode contextInfo:(void *)contextInfo -{ - [alert release]; -} - - -@end diff --git a/indra/mac_updater/main.m b/indra/mac_updater/main.m deleted file mode 100644 index aa3776a87d..0000000000 --- a/indra/mac_updater/main.m +++ /dev/null @@ -1,34 +0,0 @@ -/** - * @file main.m - * @brief - * - * $LicenseInfo:firstyear=2006&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#import - -int main(int argc, char *argv[]) -{ - int retVal = NSApplicationMain(argc, (const char **)argv); - - return retVal; -} From e3fa3addd0f91ac4c88624be6539b253f64136d3 Mon Sep 17 00:00:00 2001 From: Aura Linden Date: Thu, 20 Dec 2012 10:51:55 -0800 Subject: [PATCH 26/32] Reverted mac updater --- indra/mac_updater/AutoUpdater.nib/classes.nib | 4 + indra/mac_updater/AutoUpdater.nib/info.nib | 14 + indra/mac_updater/AutoUpdater.nib/objects.xib | 56 + indra/mac_updater/CMakeLists.txt | 22 +- indra/mac_updater/mac_updater.cpp | 1628 +++++++++++------ 5 files changed, 1190 insertions(+), 534 deletions(-) create mode 100644 indra/mac_updater/AutoUpdater.nib/classes.nib create mode 100644 indra/mac_updater/AutoUpdater.nib/info.nib create mode 100644 indra/mac_updater/AutoUpdater.nib/objects.xib diff --git a/indra/mac_updater/AutoUpdater.nib/classes.nib b/indra/mac_updater/AutoUpdater.nib/classes.nib new file mode 100644 index 0000000000..ea58db1189 --- /dev/null +++ b/indra/mac_updater/AutoUpdater.nib/classes.nib @@ -0,0 +1,4 @@ +{ +IBClasses = (); +IBVersion = 1; +} diff --git a/indra/mac_updater/AutoUpdater.nib/info.nib b/indra/mac_updater/AutoUpdater.nib/info.nib new file mode 100644 index 0000000000..a49a92385b --- /dev/null +++ b/indra/mac_updater/AutoUpdater.nib/info.nib @@ -0,0 +1,14 @@ + + + + + IBDocumentLocation + 103 138 356 240 0 0 1280 1002 + IBFramework Version + 362.0 + IBSystem Version + 7D24 + targetFramework + IBCarbonFramework + + diff --git a/indra/mac_updater/AutoUpdater.nib/objects.xib b/indra/mac_updater/AutoUpdater.nib/objects.xib new file mode 100644 index 0000000000..310411b711 --- /dev/null +++ b/indra/mac_updater/AutoUpdater.nib/objects.xib @@ -0,0 +1,56 @@ + + + IBCarbonFramework + + NSApplication + + + + 405 222 533 663 + Second Life Updater + + 0 0 128 441 + + + 20 20 44 421 + what + Initializing… + + + 88 351 108 421 + Cancel + not! + 2 + + + 51 19 70 422 + prog + 50 + + + + FALSE + 2 + 3 + 7 + + + + + + + + + + + + + + + File's Owner + + Updater + + + 194 + diff --git a/indra/mac_updater/CMakeLists.txt b/indra/mac_updater/CMakeLists.txt index 7382e912bf..00dcedecaa 100644 --- a/indra/mac_updater/CMakeLists.txt +++ b/indra/mac_updater/CMakeLists.txt @@ -18,14 +18,10 @@ include_directories( ) set(mac_updater_SOURCE_FILES - main.m - MacUpdaterAppDelegate.mm mac_updater.cpp ) set(mac_updater_HEADER_FILES - MacUpdaterAppDelegate.h - mac_updater.h CMakeLists.txt ) @@ -36,7 +32,7 @@ list(APPEND mac_updater_SOURCE_FILES ${mac_updater_HEADER_FILES}) set(mac_updater_RESOURCE_FILES - AutoUpdater.nib + AutoUpdater.nib/ ) set_source_files_properties( ${mac_updater_RESOURCE_FILES} @@ -52,19 +48,13 @@ add_executable(mac-updater set_target_properties(mac-updater PROPERTIES - MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_SOURCE_DIR}/MacUpdater-Info.plist + MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_SOURCE_DIR}/Info.plist ) -find_library(COCOA_LIBRARY Cocoa) -find_library(IOKIT_LIBRARY IOKit) - target_link_libraries(mac-updater ${LLVFS_LIBRARIES} ${OPENSSL_LIBRARIES} ${CRYPTO_LIBRARIES} - ${COCOA_LIBRARIES} - ${BOOST_FILESYSTEM_LIBRARY} - ${IOKIT_LIBRARY} ${CURL_LIBRARIES} ${CARES_LIBRARIES} ${LLCOMMON_LIBRARIES} @@ -72,16 +62,10 @@ target_link_libraries(mac-updater add_custom_command( TARGET mac-updater POST_BUILD -# COMMAND ${CMAKE_COMMAND} -# ARGS -# -E -# copy_directory -# ${CMAKE_CURRENT_SOURCE_DIR}/AutoUpdater.nib -# ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/mac-updater.app/Contents/Resources/AutoUpdater.nib COMMAND ${CMAKE_COMMAND} ARGS -E - copy + copy_directory ${CMAKE_CURRENT_SOURCE_DIR}/AutoUpdater.nib ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/mac-updater.app/Contents/Resources/AutoUpdater.nib ) diff --git a/indra/mac_updater/mac_updater.cpp b/indra/mac_updater/mac_updater.cpp index bc9fec3558..aa45c5d23f 100644 --- a/indra/mac_updater/mac_updater.cpp +++ b/indra/mac_updater/mac_updater.cpp @@ -27,8 +27,6 @@ #include "linden_common.h" #include -#include -#include #include #include @@ -36,6 +34,7 @@ #include #include +#include #include "llerror.h" #include "lltimer.h" @@ -44,123 +43,267 @@ #include "llstring.h" +#include + #include "llerrorcontrol.h" -#include "mac_updater.h" -#include + +enum +{ + kEventClassCustom = 'Cust', + kEventCustomProgress = 'Prog', + kEventParamCustomCurValue = 'Cur ', + kEventParamCustomMaxValue = 'Max ', + kEventParamCustomText = 'Text', + kEventCustomDone = 'Done', +}; + +WindowRef gWindow = NULL; +EventHandlerRef gEventHandler = NULL; +OSStatus gFailure = noErr; +Boolean gCancelled = false; + +const char *gUpdateURL; +const char *gProductName; +const char *gBundleID; +const char *gDmgFile; +const char *gMarkerPath; + +void *updatethreadproc(void*); pthread_t updatethread; -LLMacUpdater* LLMacUpdater::sInstance = NULL; - -LLMacUpdater::LLMacUpdater(): - mUpdateURL (NULL), - mProductName (NULL), - mBundleID (NULL), - mDmgFile (NULL), - mMarkerPath (NULL) +OSStatus setProgress(int cur, int max) { - sInstance = this; -} + OSStatus err; + ControlRef progressBar = NULL; + ControlID id; -void LLMacUpdater::doUpdate() -{ - // We assume that all the logs we're looking for reside on the current drive - gDirUtilp->initAppDirs("SecondLife"); - - LLError::initForApplication( gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "")); - - // Rename current log file to ".old" - std::string old_log_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "updater.log.old"); - std::string log_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "updater.log"); - LLFile::rename(log_file.c_str(), old_log_file.c_str()); - - // Set the log file to updater.log - LLError::logToFile(log_file); - - if ((mUpdateURL == NULL) && (mDmgFile == NULL)) + id.signature = 'prog'; + id.id = 0; + + err = GetControlByID(gWindow, &id, &progressBar); + if(err == noErr) { - llinfos << "Usage: mac_updater -url | -dmg [-name ] [-program ]" << llendl; - exit(1); - } - else - { - llinfos << "Update url is: " << mUpdateURL << llendl; - if (mProductName) + Boolean indeterminate; + + if(max == 0) { - llinfos << "Product name is: " << *mProductName << llendl; + indeterminate = true; + err = SetControlData(progressBar, kControlEntireControl, kControlProgressBarIndeterminateTag, sizeof(Boolean), (Ptr)&indeterminate); } else { - mProductName = new std::string("Second Life"); - } - if (mBundleID) - { - llinfos << "Bundle ID is: " << *mBundleID << llendl; - } - else - { - mBundleID = new std::string("com.secondlife.indra.viewer"); + double percentage = (double)cur / (double)max; + SetControlMinimum(progressBar, 0); + SetControlMaximum(progressBar, 100); + SetControlValue(progressBar, (SInt16)(percentage * 100)); + + indeterminate = false; + err = SetControlData(progressBar, kControlEntireControl, kControlProgressBarIndeterminateTag, sizeof(Boolean), (Ptr)&indeterminate); + + Draw1Control(progressBar); } } - - llinfos << "Starting " << *mProductName << " Updater" << llendl; - - pthread_create(&updatethread, - NULL, - &sUpdatethreadproc, - NULL); - - - void *threadresult; - - pthread_join(updatethread, &threadresult); - - if(gCancelled || gFailure) - { - sendStopAlert(); - - if(mMarkerPath != 0) - { - // Create a install fail marker that can be used by the viewer to - // detect install problems. - std::ofstream stream(mMarkerPath->c_str()); - if(stream) stream << -1; - } - exit(-1); - } else { - exit(0); - } - - return; + + return(err); } -//SPATTERS TODO this should be moved to lldir_mac.cpp -const std::string LLMacUpdater::walkParents( signed int depth, const std::string& childpath ) +OSStatus setProgressText(CFStringRef text) { - boost::filesystem::path fullpath(childpath.c_str()); - - while (depth > 0 && fullpath.has_parent_path()) - { - fullpath = boost::filesystem::path(fullpath.parent_path()); - --depth; - } - - return fullpath.string(); + OSStatus err; + ControlRef progressText = NULL; + ControlID id; + + id.signature = 'what'; + id.id = 0; + + err = GetControlByID(gWindow, &id, &progressText); + if(err == noErr) + { + err = SetControlData(progressText, kControlEntireControl, kControlStaticTextCFStringTag, sizeof(CFStringRef), (Ptr)&text); + Draw1Control(progressText); + } + + return(err); } -//#if 0 -//size_t curl_download_callback(void *data, size_t size, size_t nmemb, -// void *user_data) -//{ -// S32 bytes = size * nmemb; -// char *cdata = (char *) data; -// for (int i =0; i < bytes; i += 1) -// { -// gServerResponse.append(cdata[i]); -// } -// return bytes; -//} -//#endif +OSStatus sendProgress(long cur, long max, CFStringRef text = NULL) +{ + OSStatus result; + EventRef evt; + + result = CreateEvent( + NULL, + kEventClassCustom, + kEventCustomProgress, + 0, + kEventAttributeNone, + &evt); + + // This event needs to be targeted at the window so it goes to the window's handler. + if(result == noErr) + { + EventTargetRef target = GetWindowEventTarget(gWindow); + result = SetEventParameter ( + evt, + kEventParamPostTarget, + typeEventTargetRef, + sizeof(target), + &target); + } + + if(result == noErr) + { + result = SetEventParameter ( + evt, + kEventParamCustomCurValue, + typeLongInteger, + sizeof(cur), + &cur); + } + + if(result == noErr) + { + result = SetEventParameter ( + evt, + kEventParamCustomMaxValue, + typeLongInteger, + sizeof(max), + &max); + } + + if(result == noErr) + { + if(text != NULL) + { + result = SetEventParameter ( + evt, + kEventParamCustomText, + typeCFStringRef, + sizeof(text), + &text); + } + } + + if(result == noErr) + { + // Send the event + PostEventToQueue( + GetMainEventQueue(), + evt, + kEventPriorityStandard); + + } + + return(result); +} + +OSStatus sendDone(void) +{ + OSStatus result; + EventRef evt; + + result = CreateEvent( + NULL, + kEventClassCustom, + kEventCustomDone, + 0, + kEventAttributeNone, + &evt); + + // This event needs to be targeted at the window so it goes to the window's handler. + if(result == noErr) + { + EventTargetRef target = GetWindowEventTarget(gWindow); + result = SetEventParameter ( + evt, + kEventParamPostTarget, + typeEventTargetRef, + sizeof(target), + &target); + } + + if(result == noErr) + { + // Send the event + PostEventToQueue( + GetMainEventQueue(), + evt, + kEventPriorityStandard); + + } + + return(result); +} + +OSStatus dialogHandler(EventHandlerCallRef handler, EventRef event, void *userdata) +{ + OSStatus result = eventNotHandledErr; + OSStatus err; + UInt32 evtClass = GetEventClass(event); + UInt32 evtKind = GetEventKind(event); + + if((evtClass == kEventClassCommand) && (evtKind == kEventCommandProcess)) + { + HICommand cmd; + err = GetEventParameter(event, kEventParamDirectObject, typeHICommand, NULL, sizeof(cmd), NULL, &cmd); + + if(err == noErr) + { + switch(cmd.commandID) + { + case kHICommandCancel: + gCancelled = true; +// QuitAppModalLoopForWindow(gWindow); + result = noErr; + break; + } + } + } + else if((evtClass == kEventClassCustom) && (evtKind == kEventCustomProgress)) + { + // Request to update the progress dialog + long cur = 0; + long max = 0; + CFStringRef text = NULL; + (void) GetEventParameter(event, kEventParamCustomCurValue, typeLongInteger, NULL, sizeof(cur), NULL, &cur); + (void) GetEventParameter(event, kEventParamCustomMaxValue, typeLongInteger, NULL, sizeof(max), NULL, &max); + (void) GetEventParameter(event, kEventParamCustomText, typeCFStringRef, NULL, sizeof(text), NULL, &text); + + err = setProgress(cur, max); + if(err == noErr) + { + if(text != NULL) + { + setProgressText(text); + } + } + + result = noErr; + } + else if((evtClass == kEventClassCustom) && (evtKind == kEventCustomDone)) + { + // We're done. Exit the modal loop. + QuitAppModalLoopForWindow(gWindow); + result = noErr; + } + + return(result); +} + +#if 0 +size_t curl_download_callback(void *data, size_t size, size_t nmemb, + void *user_data) +{ + S32 bytes = size * nmemb; + char *cdata = (char *) data; + for (int i =0; i < bytes; i += 1) + { + gServerResponse.append(cdata[i]); + } + return bytes; +} +#endif int curl_progress_callback_func(void *clientp, double dltotal, @@ -170,7 +313,7 @@ int curl_progress_callback_func(void *clientp, { int max = (int)(dltotal / 1024.0); int cur = (int)(dlnow / 1024.0); - setProgress(cur, max); + sendProgress(cur, max); if(gCancelled) return(1); @@ -178,418 +321,899 @@ int curl_progress_callback_func(void *clientp, return(0); } -bool LLMacUpdater::isApplication(const std::string& app_str) +int parse_args(int argc, char **argv) { - return !(bool) app_str.compare( app_str.length()-4, 4, ".app"); -} - -// Search through the directory specified by 'parent' for an item that appears to be a Second Life viewer. -bool LLMacUpdater::findAppBundleOnDiskImage(const boost::filesystem::path& dir_path, - boost::filesystem::path& path_found) -{ - if ( !boost::filesystem::exists( dir_path ) ) return false; + int j; - boost::filesystem::directory_iterator end_itr; - - for ( boost::filesystem::directory_iterator itr( dir_path ); - itr != end_itr; - ++itr ) - { - if ( boost::filesystem::is_directory(itr->status()) ) - { - std::string dir_name = itr->path().string(); - if ( isApplication(dir_name) ) - { - if(isFSRefViewerBundle(dir_name)) - { - llinfos << dir_name << " is the one" << llendl; - - path_found = itr->path(); - return true; - } - } - } - } - return false; -} - -bool LLMacUpdater::verifyDirectory(const boost::filesystem::path* directory, bool isParent) -{ - bool replacingTarget; - std::string app_str = directory->string(); - - if (boost::filesystem::is_directory(*directory)) - { - // This is fine, just means we're not replacing anything. - replacingTarget = true; - } - else - { - replacingTarget = isParent; - } - - //Check that the directory is writeable. - if(!isDirWritable(app_str)) - { - // Parent directory isn't writable. - llinfos << "Target directory not writable." << llendl; - replacingTarget = false; - } - return replacingTarget; -} - -bool LLMacUpdater::getViewerDir(boost::filesystem::path &app_dir) -{ - std::string app_dir_str; - - //Walk up 6 levels from the App Updater's installation point. - app_dir_str = walkParents( 6, *mApplicationPath ); - - app_dir = boost::filesystem::path(app_dir_str); - - //Check to see that the directory's name ends in .app Lame but it's the best thing we have to go on. - //If it's not there, we're going to default to /Applications/VIEWERNAME - if (!isApplication(app_dir_str)) - { - llinfos << "Target search failed, defaulting to /Applications/" << *mProductName << ".app." << llendl; - std::string newpath = std::string("/Applications/") + mProductName->c_str(); - app_dir = boost::filesystem::path(newpath); - } - return verifyDirectory(&app_dir); -} - -bool LLMacUpdater::downloadDMG(const std::string& dmgName, boost::filesystem::path* temp_dir) -{ - LLFILE *downloadFile = NULL; - char temp[PATH_MAX] = ""; /* Flawfinder: ignore */ - - chdir(temp_dir->string().c_str()); - - snprintf(temp, sizeof(temp), "SecondLife.dmg"); - - downloadFile = LLFile::fopen(temp, "wb"); /* Flawfinder: ignore */ - if(downloadFile == NULL) - { - return false; - } - - bool success = false; - - CURL *curl = curl_easy_init(); - - curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1); - // curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &curl_download_callback); - curl_easy_setopt(curl, CURLOPT_FILE, downloadFile); - curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0); - curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, &curl_progress_callback_func); - curl_easy_setopt(curl, CURLOPT_URL, mUpdateURL); - curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1); - - sendProgress(0, 1, std::string("Downloading...")); - - CURLcode result = curl_easy_perform(curl); - - curl_easy_cleanup(curl); - - if(gCancelled) - { - llinfos << "User cancel, bailing out."<< llendl; - goto close_file; - } - - if(result != CURLE_OK) - { - llinfos << "Error " << result << " while downloading disk image."<< llendl; - goto close_file; - } - - fclose(downloadFile); - downloadFile = NULL; - - success = true; - -close_file: - // Close disk image file if necessary - if(downloadFile != NULL) + for (j = 1; j < argc; j++) { - llinfos << "Closing download file." << llendl; - - fclose(downloadFile); - downloadFile = NULL; + if ((!strcmp(argv[j], "-url")) && (++j < argc)) + { + gUpdateURL = argv[j]; + } + else if ((!strcmp(argv[j], "-name")) && (++j < argc)) + { + gProductName = argv[j]; + } + else if ((!strcmp(argv[j], "-bundleid")) && (++j < argc)) + { + gBundleID = argv[j]; + } + else if ((!strcmp(argv[j], "-dmg")) && (++j < argc)) + { + gDmgFile = argv[j]; + } + else if ((!strcmp(argv[j], "-marker")) && (++j < argc)) + { + gMarkerPath = argv[j];; + } } - return success; + return 0; } - -bool LLMacUpdater::doMount(const std::string& dmgName, char* deviceNode, const boost::filesystem::path& temp_dir) + +int main(int argc, char **argv) { - char temp[PATH_MAX] = ""; /* Flawfinder: ignore */ - - sendProgress(0, 0, std::string("Mounting image...")); - chdir(temp_dir.string().c_str()); - std::string mnt_dir = temp_dir.string() + std::string("/mnt"); - LLFile::mkdir(mnt_dir.c_str(), 0700); - - // NOTE: we could add -private at the end of this command line to keep the image from showing up in the Finder, - // but if our cleanup fails, this makes it much harder for the user to unmount the image. - std::string mountOutput; - boost::format cmdFormat("hdiutil attach %s -mountpoint mnt"); - cmdFormat % dmgName; - FILE* mounter = popen(cmdFormat.str().c_str(), "r"); /* Flawfinder: ignore */ - - if(mounter == NULL) - { - llinfos << "Failed to mount disk image, exiting."<< llendl; - return false; - } - - // We need to scan the output from hdiutil to find the device node it uses to attach the disk image. - // If we don't have this information, we can't detach it later. - while(mounter != NULL) - { - size_t len = fread(temp, 1, sizeof(temp)-1, mounter); - temp[len] = 0; - mountOutput.append(temp); - if(len < sizeof(temp)-1) - { - // End of file or error. - int result = pclose(mounter); - if(result != 0) - { - // NOTE: We used to abort here, but pclose() started returning - // -1, possibly when the size of the DMG passed a certain point - llinfos << "Unexpected result closing pipe: " << result << llendl; - } - mounter = NULL; - } - } - - if(!mountOutput.empty()) - { - const char *s = mountOutput.c_str(); - const char *prefix = "/dev/"; - char *sub = strstr(s, prefix); - - if(sub != NULL) - { - sub += strlen(prefix); /* Flawfinder: ignore */ - sscanf(sub, "%1023s", deviceNode); /* Flawfinder: ignore */ - } - } - - if(deviceNode[0] != 0) - { - llinfos << "Disk image attached on /dev/" << deviceNode << llendl; - } - else - { - llinfos << "Disk image device node not found!" << llendl; - return false; - } - - return true; + // We assume that all the logs we're looking for reside on the current drive + gDirUtilp->initAppDirs("SecondLife"); + + LLError::initForApplication( gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "")); + + // Rename current log file to ".old" + std::string old_log_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "updater.log.old"); + std::string log_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "updater.log"); + LLFile::rename(log_file.c_str(), old_log_file.c_str()); + + // Set the log file to updater.log + LLError::logToFile(log_file); + + ///////////////////////////////////////// + // + // Process command line arguments + // + gUpdateURL = NULL; + gProductName = NULL; + gBundleID = NULL; + gDmgFile = NULL; + gMarkerPath = NULL; + parse_args(argc, argv); + if ((gUpdateURL == NULL) && (gDmgFile == NULL)) + { + llinfos << "Usage: mac_updater -url | -dmg [-name ] [-program ]" << llendl; + exit(1); + } + else + { + llinfos << "Update url is: " << gUpdateURL << llendl; + if (gProductName) + { + llinfos << "Product name is: " << gProductName << llendl; + } + else + { + gProductName = "Second Life"; + } + if (gBundleID) + { + llinfos << "Bundle ID is: " << gBundleID << llendl; + } + else + { + gBundleID = "com.secondlife.indra.viewer"; + } + } + + llinfos << "Starting " << gProductName << " Updater" << llendl; + + // Real UI... + OSStatus err; + IBNibRef nib = NULL; + + err = CreateNibReference(CFSTR("AutoUpdater"), &nib); + + char windowTitle[MAX_PATH]; /* Flawfinder: ignore */ + snprintf(windowTitle, sizeof(windowTitle), "%s Updater", gProductName); + CFStringRef windowTitleRef = NULL; + windowTitleRef = CFStringCreateWithCString(NULL, windowTitle, kCFStringEncodingUTF8); + + if(err == noErr) + { + err = CreateWindowFromNib(nib, CFSTR("Updater"), &gWindow); + } + + if (err == noErr) + { + err = SetWindowTitleWithCFString(gWindow, windowTitleRef); + } + CFRelease(windowTitleRef); + + if(err == noErr) + { + // Set up an event handler for the window. + EventTypeSpec handlerEvents[] = + { + { kEventClassCommand, kEventCommandProcess }, + { kEventClassCustom, kEventCustomProgress }, + { kEventClassCustom, kEventCustomDone } + }; + InstallStandardEventHandler(GetWindowEventTarget(gWindow)); + InstallWindowEventHandler( + gWindow, + NewEventHandlerUPP(dialogHandler), + GetEventTypeCount (handlerEvents), + handlerEvents, + 0, + &gEventHandler); + } + + if(err == noErr) + { + ShowWindow(gWindow); + SelectWindow(gWindow); + } + + if(err == noErr) + { + pthread_create(&updatethread, + NULL, + &updatethreadproc, + NULL); + + } + + if(err == noErr) + { + RunAppModalLoopForWindow(gWindow); + } + + void *threadresult; + + pthread_join(updatethread, &threadresult); + + if(!gCancelled && (gFailure != noErr)) + { + // Something went wrong. Since we always just tell the user to download a new version, we don't really care what. + AlertStdCFStringAlertParamRec params; + SInt16 retval_mac = 1; + DialogRef alert = NULL; + OSStatus err; + + params.version = kStdCFStringAlertVersionOne; + params.movable = false; + params.helpButton = false; + params.defaultText = (CFStringRef)kAlertDefaultOKText; + params.cancelText = 0; + params.otherText = 0; + params.defaultButton = 1; + params.cancelButton = 0; + params.position = kWindowDefaultPosition; + params.flags = 0; + + err = CreateStandardAlert( + kAlertStopAlert, + CFSTR("Error"), + CFSTR("An error occurred while updating Second Life. Please download the latest version from www.secondlife.com."), + ¶ms, + &alert); + + if(err == noErr) + { + err = RunStandardAlert( + alert, + NULL, + &retval_mac); + } + + if(gMarkerPath != 0) + { + // Create a install fail marker that can be used by the viewer to + // detect install problems. + std::ofstream stream(gMarkerPath); + if(stream) stream << -1; + } + exit(-1); + } else { + exit(0); + } + + if(gWindow != NULL) + { + DisposeWindow(gWindow); + } + + if(nib != NULL) + { + DisposeNibReference(nib); + } + + return 0; } -bool LLMacUpdater::moveApplication (const boost::filesystem::path& app_dir, - const boost::filesystem::path& temp_dir, - boost::filesystem::path& aside_dir) +bool isDirWritable(FSRef &dir) { - try - { - //Grab filename from installdir append to tempdir move set aside_dir to moved path. - std::string install_str = app_dir.parent_path().string(); - std::string temp_str = temp_dir.string(); - std::string app_str = app_dir.filename().string(); - aside_dir = boost::filesystem::path( boost::filesystem::operator/(temp_dir,app_str) ); - std::cout << "Attempting to move " << app_dir.string() << " to " << aside_dir.string() << std::endl; - - boost::filesystem::rename(app_dir, aside_dir); - } - catch(boost::filesystem::filesystem_error e) - { - llinfos << "Application move failed." << llendl; - return false; - } - return true; + bool result = false; + + // Test for a writable directory by creating a directory, then deleting it again. + // This is kinda lame, but will pretty much always give the right answer. + + OSStatus err = noErr; + char temp[PATH_MAX] = ""; /* Flawfinder: ignore */ + + err = FSRefMakePath(&dir, (UInt8*)temp, sizeof(temp)); + + if(err == noErr) + { + strncat(temp, "/.test_XXXXXX", (sizeof(temp) - strlen(temp)) - 1); + + if(mkdtemp(temp) != NULL) + { + // We were able to make the directory. This means the directory is writable. + result = true; + + // Clean up. + rmdir(temp); + } + } + +#if 0 + // This seemed like a good idea, but won't tell us if we're on a volume mounted read-only. + UInt8 perm; + err = FSGetUserPrivilegesPermissions(&targetParentRef, &perm, NULL); + if(err == noErr) + { + if(perm & kioACUserNoMakeChangesMask) + { + // Parent directory isn't writable. + llinfos << "Target parent directory not writable." << llendl; + err = -1; + replacingTarget = false; + } + } +#endif + + return result; } -bool LLMacUpdater::doInstall(const boost::filesystem::path& app_dir, - const boost::filesystem::path& temp_dir, - boost::filesystem::path& mount_dir, - bool replacingTarget) -{ - std::string temp_name = temp_dir.string() + std::string("/mnt"); - - llinfos << "Disk image mount point is: " << temp_name << llendl; - - mount_dir = boost::filesystem::path(temp_name.c_str()); - - if (! boost::filesystem::exists ( mount_dir ) ) - { - llinfos << "Couldn't make FSRef to disk image mount point." << llendl; - return false; - } - - sendProgress(0, 0, std::string("Searching for the app bundle...")); - - boost::filesystem::path source_dir; - - if ( !findAppBundleOnDiskImage(mount_dir, source_dir) ) - { - llinfos << "Couldn't find application bundle on mounted disk image." << llendl; - return false; - } - else - { - llinfos << "found the bundle." << llendl; - } - - sendProgress(0, 0, std::string("Preparing to copy files...")); - - // this will hold the name of the destination target - boost::filesystem::path aside_dir; - - if(replacingTarget) - { - - if (! moveApplication (app_dir, temp_dir, aside_dir) ) - { - llwarns << "failed to move aside old version." << llendl; - return false; - } - } - - sendProgress(0, 0, std::string("Copying files...")); - - llinfos << "Starting copy..." << llendl; - // If we were replacingTarget, we've moved the app to a temp directory. - // Otherwise the destination should be empty. - // We have mounted the DMG as a volume so we should be able to just - // move the app from the volume to the destination and everything will just work. - - - // Copy the new version from the disk image to the target location. - - //The installer volume is mounted read-only so we can't move. Instead copy and then unmount. - if (! copyDir(source_dir.string(), app_dir.string()) ) - { - llwarns << "Failed to copy " << source_dir.string() << " to " << app_dir.string() << llendl; - - // Something went wrong during the copy. Attempt to put the old version back and bail. - boost::filesystem::rename(app_dir, aside_dir); - return false; - - } - - // The update has succeeded. Clear the cache directory. - - sendProgress(0, 0, std::string("Clearing cache...")); - - llinfos << "Clearing cache..." << llendl; - - gDirUtilp->deleteFilesInDir(gDirUtilp->getExpandedFilename(LL_PATH_CACHE,""), "*.*"); - - llinfos << "Clear complete." << llendl; - - return true; +static std::string HFSUniStr255_to_utf8str(const HFSUniStr255* src) +{ + llutf16string string16((U16*)&(src->unicode), src->length); + std::string result = utf16str_to_utf8str(string16); + return result; } -void* LLMacUpdater::updatethreadproc(void*) +int restoreObject(const char* aside, const char* target, const char* path, const char* object) +{ + char source[PATH_MAX] = ""; /* Flawfinder: ignore */ + char dest[PATH_MAX] = ""; /* Flawfinder: ignore */ + snprintf(source, sizeof(source), "%s/%s/%s", aside, path, object); + snprintf(dest, sizeof(dest), "%s/%s", target, path); + FSRef sourceRef; + FSRef destRef; + OSStatus err; + err = FSPathMakeRef((UInt8 *)source, &sourceRef, NULL); + if(err != noErr) return false; + err = FSPathMakeRef((UInt8 *)dest, &destRef, NULL); + if(err != noErr) return false; + + llinfos << "Copying " << source << " to " << dest << llendl; + + err = FSCopyObjectSync( + &sourceRef, + &destRef, + NULL, + NULL, + kFSFileOperationOverwrite); + + if(err != noErr) return false; + return true; +} + +// Replace any mention of "Second Life" with the product name. +void filterFile(const char* filename) +{ + char temp[PATH_MAX] = ""; /* Flawfinder: ignore */ + // First copy the target's version, so we can run it through sed. + snprintf(temp, sizeof(temp), "cp '%s' '%s.tmp'", filename, filename); + system(temp); /* Flawfinder: ignore */ + + // Now run it through sed. + snprintf(temp, sizeof(temp), + "sed 's/Second Life/%s/g' '%s.tmp' > '%s'", gProductName, filename, filename); + system(temp); /* Flawfinder: ignore */ +} + +static bool isFSRefViewerBundle(FSRef *targetRef) +{ + bool result = false; + CFURLRef targetURL = NULL; + CFBundleRef targetBundle = NULL; + CFStringRef targetBundleID = NULL; + CFStringRef sourceBundleID = NULL; + + targetURL = CFURLCreateFromFSRef(NULL, targetRef); + + if(targetURL == NULL) + { + llinfos << "Error creating target URL." << llendl; + } + else + { + targetBundle = CFBundleCreate(NULL, targetURL); + } + + if(targetBundle == NULL) + { + llinfos << "Failed to create target bundle." << llendl; + } + else + { + targetBundleID = CFBundleGetIdentifier(targetBundle); + } + + if(targetBundleID == NULL) + { + llinfos << "Couldn't retrieve target bundle ID." << llendl; + } + else + { + sourceBundleID = CFStringCreateWithCString(NULL, gBundleID, kCFStringEncodingUTF8); + if(CFStringCompare(sourceBundleID, targetBundleID, 0) == kCFCompareEqualTo) + { + // This is the bundle we're looking for. + result = true; + } + else + { + llinfos << "Target bundle ID mismatch." << llendl; + } + } + + // Don't release targetBundleID -- since we don't retain it, it's released when targetBundle is released. + if(targetURL != NULL) + CFRelease(targetURL); + if(targetBundle != NULL) + CFRelease(targetBundle); + + return result; +} + +// Search through the directory specified by 'parent' for an item that appears to be a Second Life viewer. +static OSErr findAppBundleOnDiskImage(FSRef *parent, FSRef *app) +{ + FSIterator iterator; + bool found = false; + + OSErr err = FSOpenIterator( parent, kFSIterateFlat, &iterator ); + if(!err) + { + do + { + ItemCount actualObjects = 0; + Boolean containerChanged = false; + FSCatalogInfo info; + FSRef ref; + HFSUniStr255 unicodeName; + err = FSGetCatalogInfoBulk( + iterator, + 1, + &actualObjects, + &containerChanged, + kFSCatInfoNodeFlags, + &info, + &ref, + NULL, + &unicodeName ); + + if(actualObjects == 0) + break; + + if(!err) + { + // Call succeeded and not done with the iteration. + std::string name = HFSUniStr255_to_utf8str(&unicodeName); + + llinfos << "Considering \"" << name << "\"" << llendl; + + if(info.nodeFlags & kFSNodeIsDirectoryMask) + { + // This is a directory. See if it's a .app + if(name.find(".app") != std::string::npos) + { + // Looks promising. Check to see if it has the right bundle identifier. + if(isFSRefViewerBundle(&ref)) + { + llinfos << name << " is the one" << llendl; + // This is the one. Return it. + *app = ref; + found = true; + break; + } else { + llinfos << name << " is not the bundle we are looking for; move along" << llendl; + } + + } + } + } + } + while(!err); + + llinfos << "closing the iterator" << llendl; + + FSCloseIterator(iterator); + + llinfos << "closed" << llendl; + } + + if(!err && !found) + err = fnfErr; + + return err; +} + +void *updatethreadproc(void*) { char tempDir[PATH_MAX] = ""; /* Flawfinder: ignore */ + FSRef tempDirRef; char temp[PATH_MAX] = ""; /* Flawfinder: ignore */ // *NOTE: This buffer length is used in a scanf() below. char deviceNode[1024] = ""; /* Flawfinder: ignore */ - - bool replacingTarget = false; - - boost::filesystem::path app_dir; - boost::filesystem::path temp_dir; - boost::filesystem::path mount_dir; - - // Attempt to get a reference to the Second Life application bundle containing this updater. - // Any failures during this process will cause us to default to updating /Applications/Second Life.app + LLFILE *downloadFile = NULL; + OSStatus err; + ProcessSerialNumber psn; + char target[PATH_MAX] = ""; /* Flawfinder: ignore */ + FSRef targetRef; + FSRef targetParentRef; + FSVolumeRefNum targetVol; + FSRef trashFolderRef; + Boolean replacingTarget = false; + memset(&tempDirRef, 0, sizeof(tempDirRef)); + memset(&targetRef, 0, sizeof(targetRef)); + memset(&targetParentRef, 0, sizeof(targetParentRef)); + try - { - replacingTarget = getViewerDir( app_dir ); - - if (!mkTempDir(temp_dir)) - { - throw 0; - } - - //In case the dir doesn't exist, try to create it. If create fails, verify it exists. - if (! boost::filesystem::create_directory(app_dir)) - { + { + // Attempt to get a reference to the Second Life application bundle containing this updater. + // Any failures during this process will cause us to default to updating /Applications/Second Life.app + { + FSRef myBundle; + err = GetCurrentProcess(&psn); + if(err == noErr) + { + err = GetProcessBundleLocation(&psn, &myBundle); + } - if(isFSRefViewerBundle(app_dir.string())) - { - // This is the bundle we're looking for. - replacingTarget = true; - } - else - { - throw 0; - } - } - - if ( !verifyDirectory(&app_dir, true) ) - { - // We're so hosed. - llinfos << "Applications directory not found, giving up." << llendl; - throw 0; - } + if(err == noErr) + { + // Sanity check: Make sure the name of the item referenced by targetRef is "Second Life.app". + FSRefMakePath(&myBundle, (UInt8*)target, sizeof(target)); + + llinfos << "Updater bundle location: " << target << llendl; + } + + // Our bundle should be in Second Life.app/Contents/Resources/AutoUpdater.app + // so we need to go up 3 levels to get the path to the main application bundle. + if(err == noErr) + { + err = FSGetCatalogInfo(&myBundle, kFSCatInfoNone, NULL, NULL, NULL, &targetRef); + } + if(err == noErr) + { + err = FSGetCatalogInfo(&targetRef, kFSCatInfoNone, NULL, NULL, NULL, &targetRef); + } + if(err == noErr) + { + err = FSGetCatalogInfo(&targetRef, kFSCatInfoNone, NULL, NULL, NULL, &targetRef); + } + + // And once more to get the parent of the target + if(err == noErr) + { + err = FSGetCatalogInfo(&targetRef, kFSCatInfoNone, NULL, NULL, NULL, &targetParentRef); + } + + if(err == noErr) + { + FSRefMakePath(&targetRef, (UInt8*)target, sizeof(target)); + llinfos << "Path to target: " << target << llendl; + } + + // Sanity check: make sure the target is a bundle with the right identifier + if(err == noErr) + { + // Assume the worst... + err = -1; + + if(isFSRefViewerBundle(&targetRef)) + { + // This is the bundle we're looking for. + err = noErr; + replacingTarget = true; + } + } + + // Make sure the target's parent directory is writable. + if(err == noErr) + { + if(!isDirWritable(targetParentRef)) + { + // Parent directory isn't writable. + llinfos << "Target parent directory not writable." << llendl; + err = -1; + replacingTarget = false; + } + } + + if(err != noErr) + { + Boolean isDirectory; + llinfos << "Target search failed, defaulting to /Applications/" << gProductName << ".app." << llendl; + + // Set up the parent directory + err = FSPathMakeRef((UInt8*)"/Applications", &targetParentRef, &isDirectory); + if((err != noErr) || (!isDirectory)) + { + // We're so hosed. + llinfos << "Applications directory not found, giving up." << llendl; + throw 0; + } + + snprintf(target, sizeof(target), "/Applications/%s.app", gProductName); + + memset(&targetRef, 0, sizeof(targetRef)); + err = FSPathMakeRef((UInt8*)target, &targetRef, NULL); + if(err == fnfErr) + { + // This is fine, just means we're not replacing anything. + err = noErr; + replacingTarget = false; + } + else + { + replacingTarget = true; + } + + // Make sure the target's parent directory is writable. + if(err == noErr) + { + if(!isDirWritable(targetParentRef)) + { + // Parent directory isn't writable. + llinfos << "Target parent directory not writable." << llendl; + err = -1; + replacingTarget = false; + } + } + + } + + // If we haven't fixed all problems by this point, just bail. + if(err != noErr) + { + llinfos << "Unable to pick a target, giving up." << llendl; + throw 0; + } + } + + // Find the volID of the volume the target resides on + { + FSCatalogInfo info; + err = FSGetCatalogInfo( + &targetParentRef, + kFSCatInfoVolume, + &info, + NULL, + NULL, + NULL); + + if(err != noErr) + throw 0; + + targetVol = info.volume; + } + + // Find the temporary items and trash folders on that volume. + err = FSFindFolder( + targetVol, + kTrashFolderType, + true, + &trashFolderRef); + + if(err != noErr) + throw 0; + +#if 0 // *HACK for DEV-11935 see below for details. + + FSRef tempFolderRef; + + err = FSFindFolder( + targetVol, + kTemporaryFolderType, + true, + &tempFolderRef); + + if(err != noErr) + throw 0; + + err = FSRefMakePath(&tempFolderRef, (UInt8*)temp, sizeof(temp)); + + if(err != noErr) + throw 0; + +#else + + // *HACK for DEV-11935 the above kTemporaryFolderType query was giving + // back results with path names that seem to be too long to be used as + // mount points. I suspect this incompatibility was introduced in the + // Leopard 10.5.2 update, but I have not verified this. + char const HARDCODED_TMP[] = "/tmp"; + strncpy(temp, HARDCODED_TMP, sizeof(HARDCODED_TMP)); + +#endif // 0 *HACK for DEV-11935 // Skip downloading the file if the dmg was passed on the command line. std::string dmgName; - if(mDmgFile != NULL) { - //Create a string from the mDmgFile then a dir reference to that. - //change to that directory and begin install. - - boost::filesystem::path dmg_path(*mDmgFile); - - dmgName = dmg_path.string(); - std::string* dmgPath = new std::string(dmg_path.parent_path().string()); - if ( !boost::filesystem::exists( dmg_path.parent_path() ) ) { - llinfos << "Path " << *dmgPath << " is not writeable. Aborting." << llendl; - throw 0; - } - - chdir(dmgPath->c_str()); + if(gDmgFile != NULL) { + dmgName = basename((char *)gDmgFile); + char * dmgDir = dirname((char *)gDmgFile); + strncpy(tempDir, dmgDir, sizeof(tempDir)); + err = FSPathMakeRef((UInt8*)tempDir, &tempDirRef, NULL); + if(err != noErr) throw 0; + chdir(tempDir); + goto begin_install; } else { // Continue on to download file. dmgName = "SecondLife.dmg"; - + } - if (!downloadDMG(dmgName, &temp_dir)) - { - throw 0; - } - } - - if (!doMount(dmgName, deviceNode, temp_dir)) - { - throw 0; - } - - if (!doInstall( app_dir, temp_dir, mount_dir, replacingTarget )) - { - throw 0; - } + + strncat(temp, "/SecondLifeUpdate_XXXXXX", (sizeof(temp) - strlen(temp)) - 1); + if(mkdtemp(temp) == NULL) + { + throw 0; + } + + strncpy(tempDir, temp, sizeof(tempDir)); + temp[sizeof(tempDir) - 1] = '\0'; + + llinfos << "tempDir is " << tempDir << llendl; + err = FSPathMakeRef((UInt8*)tempDir, &tempDirRef, NULL); + + if(err != noErr) + throw 0; + + chdir(tempDir); + + snprintf(temp, sizeof(temp), "SecondLife.dmg"); + + downloadFile = LLFile::fopen(temp, "wb"); /* Flawfinder: ignore */ + if(downloadFile == NULL) + { + throw 0; + } + + { + CURL *curl = curl_easy_init(); + + curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1); + // curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &curl_download_callback); + curl_easy_setopt(curl, CURLOPT_FILE, downloadFile); + curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0); + curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, &curl_progress_callback_func); + curl_easy_setopt(curl, CURLOPT_URL, gUpdateURL); + curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1); + + sendProgress(0, 1, CFSTR("Downloading...")); + + CURLcode result = curl_easy_perform(curl); + + curl_easy_cleanup(curl); + + if(gCancelled) + { + llinfos << "User cancel, bailing out."<< llendl; + throw 0; + } + + if(result != CURLE_OK) + { + llinfos << "Error " << result << " while downloading disk image."<< llendl; + throw 0; + } + + fclose(downloadFile); + downloadFile = NULL; + } + + begin_install: + sendProgress(0, 0, CFSTR("Mounting image...")); + LLFile::mkdir("mnt", 0700); + + // NOTE: we could add -private at the end of this command line to keep the image from showing up in the Finder, + // but if our cleanup fails, this makes it much harder for the user to unmount the image. + std::string mountOutput; + boost::format cmdFormat("hdiutil attach %s -mountpoint mnt"); + cmdFormat % dmgName; + FILE* mounter = popen(cmdFormat.str().c_str(), "r"); /* Flawfinder: ignore */ + + if(mounter == NULL) + { + llinfos << "Failed to mount disk image, exiting."<< llendl; + throw 0; + } + + // We need to scan the output from hdiutil to find the device node it uses to attach the disk image. + // If we don't have this information, we can't detach it later. + while(mounter != NULL) + { + size_t len = fread(temp, 1, sizeof(temp)-1, mounter); + temp[len] = 0; + mountOutput.append(temp); + if(len < sizeof(temp)-1) + { + // End of file or error. + int result = pclose(mounter); + if(result != 0) + { + // NOTE: We used to abort here, but pclose() started returning + // -1, possibly when the size of the DMG passed a certain point + llinfos << "Unexpected result closing pipe: " << result << llendl; + } + mounter = NULL; + } + } + + if(!mountOutput.empty()) + { + const char *s = mountOutput.c_str(); + const char *prefix = "/dev/"; + char *sub = strstr(s, prefix); + + if(sub != NULL) + { + sub += strlen(prefix); /* Flawfinder: ignore */ + sscanf(sub, "%1023s", deviceNode); /* Flawfinder: ignore */ + } + } + + if(deviceNode[0] != 0) + { + llinfos << "Disk image attached on /dev/" << deviceNode << llendl; + } + else + { + llinfos << "Disk image device node not found!" << llendl; + throw 0; + } + + // Get an FSRef to the new application on the disk image + FSRef sourceRef; + FSRef mountRef; + snprintf(temp, sizeof(temp), "%s/mnt", tempDir); + + llinfos << "Disk image mount point is: " << temp << llendl; + + err = FSPathMakeRef((UInt8 *)temp, &mountRef, NULL); + if(err != noErr) + { + llinfos << "Couldn't make FSRef to disk image mount point." << llendl; + throw 0; + } + + sendProgress(0, 0, CFSTR("Searching for the app bundle...")); + err = findAppBundleOnDiskImage(&mountRef, &sourceRef); + if(err != noErr) + { + llinfos << "Couldn't find application bundle on mounted disk image." << llendl; + throw 0; + } + else + { + llinfos << "found the bundle." << llendl; + } + + sendProgress(0, 0, CFSTR("Preparing to copy files...")); + + FSRef asideRef; + char aside[MAX_PATH]; /* Flawfinder: ignore */ + + // this will hold the name of the destination target + CFStringRef appNameRef; + + if(replacingTarget) + { + // Get the name of the target we're replacing + HFSUniStr255 appNameUniStr; + err = FSGetCatalogInfo(&targetRef, 0, NULL, &appNameUniStr, NULL, NULL); + if(err != noErr) + throw 0; + appNameRef = FSCreateStringFromHFSUniStr(NULL, &appNameUniStr); + + // Move aside old version (into work directory) + err = FSMoveObject(&targetRef, &tempDirRef, &asideRef); + if(err != noErr) + { + llwarns << "failed to move aside old version (error code " << + err << ")" << llendl; + throw 0; + } + + // Grab the path for later use. + err = FSRefMakePath(&asideRef, (UInt8*)aside, sizeof(aside)); + } + else + { + // Construct the name of the target based on the product name + char appName[MAX_PATH]; /* Flawfinder: ignore */ + snprintf(appName, sizeof(appName), "%s.app", gProductName); + appNameRef = CFStringCreateWithCString(NULL, appName, kCFStringEncodingUTF8); + } + + sendProgress(0, 0, CFSTR("Copying files...")); + + llinfos << "Starting copy..." << llendl; + + // Copy the new version from the disk image to the target location. + err = FSCopyObjectSync( + &sourceRef, + &targetParentRef, + appNameRef, + &targetRef, + kFSFileOperationDefaultOptions); + + // Grab the path for later use. + err = FSRefMakePath(&targetRef, (UInt8*)target, sizeof(target)); + if(err != noErr) + throw 0; + + llinfos << "Copy complete. Target = " << target << llendl; + + if(err != noErr) + { + // Something went wrong during the copy. Attempt to put the old version back and bail. + (void)FSDeleteObject(&targetRef); + if(replacingTarget) + { + (void)FSMoveObject(&asideRef, &targetParentRef, NULL); + } + throw 0; + } + else + { + // The update has succeeded. Clear the cache directory. + + sendProgress(0, 0, CFSTR("Clearing cache...")); + + llinfos << "Clearing cache..." << llendl; + + gDirUtilp->deleteFilesInDir(gDirUtilp->getExpandedFilename(LL_PATH_CACHE,""), "*.*"); + + llinfos << "Clear complete." << llendl; + + } } catch(...) { if(!gCancelled) - gFailure = true; + if(gFailure == noErr) + gFailure = -1; } // Failures from here on out are all non-fatal and not reported. - sendProgress(0, 3, std::string("Cleaning up...")); + sendProgress(0, 3, CFSTR("Cleaning up...")); - setProgress(1, 3); + // Close disk image file if necessary + if(downloadFile != NULL) + { + llinfos << "Closing download file." << llendl; + + fclose(downloadFile); + downloadFile = NULL; + } + + sendProgress(1, 3); // Unmount image if(deviceNode[0] != 0) { @@ -599,61 +1223,35 @@ void* LLMacUpdater::updatethreadproc(void*) system(temp); /* Flawfinder: ignore */ } - setProgress(2, 3); - std::string *trash_str=getUserTrashFolder(); + sendProgress(2, 3); // Move work directory to the trash if(tempDir[0] != 0) { llinfos << "Moving work directory to the trash." << llendl; - - try - { - boost::filesystem::path trash_dir(*trash_str); - boost::filesystem::rename(mount_dir, trash_dir); - } - catch(boost::filesystem::filesystem_error e) - { - llwarns << "Failed to move " << mount_dir.string() << " to " << *trash_str << llendl; - return (NULL); - } + + FSRef trashRef; + OSStatus err = FSMoveObjectToTrashSync(&tempDirRef, &trashRef, 0); + if(err != noErr) { + llwarns << "failed to move files to trash, (error code " << + err << ")" << llendl; + } } - std::string app_name_str = app_dir.string(); - - if(!gCancelled && !gFailure && !app_name_str.empty()) + if(!gCancelled && !gFailure && (target[0] != 0)) { - //SPATTERS todo is there no better way to do this than system calls? llinfos << "Touching application bundle." << llendl; - - std::stringstream touch_str; - touch_str << "touch '" << app_name_str << "'"; - - system(touch_str.str().c_str()); /* Flawfinder: ignore */ + snprintf(temp, sizeof(temp), "touch '%s'", target); + system(temp); /* Flawfinder: ignore */ llinfos << "Launching updated application." << llendl; - - std::stringstream open_str; - - open_str << "open '" << app_name_str << "'"; - system(open_str.str().c_str()); /* Flawfinder: ignore */ + snprintf(temp, sizeof(temp), "open '%s'", target); + system(temp); /* Flawfinder: ignore */ } sendDone(); - return (NULL); + return(NULL); } - -//static -void* LLMacUpdater::sUpdatethreadproc(void* vptr) -{ - if (!sInstance) - { - llerrs << "LLMacUpdater not instantiated before use. Aborting." << llendl; - return (NULL); - } - return sInstance->updatethreadproc(vptr); -} - From a53323f328dc0f81ed7182979ea0c8aefa2ce19d Mon Sep 17 00:00:00 2001 From: Oz Linden Date: Thu, 20 Dec 2012 14:50:42 -0500 Subject: [PATCH 27/32] tag merge of DRTVWR-271 --- .hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags b/.hgtags index 740260312a..9287168a8c 100755 --- a/.hgtags +++ b/.hgtags @@ -380,3 +380,4 @@ c23d734065ed593b2413385aecd8366d8e0ee96b DRTVWR-257 5cba5f39d0a81d659f24ebc4b5efd025a39e3db1 3.4.3-release 9aa1aa9f1fe13c194695a0b8f0af298296241dc2 DRTVWR-260 18c5f76ac07937e0b64bb874edba0d60a28cec56 DRTVWR-244 +2c4011bbc2b15b82198fd8b51f3a9fe765a08c4d DRTVWR-271 From 0baf43730b1390e6349304372c26a4033f45e7f8 Mon Sep 17 00:00:00 2001 From: Oz Linden Date: Thu, 20 Dec 2012 15:34:18 -0500 Subject: [PATCH 28/32] Added tag 3.4.4-beta3 for changeset 2f8a3ef687bc --- .hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags b/.hgtags index 117f00c7c4..feedde1230 100755 --- a/.hgtags +++ b/.hgtags @@ -388,3 +388,4 @@ b418be80903520c492e1173f3afbc4021cad5d07 DRTVWR-255 b634dec987c16e8c9c938e11e52591d9ead8fa9b DRTVWR-270 cd39255bd23330fd30c04105f2811e941d8524fe 3.4.4-beta2 2c4011bbc2b15b82198fd8b51f3a9fe765a08c4d DRTVWR-271 +2f8a3ef687bc55828abcb17ac1ad7cde70536d7e 3.4.4-beta3 From 4364924ee41d343a03329bb41a725ea815184d2e Mon Sep 17 00:00:00 2001 From: Oz Linden Date: Tue, 25 Dec 2012 09:00:42 -0500 Subject: [PATCH 29/32] tag merge of DRTVWR-273 --- .hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags b/.hgtags index b1bd7cf117..db4c8f1189 100755 --- a/.hgtags +++ b/.hgtags @@ -385,3 +385,4 @@ daca610d840625b5bebb966a57cb49581852c417 DRTVWR-265 0a2ca6546b499239afeb66d17b2fadbcdbe36ab1 3.4.3-release 84fbaf2d4141bd161731430e760949dc787ca206 DRTVWR-244 083d2d36b5bb1c54fc3dd7caac0e7ac381a9cef0 3.4.4-beta1 +35cfd4cf5b895fa776592f2e630e330be7f0604e DRTVWR-273 From 2cba564b24fde367b1ed1d6965e68b5a7da60201 Mon Sep 17 00:00:00 2001 From: Kelly Washington Date: Thu, 3 Jan 2013 09:17:25 -0800 Subject: [PATCH 30/32] MAINT-2184 [crashhunters] new crash in LLUUID::toString Fix dangling references. --- indra/llmessage/llavatarnamecache.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/indra/llmessage/llavatarnamecache.cpp b/indra/llmessage/llavatarnamecache.cpp index 700525e1fa..a6e2c89ba4 100644 --- a/indra/llmessage/llavatarnamecache.cpp +++ b/indra/llmessage/llavatarnamecache.cpp @@ -348,7 +348,7 @@ void LLAvatarNameCache::requestNamesViaCapability() while(!sAskQueue.empty()) { it = sAskQueue.begin(); - const LLUUID& agent_id = *it; + LLUUID agent_id = *it; sAskQueue.erase(it); if (url.empty()) @@ -416,7 +416,7 @@ void LLAvatarNameCache::requestNamesViaLegacy() for (S32 requests = 0; !sAskQueue.empty() && requests < MAX_REQUESTS; ++requests) { it = sAskQueue.begin(); - const LLUUID& agent_id = *it; + LLUUID agent_id = *it; sAskQueue.erase(it); // Mark as pending first, just in case the callback is immediately @@ -563,8 +563,7 @@ void LLAvatarNameCache::eraseUnrefreshed() const LLAvatarName& av_name = it->second; if (av_name.mExpires < max_unrefreshed) { - const LLUUID& agent_id = it->first; - LL_DEBUGS("AvNameCache") << agent_id + LL_DEBUGS("AvNameCache") << it->first << " user '" << av_name.mUsername << "' " << "expired " << now - av_name.mExpires << " secs ago" << LL_ENDL; From def472b45cb17dd125f802dc3be85450135537a8 Mon Sep 17 00:00:00 2001 From: Oz Linden Date: Thu, 3 Jan 2013 18:12:29 -0500 Subject: [PATCH 31/32] tag merge of DRTVWR-275 --- .hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags b/.hgtags index bac55e793f..25331b4894 100755 --- a/.hgtags +++ b/.hgtags @@ -390,3 +390,4 @@ cd39255bd23330fd30c04105f2811e941d8524fe 3.4.4-beta2 2c4011bbc2b15b82198fd8b51f3a9fe765a08c4d DRTVWR-271 2f8a3ef687bc55828abcb17ac1ad7cde70536d7e 3.4.4-beta3 35cfd4cf5b895fa776592f2e630e330be7f0604e DRTVWR-273 +c374035d459af3c03dea2dd90880dfc25de64706 DRTVWR-275 From fde976cf2bf9740dcd821ad37f0747beaabe34dd Mon Sep 17 00:00:00 2001 From: Oz Linden Date: Fri, 4 Jan 2013 14:09:03 -0500 Subject: [PATCH 32/32] Added tag 3.4.4-beta4 for changeset 05d9f1dd7a95 --- .hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags b/.hgtags index 25331b4894..cde3886212 100755 --- a/.hgtags +++ b/.hgtags @@ -391,3 +391,4 @@ cd39255bd23330fd30c04105f2811e941d8524fe 3.4.4-beta2 2f8a3ef687bc55828abcb17ac1ad7cde70536d7e 3.4.4-beta3 35cfd4cf5b895fa776592f2e630e330be7f0604e DRTVWR-273 c374035d459af3c03dea2dd90880dfc25de64706 DRTVWR-275 +05d9f1dd7a954069af2a33abedb7713fa36a04cb 3.4.4-beta4