<commit_before><?php
/**
 * @package Core
 * @subpackage externalWidgets
 */
class downloadAction extends sfAction
{
	
	/**
	 * Will forward to the regular swf player according to the widget_id 
	 */
	public function execute()
	{
		$entryId = $this->getRequestParameter("entry_id");
		$flavorId = $this->getRequestParameter("flavor");
		$fileName = $this->getRequestParameter("file_name");
		$fileName = basename($fileName);
		$ksStr = $this->getRequestParameter("ks");
		$referrer = $this->getRequestParameter("referrer");
		$referrer = base64_decode($referrer);
		if (!is_string($referrer)) // base64_decode can return binary data
			$referrer = "";
			
		$entry = null;
		
		if($ksStr)
		{
			try {
				kCurrentContext::initKsPartnerUser($ksStr);
			}
			catch (Exception $ex)
			{
				KExternalErrors::dieError(KExternalErrors::INVALID_KS);	
			}
		}
		else
		{
			$entry = kCurrentContext::initPartnerByEntryId($entryId);
			if(!$entry)
				KExternalErrors::dieError(KExternalErrors::ENTRY_NOT_FOUND);
		}
		
		kEntitlementUtils::initEntitlementEnforcement();
		
		if (!$entry)
		{
			$entry = entryPeer::retrieveByPK($entryId);
			
			if(!$entry)
				KExternalErrors::dieError(KExternalErrors::ENTRY_NOT_FOUND);
		}
		else
		{
			if(!kEntitlementUtils::isEntryEntitled($entry))
				KExternalErrors::dieError(KExternalErrors::ENTRY_NOT_FOUND);
		}
		
		KalturaMonitorClient::initApiMonitor(false, 'extwidget.download', $entry->getPartnerId());
		
		myPartnerUtils::blockInactivePartner($entry->getPartnerId());
		
		$shouldPreview = false;
		$securyEntryHelper = new KSecureEntryHelper($entry, $ksStr, $referrer, ContextType::DOWNLOAD);
		if ($securyEntryHelper->shouldPreview()) { 
			$shouldPreview = true;
		} else { 
			$securyEntryHelper->validateForDownload();
		}
		
		$flavorAsset = null;

		if ($flavorId) 
		{
			// get flavor asset
			$flavorAsset = assetPeer::retrieveById($flavorId);
			if (is_null($flavorAsset) || !$flavorAsset->isLocalReadyStatus())
				KExternalErrors::dieError(KExternalErrors::FLAVOR_NOT_FOUND);
			
			// the request flavor should belong to the requested entry
			if ($flavorAsset->getEntryId() != $entryId)
				KExternalErrors::dieError(KExternalErrors::FLAVOR_NOT_FOUND);
				
			if(!$securyEntryHelper->isAssetAllowed($flavorAsset))
				KExternalErrors::dieError(KExternalErrors::FLAVOR_NOT_FOUND);
		}
		else // try to find some flavor
		{
			$flavorAssets = assetPeer::retrieveReadyWebByEntryId($entry->getId());
			foreach ($flavorAssets as $curFlavorAsset) 
			{
				if($securyEntryHelper->isAssetAllowed($curFlavorAsset))
				{	
					$flavorAsset = $curFlavorAsset;
					break;
				}
			}
		}
		
		// Gonen 26-04-2010: in case entry has no flavor with 'mbr' tag - we return the source
		if(!$flavorAsset && ($entry->getMediaType() == entry::ENTRY_MEDIA_TYPE_VIDEO || $entry->getMediaType() == entry::ENTRY_MEDIA_TYPE_AUDIO))
		{
			$flavorAsset = assetPeer::retrieveOriginalByEntryId($entryId);
			if(!$securyEntryHelper->isAssetAllowed($flavorAsset))
			{
				$flavorAsset = null;
			}
		}
		
		if ($flavorAsset)
		{
			$syncKey = $this->getSyncKeyAndForFlavorAsset($entry, $flavorAsset);
		}
		else
		{
			$syncKey = $this->getBestSyncKeyForEntry($entry);
		}
		
		if (is_null($syncKey))
			KExternalErrors::dieError(KExternalErrors::FILE_NOT_FOUND);

		list ($fileSync,$local) = kFileSyncUtils::getReadyFileSyncForKey($syncKey, true, false);
		if (!$fileSync)
			KExternalErrors::dieError(KExternalErrors::FILE_NOT_FOUND);
		/**@var $fileSync FileSync */
		$filePath = $fileSync->getFullPath();

		list($fileBaseName, $fileExt) = kAssetUtils::getFileName($entry, $flavorAsset);

		if (!$fileName)
			$fileName = $fileBaseName;

		$isDir = is_dir($filePath) || $fileSync->getIsDir();
		if ($fileExt && !$isDir)
			$fileName = $fileName . '.' . $fileExt;

		if(!$local)
		{
			$this->handleFileSyncRedirection($fileSync, $flavorAsset, $entry->getId(), $fileName, $isDir);
		}
		
		$preview = 0;
		if($shouldPreview && $flavorAsset) {
			$preview = $flavorAsset->estimateFileSize($entry, $securyEntryHelper->getPreviewLength());
		} else if(kCurrentContext::$ks_object) {
			$preview = kCurrentContext::$ks_object->getPrivilegeValue(kSessionBase::PRIVILEGE_PREVIEW, 0);
		}
		
	   //enable downloading file_name which inside the flavor asset directory
		if(is_dir($filePath))
		{
				$filePath = $filePath . DIRECTORY_SEPARATOR . $fileName;
				$fileSize = null;
		}
		else
		{
				$fileSize = $fileSync->getFileSize();
		}

		$allowRemote = false;
		if(in_array($fileSync->getDc(), kStorageExporter::getPeriodicStorageIds()))
		{
			$allowRemote = true;
			$fileExt = null;
			$storage = StorageProfilePeer::retrieveByPK($fileSync->getDc());
			try
			{
				$filePath = $fileSync->getS3FileSyncUrl($storage, $fileSync->getFilePath());
				$fileExt = $flavorAsset->getFileExt();
			}
			catch (Exception $ex)
			{
				KExternalErrors::dieError(KExternalErrors::FILE_NOT_FOUND);
			}
		}
		$this->dumpFile($filePath, $fileName, $preview, $fileSync->getEncryptionKey(), $fileSync->getIv(), $fileSize, $fileExt, $allowRemote);
	
		KExternalErrors::dieGracefully(); // no view
	}
	
