plugins/admin/PluginManager.php
changeset 1227 bdac73ed481e
parent 1081 745200a9cc2a
equal deleted inserted replaced
1226:de56132c008d 1227:bdac73ed481e
    41  *
    41  *
    42  * The format for plugin metadata is as follows:
    42  * The format for plugin metadata is as follows:
    43  <code>
    43  <code>
    44  /**!info**
    44  /**!info**
    45  {
    45  {
    46    "Plugin Name" : "Foo plugin",
    46  	"Plugin Name" : "Foo plugin",
    47    "Plugin URI" : "http://fooplugin.enanocms.org/",
    47  	"Plugin URI" : "http://fooplugin.enanocms.org/",
    48    "Description" : "Some short descriptive text",
    48  	"Description" : "Some short descriptive text",
    49    "Author" : "John Doe",
    49  	"Author" : "John Doe",
    50    "Version" : "0.1",
    50  	"Version" : "0.1",
    51    "Author URI" : "http://yourdomain.com/",
    51  	"Author URI" : "http://yourdomain.com/",
    52    "Version list" : [ "0.1-alpha1", "0.1-alpha2", "0.1-beta1", "0.1" ]
    52  	"Version list" : [ "0.1-alpha1", "0.1-alpha2", "0.1-beta1", "0.1" ]
    53  }
    53  }
    54  **!* /
    54  **!* /
    55  </code>
    55  </code>
    56  * This is the format for language data:
    56  * This is the format for language data:
    57  <code>
    57  <code>
    58  /**!language**
    58  /**!language**
    59  {
    59  {
    60    // each entry at this level should be an ISO-639-1 language code.
    60  	// each entry at this level should be an ISO-639-1 language code.
    61    eng: {
    61  	eng: {
    62      // from here on in is the standard langauge file format
    62  		// from here on in is the standard langauge file format
    63      categories: [ 'meta', 'foo', 'bar' ],
    63  		categories: [ 'meta', 'foo', 'bar' ],
    64      strings: {
    64  		strings: {
    65        meta: {
    65  			meta: {
    66          foo: "Foo strings",
    66  				foo: "Foo strings",
    67          bar: "Bar strings"
    67  				bar: "Bar strings"
    68        },
    68  			},
    69        foo: {
    69  			foo: {
    70          string_name: "string value",
    70  				string_name: "string value",
    71          string_name_2: "string value 2"
    71  				string_name_2: "string value 2"
    72        }
    72  			}
    73      }
    73  		}
    74    }
    74  	}
    75  }
    75  }
    76  **!* / (once more, remove the space in there)
    76  **!* / (once more, remove the space in there)
    77  </code>
    77  </code>
    78  * Here is the format for installation schemas:
    78  * Here is the format for installation schemas:
    79  <code>
    79  <code>
    80  /**!install**
    80  /**!install**
    81  
    81  
    82  CREATE TABLE {{TABLE_PREFIX}}foo_table(
    82  CREATE TABLE {{TABLE_PREFIX}}foo_table(
    83    ...
    83  	...
    84  )
    84  )
    85  
    85  
    86  **!* /
    86  **!* /
    87  </code>
    87  </code>
    88  * And finally, the format for upgrade schemas:
    88  * And finally, the format for upgrade schemas:
   104 
   104 
   105 // Plugin manager "2.0"
   105 // Plugin manager "2.0"
   106 
   106 
   107 function page_Admin_PluginManager()
   107 function page_Admin_PluginManager()
   108 {
   108 {
   109   global $db, $session, $paths, $template, $plugins; // Common objects
   109 	global $db, $session, $paths, $template, $plugins; // Common objects
   110   global $lang, $cache;
   110 	global $lang, $cache;
   111   if ( $session->auth_level < USER_LEVEL_ADMIN || $session->user_level < USER_LEVEL_ADMIN )
   111 	if ( $session->auth_level < USER_LEVEL_ADMIN || $session->user_level < USER_LEVEL_ADMIN )
   112   {
   112 	{
   113     $login_link = makeUrlNS('Special', 'Login/' . $paths->nslist['Special'] . 'Administration', 'level=' . USER_LEVEL_ADMIN, true);
   113 		$login_link = makeUrlNS('Special', 'Login/' . $paths->nslist['Special'] . 'Administration', 'level=' . USER_LEVEL_ADMIN, true);
   114     echo '<h3>' . $lang->get('adm_err_not_auth_title') . '</h3>';
   114 		echo '<h3>' . $lang->get('adm_err_not_auth_title') . '</h3>';
   115     echo '<p>' . $lang->get('adm_err_not_auth_body', array( 'login_link' => $login_link )) . '</p>';
   115 		echo '<p>' . $lang->get('adm_err_not_auth_body', array( 'login_link' => $login_link )) . '</p>';
   116     return;
   116 		return;
   117   }
   117 	}
   118   
   118 	
   119   $plugin_list = $plugins->get_plugin_list(null, false);
   119 	$plugin_list = $plugins->get_plugin_list(null, false);
   120   
   120 	
   121   // Are we processing an AJAX request from the smartform?
   121 	// Are we processing an AJAX request from the smartform?
   122   if ( $paths->getParam(0) == 'action.json' )
   122 	if ( $paths->getParam(0) == 'action.json' )
   123   {
   123 	{
   124     // Set to application/json to discourage advertisement scripts
   124 		// Set to application/json to discourage advertisement scripts
   125     header('Content-Type: text/javascript');
   125 		header('Content-Type: text/javascript');
   126     
   126 		
   127     // Init return data
   127 		// Init return data
   128     $return = array('mode' => 'error', 'error' => 'undefined');
   128 		$return = array('mode' => 'error', 'error' => 'undefined');
   129     
   129 		
   130     // Start parsing process
   130 		// Start parsing process
   131     try
   131 		try
   132     {
   132 		{
   133       // Is the request properly sent on POST?
   133 			// Is the request properly sent on POST?
   134       if ( isset($_POST['r']) )
   134 			if ( isset($_POST['r']) )
   135       {
   135 			{
   136         // Try to decode the request
   136 				// Try to decode the request
   137         $request = enano_json_decode($_POST['r']);
   137 				$request = enano_json_decode($_POST['r']);
   138         // Is the action to perform specified?
   138 				// Is the action to perform specified?
   139         if ( isset($request['mode']) )
   139 				if ( isset($request['mode']) )
   140         {
   140 				{
   141           switch ( $request['mode'] )
   141 					switch ( $request['mode'] )
   142           {
   142 					{
   143             case 'install':
   143 						case 'install':
   144               // did they specify a plugin to operate on?
   144 							// did they specify a plugin to operate on?
   145               if ( !isset($request['plugin']) )
   145 							if ( !isset($request['plugin']) )
   146               {
   146 							{
   147                 $return = array(
   147 								$return = array(
   148                   'mode' => 'error',
   148 									'mode' => 'error',
   149                   'error' => 'No plugin specified.',
   149 									'error' => 'No plugin specified.',
   150                 );
   150 								);
   151                 break;
   151 								break;
   152               }
   152 							}
   153               if ( !isset($request['install_confirmed']) )
   153 							if ( !isset($request['install_confirmed']) )
   154               {
   154 							{
   155                 if ( $plugins->is_file_auth_plugin($request['plugin']) )
   155 								if ( $plugins->is_file_auth_plugin($request['plugin']) )
   156                 {
   156 								{
   157                   $return = array(
   157 									$return = array(
   158                     'confirm_title' => 'acppl_msg_confirm_authext_title',
   158 										'confirm_title' => 'acppl_msg_confirm_authext_title',
   159                     'confirm_body' => 'acppl_msg_confirm_authext_body',
   159 										'confirm_body' => 'acppl_msg_confirm_authext_body',
   160                     'need_confirm' => true,
   160 										'need_confirm' => true,
   161                     'success' => false
   161 										'success' => false
   162                   );
   162 									);
   163                   break;
   163 									break;
   164                 }
   164 								}
   165               }
   165 							}
   166               
   166 							
   167               $return = $plugins->install_plugin($request['plugin'], $plugin_list);
   167 							$return = $plugins->install_plugin($request['plugin'], $plugin_list);
   168               break;
   168 							break;
   169             case 'upgrade':
   169 						case 'upgrade':
   170               // did they specify a plugin to operate on?
   170 							// did they specify a plugin to operate on?
   171               if ( !isset($request['plugin']) )
   171 							if ( !isset($request['plugin']) )
   172               {
   172 							{
   173                 $return = array(
   173 								$return = array(
   174                   'mode' => 'error',
   174 									'mode' => 'error',
   175                   'error' => 'No plugin specified.',
   175 									'error' => 'No plugin specified.',
   176                 );
   176 								);
   177                 break;
   177 								break;
   178               }
   178 							}
   179               
   179 							
   180               $return = $plugins->upgrade_plugin($request['plugin'], $plugin_list);
   180 							$return = $plugins->upgrade_plugin($request['plugin'], $plugin_list);
   181               break;
   181 							break;
   182             case 'reimport':
   182 						case 'reimport':
   183               // did they specify a plugin to operate on?
   183 							// did they specify a plugin to operate on?
   184               if ( !isset($request['plugin']) )
   184 							if ( !isset($request['plugin']) )
   185               {
   185 							{
   186                 $return = array(
   186 								$return = array(
   187                   'mode' => 'error',
   187 									'mode' => 'error',
   188                   'error' => 'No plugin specified.',
   188 									'error' => 'No plugin specified.',
   189                 );
   189 								);
   190                 break;
   190 								break;
   191               }
   191 							}
   192               
   192 							
   193               $return = $plugins->reimport_plugin_strings($request['plugin'], $plugin_list);
   193 							$return = $plugins->reimport_plugin_strings($request['plugin'], $plugin_list);
   194               break;
   194 							break;
   195             case 'uninstall':
   195 						case 'uninstall':
   196               // did they specify a plugin to operate on?
   196 							// did they specify a plugin to operate on?
   197               if ( !isset($request['plugin']) )
   197 							if ( !isset($request['plugin']) )
   198               {
   198 							{
   199                 $return = array(
   199 								$return = array(
   200                   'mode' => 'error',
   200 									'mode' => 'error',
   201                   'error' => 'No plugin specified.',
   201 									'error' => 'No plugin specified.',
   202                 );
   202 								);
   203                 break;
   203 								break;
   204               }
   204 							}
   205               
   205 							
   206               $return = $plugins->uninstall_plugin($request['plugin'], $plugin_list);
   206 							$return = $plugins->uninstall_plugin($request['plugin'], $plugin_list);
   207               break;
   207 							break;
   208             case 'disable':
   208 						case 'disable':
   209             case 'enable':
   209 						case 'enable':
   210               // We're not in demo mode. Right?
   210 							// We're not in demo mode. Right?
   211               if ( defined('ENANO_DEMO_MODE') )
   211 							if ( defined('ENANO_DEMO_MODE') )
   212               {
   212 							{
   213                 $return = array(
   213 								$return = array(
   214                     'mode' => 'error',
   214 										'mode' => 'error',
   215                     'error' => $lang->get('acppl_err_demo_mode')
   215 										'error' => $lang->get('acppl_err_demo_mode')
   216                   );
   216 									);
   217                 break;
   217 								break;
   218               }
   218 							}
   219               $flags_col = ( $request['mode'] == 'disable' ) ?
   219 							$flags_col = ( $request['mode'] == 'disable' ) ?
   220                             "plugin_flags | "  . PLUGIN_DISABLED :
   220 														"plugin_flags | "  . PLUGIN_DISABLED :
   221                             "plugin_flags & ~" . PLUGIN_DISABLED;
   221 														"plugin_flags & ~" . PLUGIN_DISABLED;
   222               // did they specify a plugin to operate on?
   222 							// did they specify a plugin to operate on?
   223               if ( !isset($request['plugin']) )
   223 							if ( !isset($request['plugin']) )
   224               {
   224 							{
   225                 $return = array(
   225 								$return = array(
   226                   'mode' => 'error',
   226 									'mode' => 'error',
   227                   'error' => 'No plugin specified.',
   227 									'error' => 'No plugin specified.',
   228                 );
   228 								);
   229                 break;
   229 								break;
   230               }
   230 							}
   231               // is the plugin in the directory and already installed?
   231 							// is the plugin in the directory and already installed?
   232               if ( !isset($plugin_list[$request['plugin']]) || (
   232 							if ( !isset($plugin_list[$request['plugin']]) || (
   233                   isset($plugin_list[$request['plugin']]) && !$plugin_list[$request['plugin']]['installed']
   233 									isset($plugin_list[$request['plugin']]) && !$plugin_list[$request['plugin']]['installed']
   234                 ))
   234 								))
   235               {
   235 							{
   236                 $return = array(
   236 								$return = array(
   237                   'mode' => 'error',
   237 									'mode' => 'error',
   238                   'error' => 'Invalid plugin specified.',
   238 									'error' => 'Invalid plugin specified.',
   239                 );
   239 								);
   240                 break;
   240 								break;
   241               }
   241 							}
   242               // get plugin id
   242 							// get plugin id
   243               $dataset =& $plugin_list[$request['plugin']];
   243 							$dataset =& $plugin_list[$request['plugin']];
   244               if ( empty($dataset['plugin id']) )
   244 							if ( empty($dataset['plugin id']) )
   245               {
   245 							{
   246                 $return = array(
   246 								$return = array(
   247                   'mode' => 'error',
   247 									'mode' => 'error',
   248                   'error' => 'Couldn\'t retrieve plugin ID.',
   248 									'error' => 'Couldn\'t retrieve plugin ID.',
   249                 );
   249 								);
   250                 break;
   250 								break;
   251               }
   251 							}
   252               
   252 							
   253               // log action
   253 							// log action
   254               $time        = time();
   254 							$time        = time();
   255               $ip_db       = $db->escape($_SERVER['REMOTE_ADDR']);
   255 							$ip_db       = $db->escape($_SERVER['REMOTE_ADDR']);
   256               $username_db = $db->escape($session->username);
   256 							$username_db = $db->escape($session->username);
   257               $file_db     = $db->escape($request['plugin']);
   257 							$file_db     = $db->escape($request['plugin']);
   258               // request['mode'] is TRUSTED - the case statement will only process if it is one of {enable,disable}.
   258 							// request['mode'] is TRUSTED - the case statement will only process if it is one of {enable,disable}.
   259               $q = $db->sql_query('INSERT INTO '.table_prefix."logs(log_type, action, time_id, edit_summary, author, page_text) VALUES\n"
   259 							$q = $db->sql_query('INSERT INTO '.table_prefix."logs(log_type, action, time_id, edit_summary, author, page_text) VALUES\n"
   260                                 . "  ('security', 'plugin_{$request['mode']}', $time, '$ip_db', '$username_db', '$file_db');");
   260 																. "  ('security', 'plugin_{$request['mode']}', $time, '$ip_db', '$username_db', '$file_db');");
   261               if ( !$q )
   261 							if ( !$q )
   262                 $db->_die();
   262 								$db->_die();
   263               
   263 							
   264               // perform update
   264 							// perform update
   265               $q = $db->sql_query('UPDATE ' . table_prefix . "plugins SET plugin_flags = $flags_col WHERE plugin_id = {$dataset['plugin id']};");
   265 							$q = $db->sql_query('UPDATE ' . table_prefix . "plugins SET plugin_flags = $flags_col WHERE plugin_id = {$dataset['plugin id']};");
   266               if ( !$q )
   266 							if ( !$q )
   267                 $db->die_json();
   267 								$db->die_json();
   268               
   268 							
   269               $cache->purge('plugins');
   269 							$cache->purge('plugins');
   270               
   270 							
   271               $return = array(
   271 							$return = array(
   272                 'success' => true
   272 								'success' => true
   273               );
   273 							);
   274               break;
   274 							break;
   275             case 'import':
   275 						case 'import':
   276               // import all of the plugin_* config entries
   276 							// import all of the plugin_* config entries
   277               $q = $db->sql_query('SELECT config_name, config_value FROM ' . table_prefix . "config WHERE config_name LIKE 'plugin_%';");
   277 							$q = $db->sql_query('SELECT config_name, config_value FROM ' . table_prefix . "config WHERE config_name LIKE 'plugin_%';");
   278               if ( !$q )
   278 							if ( !$q )
   279                 $db->die_json();
   279 								$db->die_json();
   280               
   280 							
   281               while ( $row = $db->fetchrow($q) )
   281 							while ( $row = $db->fetchrow($q) )
   282               {
   282 							{
   283                 $plugin_filename = preg_replace('/^plugin_/', '', $row['config_name']);
   283 								$plugin_filename = preg_replace('/^plugin_/', '', $row['config_name']);
   284                 if ( isset($plugin_list[$plugin_filename]) && !@$plugin_list[$plugin_filename]['installed'] )
   284 								if ( isset($plugin_list[$plugin_filename]) && !@$plugin_list[$plugin_filename]['installed'] )
   285                 {
   285 								{
   286                   $return = $plugins->install_plugin($plugin_filename, $plugin_list);
   286 									$return = $plugins->install_plugin($plugin_filename, $plugin_list);
   287                   if ( !$return['success'] )
   287 									if ( !$return['success'] )
   288                     break 2;
   288 										break 2;
   289                   if ( $row['config_value'] == '0' )
   289 									if ( $row['config_value'] == '0' )
   290                   {
   290 									{
   291                     $fn_db = $db->escape($plugin_filename);
   291 										$fn_db = $db->escape($plugin_filename);
   292                     $e = $db->sql_query('UPDATE ' . table_prefix . "plugins SET plugin_flags = plugin_flags | " . PLUGIN_DISABLED . " WHERE plugin_filename = '$fn_db';");
   292 										$e = $db->sql_query('UPDATE ' . table_prefix . "plugins SET plugin_flags = plugin_flags | " . PLUGIN_DISABLED . " WHERE plugin_filename = '$fn_db';");
   293                     if ( !$e )
   293 										if ( !$e )
   294                       $db->die_json();
   294 											$db->die_json();
   295                   }
   295 									}
   296                 }
   296 								}
   297               }
   297 							}
   298               $db->free_result($q);
   298 							$db->free_result($q);
   299               
   299 							
   300               $q = $db->sql_query('DELETE FROM ' . table_prefix . "config WHERE config_name LIKE 'plugin_%';");
   300 							$q = $db->sql_query('DELETE FROM ' . table_prefix . "config WHERE config_name LIKE 'plugin_%';");
   301               if ( !$q )
   301 							if ( !$q )
   302                 $db->die_json();
   302 								$db->die_json();
   303               
   303 							
   304               $return = array('success' => true);
   304 							$return = array('success' => true);
   305               break;
   305 							break;
   306             default:
   306 						default:
   307               // The requested action isn't something this script knows how to do
   307 							// The requested action isn't something this script knows how to do
   308               $return = array(
   308 							$return = array(
   309                 'mode' => 'error',
   309 								'mode' => 'error',
   310                 'error' => 'Unknown mode "' . $request['mode'] . '" sent in request'
   310 								'error' => 'Unknown mode "' . $request['mode'] . '" sent in request'
   311               );
   311 							);
   312               break;
   312 							break;
   313           }
   313 					}
   314         }
   314 				}
   315         else
   315 				else
   316         {
   316 				{
   317           // Didn't specify action
   317 					// Didn't specify action
   318           $return = array(
   318 					$return = array(
   319             'mode' => 'error',
   319 						'mode' => 'error',
   320             'error' => 'Missing key "mode" in request'
   320 						'error' => 'Missing key "mode" in request'
   321           );
   321 					);
   322         }
   322 				}
   323       }
   323 			}
   324       else
   324 			else
   325       {
   325 			{
   326         // Didn't send a request
   326 				// Didn't send a request
   327         $return = array(
   327 				$return = array(
   328           'mode' => 'error',
   328 					'mode' => 'error',
   329           'error' => 'No request specified'
   329 					'error' => 'No request specified'
   330         );
   330 				);
   331       }
   331 			}
   332     }
   332 		}
   333     catch ( Exception $e )
   333 		catch ( Exception $e )
   334     {
   334 		{
   335       // Sent a request but it's not valid JSON
   335 			// Sent a request but it's not valid JSON
   336       $return = array(
   336 			$return = array(
   337           'mode' => 'error',
   337 					'mode' => 'error',
   338           'error' => 'Invalid request - JSON parsing failed'
   338 					'error' => 'Invalid request - JSON parsing failed'
   339         );
   339 				);
   340     }
   340 		}
   341     
   341 		
   342     echo enano_json_encode($return);
   342 		echo enano_json_encode($return);
   343     
   343 		
   344     return true;
   344 		return true;
   345   }
   345 	}
   346   
   346 	
   347   // Sort so that system plugins come last
   347 	// Sort so that system plugins come last
   348   ksort($plugin_list);
   348 	ksort($plugin_list);
   349   $plugin_list_sorted = array();
   349 	$plugin_list_sorted = array();
   350   foreach ( $plugin_list as $filename => $data )
   350 	foreach ( $plugin_list as $filename => $data )
   351   {
   351 	{
   352     if ( !$data['system plugin'] )
   352 		if ( !$data['system plugin'] )
   353     {
   353 		{
   354       $plugin_list_sorted[$filename] = $data;
   354 			$plugin_list_sorted[$filename] = $data;
   355     }
   355 		}
   356   }
   356 	}
   357   ksort($plugin_list_sorted);
   357 	ksort($plugin_list_sorted);
   358   foreach ( $plugin_list as $filename => $data )
   358 	foreach ( $plugin_list as $filename => $data )
   359   {
   359 	{
   360     if ( $data['system plugin'] )
   360 		if ( $data['system plugin'] )
   361     {
   361 		{
   362       $plugin_list_sorted[$filename] = $data;
   362 			$plugin_list_sorted[$filename] = $data;
   363     }
   363 		}
   364   }
   364 	}
   365   
   365 	
   366   $plugin_list =& $plugin_list_sorted;
   366 	$plugin_list =& $plugin_list_sorted;
   367   
   367 	
   368   //
   368 	//
   369   // Not a JSON request, output normal HTML interface
   369 	// Not a JSON request, output normal HTML interface
   370   //
   370 	//
   371   
   371 	
   372   // start printing things out
   372 	// start printing things out
   373   echo '<h3>' . $lang->get('acppl_heading_main') . '</h3>';
   373 	echo '<h3>' . $lang->get('acppl_heading_main') . '</h3>';
   374   echo '<p>' . $lang->get('acppl_intro') . '</p>';
   374 	echo '<p>' . $lang->get('acppl_intro') . '</p>';
   375   ?>
   375 	?>
   376   <div class="tblholder">
   376 	<div class="tblholder">
   377     <table border="0" cellspacing="1" cellpadding="5">
   377 		<table border="0" cellspacing="1" cellpadding="5">
   378       <?php
   378 			<?php
   379       $rowid = '2';
   379 			$rowid = '2';
   380       foreach ( $plugin_list as $filename => $data )
   380 			foreach ( $plugin_list as $filename => $data )
   381       {
   381 			{
   382         // print out all plugins
   382 				// print out all plugins
   383         $rowid = ( $rowid == '1' ) ? '2' : '1';
   383 				$rowid = ( $rowid == '1' ) ? '2' : '1';
   384         $plugin_name = ( preg_match('/^[a-z0-9_]+$/', $data['plugin name']) ) ? $lang->get($data['plugin name']) : $data['plugin name'];
   384 				$plugin_name = ( preg_match('/^[a-z0-9_]+$/', $data['plugin name']) ) ? $lang->get($data['plugin name']) : $data['plugin name'];
   385         $plugin_basics = $lang->get('acppl_lbl_plugin_name', array(
   385 				$plugin_basics = $lang->get('acppl_lbl_plugin_name', array(
   386             'plugin' => $plugin_name,
   386 						'plugin' => $plugin_name,
   387             'author' => $data['author']
   387 						'author' => $data['author']
   388           ));
   388 					));
   389         $color = '';
   389 				$color = '';
   390         $buttons = '';
   390 				$buttons = '';
   391         if ( $data['system plugin'] )
   391 				if ( $data['system plugin'] )
   392         {
   392 				{
   393           $status = $lang->get('acppl_lbl_status_system');
   393 					$status = $lang->get('acppl_lbl_status_system');
   394         }
   394 				}
   395         else if ( $data['installed'] && !( $data['status'] & PLUGIN_DISABLED ) && !( $data['status'] & PLUGIN_OUTOFDATE ) )
   395 				else if ( $data['installed'] && !( $data['status'] & PLUGIN_DISABLED ) && !( $data['status'] & PLUGIN_OUTOFDATE ) )
   396         {
   396 				{
   397           // this plugin is all good
   397 					// this plugin is all good
   398           $color = '_green';
   398 					$color = '_green';
   399           $status = $lang->get('acppl_lbl_status_installed');
   399 					$status = $lang->get('acppl_lbl_status_installed');
   400           $buttons = 'reimport|uninstall|disable';
   400 					$buttons = 'reimport|uninstall|disable';
   401         }
   401 				}
   402         else if ( $data['installed'] && $data['status'] & PLUGIN_OUTOFDATE )
   402 				else if ( $data['installed'] && $data['status'] & PLUGIN_OUTOFDATE )
   403         {
   403 				{
   404           $color = '_red';
   404 					$color = '_red';
   405           $status = $lang->get('acppl_lbl_status_need_upgrade');
   405 					$status = $lang->get('acppl_lbl_status_need_upgrade');
   406           $buttons = 'uninstall|upgrade';
   406 					$buttons = 'uninstall|upgrade';
   407         }
   407 				}
   408         else if ( $data['installed'] && $data['status'] & PLUGIN_DISABLED )
   408 				else if ( $data['installed'] && $data['status'] & PLUGIN_DISABLED )
   409         {
   409 				{
   410           $color = '_red';
   410 					$color = '_red';
   411           $status = $lang->get('acppl_lbl_status_disabled');
   411 					$status = $lang->get('acppl_lbl_status_disabled');
   412           $buttons = 'uninstall|enable';
   412 					$buttons = 'uninstall|enable';
   413         }
   413 				}
   414         else
   414 				else
   415         {
   415 				{
   416           $color = '_red';
   416 					$color = '_red';
   417           $status = $lang->get('acppl_lbl_status_uninstalled');
   417 					$status = $lang->get('acppl_lbl_status_uninstalled');
   418           $buttons = 'install';
   418 					$buttons = 'install';
   419         }
   419 				}
   420         $uuid = md5($data['plugin name'] . $data['version'] . $filename);
   420 				$uuid = md5($data['plugin name'] . $data['version'] . $filename);
   421         $desc = ( preg_match('/^[a-z0-9_]+$/', $data['description']) ) ? $lang->get($data['description']) : $data['description'];
   421 				$desc = ( preg_match('/^[a-z0-9_]+$/', $data['description']) ) ? $lang->get($data['description']) : $data['description'];
   422         $desc = sanitize_html($desc);
   422 				$desc = sanitize_html($desc);
   423         
   423 				
   424         $additional = '';
   424 				$additional = '';
   425         
   425 				
   426         // filename
   426 				// filename
   427         $additional .= '<b>' . $lang->get('acppl_lbl_filename') . '</b> ' . "{$filename}<br />";
   427 				$additional .= '<b>' . $lang->get('acppl_lbl_filename') . '</b> ' . "{$filename}<br />";
   428         
   428 				
   429         // plugin's site
   429 				// plugin's site
   430         $data['plugin uri'] = htmlspecialchars($data['plugin uri']);
   430 				$data['plugin uri'] = htmlspecialchars($data['plugin uri']);
   431         $additional .= '<b>' . $lang->get('acppl_lbl_plugin_site') . '</b> ' . "<a href=\"{$data['plugin uri']}\">{$data['plugin uri']}</a><br />";
   431 				$additional .= '<b>' . $lang->get('acppl_lbl_plugin_site') . '</b> ' . "<a href=\"{$data['plugin uri']}\">{$data['plugin uri']}</a><br />";
   432         
   432 				
   433         // author's site
   433 				// author's site
   434         $data['author uri'] = htmlspecialchars($data['author uri']);
   434 				$data['author uri'] = htmlspecialchars($data['author uri']);
   435         $additional .= '<b>' . $lang->get('acppl_lbl_author_site') . '</b> ' . "<a href=\"{$data['author uri']}\">{$data['author uri']}</a><br />";
   435 				$additional .= '<b>' . $lang->get('acppl_lbl_author_site') . '</b> ' . "<a href=\"{$data['author uri']}\">{$data['author uri']}</a><br />";
   436         
   436 				
   437         // version
   437 				// version
   438         $additional .= '<b>' . $lang->get('acppl_lbl_version') . '</b> ' . "{$data['version']}<br />";
   438 				$additional .= '<b>' . $lang->get('acppl_lbl_version') . '</b> ' . "{$data['version']}<br />";
   439         
   439 				
   440         // installed version
   440 				// installed version
   441         if ( $data['status'] & PLUGIN_OUTOFDATE )
   441 				if ( $data['status'] & PLUGIN_OUTOFDATE )
   442         {
   442 				{
   443           $additional .= '<b>' . $lang->get('acppl_lbl_installed_version') . '</b> ' . "{$data['version installed']}<br />";
   443 					$additional .= '<b>' . $lang->get('acppl_lbl_installed_version') . '</b> ' . "{$data['version installed']}<br />";
   444         }
   444 				}
   445         
   445 				
   446         // build list of buttons
   446 				// build list of buttons
   447         $buttons_html = '';
   447 				$buttons_html = '';
   448         if ( !empty($buttons) )
   448 				if ( !empty($buttons) )
   449         {
   449 				{
   450           $filename_js = addslashes($filename);
   450 					$filename_js = addslashes($filename);
   451           $buttons = explode('|', $buttons);
   451 					$buttons = explode('|', $buttons);
   452           $colors = array(
   452 					$colors = array(
   453               'install' => 'green',
   453 							'install' => 'green',
   454               'disable' => 'blue',
   454 							'disable' => 'blue',
   455               'enable' => 'blue',
   455 							'enable' => 'blue',
   456               'upgrade' => 'green',
   456 							'upgrade' => 'green',
   457               'uninstall' => 'red',
   457 							'uninstall' => 'red',
   458               'reimport' => 'green'
   458 							'reimport' => 'green'
   459             );
   459 						);
   460           foreach ( $buttons as $button )
   460 					foreach ( $buttons as $button )
   461           {
   461 					{
   462             $btnface = $lang->get("acppl_btn_$button");
   462 						$btnface = $lang->get("acppl_btn_$button");
   463             $buttons_html .= "<a href=\"#\" onclick=\"ajaxPluginAction('$button', '$filename_js', this); return false;\" class=\"abutton_{$colors[$button]} abutton\">$btnface</a>\n";
   463 						$buttons_html .= "<a href=\"#\" onclick=\"ajaxPluginAction('$button', '$filename_js', this); return false;\" class=\"abutton_{$colors[$button]} abutton\">$btnface</a>\n";
   464           }
   464 					}
   465         }
   465 				}
   466         
   466 				
   467         echo "<tr>
   467 				echo "<tr>
   468                 <td class=\"row{$rowid}$color\">
   468 								<td class=\"row{$rowid}$color\">
   469                   <div style=\"float: right;\">
   469 									<div style=\"float: right;\">
   470                     <b>$status</b>
   470 										<b>$status</b>
   471                   </div>
   471 									</div>
   472                   <div style=\"cursor: pointer;\" onclick=\"if ( !this.fx ) { load_component('jquery'); load_component('jquery-ui'); load_component('messagebox'); load_component('ajax'); this.fx = true; } $('#plugininfo_$uuid').toggle('blind', {}, 500);\">
   472 									<div style=\"cursor: pointer;\" onclick=\"if ( !this.fx ) { load_component('jquery'); load_component('jquery-ui'); load_component('messagebox'); load_component('ajax'); this.fx = true; } $('#plugininfo_$uuid').toggle('blind', {}, 500);\">
   473                     $plugin_basics
   473 										$plugin_basics
   474                   </div>
   474 									</div>
   475                   <span class=\"menuclear\"></span>
   475 									<span class=\"menuclear\"></span>
   476                   <div id=\"plugininfo_$uuid\" style=\"display: none;\">
   476 									<div id=\"plugininfo_$uuid\" style=\"display: none;\">
   477                     $desc
   477 										$desc
   478                     <div style=\"padding: 5px;\">
   478 										<div style=\"padding: 5px;\">
   479                       $additional
   479 											$additional
   480                       <div style=\"float: right; position: relative; top: -10px;\">
   480 											<div style=\"float: right; position: relative; top: -10px;\">
   481                         $buttons_html
   481 												$buttons_html
   482                       </div>
   482 											</div>
   483                       <span class=\"menuclear\"></span>
   483 											<span class=\"menuclear\"></span>
   484                     </div>
   484 										</div>
   485                   </div>
   485 									</div>
   486                 </td>
   486 								</td>
   487               </tr>";
   487 							</tr>";
   488       }
   488 			}
   489       ?>
   489 			?>
   490     </table>
   490 		</table>
   491   </div>
   491 	</div>
   492   <?php
   492 	<?php
   493   // are there still old style plugin entries?
   493 	// are there still old style plugin entries?
   494   $q = $db->sql_query('SELECT 1 FROM ' . table_prefix . "config WHERE config_name LIKE 'plugin_%';");
   494 	$q = $db->sql_query('SELECT 1 FROM ' . table_prefix . "config WHERE config_name LIKE 'plugin_%';");
   495   if ( !$q )
   495 	if ( !$q )
   496     $db->_die();
   496 		$db->_die();
   497   
   497 	
   498   $count = $db->numrows();
   498 	$count = $db->numrows();
   499   $db->free_result($q);
   499 	$db->free_result($q);
   500   
   500 	
   501   if ( $count > 0 )
   501 	if ( $count > 0 )
   502   {
   502 	{
   503     echo '<h3>' . $lang->get('acppl_msg_old_entries_title') . '</h3>';
   503 		echo '<h3>' . $lang->get('acppl_msg_old_entries_title') . '</h3>';
   504     echo '<p>' . $lang->get('acppl_msg_old_entries_body') . '</p>';
   504 		echo '<p>' . $lang->get('acppl_msg_old_entries_body') . '</p>';
   505     echo '<p><a class="abutton abutton_green" href="#" onclick="ajaxPluginAction(\'import\', \'\', false); return false;">' . $lang->get('acppl_btn_import_old') . '</a></p>';
   505 		echo '<p><a class="abutton abutton_green" href="#" onclick="ajaxPluginAction(\'import\', \'\', false); return false;">' . $lang->get('acppl_btn_import_old') . '</a></p>';
   506   }
   506 	}
   507 }
   507 }