From 4beea9e8c08ac3b70427a90e53d9c208e92cbe94 Mon Sep 17 00:00:00 2001 From: Sam Minnee Date: Sat, 24 Mar 2012 16:27:03 +1300 Subject: [PATCH 01/10] BUGFIX: Don't rely on existence of SiteTree::PageComments. --- code/BlogEntry.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/BlogEntry.php b/code/BlogEntry.php index 862b07c..a17acd8 100644 --- a/code/BlogEntry.php +++ b/code/BlogEntry.php @@ -270,7 +270,7 @@ class BlogEntry_Controller extends Page_Controller { */ function PageComments() { if($this->hasMethod('CommentsForm')) return $this->CommentsForm(); - else return parent::PageComments(); + else if(method_exists('Page_Controller', 'PageComments')) return parent::PageComments(); } } From 5d1ac0961e227b35496644ea2ed69e5cd6c8ff4f Mon Sep 17 00:00:00 2001 From: Sam Minnee Date: Sat, 24 Mar 2012 16:27:49 +1300 Subject: [PATCH 02/10] BUGFIX: Removed use of deprecated toDropdownMap(). --- code/BlogHolder.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/BlogHolder.php b/code/BlogHolder.php index b50d830..b17d737 100644 --- a/code/BlogHolder.php +++ b/code/BlogHolder.php @@ -35,7 +35,7 @@ class BlogHolder extends BlogTree implements PermissionProvider { SiteTree::enableCMSFieldsExtensions(); $fields->addFieldToTab('Root.Content.Main', new CheckboxField('TrackBacksEnabled', 'Enable TrackBacks')); - $fields->addFieldToTab('Root.Content.Main', new DropdownField('OwnerID', 'Blog owner', $blogOwners->toDropDownMap('ID', 'Name', 'None'))); + $fields->addFieldToTab('Root.Content.Main', new DropdownField('OwnerID', 'Blog owner', array_merge(array('' => "(None)"), $blogOwners->map('ID', 'Name')) )); $fields->addFieldToTab('Root.Content.Main', new CheckboxField('AllowCustomAuthors', 'Allow non-admins to have a custom author field')); $this->extend('updateCMSFields', $fields); From 3f3a84df8ec68ce758d0b267100c33e70023315c Mon Sep 17 00:00:00 2001 From: Sam Minnee Date: Sat, 24 Mar 2012 16:28:13 +1300 Subject: [PATCH 03/10] BUGFIX: Refactored bbcodehelp.js to use entwine. --- javascript/bbcodehelp.js | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/javascript/bbcodehelp.js b/javascript/bbcodehelp.js index a035b0f..7945dcf 100644 --- a/javascript/bbcodehelp.js +++ b/javascript/bbcodehelp.js @@ -1,12 +1,11 @@ -Behaviour.register({ - '#BBCodeHint': { +(function($) { +$.entwine('ss', function($){ + + $('#BBCodeHint').entwine({ onclick: function() { - if($('BBTagsHolder').style.display == "none") { - Effect.BlindDown('BBTagsHolder'); - } else{ - Effect.BlindUp('BBTagsHolder'); - } - return false; + $('#BBTagsHolder').toggle(); } - } + }); + }); +}(jQuery)); \ No newline at end of file From c574d122269e88d9217869a00a3ead9f9cd0e678 Mon Sep 17 00:00:00 2001 From: Sam Minnee Date: Sat, 24 Mar 2012 16:31:00 +1300 Subject: [PATCH 04/10] BUGFIX: Removed use of subtabs, to be compatible with SS3. --- code/BlogHolder.php | 6 +++--- code/BlogTree.php | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/code/BlogHolder.php b/code/BlogHolder.php index b17d737..025dc17 100644 --- a/code/BlogHolder.php +++ b/code/BlogHolder.php @@ -34,9 +34,9 @@ class BlogHolder extends BlogTree implements PermissionProvider { $fields = parent::getCMSFields(); SiteTree::enableCMSFieldsExtensions(); - $fields->addFieldToTab('Root.Content.Main', new CheckboxField('TrackBacksEnabled', 'Enable TrackBacks')); - $fields->addFieldToTab('Root.Content.Main', new DropdownField('OwnerID', 'Blog owner', array_merge(array('' => "(None)"), $blogOwners->map('ID', 'Name')) )); - $fields->addFieldToTab('Root.Content.Main', new CheckboxField('AllowCustomAuthors', 'Allow non-admins to have a custom author field')); + $fields->addFieldToTab('Root.Main', new CheckboxField('TrackBacksEnabled', 'Enable TrackBacks')); + $fields->addFieldToTab('Root.Main', new DropdownField('OwnerID', 'Blog owner', array_merge(array('' => "(None)"), $blogOwners->map('ID', 'Name')) )); + $fields->addFieldToTab('Root.Main', new CheckboxField('AllowCustomAuthors', 'Allow non-admins to have a custom author field')); $this->extend('updateCMSFields', $fields); diff --git a/code/BlogTree.php b/code/BlogTree.php index 758d828..40655fc 100644 --- a/code/BlogTree.php +++ b/code/BlogTree.php @@ -95,8 +95,8 @@ class BlogTree extends Page { function getCMSFields() { $fields = parent::getCMSFields(); - $fields->addFieldToTab("Root.Content.Main", new TextField("Name", "Name of blog")); - $fields->addFieldToTab('Root.Content.Main', new DropdownField('LandingPageFreshness', 'When you first open the blog, how many entries should I show', array( + $fields->addFieldToTab("Root.Main", new TextField("Name", "Name of blog")); + $fields->addFieldToTab('Root.Main', new DropdownField('LandingPageFreshness', 'When you first open the blog, how many entries should I show', array( "" => "All entries", "1 MONTH" => "Last month's entries", "2 MONTH" => "Last 2 months' entries", @@ -113,8 +113,8 @@ class BlogTree extends Page { "INHERIT" => "Take value from parent Blog Tree" ))); - $fields->addFieldToTab("Root.Content.Widgets", new CheckboxField("InheritSideBar", 'Inherit Sidebar From Parent')); - $fields->addFieldToTab("Root.Content.Widgets", new WidgetAreaEditor("SideBar")); + $fields->addFieldToTab("Root.Widgets", new CheckboxField("InheritSideBar", 'Inherit Sidebar From Parent')); + $fields->addFieldToTab("Root.Widgets", new WidgetAreaEditor("SideBar")); return $fields; } From c723c3398a55149d26c6349d8a0c2f714fc5ab27 Mon Sep 17 00:00:00 2001 From: carlos barberis Date: Sat, 19 May 2012 14:26:55 +1200 Subject: [PATCH 05/10] ENHANCEMENT: make blog module compatible with SS3 --- code/BlogEntry.php | 16 +++---- code/BlogHolder.php | 24 +++++----- code/TrackBackDecorator.php | 65 ++++++++++++++------------- code/TrackBackURL.php | 2 +- code/widgets/ArchiveWidget.php | 2 +- code/widgets/BlogManagementWidget.php | 3 +- code/widgets/RSSWidget.php | 2 +- code/widgets/TagCloudWidget.php | 6 +-- tests/BlogHolderFunctionalTest.php | 2 +- tests/BlogHolderTest.php | 5 ++- tests/BlogTrackbackTest.php | 5 ++- tests/BlogTreeTest.php | 4 +- 12 files changed, 70 insertions(+), 66 deletions(-) diff --git a/code/BlogEntry.php b/code/BlogEntry.php index a17acd8..736c4cd 100644 --- a/code/BlogEntry.php +++ b/code/BlogEntry.php @@ -61,22 +61,22 @@ class BlogEntry extends Page { SiteTree::enableCMSFieldsExtensions(); if(!self::$allow_wysiwyg_editing) { - $fields->removeFieldFromTab("Root.Content.Main","Content"); - $fields->addFieldToTab("Root.Content.Main", new TextareaField("Content", _t("BlogEntry.CN", "Content"), 20)); + $fields->removeFieldFromTab("Root.Main","Content"); + $fields->addFieldToTab("Root.Main", new TextareaField("Content", _t("BlogEntry.CN", "Content"), 20)); } - $fields->addFieldToTab("Root.Content.Main", $dateField = new DatetimeField("Date", _t("BlogEntry.DT", "Date")),"Content"); + $fields->addFieldToTab("Root.Main", $dateField = new DatetimeField("Date", _t("BlogEntry.DT", "Date")),"Content"); $dateField->getDateField()->setConfig('showcalendar', true); $dateField->getTimeField()->setConfig('showdropdown', true); - $fields->addFieldToTab("Root.Content.Main", new TextField("Author", _t("BlogEntry.AU", "Author"), $firstName),"Content"); + $fields->addFieldToTab("Root.Main", new TextField("Author", _t("BlogEntry.AU", "Author"), $firstName),"Content"); if(!self::$allow_wysiwyg_editing) { - $fields->addFieldToTab("Root.Content.Main", new LiteralField("BBCodeHelper", "
" . + $fields->addFieldToTab("Root.Main", new LiteralField("BBCodeHelper", "
" . "" . _t("BlogEntry.BBH", "BBCode help") . "" . "
")); } - $fields->addFieldToTab("Root.Content.Main", new TextField("Tags", _t("BlogEntry.TS", "Tags (comma sep.)")),"Content"); + $fields->addFieldToTab("Root.Main", new TextField("Tags", _t("BlogEntry.TS", "Tags (comma sep.)")),"Content"); $this->extend('updateCMSFields', $fields); @@ -87,8 +87,8 @@ class BlogEntry extends Page { * Returns the tags added to this blog entry */ function TagsCollection() { - $tags = split(" *, *", trim($this->Tags)); - $output = new DataObjectSet(); + $tags = preg_split(" *, *", trim($this->Tags)); + $output = new ArrayList(); $link = $this->getParent() ? $this->getParent()->Link('tag') : ''; diff --git a/code/BlogHolder.php b/code/BlogHolder.php index 025dc17..04a74c3 100644 --- a/code/BlogHolder.php +++ b/code/BlogHolder.php @@ -46,19 +46,14 @@ class BlogHolder extends BlogTree implements PermissionProvider { /** * Get members who have BLOGMANAGEMENT and ADMIN permission */ - function blogOwners($sort = 'Name', $direction = "ASC") { - $adminMembers = Permission::get_members_by_permission('ADMIN'); - $blogOwners = Permission::get_members_by_permission('BLOGMANAGEMENT'); + function blogOwners($sort = array('FirstName'=>'ASC','Surname'=>'ASC'), $direction = null) { - if(!$adminMembers) $adminMembers = new DataObjectSet(); - if(!$blogOwners) $blogOwners = new DataObjectSet(); + $members = Permission::get_members_by_permission(array('ADMIN','BLOGMANAGEMENT')); + $members->sort($sort); - $blogOwners->merge($adminMembers); - $blogOwners->sort($sort, $direction); + $this->extend('extendBlogOwners', $members); - $this->extend('extendBlogOwners', $blogOwners); - - return $blogOwners; + return $members; } public function BlogHolderIDs() { @@ -204,7 +199,7 @@ class BlogHolder_Controller extends BlogTree_Controller { } $codeparser = new BBCodeParser(); - $membername = Member::currentMember() ? Member::currentMember()->getName() : ""; + $membername = Member::currentUser() ? Member::currentUser()->getName() : ""; if(BlogEntry::$allow_wysiwyg_editing) { $contentfield = new HtmlEditorField("BlogPost", _t("BlogEntry.CN")); @@ -226,7 +221,7 @@ class BlogHolder_Controller extends BlogTree_Controller { if(!$this->AllowCustomAuthors && !Permission::check('ADMIN')) { $field = 'ReadonlyField'; } - $fields = new FieldSet( + $fields = new FieldList( new HiddenField("ID", "ID"), new TextField("Title", _t('BlogHolder.SJ', "Subject")), new $field("Author", _t('BlogEntry.AU'), $membername), @@ -237,7 +232,7 @@ class BlogHolder_Controller extends BlogTree_Controller { ); $submitAction = new FormAction('postblog', _t('BlogHolder.POST', 'Post blog entry')); - $actions = new FieldSet($submitAction); + $actions = new FieldList($submitAction); $validator = new RequiredFields('Title','BlogPost'); $form = new Form($this, 'BlogEntryForm',$fields, $actions,$validator); @@ -274,7 +269,8 @@ class BlogHolder_Controller extends BlogTree_Controller { $form->saveInto($blogentry); $blogentry->ParentID = $this->ID; - $blogentry->Content = str_replace("\r\n", "\n", $form->datafieldByName('BlogPost')->dataValue()); + + $blogentry->Content = str_replace("\r\n", "\n", $form->Fields()->fieldByName('BlogPost')->dataValue()); if(Object::has_extension($this->ClassName, 'Translatable')) { $blogentry->Locale = $this->Locale; diff --git a/code/TrackBackDecorator.php b/code/TrackBackDecorator.php index 5356fd9..5d9e05c 100644 --- a/code/TrackBackDecorator.php +++ b/code/TrackBackDecorator.php @@ -2,40 +2,45 @@ /** * Add trackback (receive and send) feature blog entry */ -class TrackBackDecorator extends DataObjectDecorator { +class TrackBackDecorator extends DataExtension { static $trackback_server_class = 'TrackbackHTTPServer'; - function extraStatics() { - return array( - 'has_many' => array( - 'TrackBackURLs' => 'TrackBackURL', - 'TrackBacks' => 'TrackBackPing' - ) - ); - } + // function extraStatics() { + // return array( + // 'has_many' => array( + // 'TrackBackURLs' => 'TrackBackURL', + // 'TrackBacks' => 'TrackBackPing' + // ) + // ); + // } + + static $has_many = array( + 'TrackBackURLs' => 'TrackBackURL', + 'TrackBacks' => 'TrackBackPing' + ); - function updateCMSFields($fields) { - // Trackback URL field - if($this->owner->TrackBacksEnabled()) { - $trackbackURLTable = new ComplexTableField( - $this, - 'TrackBackURLs', - 'TrackBackURL', - array( - 'URL' => 'URL', - 'IsPung' => 'Pung?' - ), - 'getCMSFields_forPopup', - '', - 'ID' - ); - $fields->addFieldToTab("Root.Content.Main", $trackbackURLTable); - } - else { - $fields->addFieldToTab("Root.Content.Main", new ReadonlyField("TrackBackURLsReadOnly", _t("BlogEntry.TrackbackURLs", "Trackback URLs"), _t("BlogEntry.TrackbackURLs_DISABLED", "To use this feature, please check 'Enable TrackBacks' check box on the blog holder."))); - } - } + // function updateCMSFields($fields) { + // // Trackback URL field + // if($this->owner->TrackBacksEnabled()) { + // $trackbackURLTable = new ComplexTableField( + // $this, + // 'TrackBackURLs', + // 'TrackBackURL', + // array( + // 'URL' => 'URL', + // 'IsPung' => 'Pung?' + // ), + // 'getCMSFields_forPopup', + // '', + // 'ID' + // ); + // $fields->addFieldToTab("Root.Content.Main", $trackbackURLTable); + // } + // else { + // $fields->addFieldToTab("Root.Content.Main", new ReadonlyField("TrackBackURLsReadOnly", _t("BlogEntry.TrackbackURLs", "Trackback URLs"), _t("BlogEntry.TrackbackURLs_DISABLED", "To use this feature, please check 'Enable TrackBacks' check box on the blog holder."))); + // } + // } function onBeforePublish() { if(!$this->owner->TrackBacksEnabled() && !$this->owner->TrackBackURLs()) return; diff --git a/code/TrackBackURL.php b/code/TrackBackURL.php index 7cf0903..951ae78 100644 --- a/code/TrackBackURL.php +++ b/code/TrackBackURL.php @@ -11,7 +11,7 @@ class TrackBackURL extends DataObject { ); function getCMSFields_forPopup() { - return new FieldSet( + return new FieldList( new TextField('URL'), new ReadonlyField('Pung', 'Pung?') ); diff --git a/code/widgets/ArchiveWidget.php b/code/widgets/ArchiveWidget.php index 77b2c7b..c98a177 100644 --- a/code/widgets/ArchiveWidget.php +++ b/code/widgets/ArchiveWidget.php @@ -32,7 +32,7 @@ class ArchiveWidget extends Widget { $fields = parent::getCMSFields(); $fields->merge( - new FieldSet( + new FieldList( new OptionsetField( 'DisplayMode', _t('ArchiveWidget.DispBY', 'Display by'), diff --git a/code/widgets/BlogManagementWidget.php b/code/widgets/BlogManagementWidget.php index 964d7bc..da31435 100644 --- a/code/widgets/BlogManagementWidget.php +++ b/code/widgets/BlogManagementWidget.php @@ -21,6 +21,7 @@ class BlogManagementWidget extends Widget implements PermissionProvider { static $description = "Provide a number of links useful for administering a blog. Only shown if the user is an admin."; function CommentText() { + if(!class_exists('Comment')) return false; $unmoderatedcount = DB::query("SELECT COUNT(*) FROM \"PageComment\" WHERE \"NeedsModeration\"=1")->value(); if($unmoderatedcount == 1) { return _t("BlogManagementWidget.UNM1", "You have 1 unmoderated comment"); @@ -32,7 +33,7 @@ class BlogManagementWidget extends Widget implements PermissionProvider { } function CommentLink() { - if(!Permission::check('BLOGMANAGEMENT')) { + if(!Permission::check('BLOGMANAGEMENT') || !class_exists('Comment')) { return false; } $unmoderatedcount = DB::query("SELECT COUNT(*) FROM \"PageComment\" WHERE \"NeedsModeration\"=1")->value(); diff --git a/code/widgets/RSSWidget.php b/code/widgets/RSSWidget.php index 17f8bc9..b6bfa65 100644 --- a/code/widgets/RSSWidget.php +++ b/code/widgets/RSSWidget.php @@ -43,7 +43,7 @@ class RSSWidget extends Widget { $fields = parent::getCMSFields(); $fields->merge( - new FieldSet( + new FieldList( new TextField("RSSTitle", _t('RSSWidget.CT', "Custom title for the feed")), new TextField("RssUrl", _t('RSSWidget.URL', "URL of the other page's RSS feed. Please make sure this URL points to an RSS feed.")), new NumericField("NumberToShow", _t('RSSWidget.NTS', "Number of Items to show")) diff --git a/code/widgets/TagCloudWidget.php b/code/widgets/TagCloudWidget.php index ed1bbe0..4832b1f 100644 --- a/code/widgets/TagCloudWidget.php +++ b/code/widgets/TagCloudWidget.php @@ -30,7 +30,7 @@ class TagCloudWidget extends Widget { $fields = parent::getCMSFields(); $fields->merge( - new FieldSet( + new FieldList( new TextField("Title", _t("TagCloudWidget.TILE", "Title")), new TextField("Limit", _t("TagCloudWidget.LIMIT", "Limit number of tags")), new OptionsetField("Sortby",_t("TagCloudWidget.SORTBY","Sort by"),array("alphabet"=>_t("TagCloudWidget.SBAL", "alphabet"),"frequency"=>_t("TagCloudWidget.SBFREQ", "frequency"))) @@ -57,7 +57,7 @@ class TagCloudWidget extends Widget { if($entries) { foreach($entries as $entry) { - $theseTags = split(" *, *", mb_strtolower(trim($entry->Tags))); + $theseTags = preg_split(" *, *", mb_strtolower(trim($entry->Tags))); foreach($theseTags as $tag) { if($tag != "") { $allTags[$tag] = isset($allTags[$tag]) ? $allTags[$tag] + 1 : 1; //getting the count into key => value map @@ -105,7 +105,7 @@ class TagCloudWidget extends Widget { } } - $output = new DataObjectSet(); + $output = new ArrayList(); foreach($allTags as $tag => $fields) { $output->push(new ArrayData($fields)); } diff --git a/tests/BlogHolderFunctionalTest.php b/tests/BlogHolderFunctionalTest.php index 2367074..e4a7f1d 100644 --- a/tests/BlogHolderFunctionalTest.php +++ b/tests/BlogHolderFunctionalTest.php @@ -46,6 +46,6 @@ class BlogHolderFunctionalTest extends FunctionalTest { ); $response = $this->post('blog/BlogEntryForm', $data); - $this->assertType('BlogEntry', DataObject::get_one('BlogEntry', sprintf("\"Title\" = 'Allowed'"))); + $this->assertInstanceOf('BlogEntry', DataObject::get_one('BlogEntry', sprintf("\"Title\" = 'Allowed'"))); } } diff --git a/tests/BlogHolderTest.php b/tests/BlogHolderTest.php index 05938a6..3c2eee7 100644 --- a/tests/BlogHolderTest.php +++ b/tests/BlogHolderTest.php @@ -56,11 +56,12 @@ class BlogHolderTest extends SapphireTest { function testBlogOwners() { $mainblog = $this->objFromFixture('BlogHolder', 'mainblog'); - $actualMembers = array_values($mainblog->blogOwners()->toDropDownMap('ID', 'Name')); + + $actualMembers = array_values($mainblog->blogOwners()->map('ID', 'Name')->toArray()); $expectedMembers = array( - 'ADMIN User', // test default admin 'Admin One', 'Admin Two', + 'ADMIN User', // test default admin 'Blog Owner One', 'Blog Owner Three', 'Blog Owner Two', diff --git a/tests/BlogTrackbackTest.php b/tests/BlogTrackbackTest.php index cf9550e..274707c 100644 --- a/tests/BlogTrackbackTest.php +++ b/tests/BlogTrackbackTest.php @@ -60,12 +60,13 @@ class BlogTrackbackTest extends SapphireTest { $entry1 = $this->objFromFixture('BlogEntry', 'testpost'); $entry1->doPublish(); $this->assertEquals(2, $entry1->TrackBackURLs()->Count()); - $this->assertEquals(array('testGoodTrackbackURL' => 1), $entry1->TrackBackURLs()->map('URL', 'Pung')); + + $this->assertEquals(array('testGoodTrackbackURL' => 1), $entry1->TrackBackURLs()->map('URL', 'Pung')->toArray()); $entry2 = $this->objFromFixture('BlogEntry', 'testpost2'); $entry2->doPublish(); $this->assertEquals(4, $entry2->TrackBackURLs()->Count()); - $this->assertEquals(array('testBadTrackbackURL' => 0, 'testGoodTrackbackURL2' => 1, 'noneExistingURL' => 0, 'testGoodTrackbackURL3' => 1), $entry2->TrackBackURLs()->map('URL', 'Pung')); + $this->assertEquals(array('testBadTrackbackURL' => 0, 'testGoodTrackbackURL2' => 1, 'noneExistingURL' => 0, 'testGoodTrackbackURL3' => 1), $entry2->TrackBackURLs()->map('URL', 'Pung')->toArray()); TrackBackDecorator::$trackback_server_class = $tmpServerClass; } diff --git a/tests/BlogTreeTest.php b/tests/BlogTreeTest.php index cdf1485..7ba88a5 100644 --- a/tests/BlogTreeTest.php +++ b/tests/BlogTreeTest.php @@ -14,7 +14,7 @@ class BlogTreeTest extends SapphireTest { $this->assertEquals($node->Entries()->Count(), 2); $node = $this->objFromFixture('BlogTree', 'levelab'); - $this->assertNull($node->Entries()); + $this->assertEquals($node->Entries()->Count(), 0); // this is not null anymore, it returns a DataList with no elements $node = $this->objFromFixture('BlogTree', 'levelb'); $this->assertEquals($node->Entries()->Count(), 1); @@ -22,7 +22,7 @@ class BlogTreeTest extends SapphireTest { $node = $this->objFromFixture('BlogTree', 'levelba'); $this->assertEquals($node->Entries()->Count(), 1); - $this->assertTrue($node->getCMSFields() instanceof FieldSet); + $this->assertTrue($node->getCMSFields() instanceof FieldList); } function testEntriesByMonth() { From 26d101e555cb6e53acb8404b0772122dd7bcd9c3 Mon Sep 17 00:00:00 2001 From: carlos barberis Date: Sat, 19 May 2012 14:40:39 +1200 Subject: [PATCH 06/10] BUGFIX: convert SS_Map to array before merging --- code/BlogHolder.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/BlogHolder.php b/code/BlogHolder.php index 04a74c3..1425d59 100644 --- a/code/BlogHolder.php +++ b/code/BlogHolder.php @@ -35,7 +35,7 @@ class BlogHolder extends BlogTree implements PermissionProvider { SiteTree::enableCMSFieldsExtensions(); $fields->addFieldToTab('Root.Main', new CheckboxField('TrackBacksEnabled', 'Enable TrackBacks')); - $fields->addFieldToTab('Root.Main', new DropdownField('OwnerID', 'Blog owner', array_merge(array('' => "(None)"), $blogOwners->map('ID', 'Name')) )); + $fields->addFieldToTab('Root.Main', new DropdownField('OwnerID', 'Blog owner', array_merge(array('' => "(None)"), $blogOwners->map('ID', 'Name')->toArray()))); $fields->addFieldToTab('Root.Main', new CheckboxField('AllowCustomAuthors', 'Allow non-admins to have a custom author field')); $this->extend('updateCMSFields', $fields); From fc9a93337a828f33626f708d9253f58702709f44 Mon Sep 17 00:00:00 2001 From: carlos barberis Date: Sat, 19 May 2012 15:07:13 +1200 Subject: [PATCH 07/10] BUGFIX: fix path to DB class on TypoImport.php --- code/import/TypoImport.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/import/TypoImport.php b/code/import/TypoImport.php index 11e264d..2b3b21f 100644 --- a/code/import/TypoImport.php +++ b/code/import/TypoImport.php @@ -1,6 +1,6 @@ Date: Sat, 19 May 2012 15:07:56 +1200 Subject: [PATCH 08/10] ENHANCEMENT: update XML-RPC library --- thirdparty/xmlrpc/xmlrpc.php | 310 +++++++++++++++----------- thirdparty/xmlrpc/xmlrpc_wrappers.php | 33 ++- thirdparty/xmlrpc/xmlrpcs.php | 206 ++++++++++------- 3 files changed, 333 insertions(+), 216 deletions(-) diff --git a/thirdparty/xmlrpc/xmlrpc.php b/thirdparty/xmlrpc/xmlrpc.php index 21e29a0..b3658f0 100644 --- a/thirdparty/xmlrpc/xmlrpc.php +++ b/thirdparty/xmlrpc/xmlrpc.php @@ -45,29 +45,6 @@ } } - // Try to be backward compat with php < 4.2 (are we not being nice ?) - $phpversion = phpversion(); - if($phpversion[0] == '4' && $phpversion[2] < 2) - { - // give an opportunity to user to specify where to include other files from - if(!defined('PHP_XMLRPC_COMPAT_DIR')) - { - define('PHP_XMLRPC_COMPAT_DIR',dirname(__FILE__).'/compat/'); - } - if($phpversion[2] == '0') - { - if($phpversion[4] < 6) - { - include(PHP_XMLRPC_COMPAT_DIR.'is_callable.php'); - } - include(PHP_XMLRPC_COMPAT_DIR.'is_scalar.php'); - include(PHP_XMLRPC_COMPAT_DIR.'array_key_exists.php'); - include(PHP_XMLRPC_COMPAT_DIR.'version_compare.php'); - } - include(PHP_XMLRPC_COMPAT_DIR.'var_export.php'); - include(PHP_XMLRPC_COMPAT_DIR.'is_a.php'); - } - // G. Giunta 2005/01/29: declare global these variables, // so that xmlrpc.inc will work even if included from within a function // Milosch: 2005/08/07 - explicitly request these via $GLOBALS where used. @@ -112,7 +89,8 @@ 'METHODNAME' => array('METHODCALL'), 'PARAMS' => array('METHODCALL', 'METHODRESPONSE'), 'FAULT' => array('METHODRESPONSE'), - 'NIL' => array('VALUE') // only used when extension activated + 'NIL' => array('VALUE'), // only used when extension activated + 'EX:NIL' => array('VALUE') // only used when extension activated ); // define extra types for supporting NULL (useful for json or ) @@ -231,7 +209,7 @@ $GLOBALS['xmlrpc_internalencoding']='ISO-8859-1'; $GLOBALS['xmlrpcName']='XML-RPC for PHP'; - $GLOBALS['xmlrpcVersion']='2.2.2'; + $GLOBALS['xmlrpcVersion']='3.0.0.beta'; // let user errors start at 800 $GLOBALS['xmlrpcerruser']=800; @@ -243,9 +221,12 @@ /// @deprecated $GLOBALS['xmlrpc_backslash']=chr(92).chr(92); - // set to TRUE to enable correct decoding of values + // set to TRUE to enable correct decoding of and values $GLOBALS['xmlrpc_null_extension']=false; + // set to TRUE to enable encoding of php NULL values to instead of + $GLOBALS['xmlrpc_null_apache_encoding']=false; + // used to store state during parsing // quick explanation of components: // ac - used to accumulate values @@ -426,6 +407,7 @@ else { $GLOBALS['_xh']['rt'] = strtolower($name); + $GLOBALS['_xh']['rt'] = strtolower($name); } } else @@ -518,6 +500,7 @@ $GLOBALS['_xh']['vt']=null; break; case 'NIL': + case 'EX:NIL': if ($GLOBALS['xmlrpc_null_extension']) { if ($GLOBALS['_xh']['vt']!='value') @@ -580,7 +563,7 @@ if ($rebuild_xmlrpcvals) { // build the xmlrpc val out of the data received, and substitute it - $temp =& new xmlrpcval($GLOBALS['_xh']['value'], $GLOBALS['_xh']['vt']); + $temp = new xmlrpcval($GLOBALS['_xh']['value'], $GLOBALS['_xh']['vt']); // in case we got info about underlying php class, save it // in the object we're rebuilding if (isset($GLOBALS['_xh']['php_class'])) @@ -743,6 +726,7 @@ $GLOBALS['_xh']['method']=preg_replace('/^[\n\r\t ]+/', '', $GLOBALS['_xh']['ac']); break; case 'NIL': + case 'EX:NIL': if ($GLOBALS['xmlrpc_null_extension']) { $GLOBALS['_xh']['vt']='null'; @@ -844,6 +828,8 @@ var $proxy_pass=''; var $proxy_authtype=1; var $cookies=array(); + var $extracurlopts=array(); + /** * List of http compression methods accepted by the client for responses. * NB: PHP supports deflate, gzip compressions out of the box if compiled w. zlib @@ -875,6 +861,10 @@ * valid strings are 'xmlrpcvals', 'phpvals' or 'xml' */ var $return_type = 'xmlrpcvals'; + /** + * Sent to servers in http headers + */ + var $user_agent; /** * @param string $path either the complete server URL or the PATH part of the xmlrc server URL, e.g. /xmlrpc/server.php @@ -942,15 +932,14 @@ $this->accepted_compression = array('gzip', 'deflate'); } - // keepalives: enabled by default ONLY for PHP >= 4.3.8 - // (see http://curl.haxx.se/docs/faq.html#7.3) - if(version_compare(phpversion(), '4.3.8') >= 0) - { - $this->keepalive = true; - } + // keepalives: enabled by default + $this->keepalive = true; // by default the xml parser can support these 3 charset encodings $this->accepted_charset_encodings = array('UTF-8', 'ISO-8859-1', 'US-ASCII'); + + // initialize user_agent string + $this->user_agent = $GLOBALS['xmlrpcName'] . ' ' . $GLOBALS['xmlrpcVersion']; } /** @@ -1117,6 +1106,25 @@ } } + /** + * Directly set cURL options, for extra flexibility + * It allows eg. to bind client to a specific IP interface / address + * @param $options array + */ + function SetCurlOptions( $options ) + { + $this->extracurlopts = $options; + } + + /** + * Set user-agent string that will be used by this client instance + * in http headers sent to the server + */ + function SetUserAgent( $agentstring ) + { + $this->user_agent = $agentstring; + } + /** * Send an xmlrpc request * @param mixed $msg The message object, or an array of messages for using multicall, or the complete xml representation of a request @@ -1142,7 +1150,7 @@ } elseif(is_string($msg)) { - $n =& new xmlrpcmsg(''); + $n = new xmlrpcmsg(''); $n->payload = $msg; $msg = $n; } @@ -1271,7 +1279,7 @@ $credentials='Authorization: Basic ' . base64_encode($username . ':' . $password) . "\r\n"; if ($authtype != 1) { - error_log('XML-RPC: xmlrpc_client::send: warning. Only Basic auth is supported with HTTP 1.0'); + error_log('XML-RPC: '.__METHOD__.': warning. Only Basic auth is supported with HTTP 1.0'); } } @@ -1295,7 +1303,7 @@ { if ($proxyauthtype != 1) { - error_log('XML-RPC: xmlrpc_client::send: warning. Only Basic auth to proxy is supported with HTTP 1.0'); + error_log('XML-RPC: '.__METHOD__.': warning. Only Basic auth to proxy is supported with HTTP 1.0'); } $proxy_credentials = 'Proxy-Authorization: Basic ' . base64_encode($proxyusername.':'.$proxypassword) . "\r\n"; } @@ -1335,7 +1343,7 @@ } $op= 'POST ' . $uri. " HTTP/1.0\r\n" . - 'User-Agent: ' . $GLOBALS['xmlrpcName'] . ' ' . $GLOBALS['xmlrpcVersion'] . "\r\n" . + 'User-Agent: ' . $this->user_agent . "\r\n" . 'Host: '. $server . ':' . $port . "\r\n" . $credentials . $proxy_credentials . @@ -1372,15 +1380,15 @@ else { $this->errstr='Connect error: '.$this->errstr; - $r=&new xmlrpcresp(0, $GLOBALS['xmlrpcerr']['http_error'], $this->errstr . ' (' . $this->errno . ')'); + $r=new xmlrpcresp(0, $GLOBALS['xmlrpcerr']['http_error'], $this->errstr . ' (' . $this->errno . ')'); return $r; } if(!fputs($fp, $op, strlen($op))) { - fclose($fp); + fclose($fp); $this->errstr='Write error'; - $r=&new xmlrpcresp(0, $GLOBALS['xmlrpcerr']['http_error'], $this->errstr); + $r=new xmlrpcresp(0, $GLOBALS['xmlrpcerr']['http_error'], $this->errstr); return $r; } else @@ -1431,7 +1439,7 @@ if(!function_exists('curl_init')) { $this->errstr='CURL unavailable on this install'; - $r=&new xmlrpcresp(0, $GLOBALS['xmlrpcerr']['no_curl'], $GLOBALS['xmlrpcstr']['no_curl']); + $r=new xmlrpcresp(0, $GLOBALS['xmlrpcerr']['no_curl'], $GLOBALS['xmlrpcstr']['no_curl']); return $r; } if($method == 'https') @@ -1440,7 +1448,7 @@ ((is_string($info) && strpos($info, 'OpenSSL') === null) || (is_array($info) && !isset($info['ssl_version'])))) { $this->errstr='SSL unavailable on this install'; - $r=&new xmlrpcresp(0, $GLOBALS['xmlrpcerr']['no_ssl'], $GLOBALS['xmlrpcstr']['no_ssl']); + $r=new xmlrpcresp(0, $GLOBALS['xmlrpcerr']['no_ssl'], $GLOBALS['xmlrpcstr']['no_ssl']); return $r; } } @@ -1518,7 +1526,7 @@ { curl_setopt($curl, CURLOPT_VERBOSE, 1); } - curl_setopt($curl, CURLOPT_USERAGENT, $GLOBALS['xmlrpcName'].' '.$GLOBALS['xmlrpcVersion']); + curl_setopt($curl, CURLOPT_USERAGENT, $this->user_agent); // required for XMLRPC: post the data curl_setopt($curl, CURLOPT_POST, 1); // the data @@ -1571,7 +1579,7 @@ } else if ($authtype != 1) { - error_log('XML-RPC: xmlrpc_client::send: warning. Only Basic auth is supported by the current PHP/curl install'); + error_log('XML-RPC: '.__METHOD__.': warning. Only Basic auth is supported by the current PHP/curl install'); } } @@ -1630,7 +1638,7 @@ } else if ($proxyauthtype != 1) { - error_log('XML-RPC: xmlrpc_client::send: warning. Only Basic auth to proxy is supported by the current PHP/curl install'); + error_log('XML-RPC: '.__METHOD__.': warning. Only Basic auth to proxy is supported by the current PHP/curl install'); } } } @@ -1648,6 +1656,11 @@ curl_setopt($curl, CURLOPT_COOKIE, substr($cookieheader, 0, -2)); } + foreach ($this->extracurlopts as $opt => $val) + { + curl_setopt($curl, $opt, $val); + } + $result = curl_exec($curl); if ($this->debug > 1) @@ -1661,7 +1674,7 @@ if(!$result) /// @todo we should use a better check here - what if we get back '' or '0'? { $this->errstr='no response'; - $resp=&new xmlrpcresp(0, $GLOBALS['xmlrpcerr']['curl_fail'], $GLOBALS['xmlrpcstr']['curl_fail']. ': '. curl_error($curl)); + $resp=new xmlrpcresp(0, $GLOBALS['xmlrpcerr']['curl_fail'], $GLOBALS['xmlrpcstr']['curl_fail']. ': '. curl_error($curl)); curl_close($curl); if($keepalive) { @@ -1732,7 +1745,7 @@ } else { - $result =& new xmlrpcresp(0, $GLOBALS['xmlrpcerr']['multicall_error'], $GLOBALS['xmlrpcstr']['multicall_error']); + $result = new xmlrpcresp(0, $GLOBALS['xmlrpcerr']['multicall_error'], $GLOBALS['xmlrpcstr']['multicall_error']); } } } @@ -1779,17 +1792,17 @@ $calls = array(); foreach($msgs as $msg) { - $call['methodName'] =& new xmlrpcval($msg->method(),'string'); + $call['methodName'] = new xmlrpcval($msg->method(),'string'); $numParams = $msg->getNumParams(); $params = array(); for($i = 0; $i < $numParams; $i++) { $params[$i] = $msg->getParam($i); } - $call['params'] =& new xmlrpcval($params, 'array'); - $calls[] =& new xmlrpcval($call, 'struct'); + $call['params'] = new xmlrpcval($params, 'array'); + $calls[] = new xmlrpcval($call, 'struct'); } - $multicall =& new xmlrpcmsg('system.multicall'); + $multicall = new xmlrpcmsg('system.multicall'); $multicall->addParam(new xmlrpcval($calls, 'array')); // Attempt RPC call @@ -1837,7 +1850,7 @@ return false; // Bad value } // Normal return value - $response[$i] =& new xmlrpcresp($val[0], 0, '', 'phpvals'); + $response[$i] = new xmlrpcresp($val[0], 0, '', 'phpvals'); break; case 2: /// @todo remove usage of @: it is apparently quite slow @@ -1851,7 +1864,7 @@ { return false; } - $response[$i] =& new xmlrpcresp(0, $code, $str); + $response[$i] = new xmlrpcresp(0, $code, $str); break; default: return false; @@ -1884,7 +1897,7 @@ return false; // Bad value } // Normal return value - $response[$i] =& new xmlrpcresp($val->arraymem(0)); + $response[$i] = new xmlrpcresp($val->arraymem(0)); break; case 'struct': $code = $val->structmem('faultCode'); @@ -1897,7 +1910,7 @@ { return false; } - $response[$i] =& new xmlrpcresp(0, $code->scalarval(), $str->scalarval()); + $response[$i] = new xmlrpcresp(0, $code->scalarval(), $str->scalarval()); break; default: return false; @@ -2208,7 +2221,7 @@ xmlrpc_encode_entitites($this->errstr, $GLOBALS['xmlrpc_internalencoding'], $cha * Given an open file handle, read all data available and parse it as axmlrpc response. * NB: the file handle is not closed by this function. * NNB: might have trouble in rare cases to work on network streams, as we - * check for a read of 0 bytes instead of feof($fp). + * check for a read of 0 bytes instead of feof($fp). * But since checking for feof(null) returns false, we would risk an * infinite loop in that case, because we cannot trust the caller * to give us a valid pointer to an open file... @@ -2265,8 +2278,8 @@ xmlrpc_encode_entitites($this->errstr, $GLOBALS['xmlrpc_internalencoding'], $cha } else { - error_log('XML-RPC: xmlrpcmsg::parseResponse: HTTPS via proxy error, tunnel connection possibly failed'); - $r=&new xmlrpcresp(0, $GLOBALS['xmlrpcerr']['http_error'], $GLOBALS['xmlrpcstr']['http_error']. ' (HTTPS via proxy error, tunnel connection possibly failed)'); + error_log('XML-RPC: '.__METHOD__.': HTTPS via proxy error, tunnel connection possibly failed'); + $r=new xmlrpcresp(0, $GLOBALS['xmlrpcerr']['http_error'], $GLOBALS['xmlrpcstr']['http_error']. ' (HTTPS via proxy error, tunnel connection possibly failed)'); return $r; } } @@ -2286,8 +2299,8 @@ xmlrpc_encode_entitites($this->errstr, $GLOBALS['xmlrpc_internalencoding'], $cha if(!preg_match('/^HTTP\/[0-9.]+ 200 /', $data)) { $errstr= substr($data, 0, strpos($data, "\n")-1); - error_log('XML-RPC: xmlrpcmsg::parseResponse: HTTP error, got response: ' .$errstr); - $r=&new xmlrpcresp(0, $GLOBALS['xmlrpcerr']['http_error'], $GLOBALS['xmlrpcstr']['http_error']. ' (' . $errstr . ')'); + error_log('XML-RPC: '.__METHOD__.': HTTP error, got response: ' .$errstr); + $r=new xmlrpcresp(0, $GLOBALS['xmlrpcerr']['http_error'], $GLOBALS['xmlrpcstr']['http_error']. ' (' . $errstr . ')'); return $r; } @@ -2316,7 +2329,7 @@ xmlrpc_encode_entitites($this->errstr, $GLOBALS['xmlrpc_internalencoding'], $cha } } // be tolerant to line endings, and extra empty lines - $ar = split("\r?\n", trim(substr($data, 0, $pos))); + $ar = preg_split("/\r?\n/", trim(substr($data, 0, $pos))); while(list(,$line) = @each($ar)) { // take care of multi-line headers and cookies @@ -2411,8 +2424,8 @@ xmlrpc_encode_entitites($this->errstr, $GLOBALS['xmlrpc_internalencoding'], $cha { if(!$data = decode_chunked($data)) { - error_log('XML-RPC: xmlrpcmsg::parseResponse: errors occurred when trying to rebuild the chunked data received from server'); - $r =& new xmlrpcresp(0, $GLOBALS['xmlrpcerr']['dechunk_fail'], $GLOBALS['xmlrpcstr']['dechunk_fail']); + error_log('XML-RPC: '.__METHOD__.': errors occurred when trying to rebuild the chunked data received from server'); + $r = new xmlrpcresp(0, $GLOBALS['xmlrpcerr']['dechunk_fail'], $GLOBALS['xmlrpcstr']['dechunk_fail']); return $r; } } @@ -2441,22 +2454,22 @@ xmlrpc_encode_entitites($this->errstr, $GLOBALS['xmlrpc_internalencoding'], $cha } else { - error_log('XML-RPC: xmlrpcmsg::parseResponse: errors occurred when trying to decode the deflated data received from server'); - $r =& new xmlrpcresp(0, $GLOBALS['xmlrpcerr']['decompress_fail'], $GLOBALS['xmlrpcstr']['decompress_fail']); + error_log('XML-RPC: '.__METHOD__.': errors occurred when trying to decode the deflated data received from server'); + $r = new xmlrpcresp(0, $GLOBALS['xmlrpcerr']['decompress_fail'], $GLOBALS['xmlrpcstr']['decompress_fail']); return $r; } } else { - error_log('XML-RPC: xmlrpcmsg::parseResponse: the server sent deflated data. Your php install must have the Zlib extension compiled in to support this.'); - $r =& new xmlrpcresp(0, $GLOBALS['xmlrpcerr']['cannot_decompress'], $GLOBALS['xmlrpcstr']['cannot_decompress']); + error_log('XML-RPC: '.__METHOD__.': the server sent deflated data. Your php install must have the Zlib extension compiled in to support this.'); + $r = new xmlrpcresp(0, $GLOBALS['xmlrpcerr']['cannot_decompress'], $GLOBALS['xmlrpcstr']['cannot_decompress']); return $r; } } } } // end of 'if needed, de-chunk, re-inflate response' - // real stupid hack to avoid PHP 4 complaining about returning NULL by ref + // real stupid hack to avoid PHP complaining about returning NULL by ref $r = null; $r =& $r; return $r; @@ -2480,8 +2493,8 @@ xmlrpc_encode_entitites($this->errstr, $GLOBALS['xmlrpc_internalencoding'], $cha if($data == '') { - error_log('XML-RPC: xmlrpcmsg::parseResponse: no response received from server.'); - $r =& new xmlrpcresp(0, $GLOBALS['xmlrpcerr']['no_data'], $GLOBALS['xmlrpcstr']['no_data']); + error_log('XML-RPC: '.__METHOD__.': no response received from server.'); + $r = new xmlrpcresp(0, $GLOBALS['xmlrpcerr']['no_data'], $GLOBALS['xmlrpcstr']['no_data']); return $r; } @@ -2525,23 +2538,16 @@ xmlrpc_encode_entitites($this->errstr, $GLOBALS['xmlrpc_internalencoding'], $cha // be tolerant of junk after methodResponse (e.g. javascript ads automatically inserted by free hosts) // idea from Luca Mariano originally in PEARified version of the lib - $bd = false; - // Poor man's version of strrpos for php 4... - $pos = strpos($data, ''); - while($pos || is_int($pos)) + $pos = strrpos($data, ''); + if($pos !== false) { - $bd = $pos+17; - $pos = strpos($data, '', $bd); - } - if($bd) - { - $data = substr($data, 0, $bd); + $data = substr($data, 0, $pos+17); } // if user wants back raw xml, give it to him if ($return_type == 'xml') { - $r =& new xmlrpcresp($data, 0, '', 'xml'); + $r = new xmlrpcresp($data, 0, '', 'xml'); $r->hdrs = $GLOBALS['_xh']['headers']; $r->_cookies = $GLOBALS['_xh']['cookies']; $r->raw_data = $raw_data; @@ -2566,7 +2572,7 @@ xmlrpc_encode_entitites($this->errstr, $GLOBALS['xmlrpc_internalencoding'], $cha // makes the lib about 200% slower... //if (!is_valid_charset($resp_encoding, array('UTF-8', 'ISO-8859-1', 'US-ASCII'))) { - error_log('XML-RPC: xmlrpcmsg::parseResponse: invalid charset encoding of received response: '.$resp_encoding); + error_log('XML-RPC: '.__METHOD__.': invalid charset encoding of received response: '.$resp_encoding); $resp_encoding = $GLOBALS['xmlrpc_defencoding']; } $parser = xml_parser_create($resp_encoding); @@ -2613,7 +2619,7 @@ xmlrpc_encode_entitites($this->errstr, $GLOBALS['xmlrpc_internalencoding'], $cha xml_get_current_line_number($parser), xml_get_current_column_number($parser)); } error_log($errstr); - $r=&new xmlrpcresp(0, $GLOBALS['xmlrpcerr']['invalid_return'], $GLOBALS['xmlrpcstr']['invalid_return'].' ('.$errstr.')'); + $r=new xmlrpcresp(0, $GLOBALS['xmlrpcerr']['invalid_return'], $GLOBALS['xmlrpcstr']['invalid_return'].' ('.$errstr.')'); xml_parser_free($parser); if($this->debug) { @@ -2633,7 +2639,7 @@ xmlrpc_encode_entitites($this->errstr, $GLOBALS['xmlrpc_internalencoding'], $cha /// @todo echo something for user? } - $r =& new xmlrpcresp(0, $GLOBALS['xmlrpcerr']['invalid_return'], + $r = new xmlrpcresp(0, $GLOBALS['xmlrpcerr']['invalid_return'], $GLOBALS['xmlrpcstr']['invalid_return'] . ' ' . $GLOBALS['_xh']['isf_reason']); } // third error check: parsing of the response has somehow gone boink. @@ -2643,7 +2649,7 @@ xmlrpc_encode_entitites($this->errstr, $GLOBALS['xmlrpc_internalencoding'], $cha // something odd has happened // and it's time to generate a client side error // indicating something odd went on - $r=&new xmlrpcresp(0, $GLOBALS['xmlrpcerr']['invalid_return'], + $r=new xmlrpcresp(0, $GLOBALS['xmlrpcerr']['invalid_return'], $GLOBALS['xmlrpcstr']['invalid_return']); } else @@ -2683,11 +2689,11 @@ xmlrpc_encode_entitites($this->errstr, $GLOBALS['xmlrpc_internalencoding'], $cha $errno = -1; } - $r =& new xmlrpcresp(0, $errno, $errstr); + $r = new xmlrpcresp(0, $errno, $errstr); } else { - $r=&new xmlrpcresp($v, 0, '', $return_type); + $r=new xmlrpcresp($v, 0, '', $return_type); } } @@ -2741,7 +2747,7 @@ xmlrpc_encode_entitites($this->errstr, $GLOBALS['xmlrpc_internalencoding'], $cha $this->me['struct']=$val; break; default: - error_log("XML-RPC: xmlrpcval::xmlrpcval: not a known type ($type)"); + error_log("XML-RPC: ".__METHOD__.": not a known type ($type)"); } /*if($type=='') { @@ -2773,13 +2779,13 @@ xmlrpc_encode_entitites($this->errstr, $GLOBALS['xmlrpc_internalencoding'], $cha $typeof=@$GLOBALS['xmlrpcTypes'][$type]; if($typeof!=1) { - error_log("XML-RPC: xmlrpcval::addScalar: not a scalar type ($type)"); + error_log("XML-RPC: ".__METHOD__.": not a scalar type ($type)"); return 0; } // coerce booleans into correct values - // NB: we should iether do it for datetimes, integers and doubles, too, - // or just plain remove this check, implemnted on booleans only... + // NB: we should either do it for datetimes, integers and doubles, too, + // or just plain remove this check, implemented on booleans only... if($type==$GLOBALS['xmlrpcBoolean']) { if(strcasecmp($val,'true')==0 || $val==1 || ($val==true && strcasecmp($val,'false'))) @@ -2795,18 +2801,18 @@ xmlrpc_encode_entitites($this->errstr, $GLOBALS['xmlrpc_internalencoding'], $cha switch($this->mytype) { case 1: - error_log('XML-RPC: xmlrpcval::addScalar: scalar xmlrpcval can have only one value'); + error_log('XML-RPC: '.__METHOD__.': scalar xmlrpcval can have only one value'); return 0; case 3: - error_log('XML-RPC: xmlrpcval::addScalar: cannot add anonymous scalar to struct xmlrpcval'); + error_log('XML-RPC: '.__METHOD__.': cannot add anonymous scalar to struct xmlrpcval'); return 0; case 2: // we're adding a scalar value to an array here //$ar=$this->me['array']; - //$ar[]=&new xmlrpcval($val, $type); + //$ar[]=new xmlrpcval($val, $type); //$this->me['array']=$ar; // Faster (?) avoid all the costly array-copy-by-val done here... - $this->me['array'][]=&new xmlrpcval($val, $type); + $this->me['array'][]=new xmlrpcval($val, $type); return 1; default: // a scalar, so set the value and remember we're scalar @@ -2840,7 +2846,7 @@ xmlrpc_encode_entitites($this->errstr, $GLOBALS['xmlrpc_internalencoding'], $cha } else { - error_log('XML-RPC: xmlrpcval::addArray: already initialized as a [' . $this->kindOf() . ']'); + error_log('XML-RPC: '.__METHOD__.': already initialized as a [' . $this->kindOf() . ']'); return 0; } } @@ -2869,7 +2875,7 @@ xmlrpc_encode_entitites($this->errstr, $GLOBALS['xmlrpc_internalencoding'], $cha } else { - error_log('XML-RPC: xmlrpcval::addStruct: already initialized as a [' . $this->kindOf() . ']'); + error_log('XML-RPC: '.__METHOD__.': already initialized as a [' . $this->kindOf() . ']'); return 0; } } @@ -2941,15 +2947,41 @@ xmlrpc_encode_entitites($this->errstr, $GLOBALS['xmlrpc_internalencoding'], $cha $rs.="<${typ}>".(int)$val.""; break; case $GLOBALS['xmlrpcDouble']: - // avoid using standard conversion of float to string because it is locale-dependent, - // and also because the xmlrpc spec forbids exponential notation - // sprintf('%F') would be most likely ok but it is only available since PHP 4.3.10 and PHP 5.0.3. - // The code below tries its best at keeping max precision while avoiding exp notation, - // but there is of course no limit in the number of decimal places to be used... - $rs.="<${typ}>".preg_replace('/\\.?0+$/','',number_format((double)$val, 128, '.', '')).""; + // avoid using standard conversion of float to string because it is locale-dependent, + // and also because the xmlrpc spec forbids exponential notation. + // sprintf('%F') could be most likely ok but it fails eg. on 2e-14. + // The code below tries its best at keeping max precision while avoiding exp notation, + // but there is of course no limit in the number of decimal places to be used... + $rs.="<${typ}>".preg_replace('/\\.?0+$/','',number_format((double)$val, 128, '.', '')).""; + break; + case $GLOBALS['xmlrpcDateTime']: + if (is_string($val)) + { + $rs.="<${typ}>${val}"; + } + else if(is_a($val, 'DateTime')) + { + $rs.="<${typ}>".$val->format('Ymd\TH:i:s').""; + } + else if(is_int($val)) + { + $rs.="<${typ}>".strftime("%Y%m%dT%H:%M:%S", $val).""; + } + else + { + // not really a good idea here: but what shall we output anyway? left for backward compat... + $rs.="<${typ}>${val}"; + } break; case $GLOBALS['xmlrpcNull']: - $rs.=""; + if ($GLOBALS['xmlrpc_null_apache_encoding']) + { + $rs.=""; + } + else + { + $rs.=""; + } break; default: // no standard type value should arrive here, but provide a possibility @@ -3249,7 +3281,7 @@ xmlrpc_encode_entitites($this->errstr, $GLOBALS['xmlrpc_internalencoding'], $cha * @author Dan Libby (dan@libby.com) * * @param xmlrpcval $xmlrpc_val - * @param array $options if 'decode_php_objs' is set in the options array, xmlrpc structs can be decoded into php objects + * @param array $options if 'decode_php_objs' is set in the options array, xmlrpc structs can be decoded into php objects; if 'dates_as_objects' is set xmlrpc datetimes are decoded as php DateTime objects (standard is * @return mixed */ function php_xmlrpc_decode($xmlrpc_val, $options=array()) @@ -3276,6 +3308,27 @@ xmlrpc_encode_entitites($this->errstr, $GLOBALS['xmlrpc_internalencoding'], $cha return $xmlrpc_val->scalarval(); } } + if (in_array('dates_as_objects', $options) && $xmlrpc_val->scalartyp() == 'dateTime.iso8601') + { + // we return a Datetime object instead of a string + // since now the constructor of xmlrpcval accepts safely strings, ints and datetimes, + // we cater to all 3 cases here + $out = $xmlrpc_val->scalarval(); + if (is_string($out)) + { + $out = strtotime($out); + } + if (is_int($out)) + { + $result = new Datetime(); + $result->setTimestamp($out); + return $result; + } + elseif (is_a($out, 'Datetime')) + { + return $out; + } + } return $xmlrpc_val->scalarval(); case 'array': $size = $xmlrpc_val->arraysize(); @@ -3350,27 +3403,27 @@ xmlrpc_encode_entitites($this->errstr, $GLOBALS['xmlrpc_internalencoding'], $cha * @param array $options can include 'encode_php_objs', 'auto_dates', 'null_extension' or 'extension_api' * @return xmlrpcval */ - function &php_xmlrpc_encode($php_val, $options=array()) + function php_xmlrpc_encode($php_val, $options=array()) { $type = gettype($php_val); switch($type) { case 'string': if (in_array('auto_dates', $options) && preg_match('/^[0-9]{8}T[0-9]{2}:[0-9]{2}:[0-9]{2}$/', $php_val)) - $xmlrpc_val =& new xmlrpcval($php_val, $GLOBALS['xmlrpcDateTime']); + $xmlrpc_val = new xmlrpcval($php_val, $GLOBALS['xmlrpcDateTime']); else - $xmlrpc_val =& new xmlrpcval($php_val, $GLOBALS['xmlrpcString']); + $xmlrpc_val = new xmlrpcval($php_val, $GLOBALS['xmlrpcString']); break; case 'integer': - $xmlrpc_val =& new xmlrpcval($php_val, $GLOBALS['xmlrpcInt']); + $xmlrpc_val = new xmlrpcval($php_val, $GLOBALS['xmlrpcInt']); break; case 'double': - $xmlrpc_val =& new xmlrpcval($php_val, $GLOBALS['xmlrpcDouble']); + $xmlrpc_val = new xmlrpcval($php_val, $GLOBALS['xmlrpcDouble']); break; // // Add support for encoding/decoding of booleans, since they are supported in PHP case 'boolean': - $xmlrpc_val =& new xmlrpcval($php_val, $GLOBALS['xmlrpcBoolean']); + $xmlrpc_val = new xmlrpcval($php_val, $GLOBALS['xmlrpcBoolean']); break; // case 'array': @@ -3384,7 +3437,7 @@ xmlrpc_encode_entitites($this->errstr, $GLOBALS['xmlrpc_internalencoding'], $cha $ko = false; foreach($php_val as $key => $val) { - $arr[$key] =& php_xmlrpc_encode($val, $options); + $arr[$key] = php_xmlrpc_encode($val, $options); if(!$ko && $key !== $j) { $ko = true; @@ -3393,11 +3446,11 @@ xmlrpc_encode_entitites($this->errstr, $GLOBALS['xmlrpc_internalencoding'], $cha } if($ko) { - $xmlrpc_val =& new xmlrpcval($arr, $GLOBALS['xmlrpcStruct']); + $xmlrpc_val = new xmlrpcval($arr, $GLOBALS['xmlrpcStruct']); } else { - $xmlrpc_val =& new xmlrpcval($arr, $GLOBALS['xmlrpcArray']); + $xmlrpc_val = new xmlrpcval($arr, $GLOBALS['xmlrpcArray']); } break; case 'object': @@ -3405,14 +3458,19 @@ xmlrpc_encode_entitites($this->errstr, $GLOBALS['xmlrpc_internalencoding'], $cha { $xmlrpc_val = $php_val; } + else if(is_a($php_val, 'DateTime')) + { + $xmlrpc_val = new xmlrpcval($php_val->format('Ymd\TH:i:s'), $GLOBALS['xmlrpcStruct']); + } else { $arr = array(); + reset($php_val); while(list($k,$v) = each($php_val)) { $arr[$k] = php_xmlrpc_encode($v, $options); } - $xmlrpc_val =& new xmlrpcval($arr, $GLOBALS['xmlrpcStruct']); + $xmlrpc_val = new xmlrpcval($arr, $GLOBALS['xmlrpcStruct']); if (in_array('encode_php_objs', $options)) { // let's save original class name into xmlrpcval: @@ -3424,32 +3482,32 @@ xmlrpc_encode_entitites($this->errstr, $GLOBALS['xmlrpc_internalencoding'], $cha case 'NULL': if (in_array('extension_api', $options)) { - $xmlrpc_val =& new xmlrpcval('', $GLOBALS['xmlrpcString']); + $xmlrpc_val = new xmlrpcval('', $GLOBALS['xmlrpcString']); } - if (in_array('null_extension', $options)) + else if (in_array('null_extension', $options)) { - $xmlrpc_val =& new xmlrpcval('', $GLOBALS['xmlrpcNull']); + $xmlrpc_val = new xmlrpcval('', $GLOBALS['xmlrpcNull']); } else { - $xmlrpc_val =& new xmlrpcval(); + $xmlrpc_val = new xmlrpcval(); } break; case 'resource': if (in_array('extension_api', $options)) { - $xmlrpc_val =& new xmlrpcval((int)$php_val, $GLOBALS['xmlrpcInt']); + $xmlrpc_val = new xmlrpcval((int)$php_val, $GLOBALS['xmlrpcInt']); } else { - $xmlrpc_val =& new xmlrpcval(); + $xmlrpc_val = new xmlrpcval(); } // catch "user function", "unknown type" default: // giancarlo pinerolo // it has to return // an empty object in case, not a boolean. - $xmlrpc_val =& new xmlrpcval(); + $xmlrpc_val = new xmlrpcval(); break; } return $xmlrpc_val; @@ -3513,15 +3571,15 @@ xmlrpc_encode_entitites($this->errstr, $GLOBALS['xmlrpc_internalencoding'], $cha { $vc = $v->structmem('faultCode'); $vs = $v->structmem('faultString'); - $r =& new xmlrpcresp(0, $vc->scalarval(), $vs->scalarval()); + $r = new xmlrpcresp(0, $vc->scalarval(), $vs->scalarval()); } else { - $r =& new xmlrpcresp($v); + $r = new xmlrpcresp($v); } return $r; case 'methodcall': - $m =& new xmlrpcmsg($GLOBALS['_xh']['method']); + $m = new xmlrpcmsg($GLOBALS['_xh']['method']); for($i=0; $i < count($GLOBALS['_xh']['params']); $i++) { $m->addParam($GLOBALS['_xh']['params'][$i]); @@ -3616,7 +3674,7 @@ xmlrpc_encode_entitites($this->errstr, $GLOBALS['xmlrpc_internalencoding'], $cha // Note: we do not check for invalid chars in VALUE: // this had better be done using pure ereg as below // Note 2: we might be removing whitespace/tabs that ought to be left in if - // the received charset is a quoted string. But nobody uses such charset names... + // the received charset is a quoted string. But nobody uses such charset names... /// @todo this test will pass if ANY header has charset specification, not only Content-Type. Fix it? $matches = array(); diff --git a/thirdparty/xmlrpc/xmlrpc_wrappers.php b/thirdparty/xmlrpc/xmlrpc_wrappers.php index cb0c6e8..1a663f0 100644 --- a/thirdparty/xmlrpc/xmlrpc_wrappers.php +++ b/thirdparty/xmlrpc/xmlrpc_wrappers.php @@ -5,7 +5,7 @@ * * @version $Id: xmlrpc_wrappers.inc,v 1.13 2008/09/20 01:23:47 ggiunta Exp $ * @author Gaetano Giunta - * @copyright (C) 2006-2008 G. Giunta + * @copyright (C) 2006-2009 G. Giunta * @license code licensed under the BSD License: http://phpxmlrpc.sourceforge.net/license.txt * * @todo separate introspection from code generation for func-2-method wrapping @@ -22,6 +22,7 @@ * accepted come from javadoc blocks), return corresponding phpxmlrpc type. * NB: for php 'resource' types returns empty string, since resources cannot be serialized; * for php class names returns 'struct', since php objects can be serialized as xmlrpc structs + * for php arrays always return array, even though arrays sometiles serialize as json structs * @param string $phptype * @return string */ @@ -157,6 +158,10 @@ } $exists = false; + if (is_string($funcname) && strpos($funcname, '::') !== false) + { + $funcname = explode('::', $funcname); + } if(is_array($funcname)) { if(count($funcname) < 2 || (!is_string($funcname[0]) && !is_object($funcname[0]))) @@ -173,6 +178,11 @@ $plainfuncname = get_class($funcname[0]) . '->' . $funcname[1]; } $exists = method_exists($funcname[0], $funcname[1]); + if (!$exists && version_compare(phpversion(), '5.1') < 0) + { + // workaround for php 5.0: static class methods are not seen by method_exists + $exists = is_callable( $funcname ); + } } else { @@ -214,7 +224,7 @@ // start to introspect PHP code if(is_array($funcname)) { - $func =& new ReflectionMethod($funcname[0], $funcname[1]); + $func = new ReflectionMethod($funcname[0], $funcname[1]); if($func->isPrivate()) { error_log('XML-RPC: method to be wrapped is private: '.$plainfuncname); @@ -230,7 +240,8 @@ error_log('XML-RPC: method to be wrapped is the constructor: '.$plainfuncname); return false; } - if($func->isDestructor()) + // php 503 always says isdestructor = true... + if( version_compare(phpversion(), '5.0.3') != 0 && $func->isDestructor()) { error_log('XML-RPC: method to be wrapped is the destructor: '.$plainfuncname); return false; @@ -244,7 +255,7 @@ } else { - $func =& new ReflectionFunction($funcname); + $func = new ReflectionFunction($funcname); } if($func->isInternal()) { @@ -504,7 +515,7 @@ if ($methodfilter == '' || preg_match($methodfilter, $mname)) { // echo $mlist."\n"; - $func =& new ReflectionMethod($classname, $mname); + $func = new ReflectionMethod($classname, $mname); if(!$func->isPrivate() && !$func->isProtected() && !$func->isConstructor() && !$func->isDestructor() && !$func->isAbstract()) { if(($func->isStatic && ($methodtype == 'all' || $methodtype == 'static' || ($methodtype == 'auto' && is_string($classname)))) || @@ -600,7 +611,7 @@ $valclass = $prefix.'val'; $decodefunc = 'php_'.$prefix.'_decode'; - $msg =& new $msgclass('system.methodSignature'); + $msg = new $msgclass('system.methodSignature'); $msg->addparam(new $valclass($methodname)); $client->setDebug($debug); $response =& $client->send($msg, $timeout, $protocol); @@ -646,7 +657,7 @@ // in online mode, favour speed of operation if(!$buildit) { - $msg =& new $msgclass('system.methodHelp'); + $msg = new $msgclass('system.methodHelp'); $msg->addparam(new $valclass($methodname)); $response =& $client->send($msg, $timeout, $protocol); if (!$response->faultCode()) @@ -715,7 +726,7 @@ //$valclass = $prefix.'val'; $decodefunc = 'php_'.$prefix.'_decode'; - $msg =& new $msgclass('system.listMethods'); + $msg = new $msgclass('system.listMethods'); $response =& $client->send($msg, $timeout, $protocol); if($response->faultCode()) { @@ -835,7 +846,7 @@ $innercode = ''; $this_ = 'this->'; } - $innercode .= "\$msg =& new {$prefix}msg('$methodname');\n"; + $innercode .= "\$msg = new {$prefix}msg('$methodname');\n"; if ($mdesc != '') { @@ -858,7 +869,7 @@ $ptype == 'string' || $ptype == 'dateTime.iso8601' || $ptype == 'base64' || $ptype == 'null') { // only build directly xmlrpcvals when type is known and scalar - $innercode .= "\$p$i =& new {$prefix}val(\$p$i, '$ptype');\n"; + $innercode .= "\$p$i = new {$prefix}val(\$p$i, '$ptype');\n"; } else { @@ -920,7 +931,7 @@ */ function build_client_wrapper_code($client, $verbatim_client_copy, $prefix='xmlrpc') { - $code = "\$client =& new {$prefix}_client('".str_replace("'", "\'", $client->path). + $code = "\$client = new {$prefix}_client('".str_replace("'", "\'", $client->path). "', '" . str_replace("'", "\'", $client->server) . "', $client->port);\n"; // copy all client fields to the client that will be generated runtime diff --git a/thirdparty/xmlrpc/xmlrpcs.php b/thirdparty/xmlrpc/xmlrpcs.php index a089ca5..441dc3d 100644 --- a/thirdparty/xmlrpc/xmlrpcs.php +++ b/thirdparty/xmlrpc/xmlrpcs.php @@ -85,13 +85,13 @@ $outAr=array(); foreach($server->dmap as $key => $val) { - $outAr[]=&new xmlrpcval($key, 'string'); + $outAr[]=new xmlrpcval($key, 'string'); } if($server->allow_system_funcs) { foreach($GLOBALS['_xmlrpcs_dmap'] as $key => $val) { - $outAr[]=&new xmlrpcval($key, 'string'); + $outAr[]=new xmlrpcval($key, 'string'); } } return new xmlrpcresp(new xmlrpcval($outAr, 'array')); @@ -130,22 +130,22 @@ $cursig=array(); foreach($inSig as $sig) { - $cursig[]=&new xmlrpcval($sig, 'string'); + $cursig[]=new xmlrpcval($sig, 'string'); } - $sigs[]=&new xmlrpcval($cursig, 'array'); + $sigs[]=new xmlrpcval($cursig, 'array'); } - $r=&new xmlrpcresp(new xmlrpcval($sigs, 'array')); + $r=new xmlrpcresp(new xmlrpcval($sigs, 'array')); } else { // NB: according to the official docs, we should be returning a // "none-array" here, which means not-an-array - $r=&new xmlrpcresp(new xmlrpcval('undef', 'string')); + $r=new xmlrpcresp(new xmlrpcval('undef', 'string')); } } else { - $r=&new xmlrpcresp(0,$GLOBALS['xmlrpcerr']['introspect_unknown'], $GLOBALS['xmlrpcstr']['introspect_unknown']); + $r=new xmlrpcresp(0,$GLOBALS['xmlrpcerr']['introspect_unknown'], $GLOBALS['xmlrpcstr']['introspect_unknown']); } return $r; } @@ -177,16 +177,16 @@ { if(isset($dmap[$methName]['docstring'])) { - $r=&new xmlrpcresp(new xmlrpcval($dmap[$methName]['docstring']), 'string'); + $r=new xmlrpcresp(new xmlrpcval($dmap[$methName]['docstring']), 'string'); } else { - $r=&new xmlrpcresp(new xmlrpcval('', 'string')); + $r=new xmlrpcresp(new xmlrpcval('', 'string')); } } else { - $r=&new xmlrpcresp(0, $GLOBALS['xmlrpcerr']['introspect_unknown'], $GLOBALS['xmlrpcstr']['introspect_unknown']); + $r=new xmlrpcresp(0, $GLOBALS['xmlrpcerr']['introspect_unknown'], $GLOBALS['xmlrpcstr']['introspect_unknown']); } return $r; } @@ -207,8 +207,8 @@ $str = $err->faultString(); } $struct = array(); - $struct['faultCode'] =& new xmlrpcval($code, 'int'); - $struct['faultString'] =& new xmlrpcval($str, 'string'); + $struct['faultCode'] = new xmlrpcval($code, 'int'); + $struct['faultString'] = new xmlrpcval($str, 'string'); return new xmlrpcval($struct, 'struct'); } @@ -243,7 +243,7 @@ } $numParams = $params->arraysize(); - $msg =& new xmlrpcmsg($methName->scalarval()); + $msg = new xmlrpcmsg($methName->scalarval()); for($i = 0; $i < $numParams; $i++) { if(!$msg->addParam($params->arraymem($i))) @@ -365,6 +365,7 @@ $GLOBALS['_xmlrpcs_occurred_errors'] = ''; $GLOBALS['_xmlrpcs_prev_ehandler'] = ''; + /** * Error handler used to track errors that occur during server-side execution of PHP code. * This allows to report back to the client whether an internal error has occurred or not @@ -381,7 +382,7 @@ return; //if($errcode != E_NOTICE && $errcode != E_WARNING && $errcode != E_USER_NOTICE && $errcode != E_USER_WARNING) - if($errcode != 2048) // do not use E_STRICT by name, since on PHP 4 it will not be defined + if($errcode != E_STRICT) { $GLOBALS['_xmlrpcs_occurred_errors'] = $GLOBALS['_xmlrpcs_occurred_errors'] . $errstring . "\n"; } @@ -432,17 +433,34 @@ class xmlrpc_server { - /// array defining php functions exposed as xmlrpc methods by this server + /** + * Array defining php functions exposed as xmlrpc methods by this server + * @access private + */ var $dmap=array(); /** - * Defines how functions in dmap will be invokde: either using an xmlrpc msg object + * Defines how functions in dmap will be invoked: either using an xmlrpc msg object * or plain php values. * valid strings are 'xmlrpcvals', 'phpvals' or 'epivals' */ var $functions_parameters_type='xmlrpcvals'; + /** + * Option used for fine-tuning the encoding the php values returned from + * functions registered in the dispatch map when the functions_parameters_types + * member is set to 'phpvals' + * @see php_xmlrpc_encode for a list of values + */ + var $phpvals_encoding_options = array( 'auto_dates' ); /// controls wether the server is going to echo debugging messages back to the client as comments in response body. valid values: 0,1,2,3 var $debug = 1; /** + * Controls behaviour of server when invoked user function throws an exception: + * 0 = catch it and return an 'internal error' xmlrpc response (default) + * 1 = catch it and return an xmlrpc response with the error corresponding to the exception + * 2 = allow the exception to float to the upper layers + */ + var $exception_handling = 0; + /** * When set to true, it will enable HTTP compression of the response, in case * the client has declared its support for compression in the request. */ @@ -466,9 +484,14 @@ * NB: pretty dangerous if you accept every charset and do not have mbstring enabled) */ var $response_charset_encoding = ''; - /// storage for internal debug info + /** + * Storage for internal debug info + * @access private + */ var $debug_info = ''; - /// extra data passed at runtime to method handling functions. Used only by EPI layer + /** + * Extra data passed at runtime to method handling functions. Used only by EPI layer + */ var $user_data = null; /** @@ -659,7 +682,7 @@ } else { - error_log('XML-RPC: xmlrpc_server::service: http headers already sent before response is fully generated. Check for php warning or error messages'); + error_log('XML-RPC: '.__METHOD__.': http headers already sent before response is fully generated. Check for php warning or error messages'); } print $payload; @@ -689,7 +712,7 @@ } if ($sigdoc) { - $this->dmap[$methodname]['signature_docs'] = $sigdoc; + $this->dmap[$methodname]['signature_docs'] = $sigdoc; } } @@ -731,7 +754,7 @@ } else { - $pt= $in[$n] == 'i4' ? 'int' : $in[$n]; // dispatch maps never use i4... + $pt= $in[$n] == 'i4' ? 'int' : strtolower($in[$n]); // dispatch maps never use i4... } // param index is $n+1, as first member of sig is return type @@ -767,10 +790,11 @@ */ function parseRequestHeaders(&$data, &$req_encoding, &$resp_encoding, &$resp_compression) { - // Play nice to PHP 4.0.x: superglobals were not yet invented... - if(!isset($_SERVER)) + // check if $_SERVER is populated: it might have been disabled via ini file + // (this is true even when in CLI mode) + if (count($_SERVER) == 0) { - $_SERVER = $GLOBALS['HTTP_SERVER_VARS']; + error_log('XML-RPC: '.__METHOD__.': cannot parse request headers as $_SERVER is not populated'); } if($this->debug > 1) @@ -819,14 +843,14 @@ } else { - $r =& new xmlrpcresp(0, $GLOBALS['xmlrpcerr']['server_decompress_fail'], $GLOBALS['xmlrpcstr']['server_decompress_fail']); + $r = new xmlrpcresp(0, $GLOBALS['xmlrpcerr']['server_decompress_fail'], $GLOBALS['xmlrpcstr']['server_decompress_fail']); return $r; } } else { //error_log('The server sent deflated data. Your php install must have the Zlib extension compiled in to support this.'); - $r =& new xmlrpcresp(0, $GLOBALS['xmlrpcerr']['server_cannot_decompress'], $GLOBALS['xmlrpcstr']['server_cannot_decompress']); + $r = new xmlrpcresp(0, $GLOBALS['xmlrpcerr']['server_cannot_decompress'], $GLOBALS['xmlrpcstr']['server_cannot_decompress']); return $r; } } @@ -919,7 +943,7 @@ // makes the lib about 200% slower... //if (!is_valid_charset($req_encoding, array('UTF-8', 'ISO-8859-1', 'US-ASCII'))) { - error_log('XML-RPC: xmlrpc_server::parseRequest: invalid charset encoding of received request: '.$req_encoding); + error_log('XML-RPC: '.__METHOD__.': invalid charset encoding of received request: '.$req_encoding); $req_encoding = $GLOBALS['xmlrpc_defencoding']; } /// @BUG this will fail on PHP 5 if charset is not specified in the xml prologue, @@ -957,7 +981,7 @@ if(!xml_parse($parser, $data, 1)) { // return XML error as a faultCode - $r=&new xmlrpcresp(0, + $r=new xmlrpcresp(0, $GLOBALS['xmlrpcerrxml']+xml_get_error_code($parser), sprintf('XML error: %s at line %d, column %d', xml_error_string(xml_get_error_code($parser)), @@ -967,14 +991,18 @@ elseif ($GLOBALS['_xh']['isf']) { xml_parser_free($parser); - $r=&new xmlrpcresp(0, + $r=new xmlrpcresp(0, $GLOBALS['xmlrpcerr']['invalid_request'], $GLOBALS['xmlrpcstr']['invalid_request'] . ' ' . $GLOBALS['_xh']['isf_reason']); } else { xml_parser_free($parser); - if ($this->functions_parameters_type != 'xmlrpcvals') + // small layering violation in favor of speed and memory usage: + // we should allow the 'execute' method handle this, but in the + // most common scenario (xmlrpcvals type server with some methods + // registered as phpvals) that would mean a useless encode+decode pass + if ($this->functions_parameters_type != 'xmlrpcvals' || (isset($this->dmap[$GLOBALS['_xh']['method']]['parameters_type']) && ($this->dmap[$GLOBALS['_xh']['method']]['parameters_type'] == 'phpvals'))) { if($this->debug > 1) { @@ -985,7 +1013,7 @@ else { // build an xmlrpcmsg object with data parsed from xml - $m=&new xmlrpcmsg($GLOBALS['_xh']['method']); + $m=new xmlrpcmsg($GLOBALS['_xh']['method']); // now add parameters in for($i=0; $ifunctions_parameters_type == 'epivals') + if (!is_a($r, 'xmlrpcresp')) { - $r = call_user_func_array($func, array($methName, $params, $this->user_data)); - // mimic EPI behaviour: if we get an array that looks like an error, make it - // an eror response - if (is_array($r) && array_key_exists('faultCode', $r) && array_key_exists('faultString', $r)) + error_log("XML-RPC: ".__METHOD__.": function $func registered as method handler does not return an xmlrpcresp object"); + if (is_a($r, 'xmlrpcval')) { - $r =& new xmlrpcresp(0, (integer)$r['faultCode'], (string)$r['faultString']); + $r = new xmlrpcresp($r); } else { - // functions using EPI api should NOT return resp objects, - // so make sure we encode the return type correctly - $r =& new xmlrpcresp(php_xmlrpc_encode($r, array('extension_api'))); + $r = new xmlrpcresp( + 0, + $GLOBALS['xmlrpcerr']['server_error'], + $GLOBALS['xmlrpcstr']['server_error'] . ": function does not return xmlrpcresp object" + ); } } + } + else + { + // call a 'plain php' function + if($sysCall) + { + array_unshift($params, $this); + $r = call_user_func_array($func, $params); + } else { - $r = call_user_func_array($func, $params); + // 3rd API convention for method-handling functions: EPI-style + if ($this->functions_parameters_type == 'epivals') + { + $r = call_user_func_array($func, array($methName, $params, $this->user_data)); + // mimic EPI behaviour: if we get an array that looks like an error, make it + // an eror response + if (is_array($r) && array_key_exists('faultCode', $r) && array_key_exists('faultString', $r)) + { + $r = new xmlrpcresp(0, (integer)$r['faultCode'], (string)$r['faultString']); + } + else + { + // functions using EPI api should NOT return resp objects, + // so make sure we encode the return type correctly + $r = new xmlrpcresp(php_xmlrpc_encode($r, array('extension_api'))); + } + } + else + { + $r = call_user_func_array($func, $params); + } + } + // the return type can be either an xmlrpcresp object or a plain php value... + if (!is_a($r, 'xmlrpcresp')) + { + // what should we assume here about automatic encoding of datetimes + // and php classes instances??? + $r = new xmlrpcresp(php_xmlrpc_encode($r, $this->phpvals_encoding_options)); } } - // the return type can be either an xmlrpcresp object or a plain php value... - if (!is_a($r, 'xmlrpcresp')) + } + catch(Exception $e) + { + // (barring errors in the lib) an uncatched exception happened + // in the called function, we wrap it in a proper error-response + switch($this->exception_handling) { - // what should we assume here about automatic encoding of datetimes - // and php classes instances??? - $r =& new xmlrpcresp(php_xmlrpc_encode($r, array('auto_dates'))); + case 2: + throw $e; + break; + case 1: + $r = new xmlrpcresp(0, $e->getCode(), $e->getMessage()); + break; + default: + $r = new xmlrpcresp(0, $GLOBALS['xmlrpcerr']['server_error'], $GLOBALS['xmlrpcstr']['server_error']); } } if($this->debug > 2) @@ -1191,7 +1239,7 @@ */ function echoInput() { - $r=&new xmlrpcresp(new xmlrpcval( "'Aha said I: '" . $GLOBALS['HTTP_RAW_POST_DATA'], 'string')); + $r=new xmlrpcresp(new xmlrpcval( "'Aha said I: '" . $GLOBALS['HTTP_RAW_POST_DATA'], 'string')); print $r->serialize(); } } From 3cefdf4416c33a4cbabf3eec7558e30c8a3c75b4 Mon Sep 17 00:00:00 2001 From: carlos barberis Date: Sat, 19 May 2012 15:26:45 +1200 Subject: [PATCH 09/10] BUGFIX: compatible with new FieldList (SS3) --- code/BlogHolder.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/BlogHolder.php b/code/BlogHolder.php index 1425d59..859e500 100644 --- a/code/BlogHolder.php +++ b/code/BlogHolder.php @@ -241,7 +241,7 @@ class BlogHolder_Controller extends BlogTree_Controller { $entry = DataObject::get_by_id('BlogEntry', $id); if($entry->IsOwner()) { $form->loadDataFrom($entry); - $form->datafieldByName('BlogPost')->setValue($entry->Content); + $form->Fields()->fieldByName('BlogPost')->setValue($entry->Content); } } else { $form->loadDataFrom(array("Author" => Cookie::get("BlogHolder_Name"))); From 31c56ca471b9725000368bfd812b58c21c2764c7 Mon Sep 17 00:00:00 2001 From: carlos barberis Date: Sat, 19 May 2012 15:27:29 +1200 Subject: [PATCH 10/10] BUGFIX: get rid of unnecessary code in BlogEntry::unpublishPost --- code/BlogEntry.php | 3 --- 1 file changed, 3 deletions(-) diff --git a/code/BlogEntry.php b/code/BlogEntry.php index 736c4cd..31571c7 100644 --- a/code/BlogEntry.php +++ b/code/BlogEntry.php @@ -254,9 +254,6 @@ class BlogEntry_Controller extends Page_Controller { $page = DataObject::get_by_id('SiteTree', $SQL_id); $page->deleteFromStage('Live'); $page->flushCache(); - - $page = DataObject::get_by_id('SiteTree', $SQL_id); - $page->Status = 'Unpublished'; Director::redirect($this->getParent()->Link()); }