librenms /
librenmsv2
This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
| 1 | <?php |
||
| 2 | /* |
||
| 3 | * Copyright (C) 2016 Tony Murray <[email protected]> |
||
| 4 | * This program is free software: you can redistribute it and/or modify |
||
| 5 | * it under the terms of the GNU General Public License as published by |
||
| 6 | * the Free Software Foundation, either version 3 of the License, or |
||
| 7 | * (at your option) any later version. |
||
| 8 | * |
||
| 9 | * This program is distributed in the hope that it will be useful, |
||
| 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
||
| 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the |
||
| 12 | * GNU General Public License for more details. |
||
| 13 | * |
||
| 14 | * You should have received a copy of the GNU General Public License |
||
| 15 | * along with this program. If not, see <http://www.gnu.org/licenses/>. |
||
| 16 | */ |
||
| 17 | /** |
||
| 18 | * Settings.php |
||
| 19 | * |
||
| 20 | * @package LibreNMS |
||
| 21 | * @author Tony Murray <[email protected]> |
||
| 22 | * @copyright 2016 Tony Murray |
||
| 23 | * @license @license http://opensource.org/licenses/GPL-3.0 GNU Public License v3 or later |
||
| 24 | */ |
||
| 25 | namespace App; |
||
| 26 | |||
| 27 | use App\Models\DbConfig; |
||
| 28 | use Cache; |
||
| 29 | use Config; |
||
| 30 | use Illuminate\Contracts\Config\Repository as ConfigContract; |
||
| 31 | |||
| 32 | // adds the possibility to replace the default Config facade |
||
| 33 | |||
| 34 | class Settings implements ConfigContract |
||
| 35 | { |
||
| 36 | /** |
||
| 37 | * The tag for the cache. |
||
| 38 | * |
||
| 39 | * @var string |
||
| 40 | */ |
||
| 41 | public static $cache_tag = "Settings"; |
||
| 42 | /** |
||
| 43 | * The amount of time in minutes to store values in cache |
||
| 44 | * |
||
| 45 | * @var int |
||
| 46 | */ |
||
| 47 | private $cache_time; |
||
| 48 | |||
| 49 | /** |
||
| 50 | * Settings constructor. |
||
| 51 | */ |
||
| 52 | 66 | public function __construct() |
|
| 53 | { |
||
| 54 | 66 | $this->cache_time = env('CACHE_LIFETIME', 60); |
|
| 55 | 66 | } |
|
| 56 | |||
| 57 | /** |
||
| 58 | * Set a key value pair into the Settings store. |
||
| 59 | * |
||
| 60 | * @param string $key A . separated path to this setting |
||
| 61 | * @param array|null $value A value or an array. If value is an array it will be converted to a . separate path(s) concatinated onto the given key |
||
| 62 | * @throws \Exception |
||
| 63 | */ |
||
| 64 | 33 | public function set($key, $value = null) |
|
| 65 | { |
||
| 66 | 33 | if (is_array($value)) { |
|
| 67 | // repeat until value contains no arrays |
||
| 68 | 14 | foreach ($value as $k => $v) { |
|
| 69 | 14 | if (!empty($key)) { |
|
| 70 | 13 | if (is_string($k) && !str_contains($k, '.') && DbConfig::exactKey($key)->exists() && DbConfig::key($key)->count() == 1) { |
|
|
0 ignored issues
–
show
The method
count does only exist in Illuminate\Database\Query\Builder, but not in App\Models\DbConfig.
It seems like the method you are trying to call exists only in some of the possible types. Let’s take a look at an example: class A
{
public function foo() { }
}
class B extends A
{
public function bar() { }
}
/**
* @param A|B $x
*/
function someFunction($x)
{
$x->foo(); // This call is fine as the method exists in A and B.
$x->bar(); // This method only exists in B and might cause an error.
}
Available Fixes
Loading history...
|
|||
| 71 | // check that we aren't trying to set an array onto an existing value only setting |
||
| 72 | 1 | throw new \Exception("Attempting to set array value to existing non-array value at the key '".$key."'"); |
|
| 73 | } else { |
||
| 74 | // we are not at the leaf yet, add this chunk to the key and recurse |
||
| 75 | 12 | $this->set($key.'.'.$k, $v); |
|
| 76 | } |
||
| 77 | } else { |
||
| 78 | // a leaf, recurse one last time |
||
| 79 | 13 | $this->set($k, $v); |
|
| 80 | } |
||
| 81 | } |
||
| 82 | } else { |
||
| 83 | // make sure we can save this |
||
| 84 | 33 | if ($this->isReadOnly($key)) { |
|
| 85 | 1 | throw new \Exception("The setting '".$key."' is read only"); |
|
| 86 | } |
||
| 87 | |||
| 88 | // flush the cache and save the value in db and cache |
||
| 89 | 32 | $this->flush($key); |
|
| 90 | 32 | DbConfig::updateOrCreate(['config_name' => $key], ['config_value' => $value]); |
|
| 91 | 32 | Cache::tags(self::$cache_tag)->put($key, $value, $this->cache_time); |
|
| 92 | } |
||
| 93 | 32 | } |
|
| 94 | |||
| 95 | /** |
||
| 96 | * Get a value from the Settings store. |
||
| 97 | * |
||
| 98 | * @param string $key A full or partial . separated key. |
||
| 99 | * @param null $default If the key isn't found, return this value. By default undefined keys return null. |
||
| 100 | * @return mixed If the $key is a full path, a bare value will be returned. If it is a partial path, a nested array will be retuned. |
||
| 101 | */ |
||
| 102 | public function get($key, $default = null, $is_array = false) |
||
| 103 | { |
||
| 104 | // return value from cache or fetch it and return it |
||
| 105 | 60 | return Cache::tags(self::$cache_tag)->remember($key, $this->cache_time, function () use ($key, $default, $is_array) { |
|
| 106 | // fetch the values from storage |
||
| 107 | 52 | if (Config::has('config.'.$key)) { |
|
| 108 | 5 | $config_data = Config::get('config.'.$key, $default); |
|
| 109 | } |
||
| 110 | 52 | $db_data = DbConfig::key($key)->get(['config_name', 'config_value']); |
|
|
0 ignored issues
–
show
The method
get does only exist in Illuminate\Database\Query\Builder, but not in App\Models\DbConfig.
It seems like the method you are trying to call exists only in some of the possible types. Let’s take a look at an example: class A
{
public function foo() { }
}
class B extends A
{
public function bar() { }
}
/**
* @param A|B $x
*/
function someFunction($x)
{
$x->foo(); // This call is fine as the method exists in A and B.
$x->bar(); // This method only exists in B and might cause an error.
}
Available Fixes
Loading history...
|
|||
| 111 | |||
| 112 | 52 | if (count($db_data) == 1 && $db_data->first()->config_name == $key && $is_array !== true) { |
|
| 113 | // return a value if we are getting one item and it is the requested item (not recursing) |
||
| 114 | 6 | return $db_data->first()->config_value; |
|
| 115 | 49 | } elseif (count($db_data) >= 1) { |
|
| 116 | // convert the collection to an array |
||
| 117 | 14 | $result = self::collectionToArray($db_data, $key); |
|
| 118 | |||
| 119 | // if we have config_data, merge them |
||
| 120 | 14 | if (isset($config_data)) { |
|
| 121 | 2 | return array_replace_recursive($config_data, $result); |
|
| 122 | } else { |
||
| 123 | 12 | return $result; |
|
| 124 | } |
||
| 125 | } |
||
| 126 | |||
| 127 | // fall back to config.php/defaults.php |
||
| 128 | 37 | if (isset($config_data) && (!is_array($config_data) || count($db_data) == 0)) { |
|
| 129 | // return the value from config.php if it is a value |
||
| 130 | 2 | return $config_data; |
|
| 131 | } |
||
| 132 | |||
| 133 | |||
| 134 | // we couldn't find the key, return the default |
||
| 135 | 35 | return $default; |
|
| 136 | 60 | }); |
|
| 137 | } |
||
| 138 | |||
| 139 | /** |
||
| 140 | * Convert an Eloquent Collection into a nested array |
||
| 141 | * |
||
| 142 | * @param $data \Illuminate\Database\Eloquent\Collection The Collection. |
||
| 143 | * @param string $prefix Path to prepend. Do not include trailing . |
||
| 144 | * @return array The resulting nested array. |
||
| 145 | */ |
||
| 146 | 15 | private static function collectionToArray($data, $prefix = "") |
|
| 147 | { |
||
| 148 | 15 | $tree = array(); |
|
| 149 | 15 | foreach ($data as $item) { |
|
| 150 | 15 | $key = $item->config_name; |
|
| 151 | 15 | if (starts_with($key, $prefix)) { |
|
| 152 | 14 | $key = substr($key, strlen($prefix)); |
|
| 153 | } |
||
| 154 | 15 | $parts = explode('.', trim($key, '.')); |
|
| 155 | |||
| 156 | 15 | $temp = &$tree; |
|
| 157 | 15 | foreach ($parts as $part) { |
|
| 158 | 15 | $temp = &$temp[$part]; |
|
| 159 | } |
||
| 160 | 15 | $temp = $item->config_value; |
|
| 161 | 15 | unset($temp); |
|
| 162 | } |
||
| 163 | 15 | return $tree; |
|
| 164 | } |
||
| 165 | |||
| 166 | /** |
||
| 167 | * Check if the key is defined in the Settings store. |
||
| 168 | * |
||
| 169 | * @param string $key Only full paths will return true. |
||
| 170 | * @return bool |
||
| 171 | */ |
||
| 172 | 2 | public function has($key) |
|
| 173 | { |
||
| 174 | 2 | return (Cache::tags(self::$cache_tag)->has($key) || Config::has('config.'.$key) || DbConfig::key($key)->exists()); |
|
|
0 ignored issues
–
show
The method
exists does only exist in Illuminate\Database\Query\Builder, but not in App\Models\DbConfig.
It seems like the method you are trying to call exists only in some of the possible types. Let’s take a look at an example: class A
{
public function foo() { }
}
class B extends A
{
public function bar() { }
}
/**
* @param A|B $x
*/
function someFunction($x)
{
$x->foo(); // This call is fine as the method exists in A and B.
$x->bar(); // This method only exists in B and might cause an error.
}
Available Fixes
Loading history...
|
|||
| 175 | } |
||
| 176 | |||
| 177 | /** |
||
| 178 | * Check if the key is read only. |
||
| 179 | * When the user is not a global admin. |
||
| 180 | * Currently, $key is unused |
||
| 181 | * |
||
| 182 | * @param string $key The path to check |
||
| 183 | * @return boolean false or the source: config | auth |
||
| 184 | */ |
||
| 185 | 34 | public function isReadOnly($key) |
|
| 186 | { |
||
| 187 | 34 | $user = \Auth::user(); |
|
| 188 | 34 | return (is_null($user) || !$user->isAdmin()); |
|
| 189 | } |
||
| 190 | |||
| 191 | /** |
||
| 192 | * Forget a key and all children |
||
| 193 | * This cannot forget variables set in config.php |
||
| 194 | * |
||
| 195 | * @param string $key Explicit key to forget |
||
| 196 | */ |
||
| 197 | 3 | public function forget($key) |
|
| 198 | { |
||
| 199 | // Cannot remove from config |
||
| 200 | |||
| 201 | 3 | $count = DbConfig::key($key)->count(); |
|
|
0 ignored issues
–
show
The method
count does only exist in Illuminate\Database\Query\Builder, but not in App\Models\DbConfig.
It seems like the method you are trying to call exists only in some of the possible types. Let’s take a look at an example: class A
{
public function foo() { }
}
class B extends A
{
public function bar() { }
}
/**
* @param A|B $x
*/
function someFunction($x)
{
$x->foo(); // This call is fine as the method exists in A and B.
$x->bar(); // This method only exists in B and might cause an error.
}
Available Fixes
Loading history...
|
|||
| 202 | 3 | if ($count == 1) { |
|
| 203 | 2 | $this->flush($key); |
|
| 204 | } else { |
||
| 205 | 3 | $this->flush(); // possible optimization: selective flush |
|
| 206 | } |
||
| 207 | |||
| 208 | 3 | DbConfig::key($key)->delete(); |
|
| 209 | 3 | } |
|
| 210 | |||
| 211 | /** |
||
| 212 | * Get all settings defined in the Settings store. |
||
| 213 | * |
||
| 214 | * @return array A nested array of all settings. |
||
| 215 | */ |
||
| 216 | 1 | public function all() |
|
| 217 | { |
||
| 218 | // no caching :( |
||
| 219 | 1 | $config_settings = Config::all()['config']; |
|
| 220 | 1 | $db_settings = self::collectionToArray(DbConfig::all()); |
|
| 221 | 1 | return array_replace_recursive($config_settings, $db_settings); |
|
| 222 | } |
||
| 223 | |||
| 224 | // ---- Local Utility functions ---- |
||
| 225 | |||
| 226 | /** |
||
| 227 | * Clear the settings cache. |
||
| 228 | * If path is set, only clear the path and it's parents. |
||
| 229 | * This will not clear children. |
||
| 230 | * |
||
| 231 | * @param string $key The path to clear. |
||
| 232 | */ |
||
| 233 | 35 | public function flush($key = null) |
|
| 234 | { |
||
| 235 | 35 | if (is_null($key)) { |
|
| 236 | // Clear all cache |
||
| 237 | 12 | Cache::tags(self::$cache_tag)->flush(); |
|
| 238 | } else { |
||
| 239 | // Clear specific path |
||
| 240 | 32 | $path = []; |
|
| 241 | 32 | foreach (explode('.', $key) as $element) { |
|
| 242 | 32 | $path[] = $element; |
|
| 243 | 32 | Cache::tags(self::$cache_tag)->forget(join('.', $path)); |
|
| 244 | } |
||
| 245 | } |
||
| 246 | 35 | } |
|
| 247 | |||
| 248 | /** |
||
| 249 | * Prepend a value onto an array configuration value. |
||
| 250 | * |
||
| 251 | * @param string $key |
||
| 252 | * @param mixed $value |
||
| 253 | * @return void |
||
| 254 | */ |
||
| 255 | 1 | public function prepend($key, $value) |
|
| 256 | { |
||
| 257 | 1 | $var = $this->get($key); |
|
| 258 | |||
| 259 | 1 | if (is_array($var)) { |
|
| 260 | 1 | $this->forget($key); |
|
| 261 | 1 | array_unshift($var, $value); |
|
| 262 | 1 | $this->set($key, $var); |
|
| 263 | } else { |
||
| 264 | 1 | $arr = [$value]; |
|
| 265 | 1 | if (!is_null($var)) { |
|
| 266 | 1 | $arr[] = $var; |
|
| 267 | } |
||
| 268 | |||
| 269 | 1 | $this->forget($key); |
|
| 270 | 1 | $this->set($key, $arr); |
|
| 271 | } |
||
| 272 | 1 | } |
|
| 273 | |||
| 274 | /** |
||
| 275 | * Push a value onto an array configuration value. |
||
| 276 | * |
||
| 277 | * @param string $key |
||
| 278 | * @param mixed $value |
||
| 279 | * @return void |
||
| 280 | */ |
||
| 281 | 1 | public function push($key, $value) |
|
| 282 | { |
||
| 283 | 1 | $var = $this->get($key); |
|
| 284 | 1 | if (is_array($var)) { |
|
| 285 | 1 | $var[] = $value; |
|
| 286 | 1 | $this->set($key, $var); |
|
| 287 | } else { |
||
| 288 | 1 | $arr = array(); |
|
| 289 | 1 | if (!is_null($var)) { |
|
| 290 | 1 | $arr[] = $var; |
|
| 291 | } |
||
| 292 | 1 | $arr[] = $value; |
|
| 293 | |||
| 294 | 1 | $this->forget($key); |
|
| 295 | 1 | $this->set($key, $arr); |
|
| 296 | } |
||
| 297 | 1 | } |
|
| 298 | } |
||
| 299 |
It seems like the method you are trying to call exists only in some of the possible types.
Let’s take a look at an example:
Available Fixes
Add an additional type-check:
Only allow a single type to be passed if the variable comes from a parameter: