function add_invalid_login() {
global $adminer;
- $fp = file_open_lock(get_temp_dir() . "/adminer.invalid");
+ $base = get_temp_dir() . "/adminer.invalid";
+ // adminer.invalid may not be writable by us, try the files with random suffixes
+ foreach (glob("$base*") ?: array($base) as $filename) {
+ $fp = file_open_lock($filename);
+ if ($fp) {
+ break;
+ }
+ }
+ if (!$fp) {
+ $fp = file_open_lock("$base-" . rand_string());
+ }
if (!$fp) {
return;
}
function check_invalid_login() {
global $adminer;
- $invalids = unserialize(@file_get_contents(get_temp_dir() . "/adminer.invalid")); // @ - may not exist
+ $invalids = array();
+ foreach (glob(get_temp_dir() . "/adminer.invalid*") as $filename) {
+ $fp = file_open_lock($filename);
+ if ($fp) {
+ $invalids = unserialize(stream_get_contents($fp));
+ file_unlock($fp);
+ break;
+ }
+ }
$invalid = ($invalids ? $invalids[$adminer->bruteForceKey()] : array());
$next_attempt = ($invalid[1] > 29 ? $invalid[0] - time() : 0); // allow 30 invalid attempts
if ($next_attempt > 0) { //! do the same with permanent login
* @return resource or null for error
*/
function file_open_lock($filename) {
+ if (is_link($filename)) {
+ return; // https://cwe.mitre.org/data/definitions/61.html
+ }
$fp = @fopen($filename, "c+"); // @ - may not be writable
if (!$fp) {
return;
Align numbers right (bug #912)
Remember export setting at SQL command
SQL textarea: Open help on Ctrl+click
+Security: Disallow writing temporary files to symlinks (bug #855)
MariaDB: Display MariaDB instead of MySQL
CSS: Dark mode syntax highlighting
Designs named adminer-dark.css use dark basic style