1#!/usr/bin/ruby
2
3# Copyright (c) 2011-2013 Apple Inc. All Rights Reserved.
4
5# IMPORTANT NOTE: This file is licensed only for use on Apple-branded
6# computers and is subject to the terms and conditions of the Apple Software
7# License Agreement accompanying the package this file is a part of.
8# You may not port this file to another platform without Apple's written consent.
9require 'rubygems'
10require 'cfpropertylist'
11$SERVER_INSTALL_PATH_PREFIX = "/Applications/Server.app/Contents/ServerRoot"
12$SERVER_LIBRARY_PATH = "/Library/Server"
13$SERVER_WEB_CONFIG_DIR = "#{$SERVER_LIBRARY_PATH}/Web/Config/apache2/"
14$ServerAppWebConfigPath = "#{$SERVER_WEB_CONFIG_DIR}httpd_server_app.conf"
15
16# If Server has its own Apache, the desktop launchd.plist does not require modification on promote/demote.
17$ServerAppHTTPDPath = "#{$SERVER_INSTALL_PATH_PREFIX}/usr/sbin/httpd"
18$PromotionAffectsLanchdPlist = !FileTest.exists?($ServerAppHTTPDPath)
19
20class WebPromotion
21	def initialize
22		@launchKey = "org.apache.httpd"
23		@plistFile = "/System/Library/LaunchDaemons/#{@launchKey}.plist"
24		plist = CFPropertyList::List.new(:file => @plistFile)
25		@plistDict = CFPropertyList.native_types(plist.value)
26		@args = @plistDict["ProgramArguments"]
27		@envVarDict = @plistDict["EnvironmentVariables"]
28		if @envVarDict.nil?
29			@envVarDict = {}
30		else
31			@envVarDict = @envVarDict
32		end
33		@apacheWasRunning = apacheIsRunning
34	end
35	def apacheIsRunning
36		`/bin/launchctl list #{@launchKey} >/dev/null 2>&1`
37		return $?.exitstatus == 0
38	end
39	def promote
40		if $PromotionAffectsLanchdPlist
41			if statusString != "SERVER_APP" && FileTest.directory?($SERVER_INSTALL_PATH_PREFIX)
42				`/bin/launchctl unload -w #{@plistFile}` if @apacheWasRunning
43				@args <<"-f"<<$ServerAppWebConfigPath
44				if @envVarDict.nil?
45					@envVarDict = {}
46				end
47				@envVarDict["SERVER_INSTALL_PATH_PREFIX"] = $SERVER_INSTALL_PATH_PREFIX
48				@plistDict["EnvironmentVariables"] = @envVarDict
49				plist = CFPropertyList::List.new
50				plist.value = CFPropertyList.guess(@plistDict)
51				plist.save(@plistFile, CFPropertyList::List::FORMAT_XML)
52				`/usr/bin/plutil -convert xml1 #{@plistFile}`	# Make file human-readable
53				`/bin/launchctl load -w #{@plistFile}` if @apacheWasRunning
54			end
55		end
56		`rm -f /Library/Logs/WebServer`
57		`ln -s /var/log/apache2 /Library/Logs/WebServer`
58	end
59	def demote
60		if $PromotionAffectsLanchdPlist
61			if statusString != "DESKTOP"
62				`/bin/launchctl unload -w #{@plistFile}` if @apacheWasRunning
63				index = @args.index($ServerAppWebConfigPath)
64				if !index.nil?
65					@args.delete_at(index)
66					@args.delete_at(index - 1)
67				end
68				if @envVarDict && !@envVarDict["SERVER_INSTALL_PATH_PREFIX"].nil?
69					@envVarDict.delete("SERVER_INSTALL_PATH_PREFIX")
70				end			
71				if @envVarDict.empty?
72					@plistDict.delete("EnvironmentVariables")
73				else
74					@plistDict["EnvironmentVariables"] = @envVarDict
75				end
76				plist = CFPropertyList::List.new
77				plist.value = CFPropertyList.guess(@plistDict)
78				plist.save(@plistFile, CFPropertyList::List::FORMAT_XML)
79				`/usr/bin/plutil -convert xml1 #{@plistFile}`	# Make file human-readable
80				`/bin/launchctl load -w #{@plistFile}` if @apacheWasRunning
81			end
82		end
83		`rm -f /Library/Logs/WebServer`
84	end
85	def status
86		$stdout.print("#{statusString}\n")
87	end
88	def statusString
89		if $PromotionAffectsLanchdPlist
90			if @args.join(' ').include?("-f #{$ServerAppWebConfigPath}")
91				return "SERVER_APP"
92			else
93				return "DESKTOP"
94			end
95		else
96			if FileTest.exists?("/Library/Logs/WebServer")
97				return "SERVER_APP"
98			else
99				return "DESKTOP"
100			end
101		end
102	end
103end
104
105usage = <<EOU
106Manage promotion of desktop to server or demotion from server to desktop, for web service
107
108usage: #{File.basename($0)} promote|demote|status 
109
110EOU
111
112if Process.euid != 0
113	$stderr.puts(usage)
114	raise "Must run as root"
115end
116if ARGV.count == 0
117	$stderr.puts(usage)
118	raise ArgumentError, "Invalid arg count"
119end
120action = ARGV[0]
121c = WebPromotion.new
122if c.respond_to?(action)
123	c.send(action)
124else
125	$stderr.puts(usage)
126	raise ArgumentError, "#{action}: unknown action"
127end
128
129