public static function getInstance()
 {
     if (!self::$_instance) {
         self::$_instance = new kPlayManifestCacher();
     }
     return self::$_instance;
 }
Esempio n. 2
0
 public function execute()
 {
     KExternalErrors::setResponseErrorCode(KExternalErrors::HTTP_STATUS_NOT_FOUND);
     $this->deliveryAttributes = new DeliveryProfileDynamicAttributes();
     // Parse input parameters
     $this->deliveryAttributes->setSeekFromTime($this->getRequestParameter("seekFrom", -1));
     if ($this->deliveryAttributes->getSeekFromTime() <= 0) {
         $this->deliveryAttributes->setSeekFromTime(-1);
     }
     $this->deliveryAttributes->setClipTo($this->getRequestParameter("clipTo", 0));
     $this->deliveryAttributes->setPlaybackRate($this->getRequestParameter("playbackRate", 0));
     $deliveryCode = $this->getRequestParameter("deliveryCode", null);
     $playbackContext = $this->getRequestParameter("playbackContext", null);
     $this->deliveryAttributes->setMediaProtocol($this->getRequestParameter("protocol", null));
     if (!$this->deliveryAttributes->getMediaProtocol() || $this->deliveryAttributes->getMediaProtocol() === "null") {
         $this->deliveryAttributes->setMediaProtocol(PlaybackProtocol::HTTP);
     }
     $this->deliveryAttributes->setFormat($this->getRequestParameter("format"));
     if (!$this->deliveryAttributes->getFormat()) {
         $this->deliveryAttributes->setFormat(PlaybackProtocol::HTTP);
     }
     if ($this->deliveryAttributes->getFormat() == self::HDNETWORKSMIL) {
         $this->deliveryAttributes->setMediaProtocol(PlaybackProtocol::HTTP);
     }
     // Akamai HD doesn't support any other protocol
     if ($this->deliveryAttributes->getFormat() == PlaybackProtocol::AKAMAI_HDS) {
         if (strpos($this->deliveryAttributes->getMediaProtocol(), "http") !== 0) {
             $this->deliveryAttributes->setMediaProtocol(PlaybackProtocol::HTTP);
         }
     }
     $tags = $this->getRequestParameter("tags", null);
     if (!$tags) {
         $this->deliveryAttributes->setTags(self::getDefaultTagsByFormat($this->deliveryAttributes->getFormat()));
     } else {
         $tagsArray = explode(',', $tags);
         $tags = array();
         foreach ($tagsArray as $tag) {
             $tags[] = array(trim($tag));
         }
         $this->deliveryAttributes->setTags($tags);
     }
     $this->deliveryAttributes->setpreferredBitrate($this->getRequestParameter("preferredBitrate", null));
     $this->maxBitrate = $this->getRequestParameter("maxBitrate", null);
     if ($this->maxBitrate && (!is_numeric($this->maxBitrate) || $this->maxBitrate <= 0)) {
         KExternalErrors::dieError(KExternalErrors::INVALID_MAX_BITRATE);
     }
     $this->deliveryAttributes->setStorageId($this->getRequestParameter("storageId", null));
     $this->cdnHost = $this->getRequestParameter("cdnHost", null);
     $this->deliveryAttributes->setResponseFormat($this->getRequestParameter("responseFormat", null));
     // Initialize
     $this->initEntry();
     $this->deliveryAttributes->setEntryId($this->entryId);
     $this->deliveryAttributes->setUsePlayServer((bool) $this->getRequestParameter("usePlayServer") && PermissionPeer::isValidForPartner(PermissionName::FEATURE_PLAY_SERVER, $this->entry->getPartnerId()));
     if ($this->deliveryAttributes->getUsePlayServer()) {
         $this->deliveryAttributes->setPlayerConfig($this->getRequestParameter("playerConfig"));
         //In case request needs to be redirected to play-server we need to add the ui conf id to the manifest url as well
         $this->deliveryAttributes->setUiConfId($this->getRequestParameter("uiConfId"));
     }
     $this->secureEntryHelper->updateDeliveryAttributes($this->deliveryAttributes);
     $this->enforceEncryption();
     $renderer = null;
     switch ($this->entry->getType()) {
         case entryType::MEDIA_CLIP:
             // VOD
             $renderer = $this->serveVodEntry();
             break;
         case entryType::LIVE_STREAM:
         case entryType::LIVE_CHANNEL:
             // Live stream
             $renderer = $this->serveLiveEntry();
             break;
         default:
             KExternalErrors::dieError(KExternalErrors::INVALID_ENTRY_TYPE);
     }
     if (!$renderer) {
         KExternalErrors::dieError(KExternalErrors::BAD_QUERY, 'This format is unsupported');
     }
     $renderer->contributors = array();
     $config = new kManifestContributorConfig();
     $config->format = $this->deliveryAttributes->getFormat();
     $config->deliveryCode = $deliveryCode;
     $config->storageId = $this->deliveryAttributes->getStorageId();
     $config->entryId = $this->entryId;
     $contributors = KalturaPluginManager::getPluginInstances('IKalturaPlayManifestContributor');
     foreach ($contributors as $contributor) {
         /* @var $contributor IKalturaPlayManifestContributor */
         $renderer->contributors = array_merge($renderer->contributors, $contributor->getManifestEditors($config));
     }
     $renderer->entryId = $this->entryId;
     $renderer->duration = $this->duration;
     if ($this->deliveryProfile) {
         $renderer->tokenizer = $this->deliveryProfile->getTokenizer();
     }
     $renderer->defaultDeliveryCode = $this->entry->getPartner()->getDefaultDeliveryCode();
     $renderer->lastModified = time();
     // Handle caching
     $canCacheAccessControl = false;
     if (kConf::hasParam("force_caching_headers") && in_array($this->entry->getPartnerId(), kConf::get("force_caching_headers"))) {
         $renderer->cachingHeadersAge = 60;
         $renderer->forceCachingHeaders = true;
     }
     if (!$this->secureEntryHelper) {
         $canCacheAccessControl = true;
         // TODO: reconsider this if/when expired ktokens will be used
     } else {
         if (!$this->secureEntryHelper->shouldDisableCache() && !$this->secureEntryHelper->isKsAdmin() && ($this->secureEntryHelper->isKsWidget() || !$this->secureEntryHelper->hasRules())) {
             $canCacheAccessControl = true;
         }
     }
     if (!$renderer->tokenizer && $canCacheAccessControl) {
         // Note: kApiCache::hasExtraFields is checked in kManifestRenderers
         $renderer->cachingHeadersAge = 60;
     }
     if (!$this->secureEntryHelper || !$this->secureEntryHelper->shouldDisableCache()) {
         $cache = kPlayManifestCacher::getInstance();
         $cache->storeRendererToCache($renderer);
     }
     // Output the response
     KExternalErrors::terminateDispatch();
     $renderer->output($deliveryCode, $playbackContext);
 }
