/**
  * Extract media information from remote file
  * @return KalturaMediaInfo
  */
 public function getMediaInfo()
 {
     $mediaFileExt = pathinfo($this->filePath, PATHINFO_EXTENSION);
     $kWAMS = kWAMS::getInstance($this->partnerId);
     $wamsFileSize = $kWAMS->getFileSizeForAssetId($this->wamsAssetId, $mediaFileExt);
     $mediaInfo = $this->mediaInfoParser->getMediaInfo();
     if ($this->validateMediaInfo($mediaInfo)) {
         $mediaInfo->fileSize = $wamsFileSize / 1024;
         // size in KB
         return $mediaInfo;
     }
     $localFileSize = filesize($this->filePath);
     $fp = fopen($kWAMS->getUrlForAssetId($this->wamsAssetId, $mediaFileExt), 'rb');
     if ($localFileSize > 0) {
         stream_get_contents($fp, $localFileSize);
     }
     while (!$this->validateMediaInfo($mediaInfo) && $localFileSize < $wamsFileSize) {
         $blockContent = stream_get_contents($fp, self::MAX_BLOCK_SIZE);
         $this->appendBlock($blockContent);
         clearstatcache();
         $localFileSize = filesize($this->filePath);
         $mediaInfo = $this->mediaInfoParser->getMediaInfo();
     }
     fclose($fp);
     if (!empty($mediaInfo)) {
         $mediaInfo->fileSize = $wamsFileSize / 1024;
         // size in KB
     }
     return $mediaInfo;
 }
 public function createThumbnail($position, $width, $height, $dar = null)
 {
     KalturaLog::debug("Creation thumbnail via WAMS position = [{$position}], width = [{$width}], height = [{$height}], dar = [{$dar}]");
     if (isset($dar) && $dar > 0 && isset($height)) {
         $width = floor(round($height * $dar) / 2) * 2;
     }
     $thumbFormat = 'jpg';
     $kWAMS = kWAMS::getInstance($this->partnerId);
     $thumbAssetId = $kWAMS->createThumbnail($this->srcWAMSAssetId, $position, $width, $height, $thumbFormat);
     if (!$thumbAssetId) {
         return false;
     } else {
         $thumbURL = $kWAMS->getUrlForAssetId($thumbAssetId, $thumbFormat);
         // download
         KalturaLog::debug("Downloading thumbnail url = [{$thumbURL}]");
         file_put_contents($this->targetPath, fopen($thumbURL, 'rb'));
         $kWAMS->deleteAssetById($thumbAssetId);
         return true;
     }
 }
 /**
  * Do converting
  * @param KalturaConvertJobData $data Job data
  * @return array Result of converting
  */
 public function convertJob(KalturaConvertJobData &$data)
 {
     $outputParams = $data->flavorParamsOutput;
     $videoCodec = $outputParams->videoCodec;
     $videoBitrate = $outputParams->videoBitrate;
     $width = $outputParams->width;
     $height = $outputParams->height;
     $presetName = $outputParams->name;
     $preset = array();
     $preset[kWAMS::CONVERT_PARAM_PRESET_NAME] = $outputParams->name;
     $preset[kWAMS::CONVERT_PARAM_AUDIO_CODEC] = $outputParams->audioCodec;
     $preset[kWAMS::CONVERT_PARAM_AUDIO_BITRATE] = $outputParams->audioBitrate;
     $preset[kWAMS::CONVERT_PARAM_AUDIO_CHANNELS] = $outputParams->audioChannels;
     $preset[kWAMS::CONVERT_PARAM_AUDIO_SAMPLE_RATE] = $outputParams->audioSampleRate;
     $preset[kWAMS::CONVERT_PARAM_VIDEO_CODEC] = $outputParams->videoCodec;
     $preset[kWAMS::CONVERT_PARAM_VIDEO_WIDTH] = $outputParams->width;
     $preset[kWAMS::CONVERT_PARAM_VIDEO_HEIGHT] = $outputParams->height;
     $preset[kWAMS::CONVERT_PARAM_VIDEO_BITRATE] = $outputParams->videoBitrate;
     KalturaLog::debug("Video params output: preset = [{$presetName}], videoCodec = [{$videoCodec}], videoBitrate = [{$videoBitrate}], width = [{$width}], height = [{$height}]");
     $start = microtime(true);
     $kWAMS = kWAMS::getInstance($data->flavorParamsOutput->partnerId);
     $wamsJobId = $kWAMS->addConvertJob($data->srcFileSyncWamsAssetId, $preset);
     Propel::disableInstancePooling();
     while ($kWAMS->isJobProcessing($wamsJobId)) {
         // check Kaltura Batch Job Status
         if (BatchJobPeer::retrieveByPK($this->batchJobId)->getAbort()) {
             $kWAMS->cancelJob($wamsJobId);
         }
         sleep(5);
     }
     Propel::enableInstancePooling();
     $data->destFileSyncWamsAssetId = $kWAMS->getOutputAssetId($wamsJobId);
     $end = microtime(true);
     $duration = $end - $start;
     KalturaLog::info($this->getName() . ":  took [{$duration}] seconds");
     return array(true, null);
 }
 /**
  * Uses for getting instance of singleton
  * @return kWAMS
  */
 public static function getInstance($partnerId)
 {
     if (is_null(self::$_instance)) {
         self::$_instance = new kWAMS($partnerId);
     }
     return self::$_instance;
 }
 private function dumpFile($file_path, $file_name, $wams_asset_id = null, $wams_url = null)
 {
     $relocate = $this->getRequestParameter("relocate");
     $directServe = $this->getRequestParameter("direct_serve");
     if (!$relocate) {
         $url = $_SERVER["REQUEST_URI"];
         if (strpos($url, "?") !== false) {
             $url .= "&relocate=";
         } else {
             $url .= "/relocate/";
         }
         $url .= $this->encodeUrl($file_name);
         kFile::cacheRedirect($url);
         header("Location: {$url}");
         die;
     } else {
         if (!$directServe) {
             header("Content-Disposition: attachment; filename=\"{$file_name}\"");
         }
         if (!empty($wams_asset_id)) {
             $fileSync = FileSyncPeer::retrieveByWamsAssetId($wams_asset_id);
             kWAMS::getInstance($fileSync->getPartnerId())->dumpFile($wams_asset_id, pathinfo($file_name, PATHINFO_EXTENSION));
         } else {
             $mime_type = kFile::mimeType($file_path);
             kFile::dumpFile($file_path, $mime_type);
         }
     }
 }
 /**
  * Update details and settings of an existing partner
  * 
  * @action update
  * @param KalturaPartner $partner
  * @param bool $allowEmpty
  * @return KalturaPartner
  *
  * @throws APIErrors::UNKNOWN_PARTNER_ID
  */
 public function updateAction(KalturaPartner $partner, $allowEmpty = false)
 {
     kWAMS::testConnection($partner->wamsAccountName, $partner->wamsAccountKey);
     $dbPartner = PartnerPeer::retrieveByPK($this->getPartnerId());
     if (!$dbPartner) {
         throw new KalturaAPIException(APIErrors::UNKNOWN_PARTNER_ID, $this->getPartnerId());
     }
     try {
         $dbPartner = $partner->toUpdatableObject($dbPartner);
         $dbPartner->save();
     } catch (kUserException $e) {
         if ($e->getCode() === kUserException::USER_NOT_FOUND) {
             throw new KalturaAPIException(KalturaErrors::USER_NOT_FOUND);
         }
         throw $e;
     } catch (kPermissionException $e) {
         if ($e->getCode() === kPermissionException::ACCOUNT_OWNER_NEEDS_PARTNER_ADMIN_ROLE) {
             throw new KalturaAPIException(KalturaErrors::ACCOUNT_OWNER_NEEDS_PARTNER_ADMIN_ROLE);
         }
         throw $e;
     }
     $partner = new KalturaPartner();
     $partner->fromPartner($dbPartner);
     return $partner;
 }
 private function addWamsFile(KalturaBatchJob $job, KalturaConvertJobData $data)
 {
     KalturaLog::debug("wams file({$job->id}, {$data->destFileSyncWamsAssetId})");
     if (empty($data->destFileSyncWamsAssetId)) {
         KalturaLog::err("Error: add wams file failed");
         die;
     } else {
         Propel::disableInstancePooling();
         if (BatchJobPeer::retrieveByPK($job->id)->getAbort()) {
             kWAMS::getInstance($job->partnerId)->deleteAssetById($data->destFileSyncWamsAssetId);
             return $job;
         }
         Propel::enableInstancePooling();
         $job->status = KalturaBatchJobStatus::FINISHED;
         $job->message = "File ready in WAMS";
         return $this->closeJob($job, null, null, $job->message, $job->status, $data);
     }
 }
 /**
  * Clear WAMS fields and delete asset
  * @param FileSyncKey $key
  * @param bool $strict
  */
 public static function clearWAMSDataForKey(FileSyncKey $key, $strict = false)
 {
     $file_sync = self::getLocalFileSyncForKey($key, $strict);
     if ($file_sync) {
         $parent_file_sync = self::resolve($file_sync);
         $wamsAssetId = $parent_file_sync->getWamsAssetId();
         if (!empty($wamsAssetId)) {
             kWAMS::getInstance($parent_file_sync->getPartnerId())->deleteAssetById($wamsAssetId);
         }
         $parent_file_sync->setWamsAssetId(null);
         $parent_file_sync->setWamsUrl(null);
         $parent_file_sync->save();
     }
 }
 /**
  * @param KalturaBatchJob $job
  * @param KalturaPostConvertJobData $data
  * @return KalturaBatchJob
  */
 private function postConvert(KalturaBatchJob $job, KalturaPostConvertJobData $data)
 {
     DbManager::setConfig(kConf::getDB());
     DbManager::initialize();
     $flavorAsset = assetPeer::retrieveByPK($data->flavorAssetId);
     if (!empty($flavorAsset) && $this->checkMediaInfoExists($data->flavorAssetId) && $flavorAsset->getIsOriginal() && $flavorAsset->getSize() !== 0) {
         $data->createThumb = false;
         return $this->closeJob($job, null, null, 'Media info already exists', KalturaBatchJobStatus::FINISHED, $data);
     }
     if ($data->flavorParamsOutputId) {
         $data->flavorParamsOutput = $this->kClient->flavorParamsOutput->get($data->flavorParamsOutputId);
     }
     try {
         $mediaFile = trim($data->srcFileSyncLocalPath);
         $mediaFileExt = pathinfo($mediaFile, PATHINFO_EXTENSION);
         if (!is_null($data->srcFileSyncWamsAssetId)) {
             $tempFile = kWAMS::getInstance($job->partnerId)->createTempFileForAssetId($data->srcFileSyncWamsAssetId, $mediaFileExt);
             if (file_exists($tempFile)) {
                 $mediaFile = $tempFile;
             }
         }
         if (!$data->flavorParamsOutput || !$data->flavorParamsOutput->sourceRemoteStorageProfileId) {
             if (!$this->pollingFileExists($mediaFile)) {
                 return $this->closeJob($job, KalturaBatchJobErrorTypes::APP, KalturaBatchJobAppErrors::NFS_FILE_DOESNT_EXIST, "Source file {$mediaFile} does not exist", KalturaBatchJobStatus::RETRY);
             }
             if (!is_file($mediaFile)) {
                 return $this->closeJob($job, KalturaBatchJobErrorTypes::APP, KalturaBatchJobAppErrors::NFS_FILE_DOESNT_EXIST, "Source file {$mediaFile} is not a file", KalturaBatchJobStatus::FAILED);
             }
         }
         KalturaLog::debug("mediaFile [{$mediaFile}]");
         $this->updateJob($job, "Extracting file media info on {$mediaFile}", KalturaBatchJobStatus::QUEUED, 1);
     } catch (Exception $ex) {
         return $this->closeJob($job, KalturaBatchJobErrorTypes::RUNTIME, $ex->getCode(), "Error: " . $ex->getMessage(), KalturaBatchJobStatus::FAILED);
     }
     $mediaInfo = null;
     try {
         $engine = KBaseMediaParser::getParser($job->jobSubType, realpath($mediaFile), $this->taskConfig, $job, $data->srcFileSyncWamsAssetId);
         if ($engine) {
             KalturaLog::info("Media info engine [" . get_class($engine) . "]");
             $mediaInfo = $engine->getMediaInfo();
             if (!empty($data->srcFileSyncWamsAssetId)) {
                 kWAMS::getInstance($job->partnerId)->deleteTempFileForAssetId($data->srcFileSyncWamsAssetId, $mediaFileExt);
             }
         } else {
             $err = "Media info engine not found for job subtype [" . $job->jobSubType . "]";
             KalturaLog::info($err);
             return $this->closeJob($job, KalturaBatchJobErrorTypes::APP, KalturaBatchJobAppErrors::ENGINE_NOT_FOUND, $err, KalturaBatchJobStatus::FAILED);
         }
     } catch (Exception $ex) {
         KalturaLog::err("Error: " . $ex->getMessage());
         $mediaInfo = null;
     }
     /* @var $mediaInfo KalturaMediaInfo */
     if (is_null($mediaInfo)) {
         return $this->closeJob($job, KalturaBatchJobErrorTypes::APP, KalturaBatchJobAppErrors::EXTRACT_MEDIA_FAILED, "Failed to extract media info: {$mediaFile}", KalturaBatchJobStatus::FAILED);
     }
     try {
         $mediaInfo->flavorAssetId = $data->flavorAssetId;
         $createdMediaInfo = $this->getClient()->batch->addMediaInfo($mediaInfo);
         if ($createdMediaInfo instanceof KalturaMediaInfo) {
             $mediaInfo = $createdMediaInfo;
         }
         // must save the mediaInfoId before reporting that the task is finished
         $this->updateJob($job, "Saving media info id {$createdMediaInfo->id}", KalturaBatchJobStatus::PROCESSED, 50, $data);
         $data->thumbPath = null;
         if (!$data->createThumb) {
             return $this->closeJob($job, null, null, "Media info id {$createdMediaInfo->id} saved", KalturaBatchJobStatus::FINISHED, $data);
         }
         // creates a temp file path
         $rootPath = $this->taskConfig->params->localTempPath;
         $this->createDir($rootPath);
         // creates the path
         $uniqid = uniqid('thumb_');
         $thumbPath = realpath($rootPath) . "/{$uniqid}";
         $videoDurationSec = floor($mediaInfo->videoDuration / 1000);
         $data->thumbOffset = max(0, min($data->thumbOffset, $videoDurationSec));
         if ($mediaInfo->videoHeight) {
             $data->thumbHeight = $mediaInfo->videoHeight;
         }
         if ($mediaInfo->videoBitRate) {
             $data->thumbBitrate = $mediaInfo->videoBitRate;
         }
         // generates the thumbnail
         if (!is_null($data->srcFileSyncWamsAssetId)) {
             $thumbMaker = new KWAMSThumbnailMaker($data->srcFileSyncWamsAssetId, $thumbPath);
             $created = $thumbMaker->createThumbnail($data->thumbOffset, $mediaInfo->videoWidth, $mediaInfo->videoHeight, $mediaInfo->videoDar);
         } else {
             $thumbMaker = new KFFMpegThumbnailMaker($mediaFile, $thumbPath, $this->taskConfig->params->FFMpegCmd);
             $created = $thumbMaker->createThumnail($data->thumbOffset, $mediaInfo->videoWidth, $mediaInfo->videoHeight, null, null, $mediaInfo->videoDar);
         }
         if (!$created || !file_exists($thumbPath)) {
             $data->createThumb = false;
             return $this->closeJob($job, KalturaBatchJobErrorTypes::APP, KalturaBatchJobAppErrors::THUMBNAIL_NOT_CREATED, 'Thumbnail not created', KalturaBatchJobStatus::FINISHED, $data);
         }
         $data->thumbPath = $thumbPath;
         $job = $this->moveFile($job, $data);
         if ($this->checkFileExists($job->data->thumbPath)) {
             return $this->closeJob($job, null, null, null, KalturaBatchJobStatus::FINISHED, $data);
         }
         $data->createThumb = false;
         return $this->closeJob($job, KalturaBatchJobErrorTypes::APP, KalturaBatchJobAppErrors::NFS_FILE_DOESNT_EXIST, 'File not moved correctly', KalturaBatchJobStatus::FINISHED, $data);
     } catch (Exception $ex) {
         return $this->closeJob($job, KalturaBatchJobErrorTypes::RUNTIME, $ex->getCode(), "Error: " . $ex->getMessage(), KalturaBatchJobStatus::FAILED);
     }
 }
 /**
  * addFlavorConvertJob adds a single flavor conversion 
  * 
  * @param FileSyncKey $srcSyncKey
  * @param flavorParamsOutput $flavor
  * @param int $flavorAssetId
  * @param int $mediaInfoId
  * @param BatchJob $parentJob
  * @param int $lastEngineType  
  * @param BatchJob $dbConvertFlavorJob
  * @return BatchJob 
  */
 public static function addFlavorConvertJob(FileSyncKey $srcSyncKey, flavorParamsOutput $flavor, $flavorAssetId, $mediaInfoId = null, BatchJob $parentJob = null, $lastEngineType = null, BatchJob $dbConvertFlavorJob = null)
 {
     $localPath = null;
     $remoteUrl = null;
     $flavorAsset = assetPeer::retrieveById($flavorAssetId);
     if (!$flavorAsset) {
         KalturaLog::err("No flavor asset found for id [{$flavorAssetId}]");
         return null;
     }
     if ($flavor->getSourceRemoteStorageProfileId() == StorageProfile::STORAGE_KALTURA_DC) {
         list($fileSync, $local) = kFileSyncUtils::getReadyFileSyncForKey($srcSyncKey, true, false);
         $partner = PartnerPeer::retrieveByPK($flavorAsset->getPartnerId());
         if (!$fileSync) {
             kBatchManager::updateEntry($flavorAsset->getEntryId(), entryStatus::ERROR_CONVERTING);
             $flavorAsset->setStatus(flavorAsset::FLAVOR_ASSET_STATUS_ERROR);
             $flavorAsset->setDescription("Source file sync not found: {$srcSyncKey}");
             $flavorAsset->save();
             KalturaLog::err("Source file sync not found: {$srcSyncKey}");
             return null;
         }
         if (!$local) {
             if ($fileSync->getFileType() == FileSync::FILE_SYNC_FILE_TYPE_URL && $partner && $partner->getImportRemoteSourceForConvert()) {
                 KalturaLog::debug("Creates import job for remote file sync");
                 $flavorAsset->setStatus(flavorAsset::FLAVOR_ASSET_STATUS_WAIT_FOR_CONVERT);
                 $flavorAsset->setDescription("Source file sync is importing: {$srcSyncKey}");
                 $flavorAsset->save();
                 $originalFlavorAsset = assetPeer::retrieveOriginalByEntryId($flavorAsset->getEntryId());
                 $url = $fileSync->getExternalUrl($flavorAsset->getEntryId());
                 return kJobsManager::addImportJob($parentJob, $flavorAsset->getEntryId(), $partner->getId(), $url, $originalFlavorAsset, null, null, true);
             }
             throw new kCoreException("Source file not found for flavor conversion [{$flavorAssetId}]", kCoreException::SOURCE_FILE_NOT_FOUND);
         }
         if ($fileSync->getFileType() != FileSync::FILE_SYNC_FILE_TYPE_URL) {
             $localPath = $fileSync->getFullPath();
         }
         $remoteUrl = $fileSync->getExternalUrl($flavorAsset->getEntryId());
     } else {
         $fileSync = kFileSyncUtils::getReadyExternalFileSyncForKey($srcSyncKey, $flavor->getSourceRemoteStorageProfileId());
         if (!$fileSync) {
             kBatchManager::updateEntry($flavorAsset->getEntryId(), entryStatus::ERROR_CONVERTING);
             $description = "Remote source file sync not found {$srcSyncKey}, storage profile id [" . $flavor->getSourceRemoteStorageProfileId() . "]";
             KalturaLog::err($description);
             $flavorAsset->setStatus(flavorAsset::FLAVOR_ASSET_STATUS_ERROR);
             $flavorAsset->setDescription($description);
             $flavorAsset->save();
             return null;
         }
         $localPath = $fileSync->getFilePath();
         $remoteUrl = $fileSync->getExternalUrl($flavorAsset->getEntryId());
     }
     $wamsAssetId = $fileSync->getWamsAssetId();
     // creates convert data
     $convertData = new kConvertJobData();
     $convertData->setSrcFileSyncLocalPath($localPath);
     $convertData->setSrcFileSyncRemoteUrl($remoteUrl);
     $convertData->setMediaInfoId($mediaInfoId);
     $convertData->setFlavorParamsOutputId($flavor->getId());
     $convertData->setFlavorAssetId($flavorAssetId);
     $convertData->setSrcFileSyncWamsAssetId($wamsAssetId);
     KalturaLog::log("Conversion engines string: '" . $flavor->getConversionEngines() . "'");
     $currentConversionEngine = null;
     // TODO remove after all old version flavors migrated
     // parse supported engine types
     $conversionEngines = array();
     if (!$flavor->getEngineVersion()) {
         $conversionEngines = explode(',', $flavor->getConversionEngines());
         KalturaLog::log(count($conversionEngines) . " conversion engines found for the flavor");
         $currentConversionEngine = reset($conversionEngines);
         // gets the first engine type
     }
     // remove until here
     if (is_null($lastEngineType)) {
         KalturaLog::log("Last Engine Type is null, engine version [" . $flavor->getEngineVersion() . "]");
         if ($flavor->getEngineVersion()) {
             $operatorSet = new kOperatorSets();
             $operatorSet->setSerialized($flavor->getOperators());
             $nextOperator = $operatorSet->getOperator();
             if (!$nextOperator) {
                 KalturaLog::err("First operator is invalid");
                 return null;
             }
             KalturaLog::log("Set first operator in first set");
             $currentConversionEngine = $nextOperator->id;
         }
     } else {
         if ($parentJob && $flavor->getEngineVersion() && ($parentJob->getJobType() == BatchJobType::CONVERT || $parentJob->getJobType() == BatchJobType::POSTCONVERT)) {
             // using next oprator
             KalturaLog::log("Adding next conversion operator");
             $parentData = $parentJob->getData();
             if (!$parentData || !$parentData instanceof kConvartableJobData) {
                 KalturaLog::err("Parent job data is invalid");
                 return null;
             }
             $operatorSet = new kOperatorSets();
             $operatorSet->setSerialized($flavor->getOperators());
             $nextOperatorSet = $parentData->getCurrentOperationSet();
             $nextOperatorIndex = $parentData->getCurrentOperationIndex() + 1;
             $nextOperator = $operatorSet->getOperator($nextOperatorSet, $nextOperatorIndex);
             if (!$nextOperator) {
                 KalturaLog::err("Next operator is invalid");
                 return null;
             }
             KalturaLog::log("Moving to next operator [{$nextOperatorIndex}] in set [{$nextOperatorSet}]");
             $convertData->setCurrentOperationSet($nextOperatorSet);
             $convertData->setCurrentOperationIndex($nextOperatorIndex);
             $currentConversionEngine = $nextOperator->id;
         } else {
             // TODO remove after all old version flavors migrated
             KalturaLog::log("Last used conversion engine is [{$lastEngineType}]");
             // searching for $lastEngineType in the list
             while ($lastEngineType != $currentConversionEngine && next($conversionEngines)) {
                 $currentConversionEngine = current($conversionEngines);
             }
             // takes the next engine
             $currentConversionEngine = next($conversionEngines);
             if (!$currentConversionEngine) {
                 KalturaLog::err("There is no other conversion engine to use");
                 return null;
             }
         }
     }
     if (!is_null($fileSync->getWamsAssetId())) {
         $currentConversionEngine = conversionEngineType::WAMS;
     }
     KalturaLog::log("Using conversion engine [{$currentConversionEngine}]");
     // creats a child convert job
     if (is_null($dbConvertFlavorJob)) {
         if ($parentJob) {
             $dbConvertFlavorJob = $parentJob->createChild();
             KalturaLog::log("Created from parent convert job with entry id [" . $dbConvertFlavorJob->getEntryId() . "]");
         } else {
             $dbConvertFlavorJob = new BatchJob();
             $dbConvertFlavorJob->setEntryId($flavor->getEntryId());
             $dbConvertFlavorJob->setPartnerId($flavor->getPartnerId());
             $dbConvertFlavorJob->save();
             KalturaLog::log("Created from flavor convert job with entry id [" . $dbConvertFlavorJob->getEntryId() . "]");
         }
     }
     if (!is_null($fileSync->getWamsAssetId())) {
         $srcFileSize = kWAMS::getInstance($flavor->getPartnerId())->getFileSizeForAssetId($fileSync->getWamsAssetId());
     } else {
         $srcFileSize = kFile::fileSize($convertData->getSrcFileSyncLocalPath());
     }
     $dbConvertFlavorJob->setFileSize($srcFileSize);
     // TODO remove after all old version flavors migrated
     if (in_array(conversionEngineType::ENCODING_COM, $conversionEngines)) {
         $dbConvertFlavorJob->setOnStressDivertTo(conversionEngineType::ENCODING_COM);
     }
     // remove until here
     /*
     	// Remarked by Dor until Tantan's return.
     	// Code is supposed to get a configuration file from the engine and attach it to the batch job.
     	// Was added for document conversion and is not used for now because of a bug of PDFCreator.
     
     KalturaLog::log("Calling CDLProceessFlavor with flavor params output[" . $flavor->getId() . "]");
     $config = KDLWrap::CDLProceessFlavor($flavor);
     if($config)
     {
     	$syncKey = $dbConvertFlavorJob->getSyncKey(BatchJob::FILE_SYNC_BATCHJOB_SUB_TYPE_CONFIG);
     	kFileSyncUtils::file_put_contents($syncKey, $config);
     	
     	$fileSync = kFileSyncUtils::getLocalFileSyncForKey($syncKey);
     	$remoteUrl = $fileSync->getExternalUrl($flavor->getEntryId());
     	$localPath = kFileSyncUtils::getLocalFilePathForKey($syncKey);
     	
     	$convertData->setConfigLocalPath($localPath);
     	$convertData->setConfigRemoteUrl($remoteUrl);
     }
     */
     $dbCurrentConversionEngine = kPluginableEnumsManager::apiToCore('conversionEngineType', $currentConversionEngine);
     return kJobsManager::addJob($dbConvertFlavorJob, $convertData, BatchJobType::CONVERT, $dbCurrentConversionEngine);
 }
 /**
  * Will forward to the regular swf player according to the widget_id 
  */
 public function execute()
 {
     requestUtils::handleConditionalGet();
     $wams_asset_id = NULL;
     $wams_url = NULL;
     $entry_id = $this->getRequestParameter("entry_id");
     $type = $this->getRequestParameter("type");
     $ks = $this->getRequestParameter("ks");
     $file_sync = null;
     $ret_file_name = "name";
     $referrer = $this->getRequestParameter("referrer");
     $referrer = base64_decode($referrer);
     if (!is_string($referrer)) {
         // base64_decode can return binary data
         $referrer = "";
     }
     $request_file_name = $this->getRequestParameter("file_name");
     if ($request_file_name) {
         $ret_file_name = $request_file_name;
     }
     $direct_serve = $this->getRequestParameter("direct_serve");
     $entry = null;
     if ($ks) {
         try {
             kCurrentContext::initKsPartnerUser($ks);
         } catch (Exception $ex) {
             KExternalErrors::dieError(KExternalErrors::INVALID_KS);
         }
     } else {
         $entry = kCurrentContext::initPartnerByEntryId($entry_id);
         if (!$entry) {
             die;
         }
     }
     kEntitlementUtils::initEntitlementEnforcement();
     if (!$entry) {
         $entry = entryPeer::retrieveByPK($entry_id);
         if (!$entry) {
             die;
         }
     } else {
         if (!kEntitlementUtils::isEntryEntitled($entry)) {
             die;
         }
     }
     myPartnerUtils::blockInactivePartner($entry->getPartnerId());
     $securyEntryHelper = new KSecureEntryHelper($entry, $ks, $referrer, accessControlContextType::DOWNLOAD);
     $securyEntryHelper->validateForDownload();
     //		Rmoved by Tan-Tan - asked by Eran
     //		// allow access only via cdn unless these are documents (due to the current implementation of convert ppt2swf)
     //		if ($entry->getType() != entryType::DOCUMENT && $entry->getMediaType() != entry::ENTRY_MEDIA_TYPE_IMAGE)
     //		{
     //			requestUtils::enforceCdnDelivery($entry->getPartnerId());
     //		}
     // relocate = did we use the redirect and added the extension to the name
     $relocate = $this->getRequestParameter("relocate");
     if ($ret_file_name == "name") {
         $ret_file_name = $entry->getName();
     }
     if ($ret_file_name) {
         //rawurlencode to content-disposition filename to handle spaces and other characters across different browsers
         //$name = rawurlencode($ret_file_name);
         // 19.04.2009 (Roman) - url encode is not needed when the filename in Content-Disposition header is in quotes
         // IE6/FF3/Chrome - Will show the filename correctly
         // IE7 - Will show the filename with underscores instead of spaces (this is better than showing %20)
         $name = $ret_file_name;
         if ($name) {
             if ($relocate) {
                 // if we have a good file extension (from the first time) - use it in the content-disposition
                 // in some browsers it will be stronger than the URL's extension
                 $file_ext = pathinfo($relocate, PATHINFO_EXTENSION);
                 $name .= ".{$file_ext}";
             }
             if (!$direct_serve) {
                 header("Content-Disposition: attachment; filename=\"{$name}\"");
             }
         }
     } else {
         $ret_file_name = $entry_id;
     }
     $format = $this->getRequestParameter("format");
     if ($type == "download" && $format && $entry->getType() != entryType::DOCUMENT) {
         // this is a video for a specifc extension - use the proper flavorAsset
         $flavor_asset = assetPeer::retrieveByEntryIdAndExtension($entry_id, $format);
         if ($flavor_asset && $flavor_asset->getStatus() == flavorAsset::FLAVOR_ASSET_STATUS_READY) {
             $file_sync = $this->redirectIfRemote($flavor_asset, flavorAsset::FILE_SYNC_FLAVOR_ASSET_SUB_TYPE_ASSET, null, true);
         } else {
             header('KalturaRaw: no flavor asset for extension');
             header("HTTP/1.0 404 Not Found");
             die;
         }
         $archive_file = $file_sync->getFullPath();
         $mime_type = kFile::mimeType($archive_file);
         kFile::dumpFile($archive_file, $mime_type);
     }
     // TODO - move to a different action - document should be plugin
     if ($entry->getType() == entryType::DOCUMENT) {
         // use the fileSync from the entry
         if ($type == "download" && $format) {
             $flavor_asset = assetPeer::retrieveByEntryIdAndExtension($entry_id, $format);
         } else {
             $flavor_asset = assetPeer::retrieveOriginalByEntryId($entry_id);
         }
         if ($flavor_asset && $flavor_asset->getStatus() == flavorAsset::FLAVOR_ASSET_STATUS_READY) {
             $file_sync = $this->redirectIfRemote($flavor_asset, flavorAsset::FILE_SYNC_FLAVOR_ASSET_SUB_TYPE_ASSET, null, true);
         } else {
             header('KalturaRaw: no flavor asset for extension');
             header("HTTP/1.0 404 Not Found");
             die;
         }
         // Gonen 2010-08-05 workaround to make sure file name includes correct extension
         // make sure a file extension is added to the downloaded file so browser will identify and
         // allow opening with default program
         // for direct serve we do not want to send content-disposition header
         if (!$direct_serve) {
             $ext = pathinfo($file_sync->getFullPath(), PATHINFO_EXTENSION);
             if ($relocate) {
                 // remove relocate file extension
                 $reloc_ext = pathinfo($relocate, PATHINFO_EXTENSION);
                 $name = str_replace(".{$reloc_ext}", '', $name);
             }
             header("Content-Disposition: attachment; filename=\"{$name}.{$ext}\"");
         }
         kFile::dumpFile($file_sync->getFullPath());
     } elseif ($entry->getType() == entryType::DATA) {
         $version = $this->getRequestParameter("version");
         $syncKey = $entry->getSyncKey(entry::FILE_SYNC_ENTRY_SUB_TYPE_DATA, $version);
         list($fileSync, $local) = kFileSyncUtils::getReadyFileSyncForKey($syncKey, true, false);
         if ($local) {
             $path = $fileSync->getFullPath();
         } else {
             $path = kDataCenterMgr::getRedirectExternalUrl($fileSync);
             KalturaLog::info("Redirecting to [{$path}]");
         }
         if (!$path) {
             header('KalturaRaw: no data was found available for download');
             header("HTTP/1.0 404 Not Found");
         } else {
             kFile::dumpFile($path);
         }
     }
     //$archive_file = $entry->getArchiveFile();
     $media_type = $entry->getMediaType();
     if ($media_type == entry::ENTRY_MEDIA_TYPE_IMAGE) {
         // image - use data for entry
         $file_sync = $this->redirectIfRemote($entry, entry::FILE_SYNC_ENTRY_SUB_TYPE_DATA, null);
         $key = $entry->getSyncKey(entry::FILE_SYNC_ENTRY_SUB_TYPE_DATA);
         kFile::dumpFile(kFileSyncUtils::getLocalFilePathForKey($key, true));
     } elseif ($media_type == entry::ENTRY_MEDIA_TYPE_VIDEO || $media_type == entry::ENTRY_MEDIA_TYPE_AUDIO) {
         $format = $this->getRequestParameter("format");
         if ($type == "download" && $format) {
             // this is a video for a specifc extension - use the proper flavorAsset
             $flavor_asset = assetPeer::retrieveByEntryIdAndExtension($entry_id, $format);
             if ($flavor_asset && $flavor_asset->getStatus() == flavorAsset::FLAVOR_ASSET_STATUS_READY) {
                 $file_sync = $this->redirectIfRemote($flavor_asset, flavorAsset::FILE_SYNC_FLAVOR_ASSET_SUB_TYPE_ASSET, null, true);
             } else {
                 header('KalturaRaw: no flavor asset for extension');
                 die;
             }
             $archive_file = $file_sync->getFullPath();
         } else {
             // flavorAsset of the original
             $flavor_asset = assetPeer::retrieveOriginalByEntryId($entry_id);
             if ($flavor_asset && $flavor_asset->getStatus() == flavorAsset::FLAVOR_ASSET_STATUS_READY) {
                 $file_sync = $this->redirectIfRemote($flavor_asset, flavorAsset::FILE_SYNC_FLAVOR_ASSET_SUB_TYPE_ASSET, null, false);
                 // NOT strict - if there is no archive, get the data version
                 if ($file_sync) {
                     $wams_asset_id = $file_sync->getWamsAssetId();
                     $archive_file = $file_sync->getFullPath();
                 }
             }
             if (!$flavor_asset || !$file_sync || $flavor_asset->getStatus() != flavorAsset::FLAVOR_ASSET_STATUS_READY) {
                 // either no archive asset or no fileSync for archive asset
                 // use fallback flavorAsset
                 $flavor_asset = assetPeer::retrieveBestPlayByEntryId($entry_id);
                 if (!$flavor_asset) {
                     header('KalturaRaw: no original flavor asset for entry, no best play asset for entry');
                     die;
                 }
                 $file_sync = $this->redirectIfRemote($flavor_asset, flavorAsset::FILE_SYNC_FLAVOR_ASSET_SUB_TYPE_ASSET, null, false);
                 // NOT strict - if there is no archive, get the data version
                 $archive_file = $file_sync->getFullPath();
             }
         }
     } elseif ($media_type == entry::ENTRY_MEDIA_TYPE_SHOW) {
         // in this case "raw" is a bad name
         // TODO - add the ability to fetch the actual XML by flagging "xml" or something
         $version = $this->getRequestParameter("version");
         // hotfix - links sent after flattening is done look like:
         // http://cdn.kaltura.com/p/387/sp/38700/raw/entry_id/0_ix99151g/version/100001
         // while waiting for flavor-adaptation in flattening, we want to find at least one file to return.
         $try_formats = array('mp4', 'mov', 'avi', 'flv');
         if ($format) {
             $key = array_search($format, $try_formats);
             if ($key !== FALSE) {
                 unset($try_formats[$key]);
             }
             $file_sync = $this->redirectIfRemote($entry, entry::FILE_SYNC_ENTRY_SUB_TYPE_DOWNLOAD, $format, false);
         }
         if (!isset($file_sync) || !$file_sync || !file_exists($file_sync->getFullPath())) {
             foreach ($try_formats as $ext) {
                 KalturaLog::log("raw for mix - trying to find filesync for extension: [{$ext}] on entry [{$entry->getId()}]");
                 $file_sync = $this->redirectIfRemote($entry, entry::FILE_SYNC_ENTRY_SUB_TYPE_DOWNLOAD, $ext, false);
                 if ($file_sync && file_exists($file_sync->getFullPath())) {
                     KalturaLog::log("raw for mix - found flattened video of extension: [{$ext}] continuing with this file {$file_sync->getFullPath()}");
                     break;
                 }
             }
             if (!$file_sync || !file_exists($file_sync->getFullPath())) {
                 $file_sync = $this->redirectIfRemote($entry, entry::FILE_SYNC_ENTRY_SUB_TYPE_DOWNLOAD, $ext, true);
             }
         }
         // use fileSync for entry - roughcuts don't have flavors
         //$file_sync =  $this->redirectIfRemote ( $entry ,  entry::FILE_SYNC_ENTRY_SUB_TYPE_DOWNLOAD , $version , true );  // strict - nothing to do if no flattened version
         // if got to here - fileSync was found for one of the extensions - continue with that file
         $archive_file = $file_sync->getFullPath();
     } else {
         // no archive for this file
         header("HTTP/1.0 404 Not Found");
         die;
     }
     //		echo "[$archive_file][" . file_exists ( $archive_file ) . "]";
     if (empty($wams_asset_id)) {
         $mime_type = kFile::mimeType($archive_file);
     }
     //		echo "[[$mime_type]]";
     $shouldProxy = $this->getRequestParameter("forceproxy", false);
     if ($shouldProxy || !empty($relocate)) {
         if (!empty($wams_asset_id)) {
             $fileExt = pathinfo($archive_file, PATHINFO_EXTENSION);
             kWAMS::getInstance($entry->getPartnerId())->dumpFile($wams_asset_id, $fileExt);
             die;
         } else {
             // dump the file
             kFile::dumpFile($archive_file, $mime_type);
             die;
         }
     }
     // use new Location to add the best extension we can find for the file
     $file_ext = pathinfo($archive_file, PATHINFO_EXTENSION);
     if ($file_ext != "flv") {
         // if the file does not end with "flv" - it is the real extension
         $ext = $file_ext;
     } else {
         // for now - if "flv" return "flv" - // TODO - find the real extension from the file itself
         $ext = "flv";
     }
     // rebuild the URL and redirect to it with extraa parameters
     $url = $_SERVER["REQUEST_URI"];
     $format = $this->getRequestParameter("format");
     if (!$format) {
         $url = str_replace("format", "", $url);
     }
     if (!$ret_file_name) {
         // don't leave the name empty - if it is empty - use the entry id
         $ret_file_name = $entry_id;
     }
     $ret_file_name_safe = str_replace(' ', '-', $ret_file_name);
     // spaces replace with "-"
     $ret_file_name_safe = preg_replace('/[^a-zA-Z0-9-_]/', '', $ret_file_name_safe);
     // only "a-z", "A-Z", "0-9", "-" & "_" are left
     if (strpos($url, "?") > 0) {
         $url = str_replace("?", "/{$ret_file_name_safe}.{$ext}?", $url);
         $url .= "&relocate=f.{$ext}";
         // add the ufname as a query parameter
     } else {
         $url .= "/{$ret_file_name_safe}.{$ext}?relocate=f.{$ext}";
         // add the ufname as a query parameter
     }
     // or redirect if no proxy
     header("Location: {$url}");
     die;
 }
 /**
  * Will take a single KalturaBatchJob and extract the media info for the given file 
  */
 private function extract(KalturaBatchJob $job, KalturaExtractMediaJobData $data)
 {
     KalturaLog::debug("extract({$job->id})");
     $mediaFile = trim($data->srcFileSyncLocalPath);
     $mediaFileExt = pathinfo($mediaFile, PATHINFO_EXTENSION);
     if (!is_null($data->srcFileSyncWamsAssetId)) {
         $tempFile = kWAMS::getInstance($job->partnerId)->createTempFileForAssetId($data->srcFileSyncWamsAssetId, $mediaFileExt);
         if (file_exists($tempFile)) {
             $mediaFile = $tempFile;
         }
     }
     if (!$this->pollingFileExists($mediaFile)) {
         return $this->closeJob($job, KalturaBatchJobErrorTypes::APP, KalturaBatchJobAppErrors::NFS_FILE_DOESNT_EXIST, "Source file {$mediaFile} does not exist", KalturaBatchJobStatus::RETRY);
     }
     if (!is_file($mediaFile)) {
         return $this->closeJob($job, KalturaBatchJobErrorTypes::APP, KalturaBatchJobAppErrors::NFS_FILE_DOESNT_EXIST, "Source file {$mediaFile} is not a file", KalturaBatchJobStatus::FAILED);
     }
     KalturaLog::debug("mediaFile [{$mediaFile}]");
     $this->updateJob($job, "Extracting file media info on {$mediaFile}", KalturaBatchJobStatus::QUEUED, 1);
     $mediaInfo = null;
     try {
         $mediaFile = realpath($mediaFile);
         KalturaLog::debug("file path [{$mediaFile}]");
         $engine = KBaseMediaParser::getParser($job->jobSubType, $mediaFile, $this->taskConfig, $job, $data->srcFileSyncWamsAssetId);
         if ($engine) {
             KalturaLog::debug("Found engine [" . get_class($engine) . "]");
             $mediaInfo = $engine->getMediaInfo();
             if (!is_null($data->srcFileSyncWamsAssetId)) {
                 kWAMS::getInstance($job->partnerId)->deleteTempFileForAssetId($data->srcFileSyncWamsAssetId, $mediaFileExt);
             }
         } else {
             $err = "No media info parser engine found for job sub type [{$job->jobSubType}]";
             return $this->closeJob($job, KalturaBatchJobErrorTypes::APP, KalturaBatchJobAppErrors::ENGINE_NOT_FOUND, $err, KalturaBatchJobStatus::FAILED);
         }
     } catch (Exception $ex) {
         KalturaLog::err($ex->getMessage());
         $mediaInfo = null;
     }
     if (is_null($mediaInfo)) {
         return $this->closeJob($job, KalturaBatchJobErrorTypes::APP, KalturaBatchJobAppErrors::EXTRACT_MEDIA_FAILED, "Failed to extract media info: {$mediaFile}", KalturaBatchJobStatus::RETRY);
     }
     KalturaLog::debug("flavorAssetId [{$data->flavorAssetId}]");
     $mediaInfo->flavorAssetId = $data->flavorAssetId;
     $mediaInfo = $this->getClient()->batch->addMediaInfo($mediaInfo);
     $data->mediaInfoId = $mediaInfo->id;
     $this->updateJob($job, "Saving media info id {$mediaInfo->id}", KalturaBatchJobStatus::PROCESSED, 99, $data);
     $this->closeJob($job, null, null, null, KalturaBatchJobStatus::FINISHED);
     return $job;
 }
 /**
  * Replace content associated with the media entry.
  * 
  * @action updateContent
  * @param string $entryId Media entry id to update
  * @param KalturaResource $resource Resource to be used to replace entry media content
  * @param int $conversionProfileId The conversion profile id to be used on the entry
  * @return KalturaMediaEntry The updated media entry
  * @throws KalturaErrors::ENTRY_ID_NOT_FOUND
  * @throws KalturaErrors::ENTRY_REPLACEMENT_ALREADY_EXISTS
  * @throws KalturaErrors::INVALID_OBJECT_ID
  * @validateUser entry entryId edit
  */
 function updateContentAction($entryId, KalturaResource $resource, $conversionProfileId = null)
 {
     $dbEntry = entryPeer::retrieveByPK($entryId);
     if (!$dbEntry || $dbEntry->getType() != KalturaEntryType::MEDIA_CLIP) {
         throw new KalturaAPIException(KalturaErrors::ENTRY_ID_NOT_FOUND, $entryId);
     }
     kWAMS::testConnection($this->getPartner()->getWamsAccountName(), $this->getPartner()->getWamsAccountKey());
     $this->replaceResource($resource, $dbEntry, $conversionProfileId);
     return $this->getEntry($entryId);
 }
 /**
  * @param AttachmentAsset $attachmentAsset
  * @param string $fullPath
  * @param bool $copyOnly
  */
 protected function attachFile(AttachmentAsset $attachmentAsset, $fullPath, $copyOnly = false)
 {
     $ext = pathinfo($fullPath, PATHINFO_EXTENSION);
     $attachmentAsset->incrementVersion();
     $attachmentAsset->setFileExt($ext);
     $attachmentAsset->setSize(kFile::fileSize($fullPath));
     $attachmentAsset->save();
     $syncKey = $attachmentAsset->getSyncKey(AttachmentAsset::FILE_SYNC_ASSET_SUB_TYPE_ASSET);
     try {
         kFileSyncUtils::moveFromFile($fullPath, $syncKey, true, $copyOnly);
     } catch (Exception $e) {
         if ($attachmentAsset->getStatus() == AttachmentAsset::ASSET_STATUS_QUEUED || $attachmentAsset->getStatus() == AttachmentAsset::ASSET_STATUS_NOT_APPLICABLE) {
             $attachmentAsset->setDescription($e->getMessage());
             $attachmentAsset->setStatus(AttachmentAsset::ASSET_STATUS_ERROR);
             $attachmentAsset->save();
         }
         throw $e;
     }
     $finalPath = kFileSyncUtils::getLocalFilePathForKey($syncKey);
     $wamsURL = kFileSyncUtils::getWamsURLForKey($syncKey);
     if (empty($wamsURL)) {
         list($width, $height, $type, $attr) = getimagesize($finalPath);
         $fileSize = kFile::fileSize($finalPath);
     } else {
         list($width, $height, $type, $attr) = getimagesize($wamsURL);
         $wamsAssetId = kFileSyncUtils::getWamsAssetIdForKey($syncKey);
         $fileSize = kWAMS::getInstance($syncKey->getPartnerId())->getFileSizeForAssetId($wamsAssetId, pathinfo($finalPath, PATHINFO_EXTENSION));
     }
     $attachmentAsset->setWidth($width);
     $attachmentAsset->setHeight($height);
     $attachmentAsset->setSize($fileSize);
     $attachmentAsset->setStatus(AttachmentAsset::ASSET_STATUS_READY);
     $attachmentAsset->save();
 }
 /**
  * @param ISyncableFile $syncable
  * @param int $fileSubType
  * @param string $fileName
  * @param bool $forceProxy
  * @throws KalturaErrors::FILE_DOESNT_EXIST
  */
 protected function serveFile(ISyncableFile $syncable, $fileSubType, $fileName, $entryId = null, $forceProxy = false)
 {
     /* @var $fileSync FileSync */
     $syncKey = $syncable->getSyncKey($fileSubType);
     if (!kFileSyncUtils::fileSync_exists($syncKey)) {
         throw new KalturaAPIException(KalturaErrors::FILE_DOESNT_EXIST);
     }
     list($fileSync, $local) = kFileSyncUtils::getReadyFileSyncForKey($syncKey, true, false);
     header("Content-Disposition: attachment; filename=\"{$fileName}\"");
     if ($local) {
         $filePath = $fileSync->getFullPath();
         $wamsAssetId = $fileSync->getWamsAssetId();
         if (empty($wamsAssetId)) {
             $mimeType = kFile::mimeType($filePath);
             kFile::dumpFile($filePath, $mimeType);
         } else {
             kWAMS::getInstance($fileSync->getPartnerId())->dumpFile($wamsAssetId, pathinfo($filePath, PATHINFO_EXTENSION));
         }
     } else {
         if (in_array($fileSync->getDc(), kDataCenterMgr::getDcIds())) {
             $remoteUrl = kDataCenterMgr::getRedirectExternalUrl($fileSync);
             KalturaLog::info("Redirecting to [{$remoteUrl}]");
             if ($forceProxy) {
                 kFile::dumpApiRequest($remoteUrl);
             } else {
                 //TODO find or build function which redurects the API request with all its parameters without using curl.
                 // or redirect if no proxy
                 header("Location: {$remoteUrl}");
                 die;
             }
         } else {
             $remoteUrl = $fileSync->getExternalUrl($entryId);
             header("Location: {$remoteUrl}");
             die;
         }
     }
 }
 protected function getTempFilePath($remotePath)
 {
     // create a temp file path
     $origRemotePath = $remotePath;
     $rootPath = $this->taskConfig->params->localTempPath;
     $res = self::createDir($rootPath);
     if (!$res) {
         KalturaLog::err("Cannot continue import without temp directory");
         die;
     }
     $uniqid = uniqid('import_');
     $destFile = realpath($rootPath) . "/{$uniqid}";
     // in case the url has added arguments, remove them (and reveal the real URL path)
     // in order to find the file extension
     $urlPathEndIndex = strpos($remotePath, "?");
     if ($urlPathEndIndex !== false) {
         $remotePath = substr($remotePath, 0, $urlPathEndIndex);
     }
     $ext = pathinfo($remotePath, PATHINFO_EXTENSION);
     $ext = strtolower($ext);
     if (!in_array($ext, kWAMS::getSupportedFormats())) {
         $remoteExt = kWAMS::getFileExtFromURL($origRemotePath);
         if (!empty($remoteExt)) {
             $ext = $remoteExt;
         }
     }
     if (strlen($ext)) {
         $destFile .= ".{$ext}";
     }
     return $destFile;
 }
 /**
  * @param BatchJob $dbBatchJob
  * @param kConvertJobData $data
  * @param BatchJob $twinJob
  * @return BatchJob
  */
 public static function handleConvertFinished(BatchJob $dbBatchJob, kConvertJobData $data, BatchJob $twinJob = null)
 {
     KalturaLog::debug("Convert finished with destination file: " . $data->getDestFileSyncLocalPath());
     if ($dbBatchJob->getAbort()) {
         kWAMS::getInstance($dbBatchJob->getPartnerId())->deleteAssetById($data->getDestFileSyncWamsAssetId());
         return $dbBatchJob;
     }
     // verifies that flavor asset created
     if (!$data->getFlavorAssetId()) {
         throw new APIException(APIErrors::INVALID_FLAVOR_ASSET_ID, $data->getFlavorAssetId());
     }
     $flavorAsset = assetPeer::retrieveById($data->getFlavorAssetId());
     // verifies that flavor asset exists
     if (!$flavorAsset) {
         throw new APIException(APIErrors::INVALID_FLAVOR_ASSET_ID, $data->getFlavorAssetId());
     }
     $flavorAsset->incrementVersion();
     $flavorAsset->save();
     $syncKey = $flavorAsset->getSyncKey(flavorAsset::FILE_SYNC_FLAVOR_ASSET_SUB_TYPE_ASSET);
     $flavorParamsOutput = $data->getFlavorParamsOutput();
     $storageProfileId = $flavorParamsOutput->getSourceRemoteStorageProfileId();
     if ($storageProfileId == StorageProfile::STORAGE_KALTURA_DC) {
         $destFileSyncWamsAssetId = $data->getDestFileSyncWamsAssetId();
         if (!empty($destFileSyncWamsAssetId)) {
             kFileSyncUtils::addFromWAMS($destFileSyncWamsAssetId, $syncKey);
         } else {
             kFileSyncUtils::moveFromFile($data->getDestFileSyncLocalPath(), $syncKey);
         }
     } elseif ($flavorParamsOutput->getRemoteStorageProfileIds()) {
         $remoteStorageProfileIds = explode(',', $flavorParamsOutput->getRemoteStorageProfileIds());
         foreach ($remoteStorageProfileIds as $remoteStorageProfileId) {
             $storageProfile = StorageProfilePeer::retrieveByPK($remoteStorageProfileId);
             kFileSyncUtils::createReadyExternalSyncFileForKey($syncKey, $data->getDestFileSyncLocalPath(), $storageProfile);
         }
     }
     // creats the file sync
     if (file_exists($data->getLogFileSyncLocalPath())) {
         $logSyncKey = $flavorAsset->getSyncKey(flavorAsset::FILE_SYNC_FLAVOR_ASSET_SUB_TYPE_CONVERT_LOG);
         try {
             kFileSyncUtils::moveFromFile($data->getLogFileSyncLocalPath(), $logSyncKey);
         } catch (Exception $e) {
             $err = 'Saving conversion log: ' . $e->getMessage();
             KalturaLog::err($err);
             $desc = $dbBatchJob->getDescription() . "\n" . $err;
             $dbBatchJob->getDescription($desc);
         }
     }
     if ($storageProfileId == StorageProfile::STORAGE_KALTURA_DC) {
         $data->setDestFileSyncLocalPath(kFileSyncUtils::getLocalFilePathForKey($syncKey));
         KalturaLog::debug("Convert archived file to: " . $data->getDestFileSyncLocalPath());
         // save the data changes to the db
         $dbBatchJob->setData($data);
         $dbBatchJob->save();
     }
     $entry = $dbBatchJob->getEntry();
     if (!$entry) {
         throw new APIException(APIErrors::INVALID_ENTRY, $dbBatchJob, $dbBatchJob->getEntryId());
     }
     $offset = $entry->getThumbOffset();
     // entry getThumbOffset now takes the partner DefThumbOffset into consideration
     $createThumb = $entry->getCreateThumb();
     $extractMedia = true;
     if ($entry->getType() != entryType::MEDIA_CLIP) {
         // e.g. document
         $extractMedia = false;
     }
     $rootBatchJob = $dbBatchJob->getRootJob();
     if ($extractMedia && $rootBatchJob && $rootBatchJob->getJobType() == BatchJobType::CONVERT_PROFILE) {
         $rootBatchJobData = $rootBatchJob->getData();
         if ($rootBatchJobData instanceof kConvertProfileJobData) {
             $extractMedia = $rootBatchJobData->getExtractMedia();
         }
     }
     // For apple http flavors do not attempt to get thumbs and media info,
     // It is up to the operator to provide that kind of data, rather than hardcoded check
     // To-fix
     if ($flavorParamsOutput->getFormat() == assetParams::CONTAINER_FORMAT_APPLEHTTP) {
         $createThumb = false;
         $extractMedia = false;
     }
     if ($createThumb && in_array($flavorParamsOutput->getVideoCodec(), self::$thumbUnSupportVideoCodecs)) {
         $createThumb = false;
     }
     $operatorSet = new kOperatorSets();
     $operatorSet->setSerialized(stripslashes($flavorParamsOutput->getOperators()));
     //		KalturaLog::debug("Operators: ".$flavorParamsOutput->getOperators()
     //			."\ngetCurrentOperationSet:".$data->getCurrentOperationSet()
     //			."\ngetCurrentOperationIndex:".$data->getCurrentOperationIndex());
     //		KalturaLog::debug("Operators set: " . print_r($operatorSet, true));
     $nextOperator = $operatorSet->getOperator($data->getCurrentOperationSet(), $data->getCurrentOperationIndex() + 1);
     $nextJob = null;
     if ($nextOperator) {
         //			KalturaLog::debug("Found next operator");
         $nextJob = kJobsManager::addFlavorConvertJob($syncKey, $flavorParamsOutput, $data->getFlavorAssetId(), $data->getMediaInfoId(), $dbBatchJob, $dbBatchJob->getJobSubType());
     }
     if (!$nextJob) {
         if ($createThumb || $extractMedia) {
             $postConvertAssetType = BatchJob::POSTCONVERT_ASSET_TYPE_FLAVOR;
             if ($flavorAsset->getIsOriginal()) {
                 $postConvertAssetType = BatchJob::POSTCONVERT_ASSET_TYPE_SOURCE;
             }
             kJobsManager::addPostConvertJob($dbBatchJob, $postConvertAssetType, $data->getDestFileSyncLocalPath(), $data->getFlavorAssetId(), $flavorParamsOutput->getId(), $createThumb, $offset, $data->getCustomData(), $data->getDestFileSyncWamsAssetId());
         } else {
             $flavorAsset = kBusinessPostConvertDL::handleFlavorReady($dbBatchJob, $data->getFlavorAssetId());
             if ($flavorAsset) {
                 if ($flavorAsset->hasTag(flavorParams::TAG_SOURCE)) {
                     kBusinessPreConvertDL::continueProfileConvert($dbBatchJob);
                 }
                 if ($flavorAsset->getType() == assetType::FLAVOR) {
                     $flavorAsset->setBitrate($flavorParamsOutput->getVideoBitrate() + $flavorParamsOutput->getAudioBitrate());
                     $flavorAsset->setWidth($flavorParamsOutput->getWidth());
                     $flavorAsset->setHeight($flavorParamsOutput->getHeight());
                     $flavorAsset->setFrameRate($flavorParamsOutput->getFrameRate());
                     $flavorAsset->setIsOriginal(0);
                     $flavorAsset->save();
                 }
                 kBusinessPostConvertDL::handleConvertFinished($dbBatchJob, $flavorAsset);
             }
         }
     }
     // this logic decide when a thumbnail should be created
     if ($rootBatchJob && $rootBatchJob->getJobType() == BatchJobType::BULKDOWNLOAD) {
         $localPath = kFileSyncUtils::getLocalFilePathForKey($syncKey);
         $downloadUrl = $flavorAsset->getDownloadUrl();
         $notificationData = array("puserId" => $entry->getPuserId(), "entryId" => $entry->getId(), "entryIntId" => $entry->getIntId(), "entryVersion" => $entry->getVersion(), "fileFormat" => $flavorAsset->getFileExt(), "archivedFile" => $localPath, "downoladPath" => $localPath, "conversionQuality" => $entry->getConversionQuality(), "downloadUrl" => $downloadUrl);
         $extraData = array("data" => json_encode($notificationData), "partner_id" => $entry->getPartnerId(), "puser_id" => $entry->getPuserId(), "entry_id" => $entry->getId(), "entry_int_id" => $entry->getIntId(), "entry_version" => $entry->getVersion(), "file_format" => $flavorAsset->getFileExt(), "archived_file" => $localPath, "downolad_path" => $localPath, "target" => $localPath, "conversion_quality" => $entry->getConversionQuality(), "download_url" => $downloadUrl, "status" => $entry->getStatus(), "abort" => $dbBatchJob->getAbort(), "progress" => $dbBatchJob->getProgress(), "message" => $dbBatchJob->getMessage(), "description" => $dbBatchJob->getDescription(), "updates_count" => $dbBatchJob->getUpdatesCount(), "job_type" => BatchJobType::DOWNLOAD, "status" => BatchJob::BATCHJOB_STATUS_FINISHED, "progress" => 100, "debug" => __LINE__);
         myNotificationMgr::createNotification(kNotificationJobData::NOTIFICATION_TYPE_BATCH_JOB_SUCCEEDED, $dbBatchJob, $dbBatchJob->getPartnerId(), null, null, $extraData, $dbBatchJob->getEntryId());
     }
     return $dbBatchJob;
 }