#!/usr/bin/perl # warranty # perl script for checking Apple warranty/applecare status # # Copyright © 2008,2011 Thomas A. Fine # # Version 1.1 # # Redistribution is permitted, in whole or in part, for commercial and # non-commercial purposes, provided only that this copyright notice # remains. # $plist="/Library/Preferences/com.apple.RemoteDesktop"; $|=1; while (substr($ARGV[0],0,1) eq "-") { $opt=shift(@ARGV); if ($opt eq "-v") { $verbose=1; } elsif ($opt eq "-d") { $debug=1; $verbose=1; } elsif ($opt eq "-p") { $plist=shift(@ARGV); if ($plist =~ /\.plist$/) { $plist =~ s/.plist$//; } } elsif ($opt eq "-f") { if ($#ARGV == -1) { &usage; exit(1); } $field=shift(@ARGV); if ($n>=1) { &usage; exit(1); } } else { &usage; exit(1); } } if ($#ARGV > 0) { &usage; exit(0); } if ($#ARGV > -1) { $serial=shift(@ARGV); } else { $top = &load_sysprof_xml("SPHardwareDataType"); $tmp=${$top}[0]; # Reformulate the mess we get back from this into a cleaner structure foreach $datatype (@{$top}) { $dtname = ${$datatype}{'_dataType'}; #We want the items array, stuff it into a variable with datatype for name @{$dtname}=@{${$datatype}{'_items'}}; } $serial=${$SPHardwareDataType[0]}{'serial_number'}; # This old non-xml way was simpler, but kept breaking with new OSX releases # because things would pop up that would match the pattern. #open(SP,"system_profiler SPHardwareDataType|"); #while() { # if (/Serial Number/) { # chop; # s/^.*Serial Number.*:\s*//; # $serial=$_; # } #} #close(SP); } if ($debug) { print "Looking up serial number: >>$serial<<\n"; } #getServiceOptions calls #/ServiceOption.do&serialNo= &SOcountry= #getComponents calls #/Warranty.do&serialNumber= &country= &fullCountryName= #This one worked for a long time #$host='selfsolve.apple.com'; #$port=443; #$path='/Warranty.do'; #$path='/Warranty.do?serialNumber=' . $serial . '&country=USA&fullCountryName=United%20States'; $host='selfsolve.apple.com'; $port=443; $path='/warrantyChecker.do'; $path='/warrantyChecker.do?sn=' . $serial; open(CURL,"curl -s -k 'https://$host:$port$path'|"); while() { $page .= $_; } if ($debug) { print $page, "\n"; } $tmp=$page; $tmp =~ s/^[^{]*{//; $tmp =~ s/}[^}]*$//; $tmp =~ s/\\"/%22/g; #simplify parsing by quoting quoted quotes while (length($tmp)) { $tmp =~ s/^"([^"]*)":"([^"]*)",*//; $a=$1; $b=$2; $b =~ s/%22/"/g; #put back the quoted quotes $data{$a}=$b; if ($debug) { print "$a: $b\n"; } } if ($verbose) { if (length($data{PURCHASE_DATE})) { $start=$data{PURCHASE_DATE}; } elsif (length($data{ESTIMATED_START_DT})) { $start=$data{ESTIMATED_START_DT} . " (estimated)"; } if (length($data{COV_END_DATE})) { $end=$data{COV_END_DATE}; } elsif (length($data{ESTIMATED_END_DT})) { $end=$data{ESTIMATED_END_DT} . " (estimated)"; } print "Serial Number: ", $data{'SERIAL_ID'}, "\n"; print "Product Type : ", $data{'PROD_DESCR'}, "\n"; print "Purchase Date: ", $start, "\n"; print "Covered Thru : ", $end, "\n"; print "Coverage Type: ", $data{'HW_COVERAGE_DESC'}, "\n"; print "Can buy APP? : ", $data{'IS_APP_ELIGIBLE'}, "\n"; #print "Description : ", $data{'HARDWAREMESSAGES'}, "\n"; print "Description : ", $data{'wc.desktopcomputers.hardware.pp.long'}, $data{'wc.portablecomputers.hardware.pp.long'}, "\n"; } else { if (length($data{'COV_END_DATE'})) { print $data{'COV_END_DATE'}, "\n"; } else { print "Passed\n"; } } if (length($field)) { if (length($data{'COVERAGE_DATE'})) { system("defaults write '$plist' $field $data{'COVERAGE_DATE'}"); } else { system("defaults write '$plist' $field 'Passed'"); } print STDERR "Note: changes may not show up in Remote Desktop until ARD agent is restarted\n"; } # # END OF MAIN # sub usage { print STDERR <= 0) { $SPtype .= shift(@_) . " "; } my $ret; open(SP,"system_profiler $SPtype -xml|"); while() { if (/^\s*<\?xml /) { next; } if (/^\s*/) { next; } $ret=&makeobj($_); #print "ret=$ret -- $_\n"; } close(SP); return $ret; } sub makeobj { local ($_)=shift(@_); if (/\s*/) { return(&array); } elsif (/\s*/) { return(&dict); } elsif (/\s*/) { my @foo=(); return(\@foo); } elsif (/\s*/) { my $foo="1true"; #actual string, not a reference return($foo); } elsif (/\s*/) { my $foo="0false"; #actual string, not a reference return($foo); } elsif (/\s*/) { chop; s/^\s*//; s/<\/string>.*$//; my $foo=$_; #actual string, not a reference return($foo); } elsif (/\s*/) { chop; s/^\s*//; s/<\/integer>.*$//; my $foo=$_; #actual string, not a reference return($foo); } elsif (/\s*/) { chop; s/^\s*//; s/<\/date>.*$//; my $foo=$_; #actual string, not a reference return($foo); } else { print "Gosh Darnit, what is this? $_\n"; } } sub array { my @ret=(); my $foo; #$arrayref=[]; while($foo=) { if ($foo =~ /^\s*<\/array>/) { last; } push(@ret,&makeobj($foo)); #push(@{$arrayref},&makeobj($foo)); } return(\@ret); #return($arrayref); } sub dict { my %ret=(); my $foo; my $key; while($foo=) { if ($foo =~ /^\s*/) { $key=$foo; chop($key); $key=~ s/^\s*//; $key=~ s/<\/key>.*$//; $foo=; $ret{$key}=&makeobj($foo); } elsif ($foo =~ /^\s*<\/dict>/) { last; } else { print "Gosh darnit! $foo\n"; } } #print " returning ", join(" ",keys(%ret)), "\n"; return(\%ret); }