ソースを参照

organizr now stores most user data in root data folder
updated the path for userTabs to data folder
updated the path for favicon to data folder
updated the path for custom plugins to data folder
updated the path for custom pages to data folder
updated the path for custom cert to data folder
updated install wizard to reflect new data folder
added chooseConfigFile for the process of moving the config file
added config items update to info log
added upgradeDataToFolder to upgrade script

CauseFX 4 年 前
コミット
c7858cc292

+ 43 - 20
api/classes/organizr.class.php

@@ -109,7 +109,8 @@ class Organizr
 		// Set Start Execution Time
 		$this->timeExecution = $this->timeExecution();
 		// Set location path to user config path
-		$this->userConfigPath = dirname(__DIR__, 1) . DIRECTORY_SEPARATOR . 'config' . DIRECTORY_SEPARATOR . 'config.php';
+		$this->chooseConfigFile();
+		//$this->userConfigPath = dirname(__DIR__, 2) . DIRECTORY_SEPARATOR . 'data' . DIRECTORY_SEPARATOR . 'config' . DIRECTORY_SEPARATOR . 'config.php';
 		// Set location path to default config path
 		$this->defaultConfigPath = dirname(__DIR__, 1) . DIRECTORY_SEPARATOR . 'config' . DIRECTORY_SEPARATOR . 'default.php';
 		// Set current time
@@ -139,7 +140,7 @@ class Organizr
 		$this->paths = array(
 			'Root Folder' => dirname(__DIR__, 2) . DIRECTORY_SEPARATOR,
 			'Cache Folder' => dirname(__DIR__, 2) . DIRECTORY_SEPARATOR . 'plugins' . DIRECTORY_SEPARATOR . 'images' . DIRECTORY_SEPARATOR . 'cache' . DIRECTORY_SEPARATOR,
-			'Tab Folder' => dirname(__DIR__, 2) . DIRECTORY_SEPARATOR . 'plugins' . DIRECTORY_SEPARATOR . 'images' . DIRECTORY_SEPARATOR . 'userTabs' . DIRECTORY_SEPARATOR,
+			'Tab Folder' => $this->root . DIRECTORY_SEPARATOR . 'data' . DIRECTORY_SEPARATOR . 'userTabs' . DIRECTORY_SEPARATOR,
 			'API Folder' => dirname(__DIR__, 1) . DIRECTORY_SEPARATOR,
 			'DB Folder' => ($this->hasDB()) ? $this->config['dbLocation'] : false
 		);
@@ -164,6 +165,25 @@ class Organizr
 		$this->disconnectDB();
 	}
 
+	public function chooseConfigFile()
+	{
+
+		$oldUserConfigPath = dirname(__DIR__, 1) . DIRECTORY_SEPARATOR . 'config' . DIRECTORY_SEPARATOR . 'config.php';
+		$userConfigPath = dirname(__DIR__, 2) . DIRECTORY_SEPARATOR . 'data' . DIRECTORY_SEPARATOR . 'config' . DIRECTORY_SEPARATOR . 'config.php';
+		if (file_exists($userConfigPath) && file_exists($oldUserConfigPath)) {
+			$this->userConfigPath = $userConfigPath;
+		} elseif (file_exists($oldUserConfigPath)) {
+			$this->makeDir(dirname(__DIR__, 2) . DIRECTORY_SEPARATOR . 'data' . DIRECTORY_SEPARATOR . 'config' . DIRECTORY_SEPARATOR);
+			if ($this->rcopy($oldUserConfigPath, $userConfigPath)) {
+				$this->userConfigPath = $userConfigPath;
+			} else {
+				$this->userConfigPath = $oldUserConfigPath;
+			}
+		} else {
+			$this->userConfigPath = $userConfigPath;
+		}
+	}
+
 	protected function connectDB()
 	{
 		if ($this->hasDB()) {
@@ -756,7 +776,7 @@ class Organizr
 			<meta name="theme-color" content="#ffffff">
 		';
 		if ($this->config['favIcon'] !== '' && $rootPath !== '') {
-			$this->config['favIcon'] = str_replace('plugins/images/faviconCustom', $rootPath . 'plugins/images/faviconCustom', $this->config['favIcon']);
+			$this->config['favIcon'] = str_replace('data/favicon', $rootPath . 'data/favicon', $this->config['favIcon']);
 		}
 		return ($this->config['favIcon'] == '') ? $favicon : $this->config['favIcon'];
 	}
@@ -1534,8 +1554,8 @@ class Organizr
 				);
 			}
 		}
