includes/plugins.php
changeset 527 21e11f564463
parent 519 94214ec0871c
child 528 43535769970b
equal deleted inserted replaced
526:b2fb50d572c7 527:21e11f564463
    61    * and puts that list in the $load_list property. Plugin developers have absolutely no use for this whatsoever.
    61    * and puts that list in the $load_list property. Plugin developers have absolutely no use for this whatsoever.
    62    */
    62    */
    63   
    63   
    64   function loadAll() 
    64   function loadAll() 
    65   {
    65   {
       
    66     global $db, $session, $paths, $template, $plugins; // Common objects
    66     $dir = ENANO_ROOT.'/plugins/';
    67     $dir = ENANO_ROOT.'/plugins/';
    67     
    68     
    68     $this->load_list = Array();
    69     $this->load_list = $this->system_plugins;
    69     
    70     $q = $db->sql_query('SELECT plugin_filename, plugin_version FROM ' . table_prefix . 'plugins WHERE plugin_flags & ~' . PLUGIN_DISABLED . ' = plugin_flags;');
    70     $plugins = Array();
    71     if ( !$q )
    71     
    72       $db->_die();
    72     // Open a known directory, and proceed to read its contents
    73     
    73     
    74     while ( $row = $db->fetchrow() )
    74     if (is_dir($dir))
    75     {
    75     {
    76       $this->load_list[] = $row['plugin_filename'];
    76       if ($dh = opendir($dir))
    77     }
    77       {
    78     
    78         while (($file = readdir($dh)) !== false)
    79     $this->loaded_plugins = $this->get_plugin_list($this->load_list);
    79         {
    80     
    80           if(preg_match('#^(.*?)\.php$#is', $file))
    81     // check for out-of-date plugins
    81           {
    82     foreach ( $this->load_list as $i => $plugin )
    82             if(getConfig('plugin_'.$file) == '1' || in_array($file, $this->system_plugins))
    83     {
    83             {
    84       if ( in_array($plugin, $this->system_plugins) )
    84               $this->load_list[] = $dir . $file;
    85         continue;
    85               $plugid = substr($file, 0, strlen($file)-4);
    86       if ( $this->loaded_plugins[$plugin]['status'] & PLUGIN_OUTOFDATE )
    86               $f = @file_get_contents($dir . $file);
    87       {
    87               if ( empty($f) )
    88         // it's out of date, don't load
    88                 continue;
    89         unset($this->load_list[$i]);
    89               $f = explode("\n", $f);
    90         unset($this->loaded_plugins[$plugin]);
    90               $f = array_slice($f, 2, 7);
    91       }
    91               $f[0] = substr($f[0], 13);
    92     }
    92               $f[1] = substr($f[1], 12);
    93     
    93               $f[2] = substr($f[2], 13);
    94     $this->load_list = array_unique($this->load_list);
    94               $f[3] = substr($f[3], 8 );
       
    95               $f[4] = substr($f[4], 9 );
       
    96               $f[5] = substr($f[5], 12);
       
    97               $plugins[$plugid] = Array();
       
    98               $plugins[$plugid]['name'] = $f[0];
       
    99               $plugins[$plugid]['uri']  = $f[1];
       
   100               $plugins[$plugid]['desc'] = $f[2];
       
   101               $plugins[$plugid]['auth'] = $f[3];
       
   102               $plugins[$plugid]['vers'] = $f[4];
       
   103               $plugins[$plugid]['aweb'] = $f[5];
       
   104             }
       
   105           }
       
   106         }
       
   107         closedir($dh);
       
   108       }
       
   109     }
       
   110     $this->loaded_plugins = $plugins;
       
   111     //die('<pre>'.htmlspecialchars(print_r($plugins, true)).'</pre>');
       
   112   }
    95   }
   113   
    96   
   114   /**
    97   /**
   115    * Name kept for compatibility. This method is used to add a new hook into the code somewhere. Plugins are encouraged
    98    * Name kept for compatibility. This method is used to add a new hook into the code somewhere. Plugins are encouraged
   116    * to set hooks and hook into other plugins in a fail-safe way, this encourages reuse of code. Returns an array, whose
    99    * to set hooks and hook into other plugins in a fail-safe way, this encourages reuse of code. Returns an array, whose
   213             . '([\w\W]+?)' . "\n"     // value
   196             . '([\w\W]+?)' . "\n"     // value
   214             . '\*\*!\*/'              // closing comment
   197             . '\*\*!\*/'              // closing comment
   215             . '#m';
   198             . '#m';
   216             
   199             
   217     // Match out all blocks
   200     // Match out all blocks
   218     
       
   219     $results = preg_match_all($regexp, $contents, $blocks);
   201     $results = preg_match_all($regexp, $contents, $blocks);
   220     
   202     
   221     $return = array();
   203     $return = array();
   222     foreach ( $blocks[0] as $i => $_ )
   204     foreach ( $blocks[0] as $i => $_ )
   223     {
   205     {
   254     {
   236     {
   255       $return[ $matches[1][$i] ] = $matches[2][$i];
   237       $return[ $matches[1][$i] ] = $matches[2][$i];
   256     }
   238     }
   257     return $return;
   239     return $return;
   258   }
   240   }
       
   241   
       
   242   /**
       
   243    * Reads all plugins in the filesystem and cross-references them with the database, providing a very complete summary of plugins
       
   244    * on the site.
       
   245    * @param array If specified, will restrict scanned files to this list. Defaults to null, which means all PHP files will be scanned.
       
   246    * @return array
       
   247    */
       
   248   
       
   249   function get_plugin_list($restrict = null)
       
   250   {
       
   251     global $db, $session, $paths, $template, $plugins; // Common objects
       
   252     
       
   253     // Scan all plugins
       
   254     $plugin_list = array();
       
   255     
       
   256     if ( $dirh = @opendir( ENANO_ROOT . '/plugins' ) )
       
   257     {
       
   258       while ( $dh = @readdir($dirh) )
       
   259       {
       
   260         if ( !preg_match('/\.php$/i', $dh) )
       
   261           continue;
       
   262         
       
   263         if ( is_array($restrict) )
       
   264           if ( !in_array($dh, $restrict) )
       
   265             continue;
       
   266           
       
   267         $fullpath = ENANO_ROOT . "/plugins/$dh";
       
   268         // it's a PHP file, attempt to read metadata
       
   269         // pass 1: try to read a !info block
       
   270         $blockdata = $this->parse_plugin_blocks($fullpath, 'info');
       
   271         if ( empty($blockdata) )
       
   272         {
       
   273           // no !info block, check for old header
       
   274           $fh = @fopen($fullpath, 'r');
       
   275           if ( !$fh )
       
   276             // can't read, bail out
       
   277             continue;
       
   278           $plugin_data = array();
       
   279           for ( $i = 0; $i < 8; $i++ )
       
   280           {
       
   281             $plugin_data[] = @fgets($fh, 8096);
       
   282           }
       
   283           // close our file handle
       
   284           fclose($fh);
       
   285           // is the header correct?
       
   286           if ( trim($plugin_data[0]) != '<?php' || trim($plugin_data[1]) != '/*' )
       
   287           {
       
   288             // nope. get out.
       
   289             continue;
       
   290           }
       
   291           // parse all the variables
       
   292           $plugin_meta = array();
       
   293           for ( $i = 2; $i <= 7; $i++ )
       
   294           {
       
   295             if ( !preg_match('/^([A-z0-9 ]+?): (.+?)$/', trim($plugin_data[$i]), $match) )
       
   296               continue 2;
       
   297             $plugin_meta[ strtolower($match[1]) ] = $match[2];
       
   298           }
       
   299         }
       
   300         else
       
   301         {
       
   302           // parse JSON block
       
   303           $plugin_data =& $blockdata[0]['value'];
       
   304           $plugin_data = enano_clean_json(enano_trim_json($plugin_data));
       
   305           try
       
   306           {
       
   307             $plugin_meta_uc = enano_json_decode($plugin_data);
       
   308           }
       
   309           catch ( Exception $e )
       
   310           {
       
   311             continue;
       
   312           }
       
   313           // convert all the keys to lowercase
       
   314           $plugin_meta = array();
       
   315           foreach ( $plugin_meta_uc as $key => $value )
       
   316           {
       
   317             $plugin_meta[ strtolower($key) ] = $value;
       
   318           }
       
   319         }
       
   320         if ( !isset($plugin_meta) || !is_array(@$plugin_meta) )
       
   321         {
       
   322           // parsing didn't work.
       
   323           continue;
       
   324         }
       
   325         // check for required keys
       
   326         $required_keys = array('plugin name', 'plugin uri', 'description', 'author', 'version', 'author uri');
       
   327         foreach ( $required_keys as $key )
       
   328         {
       
   329           if ( !isset($plugin_meta[$key]) )
       
   330             // not set, skip this plugin
       
   331             continue 2;
       
   332         }
       
   333         // decide if it's a system plugin
       
   334         $plugin_meta['system plugin'] = in_array($dh, $this->system_plugins);
       
   335         // reset installed variable
       
   336         $plugin_meta['installed'] = false;
       
   337         $plugin_meta['status'] = 0;
       
   338         // all checks passed
       
   339         $plugin_list[$dh] = $plugin_meta;
       
   340       }
       
   341     }
       
   342     // gather info about installed plugins
       
   343     $q = $db->sql_query('SELECT plugin_id, plugin_filename, plugin_version, plugin_flags FROM ' . table_prefix . 'plugins;');
       
   344     if ( !$q )
       
   345       $db->_die();
       
   346     while ( $row = $db->fetchrow() )
       
   347     {
       
   348       if ( !isset($plugin_list[ $row['plugin_filename'] ]) )
       
   349       {
       
   350         // missing plugin file, don't report (for now)
       
   351         continue;
       
   352       }
       
   353       $filename =& $row['plugin_filename'];
       
   354       $plugin_list[$filename]['installed'] = true;
       
   355       $plugin_list[$filename]['status'] = PLUGIN_INSTALLED;
       
   356       $plugin_list[$filename]['plugin id'] = $row['plugin_id'];
       
   357       if ( $row['plugin_version'] != $plugin_list[$filename]['version'] )
       
   358       {
       
   359         $plugin_list[$filename]['status'] |= PLUGIN_OUTOFDATE;
       
   360         $plugin_list[$filename]['version installed'] = $row['plugin_version'];
       
   361       }
       
   362       if ( $row['plugin_flags'] & PLUGIN_DISABLED )
       
   363       {
       
   364         $plugin_list[$filename]['status'] |= PLUGIN_DISABLED;
       
   365       }
       
   366     }
       
   367     $db->free_result();
       
   368     
       
   369     // sort it all out by filename
       
   370     ksort($plugin_list);
       
   371     
       
   372     // done
       
   373     return $plugin_list;
       
   374   }
       
   375   
       
   376   /**
       
   377    * Installs a plugin.
       
   378    * @param string Filename of plugin.
       
   379    * @param array The list of plugins as output by pluginLoader::get_plugin_list(). If not passed, the function is called, possibly wasting time.
       
   380    * @return array JSON-formatted but not encoded response
       
   381    */
       
   382   
       
   383   function install_plugin($filename, $plugin_list = null)
       
   384   {
       
   385     global $db, $session, $paths, $template, $plugins; // Common objects
       
   386     global $lang;
       
   387     
       
   388     if ( !$plugin_list )
       
   389       $plugin_list = $this->get_plugin_list();
       
   390     
       
   391     // we're gonna need this
       
   392     require_once ( ENANO_ROOT . '/includes/sql_parse.php' );
       
   393     
       
   394     switch ( true ): case true:
       
   395       
       
   396     // is the plugin in the directory and awaiting installation?
       
   397     if ( !isset($plugin_list[$filename]) || (
       
   398         isset($plugin_list[$filename]) && $plugin_list[$filename]['installed']
       
   399       ))
       
   400     {
       
   401       $return = array(
       
   402         'mode' => 'error',
       
   403         'error' => 'Invalid plugin specified.',
       
   404         'debug' => $filename
       
   405       );
       
   406       break;
       
   407     }
       
   408     
       
   409     $dataset =& $plugin_list[$filename];
       
   410     
       
   411     // load up the installer schema
       
   412     $schema = $this->parse_plugin_blocks( ENANO_ROOT . '/plugins/' . $filename, 'install' );
       
   413     
       
   414     $sql = array();
       
   415     if ( !empty($schema) )
       
   416     {
       
   417       // parse SQL
       
   418       $parser = new SQL_Parser($schema[0]['value'], true);
       
   419       $parser->assign_vars(array(
       
   420         'TABLE_PREFIX' => table_prefix
       
   421         ));
       
   422       $sql = $parser->parse();
       
   423     }
       
   424     
       
   425     // schema is final, check queries
       
   426     foreach ( $sql as $query )
       
   427     {
       
   428       if ( !$db->check_query($query) )
       
   429       {
       
   430         // aww crap, a query is bad
       
   431         $return = array(
       
   432           'mode' => 'error',
       
   433           'error' => $lang->get('acppm_err_upgrade_bad_query'),
       
   434         );
       
   435         break 2;
       
   436       }
       
   437     }
       
   438     
       
   439     // this is it, perform installation
       
   440     foreach ( $sql as $query )
       
   441     {
       
   442       if ( substr($query, 0, 1) == '@' )
       
   443       {
       
   444         $query = substr($query, 1);
       
   445         $db->sql_query($query);
       
   446       }
       
   447       else
       
   448       {
       
   449         if ( !$db->sql_query($query) )
       
   450           $db->die_json();
       
   451       }
       
   452     }
       
   453     
       
   454     // register plugin
       
   455     $version_db = $db->escape($dataset['version']);
       
   456     $filename_db = $db->escape($filename);
       
   457     $flags = PLUGIN_INSTALLED;
       
   458     
       
   459     $q = $db->sql_query('INSERT INTO ' . table_prefix . "plugins ( plugin_version, plugin_filename, plugin_flags )\n"
       
   460                       . "  VALUES ( '$version_db', '$filename_db', $flags );");
       
   461     if ( !$q )
       
   462       $db->die_json();
       
   463     
       
   464     $return = array(
       
   465       'success' => true
       
   466     );
       
   467     
       
   468     endswitch;
       
   469     
       
   470     return $return;
       
   471   }
       
   472   
       
   473   /**
       
   474    * Uninstalls a plugin, removing it completely from the database and calling any custom uninstallation code the plugin specifies.
       
   475    * @param string Filename of plugin.
       
   476    * @param array The list of plugins as output by pluginLoader::get_plugin_list(). If not passed, the function is called, possibly wasting time.
       
   477    * @return array JSON-formatted but not encoded response
       
   478    */
       
   479   
       
   480   function uninstall_plugin($filename, $plugin_list = null)
       
   481   {
       
   482     global $db, $session, $paths, $template, $plugins; // Common objects
       
   483     global $lang;
       
   484     
       
   485     if ( !$plugin_list )
       
   486       $plugin_list = $this->get_plugin_list();
       
   487     
       
   488     // we're gonna need this
       
   489     require_once ( ENANO_ROOT . '/includes/sql_parse.php' );
       
   490     
       
   491     switch ( true ): case true:
       
   492     
       
   493     // is the plugin in the directory and already installed?
       
   494     if ( !isset($plugin_list[$filename]) || (
       
   495         isset($plugin_list[$filename]) && !$plugin_list[$filename]['installed']
       
   496       ))
       
   497     {
       
   498       $return = array(
       
   499         'mode' => 'error',
       
   500         'error' => 'Invalid plugin specified.',
       
   501       );
       
   502       break;
       
   503     }
       
   504     // get plugin id
       
   505     $dataset =& $plugin_list[$filename];
       
   506     if ( empty($dataset['plugin id']) )
       
   507     {
       
   508       $return = array(
       
   509         'mode' => 'error',
       
   510         'error' => 'Couldn\'t retrieve plugin ID.',
       
   511       );
       
   512       break;
       
   513     }
       
   514     
       
   515     // load up the installer schema
       
   516     $schema = $this->parse_plugin_blocks( ENANO_ROOT . '/plugins/' . $filename, 'uninstall' );
       
   517     
       
   518     $sql = array();
       
   519     if ( !empty($schema) )
       
   520     {
       
   521       // parse SQL
       
   522       $parser = new SQL_Parser($schema[0]['value'], true);
       
   523       $parser->assign_vars(array(
       
   524         'TABLE_PREFIX' => table_prefix
       
   525         ));
       
   526       $sql = $parser->parse();
       
   527     }
       
   528     
       
   529     // schema is final, check queries
       
   530     foreach ( $sql as $query )
       
   531     {
       
   532       if ( !$db->check_query($query) )
       
   533       {
       
   534         // aww crap, a query is bad
       
   535         $return = array(
       
   536           'mode' => 'error',
       
   537           'error' => $lang->get('acppm_err_upgrade_bad_query'),
       
   538         );
       
   539         break 2;
       
   540       }
       
   541     }
       
   542     
       
   543     // this is it, perform uninstallation
       
   544     foreach ( $sql as $query )
       
   545     {
       
   546       if ( substr($query, 0, 1) == '@' )
       
   547       {
       
   548         $query = substr($query, 1);
       
   549         $db->sql_query($query);
       
   550       }
       
   551       else
       
   552       {
       
   553         if ( !$db->sql_query($query) )
       
   554           $db->die_json();
       
   555       }
       
   556     }
       
   557     
       
   558     // deregister plugin
       
   559     $q = $db->sql_query('DELETE FROM ' . table_prefix . "plugins WHERE plugin_id = {$dataset['plugin id']};");
       
   560     if ( !$q )
       
   561       $db->die_json();
       
   562     
       
   563     $return = array(
       
   564       'success' => true
       
   565     );
       
   566     
       
   567     endswitch;
       
   568     
       
   569     return $return;
       
   570   }
       
   571   
       
   572   /**
       
   573    * Very intelligently upgrades a plugin to the version specified in the filesystem.
       
   574    * @param string Filename of plugin.
       
   575    * @param array The list of plugins as output by pluginLoader::get_plugin_list(). If not passed, the function is called, possibly wasting time.
       
   576    * @return array JSON-formatted but not encoded response
       
   577    */
       
   578   
       
   579   function upgrade_plugin($filename, $plugin_list = null)
       
   580   {
       
   581     global $db, $session, $paths, $template, $plugins; // Common objects
       
   582     global $lang;
       
   583     
       
   584     if ( !$plugin_list )
       
   585       $plugin_list = $this->get_plugin_list();
       
   586     
       
   587     // we're gonna need this
       
   588     require_once ( ENANO_ROOT . '/includes/sql_parse.php' );
       
   589     
       
   590     switch ( true ): case true:
       
   591     
       
   592     // is the plugin in the directory and already installed?
       
   593     if ( !isset($plugin_list[$filename]) || (
       
   594         isset($plugin_list[$filename]) && !$plugin_list[$filename]['installed']
       
   595       ))
       
   596     {
       
   597       $return = array(
       
   598         'mode' => 'error',
       
   599         'error' => 'Invalid plugin specified.',
       
   600       );
       
   601       break;
       
   602     }
       
   603     // get plugin id
       
   604     $dataset =& $plugin_list[$filename];
       
   605     if ( empty($dataset['plugin id']) )
       
   606     {
       
   607       $return = array(
       
   608         'mode' => 'error',
       
   609         'error' => 'Couldn\'t retrieve plugin ID.',
       
   610       );
       
   611       break;
       
   612     }
       
   613     
       
   614     //
       
   615     // Here we go with the main upgrade process. This is the same logic that the
       
   616     // Enano official upgrader uses, in fact it's the same SQL parser. We need
       
   617     // list of all versions of the plugin to continue, though.
       
   618     //
       
   619     
       
   620     if ( !isset($dataset['version list']) || ( isset($dataset['version list']) && !is_array($dataset['version list']) ) )
       
   621     {
       
   622       // no version list - update the version number but leave the rest alone
       
   623       $version = $db->escape($dataset['version']);
       
   624       $q = $db->sql_query('UPDATE ' . table_prefix . "plugins SET plugin_version = '$version' WHERE plugin_id = {$dataset['plugin id']};");
       
   625       if ( !$q )
       
   626         $db->die_json();
       
   627       
       
   628       // send an error and notify the user even though it was technically a success
       
   629       $return = array(
       
   630         'mode' => 'error',
       
   631         'error' => $lang->get('acppm_err_upgrade_not_supported'),
       
   632       );
       
   633       break;
       
   634     }
       
   635     
       
   636     // build target list
       
   637     $versions  = $dataset['version list'];
       
   638     $indices   = array_flip($versions);
       
   639     $installed = $dataset['version installed'];
       
   640     
       
   641     // is the current version upgradeable?
       
   642     if ( !isset($indices[$installed]) )
       
   643     {
       
   644       $return = array(
       
   645         'mode' => 'error',
       
   646         'error' => $lang->get('acppm_err_upgrade_bad_version'),
       
   647       );
       
   648       break;
       
   649     }
       
   650     
       
   651     // does the plugin support upgrading to its own version?
       
   652     if ( !isset($indices[$installed]) )
       
   653     {
       
   654       $return = array(
       
   655         'mode' => 'error',
       
   656         'error' => $lang->get('acppm_err_upgrade_bad_target_version'),
       
   657       );
       
   658       break;
       
   659     }
       
   660     
       
   661     // list out which versions to do
       
   662     $index_start = @$indices[$installed] + 1;
       
   663     $index_stop  = @$indices[$dataset['version']];
       
   664     
       
   665     // Are we trying to go backwards?
       
   666     if ( $index_stop <= $index_start )
       
   667     {
       
   668       $return = array(
       
   669         'mode' => 'error',
       
   670         'error' => $lang->get('acppm_err_upgrade_to_older'),
       
   671       );
       
   672       break;
       
   673     }
       
   674     
       
   675     // build the list of version sets
       
   676     $ver_previous = $installed;
       
   677     $targets = array();
       
   678     for ( $i = $index_start; $i <= $index_stop; $i++ )
       
   679     {
       
   680       $targets[] = array($ver_previous, $versions[$i]);
       
   681       $ver_previous = $versions[$i];
       
   682     }
       
   683     
       
   684     // parse out upgrade sections in plugin file
       
   685     $plugin_blocks = $this->parse_plugin_blocks( ENANO_ROOT . '/plugins/' . $filename, 'upgrade' );
       
   686     $sql_blocks = array();
       
   687     foreach ( $plugin_blocks as $block )
       
   688     {
       
   689       if ( !isset($block['from']) || !isset($block['to']) )
       
   690       {
       
   691         continue;
       
   692       }
       
   693       $key = "{$block['from']} TO {$block['to']}";
       
   694       $sql_blocks[$key] = $block['value'];
       
   695     }
       
   696     
       
   697     // do version list check
       
   698     // for now we won't fret if a specific version set isn't found, we'll just
       
   699     // not do that version and assume there were no DB changes.
       
   700     foreach ( $targets as $i => $target )
       
   701     {
       
   702       list($from, $to) = $target;
       
   703       $key = "$from TO $to";
       
   704       if ( !isset($sql_blocks[$key]) )
       
   705       {
       
   706         unset($targets[$i]);
       
   707       }
       
   708     }
       
   709     $targets = array_values($targets);
       
   710     
       
   711     // parse and finalize schema
       
   712     $schema = array();
       
   713     foreach ( $targets as $i => $target )
       
   714     {
       
   715       list($from, $to) = $target;
       
   716       $key = "$from TO $to";
       
   717       try
       
   718       {
       
   719         $parser = new SQL_Parser($sql_blocks[$key], true);
       
   720       }
       
   721       catch ( Exception $e )
       
   722       {
       
   723         $return = array(
       
   724           'mode' => 'error',
       
   725           'error' => 'SQL parser init exception',
       
   726           'debug' => "$e"
       
   727         );
       
   728         break 2;
       
   729       }
       
   730       $parser->assign_vars(array(
       
   731         'TABLE_PREFIX' => table_prefix
       
   732         ));
       
   733       $parsed = $parser->parse();
       
   734       foreach ( $parsed as $query )
       
   735       {
       
   736         $schema[] = $query;
       
   737       }
       
   738     }
       
   739     
       
   740     // schema is final, check queries
       
   741     foreach ( $schema as $query )
       
   742     {
       
   743       if ( !$db->check_query($query) )
       
   744       {
       
   745         // aww crap, a query is bad
       
   746         $return = array(
       
   747           'mode' => 'error',
       
   748           'error' => $lang->get('acppm_err_upgrade_bad_query'),
       
   749         );
       
   750         break 2;
       
   751       }
       
   752     }
       
   753     
       
   754     // this is it, perform upgrade
       
   755     foreach ( $schema as $query )
       
   756     {
       
   757       if ( substr($query, 0, 1) == '@' )
       
   758       {
       
   759         $query = substr($query, 1);
       
   760         $db->sql_query($query);
       
   761       }
       
   762       else
       
   763       {
       
   764         if ( !$db->sql_query($query) )
       
   765           $db->die_json();
       
   766       }
       
   767     }
       
   768     
       
   769     // update version number
       
   770     $version = $db->escape($dataset['version']);
       
   771     $q = $db->sql_query('UPDATE ' . table_prefix . "plugins SET plugin_version = '$version' WHERE plugin_id = {$dataset['plugin id']};");
       
   772     if ( !$q )
       
   773       $db->die_json();
       
   774     
       
   775     // all done :-)
       
   776     $return = array(
       
   777       'success' => true
       
   778     );
       
   779     
       
   780     endswitch;
       
   781     
       
   782     return $return;
       
   783   }
   259 }
   784 }
   260 
   785 
   261 ?>
   786 ?>