#!ruby # Download iPlayer programmes by spoofing an iPhone # Paul Battley - http://po-ru.com/ require 'net/http' require 'uri' # Used by Safari Mobile IPHONE_UA = 'Mozilla/5.0 (iPhone; U; CPU like Mac OS X; en) AppleWebKit/420+ '+ '(KHTML, like Gecko) Version/3.0 Mobile/1A543a Safari/419.3' # Used by Quicktime QT_UA = 'Apple iPhone v1.1.3 CoreMedia v1.0.0.4A93' if http_proxy = ENV['http_proxy'] proxy_url = URI.parse(http_proxy) HTTP = Net::HTTP::Proxy(proxy_url.host, proxy_url.port) else HTTP = Net::HTTP end DEFAULT_HEADERS = { 'Accept' => '*/*', 'Accept-Language' => 'en', 'Accept-Encoding' => 'gzip, deflate', 'Connection' => 'keep-alive', 'Pragma' => 'no-cache' } class Net::HTTPResponse # Monkey-patch in some 21st-century functionality include Enumerable def cookies inject([]){ |acc, (key, value)| key == 'set-cookie' ? acc << value.split(/;/).first : acc } end def to_hash @to_hash ||= inject({}){ |hash, (key, value)| hash[key] = value hash } end end def http_get(location, headers={}, &blk) url = URI.parse(location) http = HTTP.new(url.host, url.port) path = url.path if url.query path << '?' << url.query end http.request_get(path, DEFAULT_HEADERS.merge(headers), &blk) end page_url = ARGV[0] unless page_url puts "Download DRM-free videos from the BBC iPlayer, courtesy of their iPhone interface." puts puts "Usage: #{$0} URL" puts "Where URL is the iPlayer viewing page." exit 1 end # Get the actual programme page response = http_get( page_url, 'User-Agent' => IPHONE_UA ) cookies = response.cookies.join('; ') html = response.body # The only information we really need is the pid pid = html[/\bpid[ \t]+:[ \t]+'([a-z0-9]+)'/, 1] title = ( html[%r!