2009102801.php 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  1. <?php
  2. /**
  3. * Move user's data directories from using username to registration date
  4. */
  5. /**
  6. * Generates a file matrix like Elgg 1.0 did
  7. *
  8. * @param string $username Username of user
  9. *
  10. * @return string File matrix path
  11. */
  12. function file_matrix_1_0($username) {
  13. $matrix = "";
  14. $len = strlen($username);
  15. if ($len > 5) {
  16. $len = 5;
  17. }
  18. for ($n = 0; $n < $len; $n++) {
  19. if (ctype_alnum($username[$n])) {
  20. $matrix .= $username[$n] . "/";
  21. }
  22. }
  23. return $matrix . $username . "/";
  24. }
  25. /**
  26. * Generate a file matrix like Elgg 1.1, 1.2 and 1.5
  27. *
  28. * @param string $filename The filename
  29. *
  30. * @return string
  31. */
  32. function file_matrix_1_1($filename) {
  33. $matrix = "";
  34. $name = $filename;
  35. $filename = mb_str_split($filename);
  36. if (!$filename) {
  37. return false;
  38. }
  39. $len = count($filename);
  40. if ($len > 5) {
  41. $len = 5;
  42. }
  43. for ($n = 0; $n < $len; $n++) {
  44. $matrix .= $filename[$n] . "/";
  45. }
  46. return $matrix . $name . "/";
  47. }
  48. /**
  49. * Handle splitting multibyte strings
  50. *
  51. * @param string $string String to split.
  52. * @param string $charset Charset to use.
  53. *
  54. * @return array|false
  55. */
  56. function mb_str_split($string, $charset = 'UTF8') {
  57. if (is_callable('mb_substr')) {
  58. $length = mb_strlen($string);
  59. $array = array();
  60. while ($length) {
  61. $array[] = mb_substr($string, 0, 1, $charset);
  62. $string = mb_substr($string, 1, $length, $charset);
  63. $length = mb_strlen($string);
  64. }
  65. return $array;
  66. } else {
  67. return str_split($string);
  68. }
  69. return false;
  70. }
  71. /**
  72. * 1.6 style file matrix
  73. *
  74. * @param string $filename The filename
  75. *
  76. * @return string
  77. */
  78. function file_matrix_1_6($filename) {
  79. $invalid_fs_chars = '*\'\\/"!$%^&*.%(){}[]#~?<>;|¬`@-+=';
  80. $matrix = "";
  81. $name = $filename;
  82. $filename = mb_str_split($filename);
  83. if (!$filename) {
  84. return false;
  85. }
  86. $len = count($filename);
  87. if ($len > 5) {
  88. $len = 5;
  89. }
  90. for ($n = 0; $n < $len; $n++) {
  91. // Prevent a matrix being formed with unsafe characters
  92. $char = $filename[$n];
  93. if (strpos($invalid_fs_chars, $char) !== false) {
  94. $char = '_';
  95. }
  96. $matrix .= $char . "/";
  97. }
  98. return $matrix . $name . "/";
  99. }
  100. /**
  101. * Scans a directory and moves any files from $from to $to
  102. * preserving structure and handling existing paths.
  103. * Will no overwrite files in $to.
  104. *
  105. * TRAILING SLASHES REQUIRED.
  106. *
  107. * @param string $from From dir.
  108. * @param string $to To dir.
  109. * @param bool $move True to move, false to copy.
  110. * @param string $preference to|from If file collisions, which dir has preference.
  111. *
  112. * @return bool
  113. */
  114. function merge_directories($from, $to, $move = false, $preference = 'to') {
  115. if (!$entries = scandir($from)) {
  116. return false;
  117. }
  118. // character filtering needs to be elsewhere.
  119. if (!is_dir($to)) {
  120. mkdir($to, 0700, true);
  121. }
  122. if ($move === true) {
  123. $f = 'rename';
  124. } else {
  125. $f = 'copy';
  126. }
  127. foreach ($entries as $entry) {
  128. if ($entry == '.' || $entry == '..') {
  129. continue;
  130. }
  131. $from_path = $from . $entry;
  132. $to_path = $to . $entry;
  133. // check to see if the path exists and is a dir, if so, recurse.
  134. if (is_dir($from_path) && is_dir($to_path)) {
  135. $from_path .= '/';
  136. $to_path .= '/';
  137. merge_directories($from_path, $to_path, $move, $preference);
  138. // since it's a dir that already exists we don't need to move it
  139. continue;
  140. }
  141. // only move if target doesn't exist or if preference is for the from dir
  142. if (!file_exists($to_path) || $preference == 'from') {
  143. if ($f($from_path, $to_path)) {
  144. //elgg_dump("Moved/Copied $from_path to $to_path");
  145. }
  146. } else {
  147. //elgg_dump("Ignoring $from_path -> $to_path");
  148. }
  149. }
  150. }
  151. /**
  152. * Create a 1.7 style user file matrix based upon date.
  153. *
  154. * @param int $guid Guid of owner
  155. *
  156. * @return string File matrix path
  157. */
  158. function user_file_matrix($guid) {
  159. // lookup the entity
  160. $user = get_entity($guid);
  161. if ($user->type != 'user') {
  162. // only to be used for user directories
  163. return FALSE;
  164. }
  165. $time_created = date('Y/m/d', $user->time_created);
  166. return "$time_created/$user->guid/";
  167. }
  168. global $ENTITY_CACHE, $CONFIG;
  169. /**
  170. * Upgrade file locations
  171. */
  172. $users = mysql_query("SELECT guid, username
  173. FROM {$CONFIG->dbprefix}users_entity WHERE username != ''");
  174. while ($user = mysql_fetch_object($users)) {
  175. $ENTITY_CACHE = array();
  176. $to = $CONFIG->dataroot . user_file_matrix($user->guid);
  177. foreach (array('1_0', '1_1', '1_6') as $version) {
  178. $function = "file_matrix_$version";
  179. $from = $CONFIG->dataroot . $function($user->username);
  180. merge_directories($from, $to, $move = TRUE, $preference = 'from');
  181. }
  182. }