Commits

obscurestar committed 6726ce7

Mac updater changes ported from another branch.

Comments (0)

Files changed (8)

indra/mac_updater/AutoUpdater.xib

+<?xml version="1.0" encoding="UTF-8"?>
+<archive type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="8.00">
+	<data>
+		<int key="IBDocument.SystemTarget">1070</int>
+		<string key="IBDocument.SystemVersion">11G63</string>
+		<string key="IBDocument.InterfaceBuilderVersion">2182</string>
+		<string key="IBDocument.AppKitVersion">1138.51</string>
+		<string key="IBDocument.HIToolboxVersion">569.00</string>
+		<object class="NSMutableDictionary" key="IBDocument.PluginVersions">
+			<string key="NS.key.0">com.apple.InterfaceBuilder.CocoaPlugin</string>
+			<string key="NS.object.0">2182</string>
+		</object>
+		<array key="IBDocument.IntegratedClassDependencies">
+			<string>NSTextField</string>
+			<string>NSView</string>
+			<string>NSWindowTemplate</string>
+			<string>NSProgressIndicator</string>
+			<string>NSCustomObject</string>
+			<string>IBNSLayoutConstraint</string>
+			<string>NSButtonCell</string>
+			<string>NSButton</string>
+			<string>NSUserDefaultsController</string>
+			<string>NSTextFieldCell</string>
+		</array>
+		<array key="IBDocument.PluginDependencies">
+			<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+		</array>
+		<object class="NSMutableDictionary" key="IBDocument.Metadata">
+			<string key="NS.key.0">PluginDependencyRecalculationVersion</string>
+			<integer value="1" key="NS.object.0"/>
+		</object>
+		<array class="NSMutableArray" key="IBDocument.RootObjects" id="1000">
+			<object class="NSCustomObject" id="1001">
+				<string key="NSClassName">NSObject</string>
+			</object>
+			<object class="NSCustomObject" id="1003">
+				<string key="NSClassName">FirstResponder</string>
+			</object>
+			<object class="NSCustomObject" id="1004">
+				<string key="NSClassName">NSApplication</string>
+			</object>
+			<object class="NSWindowTemplate" id="1005">
+				<int key="NSWindowStyleMask">15</int>
+				<int key="NSWindowBacking">2</int>
+				<string key="NSWindowRect">{{196, 240}, {402, 120}}</string>
+				<int key="NSWTFlags">544735232</int>
+				<string key="NSWindowTitle">Window</string>
+				<string key="NSWindowClass">NSWindow</string>
+				<nil key="NSViewClass"/>
+				<nil key="NSUserInterfaceItemIdentifier"/>
+				<object class="NSView" key="NSWindowView" id="1006">
+					<reference key="NSNextResponder"/>
+					<int key="NSvFlags">256</int>
+					<array class="NSMutableArray" key="NSSubviews">
+						<object class="NSTextField" id="269124353">
+							<reference key="NSNextResponder" ref="1006"/>
+							<int key="NSvFlags">268</int>
+							<string key="NSFrame">{{17, 83}, {79, 17}}</string>
+							<reference key="NSSuperview" ref="1006"/>
+							<reference key="NSWindow"/>
+							<reference key="NSNextKeyView" ref="730867742"/>
+							<string key="NSReuseIdentifierKey">_NS:1505</string>
+							<bool key="NSEnabled">YES</bool>
+							<object class="NSTextFieldCell" key="NSCell" id="702170046">
+								<int key="NSCellFlags">68288064</int>
+								<int key="NSCellFlags2">272630784</int>
+								<string key="NSContents">Initalizing...</string>
+								<object class="NSFont" key="NSSupport">
+									<string key="NSName">LucidaGrande</string>
+									<double key="NSSize">13</double>
+									<int key="NSfFlags">1044</int>
+								</object>
+								<string key="NSCellIdentifier">_NS:1505</string>
+								<reference key="NSControlView" ref="269124353"/>
+								<object class="NSColor" key="NSBackgroundColor">
+									<int key="NSColorSpace">6</int>
+									<string key="NSCatalogName">System</string>
+									<string key="NSColorName">controlColor</string>
+									<object class="NSColor" key="NSColor">
+										<int key="NSColorSpace">3</int>
+										<bytes key="NSWhite">MC42NjY2NjY2NjY3AA</bytes>
+									</object>
+								</object>
+								<object class="NSColor" key="NSTextColor">
+									<int key="NSColorSpace">6</int>
+									<string key="NSCatalogName">System</string>
+									<string key="NSColorName">controlTextColor</string>
+									<object class="NSColor" key="NSColor">
+										<int key="NSColorSpace">3</int>
+										<bytes key="NSWhite">MAA</bytes>
+									</object>
+								</object>
+							</object>
+						</object>
+						<object class="NSProgressIndicator" id="730867742">
+							<reference key="NSNextResponder" ref="1006"/>
+							<int key="NSvFlags">268</int>
+							<string key="NSFrame">{{18, 55}, {366, 20}}</string>
+							<reference key="NSSuperview" ref="1006"/>
+							<reference key="NSWindow"/>
+							<reference key="NSNextKeyView" ref="302149677"/>
+							<string key="NSReuseIdentifierKey">_NS:9</string>
+							<string key="NSHuggingPriority">{250, 250}</string>
+							<int key="NSpiFlags">16399</int>
+							<double key="NSMaxValue">100</double>
+						</object>
+						<object class="NSButton" id="302149677">
+							<reference key="NSNextResponder" ref="1006"/>
+							<int key="NSvFlags">268</int>
+							<string key="NSFrame">{{308, 19}, {74, 19}}</string>
+							<reference key="NSSuperview" ref="1006"/>
+							<reference key="NSWindow"/>
+							<reference key="NSNextKeyView"/>
+							<string key="NSReuseIdentifierKey">_NS:9</string>
+							<bool key="NSEnabled">YES</bool>
+							<object class="NSButtonCell" key="NSCell" id="677565961">
+								<int key="NSCellFlags">-2080244224</int>
+								<int key="NSCellFlags2">134217728</int>
+								<string key="NSContents">Cancel</string>
+								<object class="NSFont" key="NSSupport">
+									<string key="NSName">LucidaGrande</string>
+									<double key="NSSize">12</double>
+									<int key="NSfFlags">16</int>
+								</object>
+								<string key="NSCellIdentifier">_NS:9</string>
+								<reference key="NSControlView" ref="302149677"/>
+								<int key="NSButtonFlags">-2038152961</int>
+								<int key="NSButtonFlags2">164</int>
+								<string key="NSAlternateContents"/>
+								<string key="NSKeyEquivalent"/>
+								<int key="NSPeriodicDelay">400</int>
+								<int key="NSPeriodicInterval">75</int>
+							</object>
+						</object>
+					</array>
+					<string key="NSFrameSize">{402, 120}</string>
+					<reference key="NSSuperview"/>
+					<reference key="NSWindow"/>
+					<reference key="NSNextKeyView" ref="269124353"/>
+				</object>
+				<string key="NSScreenRect">{{0, 0}, {1680, 1028}}</string>
+				<string key="NSMaxSize">{10000000000000, 10000000000000}</string>
+				<bool key="NSWindowIsRestorable">YES</bool>
+			</object>
+			<object class="NSCustomObject" id="492080840">
+				<string key="NSClassName">MacUpdaterAppDelegate</string>
+			</object>
+			<object class="NSUserDefaultsController" id="21008314">
+				<bool key="NSSharedInstance">YES</bool>
+			</object>
+		</array>
+		<object class="IBObjectContainer" key="IBDocument.Objects">
+			<array class="NSMutableArray" key="connectionRecords">
+				<object class="IBConnectionRecord">
+					<object class="IBBindingConnection" key="connection">
+						<string key="label">title: values</string>
+						<reference key="source" ref="1005"/>
+						<reference key="destination" ref="21008314"/>
+						<object class="NSNibBindingConnector" key="connector">
+							<reference key="NSSource" ref="1005"/>
+							<reference key="NSDestination" ref="21008314"/>
+							<string key="NSLabel">title: values</string>
+							<string key="NSBinding">title</string>
+							<string key="NSKeyPath">values</string>
+							<int key="NSNibBindingConnectorVersion">2</int>
+						</object>
+					</object>
+					<int key="connectionID">41</int>
+				</object>
+			</array>
+			<object class="IBMutableOrderedSet" key="objectRecords">
+				<array key="orderedObjects">
+					<object class="IBObjectRecord">
+						<int key="objectID">0</int>
+						<array key="object" id="0"/>
+						<reference key="children" ref="1000"/>
+						<nil key="parent"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">-2</int>
+						<reference key="object" ref="1001"/>
+						<reference key="parent" ref="0"/>
+						<string key="objectName">File's Owner</string>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">-1</int>
+						<reference key="object" ref="1003"/>
+						<reference key="parent" ref="0"/>
+						<string key="objectName">First Responder</string>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">-3</int>
+						<reference key="object" ref="1004"/>
+						<reference key="parent" ref="0"/>
+						<string key="objectName">Application</string>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">1</int>
+						<reference key="object" ref="1005"/>
+						<array class="NSMutableArray" key="children">
+							<reference ref="1006"/>
+						</array>
+						<reference key="parent" ref="0"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">2</int>
+						<reference key="object" ref="1006"/>
+						<array class="NSMutableArray" key="children">
+							<reference ref="269124353"/>
+							<reference ref="730867742"/>
+							<object class="IBNSLayoutConstraint" id="463541650">
+								<reference key="firstItem" ref="269124353"/>
+								<int key="firstAttribute">5</int>
+								<int key="relation">0</int>
+								<reference key="secondItem" ref="1006"/>
+								<int key="secondAttribute">5</int>
+								<float key="multiplier">1</float>
+								<object class="IBNSLayoutSymbolicConstant" key="constant">
+									<double key="value">20</double>
+								</object>
+								<float key="priority">1000</float>
+								<int key="scoringType">8</int>
+								<float key="scoringTypeFloat">29</float>
+								<int key="contentType">3</int>
+								<reference key="containingView" ref="1006"/>
+							</object>
+							<object class="IBNSLayoutConstraint" id="772497817">
+								<reference key="firstItem" ref="730867742"/>
+								<int key="firstAttribute">5</int>
+								<int key="relation">0</int>
+								<reference key="secondItem" ref="1006"/>
+								<int key="secondAttribute">5</int>
+								<float key="multiplier">1</float>
+								<object class="IBNSLayoutSymbolicConstant" key="constant">
+									<double key="value">20</double>
+								</object>
+								<float key="priority">1000</float>
+								<int key="scoringType">8</int>
+								<float key="scoringTypeFloat">29</float>
+								<int key="contentType">3</int>
+								<reference key="containingView" ref="1006"/>
+							</object>
+							<object class="IBNSLayoutConstraint" id="929212820">
+								<reference key="firstItem" ref="1006"/>
+								<int key="firstAttribute">6</int>
+								<int key="relation">0</int>
+								<reference key="secondItem" ref="730867742"/>
+								<int key="secondAttribute">6</int>
+								<float key="multiplier">1</float>
+								<object class="IBNSLayoutSymbolicConstant" key="constant">
+									<double key="value">20</double>
+								</object>
+								<float key="priority">1000</float>
+								<int key="scoringType">8</int>
+								<float key="scoringTypeFloat">29</float>
+								<int key="contentType">3</int>
+								<reference key="containingView" ref="1006"/>
+							</object>
+							<reference ref="302149677"/>
+							<object class="IBNSLayoutConstraint" id="813415053">
+								<reference key="firstItem" ref="1006"/>
+								<int key="firstAttribute">6</int>
+								<int key="relation">0</int>
+								<reference key="secondItem" ref="302149677"/>
+								<int key="secondAttribute">6</int>
+								<float key="multiplier">1</float>
+								<object class="IBNSLayoutSymbolicConstant" key="constant">
+									<double key="value">20</double>
+								</object>
+								<float key="priority">1000</float>
+								<int key="scoringType">8</int>
+								<float key="scoringTypeFloat">29</float>
+								<int key="contentType">3</int>
+								<reference key="containingView" ref="1006"/>
+							</object>
+							<object class="IBNSLayoutConstraint" id="178579609">
+								<reference key="firstItem" ref="269124353"/>
+								<int key="firstAttribute">3</int>
+								<int key="relation">0</int>
+								<reference key="secondItem" ref="1006"/>
+								<int key="secondAttribute">3</int>
+								<float key="multiplier">1</float>
+								<object class="IBNSLayoutSymbolicConstant" key="constant">
+									<double key="value">20</double>
+								</object>
+								<float key="priority">1000</float>
+								<int key="scoringType">8</int>
+								<float key="scoringTypeFloat">29</float>
+								<int key="contentType">3</int>
+								<reference key="containingView" ref="1006"/>
+							</object>
+							<object class="IBNSLayoutConstraint" id="594621082">
+								<reference key="firstItem" ref="730867742"/>
+								<int key="firstAttribute">3</int>
+								<int key="relation">0</int>
+								<reference key="secondItem" ref="269124353"/>
+								<int key="secondAttribute">4</int>
+								<float key="multiplier">1</float>
+								<object class="IBNSLayoutSymbolicConstant" key="constant">
+									<double key="value">8</double>
+								</object>
+								<float key="priority">1000</float>
+								<int key="scoringType">6</int>
+								<float key="scoringTypeFloat">24</float>
+								<int key="contentType">3</int>
+								<reference key="containingView" ref="1006"/>
+							</object>
+							<object class="IBNSLayoutConstraint" id="658067790">
+								<reference key="firstItem" ref="1006"/>
+								<int key="firstAttribute">4</int>
+								<int key="relation">0</int>
+								<reference key="secondItem" ref="302149677"/>
+								<int key="secondAttribute">4</int>
+								<float key="multiplier">1</float>
+								<object class="IBNSLayoutSymbolicConstant" key="constant">
+									<double key="value">20</double>
+								</object>
+								<float key="priority">1000</float>
+								<int key="scoringType">8</int>
+								<float key="scoringTypeFloat">29</float>
+								<int key="contentType">3</int>
+								<reference key="containingView" ref="1006"/>
+							</object>
+						</array>
+						<reference key="parent" ref="1005"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">3</int>
+						<reference key="object" ref="269124353"/>
+						<array class="NSMutableArray" key="children">
+							<reference ref="702170046"/>
+						</array>
+						<reference key="parent" ref="1006"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">4</int>
+						<reference key="object" ref="702170046"/>
+						<reference key="parent" ref="269124353"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">8</int>
+						<reference key="object" ref="730867742"/>
+						<array class="NSMutableArray" key="children"/>
+						<reference key="parent" ref="1006"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">20</int>
+						<reference key="object" ref="463541650"/>
+						<reference key="parent" ref="1006"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">22</int>
+						<reference key="object" ref="302149677"/>
+						<array class="NSMutableArray" key="children">
+							<reference ref="677565961"/>
+							<object class="IBNSLayoutConstraint" id="981064020">
+								<reference key="firstItem" ref="302149677"/>
+								<int key="firstAttribute">7</int>
+								<int key="relation">0</int>
+								<nil key="secondItem"/>
+								<int key="secondAttribute">0</int>
+								<float key="multiplier">1</float>
+								<object class="IBLayoutConstant" key="constant">
+									<double key="value">74</double>
+								</object>
+								<float key="priority">1000</float>
+								<int key="scoringType">3</int>
+								<float key="scoringTypeFloat">9</float>
+								<int key="contentType">1</int>
+								<reference key="containingView" ref="302149677"/>
+							</object>
+						</array>
+						<reference key="parent" ref="1006"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">23</int>
+						<reference key="object" ref="677565961"/>
+						<reference key="parent" ref="302149677"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">31</int>
+						<reference key="object" ref="772497817"/>
+						<reference key="parent" ref="1006"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">32</int>
+						<reference key="object" ref="929212820"/>
+						<reference key="parent" ref="1006"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">35</int>
+						<reference key="object" ref="813415053"/>
+						<reference key="parent" ref="1006"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">36</int>
+						<reference key="object" ref="981064020"/>
+						<reference key="parent" ref="302149677"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">37</int>
+						<reference key="object" ref="178579609"/>
+						<reference key="parent" ref="1006"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">38</int>
+						<reference key="object" ref="594621082"/>
+						<reference key="parent" ref="1006"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">39</int>
+						<reference key="object" ref="658067790"/>
+						<reference key="parent" ref="1006"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">40</int>
+						<reference key="object" ref="21008314"/>
+						<reference key="parent" ref="0"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">42</int>
+						<reference key="object" ref="492080840"/>
+						<reference key="parent" ref="0"/>
+					</object>
+				</array>
+			</object>
+			<dictionary class="NSMutableDictionary" key="flattenedProperties">
+				<string key="-1.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
+				<string key="-2.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
+				<string key="-3.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
+				<string key="1.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
+				<string key="1.IBWindowTemplateEditedContentRect">{{357, 418}, {480, 270}}</string>
+				<integer value="1" key="1.NSWindowTemplate.visibleAtLaunch"/>
+				<array class="NSMutableArray" key="2.IBNSViewMetadataConstraints">
+					<reference ref="463541650"/>
+					<reference ref="772497817"/>
+					<reference ref="929212820"/>
+					<reference ref="813415053"/>
+					<reference ref="178579609"/>
+					<reference ref="594621082"/>
+					<reference ref="658067790"/>
+				</array>
+				<string key="2.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
+				<string key="20.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
+				<array class="NSMutableArray" key="22.IBNSViewMetadataConstraints">
+					<reference ref="981064020"/>
+				</array>
+				<boolean value="NO" key="22.IBNSViewMetadataTranslatesAutoresizingMaskIntoConstraints"/>
+				<string key="22.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
+				<string key="23.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
+				<boolean value="NO" key="3.IBNSViewMetadataTranslatesAutoresizingMaskIntoConstraints"/>
+				<string key="3.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
+				<string key="31.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
+				<string key="32.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
+				<string key="35.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
+				<string key="36.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
+				<string key="37.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
+				<string key="38.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
+				<string key="39.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
+				<string key="4.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
+				<string key="40.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
+				<string key="42.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
+				<boolean value="NO" key="8.IBNSViewMetadataTranslatesAutoresizingMaskIntoConstraints"/>
+				<string key="8.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
+			</dictionary>
+			<dictionary class="NSMutableDictionary" key="unlocalizedProperties"/>
+			<nil key="activeLocalization"/>
+			<dictionary class="NSMutableDictionary" key="localizations"/>
+			<nil key="sourceID"/>
+			<int key="maxID">42</int>
+		</object>
+		<object class="IBClassDescriber" key="IBDocument.Classes">
+			<array class="NSMutableArray" key="referencedPartialClassDescriptions">
+				<object class="IBPartialClassDescription">
+					<string key="className">MacUpdaterAppDelegate</string>
+					<string key="superclassName">NSObject</string>
+					<object class="NSMutableDictionary" key="actions">
+						<string key="NS.key.0">cancel:</string>
+						<string key="NS.object.0">id</string>
+					</object>
+					<object class="NSMutableDictionary" key="actionInfosByName">
+						<string key="NS.key.0">cancel:</string>
+						<object class="IBActionInfo" key="NS.object.0">
+							<string key="name">cancel:</string>
+							<string key="candidateClassName">id</string>
+						</object>
+					</object>
+					<dictionary class="NSMutableDictionary" key="outlets">
+						<string key="mProgressBar">NSProgressIndicator</string>
+						<string key="mProgressText">NSTextField</string>
+						<string key="window">NSWindow</string>
+					</dictionary>
+					<dictionary class="NSMutableDictionary" key="toOneOutletInfosByName">
+						<object class="IBToOneOutletInfo" key="mProgressBar">
+							<string key="name">mProgressBar</string>
+							<string key="candidateClassName">NSProgressIndicator</string>
+						</object>
+						<object class="IBToOneOutletInfo" key="mProgressText">
+							<string key="name">mProgressText</string>
+							<string key="candidateClassName">NSTextField</string>
+						</object>
+						<object class="IBToOneOutletInfo" key="window">
+							<string key="name">window</string>
+							<string key="candidateClassName">NSWindow</string>
+						</object>
+					</dictionary>
+					<object class="IBClassDescriptionSource" key="sourceIdentifier">
+						<string key="majorKey">IBProjectSource</string>
+						<string key="minorKey">./Classes/MacUpdaterAppDelegate.h</string>
+					</object>
+				</object>
+			</array>
+		</object>
+		<int key="IBDocument.localizationMode">0</int>
+		<string key="IBDocument.TargetRuntimeIdentifier">IBCocoaFramework</string>
+		<bool key="IBDocument.PluginDeclaredDependenciesTrackSystemTargetVersion">YES</bool>
+		<int key="IBDocument.defaultPropertyAccessControl">3</int>
+		<bool key="IBDocument.UseAutolayout">YES</bool>
+	</data>
+</archive>