	private function getSyncKeyAndForFlavorAsset(entry $entry, flavorAsset $flavorAsset)
	{
		$syncKey = $flavorAsset->getSyncKey(flavorAsset::FILE_SYNC_FLAVOR_ASSET_SUB_TYPE_ASSET);
		return $syncKey;
	}
	
	private function getBestSyncKeyForEntry(entry $entry)
	{
		$entryType = $entry->getType();
		$entryMediaType = $entry->getMediaType();
		$syncKey = null;
		switch($entryType)
		{
			case entryType::MEDIA_CLIP: 
				switch ($entryMediaType)
				{
					case entry::ENTRY_MEDIA_TYPE_IMAGE:
						$syncKey = $entry->getSyncKey(kEntryFileSyncSubType::DATA);
						break;
				}
				break;
		}
		
		return $syncKey;
	}

	private function dumpFile($file_path, $file_name, $limit_file_size = 0, $key = null, $iv = null, $fileSize = null, $fileExt = null, $allowRemote = false)
	{
		$file_name = str_replace("\n", ' ', $file_name);
		$relocate = $this->getRequestParameter("relocate");
		$directServe = $this->getRequestParameter("direct_serve");

		if (!$relocate)
		{
			$url = $_SERVER["REQUEST_URI"];
			if (strpos($url, "?") !== false) // when query string exists, just remove it (otherwise it might cause redirect loops)
			{
				$url .= "&relocate=";
			}
			else
			{
				$url .= "/relocate/";
			}
				
			$url .= kString::stripInvalidUrlChars($file_name);

			kFile::cacheRedirect($url);

			header("Location: {$url}");
			KExternalErrors::dieGracefully();
		}
		else
		{
			if(!$directServe)
				header("Content-Disposition: attachment; filename=\"$file_name\"");

			$mime_type = null;
			if(!$allowRemote)
			{
				$mime_type = kFile::mimeType($file_path);
			}

			kFileUtils::dumpFile($file_path, $mime_type, null, $limit_file_size, $key, $iv, $fileSize, $allowRemote, $fileExt);
		}
	}

