)
	);
	protected $_core_plugins = array(
		"_blank","admin_menu","banner","blogcalendar_menu",
		"chatbox_menu", "comment_menu",
		"contact", "download", "featurebox", "forum","gallery",
		"gsitemap", "hero", "import", "linkwords", "list_new",  "login_menu",
		 "newforumposts_main", "news", "newsfeed",
		"newsletter","online", "page", "pm","poll",
		"rss_menu","search_menu","siteinfo", "social", "tagcloud", "tinymce4",
		"user"
	);
	private $_accepted_categories = array('settings'=>EPL_ADLAN_147, 'users'=>EPL_ADLAN_148, 'content'=>EPL_ADLAN_149,'tools'=> EPL_ADLAN_150, 'manage'=>EPL_ADLAN_151,'misc'=> EPL_ADLAN_152, 'menu'=>EPL_ADLAN_153, 'about'=> EPL_ADLAN_154);
	function __construct()
	{
		$this->_init();
		if(empty($this->_ids) )
		{
		//	e107::getDebug()->log("Running e_plugin::_initIDs()");
		//	e107::getDebug()->log(debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS));
			$this->_initIDs();
		}
	}
		/**
	 * Load specified plugin data.
	 * @param string $plugdir
	 * @return e_plugin
	 */
	public function load($plugdir)
	{
		$this->_plugdir = (string) $plugdir;
		return $this;
	}
	/**
	 * @return array
	 */
	public function getCategoryList()
	{
		return $this->_accepted_categories;
	}
	/**
	 * @return int[]|string[]
	 */
	public function getDetected()
	{
		return array_keys($this->_data);
	}
	/**
	 * @return string[]
	 */
	public function getCorePluginList()
	{
		return $this->_core_plugins;
	}
	/**
	 * @return $this
	 */
	public function clearCache()
	{
		$this->_installed = array();
		$this->_addons = array();
		e107::setRegistry('core/e107/addons/e_url');
		$this->_init(true);
		$this->_initIDs();
		return $this;
	}
	/**
	 * @return array|false[]|string[]
	 */
	public function getInstalledWysiwygEditors()
	{
		$result = array();
		foreach(array_keys($this->_installed) as $k)
		{
			$pl = new e_plugin();
			$pl->load($k);
			$keys = $pl->getKeywords();
			// check the keywords
			if (is_array($keys) && in_array('wysiwyg', $keys['word']))
			{
				if (in_array('default', $keys['word']))
				{
					// add "default" editor to the beginning of the array
					$result = array_merge(array($k => $pl->getName()), $result);
				}
				else
				{
					// add all "wysiwyg" editors to the array
					$result[$k] = $pl->getName();
				}
			}
		}
		return $result;
	}
	/**
	 * @return array
	 */
	public function getInstalled()
	{
		return $this->_installed;
	}
	/**
	 * @return false|mixed
	 */
	public function getId()
	{
		if(empty($this->_plugdir))
		{
			e107::getDebug()->log("\$this->_plugdir is empty ".__FILE__." ". __CLASS__ ."::".__METHOD__);
		}
		if(isset($this->_ids[$this->_plugdir]))
		{
			return $this->_ids[$this->_plugdir];
		}
		return false;
	}
	/**
	 * @return false|mixed
	 */
	public function getCompat()
	{
		if(isset($this->_data[$this->_plugdir]['@attributes']['compatibility']))
		{
			return $this->_data[$this->_plugdir]['@attributes']['compatibility'];
		}
		return false;
	}
	/**
	 * @return bool
	 */
	public function getInstallRequired()
	{
		if(empty($this->_plugdir))
		{
			e107::getDebug()->log("\$this->_plugdir is empty ".__FILE__." ". __CLASS__ ."::".__METHOD__);
		}
		if(isset($this->_data[$this->_plugdir]['@attributes']['installRequired']))
		{
			return $this->_data[$this->_plugdir]['@attributes']['installRequired'] !== 'false';
		}
		return false;
	}
	/**
	 * @return false|mixed
	 */
	public function getVersion()
	{
		if(empty($this->_plugdir))
		{
			e107::getDebug()->log("\$this->_plugdir is empty ".__FILE__." ". __CLASS__ ."::".__METHOD__);
		}
		if(isset($this->_data[$this->_plugdir]['@attributes']['version']))
		{
			return $this->_data[$this->_plugdir]['@attributes']['version'];
		}
		return false;
	}
	/**
	 * @return false|mixed
	 */
	public function getDate()
	{
		if(isset($this->_data[$this->_plugdir]['@attributes']['date']))
		{
			return $this->_data[$this->_plugdir]['@attributes']['date'];
		}
		return false;
	}
	/**
	 * @param $type
	 * @return false|mixed
	 */
	public function getAuthor($type='name')
	{
		if(!isset($this->_data[$this->_plugdir]['author']['@attributes'][$type]))
		{
			return false;
		}
		return $this->_data[$this->_plugdir]['author']['@attributes'][$type];
	}
	/**
	 * @return false|string
	 */
	public function getCategory()
	{
		if(!isset($this->_data[$this->_plugdir]['category']))
		{
			return false;
		}
		return (string) $this->_data[$this->_plugdir]['category'];
	}
	/**
	 * @return false|mixed
	 */
	public function getKeywords()
	{
		if(!isset($this->_data[$this->_plugdir]['keywords']))
		{
			return false;
		}
		return $this->_data[$this->_plugdir]['keywords'];
	}
	/**
	 * @return false|mixed
	 */
	public function getDescription()
	{
		if(!isset($this->_data[$this->_plugdir]['description']['@value']))
		{
			return false;
		}
		return $this->_data[$this->_plugdir]['description']['@value'];
	}
	/**
	 * @param $size
	 * @param $opt
	 * @return mixed|string|null
	 */
	public function getIcon($size = 16, $opt='')
	{
		if(!isset($this->_data[$this->_plugdir]))
		{
			return null;
		}
		$link = varset($this->_data[$this->_plugdir]['adminLinks']['link'][0]['@attributes']);
		$k = array(16 => 'iconSmall', 24 => 'icon', 32 => 'icon', 128=>'icon128');
		$def = array(16 => E_16_PLUGIN, 24 => E_24_PLUGIN, 32 => E_32_PLUGIN);
		$key = $k[$size];
		if(empty($link[$key]))
		{
			return $def[$size];
		}
		$caption = $this->getName();
		if($opt === 'path')
		{
			return e107::getParser()->createConstants(e_PLUGIN_ABS.$this->_plugdir.'/'.$link[$key]);
		}
		return " ";
	}
	/**
	 * @return array|false|string|string[]
	 */
	public function getAdminCaption()
	{
		$att = $this->_data[$this->_plugdir]['adminLinks']['link'][0]['@attributes'];
		if(empty($att['description']))
		{
			return false;
		}
		return str_replace("'", '', e107::getParser()->toHTML($att['description'], FALSE, 'defs, emotes_off'));
	}
	/**
	 * @return false|string
	 */
	public function getAdminUrl()
	{
		if(!empty($this->_data[$this->_plugdir]['administration']['configFile']))
		{
			return e_PLUGIN_ABS.$this->_plugdir.'/'.$this->_data[$this->_plugdir]['administration']['configFile'];
		}
		return false;
	}
	/**
	 * Check if the current plugin is a legacy plugin which doesn't use plugin.xml
	 * @return mixed
	 */
	public function isLegacy()
	{
		if(empty($this->_plugdir))
		{
			e107::getDebug()->log("\$this->_plugdir is empty ".__FILE__." ". __CLASS__ ."::".__METHOD__);
		}
		return varset($this->_data[$this->_plugdir]['legacy']);
	}
	/**
	 * Check if the current plugin has a global lan file
	 * @return mixed
	 */
	public function hasLanGlobal()
	{
		if(empty($this->_plugdir))
		{
			e107::getDebug()->log("\$this->_plugdir is empty ".__FILE__." ". __CLASS__ ."::".__METHOD__);
			return null;
		}
		return isset($this->_data[$this->_plugdir]['lan']) ? $this->_data[$this->_plugdir]['lan'] : false;
	}
	/**
	 * @param $plug
	 * @param $version
	 * @return $this
	 */
	function setInstalled($plug, $version)
	{
		$this->_installed[$plug] = $version;
		return $this;
	}
	/**
	 * Check if the currently loaded plugin is installed
	 * @return bool
	 */
	public function isInstalled()
	{
		if(empty($this->_plugdir))
		{
			e107::getDebug()->log("\$this->_plugdir is empty ".__FILE__." ". __CLASS__ ."::".__METHOD__);
		}
		return array_key_exists($this->_plugdir, $this->_installed);
	}
	/**
	 * Check if the currently loaded plugin's addon has errors.
	 * @param string e_xxxx addon
	 * @return int|array
	 */
	public function getAddonErrors($e_xxx)
	{
		if(substr($e_xxx, -3) === '.sc')
		{
			$filename =  $e_xxx;
			$sc = true;
		}
		else
		{
			$filename =   $e_xxx.".php";
			$sc = false;
		}
		if (is_readable(e_PLUGIN.$this->_plugdir."/".$filename))
		{
			$content = file_get_contents(e_PLUGIN.$this->_plugdir."/".$filename);
		}
		else
		{
			return 2;
		}
		if(substr($e_xxx, - 4, 4) == '_sql')
		{
			if(strpos($content,'INSERT INTO')!==false)
			{
				return array('type'=> 'error', 'msg'=>"INSERT sql commands are not permitted here. Use a ".$this->_plugdir."_setup.php file instead.");
			}
			else
			{
				return 0;
			}
		}
		// Generic markup check
		if ($sc === false && !$this->isValidAddonMarkup($content))
		{
			return 1;
		}
		if($e_xxx == 'e_meta' && strpos($content,'
";
	}
	/**
	 * @return array|false|string|string[]
	 */
	public function getAdminCaption()
	{
		$att = $this->_data[$this->_plugdir]['adminLinks']['link'][0]['@attributes'];
		if(empty($att['description']))
		{
			return false;
		}
		return str_replace("'", '', e107::getParser()->toHTML($att['description'], FALSE, 'defs, emotes_off'));
	}
	/**
	 * @return false|string
	 */
	public function getAdminUrl()
	{
		if(!empty($this->_data[$this->_plugdir]['administration']['configFile']))
		{
			return e_PLUGIN_ABS.$this->_plugdir.'/'.$this->_data[$this->_plugdir]['administration']['configFile'];
		}
		return false;
	}
	/**
	 * Check if the current plugin is a legacy plugin which doesn't use plugin.xml
	 * @return mixed
	 */
	public function isLegacy()
	{
		if(empty($this->_plugdir))
		{
			e107::getDebug()->log("\$this->_plugdir is empty ".__FILE__." ". __CLASS__ ."::".__METHOD__);
		}
		return varset($this->_data[$this->_plugdir]['legacy']);
	}
	/**
	 * Check if the current plugin has a global lan file
	 * @return mixed
	 */
	public function hasLanGlobal()
	{
		if(empty($this->_plugdir))
		{
			e107::getDebug()->log("\$this->_plugdir is empty ".__FILE__." ". __CLASS__ ."::".__METHOD__);
			return null;
		}
		return isset($this->_data[$this->_plugdir]['lan']) ? $this->_data[$this->_plugdir]['lan'] : false;
	}
	/**
	 * @param $plug
	 * @param $version
	 * @return $this
	 */
	function setInstalled($plug, $version)
	{
		$this->_installed[$plug] = $version;
		return $this;
	}
	/**
	 * Check if the currently loaded plugin is installed
	 * @return bool
	 */
	public function isInstalled()
	{
		if(empty($this->_plugdir))
		{
			e107::getDebug()->log("\$this->_plugdir is empty ".__FILE__." ". __CLASS__ ."::".__METHOD__);
		}
		return array_key_exists($this->_plugdir, $this->_installed);
	}
	/**
	 * Check if the currently loaded plugin's addon has errors.
	 * @param string e_xxxx addon
	 * @return int|array
	 */
	public function getAddonErrors($e_xxx)
	{
		if(substr($e_xxx, -3) === '.sc')
		{
			$filename =  $e_xxx;
			$sc = true;
		}
		else
		{
			$filename =   $e_xxx.".php";
			$sc = false;
		}
		if (is_readable(e_PLUGIN.$this->_plugdir."/".$filename))
		{
			$content = file_get_contents(e_PLUGIN.$this->_plugdir."/".$filename);
		}
		else
		{
			return 2;
		}
		if(substr($e_xxx, - 4, 4) == '_sql')
		{
			if(strpos($content,'INSERT INTO')!==false)
			{
				return array('type'=> 'error', 'msg'=>"INSERT sql commands are not permitted here. Use a ".$this->_plugdir."_setup.php file instead.");
			}
			else
			{
				return 0;
			}
		}
		// Generic markup check
		if ($sc === false && !$this->isValidAddonMarkup($content))
		{
			return 1;
		}
		if($e_xxx == 'e_meta' && strpos($content,'