PageRenderTime 35ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 1ms

/xmlrpc.php

https://gitlab.com/endomorphosis/reservationtelco
PHP | 1867 lines | 1061 code | 348 blank | 458 comment | 172 complexity | b630928777c88ecafeb60894d08b5fe4 MD5 | raw file
  1. <?php
  2. /**
  3. * XML-RPC protocol support for WordPress
  4. *
  5. * @license GPL v2 <./license.txt>
  6. * @package WordPress
  7. */
  8. /**
  9. * Whether this is a XMLRPC Request
  10. *
  11. * @var bool
  12. */
  13. define('XMLRPC_REQUEST', true);
  14. // Some browser-embedded clients send cookies. We don't want them.
  15. $_COOKIE = array();
  16. // A bug in PHP < 5.2.2 makes $HTTP_RAW_POST_DATA not set by default,
  17. // but we can do it ourself.
  18. if ( !isset( $HTTP_RAW_POST_DATA ) ) {
  19. $HTTP_RAW_POST_DATA = file_get_contents( 'php://input' );
  20. }
  21. // fix for mozBlog and other cases where '<?xml' isn't on the very first line
  22. if ( isset($HTTP_RAW_POST_DATA) )
  23. $HTTP_RAW_POST_DATA = trim($HTTP_RAW_POST_DATA);
  24. /** Include the bootstrap for setting up WordPress environment */
  25. include('./wp-load.php');
  26. if ( isset( $_GET['rsd'] ) ) { // http://archipelago.phrasewise.com/rsd
  27. header('Content-Type: text/xml; charset=' . get_option('blog_charset'), true);
  28. ?>
  29. <?php echo '<?xml version="1.0" encoding="'.get_option('blog_charset').'"?'.'>'; ?>
  30. <rsd version="1.0" xmlns="http://archipelago.phrasewise.com/rsd">
  31. <service>
  32. <engineName>WordPress</engineName>
  33. <engineLink>http://wordpress.org/</engineLink>
  34. <homePageLink><?php bloginfo_rss('url') ?></homePageLink>
  35. <apis>
  36. <api name="WordPress" blogID="1" preferred="true" apiLink="<?php echo site_url('xmlrpc.php', 'rpc') ?>" />
  37. <api name="Movable Type" blogID="1" preferred="false" apiLink="<?php echo site_url('xmlrpc.php', 'rpc') ?>" />
  38. <api name="MetaWeblog" blogID="1" preferred="false" apiLink="<?php echo site_url('xmlrpc.php', 'rpc') ?>" />
  39. <api name="Blogger" blogID="1" preferred="false" apiLink="<?php echo site_url('xmlrpc.php', 'rpc') ?>" />
  40. <api name="Atom" blogID="" preferred="false" apiLink="<?php echo apply_filters('atom_service_url', site_url('wp-app.php/service', 'rpc') ) ?>" />
  41. </apis>
  42. </service>
  43. </rsd>
  44. <?php
  45. exit;
  46. }
  47. include_once(ABSPATH . 'wp-admin/includes/admin.php');
  48. include_once(ABSPATH . WPINC . '/class-IXR.php');
  49. // Turn off all warnings and errors.
  50. // error_reporting(0);
  51. /**
  52. * Posts submitted via the xmlrpc interface get that title
  53. * @name post_default_title
  54. * @var string
  55. */
  56. $post_default_title = "";
  57. /**
  58. * Whether to enable XMLRPC Logging.
  59. *
  60. * @name xmlrpc_logging
  61. * @var int|bool
  62. */
  63. $xmlrpc_logging = 0;
  64. /**
  65. * logIO() - Writes logging info to a file.
  66. *
  67. * @uses $xmlrpc_logging
  68. * @package WordPress
  69. * @subpackage Logging
  70. *
  71. * @param string $io Whether input or output
  72. * @param string $msg Information describing logging reason.
  73. * @return bool Always return true
  74. */
  75. function logIO($io,$msg) {
  76. global $xmlrpc_logging;
  77. if ($xmlrpc_logging) {
  78. $fp = fopen("../xmlrpc.log","a+");
  79. $date = gmdate("Y-m-d H:i:s ");
  80. $iot = ($io == "I") ? " Input: " : " Output: ";
  81. fwrite($fp, "\n\n".$date.$iot.$msg);
  82. fclose($fp);
  83. }
  84. return true;
  85. }
  86. if ( isset($HTTP_RAW_POST_DATA) )
  87. logIO("I", $HTTP_RAW_POST_DATA);
  88. /**
  89. * WordPress XMLRPC server implementation.
  90. *
  91. * Implements compatability for Blogger API, MetaWeblog API, MovableType, and
  92. * pingback. Additional WordPress API for managing comments, pages, posts,
  93. * options, etc.
  94. *
  95. * Since WordPress 2.6.0, WordPress XMLRPC server can be disabled in the
  96. * administration panels.
  97. *
  98. * @package WordPress
  99. * @subpackage Publishing
  100. * @since 1.5.0
  101. */
  102. class wp_xmlrpc_server extends IXR_Server {
  103. /**
  104. * Register all of the XMLRPC methods that XMLRPC server understands.
  105. *
  106. * PHP4 constructor and sets up server and method property. Passes XMLRPC
  107. * methods through the 'xmlrpc_methods' filter to allow plugins to extend
  108. * or replace XMLRPC methods.
  109. *
  110. * @since 1.5.0
  111. *
  112. * @return wp_xmlrpc_server
  113. */
  114. function wp_xmlrpc_server() {
  115. $this->methods = array(
  116. // WordPress API
  117. 'wp.getUsersBlogs' => 'this:wp_getUsersBlogs',
  118. 'wp.getPage' => 'this:wp_getPage',
  119. 'wp.getPages' => 'this:wp_getPages',
  120. 'wp.newPage' => 'this:wp_newPage',
  121. 'wp.deletePage' => 'this:wp_deletePage',
  122. 'wp.editPage' => 'this:wp_editPage',
  123. 'wp.getPageList' => 'this:wp_getPageList',
  124. 'wp.getAuthors' => 'this:wp_getAuthors',
  125. 'wp.getCategories' => 'this:mw_getCategories', // Alias
  126. 'wp.getTags' => 'this:wp_getTags',
  127. 'wp.newCategory' => 'this:wp_newCategory',
  128. 'wp.deleteCategory' => 'this:wp_deleteCategory',
  129. 'wp.suggestCategories' => 'this:wp_suggestCategories',
  130. 'wp.uploadFile' => 'this:mw_newMediaObject', // Alias
  131. 'wp.getCommentCount' => 'this:wp_getCommentCount',
  132. 'wp.getPostStatusList' => 'this:wp_getPostStatusList',
  133. 'wp.getPageStatusList' => 'this:wp_getPageStatusList',
  134. 'wp.getPageTemplates' => 'this:wp_getPageTemplates',
  135. 'wp.getOptions' => 'this:wp_getOptions',
  136. 'wp.setOptions' => 'this:wp_setOptions',
  137. 'wp.getComment' => 'this:wp_getComment',
  138. 'wp.getComments' => 'this:wp_getComments',
  139. 'wp.deleteComment' => 'this:wp_deleteComment',
  140. 'wp.editComment' => 'this:wp_editComment',
  141. 'wp.newComment' => 'this:wp_newComment',
  142. 'wp.getCommentStatusList' => 'this:wp_getCommentStatusList',
  143. // Blogger API
  144. 'blogger.getUsersBlogs' => 'this:blogger_getUsersBlogs',
  145. 'blogger.getUserInfo' => 'this:blogger_getUserInfo',
  146. 'blogger.getPost' => 'this:blogger_getPost',
  147. 'blogger.getRecentPosts' => 'this:blogger_getRecentPosts',
  148. 'blogger.getTemplate' => 'this:blogger_getTemplate',
  149. 'blogger.setTemplate' => 'this:blogger_setTemplate',
  150. 'blogger.newPost' => 'this:blogger_newPost',
  151. 'blogger.editPost' => 'this:blogger_editPost',
  152. 'blogger.deletePost' => 'this:blogger_deletePost',
  153. // MetaWeblog API (with MT extensions to structs)
  154. 'metaWeblog.newPost' => 'this:mw_newPost',
  155. 'metaWeblog.editPost' => 'this:mw_editPost',
  156. 'metaWeblog.getPost' => 'this:mw_getPost',
  157. 'metaWeblog.getRecentPosts' => 'this:mw_getRecentPosts',
  158. 'metaWeblog.getCategories' => 'this:mw_getCategories',
  159. 'metaWeblog.newMediaObject' => 'this:mw_newMediaObject',
  160. // MetaWeblog API aliases for Blogger API
  161. // see http://www.xmlrpc.com/stories/storyReader$2460
  162. 'metaWeblog.deletePost' => 'this:blogger_deletePost',
  163. 'metaWeblog.getTemplate' => 'this:blogger_getTemplate',
  164. 'metaWeblog.setTemplate' => 'this:blogger_setTemplate',
  165. 'metaWeblog.getUsersBlogs' => 'this:blogger_getUsersBlogs',
  166. // MovableType API
  167. 'mt.getCategoryList' => 'this:mt_getCategoryList',
  168. 'mt.getRecentPostTitles' => 'this:mt_getRecentPostTitles',
  169. 'mt.getPostCategories' => 'this:mt_getPostCategories',
  170. 'mt.setPostCategories' => 'this:mt_setPostCategories',
  171. 'mt.supportedMethods' => 'this:mt_supportedMethods',
  172. 'mt.supportedTextFilters' => 'this:mt_supportedTextFilters',
  173. 'mt.getTrackbackPings' => 'this:mt_getTrackbackPings',
  174. 'mt.publishPost' => 'this:mt_publishPost',
  175. // PingBack
  176. 'pingback.ping' => 'this:pingback_ping',
  177. 'pingback.extensions.getPingbacks' => 'this:pingback_extensions_getPingbacks',
  178. 'demo.sayHello' => 'this:sayHello',
  179. 'demo.addTwoNumbers' => 'this:addTwoNumbers'
  180. );
  181. $this->initialise_blog_option_info( );
  182. $this->methods = apply_filters('xmlrpc_methods', $this->methods);
  183. }
  184. function serve_request() {
  185. $this->IXR_Server($this->methods);
  186. }
  187. /**
  188. * Test XMLRPC API by saying, "Hello!" to client.
  189. *
  190. * @since 1.5.0
  191. *
  192. * @param array $args Method Parameters.
  193. * @return string
  194. */
  195. function sayHello($args) {
  196. return 'Hello!';
  197. }
  198. /**
  199. * Test XMLRPC API by adding two numbers for client.
  200. *
  201. * @since 1.5.0
  202. *
  203. * @param array $args Method Parameters.
  204. * @return int
  205. */
  206. function addTwoNumbers($args) {
  207. $number1 = $args[0];
  208. $number2 = $args[1];
  209. return $number1 + $number2;
  210. }
  211. /**
  212. * Check user's credentials.
  213. *
  214. * @since 1.5.0
  215. *
  216. * @param string $user_login User's username.
  217. * @param string $user_pass User's password.
  218. * @return bool Whether authentication passed.
  219. * @deprecated use wp_xmlrpc_server::login
  220. * @see wp_xmlrpc_server::login
  221. */
  222. function login_pass_ok($user_login, $user_pass) {
  223. if ( !get_option( 'enable_xmlrpc' ) ) {
  224. $this->error = new IXR_Error( 405, sprintf( __( 'XML-RPC services are disabled on this site. An admin user can enable them at %s'), admin_url('options-writing.php') ) );
  225. return false;
  226. }
  227. if (!user_pass_ok($user_login, $user_pass)) {
  228. $this->error = new IXR_Error(403, __('Bad login/pass combination.'));
  229. return false;
  230. }
  231. return true;
  232. }
  233. /**
  234. * Log user in.
  235. *
  236. * @since 2.8
  237. *
  238. * @param string $username User's username.
  239. * @param string $password User's password.
  240. * @return mixed WP_User object if authentication passed, false otherwise
  241. */
  242. function login($username, $password) {
  243. if ( !get_option( 'enable_xmlrpc' ) ) {
  244. $this->error = new IXR_Error( 405, sprintf( __( 'XML-RPC services are disabled on this site. An admin user can enable them at %s'), admin_url('options-writing.php') ) );
  245. return false;
  246. }
  247. $user = wp_authenticate($username, $password);
  248. if (is_wp_error($user)) {
  249. $this->error = new IXR_Error(403, __('Bad login/pass combination.'));
  250. return false;
  251. }
  252. wp_set_current_user( $user->ID );
  253. return $user;
  254. }
  255. /**
  256. * Sanitize string or array of strings for database.
  257. *
  258. * @since 1.5.2
  259. *
  260. * @param string|array $array Sanitize single string or array of strings.
  261. * @return string|array Type matches $array and sanitized for the database.
  262. */
  263. function escape(&$array) {
  264. global $wpdb;
  265. if (!is_array($array)) {
  266. return($wpdb->escape($array));
  267. } else {
  268. foreach ( (array) $array as $k => $v ) {
  269. if ( is_array($v) ) {
  270. $this->escape($array[$k]);
  271. } else if ( is_object($v) ) {
  272. //skip
  273. } else {
  274. $array[$k] = $wpdb->escape($v);
  275. }
  276. }
  277. }
  278. }
  279. /**
  280. * Retrieve custom fields for post.
  281. *
  282. * @since 2.5.0
  283. *
  284. * @param int $post_id Post ID.
  285. * @return array Custom fields, if exist.
  286. */
  287. function get_custom_fields($post_id) {
  288. $post_id = (int) $post_id;
  289. $custom_fields = array();
  290. foreach ( (array) has_meta($post_id) as $meta ) {
  291. // Don't expose protected fields.
  292. if ( strpos($meta['meta_key'], '_wp_') === 0 ) {
  293. continue;
  294. }
  295. $custom_fields[] = array(
  296. "id" => $meta['meta_id'],
  297. "key" => $meta['meta_key'],
  298. "value" => $meta['meta_value']
  299. );
  300. }
  301. return $custom_fields;
  302. }
  303. /**
  304. * Set custom fields for post.
  305. *
  306. * @since 2.5.0
  307. *
  308. * @param int $post_id Post ID.
  309. * @param array $fields Custom fields.
  310. */
  311. function set_custom_fields($post_id, $fields) {
  312. $post_id = (int) $post_id;
  313. foreach ( (array) $fields as $meta ) {
  314. if ( isset($meta['id']) ) {
  315. $meta['id'] = (int) $meta['id'];
  316. if ( isset($meta['key']) ) {
  317. update_meta($meta['id'], $meta['key'], $meta['value']);
  318. }
  319. else {
  320. delete_meta($meta['id']);
  321. }
  322. }
  323. else {
  324. $_POST['metakeyinput'] = $meta['key'];
  325. $_POST['metavalue'] = $meta['value'];
  326. add_meta($post_id);
  327. }
  328. }
  329. }
  330. /**
  331. * Set up blog options property.
  332. *
  333. * Passes property through 'xmlrpc_blog_options' filter.
  334. *
  335. * @since 2.6.0
  336. */
  337. function initialise_blog_option_info( ) {
  338. global $wp_version;
  339. $this->blog_options = array(
  340. // Read only options
  341. 'software_name' => array(
  342. 'desc' => __( 'Software Name' ),
  343. 'readonly' => true,
  344. 'value' => 'WordPress'
  345. ),
  346. 'software_version' => array(
  347. 'desc' => __( 'Software Version' ),
  348. 'readonly' => true,
  349. 'value' => $wp_version
  350. ),
  351. 'blog_url' => array(
  352. 'desc' => __( 'Site URL' ),
  353. 'readonly' => true,
  354. 'option' => 'siteurl'
  355. ),
  356. // Updatable options
  357. 'time_zone' => array(
  358. 'desc' => __( 'Time Zone' ),
  359. 'readonly' => false,
  360. 'option' => 'gmt_offset'
  361. ),
  362. 'blog_title' => array(
  363. 'desc' => __( 'Site Title' ),
  364. 'readonly' => false,
  365. 'option' => 'blogname'
  366. ),
  367. 'blog_tagline' => array(
  368. 'desc' => __( 'Site Tagline' ),
  369. 'readonly' => false,
  370. 'option' => 'blogdescription'
  371. ),
  372. 'date_format' => array(
  373. 'desc' => __( 'Date Format' ),
  374. 'readonly' => false,
  375. 'option' => 'date_format'
  376. ),
  377. 'time_format' => array(
  378. 'desc' => __( 'Time Format' ),
  379. 'readonly' => false,
  380. 'option' => 'time_format'
  381. ),
  382. 'users_can_register' => array(
  383. 'desc' => __( 'Allow new users to sign up' ),
  384. 'readonly' => false,
  385. 'option' => 'users_can_register'
  386. )
  387. );
  388. $this->blog_options = apply_filters( 'xmlrpc_blog_options', $this->blog_options );
  389. }
  390. /**
  391. * Retrieve the blogs of the user.
  392. *
  393. * @since 2.6.0
  394. *
  395. * @param array $args Method parameters.
  396. * @return array
  397. */
  398. function wp_getUsersBlogs( $args ) {
  399. global $current_site;
  400. // If this isn't on WPMU then just use blogger_getUsersBlogs
  401. if ( !is_multisite() ) {
  402. array_unshift( $args, 1 );
  403. return $this->blogger_getUsersBlogs( $args );
  404. }
  405. $this->escape( $args );
  406. $username = $args[0];
  407. $password = $args[1];
  408. if ( !$user = $this->login($username, $password) )
  409. return $this->error;
  410. do_action( 'xmlrpc_call', 'wp.getUsersBlogs' );
  411. $blogs = (array) get_blogs_of_user( $user->ID );
  412. $struct = array( );
  413. foreach ( $blogs as $blog ) {
  414. // Don't include blogs that aren't hosted at this site
  415. if ( $blog->site_id != $current_site->id )
  416. continue;
  417. $blog_id = $blog->userblog_id;
  418. switch_to_blog($blog_id);
  419. $is_admin = current_user_can('manage_options');
  420. $struct[] = array(
  421. 'isAdmin' => $is_admin,
  422. 'url' => get_option( 'home' ) . '/',
  423. 'blogid' => $blog_id,
  424. 'blogName' => get_option( 'blogname' ),
  425. 'xmlrpc' => site_url( 'xmlrpc.php' )
  426. );
  427. restore_current_blog( );
  428. }
  429. return $struct;
  430. }
  431. /**
  432. * Retrieve page.
  433. *
  434. * @since 2.2.0
  435. *
  436. * @param array $args Method parameters.
  437. * @return array
  438. */
  439. function wp_getPage($args) {
  440. $this->escape($args);
  441. $blog_id = (int) $args[0];
  442. $page_id = (int) $args[1];
  443. $username = $args[2];
  444. $password = $args[3];
  445. if ( !$user = $this->login($username, $password) ) {
  446. return $this->error;
  447. }
  448. if ( !current_user_can( 'edit_page', $page_id ) )
  449. return new IXR_Error( 401, __( 'Sorry, you cannot edit this page.' ) );
  450. do_action('xmlrpc_call', 'wp.getPage');
  451. // Lookup page info.
  452. $page = get_page($page_id);
  453. // If we found the page then format the data.
  454. if ( $page->ID && ($page->post_type == "page") ) {
  455. // Get all of the page content and link.
  456. $full_page = get_extended($page->post_content);
  457. $link = post_permalink($page->ID);
  458. // Get info the page parent if there is one.
  459. $parent_title = "";
  460. if ( !empty($page->post_parent) ) {
  461. $parent = get_page($page->post_parent);
  462. $parent_title = $parent->post_title;
  463. }
  464. // Determine comment and ping settings.
  465. $allow_comments = comments_open($page->ID) ? 1 : 0;
  466. $allow_pings = pings_open($page->ID) ? 1 : 0;
  467. // Format page date.
  468. $page_date = mysql2date("Ymd\TH:i:s", $page->post_date, false);
  469. $page_date_gmt = mysql2date("Ymd\TH:i:s", $page->post_date_gmt, false);
  470. // For drafts use the GMT version of the date
  471. if ( $page->post_status == 'draft' )
  472. $page_date_gmt = get_gmt_from_date( mysql2date( 'Y-m-d H:i:s', $page->post_date ), 'Ymd\TH:i:s' );
  473. // Pull the categories info together.
  474. $categories = array();
  475. foreach ( wp_get_post_categories($page->ID) as $cat_id ) {
  476. $categories[] = get_cat_name($cat_id);
  477. }
  478. // Get the author info.
  479. $author = get_userdata($page->post_author);
  480. $page_template = get_post_meta( $page->ID, '_wp_page_template', true );
  481. if ( empty( $page_template ) )
  482. $page_template = 'default';
  483. $page_struct = array(
  484. "dateCreated" => new IXR_Date($page_date),
  485. "userid" => $page->post_author,
  486. "page_id" => $page->ID,
  487. "page_status" => $page->post_status,
  488. "description" => $full_page["main"],
  489. "title" => $page->post_title,
  490. "link" => $link,
  491. "permaLink" => $link,
  492. "categories" => $categories,
  493. "excerpt" => $page->post_excerpt,
  494. "text_more" => $full_page["extended"],
  495. "mt_allow_comments" => $allow_comments,
  496. "mt_allow_pings" => $allow_pings,
  497. "wp_slug" => $page->post_name,
  498. "wp_password" => $page->post_password,
  499. "wp_author" => $author->display_name,
  500. "wp_page_parent_id" => $page->post_parent,
  501. "wp_page_parent_title" => $parent_title,
  502. "wp_page_order" => $page->menu_order,
  503. "wp_author_id" => $author->ID,
  504. "wp_author_display_name" => $author->display_name,
  505. "date_created_gmt" => new IXR_Date($page_date_gmt),
  506. "custom_fields" => $this->get_custom_fields($page_id),
  507. "wp_page_template" => $page_template
  508. );
  509. return($page_struct);
  510. }
  511. // If the page doesn't exist indicate that.
  512. else {
  513. return(new IXR_Error(404, __("Sorry, no such page.")));
  514. }
  515. }
  516. /**
  517. * Retrieve Pages.
  518. *
  519. * @since 2.2.0
  520. *
  521. * @param array $args Method parameters.
  522. * @return array
  523. */
  524. function wp_getPages($args) {
  525. $this->escape($args);
  526. $blog_id = (int) $args[0];
  527. $username = $args[1];
  528. $password = $args[2];
  529. $num_pages = isset($args[3]) ? (int) $args[3] : 10;
  530. if ( !$user = $this->login($username, $password) )
  531. return $this->error;
  532. if ( !current_user_can( 'edit_pages' ) )
  533. return new IXR_Error( 401, __( 'Sorry, you cannot edit pages.' ) );
  534. do_action('xmlrpc_call', 'wp.getPages');
  535. $pages = get_posts( array('post_type' => 'page', 'post_status' => 'any', 'numberposts' => $num_pages) );
  536. $num_pages = count($pages);
  537. // If we have pages, put together their info.
  538. if ( $num_pages >= 1 ) {
  539. $pages_struct = array();
  540. for ( $i = 0; $i < $num_pages; $i++ ) {
  541. $page = wp_xmlrpc_server::wp_getPage(array(
  542. $blog_id, $pages[$i]->ID, $username, $password
  543. ));
  544. $pages_struct[] = $page;
  545. }
  546. return($pages_struct);
  547. }
  548. // If no pages were found return an error.
  549. else {
  550. return(array());
  551. }
  552. }
  553. /**
  554. * Create new page.
  555. *
  556. * @since 2.2.0
  557. *
  558. * @param array $args Method parameters.
  559. * @return unknown
  560. */
  561. function wp_newPage($args) {
  562. // Items not escaped here will be escaped in newPost.
  563. $username = $this->escape($args[1]);
  564. $password = $this->escape($args[2]);
  565. $page = $args[3];
  566. $publish = $args[4];
  567. if ( !$user = $this->login($username, $password) )
  568. return $this->error;
  569. do_action('xmlrpc_call', 'wp.newPage');
  570. // Make sure the user is allowed to add new pages.
  571. if ( !current_user_can("publish_pages") )
  572. return(new IXR_Error(401, __("Sorry, you cannot add new pages.")));
  573. // Mark this as content for a page.
  574. $args[3]["post_type"] = "page";
  575. // Let mw_newPost do all of the heavy lifting.
  576. return($this->mw_newPost($args));
  577. }
  578. /**
  579. * Delete page.
  580. *
  581. * @since 2.2.0
  582. *
  583. * @param array $args Method parameters.
  584. * @return bool True, if success.
  585. */
  586. function wp_deletePage($args) {
  587. $this->escape($args);
  588. $blog_id = (int) $args[0];
  589. $username = $args[1];
  590. $password = $args[2];
  591. $page_id = (int) $args[3];
  592. if ( !$user = $this->login($username, $password) )
  593. return $this->error;
  594. do_action('xmlrpc_call', 'wp.deletePage');
  595. // Get the current page based on the page_id and
  596. // make sure it is a page and not a post.
  597. $actual_page = wp_get_single_post($page_id, ARRAY_A);
  598. if ( !$actual_page || ($actual_page["post_type"] != "page") )
  599. return(new IXR_Error(404, __("Sorry, no such page.")));
  600. // Make sure the user can delete pages.
  601. if ( !current_user_can("delete_page", $page_id) )
  602. return(new IXR_Error(401, __("Sorry, you do not have the right to delete this page.")));
  603. // Attempt to delete the page.
  604. $result = wp_delete_post($page_id);
  605. if ( !$result )
  606. return(new IXR_Error(500, __("Failed to delete the page.")));
  607. return(true);
  608. }
  609. /**
  610. * Edit page.
  611. *
  612. * @since 2.2.0
  613. *
  614. * @param array $args Method parameters.
  615. * @return unknown
  616. */
  617. function wp_editPage($args) {
  618. // Items not escaped here will be escaped in editPost.
  619. $blog_id = (int) $args[0];
  620. $page_id = (int) $this->escape($args[1]);
  621. $username = $this->escape($args[2]);
  622. $password = $this->escape($args[3]);
  623. $content = $args[4];
  624. $publish = $args[5];
  625. if ( !$user = $this->login($username, $password) )
  626. return $this->error;
  627. do_action('xmlrpc_call', 'wp.editPage');
  628. // Get the page data and make sure it is a page.
  629. $actual_page = wp_get_single_post($page_id, ARRAY_A);
  630. if ( !$actual_page || ($actual_page["post_type"] != "page") )
  631. return(new IXR_Error(404, __("Sorry, no such page.")));
  632. // Make sure the user is allowed to edit pages.
  633. if ( !current_user_can("edit_page", $page_id) )
  634. return(new IXR_Error(401, __("Sorry, you do not have the right to edit this page.")));
  635. // Mark this as content for a page.
  636. $content["post_type"] = "page";
  637. // Arrange args in the way mw_editPost understands.
  638. $args = array(
  639. $page_id,
  640. $username,
  641. $password,
  642. $content,
  643. $publish
  644. );
  645. // Let mw_editPost do all of the heavy lifting.
  646. return($this->mw_editPost($args));
  647. }
  648. /**
  649. * Retrieve page list.
  650. *
  651. * @since 2.2.0
  652. *
  653. * @param array $args Method parameters.
  654. * @return unknown
  655. */
  656. function wp_getPageList($args) {
  657. global $wpdb;
  658. $this->escape($args);
  659. $blog_id = (int) $args[0];
  660. $username = $args[1];
  661. $password = $args[2];
  662. if ( !$user = $this->login($username, $password) )
  663. return $this->error;
  664. if ( !current_user_can( 'edit_pages' ) )
  665. return new IXR_Error( 401, __( 'Sorry, you cannot edit pages.' ) );
  666. do_action('xmlrpc_call', 'wp.getPageList');
  667. // Get list of pages ids and titles
  668. $page_list = $wpdb->get_results("
  669. SELECT ID page_id,
  670. post_title page_title,
  671. post_parent page_parent_id,
  672. post_date_gmt,
  673. post_date,
  674. post_status
  675. FROM {$wpdb->posts}
  676. WHERE post_type = 'page'
  677. ORDER BY ID
  678. ");
  679. // The date needs to be formated properly.
  680. $num_pages = count($page_list);
  681. for ( $i = 0; $i < $num_pages; $i++ ) {
  682. $post_date = mysql2date("Ymd\TH:i:s", $page_list[$i]->post_date, false);
  683. $post_date_gmt = mysql2date("Ymd\TH:i:s", $page_list[$i]->post_date_gmt, false);
  684. $page_list[$i]->dateCreated = new IXR_Date($post_date);
  685. $page_list[$i]->date_created_gmt = new IXR_Date($post_date_gmt);
  686. // For drafts use the GMT version of the date
  687. if ( $page_list[$i]->post_status == 'draft' ) {
  688. $page_list[$i]->date_created_gmt = get_gmt_from_date( mysql2date( 'Y-m-d H:i:s', $page_list[$i]->post_date ), 'Ymd\TH:i:s' );
  689. $page_list[$i]->date_created_gmt = new IXR_Date( $page_list[$i]->date_created_gmt );
  690. }
  691. unset($page_list[$i]->post_date_gmt);
  692. unset($page_list[$i]->post_date);
  693. unset($page_list[$i]->post_status);
  694. }
  695. return($page_list);
  696. }
  697. /**
  698. * Retrieve authors list.
  699. *
  700. * @since 2.2.0
  701. *
  702. * @param array $args Method parameters.
  703. * @return array
  704. */
  705. function wp_getAuthors($args) {
  706. $this->escape($args);
  707. $blog_id = (int) $args[0];
  708. $username = $args[1];
  709. $password = $args[2];
  710. if ( !$user = $this->login($username, $password) )
  711. return $this->error;
  712. if ( !current_user_can("edit_posts") )
  713. return(new IXR_Error(401, __("Sorry, you cannot edit posts on this site.")));
  714. do_action('xmlrpc_call', 'wp.getAuthors');
  715. $authors = array();
  716. foreach ( (array) get_users_of_blog() as $row ) {
  717. $authors[] = array(
  718. "user_id" => $row->user_id,
  719. "user_login" => $row->user_login,
  720. "display_name" => $row->display_name
  721. );
  722. }
  723. return($authors);
  724. }
  725. /**
  726. * Get list of all tags
  727. *
  728. * @since 2.7
  729. *
  730. * @param array $args Method parameters.
  731. * @return array
  732. */
  733. function wp_getTags( $args ) {
  734. $this->escape( $args );
  735. $blog_id = (int) $args[0];
  736. $username = $args[1];
  737. $password = $args[2];
  738. if ( !$user = $this->login($username, $password) )
  739. return $this->error;
  740. if ( !current_user_can( 'edit_posts' ) )
  741. return new IXR_Error( 401, __( 'Sorry, you must be able to edit posts on this site in order to view tags.' ) );
  742. do_action( 'xmlrpc_call', 'wp.getKeywords' );
  743. $tags = array( );
  744. if ( $all_tags = get_tags() ) {
  745. foreach( (array) $all_tags as $tag ) {
  746. $struct['tag_id'] = $tag->term_id;
  747. $struct['name'] = $tag->name;
  748. $struct['count'] = $tag->count;
  749. $struct['slug'] = $tag->slug;
  750. $struct['html_url'] = esc_html( get_tag_link( $tag->term_id ) );
  751. $struct['rss_url'] = esc_html( get_tag_feed_link( $tag->term_id ) );
  752. $tags[] = $struct;
  753. }
  754. }
  755. return $tags;
  756. }
  757. /**
  758. * Create new category.
  759. *
  760. * @since 2.2.0
  761. *
  762. * @param array $args Method parameters.
  763. * @return int Category ID.
  764. */
  765. function wp_newCategory($args) {
  766. $this->escape($args);
  767. $blog_id = (int) $args[0];
  768. $username = $args[1];
  769. $password = $args[2];
  770. $category = $args[3];
  771. if ( !$user = $this->login($username, $password) )
  772. return $this->error;
  773. do_action('xmlrpc_call', 'wp.newCategory');
  774. // Make sure the user is allowed to add a category.
  775. if ( !current_user_can("manage_categories") )
  776. return(new IXR_Error(401, __("Sorry, you do not have the right to add a category.")));
  777. // If no slug was provided make it empty so that
  778. // WordPress will generate one.
  779. if ( empty($category["slug"]) )
  780. $category["slug"] = "";
  781. // If no parent_id was provided make it empty
  782. // so that it will be a top level page (no parent).
  783. if ( !isset($category["parent_id"]) )
  784. $category["parent_id"] = "";
  785. // If no description was provided make it empty.
  786. if ( empty($category["description"]) )
  787. $category["description"] = "";
  788. $new_category = array(
  789. "cat_name" => $category["name"],
  790. "category_nicename" => $category["slug"],
  791. "category_parent" => $category["parent_id"],
  792. "category_description" => $category["description"]
  793. );
  794. $cat_id = wp_insert_category($new_category);
  795. if ( !$cat_id )
  796. return(new IXR_Error(500, __("Sorry, the new category failed.")));
  797. return($cat_id);
  798. }
  799. /**
  800. * Remove category.
  801. *
  802. * @since 2.5.0
  803. *
  804. * @param array $args Method parameters.
  805. * @return mixed See {@link wp_delete_category()} for return info.
  806. */
  807. function wp_deleteCategory($args) {
  808. $this->escape($args);
  809. $blog_id = (int) $args[0];
  810. $username = $args[1];
  811. $password = $args[2];
  812. $category_id = (int) $args[3];
  813. if ( !$user = $this->login($username, $password) )
  814. return $this->error;
  815. do_action('xmlrpc_call', 'wp.deleteCategory');
  816. if ( !current_user_can("manage_categories") )
  817. return new IXR_Error( 401, __( "Sorry, you do not have the right to delete a category." ) );
  818. return wp_delete_category( $category_id );
  819. }
  820. /**
  821. * Retrieve category list.
  822. *
  823. * @since 2.2.0
  824. *
  825. * @param array $args Method parameters.
  826. * @return array
  827. */
  828. function wp_suggestCategories($args) {
  829. $this->escape($args);
  830. $blog_id = (int) $args[0];
  831. $username = $args[1];
  832. $password = $args[2];
  833. $category = $args[3];
  834. $max_results = (int) $args[4];
  835. if ( !$user = $this->login($username, $password) )
  836. return $this->error;
  837. if ( !current_user_can( 'edit_posts' ) )
  838. return new IXR_Error( 401, __( 'Sorry, you must be able to edit posts to this site in order to view categories.' ) );
  839. do_action('xmlrpc_call', 'wp.suggestCategories');
  840. $category_suggestions = array();
  841. $args = array('get' => 'all', 'number' => $max_results, 'name__like' => $category);
  842. foreach ( (array) get_categories($args) as $cat ) {
  843. $category_suggestions[] = array(
  844. "category_id" => $cat->cat_ID,
  845. "category_name" => $cat->cat_name
  846. );
  847. }
  848. return($category_suggestions);
  849. }
  850. /**
  851. * Retrieve comment.
  852. *
  853. * @since 2.7.0
  854. *
  855. * @param array $args Method parameters.
  856. * @return array
  857. */
  858. function wp_getComment($args) {
  859. $this->escape($args);
  860. $blog_id = (int) $args[0];
  861. $username = $args[1];
  862. $password = $args[2];
  863. $comment_id = (int) $args[3];
  864. if ( !$user = $this->login($username, $password) )
  865. return $this->error;
  866. if ( !current_user_can( 'moderate_comments' ) )
  867. return new IXR_Error( 403, __( 'You are not allowed to moderate comments on this site.' ) );
  868. do_action('xmlrpc_call', 'wp.getComment');
  869. if ( ! $comment = get_comment($comment_id) )
  870. return new IXR_Error( 404, __( 'Invalid comment ID.' ) );
  871. // Format page date.
  872. $comment_date = mysql2date("Ymd\TH:i:s", $comment->comment_date, false);
  873. $comment_date_gmt = mysql2date("Ymd\TH:i:s", $comment->comment_date_gmt, false);
  874. if ( '0' == $comment->comment_approved )
  875. $comment_status = 'hold';
  876. else if ( 'spam' == $comment->comment_approved )
  877. $comment_status = 'spam';
  878. else if ( '1' == $comment->comment_approved )
  879. $comment_status = 'approve';
  880. else
  881. $comment_status = $comment->comment_approved;
  882. $link = get_comment_link($comment);
  883. $comment_struct = array(
  884. "date_created_gmt" => new IXR_Date($comment_date_gmt),
  885. "user_id" => $comment->user_id,
  886. "comment_id" => $comment->comment_ID,
  887. "parent" => $comment->comment_parent,
  888. "status" => $comment_status,
  889. "content" => $comment->comment_content,
  890. "link" => $link,
  891. "post_id" => $comment->comment_post_ID,
  892. "post_title" => get_the_title($comment->comment_post_ID),
  893. "author" => $comment->comment_author,
  894. "author_url" => $comment->comment_author_url,
  895. "author_email" => $comment->comment_author_email,
  896. "author_ip" => $comment->comment_author_IP,
  897. "type" => $comment->comment_type,
  898. );
  899. return $comment_struct;
  900. }
  901. /**
  902. * Retrieve comments.
  903. *
  904. * @since 2.7.0
  905. *
  906. * @param array $args Method parameters.
  907. * @return array
  908. */
  909. function wp_getComments($args) {
  910. $raw_args = $args;
  911. $this->escape($args);
  912. $blog_id = (int) $args[0];
  913. $username = $args[1];
  914. $password = $args[2];
  915. $struct = $args[3];
  916. if ( !$user = $this->login($username, $password) )
  917. return $this->error;
  918. if ( !current_user_can( 'moderate_comments' ) )
  919. return new IXR_Error( 401, __( 'Sorry, you cannot edit comments.' ) );
  920. do_action('xmlrpc_call', 'wp.getComments');
  921. if ( isset($struct['status']) )
  922. $status = $struct['status'];
  923. else
  924. $status = '';
  925. $post_id = '';
  926. if ( isset($struct['post_id']) )
  927. $post_id = absint($struct['post_id']);
  928. $offset = 0;
  929. if ( isset($struct['offset']) )
  930. $offset = absint($struct['offset']);
  931. $number = 10;
  932. if ( isset($struct['number']) )
  933. $number = absint($struct['number']);
  934. $comments = get_comments( array('status' => $status, 'post_id' => $post_id, 'offset' => $offset, 'number' => $number ) );
  935. $num_comments = count($comments);
  936. if ( ! $num_comments )
  937. return array();
  938. $comments_struct = array();
  939. for ( $i = 0; $i < $num_comments; $i++ ) {
  940. $comment = wp_xmlrpc_server::wp_getComment(array(
  941. $raw_args[0], $raw_args[1], $raw_args[2], $comments[$i]->comment_ID,
  942. ));
  943. $comments_struct[] = $comment;
  944. }
  945. return $comments_struct;
  946. }
  947. /**
  948. * Remove comment.
  949. *
  950. * @since 2.7.0
  951. *
  952. * @param array $args Method parameters.
  953. * @return mixed {@link wp_delete_comment()}
  954. */
  955. function wp_deleteComment($args) {
  956. $this->escape($args);
  957. $blog_id = (int) $args[0];
  958. $username = $args[1];
  959. $password = $args[2];
  960. $comment_ID = (int) $args[3];
  961. if ( !$user = $this->login($username, $password) )
  962. return $this->error;
  963. if ( !current_user_can( 'moderate_comments' ) )
  964. return new IXR_Error( 403, __( 'You are not allowed to moderate comments on this site.' ) );
  965. do_action('xmlrpc_call', 'wp.deleteComment');
  966. if ( ! get_comment($comment_ID) )
  967. return new IXR_Error( 404, __( 'Invalid comment ID.' ) );
  968. return wp_delete_comment($comment_ID);
  969. }
  970. /**
  971. * Edit comment.
  972. *
  973. * @since 2.7.0
  974. *
  975. * @param array $args Method parameters.
  976. * @return bool True, on success.
  977. */
  978. function wp_editComment($args) {
  979. $this->escape($args);
  980. $blog_id = (int) $args[0];
  981. $username = $args[1];
  982. $password = $args[2];
  983. $comment_ID = (int) $args[3];
  984. $content_struct = $args[4];
  985. if ( !$user = $this->login($username, $password) )
  986. return $this->error;
  987. if ( !current_user_can( 'moderate_comments' ) )
  988. return new IXR_Error( 403, __( 'You are not allowed to moderate comments on this site.' ) );
  989. do_action('xmlrpc_call', 'wp.editComment');
  990. if ( ! get_comment($comment_ID) )
  991. return new IXR_Error( 404, __( 'Invalid comment ID.' ) );
  992. if ( isset($content_struct['status']) ) {
  993. $statuses = get_comment_statuses();
  994. $statuses = array_keys($statuses);
  995. if ( ! in_array($content_struct['status'], $statuses) )
  996. return new IXR_Error( 401, __( 'Invalid comment status.' ) );
  997. $comment_approved = $content_struct['status'];
  998. }
  999. // Do some timestamp voodoo
  1000. if ( !empty( $content_struct['date_created_gmt'] ) ) {
  1001. $dateCreated = str_replace( 'Z', '', $content_struct['date_created_gmt']->getIso() ) . 'Z'; // We know this is supposed to be GMT, so we're going to slap that Z on there by force
  1002. $comment_date = get_date_from_gmt(iso8601_to_datetime($dateCreated));
  1003. $comment_date_gmt = iso8601_to_datetime($dateCreated, GMT);
  1004. }
  1005. if ( isset($content_struct['content']) )
  1006. $comment_content = $content_struct['content'];
  1007. if ( isset($content_struct['author']) )
  1008. $comment_author = $content_struct['author'];
  1009. if ( isset($content_struct['author_url']) )
  1010. $comment_author_url = $content_struct['author_url'];
  1011. if ( isset($content_struct['author_email']) )
  1012. $comment_author_email = $content_struct['author_email'];
  1013. // We've got all the data -- post it:
  1014. $comment = compact('comment_ID', 'comment_content', 'comment_approved', 'comment_date', 'comment_date_gmt', 'comment_author', 'comment_author_email', 'comment_author_url');
  1015. $result = wp_update_comment($comment);
  1016. if ( is_wp_error( $result ) )
  1017. return new IXR_Error(500, $result->get_error_message());
  1018. if ( !$result )
  1019. return new IXR_Error(500, __('Sorry, the comment could not be edited. Something wrong happened.'));
  1020. return true;
  1021. }
  1022. /**
  1023. * Create new comment.
  1024. *
  1025. * @since 2.7.0
  1026. *
  1027. * @param array $args Method parameters.
  1028. * @return mixed {@link wp_new_comment()}
  1029. */
  1030. function wp_newComment($args) {
  1031. global $wpdb;
  1032. $this->escape($args);
  1033. $blog_id = (int) $args[0];
  1034. $username = $args[1];
  1035. $password = $args[2];
  1036. $post = $args[3];
  1037. $content_struct = $args[4];
  1038. $allow_anon = apply_filters('xmlrpc_allow_anonymous_comments', false);
  1039. $user = $this->login($username, $password);
  1040. if ( !$user ) {
  1041. $logged_in = false;
  1042. if ( $allow_anon && get_option('comment_registration') )
  1043. return new IXR_Error( 403, __( 'You must be registered to comment' ) );
  1044. else if ( !$allow_anon )
  1045. return $this->error;
  1046. } else {
  1047. $logged_in = true;
  1048. }
  1049. if ( is_numeric($post) )
  1050. $post_id = absint($post);
  1051. else
  1052. $post_id = url_to_postid($post);
  1053. if ( ! $post_id )
  1054. return new IXR_Error( 404, __( 'Invalid post ID.' ) );
  1055. if ( ! get_post($post_id) )
  1056. return new IXR_Error( 404, __( 'Invalid post ID.' ) );
  1057. $comment['comment_post_ID'] = $post_id;
  1058. if ( $logged_in ) {
  1059. $comment['comment_author'] = $wpdb->escape( $user->display_name );
  1060. $comment['comment_author_email'] = $wpdb->escape( $user->user_email );
  1061. $comment['comment_author_url'] = $wpdb->escape( $user->user_url );
  1062. $comment['user_ID'] = $user->ID;
  1063. } else {
  1064. $comment['comment_author'] = '';
  1065. if ( isset($content_struct['author']) )
  1066. $comment['comment_author'] = $content_struct['author'];
  1067. $comment['comment_author_email'] = '';
  1068. if ( isset($content_struct['author_email']) )
  1069. $comment['comment_author_email'] = $content_struct['author_email'];
  1070. $comment['comment_author_url'] = '';
  1071. if ( isset($content_struct['author_url']) )
  1072. $comment['comment_author_url'] = $content_struct['author_url'];
  1073. $comment['user_ID'] = 0;
  1074. if ( get_option('require_name_email') ) {
  1075. if ( 6 > strlen($comment['comment_author_email']) || '' == $comment['comment_author'] )
  1076. return new IXR_Error( 403, __( 'Comment author name and email are required' ) );
  1077. elseif ( !is_email($comment['comment_author_email']) )
  1078. return new IXR_Error( 403, __( 'A valid email address is required' ) );
  1079. }
  1080. }
  1081. $comment['comment_parent'] = isset($content_struct['comment_parent']) ? absint($content_struct['comment_parent']) : 0;
  1082. $comment['comment_content'] = $content_struct['content'];
  1083. do_action('xmlrpc_call', 'wp.newComment');
  1084. return wp_new_comment($comment);
  1085. }
  1086. /**
  1087. * Retrieve all of the comment status.
  1088. *
  1089. * @since 2.7.0
  1090. *
  1091. * @param array $args Method parameters.
  1092. * @return array
  1093. */
  1094. function wp_getCommentStatusList($args) {
  1095. $this->escape( $args );
  1096. $blog_id = (int) $args[0];
  1097. $username = $args[1];
  1098. $password = $args[2];
  1099. if ( !$user = $this->login($username, $password) )
  1100. return $this->error;
  1101. if ( !current_user_can( 'moderate_comments' ) )
  1102. return new IXR_Error( 403, __( 'You are not allowed access to details about this site.' ) );
  1103. do_action('xmlrpc_call', 'wp.getCommentStatusList');
  1104. return get_comment_statuses( );
  1105. }
  1106. /**
  1107. * Retrieve comment count.
  1108. *
  1109. * @since 2.5.0
  1110. *
  1111. * @param array $args Method parameters.
  1112. * @return array
  1113. */
  1114. function wp_getCommentCount( $args ) {
  1115. $this->escape($args);
  1116. $blog_id = (int) $args[0];
  1117. $username = $args[1];
  1118. $password = $args[2];
  1119. $post_id = (int) $args[3];
  1120. if ( !$user = $this->login($username, $password) )
  1121. return $this->error;
  1122. if ( !current_user_can( 'edit_posts' ) )
  1123. return new IXR_Error( 403, __( 'You are not allowed access to details about comments.' ) );
  1124. do_action('xmlrpc_call', 'wp.getCommentCount');
  1125. $count = wp_count_comments( $post_id );
  1126. return array(
  1127. "approved" => $count->approved,
  1128. "awaiting_moderation" => $count->moderated,
  1129. "spam" => $count->spam,
  1130. "total_comments" => $count->total_comments
  1131. );
  1132. }
  1133. /**
  1134. * Retrieve post statuses.
  1135. *
  1136. * @since 2.5.0
  1137. *
  1138. * @param array $args Method parameters.
  1139. * @return array
  1140. */
  1141. function wp_getPostStatusList( $args ) {
  1142. $this->escape( $args );
  1143. $blog_id = (int) $args[0];
  1144. $username = $args[1];
  1145. $password = $args[2];
  1146. if ( !$user = $this->login($username, $password) )
  1147. return $this->error;
  1148. if ( !current_user_can( 'edit_posts' ) )
  1149. return new IXR_Error( 403, __( 'You are not allowed access to details about this site.' ) );
  1150. do_action('xmlrpc_call', 'wp.getPostStatusList');
  1151. return get_post_statuses( );
  1152. }
  1153. /**
  1154. * Retrieve page statuses.
  1155. *
  1156. * @since 2.5.0
  1157. *
  1158. * @param array $args Method parameters.
  1159. * @return array
  1160. */
  1161. function wp_getPageStatusList( $args ) {
  1162. $this->escape( $args );
  1163. $blog_id = (int) $args[0];
  1164. $username = $args[1];
  1165. $password = $args[2];
  1166. if ( !$user = $this->login($username, $password) )
  1167. return $this->error;
  1168. if ( !current_user_can( 'edit_posts' ) )
  1169. return new IXR_Error( 403, __( 'You are not allowed access to details about this site.' ) );
  1170. do_action('xmlrpc_call', 'wp.getPageStatusList');
  1171. return get_page_statuses( );
  1172. }
  1173. /**
  1174. * Retrieve page templates.
  1175. *
  1176. * @since 2.6.0
  1177. *
  1178. * @param array $args Method parameters.
  1179. * @return array
  1180. */
  1181. function wp_getPageTemplates( $args ) {
  1182. $this->escape( $args );
  1183. $blog_id = (int) $args[0];
  1184. $username = $args[1];
  1185. $password = $args[2];
  1186. if ( !$user = $this->login($username, $password) )
  1187. return $this->error;
  1188. if ( !current_user_can( 'edit_pages' ) )
  1189. return new IXR_Error( 403, __( 'You are not allowed access to details about this site.' ) );
  1190. $templates = get_page_templates( );
  1191. $templates['Default'] = 'default';
  1192. return $templates;
  1193. }
  1194. /**
  1195. * Retrieve blog options.
  1196. *
  1197. * @since 2.6.0
  1198. *
  1199. * @param array $args Method parameters.
  1200. * @return array
  1201. */
  1202. function wp_getOptions( $args ) {
  1203. $this->escape( $args );
  1204. $blog_id = (int) $args[0];
  1205. $username = $args[1];
  1206. $password = $args[2];
  1207. $options = (array) $args[3];
  1208. if ( !$user = $this->login($username, $password) )
  1209. return $this->error;
  1210. // If no specific options where asked for, return all of them
  1211. if ( count( $options ) == 0 )
  1212. $options = array_keys($this->blog_options);
  1213. return $this->_getOptions($options);
  1214. }
  1215. /**
  1216. * Retrieve blog options value from list.
  1217. *
  1218. * @since 2.6.0
  1219. *
  1220. * @param array $options Options to retrieve.
  1221. * @return array
  1222. */
  1223. function _getOptions($options) {
  1224. $data = array( );
  1225. foreach ( $options as $option ) {
  1226. if ( array_key_exists( $option, $this->blog_options ) ) {
  1227. $data[$option] = $this->blog_options[$option];
  1228. //Is the value static or dynamic?
  1229. if ( isset( $data[$option]['option'] ) ) {
  1230. $data[$option]['value'] = get_option( $data[$option]['option'] );
  1231. unset($data[$option]['option']);
  1232. }
  1233. }
  1234. }
  1235. return $data;
  1236. }
  1237. /**
  1238. * Update blog options.
  1239. *
  1240. * @since 2.6.0
  1241. *
  1242. * @param array $args Method parameters.
  1243. * @return unknown
  1244. */
  1245. function wp_setOptions( $args ) {
  1246. $this->escape( $args );
  1247. $blog_id = (int) $args[0];
  1248. $username = $args[1];
  1249. $password = $args[2];
  1250. $options = (array) $args[3];
  1251. if ( !$user = $this->login($username, $password) )
  1252. return $this->error;
  1253. if ( !current_user_can( 'manage_options' ) )
  1254. return new IXR_Error( 403, __( 'You are not allowed to update options.' ) );
  1255. foreach ( $options as $o_name => $o_value ) {
  1256. $option_names[] = $o_name;
  1257. if ( !array_key_exists( $o_name, $this->blog_options ) )
  1258. continue;
  1259. if ( $this->blog_options[$o_name]['readonly'] == true )
  1260. continue;
  1261. update_option( $this->blog_options[$o_name]['option'], $o_value );
  1262. }
  1263. //Now return the updated values
  1264. return $this->_getOptions($option_names);
  1265. }
  1266. /* Blogger API functions.
  1267. * specs on http://plant.blogger.com/api and http://groups.yahoo.com/group/bloggerDev/
  1268. */
  1269. /**
  1270. * Retrieve blogs that user owns.
  1271. *
  1272. * Will make more sense once we support multiple blogs.
  1273. *
  1274. * @since 1.5.0
  1275. *
  1276. * @param array $args Method parameters.
  1277. * @return array
  1278. */
  1279. function blogger_getUsersBlogs($args) {
  1280. if ( is_multisite() )
  1281. return $this->_multisite_getUsersBlogs($args);
  1282. $this->escape($args);
  1283. $username = $args[1];
  1284. $password = $args[2];
  1285. if ( !$user = $this->login($username, $password) )
  1286. return $this->error;
  1287. do_action('xmlrpc_call', 'blogger.getUsersBlogs');
  1288. $is_admin = current_user_can('manage_options');
  1289. $struct = array(
  1290. 'isAdmin' => $is_admin,
  1291. 'url' => get_option('home') . '/',
  1292. 'blogid' => '1',
  1293. 'blogName' => get_option('blogname'),
  1294. 'xmlrpc' => site_url( 'xmlrpc.php' )
  1295. );
  1296. return array($struct);
  1297. }
  1298. /**
  1299. * Private function for retrieving a users blogs for multisite setups
  1300. *
  1301. * @access protected
  1302. */
  1303. function _multisite_getUsersBlogs($args) {
  1304. global $current_blog;
  1305. $domain = $current_blog->domain;
  1306. $path = $current_blog->path . 'xmlrpc.php';
  1307. $protocol = is_ssl() ? 'https' : 'http';
  1308. $rpc = new IXR_Client("$protocol://{$domain}{$path}");
  1309. $rpc->query('wp.getUsersBlogs', $args[1], $args[2]);
  1310. $blogs = $rpc->getResponse();
  1311. if ( isset($blogs['faultCode']) )
  1312. return new IXR_Error($blogs['faultCode'], $blogs['faultString']);
  1313. if ( $_SERVER['HTTP_HOST'] == $domain && $_SERVER['REQUEST_URI'] == $path ) {
  1314. return $blogs;
  1315. } else {
  1316. foreach ( (array) $blogs as $blog ) {
  1317. if ( strpos($blog['url'], $_SERVER['HTTP_HOST']) )
  1318. return array($blog);
  1319. }
  1320. return array();
  1321. }
  1322. }
  1323. /**
  1324. * Retrieve user's data.
  1325. *
  1326. * Gives your client some info about you, so you don't have to.
  1327. *
  1328. * @since 1.5.0
  1329. *
  1330. * @param array $args Method parameters.
  1331. * @return array
  1332. */
  1333. function blogger_getUserInfo($args) {
  1334. $this->escape($args);
  1335. $username = $args[1];
  1336. $password = $args[2];
  1337. if ( !$user = $this->login($username, $password) )
  1338. return $this->error;
  1339. if ( !current_user_can( 'edit_posts' ) )
  1340. return new IXR_Error( 401, __( 'Sorry, you do not have access to user data on this site.' ) );
  1341. do_action('xmlrpc_call', 'blogger.getUserInfo');
  1342. $struct = array(
  1343. 'nickname' => $user->nickname,
  1344. 'userid' => $user->ID,
  1345. 'url' => $user->user_url,
  1346. 'lastname' => $user->last_name,
  1347. 'firstname' => $user->first_name
  1348. );
  1349. return $struct;
  1350. }
  1351. /**
  1352. * Retrieve post.
  1353. *
  1354. * @since 1.5.0
  1355. *
  1356. * @param array $args Method parameters.
  1357. * @return array
  1358. */
  1359. function blogger_getPost($args) {
  1360. $this->escape($args);
  1361. $post_ID = (int) $args[1];
  1362. $username = $args[2];
  1363. $password = $args[3];
  1364. if ( !$user = $this->login($username, $password) )
  1365. return $this->error;
  1366. if ( !current_user_can( 'edit_post', $post_ID ) )
  1367. return new IXR_Error( 401, __( 'Sorry, you cannot edit this post.' ) );
  1368. do_action('xmlrpc_call', 'blogger.getPost');
  1369. $post_data = wp_get_single_post($post_ID, ARRAY_A);
  1370. $categories = implode(',', wp_get_post_categories($post_ID));
  1371. $content = '<title>'.stripslashes($post_data['post_title']).'</title>';
  1372. $content .= '<category>'.$categories.'</category>';
  1373. $content .= stripslashes($post_data['post_content']);
  1374. $struct = array(
  1375. 'userid' => $post_data['post_author'],
  1376. 'dateCreated' => new IXR_Date(mysql2date('Ymd\TH:i:s', $post_data['post_date'], false)),
  1377. 'content' => $content,
  1378. 'postid' => $post_data['ID']
  1379. );
  1380. return $struct;
  1381. }
  1382. /**
  1383. * Retrieve list of recent posts.
  1384. *
  1385. * @since 1.5.0
  1386. *
  1387. * @param array $args Method parameters.
  1388. * @return array
  1389. */
  1390. function blogger_getRecentPosts($args) {
  1391. $this->escape($args);
  1392. $blog_ID = (int) $args[1]; /* though we don't use it yet */
  1393. $username = $args[2];
  1394. $password = $args[3];
  1395. $num_posts = $args[4];
  1396. if ( !$user = $this->login($username, $password) )
  1397. return $this->error;
  1398. do_action('xmlrpc_call', 'blogger.getRecentPosts');
  1399. $posts_list = wp_get_recent_posts($num_posts);
  1400. if ( !$posts_list ) {
  1401. $this->error = new IXR_Error(500, __('Either there are no posts, or something went wrong.'));
  1402. return $this->error;
  1403. }
  1404. foreach ($posts_list as $entry) {
  1405. if ( !current_user_can( 'edit_post', $entry['ID'] ) )
  1406. continue;
  1407. $post_date = mysql2date('Ymd\TH:i:s', $entry['post_date'], false);
  1408. $categories = implode(',', wp_get_post_categories($entry['ID']));
  1409. $content = '<title>'.stripslashes($entry['post_title']).'</title>';
  1410. $content .= '<category>'.$categories.'</category>';
  1411. $content .= stripslashes($entry['post_content']);
  1412. $struct[] = array(
  1413. 'userid' => $entry['post_author'],
  1414. 'dateCreated' => new IXR_Date($post_date),
  1415. 'content' => $content,
  1416. 'postid' => $entry['ID'],
  1417. );
  1418. }
  1419. $recent_posts = array();
  1420. for ( $j=0; $j<count($struct); $j++ ) {
  1421. array_push($recent_posts, $struct[$j]);
  1422. }
  1423. return $recent_posts;
  1424. }
  1425. /**
  1426. * Retrieve blog_filename content.
  1427. *
  1428. * @since 1.5.0
  1429. *
  1430. * @param array $args Method parameters.
  1431. * @return string
  1432. */
  1433. function blogger_getTemplate($args) {
  1434. $this->escape($args);
  1435. $blog_ID = (int) $args[1];
  1436. $username = $args[2];
  1437. $password = $args[3];
  1438. $template = $args[4]; /* could be 'main' or 'archiveIndex', but we don't use it */
  1439. if ( !$user = $this->login($username, $password) )
  1440. return $this->error;
  1441. do_action('xmlrpc_call', 'blogger.getTemplate');
  1442. if ( !current_user_can('edit_themes') )
  1443. return new IXR_Error(401, __('Sorry, this user can not edit the template.'));
  1444. /* warning: here we make the assumption that the blog's URL is on the same server */
  1445. $filename = get_option('home') . '/';
  1446. $filename = preg_replace('#https?://.+?/#', $_SERVER['DOCUMENT_ROOT'].'/', $filename);
  1447. $f = fopen($filename, 'r');
  1448. $content = fread($f, filesize($filename));
  1449. fclose($f);
  1450. /* so it is actually editable with a windows/mac client */
  1451. // FIXME: (or delete me) do we really want to cater to bad clients at the expense of good ones by BEEPing up their line breaks? commented. $content = str_replace("\n", "\r\n", $content);
  1452. return $content;
  1453. }
  1454. /**
  1455. * Updates the content of blog_filename.
  1456. *
  1457. * @since 1.5.0
  1458. *
  1459. * @param array $args Method parameters.
  1460. * @return bool True when done.
  1461. */
  1462. function blogger_setTemplate($args) {
  1463. $this->escape($args);
  1464. $blog_ID = (int) $args[1];
  1465. $username = $args[2];
  1466. $password = $args[3];
  1467. $content = $args[4];
  1468. $template = $args[5]; /* could be 'main' or 'archiveIndex', but we don't use it */
  1469. if ( !$user = $this->login($username, $password) )
  1470. return $this->error;
  1471. do_action('xmlrpc_call', 'blogger.setTemplate');
  1472. if ( !current_user_can('edit_themes') )
  1473. return new IXR_Error(401, __('Sorry, this user cannot edit the template.'));
  1474. /* warning: here we make the assumption that the blog's URL is on the same server */
  1475. $filename = get_option('home') . '/';
  1476. $filename = preg_replace('#https?://.+?/#', $_SERVER['DOCUMENT_ROOT'].'/', $filename);
  1477. if ($f = fopen($filename, 'w+')) {
  1478. fwrite($f, $content);
  1479. fclose($f);
  1480. } else {
  1481. return new IXR_Error(500, __('Either the file is not writable, or something wrong happened. The file has not been updated.'));
  1482. }
  1483. return true;
  1484. }
  1485. /**
  1486. * Create new post.
  1487. *
  1488. * @since 1.5.0
  1489. *
  1490. * @param array $args Method parameters.
  1491. * @return int
  1492. */
  1493. function blogger_newPost($args) {
  1494. $this->escape($args);
  1495. $blog_ID = (int) $args[1]; /* though we don't use it yet */
  1496. $username = $args[2];
  1497. $password = $args[3];
  1498. $content = $args[4];
  1499. $publish = $args[5];
  1500. if ( !$user = $this->login($username, $password) )
  1501. return $this->error;
  1502. do_action('xmlrpc_call', 'blogger.newPost');
  1503. $cap = ($publish) ? 'publish_posts' : 'edit_posts';
  1504. if ( !current_user_can($cap) )
  1505. return new IXR_Error(401, __('Sorry, you are not allowed to post on this site.'));
  1506. $post_status = ($publish) ? 'publish' : 'draft';
  1507. $post_author = $user->ID;
  1508. $post_title = xmlrpc_getposttitle($content);
  1509. $post_category = xmlrpc_getpostcategory($content);
  1510. $post_content = xmlrpc_removepostdata($content);
  1511. $post_date = current_time('mysql');
  1512. $post_date_gmt = current_time('mysql', 1);
  1513. $post_data = compact('blog_ID', 'post_author', 'post_date', 'post_date_gmt', 'post_content', 'post_title', 'post_category', 'post_status');
  1514. $post_ID = wp_insert_post($post_data);
  1515. if ( is_wp_error( $post_ID ) )
  1516. return new IXR_Error(500, $post_ID->get_error_message());
  1517. if ( !$post_ID )
  1518. return new IXR_Error(500, __('Sorry, your entry could not be posted. Something wrong happened.'));
  1519. $this->attach_up