-		$dirname = dirname(__DIR__, 2) . DIRECTORY_SEPARATOR . 'plugins' . DIRECTORY_SEPARATOR . 'images' . DIRECTORY_SEPARATOR . 'userTabs' . DIRECTORY_SEPARATOR;
-		$path = 'plugins/images/userTabs/';
+		$dirname = $this->root . DIRECTORY_SEPARATOR . 'data' . DIRECTORY_SEPARATOR . 'userTabs' . DIRECTORY_SEPARATOR;
+		$path = 'data/userTabs/';
 		$images = scandir($dirname);
 		foreach ($images as $image) {
 			if (!in_array($image, $ignore)) {
@@ -1588,7 +1608,7 @@ class Organizr
 			$this->setAPIResponse('error', 'No image supplied', 422);
 			return false;
 		}
-		$approvedPath = 'plugins/images/userTabs/';
+		$approvedPath = 'data/userTabs/';
 		$removeImage = $approvedPath . pathinfo($image, PATHINFO_BASENAME);
 		if ($this->approvedFileExtension($removeImage, 'image')) {
 			if (file_exists(dirname(__DIR__, 2) . DIRECTORY_SEPARATOR . $removeImage)) {
@@ -1613,7 +1633,7 @@ class Organizr
 			ini_set('upload_max_filesize', '10M');
 			ini_set('post_max_size', '10M');
 			$tempFile = $_FILES['file']['tmp_name'];
-			$targetPath = dirname(__DIR__, 2) . DIRECTORY_SEPARATOR . 'plugins' . DIRECTORY_SEPARATOR . 'images' . DIRECTORY_SEPARATOR . 'userTabs' . DIRECTORY_SEPARATOR;
+			$targetPath = $this->root . DIRECTORY_SEPARATOR . 'data' . DIRECTORY_SEPARATOR . 'userTabs' . DIRECTORY_SEPARATOR;
 			$targetFile = $targetPath . $_FILES['file']['name'];
 			$this->setAPIResponse(null, pathinfo($_FILES['file']['name'], PATHINFO_BASENAME) . ' has been uploaded', null);
 			return move_uploaded_file($tempFile, $targetFile);
@@ -1771,9 +1791,9 @@ class Organizr
 									<li lang="en"><i class="fa fa-caret-right text-info"></i> Choose your image to use</li>
 									<li lang="en"><i class="fa fa-caret-right text-info"></i> Edit settings to your liking</li>
 									<li lang="en"><i class="fa fa-caret-right text-info"></i> At bottom of page on [Favicon Generator Options] under [Path] choose [I cannot or I do not want to place favicon files at the root of my web site.]</li>
-									<li lang="en"><i class="fa fa-caret-right text-info"></i> Enter this path <code>plugins/images/faviconCustom</code></li>
+									<li lang="en"><i class="fa fa-caret-right text-info"></i> Enter this path <code>data/favicon</code></li>
 									<li lang="en"><i class="fa fa-caret-right text-info"></i> Click [Generate your Favicons and HTML code]</li>
-									<li lang="en"><i class="fa fa-caret-right text-info"></i> Download and unzip file and place in <code>plugins/images/faviconCustom</code></li>
+									<li lang="en"><i class="fa fa-caret-right text-info"></i> Download and unzip file and place in <code>data/favicon</code></li>
 									<li lang="en"><i class="fa fa-caret-right text-info"></i> Copy code and paste inside left box</li>
 								</ul>
 							</div>
@@ -2246,6 +2266,8 @@ class Organizr
 			}
 		}
 		$this->setAPIResponse('success', 'Config items updated', 200);
+		$this->setLoggerChannel('Config');
+		$this->logger->info('Config items updated', array_keys($array));
 		return (bool)$this->updateConfig($newItem);
 	}
 