indra/mac_updater/CMakeLists.txt

     )
 
 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
     )
 
 
 
 set(mac_updater_RESOURCE_FILES
-  AutoUpdater.nib/
+  AutoUpdater.nib
   )
 set_source_files_properties(
   ${mac_updater_RESOURCE_FILES}
 
 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}
 
 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
   )

indra/mac_updater/MacUpdater-Info.plist

+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>CFBundleDevelopmentRegion</key>
+	<string>en</string>
+	<key>CFBundleExecutable</key>
+	<string>mac-updater</string>
+	<key>CFBundleGetInfoString</key>
+	<string></string>
+	<key>CFBundleIconFile</key>
+	<string></string>
+	<key>CFBundleIdentifier</key>
+	<string>com.secondlife.indra.autoupdater</string>
+	<key>CFBundleInfoDictionaryVersion</key>
+	<string>6.0</string>
+	<key>CFBundlePackageType</key>
+	<string>APPL</string>
+	<key>CFBundleShortVersionString</key>
+	<string></string>
+	<key>CFBundleSignature</key>
+	<string>????</string>
+	<key>CFBundleVersion</key>
+	<string>1.0.0</string>
+	<key>NSMainNibFile</key>
+	<string>AutoUpdater</string>
+	<key>NSPrincipalClass</key>
+	<string>NSApplication</string>
+</dict>
+</plist>

