| 1 | #!/usr/bin/perl |
|---|
| 2 | |
|---|
| 3 | use strict; |
|---|
| 4 | use Socket; |
|---|
| 5 | use POSIX 'setsid'; |
|---|
| 6 | use XML::XPath; |
|---|
| 7 | |
|---|
| 8 | $| = 1; # can't use stderr as AuthorizationExecuteWithPrivileges only reads stdout. |
|---|
| 9 | |
|---|
| 10 | $ENV{"SHELL"} = "/bin/sh"; |
|---|
| 11 | $ENV{"IFS"} = ""; |
|---|
| 12 | $ENV{"PATH"} = "/bin:/usr/bin:/usr/sbin:/sbin"; |
|---|
| 13 | $ENV{"CDPATH"} = ""; |
|---|
| 14 | |
|---|
| 15 | my $verbose = defined($ENV{VERBOSE}); |
|---|
| 16 | print "GlimmerBlocker installer: uid = $<, euid = $>\n"; |
|---|
| 17 | system("id"); |
|---|
| 18 | $< = 0; |
|---|
| 19 | die "Not running as root" if $<; |
|---|
| 20 | |
|---|
| 21 | my $runningBundlePath = undef; |
|---|
| 22 | my $runningFromSystemPreferences = undef; |
|---|
| 23 | while (@ARGV) { |
|---|
| 24 | my $opt = shift(@ARGV); |
|---|
| 25 | if ($opt eq "-v") { |
|---|
| 26 | $verbose = 1; |
|---|
| 27 | } elsif ($opt eq "-syspref") { |
|---|
| 28 | $runningFromSystemPreferences = 1; |
|---|
| 29 | print "Running from System Preferences.\n"; |
|---|
| 30 | } elsif ($opt eq "-bundle") { |
|---|
| 31 | $_ = shift(@ARGV) || die "Missing -bundle argument."; |
|---|
| 32 | die unless m{^(/.*[^/])\/*$}; |
|---|
| 33 | $runningBundlePath = $1; # untaint. |
|---|
| 34 | } else { |
|---|
| 35 | warn "Unknown arg: $opt\n"; |
|---|
| 36 | } |
|---|
| 37 | } |
|---|
| 38 | die "-bundle <path> not specified." unless defined $runningBundlePath; |
|---|
| 39 | print "Current panel bundle path: $runningBundlePath\n"; |
|---|
| 40 | |
|---|
| 41 | my $panelFilename = "GlimmerBlocker.prefPane"; |
|---|
| 42 | my $panelPath = "/Library/PreferencePanes/$panelFilename"; |
|---|
| 43 | my $authHelper = "$panelPath/Contents/MacOS/AuthHelper"; |
|---|
| 44 | my $settingsPath = "/Library/GlimmerBlocker"; |
|---|
| 45 | my $panelSettingsPath = "$settingsPath/PanelSettings.xml"; |
|---|
| 46 | my $javaSettingsPath = "$settingsPath/JavaSettings.xml"; |
|---|
| 47 | my $lastUpdateCheckPath = "$settingsPath/LastUpdateCheck"; |
|---|
| 48 | my $javaJarDir = "$panelPath/Contents/GlimmerBlockerProxy.app/Contents/Resources/Java"; |
|---|
| 49 | |
|---|
| 50 | sub sys |
|---|
| 51 | { |
|---|
| 52 | my (@cmd) = @_; |
|---|
| 53 | print "# execs: ", join(" ", @cmd), "\n"; |
|---|
| 54 | my $x = system(@cmd); |
|---|
| 55 | return unless $x; |
|---|
| 56 | die "system(".join(" ", @cmd).") failed with exitcode ".($x / 256)."\n"; |
|---|
| 57 | } |
|---|
| 58 | |
|---|
| 59 | sub getHash |
|---|
| 60 | { |
|---|
| 61 | my ($cmd) = @_; |
|---|
| 62 | my %h; |
|---|
| 63 | open(DSCL, "$cmd |") || die; |
|---|
| 64 | while (<DSCL>) { |
|---|
| 65 | chomp; |
|---|
| 66 | if (/^(\S+?):?\s+(\S+)/) { |
|---|
| 67 | $h{$1} = $2; |
|---|
| 68 | } elsif (/^(\S+)/) { |
|---|
| 69 | $h{$1} = 1; |
|---|
| 70 | } else { |
|---|
| 71 | print "Weird value from '$cmd': '$_'\n"; |
|---|
| 72 | } |
|---|
| 73 | } |
|---|
| 74 | close(DSCL); |
|---|
| 75 | return \%h; |
|---|
| 76 | } |
|---|
| 77 | |
|---|
| 78 | sub findUnusedId |
|---|
| 79 | { |
|---|
| 80 | my ($hR) = @_; |
|---|
| 81 | my %id; |
|---|
| 82 | $id{$_} = 1 foreach values %$hR; |
|---|
| 83 | for (my $i = 50; 1; $i++) { |
|---|
| 84 | return $i unless $id{$i}; |
|---|
| 85 | } |
|---|
| 86 | } |
|---|
| 87 | |
|---|
| 88 | sub makeGroup |
|---|
| 89 | { |
|---|
| 90 | my $hR = getHash("dscl . -list /Groups PrimaryGroupID"); |
|---|
| 91 | if ($$hR{_glimmerblocker}) { |
|---|
| 92 | print "Has already _glimmerblocker group\n"; |
|---|
| 93 | return; |
|---|
| 94 | } |
|---|
| 95 | my $id = findUnusedId($hR); |
|---|
| 96 | print "Creates group _glimmerblocker with PrimaryGroupID = $id\n"; |
|---|
| 97 | my $g = "/Groups/_glimmerblocker"; |
|---|
| 98 | sys(("dscl", ".", "-create", $g)); |
|---|
| 99 | sys(("dscl", ".", "-create", $g, "PrimaryGroupID", $id)); |
|---|
| 100 | sys(("dscl", ".", "-append", $g, "RecordName", "glimmerblocker")); |
|---|
| 101 | sys(("dscl", ".", "-create", $g, "RealName", "GlimmerBlocker-proxy")); |
|---|
| 102 | } |
|---|
| 103 | |
|---|
| 104 | sub makeUser |
|---|
| 105 | { |
|---|
| 106 | my $hR = getHash("dscl . -read /Groups/_glimmerblocker PrimaryGroupID"); |
|---|
| 107 | my $groupId = $$hR{PrimaryGroupID} || die "Can't get PrimaryGroupID of _glimmerblocker group"; |
|---|
| 108 | $hR = getHash("dscl . -list /Users UniqueID"); |
|---|
| 109 | if ($$hR{_glimmerblocker}) { |
|---|
| 110 | print "Has already _glimmerblocker user\n"; |
|---|
| 111 | return; |
|---|
| 112 | } |
|---|
| 113 | my $id = findUnusedId($hR); |
|---|
| 114 | print "Creates user _glimmerblocker with UniqueID = $id\n"; |
|---|
| 115 | my $g = "/Users/_glimmerblocker"; |
|---|
| 116 | sys(("dscl", ".", "-create", $g)); |
|---|
| 117 | sys(("dscl", ".", "-create", $g, "UniqueID", $id)); |
|---|
| 118 | sys(("dscl", ".", "-create", $g, "PrimaryGroupID", $groupId)); |
|---|
| 119 | sys(("dscl", ".", "-append", $g, "RecordName", "glimmerblocker")); |
|---|
| 120 | sys(("dscl", ".", "-create", $g, "RealName", "GlimmerBlocker-proxy")); |
|---|
| 121 | sys(("dscl", ".", "-create", $g, "NFSHomeDirectory", "$panelPath/Contents/Resources")); |
|---|
| 122 | sys(("dscl", ".", "-create", $g, "UserShell", "/usr/bin/false")); |
|---|
| 123 | } |
|---|
| 124 | |
|---|
| 125 | sub setPerms |
|---|
| 126 | { |
|---|
| 127 | my ($path, $perm) = @_; |
|---|
| 128 | return unless -e $path; |
|---|
| 129 | if ($perm =~ /\D/) { |
|---|
| 130 | sys(("chmod", sprintf("0%o", $perm), $path)); |
|---|
| 131 | } else { |
|---|
| 132 | printf "chmod 0%o %s\n", $perm, $path if $verbose; |
|---|
| 133 | chmod($perm, $path) || die sprintf("Can't chmod 0%o %s", $perm, $path); |
|---|
| 134 | } |
|---|
| 135 | } |
|---|
| 136 | |
|---|
| 137 | sub createFolder |
|---|
| 138 | { |
|---|
| 139 | my ($path, $owner, $perm, $force) = @_; |
|---|
| 140 | if (-e $path) { |
|---|
| 141 | return unless $force; |
|---|
| 142 | } else { |
|---|
| 143 | mkdir($path, $perm) || die "Can't create dir: $path"; |
|---|
| 144 | sys(("chown", $owner, $path)); |
|---|
| 145 | return; |
|---|
| 146 | } |
|---|
| 147 | if ($force > 1) { |
|---|
| 148 | print STDERR "createFolder.setDeepPerms($owner, $perm, $force): $path\n"; |
|---|
| 149 | system("find '$path' -type d -print0 | xargs -0 chmod ".sprintf("0%o", $perm)); |
|---|
| 150 | system("find '$path' -type f -print0 | xargs -0 chmod ".sprintf("0%o", $perm & 0666)); |
|---|
| 151 | } else { |
|---|
| 152 | print STDERR "createFolder.setPerms($owner, $perm, $force): $path\n"; |
|---|
| 153 | setPerms($path, $perm); |
|---|
| 154 | } |
|---|
| 155 | system("find '$path' -print0 | xargs -0 chown $owner"); |
|---|
| 156 | } |
|---|
| 157 | |
|---|
| 158 | sub prefByXPath |
|---|
| 159 | { |
|---|
| 160 | my ($xpath) = @_; |
|---|
| 161 | if (! -e $panelSettingsPath) { |
|---|
| 162 | print STDERR "prefByXPath: Missing settings file for: '$xpath'\n"; |
|---|
| 163 | return ''; |
|---|
| 164 | } |
|---|
| 165 | my $r = XML::XPath->new(filename => $panelSettingsPath); |
|---|
| 166 | my $nodes = $r->find($xpath); |
|---|
| 167 | unless ($nodes->isa('XML::XPath::NodeSet')) { |
|---|
| 168 | print STDERR "prefByXPath: xpath didn't return nodeset: '$xpath'\n"; |
|---|
| 169 | return ""; |
|---|
| 170 | } |
|---|
| 171 | unless ($nodes->size) { |
|---|
| 172 | print STDERR "prefByXPath: No node matches: '$xpath'\n"; |
|---|
| 173 | return ''; |
|---|
| 174 | } |
|---|
| 175 | my $v = ($nodes->get_nodelist)[0]->string_value; |
|---|
| 176 | print STDERR "prefByXPath: Node with value '$v' matches: '$xpath'\n"; |
|---|
| 177 | return $v; |
|---|
| 178 | } |
|---|
| 179 | |
|---|
| 180 | sub stopLaunchdDaemons |
|---|
| 181 | { |
|---|
| 182 | my $any = 1; |
|---|
| 183 | foreach my $dir (qw( /Library/LaunchAgents /Library/LaunchDaemons )) { |
|---|
| 184 | opendir(DIR, $dir) or next; |
|---|
| 185 | while (defined($_ = readdir(DIR))) { |
|---|
| 186 | next unless /^(org\.glimmerblocker.*\.plist)$/; |
|---|
| 187 | print STDERR "Stops launchd daemon: $1\n"; |
|---|
| 188 | my $path = "$dir/$1"; |
|---|
| 189 | sys(("launchctl", "unload", $path)); |
|---|
| 190 | unlink($path); |
|---|
| 191 | $any = 1; |
|---|
| 192 | } |
|---|
| 193 | closedir(DIR); |
|---|
| 194 | } |
|---|
| 195 | sleep 1 if $any; |
|---|
| 196 | } |
|---|
| 197 | |
|---|
| 198 | sub killSystemPreferencesApplication |
|---|
| 199 | { |
|---|
| 200 | if ($runningFromSystemPreferences) { |
|---|
| 201 | print "Detaches from System Preferences process: pid = $$, ppid = ", getppid(), "\n"; |
|---|
| 202 | if (setsid() < 0) { |
|---|
| 203 | print "Failed to setsid() nr 1\n"; |
|---|
| 204 | } |
|---|
| 205 | exit if fork(); |
|---|
| 206 | if (setsid() < 0) { |
|---|
| 207 | print "Failed to setsid() nr 2\n"; |
|---|
| 208 | } |
|---|
| 209 | exit if fork(); |
|---|
| 210 | if (setsid() < 0) { |
|---|
| 211 | print "Failed to setsid() nr 3\n"; |
|---|
| 212 | } |
|---|
| 213 | sleep 1; |
|---|
| 214 | print "Now detacted from SysPref parent process: pid = $$, ppid = ", getppid(), "\n"; |
|---|
| 215 | # if (fork()) { |
|---|
| 216 | # print "Tells System Preferences to quit using AppleScript (helper pid $$).\n"; |
|---|
| 217 | # system(("osascript", "-e", |
|---|
| 218 | # "tell application \"System Preferences\"\n". |
|---|
| 219 | # " ignoring application responses\n". |
|---|
| 220 | # " quit\n". |
|---|
| 221 | # " end ignoring\n". |
|---|
| 222 | # "end tell\n")); |
|---|
| 223 | # exit; |
|---|
| 224 | # } |
|---|
| 225 | } |
|---|
| 226 | # The updater application should already have quitted it, |
|---|
| 227 | # but make really sure it doesn't override the upgraded PanelPreferences.xml |
|---|
| 228 | unless (open(FH, "ps axo pid=,user=,comm= |")) { |
|---|
| 229 | print "Can't pipe from ps-find-syspanel.\n"; |
|---|
| 230 | return; |
|---|
| 231 | } |
|---|
| 232 | my $num = 0; |
|---|
| 233 | while (<FH>) { |
|---|
| 234 | next unless m!^\s*(\d+)\s+(\S+)\s+/Applications/System Preferences.app/Contents/MacOS!; |
|---|
| 235 | print "Kills System Preferences.app with pid $1 user ($2)\n"; |
|---|
| 236 | #kill 1, $1; |
|---|
| 237 | #sleep 1; |
|---|
| 238 | #kill 9, $1; |
|---|
| 239 | $num++; |
|---|
| 240 | } |
|---|
| 241 | print "Found $num running System Preferences apps.\n"; |
|---|
| 242 | close(FH); |
|---|
| 243 | } |
|---|
| 244 | |
|---|
| 245 | ############################################################################################### |
|---|
| 246 | # |
|---|
| 247 | print "MSG:Stops old proxy.\n"; |
|---|
| 248 | stopLaunchdDaemons(); |
|---|
| 249 | # |
|---|
| 250 | print "MSG:Prepares system.\n"; |
|---|
| 251 | makeGroup(); |
|---|
| 252 | makeUser(); |
|---|
| 253 | # |
|---|
| 254 | createFolder("/Library/Logs", "root:admin", 0775, 0); |
|---|
| 255 | createFolder("/Library/Logs/GlimmerBlocker", "_glimmerblocker:_glimmerblocker", 0755, 2); |
|---|
| 256 | my $log = "/Library/Logs/GlimmerBlocker/GlimmerBlocker.log"; |
|---|
| 257 | unless (-e $log) { |
|---|
| 258 | open(FH, ">$log") && close(FH); |
|---|
| 259 | } |
|---|
| 260 | setPerms($log, 0644); |
|---|
| 261 | system(("chown", "_glimmerblocker:_glimmerblocker", $log)); |
|---|
| 262 | system(("chmod", "666", "/Library/Logs/GlimmerBlocker/Launchd.log")); |
|---|
| 263 | # |
|---|
| 264 | # Can't store preferences in /Library/Preferences because it has drwxrwxr-x |
|---|
| 265 | # so all admin users can change all files at will. |
|---|
| 266 | createFolder($settingsPath, "_glimmerblocker:_glimmerblocker", 0755, 1); |
|---|
| 267 | createFolder("$settingsPath/Filter subscriptions", "_glimmerblocker:_glimmerblocker", 0755, 2); |
|---|
| 268 | createFolder($lastUpdateCheckPath, "_glimmerblocker:admin", 0777, 2); |
|---|
| 269 | setPerms($javaSettingsPath, 0600); |
|---|
| 270 | setPerms($panelSettingsPath, 0644); |
|---|
| 271 | # |
|---|
| 272 | unless ($runningBundlePath eq $panelPath) { |
|---|
| 273 | print "\n"; |
|---|
| 274 | printf "Payload size: %.1f MB.\n", (-s $runningBundlePath) / 1024.0 / 1024.0; |
|---|
| 275 | print "MSG:Relocates Panel bundle.\n"; |
|---|
| 276 | sys(("rsync", "--archive", "--delete-after", "$runningBundlePath/", $panelPath)); |
|---|
| 277 | } |
|---|
| 278 | foreach my $payloadName (qw( GlimmerBlockerProxy GlimmerBlockerUpdater )) { |
|---|
| 279 | my $tar = "$panelPath/$payloadName.tar.gz"; |
|---|
| 280 | next unless -e $tar; |
|---|
| 281 | print "MSG:Installs $payloadName\n"; |
|---|
| 282 | sys(("tar", "zxf", $tar, "-C", "$panelPath/Contents")); |
|---|
| 283 | sys(("rm", $tar)); |
|---|
| 284 | } |
|---|
| 285 | print "MSG:Sets permissions.\n"; |
|---|
| 286 | system(("chown", "-R", "_glimmerblocker:_glimmerblocker", $panelPath)); |
|---|
| 287 | system(("chown", "root:admin", "$panelPath/Contents/MacOS/AuthHelper")); |
|---|
| 288 | system(("chmod", "6555", "$panelPath/Contents/MacOS/AuthHelper")); |
|---|
| 289 | unlink("/Library/GlimmerBlocker/LastUpdateCheck.txt"); # obsolete. |
|---|
| 290 | |
|---|
| 291 | ############################################################################################### |
|---|
| 292 | |
|---|
| 293 | sub needsUpgradeLittleSnitch |
|---|
| 294 | { |
|---|
| 295 | my $path = "/Library/Little Snitch/Little Snitch UIAgent.app/Contents/Info.plist"; |
|---|
| 296 | return 0 unless -s $path; |
|---|
| 297 | open(FH, $path) || return 0; |
|---|
| 298 | $_ = join("", <FH>); |
|---|
| 299 | close(FH); |
|---|
| 300 | return m!<key>CFBundleVersion</key>\s*<string>385</string>! ? 1 : 0; |
|---|
| 301 | } |
|---|
| 302 | |
|---|
| 303 | sub openPreferencesPanel |
|---|
| 304 | { |
|---|
| 305 | print "Opens System Preferences.\n"; |
|---|
| 306 | system(("open", $panelPath)); |
|---|
| 307 | } |
|---|
| 308 | |
|---|
| 309 | sub getPlistPath |
|---|
| 310 | { |
|---|
| 311 | my ($opt) = @_; |
|---|
| 312 | my $r = `$authHelper $opt`; |
|---|
| 313 | unless ($r =~ m{^((/[-.\w]+)+)$}) { |
|---|
| 314 | die "Could not decode AuthHelper $opt output = '$r'"; |
|---|
| 315 | } |
|---|
| 316 | return $1; |
|---|
| 317 | } |
|---|
| 318 | |
|---|
| 319 | sub savePlist |
|---|
| 320 | { |
|---|
| 321 | my ($pathOpt, $contentsOpt) = @_; |
|---|
| 322 | my $plistPath = getPlistPath($pathOpt); |
|---|
| 323 | my $plistContents = `$authHelper $contentsOpt`; |
|---|
| 324 | my $plistDir = $plistPath; |
|---|
| 325 | $plistDir =~ s{/[^/]+$}{}; |
|---|
| 326 | unless (-e $plistDir) { |
|---|
| 327 | sys("mkdir -p $plistDir"); |
|---|
| 328 | sys("chmod 755 $plistDir"); |
|---|
| 329 | system("chown root:wheel $plistDir"); # ok to fail in 10.6 |
|---|
| 330 | } |
|---|
| 331 | sys("chmod u+w $plistDir"); |
|---|
| 332 | open(FH, ">$plistPath") || die "Can't create $plistPath for writing."; |
|---|
| 333 | print FH $plistContents; |
|---|
| 334 | close(FH); |
|---|
| 335 | sys("chown root:wheel $plistPath"); |
|---|
| 336 | sys("chmod 644 $plistPath"); |
|---|
| 337 | sys("launchctl load $plistPath"); |
|---|
| 338 | } |
|---|
| 339 | |
|---|
| 340 | sub startServer |
|---|
| 341 | { |
|---|
| 342 | print "\n"; |
|---|
| 343 | print "Launches java server.\n"; |
|---|
| 344 | print "MSG:Starts proxy server.\n"; |
|---|
| 345 | savePlist("--plist-path", "--plist-contents"); |
|---|
| 346 | } |
|---|
| 347 | |
|---|
| 348 | sub runJavaProgram |
|---|
| 349 | { |
|---|
| 350 | my ($simpleClassPath, $mainClass, $desc) = @_; |
|---|
| 351 | my $cp = ""; |
|---|
| 352 | opendir(DIR, $javaJarDir) || die "Can't readdir ($!): $javaJarDir"; |
|---|
| 353 | while (defined($_ = readdir(DIR))) { |
|---|
| 354 | next unless /^(\w+(-\w+)*\.jar)$/; |
|---|
| 355 | my $fn = $1; |
|---|
| 356 | next if $simpleClassPath && $fn ne "glimmerblocker-server.jar"; |
|---|
| 357 | $cp .= ":" if length($cp); |
|---|
| 358 | my $path = "$javaJarDir/$fn"; |
|---|
| 359 | sys(("file", $path)); |
|---|
| 360 | sys(("md5", $path)); |
|---|
| 361 | $cp .= $path; |
|---|
| 362 | } |
|---|
| 363 | closedir(DIR); |
|---|
| 364 | print "\n"; |
|---|
| 365 | print "Default 'java':\n"; |
|---|
| 366 | system(("java", "-version")); |
|---|
| 367 | print "Running $desc.\n"; |
|---|
| 368 | foreach my $v (("1.6", "1.5", "1.7", "1.8", "1.9", "")) { |
|---|
| 369 | my $java = length($v); |
|---|
| 370 | if (-x "/usr/libexec/java_home" && -e "/System/Library/Java/JavaVirtualMachines") { |
|---|
| 371 | ;# java_home in 10.6.0 doesn't support the -exec parameter. |
|---|
| 372 | $java = "/usr/libexec/java_home"; |
|---|
| 373 | $java .= " -v'$v+'" if length $v; |
|---|
| 374 | $java .= " -exec java"; |
|---|
| 375 | } else { |
|---|
| 376 | $java = length($v) |
|---|
| 377 | ? "/System/Library/Frameworks/JavaVM.framework/Versions/$v/Home/bin/java" |
|---|
| 378 | : "/usr/bin/java"; |
|---|
| 379 | next unless -e $java; |
|---|
| 380 | } |
|---|
| 381 | my $cmd = "time sudo -u _glimmerblocker $java"; |
|---|
| 382 | $cmd .= " -XX:+UseCompressedOops" unless $v eq "1.5"; |
|---|
| 383 | $cmd .= " -Djava.awt.headless=true"; |
|---|
| 384 | $cmd .= " -Dfile.encoding=UTF-8"; |
|---|
| 385 | $cmd .= " -cp '$cp'"; |
|---|
| 386 | $cmd .= " $mainClass"; |
|---|
| 387 | print "Runs: $cmd\n"; |
|---|
| 388 | print "\n"; |
|---|
| 389 | my $x = system($cmd); |
|---|
| 390 | unless ($x) { |
|---|
| 391 | print "Done running $desc.\n"; |
|---|
| 392 | return; |
|---|
| 393 | } |
|---|
| 394 | print "Failed ($x) executing: $cmd\n"; |
|---|
| 395 | } |
|---|
| 396 | print "CAN'T FIND JAVA INSTALLATION.\n"; |
|---|
| 397 | exit(1); |
|---|
| 398 | } |
|---|
| 399 | |
|---|
| 400 | sub upgradePanelPreferences |
|---|
| 401 | { |
|---|
| 402 | runJavaProgram(0, "org.glimmerblocker.proxy.PanelPreferencesUpgrader", "PanelPreferencesUpgrader"); |
|---|
| 403 | } |
|---|
| 404 | |
|---|
| 405 | sub savePanelPrefsXml |
|---|
| 406 | { |
|---|
| 407 | my ($xml) = @_; |
|---|
| 408 | open(FH, ">$panelSettingsPath") || die "Can't create $panelSettingsPath for writing: $!"; |
|---|
| 409 | print FH $xml; |
|---|
| 410 | close(FH); |
|---|
| 411 | sys("chown _glimmerblocker:_glimmerblocker $panelSettingsPath"); |
|---|
| 412 | sys("chmod 644 $panelSettingsPath"); |
|---|
| 413 | } |
|---|
| 414 | |
|---|
| 415 | sub wantsServerToRun |
|---|
| 416 | { |
|---|
| 417 | return 1 if -e getPlistPath("--plist-path"); |
|---|
| 418 | return prefByXPath('prefs/proxy-server/@enabled'); |
|---|
| 419 | } |
|---|
| 420 | |
|---|
| 421 | sub doneInstalling |
|---|
| 422 | { |
|---|
| 423 | unless ($runningBundlePath eq $panelPath) { |
|---|
| 424 | print "\n"; |
|---|
| 425 | print "MSG:Zaps wrongly located bundle.\n"; |
|---|
| 426 | sys(("rm", "-rf", $runningBundlePath)); |
|---|
| 427 | } |
|---|
| 428 | if (prefByXPath('prefs/updater/@check-in-background')) { |
|---|
| 429 | my $beta = prefByXPath('prefs/updater/@use-beta-versions'); |
|---|
| 430 | my $content = $beta ? '--updater-plist-content --beta' : '--updater-plist-content'; |
|---|
| 431 | savePlist("--updater-plist-path", $content); |
|---|
| 432 | } |
|---|
| 433 | sleep 2; # give Java a bit of time to get running. |
|---|
| 434 | openPreferencesPanel(); # if needsUpgradeLittleSnitch() || $runningFromSystemPreferences; |
|---|
| 435 | print "\n"; |
|---|
| 436 | print "Installer done, exits.\n"; |
|---|
| 437 | exit(0); |
|---|
| 438 | } |
|---|
| 439 | |
|---|
| 440 | killSystemPreferencesApplication(); |
|---|
| 441 | sys("ls -ld / /Library /Library/PreferencePanes $panelPath $javaJarDir"); |
|---|
| 442 | print "#\n"; |
|---|
| 443 | print "# OBS: If the following command fails,\n"; |
|---|
| 444 | print " you probably have a permission problem with one of the above directories.\n"; |
|---|
| 445 | print "#\n"; |
|---|
| 446 | sys("sudo -u _glimmerblocker sh -c 'id;pwd;cd $javaJarDir;pwd;ls -l'"); |
|---|
| 447 | |
|---|
| 448 | runJavaProgram(1, "org.glimmerblocker.proxy.TestJava", "SimpleJavaTest"); |
|---|
| 449 | |
|---|
| 450 | if (-e $panelSettingsPath) { |
|---|
| 451 | print "\n"; |
|---|
| 452 | my $run = wantsServerToRun(); |
|---|
| 453 | print "", ($run ? "Wants" : "Does not want"), " server to run.\n"; |
|---|
| 454 | print "MSG:Updates settings.\n"; |
|---|
| 455 | upgradePanelPreferences(); |
|---|
| 456 | openPreferencesPanel() if needsUpgradeLittleSnitch() || $runningFromSystemPreferences; |
|---|
| 457 | print "postflight done of upgrade, has panel-prefs, so just quit\n"; |
|---|
| 458 | if ($run) { |
|---|
| 459 | sleep 2; |
|---|
| 460 | startServer(); |
|---|
| 461 | } |
|---|
| 462 | doneInstalling(); |
|---|
| 463 | } |
|---|
| 464 | |
|---|
| 465 | print "\n"; |
|---|
| 466 | print "Missing panel prefs -> creates initial file\n"; |
|---|
| 467 | print "MSG:Creates initial settings.\n"; |
|---|
| 468 | # initial installation. Create prefs file and launch java server. |
|---|
| 469 | open(FH, "/dev/random") || die "Can't open /dev/random for reading"; |
|---|
| 470 | my $adminKey; |
|---|
| 471 | read(FH, $adminKey, 20); |
|---|
| 472 | $adminKey = unpack("H*", $adminKey); |
|---|
| 473 | my $port = 8228; |
|---|
| 474 | my $xml = <<"XML"; |
|---|
| 475 | <?xml version="1.0" encoding="UTF-8"?> |
|---|
| 476 | <prefs version="0"> |
|---|
| 477 | <filters> |
|---|
| 478 | </filters> |
|---|
| 479 | <proxy-server listen-port="$port" info-admin-key="$adminKey" enabled="1"></proxy-server> |
|---|
| 480 | <suspects show-details="1" enabled="1"/> |
|---|
| 481 | <history enabled="1"/> |
|---|
| 482 | <updater check-in-background="1"/> |
|---|
| 483 | </prefs> |
|---|
| 484 | XML |
|---|
| 485 | savePanelPrefsXml($xml); |
|---|
| 486 | upgradePanelPreferences(); |
|---|
| 487 | sys("sync"); |
|---|
| 488 | # |
|---|
| 489 | startServer(); |
|---|
| 490 | # |
|---|
| 491 | print "\n"; |
|---|
| 492 | print "Synchronizes network proxy settings.\n"; |
|---|
| 493 | print "MSG:Updates 'Network' proxy settings.\n"; |
|---|
| 494 | sys("$panelPath/Contents/MacOS/NetworkSettingsTool $port"); |
|---|
| 495 | # |
|---|
| 496 | # wait for java server to start before we're really done |
|---|
| 497 | # so the user don't get the "proxy not responding" error if he's quick to launch Safari. |
|---|
| 498 | print "\n"; |
|---|
| 499 | print "MSG:Waits for proxy to become ready.\n"; |
|---|
| 500 | my $iaddr = inet_aton("127.0.0.1") || die "Failed creating iaddr"; |
|---|
| 501 | my $paddr = sockaddr_in($port, $iaddr) || die "Failed creating paddr"; |
|---|
| 502 | my $proto = getprotobyname('tcp') || die "Failed getting tcp proto"; |
|---|
| 503 | foreach (1 .. 20) { |
|---|
| 504 | socket(SOCK, PF_INET, SOCK_STREAM, $proto) || die "Failed creating socket"; |
|---|
| 505 | my $ok = connect(SOCK, $paddr); |
|---|
| 506 | close(SOCK); |
|---|
| 507 | if ($ok) { |
|---|
| 508 | print "Java proxy is now responding at localhost:$port\n"; |
|---|
| 509 | last; |
|---|
| 510 | } |
|---|
| 511 | print "Waits for java proxy to respond at localhost:$port\n"; |
|---|
| 512 | sleep 1; |
|---|
| 513 | } |
|---|
| 514 | doneInstalling(); |
|---|
| 515 | # EOF |
|---|