@@ -4650,11 +4672,12 @@ class Organizr
 			if ($v['type'] !== 'dir') {
 				$filesList[] = array(
 					'fileName' => $v['name'],
-					'path' => DIRECTORY_SEPARATOR . 'api' . DIRECTORY_SEPARATOR . 'plugins' . DIRECTORY_SEPARATOR . $folder . DIRECTORY_SEPARATOR . str_replace($v['name'], '', $v['path']),
+					'path' => $this->root . DIRECTORY_SEPARATOR . 'data' . DIRECTORY_SEPARATOR . 'plugins' . DIRECTORY_SEPARATOR . $folder . DIRECTORY_SEPARATOR . str_replace($v['name'], '', $v['path']),
 					'githubPath' => $v['download_url']
 				);
 			}
 		}
+		$this->makeDir($this->root . DIRECTORY_SEPARATOR . 'data' . DIRECTORY_SEPARATOR . 'plugins' . DIRECTORY_SEPARATOR . $folder);
 		return $filesList;
 	}
 
@@ -4796,9 +4819,10 @@ class Organizr
 		foreach ($downloadList as $k => $v) {
 			$file = array(
 				'from' => $v['githubPath'],
-				'to' => str_replace(array('/', '\\'), DIRECTORY_SEPARATOR, $this->root . $v['path'] . $v['fileName']),
-				'path' => str_replace(array('/', '\\'), DIRECTORY_SEPARATOR, $this->root . $v['path'])
+				'to' => str_replace(array('/', '\\'), DIRECTORY_SEPARATOR, $v['path'] . $v['fileName']),
+				'path' => str_replace(array('/', '\\'), DIRECTORY_SEPARATOR, $v['path'])
 			);
+			$this->makeDir($this->root . DIRECTORY_SEPARATOR . 'data' . DIRECTORY_SEPARATOR . 'plugins');
 			if (!$this->downloadFileToPath($file['from'], $file['to'], $file['path'])) {
 				$this->setLoggerChannel('Plugin Marketplace');
 				$this->logger->warning('Downloaded File Failed  for: ' . $v['githubPath']);
@@ -4829,7 +4853,7 @@ class Organizr
 			$plugin = array_keys($array)[$key];
 		}
 		$array = $array[$plugin];
-		$pluginDir = $this->root . DIRECTORY_SEPARATOR . 'api' . DIRECTORY_SEPARATOR . 'plugins' . DIRECTORY_SEPARATOR . $array['project_folder'] . DIRECTORY_SEPARATOR;
+		$pluginDir = $this->root . DIRECTORY_SEPARATOR . 'data' . DIRECTORY_SEPARATOR . 'plugins' . DIRECTORY_SEPARATOR . $array['project_folder'] . DIRECTORY_SEPARATOR;
 		$dirExists = file_exists($pluginDir);
 		if ($dirExists) {
 			if (!$this->rrmdir($pluginDir)) {
@@ -5230,10 +5254,8 @@ class Organizr
 		}
 		ini_set('max_execution_time', 0);
 		set_time_limit(0);
-		$this->setLoggerChannel('File Management');
-		if (@!mkdir($path, 0777, true)) {
-			$this->logger->warning('Organizr could not create folder or folder already exists');
-		}
+
+		$this->makeDir($path);
 		$file = fopen($from, 'rb', false, $context);
 		if ($file) {
 			$newf = fopen($to, 'wb', false, $context);
@@ -5909,12 +5931,12 @@ class Organizr
 
 	public function hasCustomCert()
 	{
-		return file_exists(dirname(__DIR__, 1) . DIRECTORY_SEPARATOR . 'functions' . DIRECTORY_SEPARATOR . 'cert' . DIRECTORY_SEPARATOR . 'custom.pem');
+		return file_exists($this->root . DIRECTORY_SEPARATOR . 'data' . DIRECTORY_SEPARATOR . 'cert' . DIRECTORY_SEPARATOR . 'custom.pem');
 	}
 
 	public function getCustomCert()
 	{
-		return ($this->hasCustomCert()) ? dirname(__DIR__, 1) . DIRECTORY_SEPARATOR . 'functions' . DIRECTORY_SEPARATOR . 'cert' . DIRECTORY_SEPARATOR . 'custom.pem' : false;
+		return ($this->hasCustomCert()) ? $this->root . DIRECTORY_SEPARATOR . 'data' . DIRECTORY_SEPARATOR . 'cert' . DIRECTORY_SEPARATOR . 'custom.pem' : false;
 	}
 
 	public function uploadCert()
@@ -5924,9 +5946,10 @@ class Organizr
 			ini_set('upload_max_filesize', '10M');
 			ini_set('post_max_size', '10M');
 			$tempFile = $_FILES['file']['tmp_name'];
-			$targetPath = dirname(__DIR__, 1) . DIRECTORY_SEPARATOR . 'functions' . DIRECTORY_SEPARATOR . 'cert' . DIRECTORY_SEPARATOR;
+			$targetPath = $this->root . DIRECTORY_SEPARATOR . 'data' . DIRECTORY_SEPARATOR . 'cert' . DIRECTORY_SEPARATOR;
 			$targetFile = $targetPath . 'custom.pem';
 			$this->setAPIResponse(null, pathinfo($_FILES['file']['name'], PATHINFO_BASENAME) . ' has been uploaded', null);
+			$this->makeDir($this->root . DIRECTORY_SEPARATOR . 'data' . DIRECTORY_SEPARATOR . 'cert');
 			return move_uploaded_file($tempFile, $targetFile);
 		} else {
 			$this->setAPIResponse('error', pathinfo($_FILES['file']['name'], PATHINFO_BASENAME) . ' is not approved to be uploaded', 403);

+ 16 - 2
api/functions.php

@@ -18,9 +18,12 @@ foreach (glob(__DIR__ . DIRECTORY_SEPARATOR . 'pages' . DIRECTORY_SEPARATOR . "*
 	require_once $filename;
 }
 // Include all custom pages files
-foreach (glob(__DIR__ . DIRECTORY_SEPARATOR . 'pages' . DIRECTORY_SEPARATOR . 'custom' . DIRECTORY_SEPARATOR . "*.php") as $filename) {
-	require_once $filename;
+if (file_exists(dirname(__DIR__, 1) . DIRECTORY_SEPARATOR . 'data' . DIRECTORY_SEPARATOR . 'pages')) {
+	foreach (glob(dirname(__DIR__, 1) . DIRECTORY_SEPARATOR . 'data' . DIRECTORY_SEPARATOR . 'pages' . DIRECTORY_SEPARATOR . '*.php') as $filename) {
+		require_once $filename;
+	}
 }
+
 // Include all plugin files
 $folder = __DIR__ . DIRECTORY_SEPARATOR . 'plugins';
 $directoryIterator = new RecursiveDirectoryIterator($folder, FilesystemIterator::SKIP_DOTS);
@@ -29,4 +32,15 @@ foreach ($iteratorIterator as $info) {
 	if ($info->getFilename() == 'plugin.php' || strpos($info->getFilename(), 'page.php') !== false || $info->getFilename() == 'cron.php') {
 		require_once $info->getPathname();
 	}
+}
+// Include all custom plugin files
+if (file_exists(dirname(__DIR__, 1) . DIRECTORY_SEPARATOR . 'data' . DIRECTORY_SEPARATOR . 'plugins')) {
+	$folder = dirname(__DIR__, 1) . DIRECTORY_SEPARATOR . 'data' . DIRECTORY_SEPARATOR . 'plugins';
+	$directoryIterator = new RecursiveDirectoryIterator($folder, FilesystemIterator::SKIP_DOTS);
+	$iteratorIterator = new RecursiveIteratorIterator($directoryIterator);
+	foreach ($iteratorIterator as $info) {
+		if ($info->getFilename() == 'plugin.php' || strpos($info->getFilename(), 'page.php') !== false || $info->getFilename() == 'cron.php') {
+			require_once $info->getPathname();
+		}
+	}
 }

+ 2 - 2
api/functions/organizr-functions.php

@@ -247,8 +247,8 @@ trait OrganizrFunctions
 				);
 			}
 		}
-		$dirname = dirname(__DIR__, 2) . DIRECTORY_SEPARATOR . 'plugins' . DIRECTORY_SEPARATOR . 'images' . DIRECTORY_SEPARATOR . 'userTabs' . DIRECTORY_SEPARATOR;
-		$path = 'plugins/images/userTabs/';
+		$dirname = $this->root . DIRECTORY_SEPARATOR . 'data' . DIRECTORY_SEPARATOR . 'userTabs' . DIRECTORY_SEPARATOR;
+		$path = 'data/userTabs/';
 		$images = scandir($dirname);
 		foreach ($images as $image) {
 			if (!in_array($image, $ignore)) {

+ 96 - 10
api/functions/upgrade-functions.php

@@ -89,7 +89,7 @@ trait UpgradeFunctions
 			return true;
 		}
 	}
-	
+
 	public function addColumnToDatabase($table = '', $columnName = '', $definition = 'TEXT')
 	{
 		if ($table == '' || $columnName == '' || $definition == '') {
@@ -130,7 +130,7 @@ trait UpgradeFunctions
 		}
 		return false;
 	}
-	
+
 	public function updateDB($oldVerNum = false)
 	{
 		$tempLock = $this->config['dbLocation'] . 'DBLOCK.txt';
@@ -204,7 +204,6 @@ trait UpgradeFunctions
 				}
 				@unlink($tempLock);
 				return false;
-				
 			} else {
 				$this->writeLog('error', 'Update Function -  Could not create migration DB', 'Database');
 			}
@@ -213,7 +212,7 @@ trait UpgradeFunctions
 		}
 		return false;
 	}