indra/mac_updater/MacUpdaterAppDelegate.h

+/** 
+ * @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 <Cocoa/Cocoa.h>
+#include <iostream>
+#include "mac_updater.h"
+
+#ifndef LL_MAC_UPDATE_DELEGATE_H
+#define LL_MAC_UPDATE_DELEGATE_H
+
+@interface MacUpdaterAppDelegate : NSObject <NSApplicationDelegate>
+{
+    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

indra/mac_updater/MacUpdaterAppDelegate.mm

+/** 
+ * @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 <string.h>
+#include <boost/filesystem.hpp>
+
+@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

indra/mac_updater/mac_updater.cpp

 #include "linden_common.h"
 
 #include <boost/format.hpp>
+#include <boost/filesystem/operations.hpp>
+#include <boost/filesystem.hpp>
 
 #include <libgen.h>
 #include <sys/types.h>
 #include <unistd.h>
 
 #include <curl/curl.h>
-#include <pthread.h>
 
 #include "llerror.h"
 #include "lltimer.h"
 
 #include "llstring.h"
 
-#include <Carbon/Carbon.h>
-
 #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 <sstream>
 
 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 <url> | -dmg <dmg file> [-name <product_name>] [-program <program_name>]" << 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;
+		}
+		else
+		{
+			mBundleID = new std::string("com.secondlife.indra.viewer");
 		}
 	}
 	
-	if(result == noErr)
+	llinfos << "Starting " << *mProductName << " Updater" << llendl;
+    
+    pthread_create(&updatethread, 
+                   NULL,
+                   &sUpdatethreadproc, 
+                   NULL);
+    
+    
+	void *threadresult;
+    
+	pthread_join(updatethread, &threadresult);
+    
+	if(gCancelled || gFailure)
 	{
-		// Send the event
-		PostEventToQueue(
-			GetMainEventQueue(),
-			evt,
-			kEventPriorityStandard);
-
+        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(result);
+	return;  
 }
 
-OSStatus sendDone(void)
+//SPATTERS TODO this should be moved to lldir_mac.cpp
+const std::string LLMacUpdater::walkParents( unsigned int depth, const std::string& childpath )
 {
-	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);
+    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 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
+//#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,
 {
 	int max = (int)(dltotal / 1024.0);
 	int cur = (int)(dlnow / 1024.0);
-	sendProgress(cur, max);
+	setProgress(cur, max);
 	
 	if(gCancelled)
 		return(1);
 	return(0);
 }
 
-int parse_args(int argc, char **argv)
+bool LLMacUpdater::isApplication(const std::string& app_str)
 {
-	int j;
+    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 ( !exists( dir_path ) ) return false;
 
-	for (j = 1; j < argc; 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->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);
+    
+    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)
+{
+	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)
 	{
-		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];;
-		}
+		llinfos << "Closing download file." << llendl;
+        
+		fclose(downloadFile);
+		downloadFile = NULL;
 	}
 
-	return 0;
+    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;
 }
 
-int main(int argc, char **argv)
+bool LLMacUpdater::moveApplication (const boost::filesystem::path& app_dir, 
+                 const boost::filesystem::path& temp_dir, 
+                 boost::filesystem::path& aside_dir)
 {
-	// 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 <url> | -dmg <dmg file> [-name <product_name>] [-program <program_name>]" << 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."),
-				&params,
-				&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;
+    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 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;
+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;
-}
-
-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)
-	{