- function isValidCollection($collectionName) {
- global $member, $DIR_MEDIA;
-
- // private collections only accept uploads from their owners
- if (is_numeric($collectionName))
- return ($member->getID() == $collectionName);
-
- // other collections should exists and be writable
- $collectionDir = $DIR_MEDIA . $collectionName;
- return (@is_dir($collectionDir) || @is_writable($collectionDir));
- }
+ function isValidCollection($collectionName) {\r
+ global $member, $DIR_MEDIA;\r
+\r
+ // allow creating new private directory\r
+ if (preg_match('#^[0-9]+[/\\\\]?$#',$collectionName))\r
+ return ((int)$member->getID() == (int)$collectionName);\r
+\r
+ // avoid directory traversal\r
+ // note that preg_replace() is requred to remove the last "/" or "\" if exists\r
+ $media = realpath($DIR_MEDIA);\r
+ $media = preg_replace('#[/\\\\]+$#','',$media);\r
+ $collectionDir = realpath( $DIR_MEDIA . $collectionName );\r
+ $collectionDir = preg_replace('#[/\\\\]+$#','',$collectionDir);\r
+ if (strpos($collectionDir,$media)!==0 || $collectionDir == $media) return false;\r
+\r
+ // private collections only accept uploads from their owners\r
+ // The "+1" of "strlen($media)+1" corresponds to "/" or "\".\r
+ $collectionName=substr($collectionDir,strlen($media)+1);\r
+ if (preg_match('/^[0-9]+$/',$collectionName))\r
+ return ((int)$member->getID() == (int)$collectionName);\r
+\r
+ // other collections should exists and be writable\r
+ return (@is_dir($collectionDir) && @is_writable($collectionDir));\r
+ }\r