-	
+
 	public function upgradeToVersion($version = '2.1.0')
 	{
 		switch ($version) {
@@ -226,12 +225,99 @@ trait UpgradeFunctions
 				$this->removeOldCustomHTML();
 			case '2.1.860':
 				$this->upgradeInstalledPluginsConfigItem();
+			case '2.1.1300':
+				$this->upgradeDataToFolder();
 			default:
 				$this->setAPIResponse('success', 'Ran update function for version: ' . $version, 200);
 				return true;
 		}
 	}
-	
+
+	public function upgradeDataToFolder()
+	{
+		if ($this->hasDB()) {
+			// Make main data folder
+			$rootFolderMade = $this->makeDir($this->root . DIRECTORY_SEPARATOR . 'data');
+			// Make config folder child
+			$this->makeDir($this->root . DIRECTORY_SEPARATOR . 'data' . DIRECTORY_SEPARATOR . 'config' . DIRECTORY_SEPARATOR);
+
+			if ($rootFolderMade) {
+				// Migrate over userTabs folder
+				$this->makeDir($this->root . DIRECTORY_SEPARATOR . 'data' . DIRECTORY_SEPARATOR . 'userTabs');
+				if ($this->rcopy($this->root . DIRECTORY_SEPARATOR . 'plugins' . DIRECTORY_SEPARATOR . 'images' . DIRECTORY_SEPARATOR . 'userTabs', $this->root . DIRECTORY_SEPARATOR . 'data' . DIRECTORY_SEPARATOR . 'userTabs')) {
+					// Convert tabs over
+					$query = [
+						[
+							'function' => 'fetchAll',
+							'query' => [
+								'SELECT * FROM tabs WHERE image like "%userTabs%"'
+							]
+						],
+					];
+					$tabs = $this->processQueries($query);
+					if (count($tabs) > 0) {
+						foreach ($tabs as $tab) {
+							$newImage = str_replace('plugins/images/userTabs', 'data/userTabs', $tab['image']);
+							$updateQuery = [
+								[
+									'function' => 'query',
+									'query' => [
+										'UPDATE tabs SET',
+										['image' => $newImage],
+										'WHERE id = ?',
+										$tab['id']
+									]
+								],
+							];
+							$this->processQueries($updateQuery);
+						}
+					}
+					$this->setLoggerChannel('Migration');
+					$this->logger->info('The folder "userTabs" was migrated to new data folder');
+				}
+				// Migrate over custom cert
+				if (file_exists($this->root . DIRECTORY_SEPARATOR . 'api' . DIRECTORY_SEPARATOR . 'functions' . DIRECTORY_SEPARATOR . 'cert' . DIRECTORY_SEPARATOR . 'custom.pem')) {
+					// Make cert folder child
+					$this->makeDir($this->root . DIRECTORY_SEPARATOR . 'data' . DIRECTORY_SEPARATOR . 'cert' . DIRECTORY_SEPARATOR);
+					if ($this->rcopy($this->root . DIRECTORY_SEPARATOR . 'api' . DIRECTORY_SEPARATOR . 'functions' . DIRECTORY_SEPARATOR . 'cert' . DIRECTORY_SEPARATOR . 'custom.pem', $this->root . DIRECTORY_SEPARATOR . 'data' . DIRECTORY_SEPARATOR . 'cert' . DIRECTORY_SEPARATOR . 'custom.pem')) {
+						$this->setLoggerChannel('Migration');
+						$this->logger->info('Moved over custom cert file');
+					}
+				}
+				// Migrate over favIcon
+				$this->makeDir($this->root . DIRECTORY_SEPARATOR . 'data' . DIRECTORY_SEPARATOR . 'favicon');
+				if ($this->rcopy($this->root . DIRECTORY_SEPARATOR . 'plugins' . DIRECTORY_SEPARATOR . 'images' . DIRECTORY_SEPARATOR . 'faviconCustom', $this->root . DIRECTORY_SEPARATOR . 'data' . DIRECTORY_SEPARATOR . 'favicon')) {
+					if ($this->config['favIcon'] !== '') {
+						$this->config['favIcon'] = str_replace('plugins/images/faviconCustom', 'data/favicon', $this->config['favIcon']);
+						$this->updateConfig(array('favIcon' => $this->config['favIcon']));
+					}
+					$this->setLoggerChannel('Migration');
+					$this->logger->info('Favicon was migrated over');
+				}
+				// Migrate over custom pages
+				$this->makeDir($this->root . DIRECTORY_SEPARATOR . 'data' . DIRECTORY_SEPARATOR . 'pages');
+				if (file_exists($this->root . DIRECTORY_SEPARATOR . 'api' . DIRECTORY_SEPARATOR . 'pages' . DIRECTORY_SEPARATOR . 'custom')) {
+					if ($this->rcopy($this->root . DIRECTORY_SEPARATOR . 'api' . DIRECTORY_SEPARATOR . 'pages' . DIRECTORY_SEPARATOR . 'custom', $this->root . DIRECTORY_SEPARATOR . 'data' . DIRECTORY_SEPARATOR . 'pages')) {
+						$this->rrmdir($this->root . DIRECTORY_SEPARATOR . 'api' . DIRECTORY_SEPARATOR . 'pages' . DIRECTORY_SEPARATOR . 'custom');
+						$this->setLoggerChannel('Migration');
+						$this->logger->info('Custom pages was migrated over');
+					}
+				}
+				// Migrate over custom routes
+				$this->makeDir($this->root . DIRECTORY_SEPARATOR . 'data' . DIRECTORY_SEPARATOR . 'routes');
+				if (file_exists($this->root . DIRECTORY_SEPARATOR . 'api' . DIRECTORY_SEPARATOR . 'v2' . DIRECTORY_SEPARATOR . 'routes' . DIRECTORY_SEPARATOR . 'custom')) {
+					if ($this->rcopy($this->root . DIRECTORY_SEPARATOR . 'api' . DIRECTORY_SEPARATOR . 'v2' . DIRECTORY_SEPARATOR . 'routes' . DIRECTORY_SEPARATOR . 'custom', $this->root . DIRECTORY_SEPARATOR . 'data' . DIRECTORY_SEPARATOR . 'routes')) {
+						$this->rrmdir($this->root . DIRECTORY_SEPARATOR . 'api' . DIRECTORY_SEPARATOR . 'v2' . DIRECTORY_SEPARATOR . 'routes' . DIRECTORY_SEPARATOR . 'custom');
+						$this->setLoggerChannel('Migration');
+						$this->logger->info('Custom routes was migrated over');
+					}
+				}
+			}
+			return true;
+		}
+		return false;
+	}
+
 	public function upgradeSettingsTabURL()
 	{
 		$response = [
@@ -247,7 +333,7 @@ trait UpgradeFunctions
 		];
 		return $this->processQueries($response);
 	}
