diff options
| author | Oz Linden <oz@lindenlab.com> | 2012-12-20 14:50:48 -0500 | 
|---|---|---|
| committer | Oz Linden <oz@lindenlab.com> | 2012-12-20 14:50:48 -0500 | 
| commit | e1497b1b39a11e9e1e41e43b905f644a52073474 (patch) | |
| tree | ded1adea7de71bd4808e767c19b2abc5b128da0f | |
| parent | d8ac1c0f2f05e85a9a85547c0529734fc7d52d30 (diff) | |
| parent | a53323f328dc0f81ed7182979ea0c8aefa2ce19d (diff) | |
merge changes for DRTVWR-271
| -rwxr-xr-x | .hgtags | 1 | ||||
| -rwxr-xr-x | indra/mac_updater/AutoUpdater.nib | bin | 5251 -> 0 bytes | |||
| -rw-r--r-- | indra/mac_updater/AutoUpdater.nib/classes.nib | 4 | ||||
| -rw-r--r-- | indra/mac_updater/AutoUpdater.nib/info.nib | 14 | ||||
| -rw-r--r-- | indra/mac_updater/AutoUpdater.nib/objects.xib | 56 | ||||
| -rw-r--r-- | indra/mac_updater/AutoUpdater.xib | 520 | ||||
| -rw-r--r-- | indra/mac_updater/CMakeLists.txt | 22 | ||||
| -rw-r--r-- | indra/mac_updater/MacUpdater-Info.plist | 30 | ||||
| -rw-r--r-- | indra/mac_updater/MacUpdaterAppDelegate.h | 60 | ||||
| -rw-r--r-- | indra/mac_updater/MacUpdaterAppDelegate.mm | 288 | ||||
| -rw-r--r-- | indra/mac_updater/mac_updater.cpp | 1582 | ||||
| -rw-r--r-- | indra/mac_updater/main.m | 34 | 
12 files changed, 1168 insertions, 1443 deletions
| @@ -387,3 +387,4 @@ b418be80903520c492e1173f3afbc4021cad5d07 DRTVWR-255  083d2d36b5bb1c54fc3dd7caac0e7ac381a9cef0 3.4.4-beta1  b634dec987c16e8c9c938e11e52591d9ead8fa9b DRTVWR-270  cd39255bd23330fd30c04105f2811e941d8524fe 3.4.4-beta2 +2c4011bbc2b15b82198fd8b51f3a9fe765a08c4d DRTVWR-271 diff --git a/indra/mac_updater/AutoUpdater.nib b/indra/mac_updater/AutoUpdater.nibBinary files differ deleted file mode 100755 index 03883e2b86..0000000000 --- a/indra/mac_updater/AutoUpdater.nib +++ /dev/null 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 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<dict> +	<key>IBDocumentLocation</key> +	<string>103 138 356 240 0 0 1280 1002 </string> +	<key>IBFramework Version</key> +	<string>362.0</string> +	<key>IBSystem Version</key> +	<string>7D24</string> +	<key>targetFramework</key> +	<string>IBCarbonFramework</string> +</dict> +</plist> 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 @@ +<?xml version="1.0" standalone="yes"?> +<object class="NSIBObjectData"> +  <string name="targetFramework">IBCarbonFramework</string> +  <object name="rootObject" class="NSCustomObject" id="1"> +    <string name="customClass">NSApplication</string> +  </object> +  <array count="5" name="allObjects"> +    <object class="IBCarbonWindow" id="166"> +      <string name="windowRect">405 222 533 663 </string> +      <string name="title">Second Life Updater</string> +      <object name="rootControl" class="IBCarbonRootControl" id="167"> +        <string name="bounds">0 0 128 441 </string> +        <array count="3" name="subviews"> +          <object class="IBCarbonStaticText" id="181"> +            <string name="bounds">20 20 44 421 </string> +            <ostype name="controlSignature">what</ostype> +            <string name="title">Initializing…</string> +          </object> +          <object class="IBCarbonButton" id="183"> +            <string name="bounds">88 351 108 421 </string> +            <string name="title">Cancel</string> +            <ostype name="command">not!</ostype> +            <int name="buttonType">2</int> +          </object> +          <object class="IBCarbonProgressBar" id="193"> +            <string name="bounds">51 19 70 422 </string> +            <ostype name="controlSignature">prog</ostype> +            <int name="initialValue">50</int> +          </object> +        </array> +      </object> +      <boolean name="isResizable">FALSE</boolean> +      <int name="carbonWindowClass">2</int> +      <int name="themeBrush">3</int> +      <int name="windowPosition">7</int> +    </object> +    <reference idRef="167"/> +    <reference idRef="181"/> +    <reference idRef="183"/> +    <reference idRef="193"/> +  </array> +  <array count="5" name="allParents"> +    <reference idRef="1"/> +    <reference idRef="166"/> +    <reference idRef="167"/> +    <reference idRef="167"/> +    <reference idRef="167"/> +  </array> +  <dictionary count="2" name="nameTable"> +    <string>File's Owner</string> +    <reference idRef="1"/> +    <string>Updater</string> +    <reference idRef="166"/> +  </dictionary> +  <unsigned_int name="nextObjectID">194</unsigned_int> +</object> 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 @@ -<?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> 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/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 @@ -<?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> 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 <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 - - 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 <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); -     -    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/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 <boost/format.hpp> -#include <boost/filesystem/operations.hpp> -#include <boost/filesystem.hpp>  #include <libgen.h>  #include <sys/types.h> @@ -36,6 +34,7 @@  #include <unistd.h>  #include <curl/curl.h> +#include <pthread.h>  #include "llerror.h"  #include "lltimer.h" @@ -44,552 +43,1177 @@  #include "llstring.h" +#include <Carbon/Carbon.h> +  #include "llerrorcontrol.h" -#include "mac_updater.h" -#include <sstream> + +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; +OSStatus setProgress(int cur, int max) +{ +	OSStatus err; +	ControlRef progressBar = NULL; +	ControlID id; + +	id.signature = 'prog'; +	id.id = 0; + +	err = GetControlByID(gWindow, &id, &progressBar); +	if(err == noErr) +	{ +		Boolean indeterminate; +		 +		if(max == 0) +		{ +			indeterminate = true; +			err = SetControlData(progressBar, kControlEntireControl, kControlProgressBarIndeterminateTag, sizeof(Boolean), (Ptr)&indeterminate); +		} +		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); +		} +	} + +	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) +		{ +			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); -LLMacUpdater::LLMacUpdater(): -                mUpdateURL   (NULL), -                mProductName (NULL), -                mBundleID    (NULL), -                mDmgFile     (NULL), -                mMarkerPath  (NULL) +	} +	 +	return(result); +} + +OSStatus dialogHandler(EventHandlerCallRef handler, EventRef event, void *userdata)  { -    sInstance    = this; +	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);  } -void LLMacUpdater::doUpdate() +#if 0 +size_t curl_download_callback(void *data, size_t size, size_t nmemb, +										  void *user_data)  { -  	// We assume that all the logs we're looking for reside on the current drive +	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, +							  double dlnow, +							  double ultotal, +							  double ulnow) +{ +	int max = (int)(dltotal / 1024.0); +	int cur = (int)(dlnow / 1024.0); +	sendProgress(cur, max); +	 +	if(gCancelled) +		return(1); + +	return(0); +} + +int parse_args(int argc, char **argv) +{ +	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; +} + +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); -     -	if ((mUpdateURL == NULL) && (mDmgFile == NULL)) + +	///////////////////////////////////////// +	// +	// 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: " << mUpdateURL << llendl; -		if (mProductName) +		llinfos << "Update url is: " << gUpdateURL << llendl; +		if (gProductName)  		{ -			llinfos << "Product name is: " << *mProductName << llendl; +			llinfos << "Product name is: " << gProductName << llendl;  		}  		else  		{ -			mProductName = new std::string("Second Life"); +			gProductName = "Second Life";  		} -		if (mBundleID) +		if (gBundleID)  		{ -			llinfos << "Bundle ID is: " << *mBundleID << llendl; +			llinfos << "Bundle ID is: " << gBundleID << llendl;  		}  		else  		{ -			mBundleID = new std::string("com.secondlife.indra.viewer"); +			gBundleID = "com.secondlife.indra.viewer";  		}  	} -	llinfos << "Starting " << *mProductName << " Updater" << llendl; -     -    pthread_create(&updatethread,  -                   NULL, -                   &sUpdatethreadproc,  -                   NULL); -     -     +	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) + +	if(!gCancelled && (gFailure != noErr))  	{ -        sendStopAlert(); -         -		if(mMarkerPath != 0) +		// 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(mMarkerPath->c_str()); +			std::ofstream stream(gMarkerPath);  			if(stream) stream << -1;  		}  		exit(-1);  	} else {  		exit(0);  	} + +	if(gWindow != NULL) +	{ +		DisposeWindow(gWindow); +	} -	return;   +	if(nib != NULL) +	{ +		DisposeNibReference(nib); +	} +	 +	return 0;  } -//SPATTERS TODO this should be moved to lldir_mac.cpp -const std::string LLMacUpdater::walkParents( signed int depth, const std::string& childpath ) +bool isDirWritable(FSRef &dir)  { -    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(); -} +	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 */ -//#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 +	err = FSRefMakePath(&dir, (UInt8*)temp, sizeof(temp)); -int curl_progress_callback_func(void *clientp, -							  double dltotal, -							  double dlnow, -							  double ultotal, -							  double ulnow) -{ -	int max = (int)(dltotal / 1024.0); -	int cur = (int)(dlnow / 1024.0); -	setProgress(cur, max); -	 -	if(gCancelled) -		return(1); +	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); +		} +	} -	return(0); -} +#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 -bool LLMacUpdater::isApplication(const std::string& app_str) -{ -    return  !(bool) app_str.compare( app_str.length()-4, 4, ".app"); +	return result;  } -                                      -// 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) + +static std::string HFSUniStr255_to_utf8str(const HFSUniStr255* src)  { -    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 ) -    { -        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; +	llutf16string string16((U16*)&(src->unicode), src->length); +	std::string result = utf16str_to_utf8str(string16); +	return result;  } -bool LLMacUpdater::verifyDirectory(const boost::filesystem::path* directory, bool isParent) +int restoreObject(const char* aside, const char* target, const char* path, const char* object)  { -    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; +	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;  } -                                      -bool LLMacUpdater::getViewerDir(boost::filesystem::path &app_dir) + +// Replace any mention of "Second Life" with the product name. +void filterFile(const char* filename)  { -    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);     +	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 */  } -bool LLMacUpdater::downloadDMG(const std::string& dmgName, boost::filesystem::path* temp_dir) +static bool isFSRefViewerBundle(FSRef *targetRef)  { -	LLFILE *downloadFile = NULL; -	char temp[PATH_MAX] = "";	/* Flawfinder: ignore */ +	bool result = false; +	CFURLRef targetURL = NULL; +	CFBundleRef targetBundle = NULL; +	CFStringRef targetBundleID = NULL; +	CFStringRef sourceBundleID = NULL; -    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) +	targetURL = CFURLCreateFromFSRef(NULL, targetRef); + +	if(targetURL == NULL)  	{ -		llinfos << "Closing download file." << llendl; -         -		fclose(downloadFile); -		downloadFile = NULL; +		llinfos << "Error creating target URL." << llendl;  	} - -    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; +	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;  } -bool LLMacUpdater::moveApplication (const boost::filesystem::path& app_dir,  -                 const boost::filesystem::path& temp_dir,  -                 boost::filesystem::path& aside_dir) +// 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)  { -    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; -} +	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; +						} -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; +					} +				} +			} +		} +		while(!err); +		 +		llinfos << "closing the iterator" << llendl; +		 +		FSCloseIterator(iterator); +		 +		llinfos << "closed" << llendl; +	} +	 +	if(!err && !found) +		err = fnfErr; +		 +	return err;  } -void* LLMacUpdater::updatethreadproc(void*) +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)) -        { - - -            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; -        }     +	{ +		// 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(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); -} - 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 <Cocoa/Cocoa.h> - -int main(int argc, char *argv[]) -{ -    int retVal = NSApplicationMain(argc, (const char **)argv); - -    return retVal; -} | 