Esempio n. 3
0
function checkCache()
{
    $baseDir = "/tmp/cache_v2";
    $start_time = microtime(true);
    $protocol = isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on' ? "https" : "http";
    $host = "";
    if (isset($_SERVER['HTTP_X_FORWARDED_HOST'])) {
        $host = $_SERVER['HTTP_X_FORWARDED_HOST'];
    } else {
        if (isset($_SERVER['HTTP_HOST'])) {
            $host = $_SERVER['HTTP_HOST'];
        }
    }
    $uri = $_SERVER["REQUEST_URI"];
    if (function_exists('apc_fetch')) {
        $url = apc_fetch("redirect-" . $protocol . $uri);
        if ($url) {
            sendCachingHeaders(60, true, time());
            header("X-Kaltura:cached-dispatcher-redirect");
            header("Location:{$url}");
            die;
        }
        $errorHeaders = apc_fetch("exterror-{$protocol}://{$host}{$uri}");
        if ($errorHeaders !== false) {
            sendCachingHeaders(60, true, time());
            foreach ($errorHeaders as $header) {
                header($header);
            }
            die;
        }
    }
    if (strpos($uri, "/playManifest") !== false) {
        require_once dirname(__FILE__) . "/../apps/kaltura/lib/cache/kPlayManifestCacher.php";
        $cache = kPlayManifestCacher::getInstance();
        $cache->checkOrStart();
    } else {
        if (strpos($uri, "/partnerservices2") !== false) {
            $params = $_GET + $_POST;
            unset($params['ks']);
            unset($params['kalsig']);
            $params['uri'] = $_SERVER['PATH_INFO'];
            $params['__protocol'] = $protocol;
            ksort($params);
            $keys = array_keys($params);
            $key = md5(implode("|", $params) . implode("|", $keys));
            $cache_filename = "{$baseDir}/cache-{$key}";
            if (file_exists($cache_filename)) {
                if (filemtime($cache_filename) + 600 < time()) {
                    @unlink($cache_filename);
                    @unlink($cache_filename . ".headers");
                    @unlink($cache_filename . ".log");
                } else {
                    $content_type = @file_get_contents("{$baseDir}/cache-{$key}.headers");
                    if ($content_type) {
                        header("Content-Type: {$content_type}");
                    }
                    $response = @file_get_contents("{$baseDir}/cache-{$key}");
                    if ($response) {
                        header("Access-Control-Allow-Origin:*");
                        // avoid html5 xss issues
                        if (strpos($uri, "/partnerservices2/executeplaylist") !== false) {
                            $max_age = 60;
                            sendCachingHeaders($max_age, true, time());
                        } else {
                            sendCachingHeaders(0);
                        }
                        $processing_time = microtime(true) - $start_time;
                        header("X-Kaltura:cached-dispatcher,{$key},{$processing_time}");
                        echo $response;
                        die;
                    }
                }
            }
        } else {
            if (strpos($uri, "/kwidget") !== false) {
                require_once dirname(__FILE__) . "/../apps/kaltura/lib/cache/kCacheManager.php";
                $cache = kCacheManager::getSingleLayerCache(kCacheManager::CACHE_TYPE_PS2);
                if ($cache) {
                    // check if we cached the patched swf with flashvars
                    $uri = $protocol . $uri;
                    $cachedResponse = $cache->get("kwidgetswf{$uri}");
                    if ($cachedResponse) {
                        $max_age = 60 * 10;
                        header("X-Kaltura:cached-dispatcher");
                        header("Content-Type: application/x-shockwave-flash");
                        sendCachingHeaders($max_age, true, time());
                        header("Content-Length: " . strlen($cachedResponse));
                        echo $cachedResponse;
                        die;
                    }
                    $cachedResponse = $cache->get("kwidget{$uri}");
                    if ($cachedResponse) {
                        header("X-Kaltura:cached-dispatcher");
                        header("Expires: Sun, 19 Nov 2000 08:52:00 GMT");
                        header("Cache-Control", "no-store, no-cache, must-revalidate, post-check=0, pre-check=0");
                        header("Pragma", "no-cache");
                        if (strpos($uri, "nowrapper") !== false) {
                            header("Location:{$cachedResponse}");
                            die;
                        }
                        $referer = @$_SERVER['HTTP_REFERER'];
                        $externalInterfaceDisabled = strstr($referer, "bebo.com") === false && strstr($referer, "myspace.com") === false && strstr($referer, "current.com") === false && strstr($referer, "myyearbook.com") === false && strstr($referer, "facebook.com") === false && strstr($referer, "friendster.com") === false ? "" : "&externalInterfaceDisabled=1";
                        $noncached_params = $externalInterfaceDisabled . "&referer=" . urlencode($referer);
                        if (strpos($cachedResponse, "/swfparams/") > 0) {
                            $cachedResponse = substr($cachedResponse, 0, -4) . urlencode($noncached_params) . ".swf";
                        } else {
                            $cachedResponse .= $noncached_params;
                        }
                        header("Location:{$cachedResponse}");
                        die;
                    }
                }
            } else {
                if (strpos($uri, "/thumbnail") !== false) {
                    require_once dirname(__FILE__) . "/../apps/kaltura/lib/cache/kCacheManager.php";
                    $cache = kCacheManager::getSingleLayerCache(kCacheManager::CACHE_TYPE_PS2);
                    if ($cache) {
                        require_once dirname(__FILE__) . '/../apps/kaltura/lib/renderers/kRendererDumpFile.php';
                        $cachedResponse = $cache->get("thumb{$uri}");
                        if ($cachedResponse && is_array($cachedResponse)) {
                            list($renderer, $invalidationKey, $cacheTime) = $cachedResponse;
                            $keysStore = kCacheManager::getSingleLayerCache(kCacheManager::CACHE_TYPE_QUERY_CACHE_KEYS);
                            if ($keysStore) {
                                $modifiedTime = $keysStore->get($invalidationKey);
                                if ($modifiedTime && $modifiedTime > $cacheTime) {
                                    return;
                                    // entry has changed (not necessarily the thumbnail)
                                }
                            }
                            require_once dirname(__FILE__) . '/../apps/kaltura/lib/monitor/KalturaMonitorClient.php';
                            KalturaMonitorClient::initApiMonitor(true, 'extwidget.thumbnail', $renderer->partnerId);
                            header("X-Kaltura:cached-dispatcher-thumb");
                            $renderer->output();
                            die;
                        }
                    }
                } else {
                    if (strpos($uri, "/embedIframe/") !== false) {
                        require_once dirname(__FILE__) . "/../apps/kaltura/lib/cache/kCacheManager.php";
                        $cache = kCacheManager::getSingleLayerCache(kCacheManager::CACHE_TYPE_PS2);
                        if ($cache) {
                            // check if we cached the patched swf with flashvars
                            $cachedResponse = $cache->get("embedIframe{$uri}");
                            if ($cachedResponse) {
                                header("X-Kaltura:cached-dispatcher");
                                sendCachingHeaders(0);
                                header("Location:{$cachedResponse}");
                                die;
                            }
                        }
                    } else {
                        if (strpos($uri, "/serveFlavor/") !== false && function_exists('apc_fetch') && $_SERVER["REQUEST_METHOD"] == "GET") {
                            require_once dirname(__FILE__) . '/../apps/kaltura/lib/renderers/kRendererDumpFile.php';
                            require_once dirname(__FILE__) . '/../apps/kaltura/lib/renderers/kRendererString.php';
                            require_once dirname(__FILE__) . '/../apps/kaltura/lib/monitor/KalturaMonitorClient.php';
                            require_once dirname(__FILE__) . '/../apps/kaltura/lib/request/kIpAddressUtils.php';
                            $host = isset($_SERVER['HTTP_X_FORWARDED_HOST']) ? $_SERVER['HTTP_X_FORWARDED_HOST'] : $_SERVER['HTTP_HOST'];
                            $cacheKey = 'dumpFile-' . kIpAddressUtils::isInternalIp($_SERVER['REMOTE_ADDR']) . '-' . $host . $uri;
                            $renderer = apc_fetch($cacheKey);
                            if ($renderer) {
                                KalturaMonitorClient::initApiMonitor(true, 'extwidget.serveFlavor', $renderer->partnerId);
                                header("X-Kaltura:cached-dispatcher");
                                $renderer->output();
                                die;
                            }
                        }
                    }
                }
            }
        }
    }
}
function checkCache()
{
    $baseDir = "/tmp/cache_v2";
    $start_time = microtime(true);
    $uri = $_SERVER["REQUEST_URI"];
    $protocol = isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on' ? "https" : "http";
    if (function_exists('apc_fetch')) {
        $url = apc_fetch("redirect-" . $protocol . $_SERVER["REQUEST_URI"]);
        if ($url) {
            $max_age = 60;
            header("Cache-Control: private, max-age={$max_age}, max-stale=0");
            header('Expires: ' . gmdate('D, d M Y H:i:s', time() + $max_age) . ' GMT');
            header('Last-Modified: ' . gmdate('D, d M Y H:i:s', time()) . ' GMT');
            header("X-Kaltura:cached-dispatcher-redirect");
            header("Location:{$url}");
            die;
        }
    }
    if (strpos($uri, "/playManifest") !== false) {
        require_once dirname(__FILE__) . "/../apps/kaltura/lib/cache/kPlayManifestCacher.php";
        $cache = kPlayManifestCacher::getInstance();
        $cache->checkOrStart();
    }
    if (strpos($uri, "/partnerservices2") !== false) {
        $params = $_GET + $_POST;
        unset($params['ks']);
        unset($params['kalsig']);
        $params['uri'] = $_SERVER['PATH_INFO'];
        ksort($params);
        $keys = array_keys($params);
        $key = md5(implode("|", $params) . implode("|", $keys));
        $cache_filename = "{$baseDir}/cache-{$key}";
        if (file_exists($cache_filename)) {
            if (filemtime($cache_filename) + 600 < time()) {
                @unlink($cache_filename);
                @unlink($cache_filename . ".headers");
                @unlink($cache_filename . ".log");
            } else {
                $content_type = @file_get_contents("{$baseDir}/cache-{$key}.headers");
                if ($content_type) {
                    header("Content-Type: {$content_type}");
                }
                $response = @file_get_contents("{$baseDir}/cache-{$key}");
                if ($response) {
                    header("Access-Control-Allow-Origin:*");
                    // avoid html5 xss issues
                    if (strpos($uri, "/partnerservices2/executeplaylist") !== false) {
                        $max_age = 60;
                        header("Cache-Control: private, max-age={$max_age}, max-stale=0");
                        header('Expires: ' . gmdate('D, d M Y H:i:s', time() + $max_age) . 'GMT');
                        header('Last-Modified: ' . gmdate('D, d M Y H:i:s', time()) . 'GMT');
                    } else {
                        header("Expires: Sun, 19 Nov 2000 08:52:00 GMT");
                        header("Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0");
                        header("Pragma: no-cache");
                    }
                    $processing_time = microtime(true) - $start_time;
                    header("X-Kaltura:cached-dispatcher,{$key},{$processing_time}");
                    echo $response;
                    die;
                }
            }
        }
    }
    if (strpos($uri, "/kwidget") !== false) {
        if (!function_exists('memcache_connect')) {
            return;
        }
        $cache = new Memcache();
        $res = @$cache->connect("localhost", "11211");
        if ($res) {
            // check if we cached the patched swf with flashvars
            $uri = $protocol . $uri;
            $cachedResponse = $cache->get("kwidgetswf{$uri}");
            if ($cachedResponse) {
                $max_age = 60 * 10;
                header("X-Kaltura:cached-dispatcher");
                header("Content-Type: application/x-shockwave-flash");
                header("Cache-Control: private, max-age={$max_age} max-stale=0");
                header('Expires: ' . gmdate('D, d M Y H:i:s', time() + $max_age) . 'GMT');
                header('Last-Modified: ' . gmdate('D, d M Y H:i:s', time()) . 'GMT');
                header("Content-Length: " . strlen($cachedResponse));
                echo $cachedResponse;
                die;
            }
            $cachedResponse = $cache->get("kwidget{$uri}");
            if ($cachedResponse) {
                // set our uv cookie
                $uv_cookie = @$_COOKIE['uv'];
                if (strlen($uv_cookie) != 35) {
                    $uv_cookie = "uv_" . md5(uniqid(rand(), true));
                }
                setrawcookie('uv', $uv_cookie, time() + 3600 * 24 * 365, '/');
                header("X-Kaltura:cached-dispatcher");
                header("Expires: Sun, 19 Nov 2000 08:52:00 GMT");
                header("Cache-Control", "no-store, no-cache, must-revalidate, post-check=0, pre-check=0");
                header("Pragma", "no-cache");
                if (strpos($uri, "nowrapper") !== false) {
                    header("Location:{$cachedResponse}");
                    die;
                }
                $referer = @$_SERVER['HTTP_REFERER'];
                $externalInterfaceDisabled = strstr($referer, "bebo.com") === false && strstr($referer, "myspace.com") === false && strstr($referer, "current.com") === false && strstr($referer, "myyearbook.com") === false && strstr($referer, "facebook.com") === false && strstr($referer, "friendster.com") === false ? "" : "&externalInterfaceDisabled=1";
                $noncached_params = $externalInterfaceDisabled . "&referer=" . urlencode($referer);
                if (strpos($cachedResponse, "/swfparams/") > 0) {
                    $cachedResponse = substr($cachedResponse, 0, -4) . urlencode($noncached_params) . ".swf";
                } else {
                    $cachedResponse .= $noncached_params;
                }
                header("Location:{$cachedResponse}");
                die;
            }
        }
    } else {
        if (strpos($uri, "/thumbnail") !== false) {
            if (!function_exists('memcache_connect')) {
                return;
            }
            $cache = new Memcache();
            $res = @$cache->connect("localhost", "11211");
            if ($res) {
                $file_name = $cache->get("thumb{$uri}");
                if ($file_name && file_exists($file_name)) {
                    $ext = pathinfo($file_name, PATHINFO_EXTENSION);
                    if ($ext == "jpg") {
                        $content_type = "image/jpeg";
                    } else {
                        $content_type = "image/{$ext}";
                    }
                    $total_length = filesize($file_name);
                    $max_age = 8640000;
                    header("X-Kaltura:cached-dispatcher-thumb");
                    header("Cache-Control: public, max-age={$max_age} max-stale=0");
                    header('Expires: ' . gmdate('D, d M Y H:i:s', time() + $max_age) . 'GMT');
                    header('Last-Modified: Sun, 19 Nov 2000 08:52:00 GMT');
                    header("Content-Length: {$total_length} ");
                    header("Pragma:");
                    header("Content-Type: {$content_type}");
                    $chunk_size = 100000;
                    $fh = fopen($file_name, "rb");
                    if ($fh) {
                        $pos = 0;
                        while ($total_length >= 0) {
                            $content = fread($fh, $chunk_size);
                            echo $content;
                            $total_length -= $chunk_size;
                        }
                        fclose($fh);
                    }
                    die;
                }
            }
        }
    }
}
 public function execute()
 {
     $this->seekFrom = $this->getRequestParameter("seekFrom", -1);
     if ($this->seekFrom <= 0) {
         $this->seekFrom = -1;
     }
     $this->clipTo = $this->getRequestParameter("clipTo", 0);
     $this->deliveryCode = $this->getRequestParameter("deliveryCode", null);
     $playbackContext = $this->getRequestParameter("playbackContext", null);
     $this->protocol = $this->getRequestParameter("protocol", null);
     if (!$this->protocol || $this->protocol === "null") {
         $this->protocol = StorageProfile::PLAY_FORMAT_HTTP;
     }
     $this->format = $this->getRequestParameter("format");
     if (!$this->format) {
         $this->format = StorageProfile::PLAY_FORMAT_HTTP;
     }
     $this->tags = $this->getRequestParameter("tags", null);
     if (!$this->tags) {
         switch ($this->format) {
             case StorageProfile::PLAY_FORMAT_SILVER_LIGHT:
                 $this->tags = array(array(assetParams::TAG_SLWEB));
                 break;
             case StorageProfile::PLAY_FORMAT_APPLE_HTTP:
             case StorageProfile::PLAY_FORMAT_HDS:
                 $this->tags = array(array(assetParams::TAG_APPLEMBR), array('ipadnew', 'iphonenew'), array('ipad', 'iphone'));
                 break;
             default:
                 $this->tags = array(array(assetParams::TAG_MBR), array(assetParams::TAG_WEB));
         }
     } else {
         $this->tags = array(array($this->tags));
     }
     $this->cdnHost = $this->getRequestParameter("cdnHost", null);
     $this->preferredBitrate = $this->getRequestParameter("preferredBitrate", null);
     $this->maxBitrate = $this->getRequestParameter("maxBitrate", null);
     if ($this->maxBitrate && (!is_numeric($this->maxBitrate) || $this->maxBitrate <= 0)) {
         KExternalErrors::dieError(KExternalErrors::INVALID_MAX_BITRATE);
     }
     $this->initEntry();
     $this->initFlavorIds();
     $this->storageId = $this->getRequestParameter("storageId", null);
     $this->validateStorageId();
     $partner = $this->entry->getPartner();
     if (!$this->cdnHost || $partner->getForceCdnHost()) {
         $this->cdnHost = myPartnerUtils::getCdnHost($this->entry->getPartnerId(), $this->protocol);
     }
     $playbackParams = array();
     if (kConf::hasMap("optimized_playback")) {
         $partnerId = $this->entry->getPartnerId();
         $optimizedPlayback = kConf::getMap("optimized_playback");
         if (array_key_exists($partnerId, $optimizedPlayback)) {
             $playbackParams = $optimizedPlayback[$partnerId];
         }
     }
     if (array_key_exists('enforce_encryption', $playbackParams) && $playbackParams['enforce_encryption']) {
         if (!isset($_SERVER['HTTPS']) || $_SERVER['HTTPS'] != 'on') {
             KExternalErrors::dieError(KExternalErrors::ACCESS_CONTROL_RESTRICTED, 'unencrypted manifest request - forbidden');
         }
         if (strtolower($this->protocol) != 'https') {
             KExternalErrors::dieError(KExternalErrors::ACCESS_CONTROL_RESTRICTED, 'unencrypted playback protocol - forbidden');
         }
     }
     $renderer = null;
     switch ($this->format) {
         case StorageProfile::PLAY_FORMAT_HTTP:
             $renderer = $this->serveHttp();
             break;
         case StorageProfile::PLAY_FORMAT_RTMP:
             $renderer = $this->serveRtmp();
             break;
         case StorageProfile::PLAY_FORMAT_SILVER_LIGHT:
             $renderer = $this->serveSilverLight();
             break;
         case StorageProfile::PLAY_FORMAT_APPLE_HTTP:
             $renderer = $this->serveAppleHttp();
             break;
         case StorageProfile::PLAY_FORMAT_HDS:
             $renderer = $this->serveHds();
             break;
         case "url":
             $this->format = "http";
             // build url for an http delivery
             $renderer = $this->serveUrl();
             break;
         case "rtsp":
             $renderer = $this->serveRtsp();
             break;
         case "hdnetworksmil":
             $renderer = $this->serveHDNetworkSmil();
             break;
         case "hdnetwork":
             $renderer = $this->serveHDNetwork();
             break;
         case "hdnetworkmanifest":
             $renderer = $this->serveHDNetworkManifest();
             break;
     }
     if (!$renderer) {
         KExternalErrors::dieError(KExternalErrors::BAD_QUERY, 'This format is unsupported');
     }
     $canCacheAccessControl = false;
     if (!$this->secureEntryHelper) {
         $canCacheAccessControl = true;
         // TODO: reconsider this if/when expired ktokens will be used
     } else {
         if (!$this->secureEntryHelper->shouldDisableCache() && !$this->secureEntryHelper->isKsAdmin() && ($this->secureEntryHelper->isKsWidget() || !$this->secureEntryHelper->hasRules())) {
             $canCacheAccessControl = true;
         }
     }
     if (!$renderer->tokenizer && $canCacheAccessControl) {
         // Note: kApiCache::hasExtraFields is checked in kManifestRenderers
         $renderer->cachingHeadersAge = 60;
     }
     if (!$this->secureEntryHelper || !$this->secureEntryHelper->shouldDisableCache()) {
         $cache = kPlayManifestCacher::getInstance();
         $cache->storeCache($renderer);
     }
     $renderer->output($playbackContext);
 }