Changeset 3730:5c45a5df9a59 for inc/core/class.dc.xmlrpc.php
- Timestamp:
- 03/08/18 17:58:39 (8 years ago)
- Branch:
- default
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
inc/core/class.dc.xmlrpc.php
r3415 r3730 10 10 # 11 11 # -- END LICENSE BLOCK ----------------------------------------- 12 if (!defined('DC_RC_PATH')) { return;}12 if (!defined('DC_RC_PATH')) {return;} 13 13 14 14 class dcXmlRpc extends xmlrpcIntrospectionServer 15 15 { 16 public $core; 17 private $blog_id; 18 private $blog_loaded = false; 19 private $debug = false; 20 private $debug_file = '/tmp/dotclear-xmlrpc.log'; 21 private $trace_args = true; 22 private $trace_response = true; 23 24 public function __construct($core,$blog_id) 25 { 26 parent::__construct(); 27 28 $this->core =& $core; 29 $this->blog_id = $blog_id; 30 31 # Blogger methods 32 $this->addCallback('blogger.newPost',array($this,'blogger_newPost'), 33 array('string','string','string','string','string','string','integer'), 34 'New post'); 35 36 $this->addCallback('blogger.editPost',array($this,'blogger_editPost'), 37 array('boolean','string','string','string','string','string','integer'), 38 'Edit a post'); 39 40 $this->addCallback('blogger.getPost',array($this,'blogger_getPost'), 41 array('struct','string','integer','string','string'), 42 'Return a posts by ID'); 43 44 $this->addCallback('blogger.deletePost',array($this,'blogger_deletePost'), 45 array('string','string','string','string','string','integer'), 46 'Delete a post'); 47 48 $this->addCallback('blogger.getRecentPosts',array($this,'blogger_getRecentPosts'), 49 array('array','string','string','string','string','integer'), 50 'Return a list of recent posts'); 51 52 $this->addCallback('blogger.getUsersBlogs',array($this,'blogger_getUserBlogs'), 53 array('struct','string','string','string'), 54 "Return user's blog"); 55 56 $this->addCallback('blogger.getUserInfo',array($this,'blogger_getUserInfo'), 57 array('struct','string','string','string'), 58 'Return User Info'); 59 60 # Metaweblog methods 61 $this->addCallback('metaWeblog.newPost',array($this,'mw_newPost'), 62 array('string','string','string','string','struct','boolean'), 63 'Creates a new post, and optionnaly publishes it.'); 64 65 $this->addCallback('metaWeblog.editPost',array($this,'mw_editPost'), 66 array('boolean','string','string','string','struct','boolean'), 67 'Updates information about an existing entry'); 68 69 $this->addCallback('metaWeblog.getPost',array($this,'mw_getPost'), 70 array('struct','string','string','string'), 71 'Returns information about a specific post'); 72 73 $this->addCallback('metaWeblog.getRecentPosts',array($this,'mw_getRecentPosts'), 74 array('array','string','string','string','integer'), 75 'List of most recent posts in the system'); 76 77 $this->addCallback('metaWeblog.getCategories',array($this,'mw_getCategories'), 78 array('array','string','string','string'), 79 'List of all categories defined in the weblog'); 80 81 $this->addCallback('metaWeblog.newMediaObject',array($this,'mw_newMediaObject'), 82 array('struct','string','string','string','struct'), 83 'Upload a file on the web server'); 84 85 # MovableType methods 86 $this->addCallback('mt.getRecentPostTitles',array($this,'mt_getRecentPostTitles'), 87 array('array','string','string','string','integer'), 88 'List of most recent posts in the system'); 89 90 $this->addCallback('mt.getCategoryList',array($this,'mt_getCategoryList'), 91 array('array','string','string','string'), 92 'List of all categories defined in the weblog'); 93 94 $this->addCallback('mt.getPostCategories',array($this,'mt_getPostCategories'), 95 array('array','string','string','string'), 96 'List of all categories to which the post is assigned'); 97 98 $this->addCallback('mt.setPostCategories',array($this,'mt_setPostCategories'), 99 array('boolean','string','string','string','array'), 100 'Sets the categories for a post'); 101 102 $this->addCallback('mt.publishPost',array($this,'mt_publishPost'), 103 array('boolean','string','string','string'), 104 'Retrieve pings list for a post'); 105 106 $this->addCallback('mt.supportedMethods',array($this,'listMethods'), 107 array(),'Retrieve information about the XML-RPC methods supported by the server.'); 108 109 $this->addCallback('mt.supportedTextFilters',array($this,'mt_supportedTextFilters'), 110 array(),'Retrieve information about supported text filters.'); 111 112 # WordPress methods 113 $this->addCallback('wp.getUsersBlogs',array($this,'wp_getUsersBlogs'), 114 array('array','string','string'), 115 'Retrieve the blogs of the user.'); 116 117 $this->addCallback('wp.getPage',array($this,'wp_getPage'), 118 array('struct','integer','integer','string','string'), 119 'Get the page identified by the page ID.'); 120 121 $this->addCallback('wp.getPages',array($this,'wp_getPages'), 122 array('array','integer','string','string','integer'), 123 'Get an array of all the pages on a blog.'); 124 125 $this->addCallback('wp.newPage',array($this,'wp_newPage'), 126 array('integer','integer','string','string','struct','boolean'), 127 'Create a new page.'); 128 129 $this->addCallback('wp.deletePage',array($this,'wp_deletePage'), 130 array('boolean','integer','string','string','integer'), 131 'Removes a page from the blog.'); 132 133 $this->addCallback('wp.editPage',array($this,'wp_editPage'), 134 array('boolean','integer','integer','string','string','struct','boolean'), 135 'Make changes to a blog page.'); 136 137 $this->addCallback('wp.getPageList',array($this,'wp_getPageList'), 138 array('array','integer','string','string'), 139 'Get an array of all the pages on a blog. Just the minimum details, lighter than wp.getPages.'); 140 141 $this->addCallback('wp.getAuthors',array($this,'wp_getAuthors'), 142 array('array','integer','string','string'), 143 'Get an array of users for the blog.'); 144 145 $this->addCallback('wp.getCategories',array($this,'wp_getCategories'), 146 array('array','integer','string','string'), 147 'Get an array of available categories on a blog.'); 148 149 $this->addCallback('wp.getTags',array($this,'wp_getTags'), 150 array('array','integer','string','string'), 151 'Get list of all tags for the blog.'); 152 153 $this->addCallback('wp.newCategory',array($this,'wp_newCategory'), 154 array('integer','integer','string','string','struct'), 155 'Create a new category.'); 156 157 $this->addCallback('wp.deleteCategory',array($this,'wp_deleteCategory'), 158 array('boolean','integer','string','string','integer'), 159 'Delete a category with a given ID.'); 160 161 $this->addCallback('wp.suggestCategories',array($this,'wp_suggestCategories'), 162 array('array','integer','string','string','string','integer'), 163 'Get an array of categories that start with a given string.'); 164 165 $this->addCallback('wp.uploadFile',array($this,'wp_uploadFile'), 166 array('struct','integer','string','string','struct'), 167 'Upload a file'); 168 169 $this->addCallback('wp.getPostStatusList',array($this,'wp_getPostStatusList'), 170 array('array','integer','string','string'), 171 'Retrieve all of the post statuses.'); 172 173 $this->addCallback('wp.getPageStatusList',array($this,'wp_getPageStatusList'), 174 array('array','integer','string','string'), 175 'Retrieve all of the pages statuses.'); 176 177 $this->addCallback('wp.getPageTemplates',array($this,'wp_getPageTemplates'), 178 array('struct','integer','string','string'), 179 'Retrieve page templates.'); 180 181 $this->addCallback('wp.getOptions',array($this,'wp_getOptions'), 182 array('struct','integer','string','string','array'), 183 'Retrieve blog options'); 184 185 $this->addCallback('wp.setOptions',array($this,'wp_setOptions'), 186 array('struct','integer','string','string','struct'), 187 'Update blog options'); 188 189 $this->addCallback('wp.getComment',array($this,'wp_getComment'), 190 array('struct','integer','string','string','integer'), 191 "Gets a comment, given it's comment ID."); 192 193 $this->addCallback('wp.getCommentCount',array($this,'wp_getCommentCount'), 194 array('array','integer','string','string','integer'), 195 'Retrieve comment count.'); 196 197 $this->addCallback('wp.getComments',array($this,'wp_getComments'), 198 array('array','integer','string','string','struct'), 199 'Gets a set of comments for a given post.'); 200 201 $this->addCallback('wp.deleteComment',array($this,'wp_deleteComment'), 202 array('boolean','integer','string','string','integer'), 203 'Delete a comment with given ID.'); 204 205 $this->addCallback('wp.editComment',array($this,'wp_editComment'), 206 array('boolean','integer','string','string','integer','struct'), 207 'Edit a comment with given ID.'); 208 209 $this->addCallback('wp.newComment',array($this,'wp_newComment'), 210 array('integer','integer','string','string','integer','struct'), 211 'Create a new comment for a given post ID.'); 212 213 $this->addCallback('wp.getCommentStatusList',array($this,'wp_getCommentStatusList'), 214 array('array','integer','string','string'), 215 'Retrieve all of the comment statuses.'); 216 217 # Pingback support 218 $this->addCallback('pingback.ping',array($this,'pingback_ping'), 219 array('string', 'string', 'string'), 220 'Notify a link to a post.'); 221 } 222 223 public function serve($data=false,$encoding='UTF-8') 224 { 225 parent::serve(false,$encoding); 226 } 227 228 public function call($methodname,$args) 229 { 230 try { 231 $rsp = @parent::call($methodname,$args); 232 $this->debugTrace($methodname,$args,$rsp); 233 return $rsp; 234 } catch (Exception $e) { 235 $this->debugTrace($methodname,$args,array($e->getMessage(),$e->getCode())); 236 throw $e; 237 } 238 } 239 240 private function debugTrace($methodname,$args,$rsp) 241 { 242 if (!$this->debug) { 243 return; 244 } 245 246 if (($fp = @fopen($this->debug_file,'a')) !== false) 247 { 248 fwrite($fp,'['.date('r').']'.' '.$methodname); 249 250 if ($this->trace_args) { 251 fwrite($fp,"\n- args ---\n".var_export($args,1)); 252 } 253 254 if ($this->trace_response) { 255 fwrite($fp,"\n- response ---\n".var_export($rsp,1)); 256 } 257 fwrite($fp,"\n"); 258 fclose($fp); 259 } 260 } 261 262 /* Internal methods 263 --------------------------------------------------- */ 264 private function setUser($user_id,$pwd) 265 { 266 if (empty($pwd) || $this->core->auth->checkUser($user_id,$pwd) !== true) { 267 throw new Exception('Login error'); 268 } 269 270 return true; 271 } 272 273 private function setBlog($bypass = false) 274 { 275 if (!$this->blog_id) { 276 throw new Exception('No blog ID given.'); 277 } 278 279 if ($this->blog_loaded) { 280 return true; 281 } 282 283 $this->core->setBlog($this->blog_id); 284 $this->blog_loaded = true; 285 286 if (!$this->core->blog->id) { 287 $this->core->blog = null; 288 throw new Exception('Blog does not exist.'); 289 } 290 291 if (!$bypass && 292 (!$this->core->blog->settings->system->enable_xmlrpc || 293 !$this->core->auth->check('usage,contentadmin',$this->core->blog->id))) { 294 $this->core->blog = null; 295 throw new Exception('Not enough permissions on this blog.'); 296 } 297 298 foreach ($this->core->plugins->getModules() as $id => $m) { 299 $this->core->plugins->loadNsFile($id,'xmlrpc'); 300 } 301 302 return true; 303 } 304 305 private function getPostRS($post_id,$user,$pwd,$post_type='post') 306 { 307 $this->setUser($user,$pwd); 308 $this->setBlog(); 309 $rs = $this->core->blog->getPosts(array( 310 'post_id' => (integer) $post_id, 311 'post_type' => $post_type 312 )); 313 314 if ($rs->isEmpty()) { 315 throw new Exception('This entry does not exist'); 316 } 317 318 return $rs; 319 } 320 321 private function getCatID($cat_url) 322 { 323 $rs = $this->core->blog->getCategories(array('cat_url' => $cat_url)); 324 325 return $rs->isEmpty() ? null : $rs->cat_id; 326 } 327 328 /* Generic methods 329 --------------------------------------------------- */ 330 private function newPost($blog_id,$user,$pwd,$content,$struct=array(),$publish=true) 331 { 332 $this->setUser($user,$pwd); 333 $this->setBlog(); 334 335 $title = !empty($struct['title']) ? $struct['title'] : ''; 336 $excerpt = !empty($struct['mt_excerpt']) ? $struct['mt_excerpt'] : ''; 337 $description = !empty($struct['description']) ? $struct['description'] : null; 338 $dateCreated = !empty($struct['dateCreated']) ? $struct['dateCreated'] : null; 339 $open_comment = isset($struct['mt_allow_comments']) ? $struct['mt_allow_comments'] : 1; 340 $open_tb = isset($struct['mt_allow_pings']) ? $struct['mt_allow_pings'] : 1; 341 342 if ($description !== null) { 343 $content = $description; 344 } 345 346 if (!$title) { 347 $title = text::cutString(html::clean($content),25).'...'; 348 } 349 350 $excerpt_xhtml = $this->core->callFormater('xhtml',$excerpt); 351 $content_xhtml = $this->core->callFormater('xhtml',$content); 352 353 if (empty($content)) { 354 throw new Exception('Cannot create an empty entry'); 355 } 356 357 $cur = $this->core->con->openCursor($this->core->prefix.'post'); 358 359 $cur->user_id = $this->core->auth->userID(); 360 $cur->post_lang = $this->core->auth->getInfo('user_lang'); 361 $cur->post_title = trim($title); 362 $cur->post_content = $content; 363 $cur->post_excerpt = $excerpt; 364 $cur->post_content_xhtml = $content_xhtml; 365 $cur->post_excerpt_xhtml = $excerpt_xhtml; 366 $cur->post_open_comment = (integer) ($open_comment == 1); 367 $cur->post_open_tb = (integer) ($open_tb == 1); 368 $cur->post_status = (integer) $publish; 369 $cur->post_format = 'xhtml'; 370 371 if ($dateCreated) { 372 if ($dateCreated instanceof xmlrpcDate) { 373 $cur->post_dt = date('Y-m-d H:i:00',$dateCreated->getTimestamp()); 374 } elseif (is_string($dateCreated) && @strtotime($dateCreated)) { 375 $cur->post_dt = date('Y-m-d H:i:00',strtotime($dateCreated)); 376 } 377 } 378 379 # Categories in an array 380 if (isset($struct['categories']) && is_array($struct['categories'])) 381 { 382 $categories = $struct['categories']; 383 $cat_id = !empty($categories[0]) ? $categories[0] : null; 384 385 $cur->cat_id = $this->getCatID($cat_id); 386 } 387 388 if (isset($struct['wp_slug'])) { 389 $cur->post_url = $struct['wp_slug']; 390 } 391 392 if (isset($struct['wp_password'])) { 393 $cur->post_password = $struct['wp_password']; 394 } 395 396 $cur->post_type = 'post'; 397 if (!empty($struct['post_type'])) { 398 $cur->post_type = $struct['post_type']; 399 } 400 401 if ($cur->post_type == 'post') 402 { 403 # --BEHAVIOR-- xmlrpcBeforeNewPost 404 $this->core->callBehavior('xmlrpcBeforeNewPost',$this,$cur,$content,$struct,$publish); 405 406 $post_id = $this->core->blog->addPost($cur); 407 408 # --BEHAVIOR-- xmlrpcAfterNewPost 409 $this->core->callBehavior('xmlrpcAfterNewPost',$this,$post_id,$cur,$content,$struct,$publish); 410 } 411 elseif ($cur->post_type == 'page') 412 { 413 if (isset($struct['wp_page_order'])) { 414 $cur->post_position = (integer) $struct['wp_page_order']; 415 } 416 417 $this->core->blog->settings->system->post_url_format = '{t}'; 418 419 $post_id = $this->core->blog->addPost($cur); 420 } 421 else 422 { 423 throw new Exception('Invalid post type',401); 424 } 425 426 return (string) $post_id; 427 } 428 429 private function editPost($post_id,$user,$pwd,$content,$struct=array(),$publish=true) 430 { 431 $post_id = (integer) $post_id; 432 433 $post_type = 'post'; 434 if (!empty($struct['post_type'])) { 435 $post_type = $struct['post_type']; 436 } 437 438 $post = $this->getPostRS($post_id,$user,$pwd,$post_type); 439 440 $title = (!empty($struct['title'])) ? $struct['title'] : ''; 441 $excerpt = (!empty($struct['mt_excerpt'])) ? $struct['mt_excerpt'] : ''; 442 $description = (!empty($struct['description'])) ? $struct['description'] : null; 443 $dateCreated = !empty($struct['dateCreated']) ? $struct['dateCreated'] : null; 444 $open_comment = (isset($struct['mt_allow_comments'])) ? $struct['mt_allow_comments'] : 1; 445 $open_tb = (isset($struct['mt_allow_pings'])) ? $struct['mt_allow_pings'] : 1; 446 447 if ($description !== null) { 448 $content = $description; 449 } 450 451 if (!$title) { 452 $title = text::cutString(html::clean($content),25).'...'; 453 } 454 455 $excerpt_xhtml = $this->core->callFormater('xhtml',$excerpt); 456 $content_xhtml = $this->core->callFormater('xhtml',$content); 457 458 if (empty($content)) { 459 throw new Exception('Cannot create an empty entry'); 460 } 461 462 $cur = $this->core->con->openCursor($this->core->prefix.'post'); 463 464 $cur->post_type = $post_type; 465 $cur->post_title = trim($title); 466 $cur->post_content = $content; 467 $cur->post_excerpt = $excerpt; 468 $cur->post_content_xhtml = $content_xhtml; 469 $cur->post_excerpt_xhtml = $excerpt_xhtml; 470 $cur->post_open_comment = (integer) ($open_comment == 1); 471 $cur->post_open_tb = (integer) ($open_tb == 1); 472 $cur->post_status = (integer) $publish; 473 $cur->post_format = 'xhtml'; 474 $cur->post_url = $post->post_url; 475 476 477 if ($dateCreated) { 478 if ($dateCreated instanceof xmlrpcDate) { 479 $cur->post_dt = date('Y-m-d H:i:00',$dateCreated->getTimestamp()); 480 } elseif (is_string($dateCreated) && @strtotime($dateCreated)) { 481 $cur->post_dt = date('Y-m-d H:i:00',strtotime($dateCreated)); 482 } 483 } else { 484 $cur->post_dt = $post->post_dt; 485 } 486 487 # Categories in an array 488 if (isset($struct['categories']) && is_array($struct['categories'])) 489 { 490 $categories = $struct['categories']; 491 $cat_id = !empty($categories[0]) ? $categories[0] : null; 492 493 $cur->cat_id = $this->getCatID($cat_id); 494 } 495 496 if (isset($struct['wp_slug'])) { 497 $cur->post_url = $struct['wp_slug']; 498 } 499 500 if (isset($struct['wp_password'])) { 501 $cur->post_password = $struct['wp_password']; 502 } 503 504 if ($cur->post_type == 'post') 505 { 506 # --BEHAVIOR-- xmlrpcBeforeEditPost 507 $this->core->callBehavior('xmlrpcBeforeEditPost',$this,$post_id,$cur,$content,$struct,$publish); 508 509 $this->core->blog->updPost($post_id,$cur); 510 511 # --BEHAVIOR-- xmlrpcAfterEditPost 512 $this->core->callBehavior('xmlrpcAfterEditPost',$this,$post_id,$cur,$content,$struct,$publish); 513 } 514 elseif ($cur->post_type == 'page') 515 { 516 if (isset($struct['wp_page_order'])) { 517 $cur->post_position = (integer) $struct['wp_page_order']; 518 } 519 520 $this->core->blog->settings->system->post_url_format = '{t}'; 521 522 $this->core->blog->updPost($post_id,$cur); 523 } 524 else 525 { 526 throw new Exception('Invalid post type',401); 527 } 528 529 return true; 530 } 531 532 private function getPost($post_id,$user,$pwd,$type='mw') 533 { 534 $post_id = (integer) $post_id; 535 536 $post = $this->getPostRS($post_id,$user,$pwd); 537 538 $res = new ArrayObject(); 539 540 $res['dateCreated'] = new xmlrpcDate($post->getTS()); 541 $res['userid'] = $post->user_id; 542 $res['postid'] = $post->post_id; 543 544 if ($post->cat_id) { 545 $res['categories'] = array($post->cat_url); 546 } 547 548 if ($type == 'blogger') { 549 $res['content'] = $post->post_content_xhtml; 550 } 551 552 if ($type == 'mt' || $type == 'mw') { 553 $res['title'] = $post->post_title; 554 } 555 556 if ($type == 'mw') { 557 $res['description'] = $post->post_content_xhtml; 558 $res['link'] = $res['permaLink'] = $post->getURL(); 559 $res['mt_excerpt'] = $post->post_excerpt_xhtml; 560 $res['mt_text_more'] = ''; 561 $res['mt_allow_comments'] = (integer) $post->post_open_comment; 562 $res['mt_allow_pings'] = (integer) $post->post_open_tb; 563 $res['mt_convert_breaks'] = ''; 564 $res['mt_keywords'] = ''; 565 } 566 567 # --BEHAVIOR-- xmlrpcGetPostInfo 568 $this->core->callBehavior('xmlrpcGetPostInfo',$this,$type,array(&$res)); 569 570 return $res; 571 } 572 573 private function deletePost($post_id,$user,$pwd) 574 { 575 $post_id = (integer) $post_id; 576 577 $this->getPostRS($post_id,$user,$pwd); 578 $this->core->blog->delPost($post_id); 579 580 return true; 581 } 582 583 private function getRecentPosts($blog_id,$user,$pwd,$nb_post,$type='mw') 584 { 585 $this->setUser($user,$pwd); 586 $this->setBlog(); 587 588 $nb_post = (integer) $nb_post; 589 590 if ($nb_post > 50) { 591 throw new Exception('Cannot retrieve more than 50 entries'); 592 } 593 594 $params = array(); 595 $params['limit'] = $nb_post; 596 597 $posts = $this->core->blog->getPosts($params); 598 599 $res = array(); 600 while ($posts->fetch()) 601 { 602 $tres = array(); 603 604 $tres['dateCreated'] = new xmlrpcDate($posts->getTS()); 605 $tres['userid'] = $posts->user_id; 606 $tres['postid'] = $posts->post_id; 607 608 if ($posts->cat_id) { 609 $tres['categories'] = array($posts->cat_url); 610 } 611 612 if ($type == 'blogger') { 613 $tres['content'] = $posts->post_content_xhtml; 614 } 615 616 if ($type == 'mt' || $type == 'mw') { 617 $tres['title'] = $posts->post_title; 618 } 619 620 if ($type == 'mw') { 621 $tres['description'] = $posts->post_content_xhtml; 622 $tres['link'] = $tres['permaLink'] = $posts->getURL(); 623 $tres['mt_excerpt'] = $posts->post_excerpt_xhtml; 624 $tres['mt_text_more'] = ''; 625 $tres['mt_allow_comments'] = (integer) $posts->post_open_comment; 626 $tres['mt_allow_pings'] = (integer) $posts->post_open_tb; 627 $tres['mt_convert_breaks'] = ''; 628 $tres['mt_keywords'] = ''; 629 } 630 631 # --BEHAVIOR-- xmlrpcGetPostInfo 632 $this->core->callBehavior('xmlrpcGetPostInfo',$this,$type,array(&$tres)); 633 634 $res[] = $tres; 635 } 636 637 return $res; 638 } 639 640 private function getUserBlogs($user,$pwd) 641 { 642 $this->setUser($user,$pwd); 643 $this->setBlog(); 644 645 return array(array( 646 'url' => $this->core->blog->url, 647 'blogid' => '1', 648 'blogName' => $this->core->blog->name 649 )); 650 } 651 652 private function getUserInfo($user,$pwd) 653 { 654 $this->setUser($user,$pwd); 655 656 return array( 657 'userid' => $this->core->auth->userID(), 658 'firstname' => $this->core->auth->getInfo('user_firstname'), 659 'lastname' => $this->core->auth->getInfo('user_name'), 660 'nickname' => $this->core->auth->getInfo('user_displayname'), 661 'email' => $this->core->auth->getInfo('user_email'), 662 'url' => $this->core->auth->getInfo('user_url') 663 ); 664 } 665 666 private function getCategories($blog_id,$user,$pwd) 667 { 668 $this->setUser($user,$pwd); 669 $this->setBlog(); 670 $rs = $this->core->blog->getCategories(); 671 672 $res = array(); 673 674 $l = $rs->level; 675 $stack = array('',$rs->cat_url); 676 677 while ($rs->fetch()) 678 { 679 $d = $rs->level - $l; 680 if ($d == 0) { 681 array_pop($stack); 682 $parent = end($stack); 683 } elseif ($d > 0) { 684 $parent = end($stack); 685 } elseif ($d < 0) { 686 $D = abs($d); 687 for ($i=0; $i<=$D; $i++) { 688 array_pop($stack); 689 } 690 $parent = end($stack); 691 } 692 693 $res[] = array( 694 'categoryId' => $rs->cat_url, 695 'parentId' => $parent, 696 'description' => $rs->cat_title, 697 'categoryName' => $rs->cat_url, 698 'htmlUrl' => $this->core->blog->url. 699 $this->core->url->getURLFor('category',$rs->cat_url), 700 'rssUrl' => $this->core->blog->url. 701 $this->core->url->getURLFor('feed','category/'.$rs->cat_url.'/rss2') 702 ); 703 704 $stack[] = $rs->cat_url; 705 $l = $rs->level; 706 } 707 708 return $res; 709 } 710 711 private function getPostCategories($post_id,$user,$pwd) 712 { 713 $post_id = (integer) $post_id; 714 715 $post = $this->getPostRS($post_id,$user,$pwd); 716 717 return array( 718 array( 719 'categoryName' => $post->cat_url, 720 'categoryId' => (string) $post->cat_url, 721 'isPrimary' => true 722 ) 723 ); 724 } 725 726 private function setPostCategories($post_id,$user,$pwd,$categories) 727 { 728 $post_id = (integer) $post_id; 729 730 $post = $this->getPostRS($post_id,$user,$pwd); 731 732 $cat_id = (!empty($categories[0]['categoryId'])) ? $categories[0]['categoryId'] : null; 733 734 foreach($categories as $v) 735 { 736 if (isset($v['isPrimary']) && $v['isPrimary']) { 737 $cat_id = $v['categoryId']; 738 break; 739 } 740 } 741 742 # w.bloggar sends -1 for no category. 743 if ($cat_id == -1) { 744 $cat_id = null; 745 } 746 747 if ($cat_id) { 748 $cat_id = $this->getCatID($cat_id); 749 } 750 751 $this->core->blog->updPostCategory($post_id,(integer) $cat_id); 752 753 return true; 754 } 755 756 private function publishPost($post_id,$user,$pwd) 757 { 758 $post_id = (integer) $post_id; 759 760 $this->getPostRS($post_id,$user,$pwd); 761 762 # --BEHAVIOR-- xmlrpcBeforePublishPost 763 $this->core->callBehavior('xmlrpcBeforePublishPost',$this,$post_id); 764 765 $this->core->blog->updPostStatus($post_id,1); 766 767 # --BEHAVIOR-- xmlrpcAfterPublishPost 768 $this->core->callBehavior('xmlrpcAfterPublishPost',$this,$post_id); 769 770 return true; 771 } 772 773 private function newMediaObject($blog_id,$user,$pwd,$file) 774 { 775 if (empty($file['name'])) { 776 throw new Exception('No file name'); 777 } 778 779 if (empty($file['bits'])) { 780 throw new Exception('No file content'); 781 } 782 783 $file_name = $file['name']; 784 $file_bits = $file['bits']; 785 786 $this->setUser($user,$pwd); 787 $this->setBlog(); 788 789 $media = new dcMedia($this->core); 790 791 $dir_name = path::clean(dirname($file_name)); 792 $file_name = basename($file_name); 793 794 $dir_name = preg_replace('!^/!','',$dir_name); 795 if ($dir_name != '') 796 { 797 $dir = explode('/',$dir_name); 798 $cwd = './'; 799 foreach ($dir as $v) 800 { 801 $v = files::tidyFileName($v); 802 $cwd .= $v.'/'; 803 $media->makeDir($v); 804 $media->chdir($cwd); 805 } 806 } 807 808 $media_id = $media->uploadBits($file_name,$file_bits); 809 810 $f = $media->getFile($media_id); 811 return array( 812 'file' => $file_name, 813 'url' => $f->file_url, 814 'type' => files::getMimeType($file_name) 815 ); 816 } 817 818 private function translateWpStatus($s) 819 { 820 $status = array( 821 'draft' => -2, 822 'pending' => -2, 823 'private' => 0, 824 'publish' => 1, 825 'scheduled' => -1 826 ); 827 828 if (is_int($s)) { 829 $status = array_flip($status); 830 return isset($status[$s]) ? $status[$s] : $status[-2]; 831 } else { 832 return isset($status[$s]) ? $status[$s] : $status['pending']; 833 } 834 } 835 836 private function translateWpCommentstatus($s) 837 { 838 $status = array( 839 'hold' => -1, 840 'approve' => 0, 841 'spam' => -2 842 ); 843 844 if (is_int($s)) { 845 $status = array_flip($status); 846 return isset($status[$s]) ? $status[$s] : $status[0]; 847 } else { 848 return isset($status[$s]) ? $status[$s] : $status['approve']; 849 } 850 } 851 852 private function translateWpOptions($options=array()) 853 { 854 $timezone = 0; 855 if ($this->core->blog->settings->system->blog_timezone) { 856 $timezone = dt::getTimeOffset($this->core->blog->settings->system->blog_timezone)/3600; 857 } 858 859 $res = array ( 860 'software_name' => array ( 861 'desc' => 'Software Name', 862 'readonly' => true, 863 'value' => 'Dotclear' 864 ), 865 'software_version' => array ( 866 'desc' => 'Software Version', 867 'readonly' => true, 868 'value' => DC_VERSION 869 ), 870 'blog_url' => array ( 871 'desc' => 'Blog URL', 872 'readonly' => true, 873 'value' => $this->core->blog->url 874 ), 875 'time_zone' => array ( 876 'desc' => 'Time Zone', 877 'readonly' => true, 878 'value' => (string) $timezone 879 ), 880 'blog_title' => array ( 881 'desc' => 'Blog Title', 882 'readonly' => false, 883 'value' => $this->core->blog->name 884 ), 885 'blog_tagline' => array ( 886 'desc' => 'Blog Tagline', 887 'readonly' => false, 888 'value' => $this->core->blog->desc 889 ), 890 'date_format' => array ( 891 'desc' => 'Date Format', 892 'readonly' => false, 893 'value' => $this->core->blog->settings->system->date_format 894 ), 895 'time_format' => array ( 896 'desc' => 'Time Format', 897 'readonly' => false, 898 'value' => $this->core->blog->settings->system->time_format 899 ) 900 ); 901 902 if (!empty($options)) 903 { 904 $r = array(); 905 foreach ($options as $v) { 906 if (isset($res[$v])) { 907 $r[$v] = $res[$v]; 908 } 909 } 910 return $r; 911 } 912 913 return $res; 914 } 915 916 private function getPostStatusList($blog_id,$user,$pwd) 917 { 918 $this->setUser($user,$pwd); 919 $this->setBlog(); 920 921 return array( 922 'draft' => 'Draft', 923 'pending' => 'Pending Review', 924 'private' => 'Private', 925 'publish' => 'Published', 926 'scheduled' => 'Scheduled' 927 ); 928 } 929 930 private function getPageStatusList($blog_id,$user,$pwd) 931 { 932 $this->setUser($user,$pwd); 933 $this->setBlog(); 934 $this->checkPagesPermission(); 935 936 return array( 937 'draft' => 'Draft', 938 'private' => 'Private', 939 'published' => 'Published', 940 'scheduled' => 'Scheduled' 941 ); 942 } 943 944 private function checkPagesPermission() 945 { 946 if (!$this->core->plugins->moduleExists('pages')) { 947 throw new Exception('Pages management is not available on this blog.'); 948 } 949 950 if (!$this->core->auth->check('pages,contentadmin',$this->core->blog->id)) { 951 throw new Exception('Not enough permissions to edit pages.',401); 952 } 953 } 954 955 private function getPages($blog_id,$user,$pwd,$limit=null,$id=null) 956 { 957 $this->setUser($user,$pwd); 958 $this->setBlog(); 959 $this->checkPagesPermission(); 960 961 $params = array( 962 'post_type' => 'page', 963 'order' => 'post_position ASC, post_title ASC' 964 ); 965 966 if ($id) { 967 $params['post_id'] = (integer) $id; 968 } 969 if ($limit) { 970 $params['limit'] = $limit; 971 } 972 973 $posts = $this->core->blog->getPosts($params); 974 975 $res = array(); 976 while ($posts->fetch()) 977 { 978 $tres = array( 979 "dateCreated" => new xmlrpcDate($posts->getTS()), 980 "userid" => $posts->user_id, 981 "page_id" => $posts->post_id, 982 "page_status" => $this->translateWpStatus((integer) $posts->post_status), 983 "description" => $posts->post_content_xhtml, 984 "title" => $posts->post_title, 985 "link" => $posts->getURL(), 986 "permaLink" => $posts->getURL(), 987 "categories" => array(), 988 "excerpt" => $posts->post_excerpt_xhtml, 989 "text_more" => '', 990 "mt_allow_comments" => (integer) $posts->post_open_comment, 991 "mt_allow_pings" => (integer) $posts->post_open_tb, 992 "wp_slug" => $posts->post_url, 993 "wp_password" => $posts->post_password, 994 "wp_author" => $posts->getAuthorCN(), 995 "wp_page_parent_id" => 0, 996 "wp_page_parent_title" => '', 997 "wp_page_order" => $posts->post_position, 998 "wp_author_id" => $posts->user_id, 999 "wp_author_display_name" => $posts->getAuthorCN(), 1000 "date_created_gmt" => new xmlrpcDate(dt::iso8601($posts->getTS(),$posts->post_tz)), 1001 "custom_fields" => array(), 1002 "wp_page_template" => 'default' 1003 ); 1004 1005 # --BEHAVIOR-- xmlrpcGetPageInfo 1006 $this->core->callBehavior('xmlrpcGetPageInfo',$this,array(&$tres)); 1007 1008 $res[] = $tres; 1009 } 1010 1011 return $res; 1012 } 1013 1014 private function newPage($blog_id,$user,$pwd,$struct,$publish) 1015 { 1016 $this->setUser($user,$pwd); 1017 $this->setBlog(); 1018 $this->checkPagesPermission(); 1019 1020 $struct['post_type'] = 'page'; 1021 1022 return $this->newPost($blog_id,$user,$pwd,null,$struct,$publish); 1023 } 1024 1025 private function editPage($page_id,$user,$pwd,$struct,$publish) 1026 { 1027 $this->setUser($user,$pwd); 1028 $this->setBlog(); 1029 $this->checkPagesPermission(); 1030 1031 $struct['post_type'] = 'page'; 1032 1033 return $this->editPost($page_id,$user,$pwd,null,$struct,$publish); 1034 } 1035 1036 private function deletePage($page_id,$user,$pwd) 1037 { 1038 $this->setUser($user,$pwd); 1039 $this->setBlog(); 1040 $this->checkPagesPermission(); 1041 1042 $page_id = (integer) $page_id; 1043 1044 $this->getPostRS($page_id,$user,$pwd,'page'); 1045 $this->core->blog->delPost($page_id); 1046 1047 return true; 1048 } 1049 1050 private function getAuthors($user,$pwd) 1051 { 1052 $this->setUser($user,$pwd); 1053 $this->setBlog(); 1054 1055 $rs = $this->core->getBlogPermissions($this->core->blog->id); 1056 $res = array(); 1057 1058 foreach($rs as $k => $v) 1059 { 1060 $res[] = array( 1061 'user_id' => $k, 1062 'user_login' => $k, 1063 'display_name' => dcUtils::getUserCN($k,$v['name'],$v['firstname'],$v['displayname']) 1064 ); 1065 } 1066 return $res; 1067 } 1068 1069 private function getTags($user,$pwd) 1070 { 1071 $this->setUser($user,$pwd); 1072 $this->setBlog(); 1073 1074 $tags = $this->core->meta->getMeta('tag'); 1075 $tags->sort('meta_id_lower','asc'); 1076 1077 $res = array(); 1078 $url = $this->core->blog->url. 1079 $this->core->url->getURLFor('tag','%s'); 1080 $f_url = $this->core->blog->url. 1081 $this->core->url->getURLFor('tag_feed','%s'); 1082 while ($tags->fetch()) 1083 { 1084 $res[] = array( 1085 'tag_id' => $tags->meta_id, 1086 'name' => $tags->meta_id, 1087 'count' => $tags->count, 1088 'slug' => $tags->meta_id, 1089 'html_url' => sprintf($url,$tags->meta_id), 1090 'rss_url' => sprintf($f_url,$tags->meta_id) 1091 ); 1092 } 1093 return $res; 1094 } 1095 1096 private function newCategory($user,$pwd,$struct) 1097 { 1098 $this->setUser($user,$pwd); 1099 $this->setBlog(); 1100 1101 if (empty($struct['name'])) { 1102 throw new Exception('You mus give a category name.'); 1103 } 1104 1105 $cur = $this->core->con->openCursor($this->core->prefix.'category'); 1106 $cur->cat_title = $struct['name']; 1107 1108 if (!empty($struct['slug'])) { 1109 $cur->cat_url = $struct['slug']; 1110 } 1111 if (!empty($struct['category_description'])) { 1112 $cur->cat_desc = $struct['category_description']; 1113 if (html::clean($cur->cat_desc) == $cur->cat_desc) { 1114 $cur->cat_desc = '<p>'.$cur->cat_desc.'</p>'; 1115 } 1116 } 1117 1118 $parent = !empty($struct['category_parent']) ? (integer) $struct['category_parent'] : 0; 1119 1120 $id = $this->core->blog->addCategory($cur,$parent); 1121 $rs = $this->core->blog->getCategory($id); 1122 return $rs->cat_url; 1123 } 1124 1125 private function deleteCategory($user,$pwd,$cat_id) 1126 { 1127 $this->setUser($user,$pwd); 1128 $this->setBlog(); 1129 1130 $c = $this->core->blog->getCategories(array('cat_url' => $cat_id)); 1131 if ($c->isEmpty()) { 1132 throw new Exception(__('This category does not exist.')); 1133 } 1134 $cat_id = $c->cat_id; 1135 unset($c); 1136 1137 $this->core->blog->delCategory((integer) $cat_id); 1138 return true; 1139 } 1140 1141 private function searchCategories($user,$pwd,$category,$limit) 1142 { 1143 $this->setUser($user,$pwd); 1144 $this->setBlog(); 1145 1146 $strReq = 'SELECT cat_id, cat_title, cat_url '. 1147 'FROM '.$this->core->prefix.'category '. 1148 "WHERE blog_id = '".$this->core->con->escape($this->core->blog->id)."' ". 1149 "AND LOWER(cat_title) LIKE LOWER('%".$this->core->con->escape($category)."%') ". 1150 ($limit > 0 ? $this->core->con->limit($limit) : ''); 1151 1152 $rs = $this->core->con->select($strReq); 1153 1154 $res = array(); 1155 while ($rs->fetch()) 1156 { 1157 $res[] = array( 1158 'category_id' => $rs->cat_url, 1159 'category_name' => $rs->cat_url 1160 ); 1161 } 1162 return $res; 1163 } 1164 1165 private function countComments($user,$pwd,$post_id) 1166 { 1167 $this->setUser($user,$pwd); 1168 $this->setBlog(); 1169 1170 $res = array( 1171 'approved' => 0, 1172 'awaiting_moderation' => 0, 1173 'spam' => 0, 1174 'total' => 0 1175 ); 1176 $rs = $this->core->blog->getComments(array('post_id' => $post_id)); 1177 1178 while ($rs->fetch()) { 1179 $res['total']++; 1180 if ($rs->comment_status == 1) { 1181 $res['approved']++; 1182 } elseif ($rs->comment_status == -2) { 1183 $res['spam']++; 1184 } else { 1185 $res['awaiting_moderation']++; 1186 } 1187 } 1188 return $res; 1189 } 1190 1191 private function getComments($user,$pwd,$struct,$id=null) 1192 { 1193 $this->setUser($user,$pwd); 1194 $this->setBlog(); 1195 1196 $params = array(); 1197 1198 if (!empty($struct['status'])) { 1199 $params['comment_status'] = $this->translateWpCommentstatus($struct['status']); 1200 } 1201 1202 if (!empty($struct['post_id'])) { 1203 $params['post_id'] = (integer) $struct['post_id']; 1204 } 1205 1206 if (isset($id)) { 1207 $params['comment_id'] = $id; 1208 } 1209 1210 $offset = !empty($struct['offset']) ? (integer) $struct['offset'] : 0; 1211 $limit = !empty($struct['number']) ? (integer) $struct['number'] : 10; 1212 $params['limit'] = array($offset,$limit); 1213 1214 $rs = $this->core->blog->getComments($params); 1215 $res = array(); 1216 while ($rs->fetch()) 1217 { 1218 $res[] = array( 1219 'date_created_gmt' => new xmlrpcDate($rs->getTS()), 1220 'user_id' => $rs->user_id, 1221 'comment_id' => $rs->comment_id, 1222 'parent' => 0, 1223 'status' => $this->translateWpCommentstatus((integer) $rs->comment_status), 1224 'content' => $rs->comment_content, 1225 'link' => $rs->getPostURL().'#c'.$rs->comment_id, 1226 'post_id' => $rs->post_id, 1227 'post_title' => $rs->post_title, 1228 'author' => $rs->comment_author, 1229 'author_url' => $rs->comment_site, 1230 'author_email' => $rs->comment_email, 1231 'author_ip' => $rs->comment_ip 1232 ); 1233 } 1234 return $res; 1235 } 1236 1237 private function addComment($user,$pwd,$post_id,$struct) 1238 { 1239 $this->setUser($user,$pwd); 1240 $this->setBlog(); 1241 1242 if (empty($struct['content'])) { 1243 throw new Exception('Sorry, you cannot post an empty comment',401); 1244 } 1245 1246 if (is_numeric($post_id)) { 1247 $p['post_id'] = $post_id; 1248 } else { 1249 $p['post_url'] = $post_id; 1250 } 1251 $rs = $this->core->blog->getPosts($p); 1252 if ($rs->isEmpty()) { 1253 throw new Exception('Sorry, no such post.',404); 1254 } 1255 1256 $cur = $this->core->con->openCursor($this->core->prefix.'comment'); 1257 1258 $cur->comment_author = $this->core->auth->getInfo('user_cn'); 1259 $cur->comment_email = $this->core->auth->getInfo('user_email'); 1260 $cur->comment_site = $this->core->auth->getInfo('user_url'); 1261 1262 $cur->comment_content = $struct['content']; 1263 $cur->post_id = (integer) $post_id; 1264 1265 $id = $this->core->blog->addComment($cur); 1266 return $id; 1267 } 1268 1269 private function updComment($user,$pwd,$comment_id,$struct) 1270 { 1271 $this->setUser($user,$pwd); 1272 $this->setBlog(); 1273 1274 $cur = $this->core->con->openCursor($this->core->prefix.'comment'); 1275 1276 if (isset($struct['status'])) { 1277 $cur->comment_status = $this->translateWpCommentstatus($struct['status']); 1278 } 1279 1280 if (isset($struct['date_created_gmt'])) { 1281 if ($struct['date_created_gmt'] instanceof xmlrpcDate) { 1282 $cur->comment_dt = date('Y-m-d H:i:00',$struct['date_created_gmt']->getTimestamp()); 1283 } elseif (is_string($struct['date_created_gmt']) && @strtotime($struct['date_created_gmt'])) { 1284 $cur->comment_dt = date('Y-m-d H:i:00',strtotime($struct['date_created_gmt'])); 1285 } 1286 $cur->comment_dt = $struct['date_created_gmt']; 1287 } 1288 1289 if (isset($struct['content'])) { 1290 $cur->comment_content = $struct['content']; 1291 } 1292 1293 if (isset($struct['author'])) { 1294 $cur->comment_author = $struct['author']; 1295 } 1296 1297 if (isset($struct['author_url'])) { 1298 $cur->comment_site = $struct['author_url']; 1299 } 1300 1301 if (isset($struct['author_email'])) { 1302 $cur->comment_email = $struct['author_email']; 1303 } 1304 1305 $this->core->blog->updComment($comment_id,$cur); 1306 return true; 1307 } 1308 1309 private function delComment($user,$pwd,$comment_id) 1310 { 1311 $this->setUser($user,$pwd); 1312 $this->setBlog(); 1313 1314 $this->core->blog->delComment($comment_id); 1315 return true; 1316 } 1317 1318 /* Blogger methods 1319 --------------------------------------------------- */ 1320 public function blogger_newPost($appkey,$blogid,$username,$password,$content,$publish) 1321 { 1322 return $this->newPost($blogid,$username,$password,$content,array(),$publish); 1323 } 1324 1325 public function blogger_editPost($appkey,$postid,$username,$password,$content,$publish) 1326 { 1327 return $this->editPost($postid,$username,$password,$content,array(),$publish); 1328 } 1329 1330 public function blogger_getPost($appkey,$postid,$username,$password) 1331 { 1332 return $this->getPost($postid,$username,$password,'blogger'); 1333 } 1334 1335 public function blogger_deletePost($appkey,$postid,$username,$password,$publish) 1336 { 1337 return $this->deletePost($postid,$username,$password); 1338 } 1339 1340 public function blogger_getRecentPosts($appkey,$blogid,$username,$password,$numberOfPosts) 1341 { 1342 return $this->getRecentPosts($blogid,$username,$password,$numberOfPosts,'blogger'); 1343 } 1344 1345 public function blogger_getUserBlogs($appkey,$username,$password) 1346 { 1347 return $this->getUserBlogs($username,$password); 1348 } 1349 1350 public function blogger_getUserInfo($appkey,$username,$password) 1351 { 1352 return $this->getUserInfo($username,$password); 1353 } 1354 1355 1356 /* Metaweblog methods 1357 ------------------------------------------------------- */ 1358 public function mw_newPost($blogid,$username,$password,$content,$publish) 1359 { 1360 return $this->newPost($blogid,$username,$password,'',$content,$publish); 1361 } 1362 1363 public function mw_editPost($postid,$username,$password,$content,$publish) 1364 { 1365 return $this->editPost($postid,$username,$password,'',$content,$publish); 1366 } 1367 1368 public function mw_getPost($postid,$username,$password) 1369 { 1370 return $this->getPost($postid,$username,$password,'mw'); 1371 } 1372 1373 public function mw_getRecentPosts($blogid,$username,$password,$numberOfPosts) 1374 { 1375 return $this->getRecentPosts($blogid,$username,$password,$numberOfPosts,'mw'); 1376 } 1377 1378 public function mw_getCategories($blogid,$username,$password) 1379 { 1380 return $this->getCategories($blogid,$username,$password); 1381 } 1382 1383 public function mw_newMediaObject($blogid,$username,$password,$file) 1384 { 1385 return $this->newMediaObject($blogid,$username,$password,$file); 1386 } 1387 1388 /* MovableType methods 1389 --------------------------------------------------- */ 1390 public function mt_getRecentPostTitles($blogid,$username,$password,$numberOfPosts) 1391 { 1392 return $this->getRecentPosts($blogid,$username,$password,$numberOfPosts,'mt'); 1393 } 1394 1395 public function mt_getCategoryList($blogid,$username,$password) 1396 { 1397 return $this->getCategories($blogid,$username,$password); 1398 } 1399 1400 public function mt_getPostCategories($postid,$username,$password) 1401 { 1402 return $this->getPostCategories($postid,$username,$password); 1403 } 1404 1405 public function mt_setPostCategories($postid,$username,$password,$categories) 1406 { 1407 return $this->setPostCategories($postid,$username,$password,$categories); 1408 } 1409 1410 public function mt_publishPost($postid,$username,$password) 1411 { 1412 return $this->publishPost($postid,$username,$password); 1413 } 1414 1415 public function mt_supportedTextFilters() 1416 { 1417 return array(); 1418 } 1419 1420 /* WordPress methods 1421 --------------------------------------------------- */ 1422 public function wp_getUsersBlogs($username,$password) 1423 { 1424 return $this->getUserBlogs($username,$password); 1425 } 1426 1427 public function wp_getPage($blogid,$pageid,$username,$password) 1428 { 1429 $res = $this->getPages($blogid,$username,$password,null,$pageid); 1430 1431 if (empty($res)) { 1432 throw new Exception('Sorry, no such page',404); 1433 } 1434 1435 return $res[0]; 1436 } 1437 1438 public function wp_getPages($blogid,$username,$password,$num=10) 1439 { 1440 return $this->getPages($blogid,$username,$password,$num); 1441 } 1442 1443 public function wp_newPage($blogid,$username,$password,$content,$publish) 1444 { 1445 return $this->newPage($blogid,$username,$password,$content,$publish); 1446 } 1447 1448 public function wp_deletePage($blogid,$username,$password,$pageid) 1449 { 1450 return $this->deletePage($pageid,$username,$password); 1451 } 1452 1453 public function wp_editPage($blogid,$pageid,$username,$password,$content,$publish) 1454 { 1455 return $this->editPage($pageid,$username,$password,$content,$publish); 1456 } 1457 1458 public function wp_getPageList($blogid,$username,$password) 1459 { 1460 $A = $this->getPages($blogid,$username,$password); 1461 $res = array(); 1462 foreach ($A as $v) { 1463 $res[] = array( 1464 'page_id' => $v['page_id'], 1465 'page_title' => $v['title'], 1466 'page_parent_id' => $v['wp_page_parent_id'], 1467 'dateCreated' => $v['dateCreated'], 1468 'date_created_gmt' => $v['date_created_gmt'] 1469 ); 1470 } 1471 return $res; 1472 } 1473 1474 public function wp_getAuthors($blogid,$username,$password) 1475 { 1476 return $this->getAuthors($username,$password); 1477 } 1478 1479 public function wp_getCategories($blogid,$username,$password) 1480 { 1481 return $this->getCategories($blogid,$username,$password); 1482 } 1483 1484 public function wp_getTags($blogid,$username,$password) 1485 { 1486 return $this->getTags($username,$password); 1487 } 1488 1489 public function wp_newCategory($blogid,$username,$password,$content) 1490 { 1491 return $this->newCategory($username,$password,$content); 1492 } 1493 1494 public function wp_deleteCategory($blogid,$username,$password,$categoryid) 1495 { 1496 return $this->deleteCategory($username,$password,$categoryid); 1497 } 1498 1499 public function wp_suggestCategories($blogid,$username,$password,$category,$max_results=0) 1500 { 1501 return $this->searchCategories($username,$password,$category,$max_results); 1502 } 1503 1504 public function wp_uploadFile($blogid,$username,$password,$file) 1505 { 1506 return $this->newMediaObject($blogid,$username,$password,$file); 1507 } 1508 1509 public function wp_getPostStatusList($blogid,$username,$password) 1510 { 1511 return $this->getPostStatusList($blogid,$username,$password); 1512 } 1513 1514 public function wp_getPageStatusList($blogid,$username,$password) 1515 { 1516 return $this->getPostStatusList($blogid,$username,$password); 1517 } 1518 1519 public function wp_getPageTemplates($blogid,$username,$password) 1520 { 1521 return array('Default' => 'default'); 1522 } 1523 1524 public function wp_getOptions($blogid,$username,$password,$options=array()) 1525 { 1526 $this->setUser($username,$password); 1527 $this->setBlog(); 1528 1529 return $this->translateWpOptions($options); 1530 } 1531 1532 public function wp_setOptions($blogid,$username,$password,$options) 1533 { 1534 $this->setUser($username,$password); 1535 $this->setBlog(); 1536 1537 if (!$this->core->auth->check('admin',$this->core->blog->id)) { 1538 throw new Exception('Not enough permissions to edit options.',401); 1539 } 1540 1541 $opt = $this->translateWpOptions(); 1542 1543 $done = array(); 1544 $blog_changes = false; 1545 $cur = $this->core->con->openCursor($this->core->prefix.'blog'); 1546 1547 $this->core->blog->settings->addNamespace('system'); 1548 1549 foreach ($options as $name => $value) 1550 { 1551 if (!isset($opt[$name]) || $opt[$name]['readonly']) { 1552 continue; 1553 } 1554 1555 switch ($name) 1556 { 1557 case 'blog_title': 1558 $blog_changes = true; 1559 $cur->blog_name = $value; 1560 $done[] = $name; 1561 break; 1562 case 'blog_tagline': 1563 $blog_changes = true; 1564 $cur->blog_desc = $value; 1565 $done[] = $name; 1566 break; 1567 case 'date_format': 1568 $this->core->blog->settings->system->put('date_format',$value); 1569 $done[] = $name; 1570 break; 1571 case 'time_format': 1572 $this->core->blog->settings->system->put('time_format',$value); 1573 $done[] = $name; 1574 break; 1575 } 1576 } 1577 1578 if ($blog_changes) { 1579 $this->core->updBlog($this->core->blog->id,$cur); 1580 $this->core->setBlog($this->core->blog->id); 1581 } 1582 1583 return $this->translateWpOptions($done); 1584 } 1585 1586 public function wp_getComment($blogid,$username,$password,$commentid) 1587 { 1588 $res = $this->getComments($username,$password,array(),$commentid); 1589 1590 if (empty($res)) { 1591 throw new Exception('Sorry, no such comment',404); 1592 } 1593 1594 return $res[0]; 1595 } 1596 1597 public function wp_getCommentCount($blogid,$username,$password,$postid) 1598 { 1599 return $this->countComments($username,$password,$postid); 1600 } 1601 1602 public function wp_getComments($blogid,$username,$password,$struct) 1603 { 1604 return $this->getComments($username,$password,$struct); 1605 } 1606 1607 public function wp_deleteComment($blogid,$username,$password,$commentid) 1608 { 1609 return $this->delComment($username,$password,$commentid); 1610 } 1611 1612 public function wp_editComment($blogid,$username,$password,$commentid,$content) 1613 { 1614 return $this->updComment($username,$password,$commentid,$content); 1615 } 1616 1617 public function wp_newComment($blogid,$username,$password,$postid,$content) 1618 { 1619 return $this->addComment($username,$password,$postid,$content); 1620 } 1621 1622 public function wp_getCommentStatusList($blogid,$username,$password) 1623 { 1624 $this->setUser($username,$password); 1625 $this->setBlog(); 1626 1627 return array( 1628 'hold' => 'Unapproved', 1629 'approve' => 'Approved', 1630 'spam' => 'Spam' 1631 ); 1632 } 1633 1634 /* Pingback support 1635 --------------------------------------------------- */ 1636 public function pingback_ping($from_url, $to_url) 1637 { 1638 dcTrackback::checkURLs($from_url,$to_url); 1639 1640 $args = array('type'=>'pingback','from_url'=>$from_url,'to_url'=>$to_url); 1641 1642 # Time to get things done... 1643 $this->setBlog(true); 1644 1645 # --BEHAVIOR-- publicBeforeReceiveTrackback 1646 $this->core->callBehavior('publicBeforeReceiveTrackback',$this->core,$args); 1647 1648 $tb = new dcTrackback($this->core); 1649 return $tb->receivePingback($from_url,$to_url); 1650 } 16 public $core; 17 private $blog_id; 18 private $blog_loaded = false; 19 private $debug = false; 20 private $debug_file = '/tmp/dotclear-xmlrpc.log'; 21 private $trace_args = true; 22 private $trace_response = true; 23 24 public function __construct($core, $blog_id) 25 { 26 parent::__construct(); 27 28 $this->core = &$core; 29 $this->blog_id = $blog_id; 30 31 # Blogger methods 32 $this->addCallback('blogger.newPost', array($this, 'blogger_newPost'), 33 array('string', 'string', 'string', 'string', 'string', 'string', 'integer'), 34 'New post'); 35 36 $this->addCallback('blogger.editPost', array($this, 'blogger_editPost'), 37 array('boolean', 'string', 'string', 'string', 'string', 'string', 'integer'), 38 'Edit a post'); 39 40 $this->addCallback('blogger.getPost', array($this, 'blogger_getPost'), 41 array('struct', 'string', 'integer', 'string', 'string'), 42 'Return a posts by ID'); 43 44 $this->addCallback('blogger.deletePost', array($this, 'blogger_deletePost'), 45 array('string', 'string', 'string', 'string', 'string', 'integer'), 46 'Delete a post'); 47 48 $this->addCallback('blogger.getRecentPosts', array($this, 'blogger_getRecentPosts'), 49 array('array', 'string', 'string', 'string', 'string', 'integer'), 50 'Return a list of recent posts'); 51 52 $this->addCallback('blogger.getUsersBlogs', array($this, 'blogger_getUserBlogs'), 53 array('struct', 'string', 'string', 'string'), 54 "Return user's blog"); 55 56 $this->addCallback('blogger.getUserInfo', array($this, 'blogger_getUserInfo'), 57 array('struct', 'string', 'string', 'string'), 58 'Return User Info'); 59 60 # Metaweblog methods 61 $this->addCallback('metaWeblog.newPost', array($this, 'mw_newPost'), 62 array('string', 'string', 'string', 'string', 'struct', 'boolean'), 63 'Creates a new post, and optionnaly publishes it.'); 64 65 $this->addCallback('metaWeblog.editPost', array($this, 'mw_editPost'), 66 array('boolean', 'string', 'string', 'string', 'struct', 'boolean'), 67 'Updates information about an existing entry'); 68 69 $this->addCallback('metaWeblog.getPost', array($this, 'mw_getPost'), 70 array('struct', 'string', 'string', 'string'), 71 'Returns information about a specific post'); 72 73 $this->addCallback('metaWeblog.getRecentPosts', array($this, 'mw_getRecentPosts'), 74 array('array', 'string', 'string', 'string', 'integer'), 75 'List of most recent posts in the system'); 76 77 $this->addCallback('metaWeblog.getCategories', array($this, 'mw_getCategories'), 78 array('array', 'string', 'string', 'string'), 79 'List of all categories defined in the weblog'); 80 81 $this->addCallback('metaWeblog.newMediaObject', array($this, 'mw_newMediaObject'), 82 array('struct', 'string', 'string', 'string', 'struct'), 83 'Upload a file on the web server'); 84 85 # MovableType methods 86 $this->addCallback('mt.getRecentPostTitles', array($this, 'mt_getRecentPostTitles'), 87 array('array', 'string', 'string', 'string', 'integer'), 88 'List of most recent posts in the system'); 89 90 $this->addCallback('mt.getCategoryList', array($this, 'mt_getCategoryList'), 91 array('array', 'string', 'string', 'string'), 92 'List of all categories defined in the weblog'); 93 94 $this->addCallback('mt.getPostCategories', array($this, 'mt_getPostCategories'), 95 array('array', 'string', 'string', 'string'), 96 'List of all categories to which the post is assigned'); 97 98 $this->addCallback('mt.setPostCategories', array($this, 'mt_setPostCategories'), 99 array('boolean', 'string', 'string', 'string', 'array'), 100 'Sets the categories for a post'); 101 102 $this->addCallback('mt.publishPost', array($this, 'mt_publishPost'), 103 array('boolean', 'string', 'string', 'string'), 104 'Retrieve pings list for a post'); 105 106 $this->addCallback('mt.supportedMethods', array($this, 'listMethods'), 107 array(), 'Retrieve information about the XML-RPC methods supported by the server.'); 108 109 $this->addCallback('mt.supportedTextFilters', array($this, 'mt_supportedTextFilters'), 110 array(), 'Retrieve information about supported text filters.'); 111 112 # WordPress methods 113 $this->addCallback('wp.getUsersBlogs', array($this, 'wp_getUsersBlogs'), 114 array('array', 'string', 'string'), 115 'Retrieve the blogs of the user.'); 116 117 $this->addCallback('wp.getPage', array($this, 'wp_getPage'), 118 array('struct', 'integer', 'integer', 'string', 'string'), 119 'Get the page identified by the page ID.'); 120 121 $this->addCallback('wp.getPages', array($this, 'wp_getPages'), 122 array('array', 'integer', 'string', 'string', 'integer'), 123 'Get an array of all the pages on a blog.'); 124 125 $this->addCallback('wp.newPage', array($this, 'wp_newPage'), 126 array('integer', 'integer', 'string', 'string', 'struct', 'boolean'), 127 'Create a new page.'); 128 129 $this->addCallback('wp.deletePage', array($this, 'wp_deletePage'), 130 array('boolean', 'integer', 'string', 'string', 'integer'), 131 'Removes a page from the blog.'); 132 133 $this->addCallback('wp.editPage', array($this, 'wp_editPage'), 134 array('boolean', 'integer', 'integer', 'string', 'string', 'struct', 'boolean'), 135 'Make changes to a blog page.'); 136 137 $this->addCallback('wp.getPageList', array($this, 'wp_getPageList'), 138 array('array', 'integer', 'string', 'string'), 139 'Get an array of all the pages on a blog. Just the minimum details, lighter than wp.getPages.'); 140 141 $this->addCallback('wp.getAuthors', array($this, 'wp_getAuthors'), 142 array('array', 'integer', 'string', 'string'), 143 'Get an array of users for the blog.'); 144 145 $this->addCallback('wp.getCategories', array($this, 'wp_getCategories'), 146 array('array', 'integer', 'string', 'string'), 147 'Get an array of available categories on a blog.'); 148 149 $this->addCallback('wp.getTags', array($this, 'wp_getTags'), 150 array('array', 'integer', 'string', 'string'), 151 'Get list of all tags for the blog.'); 152 153 $this->addCallback('wp.newCategory', array($this, 'wp_newCategory'), 154 array('integer', 'integer', 'string', 'string', 'struct'), 155 'Create a new category.'); 156 157 $this->addCallback('wp.deleteCategory', array($this, 'wp_deleteCategory'), 158 array('boolean', 'integer', 'string', 'string', 'integer'), 159 'Delete a category with a given ID.'); 160 161 $this->addCallback('wp.suggestCategories', array($this, 'wp_suggestCategories'), 162 array('array', 'integer', 'string', 'string', 'string', 'integer'), 163 'Get an array of categories that start with a given string.'); 164 165 $this->addCallback('wp.uploadFile', array($this, 'wp_uploadFile'), 166 array('struct', 'integer', 'string', 'string', 'struct'), 167 'Upload a file'); 168 169 $this->addCallback('wp.getPostStatusList', array($this, 'wp_getPostStatusList'), 170 array('array', 'integer', 'string', 'string'), 171 'Retrieve all of the post statuses.'); 172 173 $this->addCallback('wp.getPageStatusList', array($this, 'wp_getPageStatusList'), 174 array('array', 'integer', 'string', 'string'), 175 'Retrieve all of the pages statuses.'); 176 177 $this->addCallback('wp.getPageTemplates', array($this, 'wp_getPageTemplates'), 178 array('struct', 'integer', 'string', 'string'), 179 'Retrieve page templates.'); 180 181 $this->addCallback('wp.getOptions', array($this, 'wp_getOptions'), 182 array('struct', 'integer', 'string', 'string', 'array'), 183 'Retrieve blog options'); 184 185 $this->addCallback('wp.setOptions', array($this, 'wp_setOptions'), 186 array('struct', 'integer', 'string', 'string', 'struct'), 187 'Update blog options'); 188 189 $this->addCallback('wp.getComment', array($this, 'wp_getComment'), 190 array('struct', 'integer', 'string', 'string', 'integer'), 191 "Gets a comment, given it's comment ID."); 192 193 $this->addCallback('wp.getCommentCount', array($this, 'wp_getCommentCount'), 194 array('array', 'integer', 'string', 'string', 'integer'), 195 'Retrieve comment count.'); 196 197 $this->addCallback('wp.getComments', array($this, 'wp_getComments'), 198 array('array', 'integer', 'string', 'string', 'struct'), 199 'Gets a set of comments for a given post.'); 200 201 $this->addCallback('wp.deleteComment', array($this, 'wp_deleteComment'), 202 array('boolean', 'integer', 'string', 'string', 'integer'), 203 'Delete a comment with given ID.'); 204 205 $this->addCallback('wp.editComment', array($this, 'wp_editComment'), 206 array('boolean', 'integer', 'string', 'string', 'integer', 'struct'), 207 'Edit a comment with given ID.'); 208 209 $this->addCallback('wp.newComment', array($this, 'wp_newComment'), 210 array('integer', 'integer', 'string', 'string', 'integer', 'struct'), 211 'Create a new comment for a given post ID.'); 212 213 $this->addCallback('wp.getCommentStatusList', array($this, 'wp_getCommentStatusList'), 214 array('array', 'integer', 'string', 'string'), 215 'Retrieve all of the comment statuses.'); 216 217 # Pingback support 218 $this->addCallback('pingback.ping', array($this, 'pingback_ping'), 219 array('string', 'string', 'string'), 220 'Notify a link to a post.'); 221 } 222 223 public function serve($data = false, $encoding = 'UTF-8') 224 { 225 parent::serve(false, $encoding); 226 } 227 228 public function call($methodname, $args) 229 { 230 try { 231 $rsp = @parent::call($methodname, $args); 232 $this->debugTrace($methodname, $args, $rsp); 233 return $rsp; 234 } catch (Exception $e) { 235 $this->debugTrace($methodname, $args, array($e->getMessage(), $e->getCode())); 236 throw $e; 237 } 238 } 239 240 private function debugTrace($methodname, $args, $rsp) 241 { 242 if (!$this->debug) { 243 return; 244 } 245 246 if (($fp = @fopen($this->debug_file, 'a')) !== false) { 247 fwrite($fp, '[' . date('r') . ']' . ' ' . $methodname); 248 249 if ($this->trace_args) { 250 fwrite($fp, "\n- args ---\n" . var_export($args, 1)); 251 } 252 253 if ($this->trace_response) { 254 fwrite($fp, "\n- response ---\n" . var_export($rsp, 1)); 255 } 256 fwrite($fp, "\n"); 257 fclose($fp); 258 } 259 } 260 261 /* Internal methods 262 --------------------------------------------------- */ 263 private function setUser($user_id, $pwd) 264 { 265 if (empty($pwd) || $this->core->auth->checkUser($user_id, $pwd) !== true) { 266 throw new Exception('Login error'); 267 } 268 269 return true; 270 } 271 272 private function setBlog($bypass = false) 273 { 274 if (!$this->blog_id) { 275 throw new Exception('No blog ID given.'); 276 } 277 278 if ($this->blog_loaded) { 279 return true; 280 } 281 282 $this->core->setBlog($this->blog_id); 283 $this->blog_loaded = true; 284 285 if (!$this->core->blog->id) { 286 $this->core->blog = null; 287 throw new Exception('Blog does not exist.'); 288 } 289 290 if (!$bypass && 291 (!$this->core->blog->settings->system->enable_xmlrpc || 292 !$this->core->auth->check('usage,contentadmin', $this->core->blog->id))) { 293 $this->core->blog = null; 294 throw new Exception('Not enough permissions on this blog.'); 295 } 296 297 foreach ($this->core->plugins->getModules() as $id => $m) { 298 $this->core->plugins->loadNsFile($id, 'xmlrpc'); 299 } 300 301 return true; 302 } 303 304 private function getPostRS($post_id, $user, $pwd, $post_type = 'post') 305 { 306 $this->setUser($user, $pwd); 307 $this->setBlog(); 308 $rs = $this->core->blog->getPosts(array( 309 'post_id' => (integer) $post_id, 310 'post_type' => $post_type 311 )); 312 313 if ($rs->isEmpty()) { 314 throw new Exception('This entry does not exist'); 315 } 316 317 return $rs; 318 } 319 320 private function getCatID($cat_url) 321 { 322 $rs = $this->core->blog->getCategories(array('cat_url' => $cat_url)); 323 324 return $rs->isEmpty() ? null : $rs->cat_id; 325 } 326 327 /* Generic methods 328 --------------------------------------------------- */ 329 private function newPost($blog_id, $user, $pwd, $content, $struct = array(), $publish = true) 330 { 331 $this->setUser($user, $pwd); 332 $this->setBlog(); 333 334 $title = !empty($struct['title']) ? $struct['title'] : ''; 335 $excerpt = !empty($struct['mt_excerpt']) ? $struct['mt_excerpt'] : ''; 336 $description = !empty($struct['description']) ? $struct['description'] : null; 337 $dateCreated = !empty($struct['dateCreated']) ? $struct['dateCreated'] : null; 338 $open_comment = isset($struct['mt_allow_comments']) ? $struct['mt_allow_comments'] : 1; 339 $open_tb = isset($struct['mt_allow_pings']) ? $struct['mt_allow_pings'] : 1; 340 341 if ($description !== null) { 342 $content = $description; 343 } 344 345 if (!$title) { 346 $title = text::cutString(html::clean($content), 25) . '...'; 347 } 348 349 $excerpt_xhtml = $this->core->callFormater('xhtml', $excerpt); 350 $content_xhtml = $this->core->callFormater('xhtml', $content); 351 352 if (empty($content)) { 353 throw new Exception('Cannot create an empty entry'); 354 } 355 356 $cur = $this->core->con->openCursor($this->core->prefix . 'post'); 357 358 $cur->user_id = $this->core->auth->userID(); 359 $cur->post_lang = $this->core->auth->getInfo('user_lang'); 360 $cur->post_title = trim($title); 361 $cur->post_content = $content; 362 $cur->post_excerpt = $excerpt; 363 $cur->post_content_xhtml = $content_xhtml; 364 $cur->post_excerpt_xhtml = $excerpt_xhtml; 365 $cur->post_open_comment = (integer) ($open_comment == 1); 366 $cur->post_open_tb = (integer) ($open_tb == 1); 367 $cur->post_status = (integer) $publish; 368 $cur->post_format = 'xhtml'; 369 370 if ($dateCreated) { 371 if ($dateCreated instanceof xmlrpcDate) { 372 $cur->post_dt = date('Y-m-d H:i:00', $dateCreated->getTimestamp()); 373 } elseif (is_string($dateCreated) && @strtotime($dateCreated)) { 374 $cur->post_dt = date('Y-m-d H:i:00', strtotime($dateCreated)); 375 } 376 } 377 378 # Categories in an array 379 if (isset($struct['categories']) && is_array($struct['categories'])) { 380 $categories = $struct['categories']; 381 $cat_id = !empty($categories[0]) ? $categories[0] : null; 382 383 $cur->cat_id = $this->getCatID($cat_id); 384 } 385 386 if (isset($struct['wp_slug'])) { 387 $cur->post_url = $struct['wp_slug']; 388 } 389 390 if (isset($struct['wp_password'])) { 391 $cur->post_password = $struct['wp_password']; 392 } 393 394 $cur->post_type = 'post'; 395 if (!empty($struct['post_type'])) { 396 $cur->post_type = $struct['post_type']; 397 } 398 399 if ($cur->post_type == 'post') { 400 # --BEHAVIOR-- xmlrpcBeforeNewPost 401 $this->core->callBehavior('xmlrpcBeforeNewPost', $this, $cur, $content, $struct, $publish); 402 403 $post_id = $this->core->blog->addPost($cur); 404 405 # --BEHAVIOR-- xmlrpcAfterNewPost 406 $this->core->callBehavior('xmlrpcAfterNewPost', $this, $post_id, $cur, $content, $struct, $publish); 407 } elseif ($cur->post_type == 'page') { 408 if (isset($struct['wp_page_order'])) { 409 $cur->post_position = (integer) $struct['wp_page_order']; 410 } 411 412 $this->core->blog->settings->system->post_url_format = '{t}'; 413 414 $post_id = $this->core->blog->addPost($cur); 415 } else { 416 throw new Exception('Invalid post type', 401); 417 } 418 419 return (string) $post_id; 420 } 421 422 private function editPost($post_id, $user, $pwd, $content, $struct = array(), $publish = true) 423 { 424 $post_id = (integer) $post_id; 425 426 $post_type = 'post'; 427 if (!empty($struct['post_type'])) { 428 $post_type = $struct['post_type']; 429 } 430 431 $post = $this->getPostRS($post_id, $user, $pwd, $post_type); 432 433 $title = (!empty($struct['title'])) ? $struct['title'] : ''; 434 $excerpt = (!empty($struct['mt_excerpt'])) ? $struct['mt_excerpt'] : ''; 435 $description = (!empty($struct['description'])) ? $struct['description'] : null; 436 $dateCreated = !empty($struct['dateCreated']) ? $struct['dateCreated'] : null; 437 $open_comment = (isset($struct['mt_allow_comments'])) ? $struct['mt_allow_comments'] : 1; 438 $open_tb = (isset($struct['mt_allow_pings'])) ? $struct['mt_allow_pings'] : 1; 439 440 if ($description !== null) { 441 $content = $description; 442 } 443 444 if (!$title) { 445 $title = text::cutString(html::clean($content), 25) . '...'; 446 } 447 448 $excerpt_xhtml = $this->core->callFormater('xhtml', $excerpt); 449 $content_xhtml = $this->core->callFormater('xhtml', $content); 450 451 if (empty($content)) { 452 throw new Exception('Cannot create an empty entry'); 453 } 454 455 $cur = $this->core->con->openCursor($this->core->prefix . 'post'); 456 457 $cur->post_type = $post_type; 458 $cur->post_title = trim($title); 459 $cur->post_content = $content; 460 $cur->post_excerpt = $excerpt; 461 $cur->post_content_xhtml = $content_xhtml; 462 $cur->post_excerpt_xhtml = $excerpt_xhtml; 463 $cur->post_open_comment = (integer) ($open_comment == 1); 464 $cur->post_open_tb = (integer) ($open_tb == 1); 465 $cur->post_status = (integer) $publish; 466 $cur->post_format = 'xhtml'; 467 $cur->post_url = $post->post_url; 468 469 if ($dateCreated) { 470 if ($dateCreated instanceof xmlrpcDate) { 471 $cur->post_dt = date('Y-m-d H:i:00', $dateCreated->getTimestamp()); 472 } elseif (is_string($dateCreated) && @strtotime($dateCreated)) { 473 $cur->post_dt = date('Y-m-d H:i:00', strtotime($dateCreated)); 474 } 475 } else { 476 $cur->post_dt = $post->post_dt; 477 } 478 479 # Categories in an array 480 if (isset($struct['categories']) && is_array($struct['categories'])) { 481 $categories = $struct['categories']; 482 $cat_id = !empty($categories[0]) ? $categories[0] : null; 483 484 $cur->cat_id = $this->getCatID($cat_id); 485 } 486 487 if (isset($struct['wp_slug'])) { 488 $cur->post_url = $struct['wp_slug']; 489 } 490 491 if (isset($struct['wp_password'])) { 492 $cur->post_password = $struct['wp_password']; 493 } 494 495 if ($cur->post_type == 'post') { 496 # --BEHAVIOR-- xmlrpcBeforeEditPost 497 $this->core->callBehavior('xmlrpcBeforeEditPost', $this, $post_id, $cur, $content, $struct, $publish); 498 499 $this->core->blog->updPost($post_id, $cur); 500 501 # --BEHAVIOR-- xmlrpcAfterEditPost 502 $this->core->callBehavior('xmlrpcAfterEditPost', $this, $post_id, $cur, $content, $struct, $publish); 503 } elseif ($cur->post_type == 'page') { 504 if (isset($struct['wp_page_order'])) { 505 $cur->post_position = (integer) $struct['wp_page_order']; 506 } 507 508 $this->core->blog->settings->system->post_url_format = '{t}'; 509 510 $this->core->blog->updPost($post_id, $cur); 511 } else { 512 throw new Exception('Invalid post type', 401); 513 } 514 515 return true; 516 } 517 518 private function getPost($post_id, $user, $pwd, $type = 'mw') 519 { 520 $post_id = (integer) $post_id; 521 522 $post = $this->getPostRS($post_id, $user, $pwd); 523 524 $res = new ArrayObject(); 525 526 $res['dateCreated'] = new xmlrpcDate($post->getTS()); 527 $res['userid'] = $post->user_id; 528 $res['postid'] = $post->post_id; 529 530 if ($post->cat_id) { 531 $res['categories'] = array($post->cat_url); 532 } 533 534 if ($type == 'blogger') { 535 $res['content'] = $post->post_content_xhtml; 536 } 537 538 if ($type == 'mt' || $type == 'mw') { 539 $res['title'] = $post->post_title; 540 } 541 542 if ($type == 'mw') { 543 $res['description'] = $post->post_content_xhtml; 544 $res['link'] = $res['permaLink'] = $post->getURL(); 545 $res['mt_excerpt'] = $post->post_excerpt_xhtml; 546 $res['mt_text_more'] = ''; 547 $res['mt_allow_comments'] = (integer) $post->post_open_comment; 548 $res['mt_allow_pings'] = (integer) $post->post_open_tb; 549 $res['mt_convert_breaks'] = ''; 550 $res['mt_keywords'] = ''; 551 } 552 553 # --BEHAVIOR-- xmlrpcGetPostInfo 554 $this->core->callBehavior('xmlrpcGetPostInfo', $this, $type, array(&$res)); 555 556 return $res; 557 } 558 559 private function deletePost($post_id, $user, $pwd) 560 { 561 $post_id = (integer) $post_id; 562 563 $this->getPostRS($post_id, $user, $pwd); 564 $this->core->blog->delPost($post_id); 565 566 return true; 567 } 568 569 private function getRecentPosts($blog_id, $user, $pwd, $nb_post, $type = 'mw') 570 { 571 $this->setUser($user, $pwd); 572 $this->setBlog(); 573 574 $nb_post = (integer) $nb_post; 575 576 if ($nb_post > 50) { 577 throw new Exception('Cannot retrieve more than 50 entries'); 578 } 579 580 $params = array(); 581 $params['limit'] = $nb_post; 582 583 $posts = $this->core->blog->getPosts($params); 584 585 $res = array(); 586 while ($posts->fetch()) { 587 $tres = array(); 588 589 $tres['dateCreated'] = new xmlrpcDate($posts->getTS()); 590 $tres['userid'] = $posts->user_id; 591 $tres['postid'] = $posts->post_id; 592 593 if ($posts->cat_id) { 594 $tres['categories'] = array($posts->cat_url); 595 } 596 597 if ($type == 'blogger') { 598 $tres['content'] = $posts->post_content_xhtml; 599 } 600 601 if ($type == 'mt' || $type == 'mw') { 602 $tres['title'] = $posts->post_title; 603 } 604 605 if ($type == 'mw') { 606 $tres['description'] = $posts->post_content_xhtml; 607 $tres['link'] = $tres['permaLink'] = $posts->getURL(); 608 $tres['mt_excerpt'] = $posts->post_excerpt_xhtml; 609 $tres['mt_text_more'] = ''; 610 $tres['mt_allow_comments'] = (integer) $posts->post_open_comment; 611 $tres['mt_allow_pings'] = (integer) $posts->post_open_tb; 612 $tres['mt_convert_breaks'] = ''; 613 $tres['mt_keywords'] = ''; 614 } 615 616 # --BEHAVIOR-- xmlrpcGetPostInfo 617 $this->core->callBehavior('xmlrpcGetPostInfo', $this, $type, array(&$tres)); 618 619 $res[] = $tres; 620 } 621 622 return $res; 623 } 624 625 private function getUserBlogs($user, $pwd) 626 { 627 $this->setUser($user, $pwd); 628 $this->setBlog(); 629 630 return array(array( 631 'url' => $this->core->blog->url, 632 'blogid' => '1', 633 'blogName' => $this->core->blog->name 634 )); 635 } 636 637 private function getUserInfo($user, $pwd) 638 { 639 $this->setUser($user, $pwd); 640 641 return array( 642 'userid' => $this->core->auth->userID(), 643 'firstname' => $this->core->auth->getInfo('user_firstname'), 644 'lastname' => $this->core->auth->getInfo('user_name'), 645 'nickname' => $this->core->auth->getInfo('user_displayname'), 646 'email' => $this->core->auth->getInfo('user_email'), 647 'url' => $this->core->auth->getInfo('user_url') 648 ); 649 } 650 651 private function getCategories($blog_id, $user, $pwd) 652 { 653 $this->setUser($user, $pwd); 654 $this->setBlog(); 655 $rs = $this->core->blog->getCategories(); 656 657 $res = array(); 658 659 $l = $rs->level; 660 $stack = array('', $rs->cat_url); 661 662 while ($rs->fetch()) { 663 $d = $rs->level - $l; 664 if ($d == 0) { 665 array_pop($stack); 666 $parent = end($stack); 667 } elseif ($d > 0) { 668 $parent = end($stack); 669 } elseif ($d < 0) { 670 $D = abs($d); 671 for ($i = 0; $i <= $D; $i++) { 672 array_pop($stack); 673 } 674 $parent = end($stack); 675 } 676 677 $res[] = array( 678 'categoryId' => $rs->cat_url, 679 'parentId' => $parent, 680 'description' => $rs->cat_title, 681 'categoryName' => $rs->cat_url, 682 'htmlUrl' => $this->core->blog->url . 683 $this->core->url->getURLFor('category', $rs->cat_url), 684 'rssUrl' => $this->core->blog->url . 685 $this->core->url->getURLFor('feed', 'category/' . $rs->cat_url . '/rss2') 686 ); 687 688 $stack[] = $rs->cat_url; 689 $l = $rs->level; 690 } 691 692 return $res; 693 } 694 695 private function getPostCategories($post_id, $user, $pwd) 696 { 697 $post_id = (integer) $post_id; 698 699 $post = $this->getPostRS($post_id, $user, $pwd); 700 701 return array( 702 array( 703 'categoryName' => $post->cat_url, 704 'categoryId' => (string) $post->cat_url, 705 'isPrimary' => true 706 ) 707 ); 708 } 709 710 private function setPostCategories($post_id, $user, $pwd, $categories) 711 { 712 $post_id = (integer) $post_id; 713 714 $post = $this->getPostRS($post_id, $user, $pwd); 715 716 $cat_id = (!empty($categories[0]['categoryId'])) ? $categories[0]['categoryId'] : null; 717 718 foreach ($categories as $v) { 719 if (isset($v['isPrimary']) && $v['isPrimary']) { 720 $cat_id = $v['categoryId']; 721 break; 722 } 723 } 724 725 # w.bloggar sends -1 for no category. 726 if ($cat_id == -1) { 727 $cat_id = null; 728 } 729 730 if ($cat_id) { 731 $cat_id = $this->getCatID($cat_id); 732 } 733 734 $this->core->blog->updPostCategory($post_id, (integer) $cat_id); 735 736 return true; 737 } 738 739 private function publishPost($post_id, $user, $pwd) 740 { 741 $post_id = (integer) $post_id; 742 743 $this->getPostRS($post_id, $user, $pwd); 744 745 # --BEHAVIOR-- xmlrpcBeforePublishPost 746 $this->core->callBehavior('xmlrpcBeforePublishPost', $this, $post_id); 747 748 $this->core->blog->updPostStatus($post_id, 1); 749 750 # --BEHAVIOR-- xmlrpcAfterPublishPost 751 $this->core->callBehavior('xmlrpcAfterPublishPost', $this, $post_id); 752 753 return true; 754 } 755 756 private function newMediaObject($blog_id, $user, $pwd, $file) 757 { 758 if (empty($file['name'])) { 759 throw new Exception('No file name'); 760 } 761 762 if (empty($file['bits'])) { 763 throw new Exception('No file content'); 764 } 765 766 $file_name = $file['name']; 767 $file_bits = $file['bits']; 768 769 $this->setUser($user, $pwd); 770 $this->setBlog(); 771 772 $media = new dcMedia($this->core); 773 774 $dir_name = path::clean(dirname($file_name)); 775 $file_name = basename($file_name); 776 777 $dir_name = preg_replace('!^/!', '', $dir_name); 778 if ($dir_name != '') { 779 $dir = explode('/', $dir_name); 780 $cwd = './'; 781 foreach ($dir as $v) { 782 $v = files::tidyFileName($v); 783 $cwd .= $v . '/'; 784 $media->makeDir($v); 785 $media->chdir($cwd); 786 } 787 } 788 789 $media_id = $media->uploadBits($file_name, $file_bits); 790 791 $f = $media->getFile($media_id); 792 return array( 793 'file' => $file_name, 794 'url' => $f->file_url, 795 'type' => files::getMimeType($file_name) 796 ); 797 } 798 799 private function translateWpStatus($s) 800 { 801 $status = array( 802 'draft' => -2, 803 'pending' => -2, 804 'private' => 0, 805 'publish' => 1, 806 'scheduled' => -1 807 ); 808 809 if (is_int($s)) { 810 $status = array_flip($status); 811 return isset($status[$s]) ? $status[$s] : $status[-2]; 812 } else { 813 return isset($status[$s]) ? $status[$s] : $status['pending']; 814 } 815 } 816 817 private function translateWpCommentstatus($s) 818 { 819 $status = array( 820 'hold' => -1, 821 'approve' => 0, 822 'spam' => -2 823 ); 824 825 if (is_int($s)) { 826 $status = array_flip($status); 827 return isset($status[$s]) ? $status[$s] : $status[0]; 828 } else { 829 return isset($status[$s]) ? $status[$s] : $status['approve']; 830 } 831 } 832 833 private function translateWpOptions($options = array()) 834 { 835 $timezone = 0; 836 if ($this->core->blog->settings->system->blog_timezone) { 837 $timezone = dt::getTimeOffset($this->core->blog->settings->system->blog_timezone) / 3600; 838 } 839 840 $res = array( 841 'software_name' => array( 842 'desc' => 'Software Name', 843 'readonly' => true, 844 'value' => 'Dotclear' 845 ), 846 'software_version' => array( 847 'desc' => 'Software Version', 848 'readonly' => true, 849 'value' => DC_VERSION 850 ), 851 'blog_url' => array( 852 'desc' => 'Blog URL', 853 'readonly' => true, 854 'value' => $this->core->blog->url 855 ), 856 'time_zone' => array( 857 'desc' => 'Time Zone', 858 'readonly' => true, 859 'value' => (string) $timezone 860 ), 861 'blog_title' => array( 862 'desc' => 'Blog Title', 863 'readonly' => false, 864 'value' => $this->core->blog->name 865 ), 866 'blog_tagline' => array( 867 'desc' => 'Blog Tagline', 868 'readonly' => false, 869 'value' => $this->core->blog->desc 870 ), 871 'date_format' => array( 872 'desc' => 'Date Format', 873 'readonly' => false, 874 'value' => $this->core->blog->settings->system->date_format 875 ), 876 'time_format' => array( 877 'desc' => 'Time Format', 878 'readonly' => false, 879 'value' => $this->core->blog->settings->system->time_format 880 ) 881 ); 882 883 if (!empty($options)) { 884 $r = array(); 885 foreach ($options as $v) { 886 if (isset($res[$v])) { 887 $r[$v] = $res[$v]; 888 } 889 } 890 return $r; 891 } 892 893 return $res; 894 } 895 896 private function getPostStatusList($blog_id, $user, $pwd) 897 { 898 $this->setUser($user, $pwd); 899 $this->setBlog(); 900 901 return array( 902 'draft' => 'Draft', 903 'pending' => 'Pending Review', 904 'private' => 'Private', 905 'publish' => 'Published', 906 'scheduled' => 'Scheduled' 907 ); 908 } 909 910 private function getPageStatusList($blog_id, $user, $pwd) 911 { 912 $this->setUser($user, $pwd); 913 $this->setBlog(); 914 $this->checkPagesPermission(); 915 916 return array( 917 'draft' => 'Draft', 918 'private' => 'Private', 919 'published' => 'Published', 920 'scheduled' => 'Scheduled' 921 ); 922 } 923 924 private function checkPagesPermission() 925 { 926 if (!$this->core->plugins->moduleExists('pages')) { 927 throw new Exception('Pages management is not available on this blog.'); 928 } 929 930 if (!$this->core->auth->check('pages,contentadmin', $this->core->blog->id)) { 931 throw new Exception('Not enough permissions to edit pages.', 401); 932 } 933 } 934 935 private function getPages($blog_id, $user, $pwd, $limit = null, $id = null) 936 { 937 $this->setUser($user, $pwd); 938 $this->setBlog(); 939 $this->checkPagesPermission(); 940 941 $params = array( 942 'post_type' => 'page', 943 'order' => 'post_position ASC, post_title ASC' 944 ); 945 946 if ($id) { 947 $params['post_id'] = (integer) $id; 948 } 949 if ($limit) { 950 $params['limit'] = $limit; 951 } 952 953 $posts = $this->core->blog->getPosts($params); 954 955 $res = array(); 956 while ($posts->fetch()) { 957 $tres = array( 958 "dateCreated" => new xmlrpcDate($posts->getTS()), 959 "userid" => $posts->user_id, 960 "page_id" => $posts->post_id, 961 "page_status" => $this->translateWpStatus((integer) $posts->post_status), 962 "description" => $posts->post_content_xhtml, 963 "title" => $posts->post_title, 964 "link" => $posts->getURL(), 965 "permaLink" => $posts->getURL(), 966 "categories" => array(), 967 "excerpt" => $posts->post_excerpt_xhtml, 968 "text_more" => '', 969 "mt_allow_comments" => (integer) $posts->post_open_comment, 970 "mt_allow_pings" => (integer) $posts->post_open_tb, 971 "wp_slug" => $posts->post_url, 972 "wp_password" => $posts->post_password, 973 "wp_author" => $posts->getAuthorCN(), 974 "wp_page_parent_id" => 0, 975 "wp_page_parent_title" => '', 976 "wp_page_order" => $posts->post_position, 977 "wp_author_id" => $posts->user_id, 978 "wp_author_display_name" => $posts->getAuthorCN(), 979 "date_created_gmt" => new xmlrpcDate(dt::iso8601($posts->getTS(), $posts->post_tz)), 980 "custom_fields" => array(), 981 "wp_page_template" => 'default' 982 ); 983 984 # --BEHAVIOR-- xmlrpcGetPageInfo 985 $this->core->callBehavior('xmlrpcGetPageInfo', $this, array(&$tres)); 986 987 $res[] = $tres; 988 } 989 990 return $res; 991 } 992 993 private function newPage($blog_id, $user, $pwd, $struct, $publish) 994 { 995 $this->setUser($user, $pwd); 996 $this->setBlog(); 997 $this->checkPagesPermission(); 998 999 $struct['post_type'] = 'page'; 1000 1001 return $this->newPost($blog_id, $user, $pwd, null, $struct, $publish); 1002 } 1003 1004 private function editPage($page_id, $user, $pwd, $struct, $publish) 1005 { 1006 $this->setUser($user, $pwd); 1007 $this->setBlog(); 1008 $this->checkPagesPermission(); 1009 1010 $struct['post_type'] = 'page'; 1011 1012 return $this->editPost($page_id, $user, $pwd, null, $struct, $publish); 1013 } 1014 1015 private function deletePage($page_id, $user, $pwd) 1016 { 1017 $this->setUser($user, $pwd); 1018 $this->setBlog(); 1019 $this->checkPagesPermission(); 1020 1021 $page_id = (integer) $page_id; 1022 1023 $this->getPostRS($page_id, $user, $pwd, 'page'); 1024 $this->core->blog->delPost($page_id); 1025 1026 return true; 1027 } 1028 1029 private function getAuthors($user, $pwd) 1030 { 1031 $this->setUser($user, $pwd); 1032 $this->setBlog(); 1033 1034 $rs = $this->core->getBlogPermissions($this->core->blog->id); 1035 $res = array(); 1036 1037 foreach ($rs as $k => $v) { 1038 $res[] = array( 1039 'user_id' => $k, 1040 'user_login' => $k, 1041 'display_name' => dcUtils::getUserCN($k, $v['name'], $v['firstname'], $v['displayname']) 1042 ); 1043 } 1044 return $res; 1045 } 1046 1047 private function getTags($user, $pwd) 1048 { 1049 $this->setUser($user, $pwd); 1050 $this->setBlog(); 1051 1052 $tags = $this->core->meta->getMeta('tag'); 1053 $tags->sort('meta_id_lower', 'asc'); 1054 1055 $res = array(); 1056 $url = $this->core->blog->url . 1057 $this->core->url->getURLFor('tag', '%s'); 1058 $f_url = $this->core->blog->url . 1059 $this->core->url->getURLFor('tag_feed', '%s'); 1060 while ($tags->fetch()) { 1061 $res[] = array( 1062 'tag_id' => $tags->meta_id, 1063 'name' => $tags->meta_id, 1064 'count' => $tags->count, 1065 'slug' => $tags->meta_id, 1066 'html_url' => sprintf($url, $tags->meta_id), 1067 'rss_url' => sprintf($f_url, $tags->meta_id) 1068 ); 1069 } 1070 return $res; 1071 } 1072 1073 private function newCategory($user, $pwd, $struct) 1074 { 1075 $this->setUser($user, $pwd); 1076 $this->setBlog(); 1077 1078 if (empty($struct['name'])) { 1079 throw new Exception('You mus give a category name.'); 1080 } 1081 1082 $cur = $this->core->con->openCursor($this->core->prefix . 'category'); 1083 $cur->cat_title = $struct['name']; 1084 1085 if (!empty($struct['slug'])) { 1086 $cur->cat_url = $struct['slug']; 1087 } 1088 if (!empty($struct['category_description'])) { 1089 $cur->cat_desc = $struct['category_description']; 1090 if (html::clean($cur->cat_desc) == $cur->cat_desc) { 1091 $cur->cat_desc = '<p>' . $cur->cat_desc . '</p>'; 1092 } 1093 } 1094 1095 $parent = !empty($struct['category_parent']) ? (integer) $struct['category_parent'] : 0; 1096 1097 $id = $this->core->blog->addCategory($cur, $parent); 1098 $rs = $this->core->blog->getCategory($id); 1099 return $rs->cat_url; 1100 } 1101 1102 private function deleteCategory($user, $pwd, $cat_id) 1103 { 1104 $this->setUser($user, $pwd); 1105 $this->setBlog(); 1106 1107 $c = $this->core->blog->getCategories(array('cat_url' => $cat_id)); 1108 if ($c->isEmpty()) { 1109 throw new Exception(__('This category does not exist.')); 1110 } 1111 $cat_id = $c->cat_id; 1112 unset($c); 1113 1114 $this->core->blog->delCategory((integer) $cat_id); 1115 return true; 1116 } 1117 1118 private function searchCategories($user, $pwd, $category, $limit) 1119 { 1120 $this->setUser($user, $pwd); 1121 $this->setBlog(); 1122 1123 $strReq = 'SELECT cat_id, cat_title, cat_url ' . 1124 'FROM ' . $this->core->prefix . 'category ' . 1125 "WHERE blog_id = '" . $this->core->con->escape($this->core->blog->id) . "' " . 1126 "AND LOWER(cat_title) LIKE LOWER('%" . $this->core->con->escape($category) . "%') " . 1127 ($limit > 0 ? $this->core->con->limit($limit) : ''); 1128 1129 $rs = $this->core->con->select($strReq); 1130 1131 $res = array(); 1132 while ($rs->fetch()) { 1133 $res[] = array( 1134 'category_id' => $rs->cat_url, 1135 'category_name' => $rs->cat_url 1136 ); 1137 } 1138 return $res; 1139 } 1140 1141 private function countComments($user, $pwd, $post_id) 1142 { 1143 $this->setUser($user, $pwd); 1144 $this->setBlog(); 1145 1146 $res = array( 1147 'approved' => 0, 1148 'awaiting_moderation' => 0, 1149 'spam' => 0, 1150 'total' => 0 1151 ); 1152 $rs = $this->core->blog->getComments(array('post_id' => $post_id)); 1153 1154 while ($rs->fetch()) { 1155 $res['total']++; 1156 if ($rs->comment_status == 1) { 1157 $res['approved']++; 1158 } elseif ($rs->comment_status == -2) { 1159 $res['spam']++; 1160 } else { 1161 $res['awaiting_moderation']++; 1162 } 1163 } 1164 return $res; 1165 } 1166 1167 private function getComments($user, $pwd, $struct, $id = null) 1168 { 1169 $this->setUser($user, $pwd); 1170 $this->setBlog(); 1171 1172 $params = array(); 1173 1174 if (!empty($struct['status'])) { 1175 $params['comment_status'] = $this->translateWpCommentstatus($struct['status']); 1176 } 1177 1178 if (!empty($struct['post_id'])) { 1179 $params['post_id'] = (integer) $struct['post_id']; 1180 } 1181 1182 if (isset($id)) { 1183 $params['comment_id'] = $id; 1184 } 1185 1186 $offset = !empty($struct['offset']) ? (integer) $struct['offset'] : 0; 1187 $limit = !empty($struct['number']) ? (integer) $struct['number'] : 10; 1188 $params['limit'] = array($offset, $limit); 1189 1190 $rs = $this->core->blog->getComments($params); 1191 $res = array(); 1192 while ($rs->fetch()) { 1193 $res[] = array( 1194 'date_created_gmt' => new xmlrpcDate($rs->getTS()), 1195 'user_id' => $rs->user_id, 1196 'comment_id' => $rs->comment_id, 1197 'parent' => 0, 1198 'status' => $this->translateWpCommentstatus((integer) $rs->comment_status), 1199 'content' => $rs->comment_content, 1200 'link' => $rs->getPostURL() . '#c' . $rs->comment_id, 1201 'post_id' => $rs->post_id, 1202 'post_title' => $rs->post_title, 1203 'author' => $rs->comment_author, 1204 'author_url' => $rs->comment_site, 1205 'author_email' => $rs->comment_email, 1206 'author_ip' => $rs->comment_ip 1207 ); 1208 } 1209 return $res; 1210 } 1211 1212 private function addComment($user, $pwd, $post_id, $struct) 1213 { 1214 $this->setUser($user, $pwd); 1215 $this->setBlog(); 1216 1217 if (empty($struct['content'])) { 1218 throw new Exception('Sorry, you cannot post an empty comment', 401); 1219 } 1220 1221 if (is_numeric($post_id)) { 1222 $p['post_id'] = $post_id; 1223 } else { 1224 $p['post_url'] = $post_id; 1225 } 1226 $rs = $this->core->blog->getPosts($p); 1227 if ($rs->isEmpty()) { 1228 throw new Exception('Sorry, no such post.', 404); 1229 } 1230 1231 $cur = $this->core->con->openCursor($this->core->prefix . 'comment'); 1232 1233 $cur->comment_author = $this->core->auth->getInfo('user_cn'); 1234 $cur->comment_email = $this->core->auth->getInfo('user_email'); 1235 $cur->comment_site = $this->core->auth->getInfo('user_url'); 1236 1237 $cur->comment_content = $struct['content']; 1238 $cur->post_id = (integer) $post_id; 1239 1240 $id = $this->core->blog->addComment($cur); 1241 return $id; 1242 } 1243 1244 private function updComment($user, $pwd, $comment_id, $struct) 1245 { 1246 $this->setUser($user, $pwd); 1247 $this->setBlog(); 1248 1249 $cur = $this->core->con->openCursor($this->core->prefix . 'comment'); 1250 1251 if (isset($struct['status'])) { 1252 $cur->comment_status = $this->translateWpCommentstatus($struct['status']); 1253 } 1254 1255 if (isset($struct['date_created_gmt'])) { 1256 if ($struct['date_created_gmt'] instanceof xmlrpcDate) { 1257 $cur->comment_dt = date('Y-m-d H:i:00', $struct['date_created_gmt']->getTimestamp()); 1258 } elseif (is_string($struct['date_created_gmt']) && @strtotime($struct['date_created_gmt'])) { 1259 $cur->comment_dt = date('Y-m-d H:i:00', strtotime($struct['date_created_gmt'])); 1260 } 1261 $cur->comment_dt = $struct['date_created_gmt']; 1262 } 1263 1264 if (isset($struct['content'])) { 1265 $cur->comment_content = $struct['content']; 1266 } 1267 1268 if (isset($struct['author'])) { 1269 $cur->comment_author = $struct['author']; 1270 } 1271 1272 if (isset($struct['author_url'])) { 1273 $cur->comment_site = $struct['author_url']; 1274 } 1275 1276 if (isset($struct['author_email'])) { 1277 $cur->comment_email = $struct['author_email']; 1278 } 1279 1280 $this->core->blog->updComment($comment_id, $cur); 1281 return true; 1282 } 1283 1284 private function delComment($user, $pwd, $comment_id) 1285 { 1286 $this->setUser($user, $pwd); 1287 $this->setBlog(); 1288 1289 $this->core->blog->delComment($comment_id); 1290 return true; 1291 } 1292 1293 /* Blogger methods 1294 --------------------------------------------------- */ 1295 public function blogger_newPost($appkey, $blogid, $username, $password, $content, $publish) 1296 { 1297 return $this->newPost($blogid, $username, $password, $content, array(), $publish); 1298 } 1299 1300 public function blogger_editPost($appkey, $postid, $username, $password, $content, $publish) 1301 { 1302 return $this->editPost($postid, $username, $password, $content, array(), $publish); 1303 } 1304 1305 public function blogger_getPost($appkey, $postid, $username, $password) 1306 { 1307 return $this->getPost($postid, $username, $password, 'blogger'); 1308 } 1309 1310 public function blogger_deletePost($appkey, $postid, $username, $password, $publish) 1311 { 1312 return $this->deletePost($postid, $username, $password); 1313 } 1314 1315 public function blogger_getRecentPosts($appkey, $blogid, $username, $password, $numberOfPosts) 1316 { 1317 return $this->getRecentPosts($blogid, $username, $password, $numberOfPosts, 'blogger'); 1318 } 1319 1320 public function blogger_getUserBlogs($appkey, $username, $password) 1321 { 1322 return $this->getUserBlogs($username, $password); 1323 } 1324 1325 public function blogger_getUserInfo($appkey, $username, $password) 1326 { 1327 return $this->getUserInfo($username, $password); 1328 } 1329 1330 /* Metaweblog methods 1331 ------------------------------------------------------- */ 1332 public function mw_newPost($blogid, $username, $password, $content, $publish) 1333 { 1334 return $this->newPost($blogid, $username, $password, '', $content, $publish); 1335 } 1336 1337 public function mw_editPost($postid, $username, $password, $content, $publish) 1338 { 1339 return $this->editPost($postid, $username, $password, '', $content, $publish); 1340 } 1341 1342 public function mw_getPost($postid, $username, $password) 1343 { 1344 return $this->getPost($postid, $username, $password, 'mw'); 1345 } 1346 1347 public function mw_getRecentPosts($blogid, $username, $password, $numberOfPosts) 1348 { 1349 return $this->getRecentPosts($blogid, $username, $password, $numberOfPosts, 'mw'); 1350 } 1351 1352 public function mw_getCategories($blogid, $username, $password) 1353 { 1354 return $this->getCategories($blogid, $username, $password); 1355 } 1356 1357 public function mw_newMediaObject($blogid, $username, $password, $file) 1358 { 1359 return $this->newMediaObject($blogid, $username, $password, $file); 1360 } 1361 1362 /* MovableType methods 1363 --------------------------------------------------- */ 1364 public function mt_getRecentPostTitles($blogid, $username, $password, $numberOfPosts) 1365 { 1366 return $this->getRecentPosts($blogid, $username, $password, $numberOfPosts, 'mt'); 1367 } 1368 1369 public function mt_getCategoryList($blogid, $username, $password) 1370 { 1371 return $this->getCategories($blogid, $username, $password); 1372 } 1373 1374 public function mt_getPostCategories($postid, $username, $password) 1375 { 1376 return $this->getPostCategories($postid, $username, $password); 1377 } 1378 1379 public function mt_setPostCategories($postid, $username, $password, $categories) 1380 { 1381 return $this->setPostCategories($postid, $username, $password, $categories); 1382 } 1383 1384 public function mt_publishPost($postid, $username, $password) 1385 { 1386 return $this->publishPost($postid, $username, $password); 1387 } 1388 1389 public function mt_supportedTextFilters() 1390 { 1391 return array(); 1392 } 1393 1394 /* WordPress methods 1395 --------------------------------------------------- */ 1396 public function wp_getUsersBlogs($username, $password) 1397 { 1398 return $this->getUserBlogs($username, $password); 1399 } 1400 1401 public function wp_getPage($blogid, $pageid, $username, $password) 1402 { 1403 $res = $this->getPages($blogid, $username, $password, null, $pageid); 1404 1405 if (empty($res)) { 1406 throw new Exception('Sorry, no such page', 404); 1407 } 1408 1409 return $res[0]; 1410 } 1411 1412 public function wp_getPages($blogid, $username, $password, $num = 10) 1413 { 1414 return $this->getPages($blogid, $username, $password, $num); 1415 } 1416 1417 public function wp_newPage($blogid, $username, $password, $content, $publish) 1418 { 1419 return $this->newPage($blogid, $username, $password, $content, $publish); 1420 } 1421 1422 public function wp_deletePage($blogid, $username, $password, $pageid) 1423 { 1424 return $this->deletePage($pageid, $username, $password); 1425 } 1426 1427 public function wp_editPage($blogid, $pageid, $username, $password, $content, $publish) 1428 { 1429 return $this->editPage($pageid, $username, $password, $content, $publish); 1430 } 1431 1432 public function wp_getPageList($blogid, $username, $password) 1433 { 1434 $A = $this->getPages($blogid, $username, $password); 1435 $res = array(); 1436 foreach ($A as $v) { 1437 $res[] = array( 1438 'page_id' => $v['page_id'], 1439 'page_title' => $v['title'], 1440 'page_parent_id' => $v['wp_page_parent_id'], 1441 'dateCreated' => $v['dateCreated'], 1442 'date_created_gmt' => $v['date_created_gmt'] 1443 ); 1444 } 1445 return $res; 1446 } 1447 1448 public function wp_getAuthors($blogid, $username, $password) 1449 { 1450 return $this->getAuthors($username, $password); 1451 } 1452 1453 public function wp_getCategories($blogid, $username, $password) 1454 { 1455 return $this->getCategories($blogid, $username, $password); 1456 } 1457 1458 public function wp_getTags($blogid, $username, $password) 1459 { 1460 return $this->getTags($username, $password); 1461 } 1462 1463 public function wp_newCategory($blogid, $username, $password, $content) 1464 { 1465 return $this->newCategory($username, $password, $content); 1466 } 1467 1468 public function wp_deleteCategory($blogid, $username, $password, $categoryid) 1469 { 1470 return $this->deleteCategory($username, $password, $categoryid); 1471 } 1472 1473 public function wp_suggestCategories($blogid, $username, $password, $category, $max_results = 0) 1474 { 1475 return $this->searchCategories($username, $password, $category, $max_results); 1476 } 1477 1478 public function wp_uploadFile($blogid, $username, $password, $file) 1479 { 1480 return $this->newMediaObject($blogid, $username, $password, $file); 1481 } 1482 1483 public function wp_getPostStatusList($blogid, $username, $password) 1484 { 1485 return $this->getPostStatusList($blogid, $username, $password); 1486 } 1487 1488 public function wp_getPageStatusList($blogid, $username, $password) 1489 { 1490 return $this->getPostStatusList($blogid, $username, $password); 1491 } 1492 1493 public function wp_getPageTemplates($blogid, $username, $password) 1494 { 1495 return array('Default' => 'default'); 1496 } 1497 1498 public function wp_getOptions($blogid, $username, $password, $options = array()) 1499 { 1500 $this->setUser($username, $password); 1501 $this->setBlog(); 1502 1503 return $this->translateWpOptions($options); 1504 } 1505 1506 public function wp_setOptions($blogid, $username, $password, $options) 1507 { 1508 $this->setUser($username, $password); 1509 $this->setBlog(); 1510 1511 if (!$this->core->auth->check('admin', $this->core->blog->id)) { 1512 throw new Exception('Not enough permissions to edit options.', 401); 1513 } 1514 1515 $opt = $this->translateWpOptions(); 1516 1517 $done = array(); 1518 $blog_changes = false; 1519 $cur = $this->core->con->openCursor($this->core->prefix . 'blog'); 1520 1521 $this->core->blog->settings->addNamespace('system'); 1522 1523 foreach ($options as $name => $value) { 1524 if (!isset($opt[$name]) || $opt[$name]['readonly']) { 1525 continue; 1526 } 1527 1528 switch ($name) { 1529 case 'blog_title': 1530 $blog_changes = true; 1531 $cur->blog_name = $value; 1532 $done[] = $name; 1533 break; 1534 case 'blog_tagline': 1535 $blog_changes = true; 1536 $cur->blog_desc = $value; 1537 $done[] = $name; 1538 break; 1539 case 'date_format': 1540 $this->core->blog->settings->system->put('date_format', $value); 1541 $done[] = $name; 1542 break; 1543 case 'time_format': 1544 $this->core->blog->settings->system->put('time_format', $value); 1545 $done[] = $name; 1546 break; 1547 } 1548 } 1549 1550 if ($blog_changes) { 1551 $this->core->updBlog($this->core->blog->id, $cur); 1552 $this->core->setBlog($this->core->blog->id); 1553 } 1554 1555 return $this->translateWpOptions($done); 1556 } 1557 1558 public function wp_getComment($blogid, $username, $password, $commentid) 1559 { 1560 $res = $this->getComments($username, $password, array(), $commentid); 1561 1562 if (empty($res)) { 1563 throw new Exception('Sorry, no such comment', 404); 1564 } 1565 1566 return $res[0]; 1567 } 1568 1569 public function wp_getCommentCount($blogid, $username, $password, $postid) 1570 { 1571 return $this->countComments($username, $password, $postid); 1572 } 1573 1574 public function wp_getComments($blogid, $username, $password, $struct) 1575 { 1576 return $this->getComments($username, $password, $struct); 1577 } 1578 1579 public function wp_deleteComment($blogid, $username, $password, $commentid) 1580 { 1581 return $this->delComment($username, $password, $commentid); 1582 } 1583 1584 public function wp_editComment($blogid, $username, $password, $commentid, $content) 1585 { 1586 return $this->updComment($username, $password, $commentid, $content); 1587 } 1588 1589 public function wp_newComment($blogid, $username, $password, $postid, $content) 1590 { 1591 return $this->addComment($username, $password, $postid, $content); 1592 } 1593 1594 public function wp_getCommentStatusList($blogid, $username, $password) 1595 { 1596 $this->setUser($username, $password); 1597 $this->setBlog(); 1598 1599 return array( 1600 'hold' => 'Unapproved', 1601 'approve' => 'Approved', 1602 'spam' => 'Spam' 1603 ); 1604 } 1605 1606 /* Pingback support 1607 --------------------------------------------------- */ 1608 public function pingback_ping($from_url, $to_url) 1609 { 1610 dcTrackback::checkURLs($from_url, $to_url); 1611 1612 $args = array('type' => 'pingback', 'from_url' => $from_url, 'to_url' => $to_url); 1613 1614 # Time to get things done... 1615 $this->setBlog(true); 1616 1617 # --BEHAVIOR-- publicBeforeReceiveTrackback 1618 $this->core->callBehavior('publicBeforeReceiveTrackback', $this->core, $args); 1619 1620 $tb = new dcTrackback($this->core); 1621 return $tb->receivePingback($from_url, $to_url); 1622 } 1651 1623 }
Note: See TracChangeset
for help on using the changeset viewer.