	private function handleFileSyncRedirection($fileSync, asset $flavorAsset, $entryId, $fileName, $isDir)
	{
		$downloadDeliveryProfile = myPartnerUtils::getDownloadDeliveryProfile($fileSync->getDc(), $entryId);
		if($downloadDeliveryProfile && $flavorAsset)
		{
			$url = $this->getDownloadRedirectUrl($downloadDeliveryProfile, $flavorAsset, $fileName, $isDir);
		}
		else if(in_array($fileSync->getDc(), kStorageExporter::getPeriodicStorageIds()))
		{
			return;
		}
		else
		{
			$url = kDataCenterMgr::getRedirectExternalUrl($fileSync);
		}
		KExternalErrors::terminateDispatch();
		$this->redirect($url);
	}

	protected function getDownloadRedirectUrl($downloadDeliveryProfile, $flavorAsset, $fileName, $isDir)
	{
		if($fileName)
		{
			$fileName = str_replace("\n", ' ', $fileName);
			$fileName = kString::keepOnlyValidUrlChars($fileName);
		}
		$url = $flavorAsset->getServeFlavorUrl(null, $fileName, $downloadDeliveryProfile, $isDir);
		KalturaLog::log ("URL to redirect to [$url]" );
		return $url;
	}
}<commit_msg>PLAT-11239: use packager redirect for shared files download and encode file name<commit_after><?php
/**
 * @package Core
 * @subpackage externalWidgets
 */
class downloadAction extends sfAction
{
	
