/** * BeebhackDownloader * Class for downloading iPhone video off BBC iPlayer * @author Iain Wallace http://strawp.net */ import java.io.DataOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; import java.net.URLConnection; import java.util.Random; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import org.apache.http.Header; import org.apache.http.HttpResponse; import org.apache.http.client.ClientProtocolException; import org.apache.http.client.HttpClient; import org.apache.http.client.methods.HttpGet; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.util.EntityUtils; import org.w3c.dom.Document; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.xml.sax.SAXException; public class Downloader { public String coreMediaUserAgent = "Apple iPhone v1.1.1 CoreMedia v1.0.0.3A110a"; public String iPhoneMediaSelectorPrefix = "http://www.bbc.co.uk/mediaselector/3/auth/iplayer_streaming_http_mp4"; public String versionMediaSelectorPrefix = "http://www.bbc.co.uk/mediaselector/4/mtis/stream/"; public String safariUserAgent = "Mozilla/5.0 (iPhone; U; CPU like Mac OS X; en) AppleWebKit/420.1 (KHTML, like Gecko) Version/3.0 Mobile/3A110a Safari/419.3"; public String[] versionNames = "default original signed audiodescribed opensubtitled shortened lengthened other".split(" "); public String playlistPrefix = "http://www.bbc.co.uk/iplayer/playlist/"; public String metaDataPrefix = "http://www.bbc.co.uk/iplayer/metafiles/episode/"; public Boolean debug = true; private HttpClient client; private String downloadDestination = ""; private String filename; private long blocksize = 524288; // 4194304; Downloader(){ this.client = new DefaultHttpClient(); this.client.getParams().setBooleanParameter("http.protocol.handle-redirects", false); } /** * Download to a specific folder * @param pid * @param dest * @return */ public Boolean downloadByPid( String pid, String dest ){ this.downloadDestination = dest; return this.downloadByPid(pid); } /** * Pass a programme ID and download the file, working out the details automatically * @param pid * @return */ public Boolean downloadByPid( String pid ){ // Get stream url String streamUrl = this.getIphoneStreamUrl(pid); if( streamUrl == null ){ System.out.println("streamUrl is null"); return false; } return this.downloadIphoneStream( streamUrl, this.filename ); } /** * Work out the stream URL of a programme from the programme ID (pid) * http://download.iplayer.bbc.co.uk/iplayer_streaming_http_mp4/5291651394040737632.mp4?token=iVXcx557SN8malAhHh1%2BZ%2FVk4n35UKfH4qGsJzA1oF%2BhC2K%2Bq9ok8Ky3z%2BkeoBmwfs9pJvH3SUKU%0A8c7z%2BxIG5tNEF2xNIl6%2F%2Bdwl3brQkb6ctOKggoHosrDAVwp5ZPqGNBdQKg%3D%3D%0A * @param pid * @return * @throws IOException * @throws ClientProtocolException */ public String getIphoneStreamUrl( String pid ) { String url = this.getValidVersionUrl(pid); if( url == null ) return null; if(this.debug) System.out.println("Getting " + url ); HttpGet request = new HttpGet(url); request.addHeader("User-Agent", this.coreMediaUserAgent ); request.addHeader("Accept", "*/*"); request.addHeader("Range", "bytes=0-1"); HttpResponse response; try { response = this.client.execute(request); } catch (ClientProtocolException e) { // TODO Auto-generated catch block e.printStackTrace(); System.out.println("Error: " + e.getLocalizedMessage()); return null; } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); System.out.println("Error: " + e.getLocalizedMessage()); return null; } if(this.debug) System.out.println("Request completed"); Header [] headers = response.getAllHeaders(); for( int i=0; i 0 ){ String strTitle = title.item(0).getTextContent(); strTitle = strTitle.replaceAll(":", " -" ); strTitle = strTitle.replaceAll("/[^-a-zA-Z0-9]/", ""); this.filename = strTitle.trim() + ".mov"; } NodeList nodes = doc.getElementsByTagName("item"); int versionCount = nodes.getLength(); if( versionCount == 0 ) return null; String[] aPids = new String[versionCount]; for(int i=0; i