diff --git a/php/modules/Database.php b/php/modules/Database.php index 17a34da..afff1ea 100755 --- a/php/modules/Database.php +++ b/php/modules/Database.php @@ -258,18 +258,61 @@ if(!defined('LYCHEE')) exit('Error: Direct access is not allowed!'); # Check dependencies Module::dependencies(isset($database, $query, $data)); + # Count the number of placeholders and compare it with the number of arguments + # If it doesn't match, calculate the difference and skip this number of placeholders before starting the replacement + # This avoids problems with placeholders in user-input + # $skip = Number of placeholders which need to be skipped + $skip = 0; + $num = array( + 'placeholder' => substr_count($query, '?'), + 'data' => count($data) + ); + + if (($num['data']-$num['placeholder'])<0) Log::notice($database, __METHOD__, __LINE__, 'Could not completely prepare query. Query has more placeholders than values.'); + foreach ($data as $value) { # Escape $value = mysqli_real_escape_string($database, $value); + # Recalculate number of placeholders + $num['placeholder'] = substr_count($query, '?'); + + # Calculate number of skips + if ($num['placeholder']>$num['data']) $skip = $num['placeholder'] - $num['data']; + + if ($skip>0) { + + # Need to skip $skip placeholders, because the user input contained placeholders + # Calculate a substring which does not contain the user placeholders + # 1 or -1 is the length of the placeholder (placeholder = ?) + + $pos = -1; + for ($i=$skip; $i>0; $i--) $pos = strpos($query, '?', $pos + 1); + $pos++; + + $temp = substr($query, 0, $pos); # First part of $query + $query = substr($query, $pos); # Last part of $query + + } + # Replace $query = preg_replace('/\?/', $value, $query, 1); - } + if ($skip>0) { - # Add semicolon at the end - $query .= ';'; + # Reassemble the parts of $query + $query = $temp . $query; + + } + + # Reset skip + $skip = 0; + + # Decrease number of data elements + $num['data']--; + + } return $query;