()
| 106 | } |
| 107 | |
| 108 | private static function ensureUserCaseMigration(): void |
| 109 | { |
| 110 | if (self::$caseMigrationChecked) { |
| 111 | return; |
| 112 | } |
| 113 | self::$caseMigrationChecked = true; |
| 114 | |
| 115 | $usersDir = rtrim(USERS_DIR, '/\\') . DIRECTORY_SEPARATOR; |
| 116 | $marker = $usersDir . 'user_case_migration.done'; |
| 117 | if (is_file($marker)) { |
| 118 | return; |
| 119 | } |
| 120 | |
| 121 | $usersFile = USERS_DIR . USERS_FILE; |
| 122 | if (!is_file($usersFile)) { |
| 123 | return; |
| 124 | } |
| 125 | |
| 126 | $fp = fopen($usersFile, 'c+'); |
| 127 | if (!$fp || !flock($fp, LOCK_EX)) { |
| 128 | if ($fp) { |
| 129 | fclose($fp); |
| 130 | } |
| 131 | return; |
| 132 | } |
| 133 | $contents = stream_get_contents($fp); |
| 134 | $lines = $contents === '' ? [] : preg_split("/\r\n|\n|\r/", $contents); |
| 135 | if ($lines === false) { |
| 136 | flock($fp, LOCK_UN); |
| 137 | fclose($fp); |
| 138 | return; |
| 139 | } |
| 140 | if (!empty($lines) && $lines[count($lines) - 1] === '') { |
| 141 | array_pop($lines); |
| 142 | } |
| 143 | |
| 144 | $canonical = []; |
| 145 | $out = []; |
| 146 | $changedUsers = false; |
| 147 | |
| 148 | foreach ($lines as $line) { |
| 149 | if ($line === '') { |
| 150 | $out[] = $line; |
| 151 | continue; |
| 152 | } |
| 153 | $parts = explode(':', $line); |
| 154 | if (count($parts) < 3) { |
| 155 | $out[] = $line; |
| 156 | continue; |
| 157 | } |
| 158 | $user = $parts[0]; |
| 159 | $lc = strtolower($user); |
| 160 | if (!isset($canonical[$lc])) { |
| 161 | $canonical[$lc] = $user; |
| 162 | $out[] = $line; |
| 163 | } else { |
| 164 | $changedUsers = true; |
| 165 | } |
no test coverage detected