-	
+
 	public function upgradeHomepageTabURL()
 	{
 		$response = [
@@ -263,7 +349,7 @@ trait UpgradeFunctions
 		];
 		return $this->processQueries($response);
 	}
-	
+
 	public function upgradeInstalledPluginsConfigItem()
 	{
 		$oldConfigItem = $this->config['installedPlugins'];
@@ -296,7 +382,7 @@ trait UpgradeFunctions
 		}
 		return true;
 	}
-	
+
 	public function removeOldPluginDirectoriesAndFiles()
 	{
 		$folders = [
@@ -326,7 +412,7 @@ trait UpgradeFunctions
 		}
 		return true;
 	}
-	
+
 	public function checkForConfigKeyAddToArray($keys)
 	{
 		$updateItems = [];
@@ -340,7 +426,7 @@ trait UpgradeFunctions
 		}
 		return $updateItems;
 	}
-	
+
 	public function removeOldCustomHTML()
 	{
 		$backup = $this->backupOrganizr();

+ 2 - 2
api/pages/wizard.php

@@ -282,8 +282,8 @@ function get_page_wizard($Organizr)
                                     <div class="panel-wrapper collapse in" aria-expanded="true">
                                         <div class="panel-body">
                                             <p lang="en">The Database will contain sensitive information.  Please place in directory outside of root Web Directory.</p>
-                                            <p lang="en">Suggested Directory: <code>' . dirname(__DIR__, 3) . DIRECTORY_SEPARATOR . 'db</code> <a class="btn default btn-outline clipboard p-a-5" data-clipboard-text="' . dirname(__DIR__, 3) . DIRECTORY_SEPARATOR . 'db" href="javascript:void(0);"><i class="ti-clipboard"></i></a></p>
-                                            <p lang="en">Current Directory: <code>' . dirname(__DIR__, 2) . '</code> <a class="btn default btn-outline clipboard p-a-5" data-clipboard-text="' . dirname(__DIR__, 2) . '" href="javascript:void(0);"><i class="ti-clipboard"></i></a></p>
+                                            <p lang="en">Suggested Directory: <code>' . dirname(__DIR__, 2) . DIRECTORY_SEPARATOR . 'data' . DIRECTORY_SEPARATOR . $Organizr->random_ascii_string(10) . DIRECTORY_SEPARATOR . '</code> <a class="btn default btn-outline clipboard p-a-5" data-clipboard-text="' . dirname(__DIR__, 3) . DIRECTORY_SEPARATOR . 'db" href="javascript:void(0);"><i class="ti-clipboard"></i></a></p>
+                                            <p lang="en">Current Directory: <code>' . dirname(__DIR__, 2) . DIRECTORY_SEPARATOR . 'data' . DIRECTORY_SEPARATOR . '</code> <a class="btn default btn-outline clipboard p-a-5" data-clipboard-text="' . dirname(__DIR__, 2) . '" href="javascript:void(0);"><i class="ti-clipboard"></i></a></p>
                                             <p lang="en">Parent Directory: <code>' . dirname(__DIR__, 3) . '</code> <a class="btn default btn-outline clipboard p-a-5" data-clipboard-text="' . dirname(__DIR__, 3) . '" href="javascript:void(0);"><i class="ti-clipboard"></i></a></p>
                                         </div>
                                     </div>

+ 17 - 2
api/v2/index.php

@@ -99,8 +99,10 @@ foreach (glob(__DIR__ . DIRECTORY_SEPARATOR . 'routes' . DIRECTORY_SEPARATOR . '
 /*
  * Include all custom routes
  */
-foreach (glob(__DIR__ . DIRECTORY_SEPARATOR . 'routes' . DIRECTORY_SEPARATOR . 'custom' . DIRECTORY_SEPARATOR . '*.php') as $filename) {
-	require_once $filename;
+if (file_exists(dirname(__DIR__, 2) . DIRECTORY_SEPARATOR . 'data' . DIRECTORY_SEPARATOR . 'routes')) {
+	foreach (glob(dirname(__DIR__, 2) . DIRECTORY_SEPARATOR . 'data' . DIRECTORY_SEPARATOR . 'routes' . DIRECTORY_SEPARATOR . '*.php') as $filename) {
+		require_once $filename;
+	}
 }
 /*
  * Include all Plugin routes
@@ -113,6 +115,19 @@ foreach ($iteratorIterator as $info) {
 		require_once $info->getPathname();
 	}
 }
+/*
+ * Include all custom Plugin routes
+ */
+if (file_exists(dirname(__DIR__, 2) . DIRECTORY_SEPARATOR . 'data' . DIRECTORY_SEPARATOR . 'plugins')) {
+	$folder = dirname(__DIR__, 2) . DIRECTORY_SEPARATOR . 'data' . DIRECTORY_SEPARATOR . 'plugins';
+	$directoryIterator = new RecursiveDirectoryIterator($folder, FilesystemIterator::SKIP_DOTS);
+	$iteratorIterator = new RecursiveIteratorIterator($directoryIterator);
+	foreach ($iteratorIterator as $info) {
+		if ($info->getFilename() == 'api.php') {
+			require_once $info->getPathname();
+		}
+	}
+}
 /*
  *
  *  This is the last defined api endpoint to catch all undefined endpoints

+ 4 - 3
js/functions.js

@@ -2088,10 +2088,11 @@ function buildImageManagerViewItem(array){
 	if (Array.isArray(array)) {
 		$.each(array, function(i,v) {
 			var filepath = v.split("/");
-			var name = filepath[3].split(".");
+			var name = filepath[(filepath.length) - 1].split(".");
 			var clipboardText = v.replace(/ /g,"%20");
-			imageListing += `
-			<a class="imageManagerItem" href="javascript:void(0);" data-toggle="lightbox" data-gallery="multiimages" data-title="`+name[0]+`" data-clipboard-text="`+clipboardText+`" data-image-path="`+v+`" data-image-name="`+name[0]+`" data-image-name-ext="`+filepath[3]+`"><img data-src="`+v+`" alt="tabImage" class="all studio lazyload" /> </a>
+            var fileAndExt = filepath[(filepath.length) - 1];
+            imageListing += `
+			<a class="imageManagerItem" href="javascript:void(0);" data-toggle="lightbox" data-gallery="multiimages" data-title="`+name[0]+`" data-clipboard-text="`+clipboardText+`" data-image-path="`+v+`" data-image-name="`+name[0]+`" data-image-name-ext="`+fileAndExt+`"><img data-src="`+v+`" alt="tabImage" class="all studio lazyload" /> </a>
 			`;
 		});
 	}