Recent Tweets

    Elsewhere

     

    July 2008
    S M T W T F S
    « Jun   Aug »
     12345
    6789101112
    13141516171819
    20212223242526
    2728293031  

    Archives

    AT&T Store Apple iPhone 3G preorder status checking

    I have pre-ordered Apple iPhone 3G from my neighboring AT&T store last Sunday (Jul 20). I have done this as purchasing from the Apple Store wouldn’t let me to apply my FAN discounts on the plan. Applying it latter would reflect only after a couple of billing cycles. Also I don’t wanna get into the crazy line. I didn’t join the true Apple cult yet. I was just curious about the status of the pre-order and I checked the status online and found that the status query mechanism can be exploited to post automated queries. Here is a small ruby script that I wrote to check bulk statuses. This would also give you a clue on where you are in preorder line.

    This script is intended to be used to check your order status only. Please note that this comes with absolutely no warranty and I can’t be held responsible for the misuse of the script. AT&T may change their query mechanism if they know about this exploit.

    #!/usr/bin/env ruby
     
    require 'rubygems'
    require 'open-uri'
    require 'openssl'
     
    # FIXME (2008-07-24, praveen): This is nasty. I don't know of any other
    # simpler way to skip SSL certificate verification.
    OpenSSL::SSL::VERIFY_PEER = OpenSSL::SSL::VERIFY_NONE
     
     
    class Order
      attr_reader :order_number, :zip_code, :valid, :canceled, \
      :customer_name, :order_date, :shipped, :ship_date, :ship_carrier, \
      :tracking_number
     
      def initialize order_number, zip_code
        @order_number = order_number
        @zip_code = zip_code
        @valid = false
        @canceled = false
     
        order_status_uri = URI.parse "https://www.wireless.att.com/order_status/\
    order_status_results.jsp?fromwhere=order_status&vMethod=ordernum&\
    vNumber=#{order_number}&ZipCode=#{zip_code}&x=40&y=14"
        order_status = order_status_uri.read
     
        if !order_status.scan("We're sorry, but the information you entered \
    was not recognized by our systems.").to_s.empty?
          @valid = false
          return
        end
        @valid = true
     
        if !order_status.scan("Canceled")[0].to_s.empty?
          @canceled = true
          return
        end
        @canceled = false
     
        @customer_name =
          order_status.scan(/Customer:\s*\w*/).to_s.gsub!(/Customer:\s*/,"")
        @order_date =
          order_status.scan(/Date Ordered:.*/).to_s.gsub!(/Date Ordered:\s*/, "")
        @order_date.gsub!(/\s/, "")
        @shipped =
          order_status.scan(/\<td width="5%".*/)[3].scan(/[01]/).to_s.to_i == 1 ?
        true : false
        if !@shipped
          return
        end
        @ship_date = order_status.scan(/\<td width="6%".*/)[5]
        @ship_date.gsub! /^.*\<p\>/, ""
        @ship_date.gsub! /\<\/p\>.*$/, ""
        @ship_carrier = order_status.scan(/\<td width="6%".*/)[7]
        @ship_carrier.gsub! /^.*\<p\>/, ""
        @ship_carrier.gsub! /\<\/p\>.*$/, ""
        @tracking_number =
          order_status.scan(/\http:\/\/fedex.com\/Tracking\?tracknumbers=\d*/).to_s
        @tracking_number.gsub! /\http:\/\/fedex.com\/Tracking\?tracknumbers=/, ""
      end
     
      def print
        if !@valid
          puts "#{@order_number.ljust(6)} ------------------------ NOT FOUND \
    ------------------------"
          return
        end
        if @canceled
          puts "#{@order_number.ljust(6)} ------------------------ CANCELLED \
    ------------------------"
          return
        end
        if @shipped
          puts "#{@order_number.ljust(6)} #{@customer_name.slice(0..14).ljust(15)} \
    #{@order_date} #{'Yes'.ljust(5)} #{@ship_date} #{@ship_carrier.ljust(6)} \
    #{@tracking_number}"
        else
          puts "#{@order_number.ljust(6)} #{@customer_name.slice(0..14).ljust(15)} \
    #{@order_date} #{'No'.ljust(5)} #{'NA'.ljust(8)} #{'NA'.ljust(6)} \
    #{'NA'.ljust(12)}"
        end
      end
    end
     
    if ARGV.length != 3
      puts "Usage: ./order-status.rb ZIP BEGIN END
     
      ZIP      ZIP code of the AT&T store where the order is placed.
      BEGIN    Order number to begin searching for.
      END      Order number to end searching for.
     
    Example: ./order-status.rb 94025 12000 12100
    "
    else
      puts "Que Order# #{'Name'.ljust(15)} Order Dt Ship? Ship Dt  Carrie Tracking"
      puts "----------------------------------------------------------------------"
      queue = 0
      for order_number in ARGV[1]..ARGV[2]
        o = Order.new order_number, ARGV[0]
        if o.valid and !o.canceled
          queue += 1 if !o.shipped
          display_queue = o.shipped ? "NA" : queue
        else
          display_queue = "NA"
        end
        print "#{display_queue.to_s.ljust(3)} "
        o.print
      end
    end

    Sample output:
    Data is scrambled to protect identity.

    praveen@athena:~/scratch/ruby$ ./order-status.rb [ZIP] XX208 XX250
    ./order-status.rb:9: warning: already initialized constant VERIFY_PEER
    Que Order# Name            Order Dt Ship? Ship Dt  Carrie Tracking
    ----------------------------------------------------------------------
    NA  XX208  ***IVEL         07/15/08 Yes   07/18/08 F      981870058XXX
    1   XX209  ***EPHINE       07/15/08 No    NA       NA     NA          
    2   XX210  ***PBELL        07/15/08 No    NA       NA     NA          
    3   XX211  ***ISSA         07/15/08 No    NA       NA     NA          
    NA  XX212  ------------------------ NOT FOUND ------------------------
    NA  XX213  ***N            07/15/08 Yes   07/18/08 F      981870063XXX
    NA  XX214  ***E            07/15/08 Yes   07/18/08 FDE11  978403293XXX
    4   XX215  ***DIRI         07/15/08 No    NA       NA     NA          
    NA  XX216  ***TT           07/15/08 Yes   07/24/08 F      981871193XXX
    5   XX217  ***E            07/15/08 No    NA       NA     NA          
    6   XX218  ***TT           07/15/08 No    NA       NA     NA          
    7   XX219  ***ESH          07/15/08 No    NA       NA     NA          
    8   XX220  ***D            07/15/08 No    NA       NA     NA          
    9   XX221  ***ECCA         07/15/08 No    NA       NA     NA          
    10  XX222  ***ENIA         07/15/08 No    NA       NA     NA          
    NA  XX223  ***TEH          07/15/08 Yes   07/18/08 F      981870054XXX
    11  XX224  ***TER          07/15/08 No    NA       NA     NA          
    NA  XX225  ***TER          07/15/08 Yes   07/24/08 F      981847797XXX
    NA  XX226  ------------------------ CANCELLED ------------------------
    NA  XX227  ***DA           07/16/08 Yes   07/24/08 FDE51  982002804XXX
    NA  XX228  ------------------------ CANCELLED ------------------------
    NA  XX229  ***HEESH        07/16/08 Yes   07/18/08 F      981846745XXX
    12  XX230  ***ER           07/16/08 No    NA       NA     NA          
    13  XX231  ***A            07/16/08 No    NA       NA     NA          
    14  XX232  ***EL           07/16/08 No    NA       NA     NA          
    15  XX233  ***SWORTH       07/16/08 No    NA       NA     NA          
    16  XX234  ***SWORTH       07/16/08 No    NA       NA     NA          
    17  XX235  ***SWORTH       07/16/08 No    NA       NA     NA          
    18  XX236  ***RGE          07/16/08 No    NA       NA     NA          
    19  XX237  ***AB           07/16/08 No    NA       NA     NA          
    20  XX238  ***QUIEL        07/16/08 No    NA       NA     NA          
    NA  XX239  ***RY           07/16/08 Yes   07/18/08 F      981870059XXX

    PS: The credit also goes to an anonymous guy who wrote a similar script that I came across in a forum (I forgot the exact place). Most of the regexp ideas were shamelessly stolen from his original script. This is my first non-trivial Ruby script. I don’t know much about Ruby. This was a learning script as well. Please bear with newbie mistakes and coding conventions. If you have any comments on the code, I will be more than happy to hear from you.

    Update (2008-07-29): AT&T finally decided to do something about the vulnerability. They are using “Captcha” now. So, this script might not work anymore. However I am pretty close to the head of the queue. I might get my phone in a couple of days or so. So, I don’t worry about this anymore…

    Update (2008-08-02):
    My phone shipped today.

    • Digg
    • del.icio.us
    • Twitter
    • Facebook
    • Google Bookmarks
    • LinkedIn
    • Live
    • Yahoo! Bookmarks
    • Posterous
    • Sphinn
    • Mixx

    Leave a Reply

     

     

     

    You can use these HTML tags

    <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre lang="" line="" escaped="">