diff --git a/AdobeHDS.php b/AdobeHDS.php index 3b779f5..83d8411 100644 --- a/AdobeHDS.php +++ b/AdobeHDS.php @@ -74,9 +74,9 @@ function displayHelp() { LogInfo("You can use script with following switches:\n"); foreach (self::$ACCEPTED[0] as $key => $value) - LogInfo(sprintf(" --%-18s%s", $key, $value)); + LogInfo(sprintf(" --%-17s %s", $key, $value)); foreach (self::$ACCEPTED[1] as $key => $value) - LogInfo(sprintf(" --%-9s%-9s%s", $key, " [param]", $value)); + LogInfo(sprintf(" --%-9s%-8s %s", $key, " [param]", $value)); } function error($msg) @@ -103,7 +103,7 @@ class cURL function cURL($cookies = true, $cookie = 'Cookies.txt', $compression = 'gzip', $proxy = '') { $this->headers = $this->headers(); - $this->user_agent = 'Mozilla/5.0 (Windows NT 5.1; rv:20.0) Gecko/20100101 Firefox/20.0'; + $this->user_agent = 'Mozilla/5.0 (Windows NT 5.1; rv:23.0) Gecko/20100101 Firefox/23.0'; $this->compression = $compression; $this->cookies = $cookies; if ($this->cookies == true) @@ -450,11 +450,8 @@ function ParseManifest($cc, $parentManifest) $bitrate = $count++; $entry =& $childManifests[$bitrate]; $entry['bitrate'] = $bitrate; - $href = GetString($childManifest['href']); - if (!isHttpUrl($href)) - $href = JoinUrl($baseUrl, $href); - $entry['url'] = NormalizePath($href); - $entry['xml'] = $this->GetManifest($cc, $entry['url']); + $entry['url'] = AbsoluteUrl($baseUrl, GetString($childManifest['href'])); + $entry['xml'] = $this->GetManifest($cc, $entry['url']); } unset($entry, $childManifest); } @@ -511,10 +508,9 @@ function ParseManifest($cc, $parentManifest) $bootstrap = $xml->xpath("/ns:manifest/ns:bootstrapInfo"); if (isset($bootstrap[0]['url'])) { - $bootstrapUrl = GetString($bootstrap[0]['url']); - if (!isHttpUrl($bootstrapUrl)) - $bootstrapUrl = JoinUrl($mediaEntry['baseUrl'], $bootstrapUrl); - $mediaEntry['bootstrapUrl'] = NormalizePath($bootstrapUrl) . $this->auth; + $mediaEntry['bootstrapUrl'] = AbsoluteUrl($mediaEntry['baseUrl'], GetString($bootstrap[0]['url'])); + if (strpos($mediaEntry['bootstrapUrl'], '?') === false) + $mediaEntry['bootstrapUrl'] .= $this->auth; } else $mediaEntry['bootstrap'] = base64_decode(GetString($bootstrap[0])); @@ -581,29 +577,36 @@ function ParseManifest($cc, $parentManifest) if (isset($this->media['bootstrapUrl'])) { $this->bootstrapUrl = $this->media['bootstrapUrl']; - if ($cc->get($this->bootstrapUrl) != 200) - LogError("Failed to get bootstrap info"); - $bootstrapInfo = $cc->response; + $this->UpdateBootstrapInfo($cc, $this->bootstrapUrl); } else + { $bootstrapInfo = $this->media['bootstrap']; - ReadBoxHeader($bootstrapInfo, $pos, $boxType, $boxSize); - if ($boxType == "abst") - $this->ParseBootstrapBox($bootstrapInfo, $pos); - else - LogError("Failed to parse bootstrap info"); + ReadBoxHeader($bootstrapInfo, $pos, $boxType, $boxSize); + if ($boxType == "abst") + $this->ParseBootstrapBox($bootstrapInfo, $pos); + else + LogError("Failed to parse bootstrap info"); + } } function UpdateBootstrapInfo($cc, $bootstrapUrl) { $fragNum = $this->fragCount; $retries = 0; + + // Backup original headers and add no-cache directive for fresh bootstrap info + $headers = $cc->headers; + $cc->headers[] = "Cache-Control: no-cache"; + $cc->headers[] = "Pragma: no-cache"; + while (($fragNum == $this->fragCount) and ($retries < 30)) { $bootstrapPos = 0; LogDebug("Updating bootstrap info, Available fragments: " . $this->fragCount); - if ($cc->get($bootstrapUrl) != 200) - LogError("Failed to refresh bootstrap info"); + $status = $cc->get($bootstrapUrl); + if ($status != 200) + LogError("Failed to refresh bootstrap info, Status: " . $status); $bootstrapInfo = $cc->response; ReadBoxHeader($bootstrapInfo, $bootstrapPos, $boxType, $boxSize); if ($boxType == "abst") @@ -617,6 +620,9 @@ function UpdateBootstrapInfo($cc, $bootstrapUrl) usleep(4000000); } } + + // Restore original headers + $cc->headers = $headers; } function ParseBootstrapBox($bootstrapInfo, $pos) @@ -761,10 +767,13 @@ function ParseSegAndFragTable() $this->fragCount += $current['fragmentsPerSegment']; $prev = $current; } - if ($this->fragCount > 0) + if (!($this->fragCount & 0x80000000)) $this->fragCount += $firstFragment['firstFragment'] - 1; - else + if ($this->fragCount & 0x80000000) + { + $this->fragCount = 0; $invalidFragCount = true; + } if ($this->fragCount < $lastFragment['firstFragment']) $this->fragCount = $lastFragment['firstFragment']; @@ -854,11 +863,7 @@ function DownloadFragments($cc, $manifest, $opt = array()) if ($fragNum >= $this->fragCount) LogError("No fragment available for downloading"); - if (isHttpUrl($this->media['url'])) - $this->fragUrl = $this->media['url']; - else - $this->fragUrl = JoinUrl($this->baseUrl, $this->media['url']); - $this->fragUrl = NormalizePath($this->fragUrl); + $this->fragUrl = AbsoluteUrl($this->baseUrl, $this->media['url']); LogDebug("Base Fragment Url:\n" . $this->fragUrl . "\n"); LogDebug("Downloading Fragments:\n"); @@ -1435,6 +1440,13 @@ function WriteFlvTimestamp(&$frag, $fragPos, $packetTS) WriteByte($frag, $fragPos + 7, ($packetTS & 0xFF000000) >> 24); } + function AbsoluteUrl($baseUrl, $url) + { + if (!isHttpUrl($url)) + $url = JoinUrl($baseUrl, $url); + return NormalizePath($url); + } + function GetString($object) { return trim(strval($object)); @@ -1442,18 +1454,12 @@ function GetString($object) function isHttpUrl($url) { - if (strncasecmp($url, "http", 4) == 0) - return true; - else - return false; + return (strncasecmp($url, "http", 4) == 0) ? true : false; } function isRtmpUrl($url) { - if (preg_match('/^rtm(p|pe|pt|pte|ps|pts|fp):\/\//i', $url)) - return true; - else - return false; + return (preg_match('/^rtm(p|pe|pt|pte|ps|pts|fp):\/\//i', $url)) ? true : false; } function JoinUrl($firstUrl, $secondUrl) @@ -1855,9 +1861,8 @@ function value_in_array_field($needle, $needle_field, $value_field, $haystack, $ // Download fragments when manifest is available if ($manifest) { - if (!isHttpUrl($manifest)) - $manifest = "http://" . $manifest; - $opt = array( + $manifest = AbsoluteUrl("http://", $manifest); + $opt = array( 'start' => $start, 'tDuration' => $duration, 'filesize' => $filesize diff --git a/WeebTV.php b/WeebTV.php index 411d7fa..adebfe9 100644 --- a/WeebTV.php +++ b/WeebTV.php @@ -90,7 +90,7 @@ class cURL function cURL($cookies = true, $cookie = 'Cookies.txt', $compression = 'gzip', $proxy = '') { $this->headers = $this->headers(); - $this->user_agent = 'Mozilla/5.0 (Windows NT 5.1; rv:21.0) Gecko/20100101 Firefox/21.0'; + $this->user_agent = 'Mozilla/5.0 (Windows NT 5.1; rv:25.0) Gecko/20100101 Firefox/25.0'; $this->compression = $compression; $this->cookies = $cookies; if ($this->cookies == true) @@ -235,7 +235,7 @@ function Display($items, $format, $columns) if ($cli->getParam('list')) { foreach ($items as $name => $url) - printf("%-25.25s = %s\n", preg_replace('/=/', '-', $name), $url); + printf("%-25.25s = %s" . PHP_EOL, preg_replace('/=/', '-', $name), $url); exit(0); } @@ -260,11 +260,11 @@ function Display($items, $format, $columns) printf($format, $cell, KeyName($items, $cell - 1)); } } - printf("\n\n"); + printf(PHP_EOL . PHP_EOL); } } - function GetResponse($cc, $url, $data) + function GetApiResponse($cc, $url, $data) { $response = $cc->post($url, $data); $result = explode("\r\n\r\n", $response, 2); @@ -278,6 +278,24 @@ function GetResponse($cc, $url, $data) return $Params; } + function GetHtmlResponse($cc, $url) + { + $retries = 0; + while ($retries < 5) + { + $html = $cc->get($url); + if (preg_match("/NAME=\"robots\"/i", $html)) + { + $cc->get("http://weeb.tv/_Incapsula_Resource?SWHANEDL=807917559759548716,1918358409640862410,9717984079971852691,283468"); + $retries++; + usleep(1000000); + } + else + break; + } + return $html; + } + function KeyName(array $a, $pos) { $temp = array_slice($a, $pos, 1, true); @@ -308,7 +326,7 @@ function LogOut() global $cc, $logged_in; if ($logged_in) { - $cc->get("http://weeb.tv/account/logout"); + GetHtmlResponse($cc, "http://weeb.tv/account/logout"); $logged_in = false; } } @@ -376,16 +394,15 @@ function SafeFileName($filename) function ShowChannel($url, $filename) { global $cc, $cli, $format, $password, $PremiumUser, $quality, $username, $vlc, $windows; - LogInfo("Retrieving html...."); + LogInfo("Retrieving info...."); $cc->headers = $cc->headers(); - $html = $cc->get($url); - preg_match('/flashvars.*?cid[^\d]+?(\d+)/is', $html, $cid); - if (!isset($cid[1])) + $cid = substr($url, strrpos($url, '/') + 1); + if (!$cid) Close("No channel id found"); // Retrieve rtmp stream info - $cc->headers[] = "Referer: http://static2.weeb.tv/static2/player.swf"; - $Params = GetResponse($cc, "http://weeb.tv/api/setPlayer", "cid=$cid[1]&watchTime=0&firstConnect=1&ip=NaN"); + $cc->headers[] = "Referer: http://static.weeb.tv/player.swf"; + $Params = GetApiResponse($cc, "http://weeb.tv/api/setPlayer", "cid=" . $cid . "&watchTime=0&firstConnect=1&ip=NaN"); if (isset($Params[0]) and $Params[0] <= 0) Close("Server refused to send required parameters."); $rtmp = $Params["10"]; @@ -415,7 +432,7 @@ function ShowChannel($url, $filename) // Retrieve authentication token if (!isset($Params["73"])) - $Params = GetResponse($cc, "http://weeb.tv/setplayer", "cid=$cid[2]&watchTime=0&firstConnect=0&ip=NaN"); + $Params = GetApiResponse($cc, "http://weeb.tv/api/setPlayer", "cid=" . $cid . "&watchTime=0&firstConnect=0&ip=NaN"); if (isset($Params["73"])) $token = $Params["73"]; @@ -431,7 +448,7 @@ function ShowChannel($url, $filename) $filename = SafeFileName($filename); if (file_exists($filename . ".flv")) unlink($filename . ".flv"); - $basecmd = 'rtmpdump -r "' . $rtmp . "/" . $playpath . '" -W "http://static2.weeb.tv/static2/player.swf" --weeb "' . $token . "\" --live"; + $basecmd = 'rtmpdump -r "' . $rtmp . "/" . $playpath . '" -W "http://static.weeb.tv/player.swf" --weeb "' . $token . "\" --live"; $command = $basecmd . " | \"$vlc\" --meta-title \"$filename\" -"; if ($cli->getParam('print')) @@ -519,7 +536,7 @@ function ShowHeader() } else { - $html = $cc->get("http://weeb.tv/channels/live"); + $html = GetHtmlResponse($cc, "http://weeb.tv/channels/live"); preg_match('/