	/**
	 * Will forward to the regular swf player according to the widget_id 
	 */
	public function execute()
	{
		$entryId = $this->getRequestParameter("entry_id");
		$flavorId = $this->getRequestParameter("flavor");
		$fileName = $this->getRequestParameter("file_name");
		$fileName = basename($fileName);
		$ksStr = $this->getRequestParameter("ks");
		$referrer = $this->getRequestParameter("referrer");
		$referrer = base64_decode($referrer);
		if (!is_string($referrer)) // base64_decode can return binary data
			$referrer = "";
			
		$entry = null;
		
		if($ksStr)
		{
			try {
				kCurrentContext::initKsPartnerUser($ksStr);
			}
			catch (Exception $ex)
			{
				KExternalErrors::dieError(KExternalErrors::INVALID_KS);	
			}
		}
		else
		{
			$entry = kCurrentContext::initPartnerByEntryId($entryId);
			if(!$entry)
				KExternalErrors::dieError(KExternalErrors::ENTRY_NOT_FOUND);
		}
		
		kEntitlementUtils::initEntitlementEnforcement();
		
		if (!$entry)
		{
			$entry = entryPeer::retrieveByPK($entryId);
			
			if(!$entry)
				KExternalErrors::dieError(KExternalErrors::ENTRY_NOT_FOUND);
		}
		else
		{
			if(!kEntitlementUtils::isEntryEntitled($entry))
				KExternalErrors::dieError(KExternalErrors::ENTRY_NOT_FOUND);
		}
		
		KalturaMonitorClient::initApiMonitor(false, 'extwidget.download', $entry->getPartnerId());
		
		myPartnerUtils::blockInactivePartner($entry->getPartnerId());
		
		$shouldPreview = false;
		$securyEntryHelper = new KSecureEntryHelper($entry, $ksStr, $referrer, ContextType::DOWNLOAD);
		if ($securyEntryHelper->shouldPreview()) { 
			$shouldPreview = true;
		} else { 
			$securyEntryHelper->validateForDownload();
		}
		
		$flavorAsset = null;

		if ($flavorId) 
		{
			// get flavor asset
			$flavorAsset = assetPeer::retrieveById($flavorId);
			if (is_null($flavorAsset) || !$flavorAsset->isLocalReadyStatus())
				KExternalErrors::dieError(KExternalErrors::FLAVOR_NOT_FOUND);
			
			// the request flavor should belong to the requested entry
			if ($flavorAsset->getEntryId() != $entryId)
				KExternalErrors::dieError(KExternalErrors::FLAVOR_NOT_FOUND);
				
			if(!$securyEntryHelper->isAssetAllowed($flavorAsset))
				KExternalErrors::dieError(KExternalErrors::FLAVOR_NOT_FOUND);
		}
		else // try to find some flavor
		{
			$flavorAssets = assetPeer::retrieveReadyWebByEntryId($entry->getId());
			foreach ($flavorAssets as $curFlavorAsset) 
			{
				if($securyEntryHelper->isAssetAllowed($curFlavorAsset))
				{	
					$flavorAsset = $curFlavorAsset;
					break;
				}
			}
		}
		
		// Gonen 26-04-2010: in case entry has no flavor with 'mbr' tag - we return the source
		if(!$flavorAsset && ($entry->getMediaType() == entry::ENTRY_MEDIA_TYPE_VIDEO || $entry->getMediaType() == entry::ENTRY_MEDIA_TYPE_AUDIO))
		{
			$flavorAsset = assetPeer::retrieveOriginalByEntryId($entryId);
			if(!$securyEntryHelper->isAssetAllowed($flavorAsset))
			{
				$flavorAsset = null;
			}
		}
		
		if ($flavorAsset)
		{
			$syncKey = $this->getSyncKeyAndForFlavorAsset($entry, $flavorAsset);
		}
		else
		{
			$syncKey = $this->getBestSyncKeyForEntry($entry);
		}
		
		if (is_null($syncKey))
			KExternalErrors::dieError(KExternalErrors::FILE_NOT_FOUND);

		list ($fileSync,$local) = kFileSyncUtils::getReadyFileSyncForKey($syncKey, true, false);
		if (!$fileSync)
			KExternalErrors::dieError(KExternalErrors::FILE_NOT_FOUND);
		/**@var $fileSync FileSync */
		$filePath = $fileSync->getFullPath();

		list($fileBaseName, $fileExt) = kAssetUtils::getFileName($entry, $flavorAsset);

		if (!$fileName)
			$fileName = $fileBaseName;

		$isDir = is_dir($filePath) || $fileSync->getIsDir();
		if ($fileExt && !$isDir)
			$fileName = $fileName . '.' . $fileExt;

		if(!$local || in_array( $fileSync->getDc(), kDataCenterMgr::getSharedStorageProfileIds()))
		{
			$this->handleFileSyncRedirection($fileSync, $flavorAsset, $entry->getId(), $fileName, $isDir);
		}
		
		$preview = 0;
		if($shouldPreview && $flavorAsset) {
			$preview = $flavorAsset->estimateFileSize($entry, $securyEntryHelper->getPreviewLength());
		} else if(kCurrentContext::$ks_object) {
			$preview = kCurrentContext::$ks_object->getPrivilegeValue(kSessionBase::PRIVILEGE_PREVIEW, 0);
		}
		
	   //enable downloading file_name which inside the flavor asset directory
		if(is_dir($filePath))
		{
				$filePath = $filePath . DIRECTORY_SEPARATOR . $fileName;
				$fileSize = null;
		}
		else
		{
				$fileSize = $fileSync->getFileSize();
		}

		$allowRemote = false;
		if(in_array($fileSync->getDc(), kStorageExporter::getPeriodicStorageIds()))
		{
			$allowRemote = true;
			$fileExt = null;
			$storage = StorageProfilePeer::retrieveByPK($fileSync->getDc());
			try
			{
				$filePath = $fileSync->getS3FileSyncUrl($storage, $fileSync->getFilePath());
				$fileExt = $flavorAsset->getFileExt();
			}
			catch (Exception $ex)
			{
				KExternalErrors::dieError(KExternalErrors::FILE_NOT_FOUND);
			}
		}
		$this->dumpFile($filePath, $fileName, $preview, $fileSync->getEncryptionKey(), $fileSync->getIv(), $fileSize, $fileExt, $allowRemote);
	
		KExternalErrors::dieGracefully(); // no view
	}
	
