SimpleMachines /
SMF2.1
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
| 1 | <?php |
||
| 2 | |||
| 3 | /** |
||
| 4 | * The xmlArray class is an xml parser. |
||
| 5 | * |
||
| 6 | * Simple Machines Forum (SMF) |
||
| 7 | * |
||
| 8 | * @package SMF |
||
| 9 | * @author Simple Machines http://www.simplemachines.org |
||
| 10 | * @copyright 2017 Simple Machines and individual contributors |
||
| 11 | * @license http://www.simplemachines.org/about/smf/license.php BSD |
||
| 12 | * |
||
| 13 | * @version 2.1 Beta 3 |
||
| 14 | */ |
||
| 15 | |||
| 16 | if (!defined('SMF')) |
||
| 17 | die('No direct access...'); |
||
| 18 | |||
| 19 | /** |
||
| 20 | * Class xmlArray |
||
| 21 | * Represents an XML array |
||
| 22 | */ |
||
| 23 | class xmlArray |
||
| 24 | { |
||
| 25 | /** |
||
| 26 | * @var array Holds parsed XML results |
||
| 27 | */ |
||
| 28 | public $array; |
||
| 29 | |||
| 30 | /** |
||
| 31 | * @var int The debugging level |
||
| 32 | */ |
||
| 33 | public $debug_level; |
||
| 34 | |||
| 35 | /** |
||
| 36 | * holds trim level textual data |
||
| 37 | * @var bool Holds trim level textual data |
||
| 38 | */ |
||
| 39 | public $trim; |
||
| 40 | |||
| 41 | /** |
||
| 42 | * Constructor for the xml parser. |
||
| 43 | * Example use: |
||
| 44 | * $xml = new xmlArray(file('data.xml')); |
||
| 45 | * |
||
| 46 | * @param string $data The xml data or an array of, unless is_clone is true. |
||
| 47 | * @param bool $auto_trim Used to automatically trim textual data. |
||
| 48 | * @param int $level The debug level. Specifies whether notices should be generated for missing elements and attributes. |
||
| 49 | * @param bool $is_clone default false. If is_clone is true, the xmlArray is cloned from another - used internally only. |
||
| 50 | */ |
||
| 51 | public function __construct($data, $auto_trim = false, $level = null, $is_clone = false) |
||
| 52 | { |
||
| 53 | // If we're using this try to get some more memory. |
||
| 54 | setMemoryLimit('32M'); |
||
| 55 | |||
| 56 | // Set the debug level. |
||
| 57 | $this->debug_level = $level !== null ? $level : error_reporting(); |
||
| 58 | $this->trim = $auto_trim; |
||
| 59 | |||
| 60 | // Is the data already parsed? |
||
| 61 | if ($is_clone) |
||
| 62 | { |
||
| 63 | $this->array = $data; |
||
| 64 | return; |
||
| 65 | } |
||
| 66 | |||
| 67 | // Is the input an array? (ie. passed from file()?) |
||
| 68 | if (is_array($data)) |
||
| 69 | $data = implode('', $data); |
||
| 70 | |||
| 71 | // Remove any xml declaration or doctype, and parse out comments and CDATA. |
||
| 72 | $data = preg_replace('/<!--.*?-->/s', '', $this->_to_cdata(preg_replace(array('/^<\?xml.+?\?' . '>/is', '/<!DOCTYPE[^>]+?' . '>/s'), '', $data))); |
||
| 73 | |||
| 74 | // Now parse the xml! |
||
| 75 | $this->array = $this->_parse($data); |
||
| 76 | } |
||
| 77 | |||
| 78 | /** |
||
| 79 | * Get the root element's name. |
||
| 80 | * Example use: |
||
| 81 | * echo $element->name(); |
||
| 82 | * @return string The root element's name |
||
| 83 | */ |
||
| 84 | public function name() |
||
| 85 | { |
||
| 86 | return isset($this->array['name']) ? $this->array['name'] : ''; |
||
| 87 | } |
||
| 88 | |||
| 89 | /** |
||
| 90 | * Get a specified element's value or attribute by path. |
||
| 91 | * Children are parsed for text, but only textual data is returned |
||
| 92 | * unless get_elements is true. |
||
| 93 | * Example use: |
||
| 94 | * $data = $xml->fetch('html/head/title'); |
||
| 95 | * @param string $path The path to the element to fetch |
||
| 96 | * @param bool $get_elements Whether to include elements |
||
| 97 | * @return string The value or attribute of the specified element |
||
| 98 | */ |
||
| 99 | public function fetch($path, $get_elements = false) |
||
| 100 | { |
||
| 101 | // Get the element, in array form. |
||
| 102 | $array = $this->path($path); |
||
| 103 | |||
| 104 | if ($array === false) |
||
| 105 | return false; |
||
| 106 | |||
| 107 | // Getting elements into this is a bit complicated... |
||
| 108 | if ($get_elements && !is_string($array)) |
||
| 109 | { |
||
| 110 | $temp = ''; |
||
| 111 | |||
| 112 | // Use the _xml() function to get the xml data. |
||
| 113 | foreach ($array->array as $val) |
||
| 114 | { |
||
| 115 | // Skip the name and any attributes. |
||
| 116 | if (is_array($val)) |
||
| 117 | $temp .= $this->_xml($val, null); |
||
| 118 | } |
||
| 119 | |||
| 120 | // Just get the XML data and then take out the CDATAs. |
||
| 121 | return $this->_to_cdata($temp); |
||
| 122 | } |
||
| 123 | |||
| 124 | // Return the value - taking care to pick out all the text values. |
||
| 125 | return is_string($array) ? $array : $this->_fetch($array->array); |
||
| 126 | } |
||
| 127 | |||
| 128 | /** Get an element, returns a new xmlArray. |
||
| 129 | * It finds any elements that match the path specified. |
||
| 130 | * It will always return a set if there is more than one of the element |
||
| 131 | * or return_set is true. |
||
| 132 | * Example use: |
||
| 133 | * $element = $xml->path('html/body'); |
||
| 134 | * @param $path string The path to the element to get |
||
| 135 | * @param $return_full bool Whether to return the full result set |
||
| 136 | * @return xmlArray, a new xmlArray. |
||
| 137 | */ |
||
| 138 | public function path($path, $return_full = false) |
||
| 139 | { |
||
| 140 | // Split up the path. |
||
| 141 | $path = explode('/', $path); |
||
| 142 | |||
| 143 | // Start with a base array. |
||
| 144 | $array = $this->array; |
||
| 145 | |||
| 146 | // For each element in the path. |
||
| 147 | foreach ($path as $el) |
||
| 148 | { |
||
| 149 | // Deal with sets.... |
||
| 150 | if (strpos($el, '[') !== false) |
||
| 151 | { |
||
| 152 | $lvl = (int) substr($el, strpos($el, '[') + 1); |
||
| 153 | $el = substr($el, 0, strpos($el, '[')); |
||
| 154 | } |
||
| 155 | // Find an attribute. |
||
| 156 | elseif (substr($el, 0, 1) == '@') |
||
| 157 | { |
||
| 158 | // It simplifies things if the attribute is already there ;). |
||
| 159 | if (isset($array[$el])) |
||
| 160 | return $array[$el]; |
||
| 161 | else |
||
| 162 | { |
||
| 163 | $trace = debug_backtrace(); |
||
| 164 | $i = 0; |
||
| 165 | View Code Duplication | while ($i < count($trace) && isset($trace[$i]['class']) && $trace[$i]['class'] == get_class($this)) |
|
| 166 | $i++; |
||
| 167 | $debug = ' (from ' . $trace[$i - 1]['file'] . ' on line ' . $trace[$i - 1]['line'] . ')'; |
||
| 168 | |||
| 169 | // Cause an error. |
||
| 170 | if ($this->debug_level & E_NOTICE) |
||
| 171 | trigger_error('Undefined XML attribute: ' . substr($el, 1) . $debug, E_USER_NOTICE); |
||
| 172 | return false; |
||
| 173 | } |
||
| 174 | } |
||
| 175 | else |
||
| 176 | $lvl = null; |
||
| 177 | |||
| 178 | // Find this element. |
||
| 179 | $array = $this->_path($array, $el, $lvl); |
||
| 180 | } |
||
| 181 | |||
| 182 | // Clean up after $lvl, for $return_full. |
||
| 183 | if ($return_full && (!isset($array['name']) || substr($array['name'], -1) != ']')) |
||
| 184 | $array = array('name' => $el . '[]', $array); |
||
| 185 | |||
| 186 | // Create the right type of class... |
||
| 187 | $newClass = get_class($this); |
||
| 188 | |||
| 189 | // Return a new xmlArray for the result. |
||
| 190 | return $array === false ? false : new $newClass($array, $this->trim, $this->debug_level, true); |
||
| 191 | } |
||
| 192 | |||
| 193 | /** |
||
| 194 | * Check if an element exists. |
||
| 195 | * Example use, |
||
| 196 | * echo $xml->exists('html/body') ? 'y' : 'n'; |
||
| 197 | * |
||
| 198 | * @param string $path The path to the element to get. |
||
| 199 | * @return boolean Whether the specified path exists |
||
| 200 | */ |
||
| 201 | public function exists($path) |
||
| 202 | { |
||
| 203 | // Split up the path. |
||
| 204 | $path = explode('/', $path); |
||
| 205 | |||
| 206 | // Start with a base array. |
||
| 207 | $array = $this->array; |
||
| 208 | |||
| 209 | // For each element in the path. |
||
| 210 | foreach ($path as $el) |
||
| 211 | { |
||
| 212 | // Deal with sets.... |
||
| 213 | if (strpos($el, '[') !== false) |
||
| 214 | { |
||
| 215 | $lvl = (int) substr($el, strpos($el, '[') + 1); |
||
| 216 | $el = substr($el, 0, strpos($el, '[')); |
||
| 217 | } |
||
| 218 | // Find an attribute. |
||
| 219 | elseif (substr($el, 0, 1) == '@') |
||
| 220 | return isset($array[$el]); |
||
| 221 | else |
||
| 222 | $lvl = null; |
||
| 223 | |||
| 224 | // Find this element. |
||
| 225 | $array = $this->_path($array, $el, $lvl, true); |
||
| 226 | } |
||
| 227 | |||
| 228 | return $array !== false; |
||
| 229 | } |
||
| 230 | |||
| 231 | /** |
||
| 232 | * Count the number of occurrences of a path. |
||
| 233 | * Example use: |
||
| 234 | * echo $xml->count('html/head/meta'); |
||
| 235 | * @param string $path The path to search for. |
||
| 236 | * @return int The number of elements the path matches. |
||
| 237 | */ |
||
| 238 | public function count($path) |
||
| 239 | { |
||
| 240 | // Get the element, always returning a full set. |
||
| 241 | $temp = $this->path($path, true); |
||
| 242 | |||
| 243 | // Start at zero, then count up all the numeric keys. |
||
| 244 | $i = 0; |
||
| 245 | foreach ($temp->array as $item) |
||
| 246 | { |
||
| 247 | if (is_array($item)) |
||
| 248 | $i++; |
||
| 249 | } |
||
| 250 | |||
| 251 | return $i; |
||
| 252 | } |
||
| 253 | |||
| 254 | /** |
||
| 255 | * Get an array of xmlArray's matching the specified path. |
||
| 256 | * This differs from ->path(path, true) in that instead of an xmlArray |
||
| 257 | * of elements, an array of xmlArray's is returned for use with foreach. |
||
| 258 | * Example use: |
||
| 259 | * foreach ($xml->set('html/body/p') as $p) |
||
| 260 | * @param $path string The path to search for. |
||
| 261 | * @return xmlArray[] An array of xmlArray objects |
||
| 262 | */ |
||
| 263 | public function set($path) |
||
| 264 | { |
||
| 265 | // None as yet, just get the path. |
||
| 266 | $array = array(); |
||
| 267 | $xml = $this->path($path, true); |
||
| 268 | |||
| 269 | foreach ($xml->array as $val) |
||
| 270 | { |
||
| 271 | // Skip these, they aren't elements. |
||
| 272 | if (!is_array($val) || $val['name'] == '!') |
||
| 273 | continue; |
||
| 274 | |||
| 275 | // Create the right type of class... |
||
| 276 | $newClass = get_class($this); |
||
| 277 | |||
| 278 | // Create a new xmlArray and stick it in the array. |
||
| 279 | $array[] = new $newClass($val, $this->trim, $this->debug_level, true); |
||
| 280 | } |
||
| 281 | |||
| 282 | return $array; |
||
| 283 | } |
||
| 284 | |||
| 285 | /** |
||
| 286 | * Create an xml file from an xmlArray, the specified path if any. |
||
| 287 | * Example use: |
||
| 288 | * echo $this->create_xml(); |
||
| 289 | * @param string $path The path to the element. (optional) |
||
| 290 | * @return string Xml-formatted string. |
||
| 291 | */ |
||
| 292 | public function create_xml($path = null) |
||
| 293 | { |
||
| 294 | // Was a path specified? If so, use that array. |
||
| 295 | View Code Duplication | if ($path !== null) |
|
| 296 | { |
||
| 297 | $path = $this->path($path); |
||
| 298 | |||
| 299 | // The path was not found |
||
| 300 | if ($path === false) |
||
| 301 | return false; |
||
| 302 | |||
| 303 | $path = $path->array; |
||
| 304 | } |
||
| 305 | // Just use the current array. |
||
| 306 | else |
||
| 307 | $path = $this->array; |
||
| 308 | |||
| 309 | // Add the xml declaration to the front. |
||
| 310 | return '<?xml version="1.0"?' . '>' . $this->_xml($path, 0); |
||
| 311 | } |
||
| 312 | |||
| 313 | /** |
||
| 314 | * Output the xml in an array form. |
||
| 315 | * Example use: |
||
| 316 | * print_r($xml->to_array()); |
||
| 317 | * |
||
| 318 | * @param string $path The path to output. |
||
| 319 | * @return array An array of XML data |
||
| 320 | */ |
||
| 321 | public function to_array($path = null) |
||
| 322 | { |
||
| 323 | // Are we doing a specific path? |
||
| 324 | View Code Duplication | if ($path !== null) |
|
| 325 | { |
||
| 326 | $path = $this->path($path); |
||
| 327 | |||
| 328 | // The path was not found |
||
| 329 | if ($path === false) |
||
| 330 | return false; |
||
| 331 | |||
| 332 | $path = $path->array; |
||
| 333 | } |
||
| 334 | // No, so just use the current array. |
||
| 335 | else |
||
| 336 | $path = $this->array; |
||
| 337 | |||
| 338 | return $this->_array($path); |
||
| 339 | } |
||
| 340 | |||
| 341 | /** |
||
| 342 | * Parse data into an array. (privately used...) |
||
| 343 | * |
||
| 344 | * @param string $data The data to parse |
||
| 345 | * @return array The parsed array |
||
| 346 | */ |
||
| 347 | protected function _parse($data) |
||
| 348 | { |
||
| 349 | // Start with an 'empty' array with no data. |
||
| 350 | $current = array( |
||
| 351 | ); |
||
| 352 | |||
| 353 | // Loop until we're out of data. |
||
| 354 | while ($data != '') |
||
| 355 | { |
||
| 356 | // Find and remove the next tag. |
||
| 357 | preg_match('/\A<([\w\-:]+)((?:\s+.+?)?)([\s]?\/)?' . '>/', $data, $match); |
||
| 358 | View Code Duplication | if (isset($match[0])) |
|
| 359 | $data = preg_replace('/' . preg_quote($match[0], '/') . '/s', '', $data, 1); |
||
| 360 | |||
| 361 | // Didn't find a tag? Keep looping.... |
||
| 362 | if (!isset($match[1]) || $match[1] == '') |
||
| 363 | { |
||
| 364 | // If there's no <, the rest is data. |
||
| 365 | if (strpos($data, '<') === false) |
||
| 366 | { |
||
| 367 | $text_value = $this->_from_cdata($data); |
||
| 368 | $data = ''; |
||
| 369 | |||
| 370 | if ($text_value != '') |
||
| 371 | $current[] = array( |
||
| 372 | 'name' => '!', |
||
| 373 | 'value' => $text_value |
||
| 374 | ); |
||
| 375 | } |
||
| 376 | // If the < isn't immediately next to the current position... more data. |
||
| 377 | elseif (strpos($data, '<') > 0) |
||
| 378 | { |
||
| 379 | $text_value = $this->_from_cdata(substr($data, 0, strpos($data, '<'))); |
||
| 380 | $data = substr($data, strpos($data, '<')); |
||
| 381 | |||
| 382 | if ($text_value != '') |
||
| 383 | $current[] = array( |
||
| 384 | 'name' => '!', |
||
| 385 | 'value' => $text_value |
||
| 386 | ); |
||
| 387 | } |
||
| 388 | // If we're looking at a </something> with no start, kill it. |
||
| 389 | elseif (strpos($data, '<') !== false && strpos($data, '<') == 0) |
||
| 390 | { |
||
| 391 | if (strpos($data, '<', 1) !== false) |
||
| 392 | { |
||
| 393 | $text_value = $this->_from_cdata(substr($data, 0, strpos($data, '<', 1))); |
||
| 394 | $data = substr($data, strpos($data, '<', 1)); |
||
| 395 | |||
| 396 | if ($text_value != '') |
||
| 397 | $current[] = array( |
||
| 398 | 'name' => '!', |
||
| 399 | 'value' => $text_value |
||
| 400 | ); |
||
| 401 | } |
||
| 402 | View Code Duplication | else |
|
| 403 | { |
||
| 404 | $text_value = $this->_from_cdata($data); |
||
| 405 | $data = ''; |
||
| 406 | |||
| 407 | if ($text_value != '') |
||
| 408 | $current[] = array( |
||
| 409 | 'name' => '!', |
||
| 410 | 'value' => $text_value |
||
| 411 | ); |
||
| 412 | } |
||
| 413 | } |
||
| 414 | |||
| 415 | // Wait for an actual occurance of an element. |
||
| 416 | continue; |
||
| 417 | } |
||
| 418 | |||
| 419 | // Create a new element in the array. |
||
| 420 | $el = &$current[]; |
||
| 421 | $el['name'] = $match[1]; |
||
| 422 | |||
| 423 | // If this ISN'T empty, remove the close tag and parse the inner data. |
||
| 424 | if ((!isset($match[3]) || trim($match[3]) != '/') && (!isset($match[2]) || trim($match[2]) != '/')) |
||
| 425 | { |
||
| 426 | // Because PHP 5.2.0+ seems to croak using regex, we'll have to do this the less fun way. |
||
| 427 | $last_tag_end = strpos($data, '</' . $match[1] . '>'); |
||
| 428 | if ($last_tag_end === false) |
||
| 429 | continue; |
||
| 430 | |||
| 431 | $offset = 0; |
||
| 432 | while (1 == 1) |
||
| 433 | { |
||
| 434 | // Where is the next start tag? |
||
| 435 | $next_tag_start = strpos($data, '<' . $match[1], $offset); |
||
| 436 | // If the next start tag is after the last end tag then we've found the right close. |
||
| 437 | if ($next_tag_start === false || $next_tag_start > $last_tag_end) |
||
| 438 | break; |
||
| 439 | |||
| 440 | // If not then find the next ending tag. |
||
| 441 | $next_tag_end = strpos($data, '</' . $match[1] . '>', $offset); |
||
| 442 | |||
| 443 | // Didn't find one? Then just use the last and sod it. |
||
| 444 | if ($next_tag_end === false) |
||
| 445 | break; |
||
| 446 | else |
||
| 447 | { |
||
| 448 | $last_tag_end = $next_tag_end; |
||
| 449 | $offset = $next_tag_start + 1; |
||
| 450 | } |
||
| 451 | } |
||
| 452 | // Parse the insides. |
||
| 453 | $inner_match = substr($data, 0, $last_tag_end); |
||
| 454 | // Data now starts from where this section ends. |
||
| 455 | $data = substr($data, $last_tag_end + strlen('</' . $match[1] . '>')); |
||
| 456 | |||
| 457 | if (!empty($inner_match)) |
||
| 458 | { |
||
| 459 | // Parse the inner data. |
||
| 460 | if (strpos($inner_match, '<') !== false) |
||
| 461 | $el += $this->_parse($inner_match); |
||
| 462 | View Code Duplication | elseif (trim($inner_match) != '') |
|
| 463 | { |
||
| 464 | $text_value = $this->_from_cdata($inner_match); |
||
| 465 | if ($text_value != '') |
||
| 466 | $el[] = array( |
||
| 467 | 'name' => '!', |
||
| 468 | 'value' => $text_value |
||
| 469 | ); |
||
| 470 | } |
||
| 471 | } |
||
| 472 | } |
||
| 473 | |||
| 474 | // If we're dealing with attributes as well, parse them out. |
||
| 475 | if (isset($match[2]) && $match[2] != '') |
||
| 476 | { |
||
| 477 | // Find all the attribute pairs in the string. |
||
| 478 | preg_match_all('/([\w:]+)="(.+?)"/', $match[2], $attr, PREG_SET_ORDER); |
||
| 479 | |||
| 480 | // Set them as @attribute-name. |
||
| 481 | foreach ($attr as $match_attr) |
||
| 482 | $el['@' . $match_attr[1]] = $match_attr[2]; |
||
| 483 | } |
||
| 484 | } |
||
| 485 | |||
| 486 | // Return the parsed array. |
||
| 487 | return $current; |
||
| 488 | } |
||
| 489 | |||
| 490 | /** |
||
| 491 | * Get a specific element's xml. (privately used...) |
||
| 492 | * |
||
| 493 | * @param array $array An array of element data |
||
| 494 | * @param null|int $indent How many levels to indent the elements (null = no indent) |
||
| 495 | * @return string The formatted XML |
||
| 496 | */ |
||
| 497 | protected function _xml($array, $indent) |
||
| 498 | { |
||
| 499 | $indentation = $indent !== null ? ' |
||
| 500 | ' . str_repeat(' ', $indent) : ''; |
||
| 501 | |||
| 502 | // This is a set of elements, with no name... |
||
| 503 | if (is_array($array) && !isset($array['name'])) |
||
| 504 | { |
||
| 505 | $temp = ''; |
||
| 506 | foreach ($array as $val) |
||
| 507 | $temp .= $this->_xml($val, $indent); |
||
| 508 | return $temp; |
||
| 509 | } |
||
| 510 | |||
| 511 | // This is just text! |
||
| 512 | if ($array['name'] == '!') |
||
| 513 | return $indentation . '<![CDATA[' . $array['value'] . ']]>'; |
||
| 514 | elseif (substr($array['name'], -2) == '[]') |
||
| 515 | $array['name'] = substr($array['name'], 0, -2); |
||
| 516 | |||
| 517 | // Start the element. |
||
| 518 | $output = $indentation . '<' . $array['name']; |
||
| 519 | |||
| 520 | $inside_elements = false; |
||
| 521 | $output_el = ''; |
||
| 522 | |||
| 523 | // Run through and recursively output all the elements or attrbutes inside this. |
||
| 524 | foreach ($array as $k => $v) |
||
| 525 | { |
||
| 526 | if (substr($k, 0, 1) == '@') |
||
| 527 | $output .= ' ' . substr($k, 1) . '="' . $v . '"'; |
||
| 528 | elseif (is_array($v)) |
||
| 529 | { |
||
| 530 | $output_el .= $this->_xml($v, $indent === null ? null : $indent + 1); |
||
| 531 | $inside_elements = true; |
||
| 532 | } |
||
| 533 | } |
||
| 534 | |||
| 535 | // Indent, if necessary.... then close the tag. |
||
| 536 | if ($inside_elements) |
||
| 537 | $output .= '>' . $output_el . $indentation . '</' . $array['name'] . '>'; |
||
| 538 | else |
||
| 539 | $output .= ' />'; |
||
| 540 | |||
| 541 | return $output; |
||
| 542 | } |
||
| 543 | |||
| 544 | /** |
||
| 545 | * Return an element as an array |
||
| 546 | * |
||
| 547 | * @param array $array An array of data |
||
| 548 | * @return string|array A string with the element's value or an array of element data |
||
| 549 | */ |
||
| 550 | protected function _array($array) |
||
| 551 | { |
||
| 552 | $return = array(); |
||
| 553 | $text = ''; |
||
| 554 | foreach ($array as $value) |
||
| 555 | { |
||
| 556 | if (!is_array($value) || !isset($value['name'])) |
||
| 557 | continue; |
||
| 558 | |||
| 559 | if ($value['name'] == '!') |
||
| 560 | $text .= $value['value']; |
||
| 561 | else |
||
| 562 | $return[$value['name']] = $this->_array($value); |
||
| 563 | } |
||
| 564 | |||
| 565 | if (empty($return)) |
||
| 566 | return $text; |
||
| 567 | else |
||
| 568 | return $return; |
||
| 569 | } |
||
| 570 | |||
| 571 | /** |
||
| 572 | * Parse out CDATA tags. (htmlspecialchars them...) |
||
| 573 | * |
||
| 574 | * @param string $data The data with CDATA tags included |
||
| 575 | * @return string The data contained within CDATA tags |
||
| 576 | */ |
||
| 577 | function _to_cdata($data) |
||
| 578 | { |
||
| 579 | $inCdata = $inComment = false; |
||
| 580 | $output = ''; |
||
| 581 | |||
| 582 | $parts = preg_split('~(<!\[CDATA\[|\]\]>|<!--|-->)~', $data, -1, PREG_SPLIT_DELIM_CAPTURE); |
||
| 583 | foreach ($parts as $part) |
||
| 584 | { |
||
| 585 | // Handle XML comments. |
||
| 586 | if (!$inCdata && $part === '<!--') |
||
| 587 | $inComment = true; |
||
| 588 | if ($inComment && $part === '-->') |
||
| 589 | $inComment = false; |
||
| 590 | elseif ($inComment) |
||
| 591 | continue; |
||
| 592 | |||
| 593 | // Handle Cdata blocks. |
||
| 594 | elseif (!$inComment && $part === '<![CDATA[') |
||
| 595 | $inCdata = true; |
||
| 596 | elseif ($inCdata && $part === ']]>') |
||
| 597 | $inCdata = false; |
||
| 598 | elseif ($inCdata) |
||
| 599 | $output .= htmlentities($part, ENT_QUOTES); |
||
| 600 | |||
| 601 | // Everything else is kept as is. |
||
| 602 | else |
||
| 603 | $output .= $part; |
||
| 604 | } |
||
| 605 | |||
| 606 | return $output; |
||
| 607 | } |
||
| 608 | |||
| 609 | /** |
||
| 610 | * Turn the CDATAs back to normal text. |
||
| 611 | * |
||
| 612 | * @param string $data The data with CDATA tags |
||
| 613 | * @return string The transformed data |
||
| 614 | */ |
||
| 615 | protected function _from_cdata($data) |
||
| 616 | { |
||
| 617 | // Get the HTML translation table and reverse it. |
||
| 618 | $trans_tbl = array_flip(get_html_translation_table(HTML_ENTITIES, ENT_QUOTES)); |
||
| 619 | |||
| 620 | // Translate all the entities out. |
||
| 621 | $data = strtr(preg_replace_callback('~&#(\d{1,4});~', function($m) |
||
| 622 | { |
||
| 623 | return chr("$m[1]"); |
||
| 624 | }, $data), $trans_tbl); |
||
| 625 | |||
| 626 | return $this->trim ? trim($data) : $data; |
||
| 627 | } |
||
| 628 | |||
| 629 | /** |
||
| 630 | * Given an array, return the text from that array. (recursive and privately used.) |
||
| 631 | * |
||
| 632 | * @param array $array An aray of data |
||
| 633 | * @return string The text from the array |
||
| 634 | */ |
||
| 635 | protected function _fetch($array) |
||
| 636 | { |
||
| 637 | // Don't return anything if this is just a string. |
||
| 638 | if (is_string($array)) |
||
| 639 | return ''; |
||
| 640 | |||
| 641 | $temp = ''; |
||
| 642 | foreach ($array as $text) |
||
| 643 | { |
||
| 644 | // This means it's most likely an attribute or the name itself. |
||
| 645 | if (!isset($text['name'])) |
||
| 646 | continue; |
||
| 647 | |||
| 648 | // This is text! |
||
| 649 | if ($text['name'] == '!') |
||
| 650 | $temp .= $text['value']; |
||
| 651 | // Another element - dive in ;). |
||
| 652 | else |
||
| 653 | $temp .= $this->_fetch($text); |
||
| 654 | } |
||
| 655 | |||
| 656 | // Return all the bits and pieces we've put together. |
||
| 657 | return $temp; |
||
| 658 | } |
||
| 659 | |||
| 660 | /** |
||
| 661 | * Get a specific array by path, one level down. (privately used...) |
||
| 662 | * |
||
| 663 | * @param array $array An array of data |
||
| 664 | * @param string $path The path |
||
| 665 | * @param int $level How far deep into the array we should go |
||
| 666 | * @param bool $no_error Whether or not to ignore errors |
||
| 667 | * @return string|array The specified array (or the contents of said array if there's only one result) |
||
| 668 | */ |
||
| 669 | protected function _path($array, $path, $level, $no_error = false) |
||
| 670 | { |
||
| 671 | // Is $array even an array? It might be false! |
||
| 672 | if (!is_array($array)) |
||
| 673 | return false; |
||
| 674 | |||
| 675 | // Asking for *no* path? |
||
| 676 | if ($path == '' || $path == '.') |
||
| 677 | return $array; |
||
| 678 | $paths = explode('|', $path); |
||
| 679 | |||
| 680 | // A * means all elements of any name. |
||
| 681 | $show_all = in_array('*', $paths); |
||
| 682 | |||
| 683 | $results = array(); |
||
| 684 | |||
| 685 | // Check each element. |
||
| 686 | foreach ($array as $value) |
||
| 687 | { |
||
| 688 | if (!is_array($value) || $value['name'] === '!') |
||
| 689 | continue; |
||
| 690 | |||
| 691 | if ($show_all || in_array($value['name'], $paths)) |
||
| 692 | { |
||
| 693 | // Skip elements before "the one". |
||
| 694 | if ($level !== null && $level > 0) |
||
| 695 | $level--; |
||
| 696 | else |
||
| 697 | $results[] = $value; |
||
| 698 | } |
||
| 699 | } |
||
| 700 | |||
| 701 | // No results found... |
||
| 702 | if (empty($results)) |
||
| 703 | { |
||
| 704 | $trace = debug_backtrace(); |
||
| 705 | $i = 0; |
||
| 706 | View Code Duplication | while ($i < count($trace) && isset($trace[$i]['class']) && $trace[$i]['class'] == get_class($this)) |
|
| 707 | $i++; |
||
| 708 | $debug = ' from ' . $trace[$i - 1]['file'] . ' on line ' . $trace[$i - 1]['line']; |
||
| 709 | |||
| 710 | // Cause an error. |
||
| 711 | if ($this->debug_level & E_NOTICE && !$no_error) |
||
| 712 | trigger_error('Undefined XML element: ' . $path . $debug, E_USER_NOTICE); |
||
| 713 | return false; |
||
| 714 | } |
||
| 715 | // Only one result. |
||
| 716 | elseif (count($results) == 1 || $level !== null) |
||
| 717 | return $results[0]; |
||
| 718 | // Return the result set. |
||
| 719 | else |
||
| 720 | return $results + array('name' => $path . '[]'); |
||
| 721 | } |
||
| 722 | } |
||
| 723 | |||
| 724 | /** |
||
| 725 | * Class ftp_connection |
||
| 726 | * Simple FTP protocol implementation. |
||
| 727 | * |
||
| 728 | * @see https://tools.ietf.org/html/rfc959 |
||
| 729 | */ |
||
| 730 | class ftp_connection |
||
| 731 | { |
||
| 732 | /** |
||
| 733 | * @var string Holds the connection response |
||
| 734 | */ |
||
| 735 | public $connection; |
||
| 736 | |||
| 737 | /** |
||
| 738 | * @var string Holds any errors |
||
| 739 | */ |
||
| 740 | public $error; |
||
| 741 | |||
| 742 | /** |
||
| 743 | * @var string Holds the last message from the server |
||
| 744 | */ |
||
| 745 | public $last_message; |
||
| 746 | |||
| 747 | /** |
||
| 748 | * @var boolean Whether or not this is a passive connection |
||
| 749 | */ |
||
| 750 | public $pasv; |
||
| 751 | |||
| 752 | /** |
||
| 753 | * Create a new FTP connection... |
||
| 754 | * |
||
| 755 | * @param string $ftp_server The server to connect to |
||
| 756 | * @param int $ftp_port The port to connect to |
||
| 757 | * @param string $ftp_user The username |
||
| 758 | * @param string $ftp_pass The password |
||
| 759 | */ |
||
| 760 | public function __construct($ftp_server, $ftp_port = 21, $ftp_user = 'anonymous', $ftp_pass = '[email protected]') |
||
| 761 | { |
||
| 762 | // Initialize variables. |
||
| 763 | $this->connection = 'no_connection'; |
||
| 764 | $this->error = false; |
||
| 765 | $this->pasv = array(); |
||
| 766 | |||
| 767 | if ($ftp_server !== null) |
||
| 768 | $this->connect($ftp_server, $ftp_port, $ftp_user, $ftp_pass); |
||
| 769 | } |
||
| 770 | |||
| 771 | /** |
||
| 772 | * Connects to a server |
||
| 773 | * |
||
| 774 | * @param string $ftp_server The address of the server |
||
| 775 | * @param int $ftp_port The port |
||
| 776 | * @param string $ftp_user The username |
||
| 777 | * @param string $ftp_pass The password |
||
| 778 | */ |
||
| 779 | public function connect($ftp_server, $ftp_port = 21, $ftp_user = 'anonymous', $ftp_pass = '[email protected]') |
||
| 780 | { |
||
| 781 | View Code Duplication | if (strpos($ftp_server, 'ftp://') === 0) |
|
| 782 | $ftp_server = substr($ftp_server, 6); |
||
| 783 | elseif (strpos($ftp_server, 'ftps://') === 0) |
||
| 784 | $ftp_server = 'ssl://' . substr($ftp_server, 7); |
||
| 785 | View Code Duplication | if (strpos($ftp_server, 'http://') === 0) |
|
| 786 | $ftp_server = substr($ftp_server, 7); |
||
| 787 | elseif (strpos($ftp_server, 'https://') === 0) |
||
| 788 | $ftp_server = substr($ftp_server, 8); |
||
| 789 | $ftp_server = strtr($ftp_server, array('/' => '', ':' => '', '@' => '')); |
||
| 790 | |||
| 791 | // Connect to the FTP server. |
||
| 792 | $this->connection = @fsockopen($ftp_server, $ftp_port, $err, $err, 5); |
||
| 793 | if (!$this->connection) |
||
| 794 | { |
||
| 795 | $this->error = 'bad_server'; |
||
| 796 | $this->last_message = 'Invalid Server'; |
||
| 797 | return; |
||
| 798 | } |
||
| 799 | |||
| 800 | // Get the welcome message... |
||
| 801 | if (!$this->check_response(220)) |
||
| 802 | { |
||
| 803 | $this->error = 'bad_response'; |
||
| 804 | $this->last_message = 'Bad Response'; |
||
| 805 | return; |
||
| 806 | } |
||
| 807 | |||
| 808 | // Send the username, it should ask for a password. |
||
| 809 | fwrite($this->connection, 'USER ' . $ftp_user . "\r\n"); |
||
| 810 | |||
| 811 | if (!$this->check_response(331)) |
||
| 812 | { |
||
| 813 | $this->error = 'bad_username'; |
||
| 814 | $this->last_message = 'Invalid Username'; |
||
| 815 | return; |
||
| 816 | } |
||
| 817 | |||
| 818 | // Now send the password... and hope it goes okay. |
||
| 819 | |||
| 820 | fwrite($this->connection, 'PASS ' . $ftp_pass . "\r\n"); |
||
| 821 | if (!$this->check_response(230)) |
||
| 822 | { |
||
| 823 | $this->error = 'bad_password'; |
||
| 824 | $this->last_message = 'Invalid Password'; |
||
| 825 | return; |
||
| 826 | } |
||
| 827 | } |
||
| 828 | |||
| 829 | /** |
||
| 830 | * Changes to a directory (chdir) via the ftp connection |
||
| 831 | * |
||
| 832 | * @param string $ftp_path The path to the directory we want to change to |
||
| 833 | * @return boolean Whether or not the operation was successful |
||
| 834 | */ |
||
| 835 | public function chdir($ftp_path) |
||
| 836 | { |
||
| 837 | if (!is_resource($this->connection)) |
||
| 838 | return false; |
||
| 839 | |||
| 840 | // No slash on the end, please... |
||
| 841 | if ($ftp_path !== '/' && substr($ftp_path, -1) === '/') |
||
| 842 | $ftp_path = substr($ftp_path, 0, -1); |
||
| 843 | |||
| 844 | fwrite($this->connection, 'CWD ' . $ftp_path . "\r\n"); |
||
| 845 | if (!$this->check_response(250)) |
||
| 846 | { |
||
| 847 | $this->error = 'bad_path'; |
||
| 848 | return false; |
||
| 849 | } |
||
| 850 | |||
| 851 | return true; |
||
| 852 | } |
||
| 853 | |||
| 854 | /** |
||
| 855 | * Changes a files atrributes (chmod) |
||
| 856 | * |
||
| 857 | * @param string $ftp_file The file to CHMOD |
||
| 858 | * @param int|string $chmod The value for the CHMOD operation |
||
| 859 | * @return boolean Whether or not the operation was successful |
||
| 860 | */ |
||
| 861 | public function chmod($ftp_file, $chmod) |
||
| 862 | { |
||
| 863 | if (!is_resource($this->connection)) |
||
| 864 | return false; |
||
| 865 | |||
| 866 | if ($ftp_file == '') |
||
| 867 | $ftp_file = '.'; |
||
| 868 | |||
| 869 | // Do we have a file or a dir? |
||
| 870 | $is_dir = is_dir($ftp_file); |
||
| 871 | $is_writable = false; |
||
| 872 | |||
| 873 | // Set different modes. |
||
| 874 | $chmod_values = $is_dir ? array(0750, 0755, 0775, 0777) : array(0644, 0664, 0666); |
||
| 875 | |||
| 876 | foreach ($chmod_values as $val) |
||
| 877 | { |
||
| 878 | // If it's writable, break out of the loop. |
||
| 879 | if (is_writable($ftp_file)) |
||
| 880 | { |
||
| 881 | $is_writable = true; |
||
| 882 | break; |
||
| 883 | } |
||
| 884 | |||
| 885 | else |
||
| 886 | { |
||
| 887 | // Convert the chmod value from octal (0777) to text ("777"). |
||
| 888 | fwrite($this->connection, 'SITE CHMOD ' . decoct($val) . ' ' . $ftp_file . "\r\n"); |
||
|
0 ignored issues
–
show
|
|||
| 889 | if (!$this->check_response(200)) |
||
| 890 | { |
||
| 891 | $this->error = 'bad_file'; |
||
| 892 | break; |
||
| 893 | } |
||
| 894 | } |
||
| 895 | } |
||
| 896 | return $is_writable; |
||
| 897 | } |
||
| 898 | |||
| 899 | /** |
||
| 900 | * Deletes a file |
||
| 901 | * |
||
| 902 | * @param string $ftp_file The file to delete |
||
| 903 | * @return boolean Whether or not the operation was successful |
||
| 904 | */ |
||
| 905 | public function unlink($ftp_file) |
||
| 906 | { |
||
| 907 | // We are actually connected, right? |
||
| 908 | if (!is_resource($this->connection)) |
||
| 909 | return false; |
||
| 910 | |||
| 911 | // Delete file X. |
||
| 912 | fwrite($this->connection, 'DELE ' . $ftp_file . "\r\n"); |
||
| 913 | if (!$this->check_response(250)) |
||
| 914 | { |
||
| 915 | fwrite($this->connection, 'RMD ' . $ftp_file . "\r\n"); |
||
| 916 | |||
| 917 | // Still no love? |
||
| 918 | if (!$this->check_response(250)) |
||
| 919 | { |
||
| 920 | $this->error = 'bad_file'; |
||
| 921 | return false; |
||
| 922 | } |
||
| 923 | } |
||
| 924 | |||
| 925 | return true; |
||
| 926 | } |
||
| 927 | |||
| 928 | /** |
||
| 929 | * Reads the response to the command from the server |
||
| 930 | * |
||
| 931 | * @param string $desired The desired response |
||
| 932 | * @return boolean Whether or not we got the desired response |
||
| 933 | */ |
||
| 934 | public function check_response($desired) |
||
| 935 | { |
||
| 936 | // Wait for a response that isn't continued with -, but don't wait too long. |
||
| 937 | $time = time(); |
||
| 938 | do |
||
| 939 | $this->last_message = fgets($this->connection, 1024); |
||
| 940 | while ((strlen($this->last_message) < 4 || strpos($this->last_message, ' ') === 0 || strpos($this->last_message, ' ', 3) !== 3) && time() - $time < 5); |
||
| 941 | |||
| 942 | // Was the desired response returned? |
||
| 943 | return is_array($desired) ? in_array(substr($this->last_message, 0, 3), $desired) : substr($this->last_message, 0, 3) == $desired; |
||
| 944 | } |
||
| 945 | |||
| 946 | /** |
||
| 947 | * Used to create a passive connection |
||
| 948 | * |
||
| 949 | * @return boolean Whether the passive connection was created successfully |
||
| 950 | */ |
||
| 951 | public function passive() |
||
| 952 | { |
||
| 953 | // We can't create a passive data connection without a primary one first being there. |
||
| 954 | if (!is_resource($this->connection)) |
||
| 955 | return false; |
||
| 956 | |||
| 957 | // Request a passive connection - this means, we'll talk to you, you don't talk to us. |
||
| 958 | @fwrite($this->connection, 'PASV' . "\r\n"); |
||
| 959 | $time = time(); |
||
| 960 | View Code Duplication | do |
|
| 961 | $response = fgets($this->connection, 1024); |
||
| 962 | while (strpos($response, ' ', 3) !== 3 && time() - $time < 5); |
||
| 963 | |||
| 964 | // If it's not 227, we weren't given an IP and port, which means it failed. |
||
| 965 | if (strpos($response, '227 ') !== 0) |
||
| 966 | { |
||
| 967 | $this->error = 'bad_response'; |
||
| 968 | return false; |
||
| 969 | } |
||
| 970 | |||
| 971 | // Snatch the IP and port information, or die horribly trying... |
||
| 972 | if (preg_match('~\((\d+),\s*(\d+),\s*(\d+),\s*(\d+),\s*(\d+)(?:,\s*(\d+))\)~', $response, $match) == 0) |
||
| 973 | { |
||
| 974 | $this->error = 'bad_response'; |
||
| 975 | return false; |
||
| 976 | } |
||
| 977 | |||
| 978 | // This is pretty simple - store it for later use ;). |
||
| 979 | $this->pasv = array('ip' => $match[1] . '.' . $match[2] . '.' . $match[3] . '.' . $match[4], 'port' => $match[5] * 256 + $match[6]); |
||
| 980 | |||
| 981 | return true; |
||
| 982 | } |
||
| 983 | |||
| 984 | /** |
||
| 985 | * Creates a new file on the server |
||
| 986 | * |
||
| 987 | * @param string $ftp_file The file to create |
||
| 988 | * @return boolean Whether or not the file was created successfully |
||
| 989 | */ |
||
| 990 | public function create_file($ftp_file) |
||
| 991 | { |
||
| 992 | // First, we have to be connected... very important. |
||
| 993 | if (!is_resource($this->connection)) |
||
| 994 | return false; |
||
| 995 | |||
| 996 | // I'd like one passive mode, please! |
||
| 997 | if (!$this->passive()) |
||
| 998 | return false; |
||
| 999 | |||
| 1000 | // Seems logical enough, so far... |
||
| 1001 | fwrite($this->connection, 'STOR ' . $ftp_file . "\r\n"); |
||
| 1002 | |||
| 1003 | // Okay, now we connect to the data port. If it doesn't work out, it's probably "file already exists", etc. |
||
| 1004 | $fp = @fsockopen($this->pasv['ip'], $this->pasv['port'], $err, $err, 5); |
||
| 1005 | if (!$fp || !$this->check_response(150)) |
||
| 1006 | { |
||
| 1007 | $this->error = 'bad_file'; |
||
| 1008 | @fclose($fp); |
||
| 1009 | return false; |
||
| 1010 | } |
||
| 1011 | |||
| 1012 | // This may look strange, but we're just closing it to indicate a zero-byte upload. |
||
| 1013 | fclose($fp); |
||
| 1014 | if (!$this->check_response(226)) |
||
| 1015 | { |
||
| 1016 | $this->error = 'bad_response'; |
||
| 1017 | return false; |
||
| 1018 | } |
||
| 1019 | |||
| 1020 | return true; |
||
| 1021 | } |
||
| 1022 | |||
| 1023 | /** |
||
| 1024 | * Generates a directory listing for the current directory |
||
| 1025 | * |
||
| 1026 | * @param string $ftp_path The path to the directory |
||
| 1027 | * @param bool $search Whether or not to get a recursive directory listing |
||
| 1028 | * @return string|boolean The results of the command or false if unsuccessful |
||
| 1029 | */ |
||
| 1030 | public function list_dir($ftp_path = '', $search = false) |
||
| 1031 | { |
||
| 1032 | // Are we even connected...? |
||
| 1033 | if (!is_resource($this->connection)) |
||
| 1034 | return false; |
||
| 1035 | |||
| 1036 | // Passive... non-agressive... |
||
| 1037 | if (!$this->passive()) |
||
| 1038 | return false; |
||
| 1039 | |||
| 1040 | // Get the listing! |
||
| 1041 | fwrite($this->connection, 'LIST -1' . ($search ? 'R' : '') . ($ftp_path == '' ? '' : ' ' . $ftp_path) . "\r\n"); |
||
| 1042 | |||
| 1043 | // Connect, assuming we've got a connection. |
||
| 1044 | $fp = @fsockopen($this->pasv['ip'], $this->pasv['port'], $err, $err, 5); |
||
| 1045 | if (!$fp || !$this->check_response(array(150, 125))) |
||
| 1046 | { |
||
| 1047 | $this->error = 'bad_response'; |
||
| 1048 | @fclose($fp); |
||
| 1049 | return false; |
||
| 1050 | } |
||
| 1051 | |||
| 1052 | // Read in the file listing. |
||
| 1053 | $data = ''; |
||
| 1054 | while (!feof($fp)) |
||
| 1055 | $data .= fread($fp, 4096); |
||
| 1056 | fclose($fp); |
||
| 1057 | |||
| 1058 | // Everything go okay? |
||
| 1059 | if (!$this->check_response(226)) |
||
| 1060 | { |
||
| 1061 | $this->error = 'bad_response'; |
||
| 1062 | return false; |
||
| 1063 | } |
||
| 1064 | |||
| 1065 | return $data; |
||
| 1066 | } |
||
| 1067 | |||
| 1068 | /** |
||
| 1069 | * Determines the current directory we are in |
||
| 1070 | * |
||
| 1071 | * @param string $file The name of a file |
||
| 1072 | * @param string $listing A directory listing or null to generate one |
||
| 1073 | * @return string|boolean The name of the file or false if it wasn't found |
||
| 1074 | */ |
||
| 1075 | public function locate($file, $listing = null) |
||
| 1076 | { |
||
| 1077 | if ($listing === null) |
||
| 1078 | $listing = $this->list_dir('', true); |
||
| 1079 | $listing = explode("\n", $listing); |
||
| 1080 | |||
| 1081 | @fwrite($this->connection, 'PWD' . "\r\n"); |
||
| 1082 | $time = time(); |
||
| 1083 | View Code Duplication | do |
|
| 1084 | $response = fgets($this->connection, 1024); |
||
| 1085 | while ($response[3] != ' ' && time() - $time < 5); |
||
| 1086 | |||
| 1087 | // Check for 257! |
||
| 1088 | if (preg_match('~^257 "(.+?)" ~', $response, $match) != 0) |
||
| 1089 | $current_dir = strtr($match[1], array('""' => '"')); |
||
| 1090 | else |
||
| 1091 | $current_dir = ''; |
||
| 1092 | |||
| 1093 | for ($i = 0, $n = count($listing); $i < $n; $i++) |
||
| 1094 | { |
||
| 1095 | if (trim($listing[$i]) == '' && isset($listing[$i + 1])) |
||
| 1096 | { |
||
| 1097 | $current_dir = substr(trim($listing[++$i]), 0, -1); |
||
| 1098 | $i++; |
||
| 1099 | } |
||
| 1100 | |||
| 1101 | // Okay, this file's name is: |
||
| 1102 | $listing[$i] = $current_dir . '/' . trim(strlen($listing[$i]) > 30 ? strrchr($listing[$i], ' ') : $listing[$i]); |
||
| 1103 | |||
| 1104 | View Code Duplication | if ($file[0] == '*' && substr($listing[$i], -(strlen($file) - 1)) == substr($file, 1)) |
|
| 1105 | return $listing[$i]; |
||
| 1106 | View Code Duplication | if (substr($file, -1) == '*' && substr($listing[$i], 0, strlen($file) - 1) == substr($file, 0, -1)) |
|
| 1107 | return $listing[$i]; |
||
| 1108 | if (basename($listing[$i]) == $file || $listing[$i] == $file) |
||
| 1109 | return $listing[$i]; |
||
| 1110 | } |
||
| 1111 | |||
| 1112 | return false; |
||
| 1113 | } |
||
| 1114 | |||
| 1115 | /** |
||
| 1116 | * Creates a new directory on the server |
||
| 1117 | * |
||
| 1118 | * @param string $ftp_dir The name of the directory to create |
||
| 1119 | * @return boolean Whether or not the operation was successful |
||
| 1120 | */ |
||
| 1121 | public function create_dir($ftp_dir) |
||
| 1122 | { |
||
| 1123 | // We must be connected to the server to do something. |
||
| 1124 | if (!is_resource($this->connection)) |
||
| 1125 | return false; |
||
| 1126 | |||
| 1127 | // Make this new beautiful directory! |
||
| 1128 | fwrite($this->connection, 'MKD ' . $ftp_dir . "\r\n"); |
||
|
0 ignored issues
–
show
'MKD ' . $ftp_dir . '
' can contain request data and is used in file manipulation context(s) leading to a potential security vulnerability.
16 paths for user data to reach this point
1. Path:
Read from
$_REQUEST, and $_REQUEST['file'] is passed to read_tgz_file()
in Sources/Packages.php on line 1285
2. Path:
Read from
$_REQUEST, and $_REQUEST['file'] is passed to read_tgz_file()
in Sources/Packages.php on line 1309
14. Path:
Read from
$_FILES, and $_FILES['package']['name'] is passed through strtolower(), and strtolower($_FILES['package']['name']) is passed through strrchr(), and strrchr(strtolower($_FILES['package']['name']), '.') is passed through substr(), and $extension is assigned
in Sources/PackageGet.php on line 656
15. Path:
Read from
$_REQUEST, and $_REQUEST['package'] is passed through preg_replace(), and $context is assigned
in Sources/Packages.php on line 104
General Strategies to prevent injectionIn general, it is advisable to prevent any user-data to reach this point. This can be done by white-listing certain values:
if ( ! in_array($value, array('this-is-allowed', 'and-this-too'), true)) {
throw new \InvalidArgumentException('This input is not allowed.');
}
For numeric data, we recommend to explicitly cast the data: $sanitized = (integer) $tainted;
Loading history...
|
|||
| 1129 | if (!$this->check_response(257)) |
||
| 1130 | { |
||
| 1131 | $this->error = 'bad_file'; |
||
| 1132 | return false; |
||
| 1133 | } |
||
| 1134 | |||
| 1135 | return true; |
||
| 1136 | } |
||
| 1137 | |||
| 1138 | /** |
||
| 1139 | * Detects the current path |
||
| 1140 | * |
||
| 1141 | * @param string $filesystem_path The full path from the filesystem |
||
| 1142 | * @param string $lookup_file The name of a file in the specified path |
||
| 1143 | * @return array An array of detected info - username, path from FTP root and whether or not the current path was found |
||
| 1144 | */ |
||
| 1145 | public function detect_path($filesystem_path, $lookup_file = null) |
||
| 1146 | { |
||
| 1147 | $username = ''; |
||
| 1148 | |||
| 1149 | if (isset($_SERVER['DOCUMENT_ROOT'])) |
||
| 1150 | { |
||
| 1151 | if (preg_match('~^/home[2]?/([^/]+?)/public_html~', $_SERVER['DOCUMENT_ROOT'], $match)) |
||
| 1152 | { |
||
| 1153 | $username = $match[1]; |
||
| 1154 | |||
| 1155 | $path = strtr($_SERVER['DOCUMENT_ROOT'], array('/home/' . $match[1] . '/' => '', '/home2/' . $match[1] . '/' => '')); |
||
| 1156 | |||
| 1157 | View Code Duplication | if (substr($path, -1) == '/') |
|
| 1158 | $path = substr($path, 0, -1); |
||
| 1159 | |||
| 1160 | if (strlen(dirname($_SERVER['PHP_SELF'])) > 1) |
||
| 1161 | $path .= dirname($_SERVER['PHP_SELF']); |
||
| 1162 | } |
||
| 1163 | elseif (strpos($filesystem_path, '/var/www/') === 0) |
||
| 1164 | $path = substr($filesystem_path, 8); |
||
| 1165 | else |
||
| 1166 | $path = strtr(strtr($filesystem_path, array('\\' => '/')), array($_SERVER['DOCUMENT_ROOT'] => '')); |
||
| 1167 | } |
||
| 1168 | else |
||
| 1169 | $path = ''; |
||
| 1170 | |||
| 1171 | if (is_resource($this->connection) && $this->list_dir($path) == '') |
||
| 1172 | { |
||
| 1173 | $data = $this->list_dir('', true); |
||
| 1174 | |||
| 1175 | if ($lookup_file === null) |
||
| 1176 | $lookup_file = $_SERVER['PHP_SELF']; |
||
| 1177 | |||
| 1178 | $found_path = dirname($this->locate('*' . basename(dirname($lookup_file)) . '/' . basename($lookup_file), $data)); |
||
| 1179 | if ($found_path == false) |
||
| 1180 | $found_path = dirname($this->locate(basename($lookup_file))); |
||
| 1181 | if ($found_path != false) |
||
| 1182 | $path = $found_path; |
||
| 1183 | } |
||
| 1184 | elseif (is_resource($this->connection)) |
||
| 1185 | $found_path = true; |
||
| 1186 | |||
| 1187 | return array($username, $path, isset($found_path)); |
||
| 1188 | } |
||
| 1189 | |||
| 1190 | /** |
||
| 1191 | * Close the ftp connection |
||
| 1192 | * |
||
| 1193 | * @return boolean Always returns true |
||
| 1194 | */ |
||
| 1195 | public function close() |
||
| 1196 | { |
||
| 1197 | // Goodbye! |
||
| 1198 | fwrite($this->connection, 'QUIT' . "\r\n"); |
||
| 1199 | fclose($this->connection); |
||
| 1200 | |||
| 1201 | return true; |
||
| 1202 | } |
||
| 1203 | } |
||
| 1204 | |||
| 1205 | ?> |
'SITE CHMOD ' . decoct($... ' ' . $ftp_file . ' 'can contain request data and is used in file manipulation context(s) leading to a potential security vulnerability.18 paths for user data to reach this point
$_GET,and$contextis assigned in Sources/ManageLanguages.php on line 792$_GET,and$contextis assignedin Sources/ManageLanguages.php on line 792
$contextis assignedin Sources/ManageLanguages.php on line 797
$images_dirsis assignedin Sources/ManageLanguages.php on line 839
$curPathis assignedin Sources/ManageLanguages.php on line 912
$curPathis passed to deltree()in Sources/ManageLanguages.php on line 914
$diris passed through strtr(), and$ftp_fileis assignedin Sources/Subs-Package.php on line 1758
$ftp_fileis passed to ftp_connection::chmod()in Sources/Subs-Package.php on line 1760
$_GET,and$packagesdir . '/' . $_GET['package']is passed to deltree() in Sources/Packages.php on line 1339$_GET,and$packagesdir . '/' . $_GET['package']is passed to deltree()in Sources/Packages.php on line 1339
$diris passed through strtr(), and$ftp_fileis assignedin Sources/Subs-Package.php on line 1758
$ftp_fileis passed to ftp_connection::chmod()in Sources/Subs-Package.php on line 1760
$_REQUEST,and$_REQUEST['file']is passed to read_tgz_file() in Sources/Packages.php on line 1285$_REQUEST,and$_REQUEST['file']is passed to read_tgz_file()in Sources/Packages.php on line 1285
$destinationis passed to read_tgz_data()in Sources/Subs-Package.php on line 35
$destinationis passed to mktree()in Sources/Subs-Package.php on line 90
$strPathis passed through strtr(), andstrtr($strPath, array($_SESSION['pack_ftp']['root'] => ''))is passed to ftp_connection::chmod()in Sources/Subs-Package.php on line 1832
$_REQUEST,and$_REQUEST['file']is passed to read_tgz_file() in Sources/Packages.php on line 1309$_REQUEST,and$_REQUEST['file']is passed to read_tgz_file()in Sources/Packages.php on line 1309
$destinationis passed to read_tgz_data()in Sources/Subs-Package.php on line 35
$destinationis passed to mktree()in Sources/Subs-Package.php on line 90
$strPathis passed through strtr(), andstrtr($strPath, array($_SESSION['pack_ftp']['root'] => ''))is passed to ftp_connection::chmod()in Sources/Subs-Package.php on line 1832
$_POST,and$contextis assigned in Sources/Packages.php on line 2444$_POST,and$contextis assignedin Sources/Packages.php on line 2444
$contextis assignedin Sources/Packages.php on line 2455
$pathis assignedin Sources/Packages.php on line 2509
$pathis passed to package_chmod()in Sources/Packages.php on line 2512
$filenameis passed through strtr(), and$ftp_fileis assignedin Sources/Subs-Package.php on line 2917
$ftp_fileis passed to ftp_connection::chmod()in Sources/Subs-Package.php on line 2926
$_POST,and$statusis assigned in Sources/Packages.php on line 2465$_POST,and$statusis assignedin Sources/Packages.php on line 2465
$contextis assignedin Sources/Packages.php on line 2486
$contextis assignedin Sources/Packages.php on line 2488
$pathis assignedin Sources/Packages.php on line 2509
$pathis passed to package_chmod()in Sources/Packages.php on line 2512
$filenameis passed through strtr(), and$ftp_fileis assignedin Sources/Subs-Package.php on line 2917
$ftp_fileis passed to ftp_connection::chmod()in Sources/Subs-Package.php on line 2926
$_POST,and$contextis assigned in Sources/Packages.php on line 2536$_POST,and$contextis assignedin Sources/Packages.php on line 2536
$contextis assignedin Sources/Packages.php on line 2538
$contextis assignedin Sources/Packages.php on line 2539
$contextis assignedin Sources/Packages.php on line 2541
$contextis assignedin Sources/Packages.php on line 2586
$pathis assignedin Sources/Packages.php on line 2617
$path . '/' . $entryis passed to package_chmod()in Sources/Packages.php on line 2630
$filenameis passed through strtr(), and$ftp_fileis assignedin Sources/Subs-Package.php on line 2917
$ftp_fileis passed to ftp_connection::chmod()in Sources/Subs-Package.php on line 2926
$_POST,and$fileis assigned in Sources/ManageLanguages.php on line 223$_POST,and$fileis assignedin Sources/ManageLanguages.php on line 223
$chmod_filesis assignedin Sources/ManageLanguages.php on line 229
$chmod_filesis passed to create_chmod_control()in Sources/ManageLanguages.php on line 234
$fileis assignedin Sources/Subs-Package.php on line 842
$fileis passed to package_chmod()in Sources/Subs-Package.php on line 853
$filenameis passed through strtr(), and$ftp_fileis assignedin Sources/Subs-Package.php on line 2917
$ftp_fileis passed to ftp_connection::chmod()in Sources/Subs-Package.php on line 2926
$_GET,and$contextis assigned in Sources/ManageLanguages.php on line 209$_GET,and$contextis assignedin Sources/ManageLanguages.php on line 209
$contextis assignedin Sources/ManageLanguages.php on line 210
$contextis assignedin Sources/ManageLanguages.php on line 211
$contextis assignedin Sources/ManageLanguages.php on line 261
$contextis assignedin Sources/ManageLanguages.php on line 265
$context['make_writable']is passed to create_chmod_control()in Sources/ManageLanguages.php on line 382
$fileis assignedin Sources/Subs-Package.php on line 842
$fileis passed to package_chmod()in Sources/Subs-Package.php on line 853
$filenameis passed through strtr(), and$ftp_fileis assignedin Sources/Subs-Package.php on line 2917
$ftp_fileis passed to ftp_connection::chmod()in Sources/Subs-Package.php on line 2926
$_GET,and$urlis assigned in Sources/PackageGet.php on line 230$_GET,and$urlis assignedin Sources/PackageGet.php on line 230
$url . '/' . $package['filename']is passed to getPackageInfo()in Sources/PackageGet.php on line 497
$packagesdir . '/' . $gzfilename . '/package-info.xml'is passed through file_get_contents(), and$packageInfois assignedin Sources/Subs-Package.php on line 542
$packageInfois passed to xmlArray::__construct()in Sources/Subs-Package.php on line 560
in Sources/Class-Package.php on line 63
$arrayis assignedin Sources/Class-Package.php on line 144
$arrayis assignedin Sources/Class-Package.php on line 102
in Sources/Subs-Package.php on line 1326
in vendor/Sources/Subs-Package.php on line 1735
$this_actionis assignedin Sources/Subs-Package.php on line 1326
$this_action['destination']is passed to mktree()in Sources/Subs-Package.php on line 1334
$strPathis passed through strtr(), andstrtr($strPath, array($_SESSION['pack_ftp']['root'] => ''))is passed to ftp_connection::chmod()in Sources/Subs-Package.php on line 1832
$_GET,and$urlis assigned in Sources/PackageGet.php on line 239$_GET,and$urlis assignedin Sources/PackageGet.php on line 239
$url . '/' . $package['filename']is passed to getPackageInfo()in Sources/PackageGet.php on line 497
$packagesdir . '/' . $gzfilename . '/package-info.xml'is passed through file_get_contents(), and$packageInfois assignedin Sources/Subs-Package.php on line 542
$packageInfois passed to xmlArray::__construct()in Sources/Subs-Package.php on line 560
in Sources/Class-Package.php on line 63
$arrayis assignedin Sources/Class-Package.php on line 144
$arrayis assignedin Sources/Class-Package.php on line 102
in Sources/Subs-Package.php on line 1326
in vendor/Sources/Subs-Package.php on line 1735
$this_actionis assignedin Sources/Subs-Package.php on line 1326
$this_action['destination']is passed to mktree()in Sources/Subs-Package.php on line 1334
$strPathis passed through strtr(), andstrtr($strPath, array($_SESSION['pack_ftp']['root'] => ''))is passed to ftp_connection::chmod()in Sources/Subs-Package.php on line 1832
$_GET,and$current_urlis assigned in Sources/PackageGet.php on line 358$_GET,and$current_urlis assignedin Sources/PackageGet.php on line 358
$packageis assignedin Sources/PackageGet.php on line 366
$packageis assignedin Sources/PackageGet.php on line 376
$packageis assignedin Sources/PackageGet.php on line 377
$packageis assignedin Sources/PackageGet.php on line 466
$packageis assignedin Sources/PackageGet.php on line 467
$packageis assignedin Sources/PackageGet.php on line 468
$packageis assignedin Sources/PackageGet.php on line 469
$packageis assignedin Sources/PackageGet.php on line 470
$packageis assignedin Sources/PackageGet.php on line 473
$contextis assignedin Sources/PackageGet.php on line 476
$packageSectionis assignedin Sources/PackageGet.php on line 488
$packageis assignedin Sources/PackageGet.php on line 490
$url . '/' . $package['filename']is passed to getPackageInfo()in Sources/PackageGet.php on line 497
$packagesdir . '/' . $gzfilename . '/package-info.xml'is passed through file_get_contents(), and$packageInfois assignedin Sources/Subs-Package.php on line 542
$packageInfois passed to xmlArray::__construct()in Sources/Subs-Package.php on line 560
in Sources/Class-Package.php on line 63
$arrayis assignedin Sources/Class-Package.php on line 144
$arrayis assignedin Sources/Class-Package.php on line 102
in Sources/Subs-Package.php on line 1326
in vendor/Sources/Subs-Package.php on line 1735
$this_actionis assignedin Sources/Subs-Package.php on line 1326
$this_action['destination']is passed to mktree()in Sources/Subs-Package.php on line 1334
$strPathis passed through strtr(), andstrtr($strPath, array($_SESSION['pack_ftp']['root'] => ''))is passed to ftp_connection::chmod()in Sources/Subs-Package.php on line 1832
$_GET,and$current_urlis assigned in Sources/PackageGet.php on line 360$_GET,and$current_urlis assignedin Sources/PackageGet.php on line 360
$packageis assignedin Sources/PackageGet.php on line 366
$packageis assignedin Sources/PackageGet.php on line 376
$packageis assignedin Sources/PackageGet.php on line 377
$packageis assignedin Sources/PackageGet.php on line 466
$packageis assignedin Sources/PackageGet.php on line 467
$packageis assignedin Sources/PackageGet.php on line 468
$packageis assignedin Sources/PackageGet.php on line 469
$packageis assignedin Sources/PackageGet.php on line 470
$packageis assignedin Sources/PackageGet.php on line 473
$contextis assignedin Sources/PackageGet.php on line 476
$packageSectionis assignedin Sources/PackageGet.php on line 488
$packageis assignedin Sources/PackageGet.php on line 490
$url . '/' . $package['filename']is passed to getPackageInfo()in Sources/PackageGet.php on line 497
$packagesdir . '/' . $gzfilename . '/package-info.xml'is passed through file_get_contents(), and$packageInfois assignedin Sources/Subs-Package.php on line 542
$packageInfois passed to xmlArray::__construct()in Sources/Subs-Package.php on line 560
in Sources/Class-Package.php on line 63
$arrayis assignedin Sources/Class-Package.php on line 144
$arrayis assignedin Sources/Class-Package.php on line 102
in Sources/Subs-Package.php on line 1326
in vendor/Sources/Subs-Package.php on line 1735
$this_actionis assignedin Sources/Subs-Package.php on line 1326
$this_action['destination']is passed to mktree()in Sources/Subs-Package.php on line 1334
$strPathis passed through strtr(), andstrtr($strPath, array($_SESSION['pack_ftp']['root'] => ''))is passed to ftp_connection::chmod()in Sources/Subs-Package.php on line 1832
$_GET,and$current_urlis assigned in Sources/PackageGet.php on line 383$_GET,and$current_urlis assignedin Sources/PackageGet.php on line 383
$packageis assignedin Sources/PackageGet.php on line 421
$packageis assignedin Sources/PackageGet.php on line 422
$packageis assignedin Sources/PackageGet.php on line 461
$packageis assignedin Sources/PackageGet.php on line 462
$packageis assignedin Sources/PackageGet.php on line 466
$packageis assignedin Sources/PackageGet.php on line 467
$packageis assignedin Sources/PackageGet.php on line 468
$packageis assignedin Sources/PackageGet.php on line 469
$packageis assignedin Sources/PackageGet.php on line 470
$packageis assignedin Sources/PackageGet.php on line 473
$contextis assignedin Sources/PackageGet.php on line 476
$packageSectionis assignedin Sources/PackageGet.php on line 488
$packageis assignedin Sources/PackageGet.php on line 490
$url . '/' . $package['filename']is passed to getPackageInfo()in Sources/PackageGet.php on line 497
$packagesdir . '/' . $gzfilename . '/package-info.xml'is passed through file_get_contents(), and$packageInfois assignedin Sources/Subs-Package.php on line 542
$packageInfois passed to xmlArray::__construct()in Sources/Subs-Package.php on line 560
in Sources/Class-Package.php on line 63
$arrayis assignedin Sources/Class-Package.php on line 144
$arrayis assignedin Sources/Class-Package.php on line 102
in Sources/Subs-Package.php on line 1326
in vendor/Sources/Subs-Package.php on line 1735
$this_actionis assignedin Sources/Subs-Package.php on line 1326
$this_action['destination']is passed to mktree()in Sources/Subs-Package.php on line 1334
$strPathis passed through strtr(), andstrtr($strPath, array($_SESSION['pack_ftp']['root'] => ''))is passed to ftp_connection::chmod()in Sources/Subs-Package.php on line 1832
$_GET,and$current_urlis assigned in Sources/PackageGet.php on line 385$_GET,and$current_urlis assignedin Sources/PackageGet.php on line 385
$packageis assignedin Sources/PackageGet.php on line 421
$packageis assignedin Sources/PackageGet.php on line 422
$packageis assignedin Sources/PackageGet.php on line 461
$packageis assignedin Sources/PackageGet.php on line 462
$packageis assignedin Sources/PackageGet.php on line 466
$packageis assignedin Sources/PackageGet.php on line 467
$packageis assignedin Sources/PackageGet.php on line 468
$packageis assignedin Sources/PackageGet.php on line 469
$packageis assignedin Sources/PackageGet.php on line 470
$packageis assignedin Sources/PackageGet.php on line 473
$contextis assignedin Sources/PackageGet.php on line 476
$packageSectionis assignedin Sources/PackageGet.php on line 488
$packageis assignedin Sources/PackageGet.php on line 490
$url . '/' . $package['filename']is passed to getPackageInfo()in Sources/PackageGet.php on line 497
$packagesdir . '/' . $gzfilename . '/package-info.xml'is passed through file_get_contents(), and$packageInfois assignedin Sources/Subs-Package.php on line 542
$packageInfois passed to xmlArray::__construct()in Sources/Subs-Package.php on line 560
in Sources/Class-Package.php on line 63
$arrayis assignedin Sources/Class-Package.php on line 144
$arrayis assignedin Sources/Class-Package.php on line 102
in Sources/Subs-Package.php on line 1326
in vendor/Sources/Subs-Package.php on line 1735
$this_actionis assignedin Sources/Subs-Package.php on line 1326
$this_action['destination']is passed to mktree()in Sources/Subs-Package.php on line 1334
$strPathis passed through strtr(), andstrtr($strPath, array($_SESSION['pack_ftp']['root'] => ''))is passed to ftp_connection::chmod()in Sources/Subs-Package.php on line 1832
$_FILES,and$_FILES['package']['name']is passed through strtolower(), andstrtolower($_FILES['package']['name'])is passed through strrchr(), andstrrchr(strtolower($_FILES['package']['name']), '.')is passed through substr(), and$extensionis assigned in Sources/PackageGet.php on line 656$_FILES,and$_FILES['package']['name']is passed through strtolower(), andstrtolower($_FILES['package']['name'])is passed through strrchr(), andstrrchr(strtolower($_FILES['package']['name']), '.')is passed through substr(), and$extensionis assignedin Sources/PackageGet.php on line 656
$extensionis assignedin Sources/PackageGet.php on line 663
$packageNameis assignedin Sources/PackageGet.php on line 664
$packageNameis passed to getPackageInfo()in Sources/PackageGet.php on line 677
$packagesdir . '/' . $gzfilename . '/package-info.xml'is passed through file_get_contents(), and$packageInfois assignedin Sources/Subs-Package.php on line 542
$packageInfois passed to xmlArray::__construct()in Sources/Subs-Package.php on line 560
in Sources/Class-Package.php on line 63
$arrayis assignedin Sources/Class-Package.php on line 144
$arrayis assignedin Sources/Class-Package.php on line 102
in Sources/Subs-Package.php on line 1326
in vendor/Sources/Subs-Package.php on line 1735
$this_actionis assignedin Sources/Subs-Package.php on line 1326
$this_action['destination']is passed to mktree()in Sources/Subs-Package.php on line 1334
$strPathis passed through strtr(), andstrtr($strPath, array($_SESSION['pack_ftp']['root'] => ''))is passed to ftp_connection::chmod()in Sources/Subs-Package.php on line 1832
$_REQUEST,and$_REQUEST['package']is passed through preg_replace(), and$contextis assigned in Sources/Packages.php on line 104$_REQUEST,and$_REQUEST['package']is passed through preg_replace(), and$contextis assignedin Sources/Packages.php on line 104
$contextis assignedin Sources/Packages.php on line 107
$contextis assignedin Sources/Packages.php on line 132
$contextis assignedin Sources/Packages.php on line 135
$contextis assignedin Sources/Packages.php on line 141
$context['filename']is passed to getPackageInfo()in Sources/Packages.php on line 193
$packagesdir . '/' . $gzfilename . '/package-info.xml'is passed through file_get_contents(), and$packageInfois assignedin Sources/Subs-Package.php on line 542
$packageInfois passed to xmlArray::__construct()in Sources/Subs-Package.php on line 560
in Sources/Class-Package.php on line 63
$arrayis assignedin Sources/Class-Package.php on line 144
$arrayis assignedin Sources/Class-Package.php on line 102
in Sources/Subs-Package.php on line 1326
in vendor/Sources/Subs-Package.php on line 1735
$this_actionis assignedin Sources/Subs-Package.php on line 1326
$this_action['destination']is passed to mktree()in Sources/Subs-Package.php on line 1334
$strPathis passed through strtr(), andstrtr($strPath, array($_SESSION['pack_ftp']['root'] => ''))is passed to ftp_connection::chmod()in Sources/Subs-Package.php on line 1832
$_REQUEST,and$contextis assigned in Sources/Packages.php on line 780$_REQUEST,and$contextis assignedin Sources/Packages.php on line 780
$contextis assignedin Sources/Packages.php on line 783
$contextis assignedin Sources/Packages.php on line 789
$contextis assignedin Sources/Packages.php on line 792
$contextis assignedin Sources/Packages.php on line 798
$contextis assignedin Sources/Packages.php on line 866
$context['filename']is passed to getPackageInfo()in Sources/Packages.php on line 886
$packagesdir . '/' . $gzfilename . '/package-info.xml'is passed through file_get_contents(), and$packageInfois assignedin Sources/Subs-Package.php on line 542
$packageInfois passed to xmlArray::__construct()in Sources/Subs-Package.php on line 560
in Sources/Class-Package.php on line 63
$arrayis assignedin Sources/Class-Package.php on line 144
$arrayis assignedin Sources/Class-Package.php on line 102
in Sources/Subs-Package.php on line 1326
in vendor/Sources/Subs-Package.php on line 1735
$this_actionis assignedin Sources/Subs-Package.php on line 1326
$this_action['destination']is passed to mktree()in Sources/Subs-Package.php on line 1334
$strPathis passed through strtr(), andstrtr($strPath, array($_SESSION['pack_ftp']['root'] => ''))is passed to ftp_connection::chmod()in Sources/Subs-Package.php on line 1832
General Strategies to prevent injection
In general, it is advisable to prevent any user-data to reach this point. This can be done by white-listing certain values:
if ( ! in_array($value, array('this-is-allowed', 'and-this-too'), true)) { throw new \InvalidArgumentException('This input is not allowed.'); }For numeric data, we recommend to explicitly cast the data: