PageRenderTime 46ms CodeModel.GetById 19ms RepoModel.GetById 1ms app.codeStats 0ms

/package/app/app/alpha/apps/kaltura/lib/myContentStorage.class.php

https://bitbucket.org/pandaos/kaltura
PHP | 416 lines | 272 code | 61 blank | 83 comment | 58 complexity | 56fc6aafe469228f88566ede71338c2f MD5 | raw file
Possible License(s): AGPL-3.0, GPL-3.0, BSD-3-Clause, LGPL-2.1, GPL-2.0, LGPL-3.0, JSON, MPL-2.0-no-copyleft-exception, Apache-2.0
  1. <?php
  2. class myContentStorage
  3. {
  4. const MIN_OBFUSCATOR_VALUE = 100000;
  5. const MAX_OBFUSCATOR_VALUE = 100000; // fixme - while we test generate constant obfuscators
  6. //const MAX_OBFUSCATOR_VALUE = 900000;
  7. // TODO - IMPROVE ? - may want to include the getFSContentRootPath as the beginning of the path because it's appended to
  8. // in the beginning everytime anyway in the caller's code - Eran ?
  9. public static function isTemplate ( $file_name )
  10. {
  11. return ( strstr ( $file_name, "&") !== FALSE );
  12. }
  13. /**
  14. * This function returns the file system path for a requested content entity.
  15. * The given file name is of the form last_ugc_version.ext&kaltua_template
  16. * last_ugc_version - the last version of ugc the user uploaded
  17. * kaltura_template - a kaltura made content available for the user
  18. * each one of these two may be omitted.
  19. * A user never uploaded his own content : "&kaltura_template"
  20. * A user uploaded his own content : "ugc_version"
  21. * A user replaced his old content with a template : "last_ugc_version&kaltura_template"
  22. * This way we keep the last version the user used. This allows us to force caching of the UGC
  23. * on the browser side without even checking for modification on the server side. A new ugc will
  24. * simply get another name through the version process.
  25. * When we want to set a kaltura template will set the $fileName parameter to '&'.kaltura_template_name.
  26. * The path is composed from the entity name (kshow, entry, kuser),
  27. * the entity id and it's random obfuscator (which is used also for versioning)
  28. * @param string $entityName = the entity object name
  29. * @param int $id = the entity id
  30. * @param int $fileName = random obfuscator followed by the file extension (.jpg, .flv, .txt, etc...)
  31. * @return string the content path
  32. */
  33. public static function getGeneralEntityPath($entityName, $int_id, $id, $fileName , $version = null )
  34. {
  35. if( $version != null )
  36. {
  37. $ext = pathinfo ($fileName , PATHINFO_EXTENSION);
  38. $fileName = $version;
  39. }
  40. $c = strstr($fileName, '^') ? '^' : '&';
  41. $parts = explode($c, $fileName);
  42. if (count($parts) == 2 && strlen($parts[1]))
  43. {
  44. $res = ($c == '^' ? '/content/templates/' : '/content/templates/').$entityName.'/'.$parts[1];
  45. }
  46. else
  47. {
  48. $res = '/content/'.$entityName.'/'. self::dirForId ( $int_id, $id ) .'_'.$fileName;
  49. }
  50. if( $version != null )
  51. {
  52. $res .= "." . $ext;
  53. }
  54. return $res;
  55. }
  56. /*
  57. public static function dirForId ( $id )
  58. {
  59. return (intval($id / 1048576)).'/'. (intval($id / 1024) % 1024).'/'.$id;
  60. }
  61. */
  62. public static function dirForId ( $int_id, $id , $file_name = NULL )
  63. {
  64. return (intval($int_id / 1000000)).'/'. (intval($int_id / 1000) % 1000).'/'. ( $file_name !== NULL ? $file_name : $id ) ;
  65. }
  66. public static function getVersion ($fileName)
  67. {
  68. $version = strrchr( $fileName, "_" );
  69. if ($version === FALSE)
  70. return 0;
  71. return 0 + substr( $version, 1 );
  72. }
  73. public static function getAllVersions_deprecated ( $entityName, $int_id, $id, $fileName)
  74. {
  75. $c = strstr($fileName, '^') ? '^' : '&';
  76. $parts = explode($c, $fileName);
  77. if (count($parts) == 2 && strlen($parts[1]))
  78. {
  79. // a template has no versions
  80. $dir = '/content/templates/'.$entityName.'/';
  81. $file_base = ""; //$parts[1];
  82. return $dir . $file_base;
  83. }
  84. else
  85. {
  86. // $dir = '/content/'.$entityName.'/'.
  87. // (intval($id / 1048576)).'/'.
  88. // (intval($id / 1024) % 1024).'/';
  89. //
  90. $dir = '/content/'.$entityName.'/'. self::dirForId ( $int_id, $id , "" );
  91. $file_base = $id.'_'; //.$fileName;
  92. }
  93. $id_len = strlen ( $id . "_" );
  94. // iterate the directory and find all the files that start with $file_base
  95. // the result will be tuples where the first element is the file's name, second is the file size
  96. // TODO - use glob rather than dirListExtended
  97. //$pattern = "|" . self::getFSContentRootPath(). "/" . $dir . "/^{$file_base}.*\.xml$";
  98. $files = kFile::dirListExtended( self::getFSContentRootPath() . "/" . $dir , false , false , '/^' . $file_base . ".*\.xml$/" ) ;
  99. if ( $files == null ) return null;
  100. // from each file - strip the id and the file extension
  101. // use the refernce to file_tuple - it will be modified
  102. foreach ( $files as &$file_tuple )
  103. {
  104. // the file_name includes the id and the _, then the verson and finally the file extension
  105. $file_version = substr( kFile::getFileNameNoExtension ( $file_tuple[0] ) , $id_len );
  106. $file_tuple[] = $file_version; // set the version in the forth place of the tuple.
  107. }
  108. if ( $files == null ) return null;
  109. sort($files);
  110. return $files;
  111. }
  112. /**
  113. * This function generates a random file name consisting of a random number and
  114. * a given file extension. If the new filename begins with a '&' or '^' character, the new
  115. * file is a kaltura template and it's appended to the previous filename UGC part.
  116. * This way the old UGC version is mantained. look above at getGeneralEntityPath documentation.
  117. * The random number is in the interval [100000,900000].
  118. * The 900000 upper limit provides space for storing 100000 versions
  119. * without expanding the file name length.
  120. * @param string $fileName = the original fileName from which the extension is cut.
  121. * @param string $previousFileName = in case a previous file exists, the old random is incremented
  122. * @return string the randomized file name
  123. */
  124. public static function generateRandomFileName($fileName, $previousFileName = NULL )
  125. {
  126. if( $fileName == null )
  127. return null;
  128. if ($previousFileName)
  129. {
  130. $c = strstr($previousFileName, '^') ? '^' : '&';
  131. $parts = explode( $c, $previousFileName);
  132. }
  133. else
  134. $parts = array('');
  135. if (strlen($fileName) && ( $fileName[0] == '&' || $fileName[0] == '^' ) ) // setting to a kaltura template
  136. {
  137. return $parts[0].$fileName;
  138. }
  139. if (strlen($parts[0])) // a previous UGC found, increment version
  140. $version = pathinfo($parts[0], PATHINFO_BASENAME) + 1;
  141. else
  142. $version = rand(myContentStorage::MIN_OBFUSCATOR_VALUE, myContentStorage::MAX_OBFUSCATOR_VALUE);
  143. return $version.'.'.strtolower(pathinfo($fileName, PATHINFO_EXTENSION));
  144. }
  145. /**
  146. * This function returns the hash used secure the file uploading.
  147. * The hash is the SHA1 of the kuser salt, kuser id and given entity
  148. * If the user doesnt exist in the database the returned hash is empty - an error.
  149. * @param string $entityName = the entity object name
  150. * @param int $kuser_id = the uploading kuser id
  151. * @return string the hash
  152. */
  153. public static function getTempUploadHash($entityName, $kuser_id, $user = NULL)
  154. {
  155. if ( !$user ) $user = kuserPeer::retrieveByPK($kuser_id);
  156. // found user in db, generate hash
  157. if($user)
  158. {
  159. $salt = ''; // kusers didn't have salt'
  160. return $hash = sha1($salt.$kuser_id.$entityName);
  161. }
  162. return "";
  163. }
  164. /**
  165. * This function returns the upload url paramters needed to securely upload a file.
  166. * The resulting parameters are filename and hash.
  167. * The filename is the given entity name (thumbnail, audio, etc...)
  168. * The hash is generated using the myContentStorage::getTempUploadHash function.
  169. * @param string $entityName = the entity object name
  170. * @param int $kuser_id = the uploading kuser id
  171. * @return string the url parameters string
  172. */
  173. public static function getTempUploadUrlParams($entityName, $kuser_id, $user = NULL)
  174. {
  175. // TODO - i added this becuase it took me 3 hours to find this bug.
  176. // it's clear that the module from which this is called should enforce logging in, but i added this extra defence - Eran ??
  177. if ( $kuser_id == NULL || strlen ( $kuser_id ) == 0 )
  178. {
  179. throw new Exception ( "Should not be called when user is not logged in !" );
  180. }
  181. $hash = myContentStorage::getTempUploadHash($entityName, $kuser_id, $user );
  182. if ($hash != "")
  183. return "?id=$kuser_id&filename=$entityName&hash=$hash";
  184. return "";
  185. }
  186. // TODO - maybe move generic file functions to infra/kFile !?!?
  187. public static function fullMkdir($path, $rights = 0777)
  188. {
  189. $folder_path = array(strstr($path, '.') ? dirname($path) : $path);
  190. $folder_path = str_replace( "\\" , "/" , $folder_path);
  191. while(!@is_dir(dirname(end($folder_path)))
  192. && dirname(end($folder_path)) != '/'
  193. && dirname(end($folder_path)) != '.'
  194. && dirname(end($folder_path)) != '')
  195. array_push($folder_path, dirname(end($folder_path)));
  196. while($parent_folder_path = array_pop($folder_path))
  197. {
  198. if ( ! file_exists( $parent_folder_path ))
  199. {
  200. if(!@mkdir($parent_folder_path, $rights))
  201. {
  202. //user_error("Can't create folder \"$parent_folder_path\".");
  203. }
  204. else
  205. {
  206. @chmod($parent_folder_path, $rights);
  207. }
  208. }
  209. else
  210. {
  211. @chmod($parent_folder_path, $rights);
  212. }
  213. }
  214. }
  215. // TODO - verify changes !!
  216. public static function moveFile($from, $to, $override_if_exists = false, $copy = false )
  217. {
  218. $from = str_replace( "\\" , "/" , $from );
  219. $to = str_replace( "\\" , "/" , $to );
  220. if ( $override_if_exists && is_file( $to ) )
  221. {
  222. self::deleteFile ( $to );
  223. }
  224. if ( !is_dir ( dirname ( $to )) )
  225. {
  226. myContentStorage::fullMkdir($to);
  227. }
  228. KalturaLog::log("myContentStorage::moveFile ($copy): $from to $to");
  229. if ( file_exists( $from ))
  230. {
  231. KalturaLog::log(__METHOD__." - $from file exists");
  232. }
  233. else
  234. {
  235. KalturaLog::log(__METHOD__." - $from file doesnt exist");
  236. }
  237. if ($copy)
  238. return copy($from, $to);
  239. else
  240. return rename($from, $to);
  241. }
  242. // make sure the file is closed , then remove it
  243. public static function deleteFile ( $file_name )
  244. {
  245. $fh = fopen($file_name, 'w') or die("can't open file");
  246. fclose($fh);
  247. unlink($file_name);
  248. }
  249. /**
  250. * This function returns the FILE SYSTEM path to the root archive folder.
  251. * @return string the content folder file system path
  252. */
  253. public static function getFSArchiveRootPath ()
  254. {
  255. return realpath(sfConfig::get('sf_root_dir')."/../../").'/archive/';
  256. }
  257. /**
  258. * This function returns the FILE SYSTEM path to the root content folder.
  259. * @return string the content folder file system path
  260. */
  261. public static function getFSContentRootPath ()
  262. {
  263. $dc = kDataCenterMgr::getCurrentDc();
  264. return $dc["root"];
  265. //return realpath(sfConfig::get('sf_root_dir')."/../../").'/';
  266. }
  267. public static function getFSFlashRootPath ()
  268. {
  269. return "/flash";
  270. }
  271. public static function getFSUiconfRootPath ()
  272. {
  273. return "/uiconf";
  274. }
  275. public static function getFSCacheRootPath ()
  276. {
  277. return kConf::get("general_cache_dir");
  278. }
  279. public static function getFSDeletedContentRootPath ( $original_path )
  280. {
  281. // don't delete what is already deleted
  282. if ( strpos ( $original_path , "deleted_content/") !== false ) return null;
  283. $deleted_path = str_replace ( "content/" , "deleted_content/" , $original_path );
  284. return $deleted_path;
  285. }
  286. public static function moveToDeleted ( $original_path , $copy = false )
  287. {
  288. if ( empty ( $original_path ) ) return "";
  289. if ( strpos ( $original_path , "templates/" ) !== false ) return ""; // dont' delete or move template files
  290. $deleted_path = self::getFSDeletedContentRootPath ( $original_path );
  291. if ( $deleted_path == null ) return "";
  292. if ( ! file_exists( $original_path )) return "";
  293. self::fullMkdir( $deleted_path );
  294. self::moveFile( $original_path , $deleted_path , true , $copy );
  295. return $deleted_path;
  296. }
  297. public static function moveFromDeleted ( $deleted_path , $copy = false )
  298. {
  299. if ( empty ( $deleted_path ) ) return "";
  300. if ( strpos ( $deleted_path , "templates/" ) !== false ) return ""; // dont' undelete or move template files
  301. $original_path = str_replace ( "deleted_content/" , "content/" , $deleted_path );
  302. if ( $original_path == null ) return "";
  303. if ( ! file_exists( $deleted_path )) return "";
  304. self::moveFile( $deleted_path , $original_path , true , $copy );
  305. return $original_path;
  306. }
  307. /**
  308. * This function returns the FILE SYSTEM path to the uploads folder.
  309. * @return string the uploads folder file system path
  310. */
  311. public static function getFSUploadsPath( $add_root = true )
  312. {
  313. if ( $add_root )
  314. return myContentStorage::getFSContentRootPath()."content/uploads/";
  315. else
  316. return "content/uploads/";;
  317. }
  318. public static function getFileNameEdit ( $file_name )
  319. {
  320. return str_replace( ".flv" , "_edit.flv" , $file_name );
  321. }
  322. public static function removeTempThumbnails($kuser_id)
  323. {
  324. $thumbPattern = myContentStorage::getFSUploadsPath().$kuser_id.'_thumbnail_*.*';
  325. foreach (glob($thumbPattern) as $filename)
  326. unlink($filename);
  327. }
  328. public static function removeTempKUserContent($kuser_id)
  329. {
  330. $filePattern = myContentStorage::getFSUploadsPath().$kuser_id.'_*.*';
  331. foreach (glob($filePattern) as $filename)
  332. unlink($filename);
  333. }
  334. public static function fileExtAccepted($ext)
  335. {
  336. // TODO - support all document types or enable kConf
  337. $fileExts = array("jpg", "jpeg", "bmp", "png", "gif", "tif", "tiff" );
  338. return in_array($ext, $fileExts);
  339. }
  340. // TODO - after solving the conversion issue - FLV
  341. public static function fileExtNeedConversion($ext)
  342. {
  343. $fileExts = array( "flv" , "asf", "wmv", "qt" , "mov" , "mpg", "mpeg" , "avi" , "mp3", "wav" , "wma" ,
  344. "mp4", "m4v", "3gp" , "vob", "f4v", "amr", "mkv" , "3g2" , "rm" , "rv" , "ra" , "rmvb" );
  345. return in_array($ext, $fileExts);
  346. }
  347. }
  348. ?>