	private function getSyncKeyAndForFlavorAsset(entry $entry, flavorAsset $flavorAsset)
	{
		$syncKey = $flavorAsset->getSyncKey(flavorAsset::FILE_SYNC_FLAVOR_ASSET_SUB_TYPE_ASSET);
		return $syncKey;
	}
	
	private function getBestSyncKeyForEntry(entry $entry)
	{
		$entryType = $entry->getType();
		$entryMediaType = $entry->getMediaType();
		$syncKey = null;
		switch($entryType)
		{
			case entryType::MEDIA_CLIP: 
				switch ($entryMediaType)
				{
					case entry::ENTRY_MEDIA_TYPE_IMAGE:
						$syncKey = $entry->getSyncKey(kEntryFileSyncSubType::DATA);
						break;
				}
				break;
		}
		
		return $syncKey;
	}

	private function dumpFile($file_path, $file_name, $limit_file_size = 0, $key = null, $iv = null, $fileSize = null, $fileExt = null, $allowRemote = false)
	{
		$file_name = str_replace("\n", ' ', $file_name);
		$relocate = $this->getRequestParameter("relocate");
		$directServe = $this->getRequestParameter("direct_serve");

		if (!$relocate)
		{
			$url = $_SERVER["REQUEST_URI"];
			if (strpos($url, "?") !== false) // when query string exists, just remove it (otherwise it might cause redirect loops)
			{
				$url .= "&relocate=";
			}
			else
			{
				$url .= "/relocate/";
			}
				
			$url .= kString::stripInvalidUrlChars($file_name);

			kFile::cacheRedirect($url);

			header("Location: {$url}");
			KExternalErrors::dieGracefully();
		}
		else
		{
			if(!$directServe)
				header("Content-Disposition: attachment; filename=\"$file_name\"");

			$mime_type = null;
			if(!$allowRemote)
			{
				$mime_type = kFile::mimeType($file_path);
			}

			kFileUtils::dumpFile($file_path, $mime_type, null, $limit_file_size, $key, $iv, $fileSize, $allowRemote, $fileExt);
		}
	}

	private function handleFileSyncRedirection($fileSync, asset $flavorAsset, $entryId, $fileName, $isDir)
	{
		$downloadDeliveryProfile = myPartnerUtils::getDownloadDeliveryProfile($fileSync->getDc(), $entryId);
		if($downloadDeliveryProfile && $flavorAsset)
		{
			$url = $this->getDownloadRedirectUrl($downloadDeliveryProfile, $flavorAsset, $fileName, $isDir);
		}
		else if(in_array($fileSync->getDc(), kStorageExporter::getPeriodicStorageIds()) || in_array( $fileSync->getDc(), kDataCenterMgr::getSharedStorageProfileIds()))
		{
			return;
		}
		else
		{
			$url = kDataCenterMgr::getRedirectExternalUrl($fileSync);
		}
		KExternalErrors::terminateDispatch();
		$this->redirect($url);
	}

	protected function getDownloadRedirectUrl($downloadDeliveryProfile, $flavorAsset, $fileName, $isDir)
	{
		if($fileName)
		{
			$fileName = kString::removeNewLine($fileName);
			$fileName = kString::stripInvalidUrlChars($fileName);
			$fileName = rawurlencode($fileName);
		}
		$url = $flavorAsset->getServeFlavorUrl(null, $fileName, $downloadDeliveryProfile, $isDir);
		KalturaLog::log ("URL to redirect to [$url]" );
		return $url;
	}
}
{'fraction_non_alphanumeric': 0.1510462348076682, 'fraction_numerical': 0.0023180052624984337, 'mean_word_length': 4.752432432432433, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 97, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 25, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5044962', 'n_tokens_mistral': 6280, 'n_tokens_neox': 5447, 'n_words': 864}