docs/api/source-admin.controller.common.security.html
| 1: | <?php | | 2: | namespace Opencart\Admin\Controller\Common; | | 3: | /** | | 4: | * Class Security | | 5: | * | | 6: | * @package Opencart\Admin\Controller\Common | | 7: | */ | | 8: | class Security extends \Opencart\System\Engine\Controller { | | 9: | /** | | 10: | * Index | | 11: | * | | 12: | * @return string | | 13: | */ | | 14: | public function index(): string { | | 15: | $this->load->language('common/security'); | | 16: | | | 17: | $data['list'] = $this->controller_common_security->getList(); | | 18: | | | 19: | $data['user_token'] = $this->session->data['user_token']; | | 20: | | | 21: | return $this->load->view('common/security', $data); | | 22: | } | | 23: | | | 24: | /** | | 25: | * List | | 26: | * | | 27: | * @return void | | 28: | */ | | 29: | public function list(): void { | | 30: | $this->load->language('common/security'); | | 31: | | | 32: | $this->response->setOutput($this->controller_common_security->getList()); | | 33: | } | | 34: | | | 35: | /** | | 36: | * getList | | 37: | * | | 38: | * @return string | | 39: | */ | | 40: | public function getList(): string { | | 41: | // Install directory exists | | 42: | $path = DIR_OPENCART . 'install/'; | | 43: | | | 44: | if (is_dir($path)) { | | 45: | $data['install'] = $path; | | 46: | } else { | | 47: | $data['install'] = ''; | | 48: | } | | 49: | | | 50: | // Storage directory exists | | 51: | $path = DIR_SYSTEM . 'storage/'; | | 52: | | | 53: | if (DIR_STORAGE == $path) { | | 54: | $data['storage'] = $path; | | 55: | | | 56: | $data['document_root'] = str_replace('\', '/', realpath($this->request->server['DOCUMENT_ROOT'] . '/../')) . '/'; | | 57: | | | 58: | $path = ''; | | 59: | | | 60: | $data['paths'] = []; | | 61: | | | 62: | $parts = explode('/', rtrim($data['document_root'], '/')); | | 63: | | | 64: | foreach ($parts as $part) { | | 65: | $path .= $part . '/'; | | 66: | | | 67: | $data['paths'][] = $path; | | 68: | } | | 69: | | | 70: | rsort($data['paths']); | | 71: | } else { | | 72: | $data['storage'] = ''; | | 73: | } | | 74: | | | 75: | // Storage delete | | 76: | $path = DIR_SYSTEM . 'storage/'; | | 77: | | | 78: | if (is_dir($path) && DIR_STORAGE != $path) { | | 79: | $data['storage_delete'] = $path; | | 80: | } else { | | 81: | $data['storage_delete'] = ''; | | 82: | } | | 83: | | | 84: | // Check admin directory ia renamed | | 85: | $path = DIR_OPENCART . 'admin/'; | | 86: | | | 87: | if (DIR_APPLICATION == $path) { | | 88: | $data['admin'] = 'admin'; | | 89: | } else { | | 90: | $data['admin'] = ''; | | 91: | } | | 92: | | | 93: | // Admin delete | | 94: | $path = DIR_OPENCART . 'admin/'; | | 95: | | | 96: | if (is_dir($path) && DIR_APPLICATION != $path) { | | 97: | $data['admin_delete'] = $path; | | 98: | } else { | | 99: | $data['admin_delete'] = ''; | | 100: | } | | 101: | | | 102: | $data['user_token'] = $this->session->data['user_token']; | | 103: | | | 104: | if ($data['install'] || $data['storage'] || $data['storage_delete'] || $data['admin'] || $data['admin_delete']) { | | 105: | return $this->load->view('common/security_list', $data); | | 106: | } else { | | 107: | return ''; | | 108: | } | | 109: | } | | 110: | | | 111: | /** | | 112: | * Install | | 113: | * | | 114: | * @return void | | 115: | */ | | 116: | public function install(): void { | | 117: | $this->load->language('common/security'); | | 118: | | | 119: | $json = []; | | 120: | | | 121: | if (!$this->user->hasPermission('modify', 'common/security')) { | | 122: | $json['error'] = $this->language->get('error_permission'); | | 123: | } | | 124: | | | 125: | if (!$json) { | | 126: | if (!is_dir(DIR_OPENCART . 'install/')) { | | 127: | $json['error'] = $this->language->get('error_install'); | | 128: | } | | 129: | } | | 130: | | | 131: | if (!$json) { | | 132: | $files = []; | | 133: | | | 134: | $path = DIR_OPENCART . 'install/'; | | 135: | | | 136: | // Make path into an array | | 137: | $directory = [$path]; | | 138: | | | 139: | // While the path array is still populated keep looping through | | 140: | while (count($directory) != 0) { | | 141: | $next = array_shift($directory); | | 142: | | | 143: | if (is_dir($next)) { | | 144: | foreach (glob(rtrim($next, '/') . '/{*,.[!.]*,..?*}', GLOB_BRACE) as $file) { | | 145: | // If directory add to path array | | 146: | if (is_dir($file)) { | | 147: | $directory[] = $file; | | 148: | } | | 149: | | | 150: | // Add the file to the files to be deleted array | | 151: | $files[] = $file; | | 152: | } | | 153: | } | | 154: | } | | 155: | | | 156: | rsort($files); | | 157: | | | 158: | foreach ($files as $file) { | | 159: | if (is_file($file)) { | | 160: | unlink($file); | | 161: | } elseif (is_dir($file)) { | | 162: | rmdir($file); | | 163: | } | | 164: | } | | 165: | | | 166: | rmdir($path); | | 167: | | | 168: | $json['success'] = $this->language->get('text_install_success'); | | 169: | } | | 170: | | | 171: | $this->response->addHeader('Content-Type: application/json'); | | 172: | $this->response->setOutput(json_encode($json)); | | 173: | } | | 174: | | | 175: | /** | | 176: | * Storage | | 177: | * | | 178: | * @return void | | 179: | */ | | 180: | public function storage(): void { | | 181: | $this->load->language('common/security'); | | 182: | | | 183: | $json = []; | | 184: | | | 185: | if (isset($this->request->get['page'])) { | | 186: | $page = (int)$this->request->get['page']; | | 187: | } else { | | 188: | $page = 1; | | 189: | } | | 190: | | | 191: | if (isset($this->request->get['name'])) { | | 192: | $name = preg_replace('/[^a-zA-Z0-9_.]/', '', basename(html_entity_decode(trim($this->request->get['name']), ENT_QUOTES, 'UTF-8'))); | | 193: | } else { | | 194: | $name = ''; | | 195: | } | | 196: | | | 197: | if (isset($this->request->get['path'])) { | | 198: | $path = preg_replace('/[^a-zA-Z0-9_:/.]/', '', html_entity_decode(trim($this->request->get['path']), ENT_QUOTES, 'UTF-8')); | | 199: | } else { | | 200: | $path = ''; | | 201: | } | | 202: | | | 203: | if (!$this->user->hasPermission('modify', 'common/security')) { | | 204: | $json['error'] = $this->language->get('error_permission'); | | 205: | } | | 206: | | | 207: | if (!$json) { | | 208: | $base_old = DIR_STORAGE; | | 209: | $base_new = $path . $name . '/'; | | 210: | | | 211: | // Check current storage path exists | | 212: | if (!is_dir($base_old)) { | | 213: | $json['error'] = $this->language->get('error_storage'); | | 214: | } | | 215: | | | 216: | // Check the chosen directory is not in the public webspace | | 217: | $root = str_replace('\', '/', realpath($this->request->server['DOCUMENT_ROOT'] . '/../')); | | 218: | | | 219: | if ((substr($base_new, 0, strlen($root)) != $root) || ($root == $base_new)) { | | 220: | $json['error'] = $this->language->get('error_storage_root'); | | 221: | } | | 222: | | | 223: | if (!str_starts_with($name, 'storage')) { | | 224: | $json['error'] = $this->language->get('error_storage_name'); | | 225: | } | | 226: | | | 227: | if (!is_writable(DIR_OPENCART . 'config.php') || !is_writable(DIR_APPLICATION . 'config.php')) { | | 228: | $json['error'] = $this->language->get('error_writable'); | | 229: | } | | 230: | } | | 231: | | | 232: | if (!$json) { | | 233: | $files = []; | | 234: | | | 235: | // Make path into an array | | 236: | $directory = [$base_old]; | | 237: | | | 238: | // While the path array is still populated keep looping through | | 239: | while (count($directory) != 0) { | | 240: | $next = array_shift($directory); | | 241: | | | 242: | foreach (glob(rtrim($next, '/') . '/{*,.[!.]*,..?*}', GLOB_BRACE) as $file) { | | 243: | // If directory add to path array | | 244: | if (is_dir($file)) { | | 245: | $directory[] = $file; | | 246: | } | | 247: | | | 248: | // Add the file to the files to be deleted array | | 249: | $files[] = $file; | | 250: | } | | 251: | } | | 252: | | | 253: | // Create the new storage folder | | 254: | if (!is_dir($base_new)) { | | 255: | mkdir($base_new, 0777); | | 256: | } | | 257: | | | 258: | // Copy the | | 259: | $total = count($files); | | 260: | $limit = 200; | | 261: | | | 262: | $start = ($page - 1) * $limit; | | 263: | $end = ($start > ($total - $limit)) ? $total : ($start + $limit); | | 264: | | | 265: | for ($i = $start; $i < $end; $i++) { | | 266: | $destination = substr($files[$i], strlen($base_old)); | | 267: | | | 268: | // Must not have a path before files and directories can be moved | | 269: | $path_new = ''; | | 270: | | | 271: | $directories = explode('/', dirname($destination)); | | 272: | | | 273: | foreach ($directories as $directory) { | | 274: | if (!$path_new) { | | 275: | $path_new = $directory; | | 276: | } else { | | 277: | $path_new = $path_new . '/' . $directory; | | 278: | } | | 279: | | | 280: | // To fix storage location | | 281: | if (!is_dir($base_new . $path_new)) { | | 282: | mkdir($base_new . $path_new, 0777); | | 283: | } | | 284: | } | | 285: | | | 286: | if (is_file($base_old . $destination) && !is_file($base_new . $destination)) { | | 287: | copy($base_old . $destination, $base_new . $destination); | | 288: | } | | 289: | } | | 290: | | | 291: | if ($end < $total) { | | 292: | $json['text'] = sprintf($this->language->get('text_storage_move'), $start, $end, $total); | | 293: | | | 294: | $json['next'] = $this->url->link('common/security.storage', '&user_token=' . $this->session->data['user_token'] . '&name=' . $name . '&path=' . $path . '&page=' . ($page + 1), true); | | 295: | } else { | | 296: | // Remove old directories and files | | 297: | rsort($files); | | 298: | | | 299: | foreach ($files as $file) { | | 300: | if (is_file($file)) { | | 301: | unlink($file); | | 302: | } elseif (is_dir($file)) { | | 303: | rmdir($file); | | 304: | } | | 305: | } | | 306: | | | 307: | rmdir($base_old); | | 308: | | | 309: | // Modify the config files | | 310: | $files = [ | | 311: | DIR_APPLICATION . 'config.php', | | 312: | DIR_OPENCART . 'config.php' | | 313: | ]; | | 314: | | | 315: | foreach ($files as $file) { | | 316: | $output = ''; | | 317: | | | 318: | $lines = file($file); | | 319: | | | 320: | foreach ($lines as $line_id => $line) { | | 321: | if (strpos($line, 'define('DIR_STORAGE') !== false) { | | 322: | $output .= 'define('DIR_STORAGE', '' . $base_new . '');' . "\n"; | | 323: | } else { | | 324: | $output .= $line; | | 325: | } | | 326: | } | | 327: | | | 328: | $file = fopen($file, 'w'); | | 329: | | | 330: | fwrite($file, $output); | | 331: | | | 332: | fclose($file); | | 333: | } | | 334: | | | 335: | $json['success'] = $this->language->get('text_storage_success'); | | 336: | } | | 337: | } | | 338: | | | 339: | $this->response->addHeader('Content-Type: application/json'); | | 340: | $this->response->setOutput(json_encode($json)); | | 341: | } | | 342: | | | 343: | /** | | 344: | * Admin | | 345: | * | | 346: | * @return void | | 347: | */ | | 348: | public function admin(): void { | | 349: | $this->load->language('common/security'); | | 350: | | | 351: | $json = []; | | 352: | | | 353: | if (isset($this->request->get['page'])) { | | 354: | $page = (int)$this->request->get['page']; | | 355: | } else { | | 356: | $page = 1; | | 357: | } | | 358: | | | 359: | if (isset($this->request->get['name'])) { | | 360: | $name = preg_replace('[^a-zA-Z0-9]', '', basename(html_entity_decode(trim((string)$this->request->get['name']), ENT_QUOTES, 'UTF-8'))); | | 361: | } else { | | 362: | $name = 'admin'; | | 363: | } | | 364: | | | 365: | if (!$this->user->hasPermission('modify', 'common/security')) { | | 366: | $json['error'] = $this->language->get('error_permission'); | | 367: | } | | 368: | | | 369: | if (!$json) { | | 370: | $base_old = DIR_OPENCART . 'admin/'; | | 371: | $base_new = DIR_OPENCART . $name . '/'; | | 372: | | | 373: | if (!is_dir($base_old)) { | | 374: | $json['error'] = $this->language->get('error_admin'); | | 375: | } | | 376: | | | 377: | if ($page == 1 && is_dir($base_new)) { | | 378: | $json['error'] = $this->language->get('error_admin_exists'); | | 379: | } | | 380: | | | 381: | $blocked = [ | | 382: | 'admin', | | 383: | 'catalog', | | 384: | 'extension', | | 385: | 'image', | | 386: | 'install', | | 387: | 'system' | | 388: | ]; | | 389: | | | 390: | if (in_array($name, $blocked)) { | | 391: | $json['error'] = sprintf($this->language->get('error_admin_allowed'), $name); | | 392: | } | | 393: | | | 394: | if (!is_writable(DIR_OPENCART . 'config.php') || !is_writable(DIR_APPLICATION . 'config.php')) { | | 395: | $json['error'] = $this->language->get('error_writable'); | | 396: | } | | 397: | } | | 398: | | | 399: | if (!$json) { | | 400: | // 1. // 1. We need to copy the files, as rename cannot be used on any directory, the executing script is running under | | 401: | $files = []; | | 402: | | | 403: | // Make path into an array | | 404: | $directory = [$base_old]; | | 405: | | | 406: | // While the path array is still populated keep looping through | | 407: | while (count($directory) != 0) { | | 408: | $next = array_shift($directory); | | 409: | | | 410: | foreach (glob(rtrim($next, '/') . '/{*,.[!.]*,..?*}', GLOB_BRACE) as $file) { | | 411: | // If directory add to path array | | 412: | if (is_dir($file)) { | | 413: | $directory[] = $file; | | 414: | } | | 415: | | | 416: | // Add the file to the files to be deleted array | | 417: | $files[] = $file; | | 418: | } | | 419: | } | | 420: | | | 421: | // 2. Create the new admin folder name | | 422: | if (!is_dir($base_new)) { | | 423: | mkdir($base_new, 0777); | | 424: | } | | 425: | | | 426: | // 3. split the file copies into chunks. | | 427: | $total = count($files); | | 428: | $limit = 200; | | 429: | | | 430: | $start = ($page - 1) * $limit; | | 431: | $end = ($start > ($total - $limit)) ? $total : ($start + $limit); | | 432: | | | 433: | // 4. Copy the files across | | 434: | foreach (array_slice($files, $start, $end) as $file) { | | 435: | $destination = substr($file, strlen($base_old)); | | 436: | | | 437: | // Must not have a path before files and directories can be moved | | 438: | $path_new = ''; | | 439: | | | 440: | $directories = explode('/', dirname($destination)); | | 441: | | | 442: | foreach ($directories as $directory) { | | 443: | if (!$path_new) { | | 444: | $path_new = $directory; | | 445: | } else { | | 446: | $path_new = $path_new . '/' . $directory; | | 447: | } | | 448: | | | 449: | if (!is_dir($base_new . $path_new)) { | | 450: | mkdir($base_new . $path_new, 0777); | | 451: | } | | 452: | } | | 453: | | | 454: | if (is_file($base_old . $destination) && !is_file($base_new . $destination)) { | | 455: | copy($base_old . $destination, $base_new . $destination); | | 456: | } | | 457: | } | | 458: | | | 459: | if ($end < $total) { | | 460: | $json['text'] = sprintf($this->language->get('text_admin_move'), $start, $end, $total); | | 461: | | | 462: | $json['next'] = $this->url->link('common/security.admin', '&user_token=' . $this->session->data['user_token'] . '&name=' . $name . '&page=' . ($page + 1), true); | | 463: | } else { | | 464: | // Update the old config files | | 465: | $file = $base_new . 'config.php'; | | 466: | | | 467: | $output = ''; | | 468: | | | 469: | $lines = file($file); | | 470: | | | 471: | foreach ($lines as $line_id => $line) { | | 472: | $status = true; | | 473: | | | 474: | if (strpos($line, 'define('HTTP_SERVER') !== false) { | | 475: | $output .= 'define('HTTP_SERVER', '' . substr(HTTP_SERVER, 0, strrpos(HTTP_SERVER, '/admin/')) . '/' . $name . '/');' . "\n"; | | 476: | | | 477: | $status = false; | | 478: | } | | 479: | | | 480: | if (strpos($line, 'define('DIR_APPLICATION') !== false) { | | 481: | $output .= 'define('DIR_APPLICATION', DIR_OPENCART . '' . $name . '/');' . "\n"; | | 482: | | | 483: | $status = false; | | 484: | } | | 485: | | | 486: | if ($status) { | | 487: | $output .= $line; | | 488: | } | | 489: | } | | 490: | | | 491: | $file = fopen($file, 'w'); | | 492: | | | 493: | fwrite($file, $output); | | 494: | | | 495: | fclose($file); | | 496: | | | 497: | $this->session->data['success'] = $this->language->get('text_admin_success'); | | 498: | | | 499: | // 6. redirect to the new admin | | 500: | $json['redirect'] = str_replace('&', '&', substr(HTTP_SERVER, 0, -6) . $name . '/index.php?route=common/login'); | | 501: | } | | 502: | } | | 503: | | | 504: | $this->response->addHeader('Content-Type: application/json'); | | 505: | $this->response->setOutput(json_encode($json)); | | 506: | } | | 507: | | | 508: | /** | | 509: | * Delete | | 510: | * | | 511: | * @return void | | 512: | */ | | 513: | public function delete(): void { | | 514: | $this->load->language('common/security'); | | 515: | | | 516: | $json = []; | | 517: | | | 518: | if (isset($this->request->get['remove'])) { | | 519: | $remove = (string)$this->request->get['remove']; | | 520: | } else { | | 521: | $remove = ''; | | 522: | } | | 523: | | | 524: | if (!$this->user->hasPermission('modify', 'common/security')) { | | 525: | $json['error'] = $this->language->get('error_permission'); | | 526: | } | | 527: | | | 528: | if (!$json) { | | 529: | $path = ''; | | 530: | | | 531: | if ($remove == 'storage') { | | 532: | // Storage directory exists | | 533: | $path = DIR_SYSTEM . 'storage/'; | | 534: | | | 535: | if (!is_dir($path) || DIR_STORAGE == $path) { | | 536: | $json['error'] = $this->language->get('error_storage'); | | 537: | } | | 538: | } | | 539: | | | 540: | // Admin directory exists | | 541: | if ($remove == 'admin') { | | 542: | $path = DIR_OPENCART . 'admin/'; | | 543: | | | 544: | if (!is_dir($path) || DIR_APPLICATION == $path) { | | 545: | $json['error'] = $this->language->get('error_admin'); | | 546: | } | | 547: | } | | 548: | | | 549: | if (!$path) { | | 550: | $json['error'] = $this->language->get('error_remove'); | | 551: | } | | 552: | } | | 553: | | | 554: | if (!$json) { | | 555: | // Delete old admin directory | | 556: | $directory = [$path]; | | 557: | | | 558: | // Remove paths | | 559: | foreach ($directory as $path) { | | 560: | $files = []; | | 561: | | | 562: | // While the path array is still populated keep looping through | | 563: | while (count($directory) != 0) { | | 564: | $next = array_shift($directory); | | 565: | | | 566: | if (is_dir($next)) { | | 567: | foreach (glob(rtrim($next, '/') . '/{*,.[!.]*,..?*}', GLOB_BRACE) as $file) { | | 568: | // If directory add to path array | | 569: | if (is_dir($file)) { | | 570: | $directory[] = $file; | | 571: | } | | 572: | | | 573: | // Add the file to the files to be deleted array | | 574: | $files[] = $file; | | 575: | } | | 576: | } | | 577: | } | | 578: | | | 579: | rsort($files); | | 580: | | | 581: | foreach ($files as $file) { | | 582: | if (is_file($file)) { | | 583: | unlink($file); | | 584: | } elseif (is_dir($file)) { | | 585: | rmdir($file); | | 586: | } | | 587: | } | | 588: | | | 589: | rmdir($path); | | 590: | } | | 591: | | | 592: | $json['success'] = $this->language->get('text_' . $remove . '_delete_success'); | | 593: | } | | 594: | | | 595: | $this->response->addHeader('Content-Type: application/json'); | | 596: | $this->response->setOutput(json_encode($json)); | | 597: | } | | 598: | } | | 599: | |
OpenCart API API documentation generated by ApiGen dev-master