PageRenderTime 56ms CodeModel.GetById 23ms RepoModel.GetById 1ms app.codeStats 0ms

/mem_plugin_updater/mem_plugin_updater.php

https://bitbucket.org/Manfre/txp-plugins
PHP | 1064 lines | 804 code | 222 blank | 38 comment | 103 complexity | 64b606fd281e0b9f72f3bf3625edbf0d MD5 | raw file
  1. <?php
  2. // This is a PLUGIN TEMPLATE.
  3. // Copy this file to a new name like abc_myplugin.php. Edit the code, then
  4. // run this file at the command line to produce a plugin for distribution:
  5. // $ php abc_myplugin.php > abc_myplugin-0.1.txt
  6. // Plugin name is optional. If unset, it will be extracted from the current
  7. // file name. Uncomment and edit this line to override:
  8. $plugin['name'] = 'mem_plugin_updater';
  9. // 0 = Plugin help is in Textile format, no raw HTML allowed (default).
  10. // 1 = Plugin help is in raw HTML. Not recommended.
  11. # $plugin['allow_html_help'] = 1;
  12. $plugin['version'] = '0.1';
  13. $plugin['author'] = 'Michael Manfre';
  14. $plugin['author_uri'] = 'http://manfre.net/';
  15. $plugin['description'] = 'Plugin Update RPC Server';
  16. // Plugin types:
  17. // 0 = regular plugin; loaded on the public web side only
  18. // 1 = admin plugin; loaded on both the public and admin side
  19. // 2 = library; loaded only when include_plugin() or require_plugin() is called
  20. $plugin['type'] = 1;
  21. if (!defined('txpinterface'))
  22. @include_once('../zem_tpl.php');
  23. if (0) {
  24. ?>
  25. # --- BEGIN PLUGIN HELP ---
  26. h1(title). Plugin Repository Client and Server
  27. h2(section). Summary
  28. p. This plugin is both a Plugin Repository Server and Client. The Plugin Repository Server allows a Textpattern site to maintain a collection of plugins that other Textpattern servers can query against. The Client allows a Textpattern site admin to quickly check for a new version of a plugin, or an entirely new plugin, and then install it.
  29. p. This plugin is MLP compatible.
  30. h2(section). Author Contact
  31. "Michael Manfre":mailto:mmanfre@gmail.com?subject=Textpattern%20Plugin%20mem_plugin_updater
  32. "http://manfre.net":http://manfre.net
  33. h2(section license). License
  34. p. This plugin is licensed under the "GPLv2":http://www.fsf.org/licensing/licenses/info/GPLv2.html.
  35. h2(section). Installation steps
  36. h3. Client
  37. p. To install the client, "click here":./index.php?event=mem_plugin_updater&step=client_install and then modify the repository URI through the Textpattern advanced preferenced.
  38. h3. Server
  39. p. To install the server, "click here":./index.php?event=mem_plugin_updater&step=server_install and then enable the server through the Textpattern advanced preferences.
  40. h2(section). Uninstallation steps
  41. h3. Client
  42. p. To remove all client preferences, "click here":./index.php?event=mem_plugin_updater&step=uninstall_client
  43. h3. Server
  44. p. To remove all server preferences, "click here":./index.php?event=mem_plugin_updater&step=uninstall_server
  45. p. The server installation created a table {prefix}mem_plugin_repo. If you wish to remove this table, you must do so manually.
  46. h2(section). Tags
  47. h3(tag#mem_repo_plugin). mem_repo_plugin
  48. p(tag-summary). This tag will allow the contents of the repository to be shown to a public user. The tag outputs nothing by itself, but is used in conjunction with %(tag-name)mem_repo%.
  49. *(atts) %(atts-name)name% %(atts-type)mixed% Either the plugin ID (locally unique to a site) or the plugin name.
  50. * %(atts-name)form% %(atts-type)string% Name of a form that will be parsed. If set, the text enclosed by this tag will be ignored.
  51. * %(atts-name)wraptag% %(atts-type)string% The name of an HTML tag to wrap around the output of this plugin.
  52. * %(atts-name)class% %(atts-type)string% The CSS class name to apply to %(atts-name)wraptag%.
  53. * %(atts-name)wrapid% %(atts-type)string% The HTML tag id to apply to the %(atts-name)wraptag%.
  54. * %(atts-name)show_help% %(atts-type)int% Set to 1 if you would like to fetch and output the plugin help.
  55. * %(atts-name)show_code% %(atts-type)int% Set to 1 if you would like to fetch and output the plugin code.
  56. h3(tag#mem_repo). mem_repo
  57. p(tag-summary). This tag must be used in the form referenced by %(tag-name)mem_repo_plugin%. It is responsible for outputting the results.
  58. *(atts) %(atts-name)name% %(atts-type)string% The name of the plugin field to output. Valid values are name, description, version, type, author, author_uri, plugin, plugin_md5, help.
  59. * %(atts-name)wraptag% %(atts-type)string% The name of an HTML tag to wrap around the output of this plugin.
  60. * %(atts-name)class% %(atts-type)string% The CSS class name to apply to %(atts-name)wraptag%.
  61. * %(atts-name)wrapid% %(atts-type)string% The HTML tag id to apply to the %(atts-name)wraptag%.
  62. h2(section). Admin page help
  63. p. Pending...
  64. # --- END PLUGIN HELP ---
  65. <?php
  66. }
  67. # --- BEGIN PLUGIN CODE ---
  68. define('MEM_PLUGIN_XMLRPC_PATH', 'memxmlrpc');
  69. define('MEM_PLUGIN_XMLRPC_HOST', 'manfre.net');
  70. define('MEM_PLUGIN_XMLRPC_PORT', 80);
  71. global $mem_plugin_lang, $prefs, $event;
  72. if (!is_array($mem_plugin_lang))
  73. {
  74. $mem_plugin_lang = array(
  75. 'bad_plugin_code' => 'Plugin code has an invalid format.',
  76. 'check_version' => 'Check Version',
  77. 'db_create_fail' => 'Failed to create DB table {table}.',
  78. 'db_create_success' => 'Created DB table {table}.',
  79. 'db_table_exists' => 'Table {table} already exists.',
  80. 'install_client' => 'mem_plugin_updater Client Install',
  81. 'install_server' => 'mem_plugin_updater Server Install',
  82. 'install_update' => 'Install update',
  83. 'new_version' => 'A newer version of plugin {name} v{old_version} was detected on the repository server. New Version is v{new_version}.',
  84. 'no_plugin_specified' => 'No plugin specified.',
  85. 'no_plugin_help' => 'The plugin "{name}" does not contain any help documentation.',
  86. 'plugin_conflict' => 'The plugin {name} already exists.',
  87. 'plugin_details' => 'Plugin Details',
  88. 'plugin_installed' => 'Plugin {name} v{version} has been installed.',
  89. 'plugin_install_failed' => 'Plugin {name} v{version} failed to install.',
  90. 'plugin_name_label' => 'Plugin Name:',
  91. 'plugin_repo' => 'Plugin Repository',
  92. 'plugin_updater' => 'Plugin Updater',
  93. 'plugin_upload_success' => 'Plugin {name} was uploaded.',
  94. 'plugin_upload_fail' => 'Plugin {name} failed to uploaded.',
  95. 'pref_exists' => 'The preference "{pref}" already exists with value "{val}"',
  96. 'replace_plugin' => 'The plugin {name} v{old_version} already exists. Continuing will replace the plugin with the version {new_version}.',
  97. 'rpc_error' => 'RPC error ({code}) {msg}',
  98. 'set_pref_fail' => 'Failed to set preference "{pref}".',
  99. 'set_pref_success' => 'Set preference "{pref}" to "{val}".',
  100. 'up_to_date' => 'The plugin {name} v{version} is up to date.',
  101. 'upload_plugin' => 'Upload Plugin:',
  102. 'upload_new_plugin' => 'Submit this form if you would like to add the plugin {name} (version {version}) to the repository.',
  103. 'upload_plugin_verify' => 'Verify Plugin Upload',
  104. );
  105. }
  106. register_callback( 'mem_plugin_updater_enumerate_strings' , 'l10n.enumerate_strings' );
  107. function mem_plugin_updater_enumerate_strings($event, $step='', $pre=0) {
  108. global $mem_plugin_lang;
  109. $r = array (
  110. 'owner' => 'mem_plugin_updater', # Change to your plugin's name
  111. 'prefix' => 'mem_plugin_updater', # Its unique string prefix
  112. 'lang' => 'en-gb', # The language of the initial strings.
  113. 'event' => 'common', # public/admin/common = which interface the strings will be loaded into
  114. 'strings' => $mem_plugin_lang, # The strings themselves.
  115. );
  116. return $r;
  117. }
  118. function mem_plugin_gTxt($what,$args = array())
  119. {
  120. global $mem_plugin_lang, $textarray;
  121. $key = strtolower( 'mem_plugin_updater' . '-' . $what );
  122. if (isset($textarray[$key]))
  123. $str = $textarray[$key];
  124. else
  125. {
  126. $key = strtolower($what);
  127. if (isset($mem_plugin_lang[$key]))
  128. $str = $mem_plugin_lang[$key];
  129. else
  130. $str = $what;
  131. }
  132. if( !empty($args) )
  133. $str = strtr( $str , $args );
  134. return $str;
  135. }
  136. if (txpinterface == 'public') {
  137. if (isset($prefs['mem_plugin_repo_enabled']) and $prefs['mem_plugin_repo_enabled'] == '1')
  138. register_callback('mem_plugin_updater', 'pretext');
  139. }
  140. else {
  141. register_tab('admin', 'mem_plugin_updater', mem_plugin_gTxt('plugin_updater'));
  142. register_callback('mem_plugin_updater', 'mem_plugin_updater');
  143. if (isset($prefs['mem_plugin_repo_enabled']) and $prefs['mem_plugin_repo_enabled'] == '1')
  144. {
  145. register_tab('admin', 'mem_plugin_repo', mem_plugin_gTxt('plugin_repo'));
  146. register_callback('mem_plugin_updater', 'mem_plugin_repo');
  147. }
  148. if ($event == 'mem_plugin_updater') {
  149. include_once txpath.'/include/txp_plugin.php';
  150. }
  151. if ($event == 'mem_plugin_updater' || $event == 'mem_plugin_repo') {
  152. include_once txpath.'/publish/taghandlers.php';
  153. require_once txpath.'/lib/IXRClass.php';
  154. }
  155. }
  156. if (txpinterface == 'public')
  157. {
  158. require_once txpath.'/lib/IXRClass.php';
  159. class mem_plugin_Server extends IXR_Server {
  160. function mem_plugin_Server() {
  161. $this->IXR_Server(array(
  162. 'mem_plugin.check_version' => 'this:check_version',
  163. 'mem_plugin.get_plugin' => 'this:get_plugin',
  164. 'mem_plugin.get_plugin_details' => 'this:get_plugin_details',
  165. ));
  166. }
  167. function check_version($args)
  168. {
  169. if (!is_string($args))
  170. return new IXR_Error(-34000, 'Invalid argument in function check_version');
  171. $plugin_name = doSlash($args);
  172. $version = safe_field('version', 'mem_plugin_repo', "name = '$plugin_name'");
  173. if ($version)
  174. return array('plugin_name'=>$args, 'plugin_version'=> $version);
  175. return new IXR_Error(-34001, 'Plugin not found');
  176. }
  177. // Returns the encoded plugin
  178. function get_plugin($args)
  179. {
  180. if (!is_string($args))
  181. return new IXR_Error(-34000, 'Invalid argument in function get_plugin');
  182. $rs = safe_row('plugin, version', 'mem_plugin_repo', "name = '".doSlash($args)."'");
  183. if (!$rs)
  184. return new IXR_Error(-34001, 'Plugin not found');
  185. return array(
  186. 'plugin_name' => $args,
  187. 'plugin_version'=> $rs['version'],
  188. 'plugin_file' => $rs['plugin']
  189. );
  190. }
  191. function get_plugin_details($args)
  192. {
  193. if (!is_string($args))
  194. return new IXR_Error(-34000, 'Invalid argument in function get_plugin');
  195. $rs = safe_row('type, version, description, author, author_uri, plugin_md5', 'mem_plugin_repo', "name = '".doSlash($args)."'");
  196. if (!$rs)
  197. return new IXR_Error(-34001, 'Plugin not found');
  198. return array(
  199. 'plugin_name' => $args,
  200. 'plugin_type' => $rs['type'],
  201. 'plugin_version'=> $rs['version'],
  202. 'plugin_author'=> $rs['author'],
  203. 'plugin_author_uri'=> $rs['author_uri'],
  204. 'plugin_md5'=> $rs['plugin_md5'],
  205. 'plugin_description'=> $rs['description'],
  206. );
  207. }
  208. }
  209. }
  210. function mem_plugin_updater_client_install()
  211. {
  212. global $prefs;
  213. $log = array();
  214. $pref_name = 'mem_plugin_updater_url';
  215. if (!isset($prefs[$pref_name]))
  216. {
  217. $val = 'http://manfre.net/'.MEM_PLUGIN_XMLRPC_PATH.'/';
  218. $r = set_pref($pref_name, $val, 'mem_plugin_updater', 1);
  219. $prefs[$pref_name] = $val;
  220. if ($r !== false)
  221. $log[] = mem_plugin_gTxt('set_pref_success', array('{pref}' => $pref_name, '{val}'=> $val));
  222. else
  223. $log[] = mem_plugin_gTxt('set_pref_fail', array('{pref}' => $pref_name));
  224. }
  225. else
  226. $log[] = mem_plugin_gTxt('pref_exists', array('{pref}' => $pref_name, '{val}'=> $prefs[$pref_name]));
  227. return $log;
  228. }
  229. function mem_plugin_updater_server_install()
  230. {
  231. global $prefs;
  232. $log = array();
  233. $pref_name = 'mem_plugin_repo_enabled';
  234. if (!isset($prefs[$pref_name]))
  235. {
  236. $val = '0';
  237. $r = set_pref($pref_name, $val, 'mem_plugin_updater', 1, 'yesnoradio');
  238. if ($r !== false)
  239. $log[] = mem_plugin_gTxt('set_pref_success', array('{pref}' => $pref_name, '{val}'=> $val));
  240. else
  241. $log[] = mem_plugin_gTxt('set_pref_fail', array('{pref}' => $pref_name));
  242. $prefs[$pref_name] = $val == '1';
  243. }
  244. else
  245. $log[] = mem_plugin_gTxt('pref_exists', array('{pref}' => $pref_name, '{val}'=> $prefs[$pref_name]));
  246. $table_prefix = PFX;
  247. ob_start();
  248. $rs = safe_row("id", "mem_plugin_repo", "1=1 LIMIT 1");
  249. ob_end_flush();
  250. $table_name = PFX.'mem_plugin_repo';
  251. if (!$rs && mysql_errno() != 0)
  252. {
  253. $table_sql = <<<EOF
  254. CREATE TABLE `{$table_name}` (
  255. `id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY ,
  256. `name` VARCHAR( 64 ) NOT NULL ,
  257. `description` VARCHAR( 255 ) NOT NULL,
  258. `version` VARCHAR( 10 ) NOT NULL ,
  259. `type` INT( 2 ) NOT NULL ,
  260. `author` VARCHAR( 128 ) NOT NULL ,
  261. `author_uri` VARCHAR( 128 ) NOT NULL ,
  262. `plugin` TEXT NOT NULL ,
  263. `plugin_md5` VARCHAR( 32 ) NOT NULL ,
  264. `help` TEXT NOT NULL ,
  265. INDEX ( `name` )
  266. ) ENGINE = MYISAM ;
  267. EOF;
  268. $rs = safe_query($table_sql);
  269. if ($rs)
  270. $log[] = mem_plugin_gTxt('db_create_success', array('{table}'=> $table_name));
  271. else
  272. // failed to create table
  273. $log[] = mem_plugin_gTxt('db_create_fail', array('{table}'=> $table_name));
  274. }
  275. else
  276. $log[] = mem_plugin_gTxt('db_table_exists', array('{table}' => $table_name));
  277. return $log;
  278. }
  279. // -------------------------------------------------------------
  280. function mem_plugin_form($event='mem_plugin_repo')
  281. {
  282. return n.n.form(
  283. graf(
  284. tag(mem_plugin_gTxt('upload_plugin'), 'span', ' style="vertical-align: 10px;"').sp.
  285. '<textarea name="plugin" cols="1" rows="1" style="width:40px; height: 20px;"></textarea>'.sp.
  286. tag(
  287. fInput('submit', 'upload_new', gTxt('upload'), 'smallerbox')
  288. , 'span', ' style="vertical-align: 10px;"').
  289. eInput($event).
  290. sInput('plugin_verify')
  291. )
  292. , 'text-align: center;');
  293. }
  294. function mem_plugin64_to_array($plugin64)
  295. {
  296. $plugin = base64_decode($plugin64);
  297. if (strncmp($plugin, "\x1F\x8B", 2) === 0)
  298. {
  299. if (function_exists('gzinflate'))
  300. $plugin = gzinflate(substr($plugin, 10));
  301. else
  302. return false;
  303. }
  304. $plugin = @unserialize($plugin);
  305. if (is_array($plugin))
  306. return $plugin;
  307. return false;
  308. }
  309. function mem_plugin_verify()
  310. {
  311. // make sure the plugin is valid and prompt for conflicts/updates
  312. $plugin = ps('plugin');
  313. $plugin = preg_replace('@.*\$plugin=\'([\w=+/]+)\'.*@s', '$1', $plugin);
  314. $plugin = preg_replace('/^#.*$/m', '', $plugin);
  315. if(isset($plugin)) {
  316. $plugin_encoded = $plugin;
  317. $plugin = mem_plugin64_to_array($plugin_encoded);
  318. if ($plugin)
  319. {
  320. if(is_array($plugin)){
  321. extract($plugin);
  322. $old_version = safe_field('version', 'mem_plugin_repo', "name = '{$plugin['name']}'");
  323. $txt = '';
  324. if ($old_version)
  325. $txt = tag(mem_plugin_gTxt('replace_plugin', array('{name}'=> $name, '{old_version}'=> $old_version, '{new_version}'=> $version)), 'div');
  326. else
  327. $txt = tag(mem_plugin_gTxt('upload_new_plugin', array('{name}'=> $name, '{version}'=> $version)), 'div');
  328. $out =
  329. form(
  330. hed(mem_plugin_gTxt('upload_plugin_verify'),3).
  331. $txt.
  332. fInput('submit','', mem_plugin_gTxt('submit'),'publish').
  333. hInput('replace_version', $old_version).
  334. eInput('mem_plugin_repo').
  335. sInput('plugin_upload').
  336. hInput('plugin64', $plugin_encoded)
  337. , 'margin: 0 autio; width: 65%;');
  338. return $out;
  339. }
  340. }
  341. }
  342. }
  343. function mem_plugin_upload()
  344. {
  345. extract(gpsa(array('plugin64','replace_version')));
  346. $plugin = mem_plugin64_to_array($plugin64);
  347. if ($plugin)
  348. {
  349. extract($plugin);
  350. if ($replace_version)
  351. {
  352. $rs = safe_update("mem_plugin_repo",
  353. "name = '".doSlash($name)."',
  354. description = '".doSlash($description)."',
  355. version = '".doSlash($version)."',
  356. type = ".doSlash($type).",
  357. author = '".doSlash($author)."',
  358. author_uri = '".doSlash($author_uri)."',
  359. plugin = '".doSlash($plugin64)."',
  360. plugin_md5 = '".doSlash($md5)."',
  361. help = '".doSlash($help)."'"
  362. , "name = '".doSlash($name)."' and version = '".doSlash($replace_version)."'");
  363. }
  364. else
  365. {
  366. $rs = safe_insert("mem_plugin_repo",
  367. "name = '".doSlash($name)."',
  368. description = '".doSlash($description)."',
  369. version = '".doSlash($version)."',
  370. type = ".doSlash($type).",
  371. author = '".doSlash($author)."',
  372. author_uri = '".doSlash($author_uri)."',
  373. plugin = '".doSlash($plugin64)."',
  374. plugin_md5 = '".doSlash($md5)."',
  375. help = '".doSlash($help)."'"
  376. );
  377. }
  378. if ($rs)
  379. $message = mem_plugin_gTxt('plugin_upload_success', array('{name}'=> $name));
  380. else
  381. $message = mem_plugin_gTxt('plugin_upload_fail', array('{name}'=> $name));
  382. pagetop(mem_plugin_gTxt('plugin_updater'), $message);
  383. echo mem_repo_admin_list();
  384. }
  385. // notify we handled output
  386. return false;
  387. }
  388. function mem_plugin_delete()
  389. {
  390. $name = doSlash(ps('name'));
  391. safe_delete('mem_plugin_repo', "name = '$name'");
  392. return;
  393. }
  394. function mem_plugin_help()
  395. {
  396. $name = gps('name');
  397. if (empty($name))
  398. return '';
  399. $help = safe_field('help','mem_plugin_repo',"name = '".doSlash($name)."'");
  400. if (empty($help))
  401. return '';
  402. return startTable('edit')
  403. . tr(tda($help,' width="600"'))
  404. . endTable();
  405. }
  406. function mem_plugin_list()
  407. {
  408. $out = n.n.startTable('list');
  409. $out .= tr(
  410. tda(
  411. form(
  412. tag(mem_plugin_gTxt('plugin_name_label'),'label').sp.
  413. fInput('text', 'plugin_name', '', 'edit', '', '', 22, '', '').sp.
  414. sInput('get_plugin_details').
  415. eInput('mem_plugin_updater').
  416. fInput('submit','',gTxt('details'),'publish')
  417. , 'margin: 0 auto; width: 65%;')
  418. ,' colspan="8" style="height: 30px; border: none;"')
  419. );
  420. $rs = safe_rows_start('name, status, author, author_uri, version, description, code_md5, type, md5(code) as md5, LENGTH(help) as help', 'txp_plugin', "1 order by name");
  421. if ($rs and numRows($rs) > 0)
  422. {
  423. $out .= assHead('plugin', 'author', 'version', 'plugin_modified', 'description', 'active', 'help', '', '');
  424. while ($a = nextRow($rs))
  425. {
  426. foreach ($a as $key => $value) {
  427. $$key = htmlspecialchars($value);
  428. }
  429. // Fix up the description for clean cases
  430. $description = preg_replace(array('#&lt;br /&gt;#',
  431. '#&lt;(/?(a|b|i|em|strong))&gt;#',
  432. '#&lt;a href=&quot;(https?|\.|\/|ftp)([A-Za-z0-9:/?.=_]+?)&quot;&gt;#'),
  433. array('<br />','<$1>','<a href="$1$2">'),
  434. $description);
  435. $help = !empty($help) ?
  436. '<a href="?event=plugin'.a.'step=plugin_help'.a.'name='.$name.'">'.gTxt('view').'</a>' :
  437. gTxt('none');
  438. // modified?
  439. $modified = (strtolower($md5) != strtolower($code_md5));
  440. $out .= tr(
  441. n.td($name).
  442. td(
  443. href($author, $author_uri)
  444. ).
  445. td($version, 10).
  446. td($modified ? gTxt('yes') : '').
  447. td($description, 260).
  448. td(
  449. status_link($status, $name, yes_no($status))
  450. ,30).
  451. td($help).
  452. td(
  453. eLink('plugin', 'plugin_edit', 'name', $name, gTxt('edit'))
  454. ).
  455. td(
  456. eLink('mem_plugin_updater', 'check_version', 'plugin_name', $name, mem_plugin_gTxt('check_version'))
  457. ).
  458. td(
  459. dLink('plugin', 'plugin_delete', 'name', $name)
  460. ,30)
  461. );
  462. unset($name, $page, $deletelink);
  463. }
  464. }
  465. $out .= endTable();
  466. return $out;
  467. }
  468. /////////////////////////////////////////
  469. // Repo Public Tags
  470. function mem_repo_plugin($atts, $thing='')
  471. {
  472. global $mem_repo_repo;
  473. extract(lAtts(array(
  474. 'form' => '',
  475. 'name' => '',
  476. 'show_help' => 0,
  477. 'show_code' => 0,
  478. 'wraptag' => '',
  479. 'class' => '',
  480. 'wrapid' => ''
  481. ),$atts));
  482. if (empty($name)) {
  483. trigger_error(mem_plugin_gTxt('tag_error', array('{tag}'=> 'mem_repo_plugin', '{atts}'=> 'name')),E_USER_WARNING);
  484. return;
  485. }
  486. $sql_fields = 'id, name, description, version, type, author, author_uri, plugin_md5';
  487. if ($show_help) $sql_fields .= ', help';
  488. if ($show_code) $sql_fields .= ', code';
  489. if (is_numeric($name))
  490. $sql_where = "`id` = ". doSlash($name);
  491. else
  492. $sql_where = "name = '". doSlash($name) ."'";
  493. $mem_repo_plugin = safe_row($sql_fields, 'mem_plugin_repo', $sql_where);
  494. $out = '';
  495. if ($mem_repo_plugin) {
  496. if (!empty($form))
  497. $thing = fetch_form($form);
  498. $out = parse($thing);
  499. unset($mem_repo_plugin);
  500. }
  501. return doTag($out, $wraptag, $class, '', $wrapid);
  502. }
  503. function mem_repo($atts, $thing='')
  504. {
  505. global $mem_plugin_repo;
  506. extract(lAtts(array(
  507. 'name' => 'name',
  508. 'wraptag' => '',
  509. 'class' => '',
  510. 'wrapid' => ''
  511. ),$atts));
  512. $out = '';
  513. if (is_array($mem_plugin_repo) and isset($mem_plugin_repo[$name]))
  514. $out = $mem_plugin_repo[$name];
  515. return doTag($out, $wraptag, $class, '', $wrapid);
  516. }
  517. /////////////////////////////////////////
  518. // Repo functions
  519. function mem_repo_admin_list()
  520. {
  521. $out = mem_plugin_form(). n.n.startTable('list');
  522. $rs = safe_rows_start('id, name, description, version, type, author, author_uri, LENGTH(help) as help', 'mem_plugin_repo', "1 order by name");
  523. if ($rs and numRows($rs) > 0)
  524. {
  525. $out .= assHead('plugin', 'author', 'version', 'type', 'description', 'help', '');
  526. while ($a = nextRow($rs))
  527. {
  528. foreach ($a as $key => $value) {
  529. $$key = htmlspecialchars($value);
  530. }
  531. // Fix up the description for clean cases
  532. $description = preg_replace(array('#&lt;br /&gt;#',
  533. '#&lt;(/?(a|b|i|em|strong))&gt;#',
  534. '#&lt;a href=&quot;(https?|\.|\/|ftp)([A-Za-z0-9:/?.=_]+?)&quot;&gt;#'),
  535. array('<br />','<$1>','<a href="$1$2">'),
  536. $description);
  537. $help = !empty($help) ?
  538. '<a href="?event=mem_plugin_repo'.a.'step=plugin_help'.a.'name='.$name.'">'.gTxt('view').'</a>' :
  539. gTxt('none');
  540. $out .= tr(
  541. n.td($name).
  542. td(
  543. href($author, $author_uri)
  544. ).
  545. td($version, 10).
  546. td($type).
  547. td($description, 260).
  548. td($help).
  549. td(
  550. dLink('mem_plugin_repo', 'plugin_delete', 'name', $name)
  551. ,30)
  552. );
  553. unset($name, $page, $deletelink);
  554. }
  555. }
  556. $out .= endTable();
  557. return $out;
  558. }
  559. function mem_plugin_install($plugin, $status=1)
  560. {
  561. $plugin = preg_replace('@.*\$plugin=\'([\w=+/]+)\'.*@s', '$1', $plugin);
  562. $plugin = preg_replace('/^#.*$/m', '', $plugin);
  563. if(trim($plugin)) {
  564. $plugin = mem_plugin64_to_array($plugin);
  565. if ($plugin)
  566. {
  567. extract($plugin);
  568. if (empty($type)) $type = 0;
  569. $type = assert_int($type);
  570. $exists = fetch('name','txp_plugin','name',$name);
  571. if (isset($help_raw) && empty($plugin['allow_html_help'])) {
  572. // default: help is in Textile format
  573. include_once txpath.'/lib/classTextile.php';
  574. $textile = new Textile();
  575. $help = $textile->TextileThis($help_raw, 0, 0, 1);
  576. }
  577. $code = doSlash($code);
  578. $status = doSlash($status);
  579. if ($exists) {
  580. // leave status unchanged on update
  581. $rs = safe_update(
  582. "txp_plugin",
  583. "status = $status,
  584. type = $type,
  585. author = '".doSlash($author)."',
  586. author_uri = '".doSlash($author_uri)."',
  587. version = '".doSlash($version)."',
  588. description = '".doSlash($description)."',
  589. help = '".doSlash($help)."',
  590. code = '".$code."',
  591. code_restore = '".$code."',
  592. code_md5 = '".doSlash($md5)."'",
  593. "name = '".doSlash($name)."'"
  594. );
  595. } else {
  596. $rs = safe_insert(
  597. "txp_plugin",
  598. "name = '".doSlash($name)."',
  599. status = $status,
  600. type = $type,
  601. author = '".doSlash($author)."',
  602. author_uri = '".doSlash($author_uri)."',
  603. version = '".doSlash($version)."',
  604. description = '".doSlash($description)."',
  605. help = '".doSlash($help)."',
  606. code = '".$code."',
  607. code_restore = '".$code."',
  608. code_md5 = '".doSlash($md5)."'"
  609. );
  610. }
  611. if ($rs and $code)
  612. {
  613. return mem_plugin_gTxt('plugin_installed', array('{name}' => escape_output($name), '{version}'=> escape_output($version)));
  614. }
  615. else
  616. {
  617. return mem_plugin_gTxt('plugin_install_failed', array('{name}' => escape_output($name), '{version}'=> escape_output($version)));
  618. }
  619. }
  620. else
  621. {
  622. return mem_plugin_gTxt('bad_plugin_code');
  623. }
  624. }
  625. else
  626. {
  627. return mem_plugin_gTxt('no_plugin_specified');
  628. }
  629. }
  630. function mem_plugin_updater($event, $step='')
  631. {
  632. global $prefs;
  633. $show_head = 1;
  634. $head_message = $out = '';
  635. if ($event == 'pretext')
  636. {
  637. while (@ob_end_clean());
  638. $request_uri = preg_replace("|^https?://[^/]+|i","",serverSet('REQUEST_URI'));
  639. // IIS fix
  640. if (!$request_uri and serverSet('SCRIPT_NAME'))
  641. $request_uri = serverSet('SCRIPT_NAME').( (serverSet('QUERY_STRING')) ? '?'.serverSet('QUERY_STRING') : '');
  642. // another IIS fix
  643. if (!$request_uri and serverSet('argv'))
  644. {
  645. $argv = serverSet('argv');
  646. $request_uri = @substr($argv[0], strpos($argv[0], ';') + 1);
  647. }
  648. // define the useable url, minus any subdirectories.
  649. // this is pretty fugly, if anyone wants to have a go at it - dean
  650. $subpath = preg_quote(preg_replace("/https?:\/\/.*(\/.*)/Ui","$1",hu),"/");
  651. $req = preg_replace("/^$subpath/i","/",$request_uri);
  652. extract(chopUrl($req));
  653. if ($u1 == MEM_PLUGIN_XMLRPC_PATH)
  654. {
  655. $mem_plugin_server = new mem_plugin_Server();
  656. exit();
  657. }
  658. }
  659. else if ($event == 'mem_plugin_updater')
  660. {
  661. if (empty($mem_plugin_updater_url))
  662. $mem_plugin_updater_url = 'http://'.MEM_PLUGIN_XMLRPC_HOST.':'.MEM_PLUGIN_XMLRPC_PORT.'/'.MEM_PLUGIN_XMLRPC_PATH;
  663. $client = new IXR_Client($mem_plugin_updater_url);
  664. //$client->debug = 1;
  665. $plugin_name = gps('plugin_name');
  666. switch($step) {
  667. case 'get_plugin_details':
  668. if (!$client->query('mem_plugin.get_plugin_details', $plugin_name)) {
  669. $out = mem_plugin_gTxt('rpc_error', array('{code}'=>$client->getErrorCode(), '{msg}'=>$client->getErrorMessage()));
  670. }
  671. else {
  672. $resp = $client->getResponse();
  673. extract($resp);
  674. $current_version = safe_field('version', 'txp_plugin', "name = '".doSlash($plugin_name)."'");
  675. $is_new = (version_compare($current_version, $plugin_version) < 0);
  676. // Fix up the description for clean cases
  677. $plugin_description = preg_replace(array('#&lt;br /&gt;#',
  678. '#&lt;(/?(a|b|i|em|strong))&gt;#',
  679. '#&lt;a href=&quot;(https?|\.|\/|ftp)([A-Za-z0-9:/?.=_]+?)&quot;&gt;#'),
  680. array('<br />','<$1>','<a href="$1$2">'),
  681. $plugin_description);
  682. $out = tag(
  683. n.n.startTable('edit').
  684. tr(
  685. tda(
  686. hed(mem_plugin_gTxt('plugin_details'), 3)
  687. , ' colspan="2"')
  688. ).
  689. tr(
  690. td(gTxt('name')).
  691. td($plugin_name)
  692. ).
  693. tr(
  694. td(gTxt('version')).
  695. td($plugin_version)
  696. ).
  697. tr(
  698. td(gTxt('md5')).
  699. td($plugin_md5)
  700. ).
  701. tr(
  702. td(gTxt('author')).
  703. td(href($plugin_author, $plugin_author_uri))
  704. ).
  705. tr(
  706. td(gTxt('description')).
  707. td($plugin_description, 300)
  708. ).
  709. tr(
  710. tda(
  711. ($is_new ?
  712. form(
  713. sInput('install_plugin').
  714. eInput('mem_plugin_updater').
  715. hInput('plugin_name', $plugin_name).
  716. fInput('submit','',gTxt('install'),'publish')
  717. , 'margin: 0 auto; width: 65%;')
  718. : '')
  719. , ' colspan="2"')
  720. ).
  721. n.n.endTable()
  722. , 'div');
  723. }
  724. break;
  725. case 'check_version':
  726. if (!$client->query('mem_plugin.check_version', $plugin_name)) {
  727. $out = mem_plugin_gTxt('rpc_error', array('{code}'=>$client->getErrorCode(), '{msg}'=>$client->getErrorMessage()));
  728. }
  729. else {
  730. $current_version = safe_field('version', 'txp_plugin', "name = '".doSlash($plugin_name)."'");
  731. $resp = $client->getResponse();
  732. if (is_array($resp))
  733. {
  734. extract($resp);
  735. if (version_compare($current_version, $plugin_version) >= 0)
  736. {
  737. $out = tag(
  738. hed(mem_plugin_gTxt('plugin_updater'), 3).
  739. tag(mem_plugin_gTxt('up_to_date', array('{name}'=> $plugin_name, '{version}'=> $current_version)), 'div')
  740. , 'div');
  741. }
  742. else
  743. {
  744. $out = tag(
  745. hed(mem_plugin_gTxt('plugin_updater'), 3).
  746. tag(mem_plugin_gTxt('new_version', array('{name}'=> $plugin_name, '{old_version}'=> $current_version, '{new_version}'=> $plugin_version)), 'div')
  747. , 'div').
  748. br.
  749. form(
  750. sInput('install_plugin').
  751. eInput('mem_plugin_updater').
  752. hInput('plugin_name', $plugin_name).
  753. fInput('submit','',gTxt('install'),'publish')
  754. , 'margin: 0 auto; width: 65%;');
  755. }
  756. }
  757. }
  758. break;
  759. case 'install_plugin':
  760. if (!$client->query('mem_plugin.get_plugin', $plugin_name))
  761. {
  762. $out = mem_plugin_gTxt('rpc_error', array('{code}'=>$client->getErrorCode(), '{msg}'=>$client->getErrorMessage()));
  763. }
  764. else
  765. {
  766. $resp = $client->getResponse();
  767. if (is_array($resp))
  768. {
  769. extract($resp);
  770. $head_message = mem_plugin_install($resp['plugin_file']);
  771. }
  772. }
  773. break;
  774. case 'install_client':
  775. case 'client_install':
  776. $log = mem_plugin_updater_client_install();
  777. break;
  778. case 'install_server':
  779. case 'server_install':
  780. $log = mem_plugin_updater_server_install();
  781. break;
  782. default:
  783. break;
  784. }
  785. if ($out !== false)
  786. {
  787. if ($show_head)
  788. pagetop(mem_plugin_gTxt('plugin_updater'), !empty($head_message) ? $head_message : '');
  789. if (isset($log))
  790. $out = hed(mem_plugin_gTxt($step),1) . doWrap($log, 'ul', '');
  791. if (!empty($out))
  792. echo $out;
  793. else
  794. echo mem_plugin_list();
  795. echo br;
  796. }
  797. }
  798. else if ($event == 'mem_plugin_repo')
  799. {
  800. $plugin_name = gps('plugin_name');
  801. $func = 'mem_'.$step;
  802. //if (function_exists($func)) $out = call_user_func($func);
  803. switch($step) {
  804. case 'plugin_upload':
  805. $out = mem_plugin_upload();
  806. break;
  807. case 'plugin_delete':
  808. $out = mem_plugin_delete();
  809. break;
  810. case 'plugin_verify':
  811. $out = mem_plugin_verify();
  812. break;
  813. case 'plugin_help':
  814. $out = mem_plugin_help();
  815. break;
  816. default:
  817. // force showing of repo list
  818. $out = '';
  819. break;
  820. }
  821. if ($out !== false)
  822. {
  823. if ($show_head)
  824. pagetop(mem_plugin_gTxt('plugin_repo'), !empty($head_message) ? $head_message : '');
  825. if (isset($log))
  826. $out = hed(mem_plugin_gTxt($step),1) . doWrap($log, 'ul', '');
  827. if (!empty($out))
  828. echo $out;
  829. else
  830. echo mem_repo_admin_list();
  831. }
  832. }
  833. else
  834. {
  835. echo "shouldn't be here";
  836. }
  837. }
  838. # --- END PLUGIN CODE ---
  839. ?>