XML_RPC_Message::parseResponse PHP Method

parseResponse() public method

Parse External XML-RPC Server's Response
public parseResponse ( $fp ) : object
return object
    public function parseResponse($fp)
    {
        $data = '';
        while ($datum = fread($fp, 4096)) {
            $data .= $datum;
        }
        // Display HTTP content for debugging
        if ($this->debug === TRUE) {
            echo "<pre>---DATA---\n" . htmlspecialchars($data) . "\n---END DATA---\n\n</pre>";
        }
        // Check for data
        if ($data === '') {
            error_log($this->xmlrpcstr['no_data']);
            return new XML_RPC_Response(0, $this->xmlrpcerr['no_data'], $this->xmlrpcstr['no_data']);
        }
        // Check for HTTP 200 Response
        if (strpos($data, 'HTTP') === 0 && !preg_match('/^HTTP\\/[0-9\\.]+ 200 /', $data)) {
            $errstr = substr($data, 0, strpos($data, "\n") - 1);
            return new XML_RPC_Response(0, $this->xmlrpcerr['http_error'], $this->xmlrpcstr['http_error'] . ' (' . $errstr . ')');
        }
        //-------------------------------------
        // Create and Set Up XML Parser
        //-------------------------------------
        $parser = xml_parser_create($this->xmlrpc_defencoding);
        $pname = (string) $parser;
        $this->xh[$pname] = array('isf' => 0, 'ac' => '', 'headers' => array(), 'stack' => array(), 'valuestack' => array(), 'isf_reason' => 0);
        xml_set_object($parser, $this);
        xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, TRUE);
        xml_set_element_handler($parser, 'open_tag', 'closing_tag');
        xml_set_character_data_handler($parser, 'character_data');
        //xml_set_default_handler($parser, 'default_handler');
        // Get headers
        $lines = explode("\r\n", $data);
        while ($line = array_shift($lines)) {
            if (strlen($line) < 1) {
                break;
            }
            $this->xh[$pname]['headers'][] = $line;
        }
        $data = implode("\r\n", $lines);
        // Parse XML data
        if (!xml_parse($parser, $data, count($data))) {
            $errstr = sprintf('XML error: %s at line %d', xml_error_string(xml_get_error_code($parser)), xml_get_current_line_number($parser));
            $r = new XML_RPC_Response(0, $this->xmlrpcerr['invalid_return'], $this->xmlrpcstr['invalid_return']);
            xml_parser_free($parser);
            return $r;
        }
        xml_parser_free($parser);
        // Got ourselves some badness, it seems
        if ($this->xh[$pname]['isf'] > 1) {
            if ($this->debug === TRUE) {
                echo "---Invalid Return---\n" . $this->xh[$pname]['isf_reason'] . "---Invalid Return---\n\n";
            }
            return new XML_RPC_Response(0, $this->xmlrpcerr['invalid_return'], $this->xmlrpcstr['invalid_return'] . ' ' . $this->xh[$pname]['isf_reason']);
        } elseif (!is_object($this->xh[$pname]['value'])) {
            return new XML_RPC_Response(0, $this->xmlrpcerr['invalid_return'], $this->xmlrpcstr['invalid_return'] . ' ' . $this->xh[$pname]['isf_reason']);
        }
        // Display XML content for debugging
        if ($this->debug === TRUE) {
            echo '<pre>';
            if (count($this->xh[$pname]['headers'] > 0)) {
                echo "---HEADERS---\n";
                foreach ($this->xh[$pname]['headers'] as $header) {
                    echo $header . "\n";
                }
                echo "---END HEADERS---\n\n";
            }
            echo "---DATA---\n" . htmlspecialchars($data) . "\n---END DATA---\n\n---PARSED---\n";
            var_dump($this->xh[$pname]['value']);
            echo "\n---END PARSED---</pre>";
        }
        // Send response
        $v = $this->xh[$pname]['value'];
        if ($this->xh[$pname]['isf']) {
            $errno_v = $v->me['struct']['faultCode'];
            $errstr_v = $v->me['struct']['faultString'];
            $errno = $errno_v->scalarval();
            if ($errno === 0) {
                // FAULT returned, errno needs to reflect that
                $errno = -1;
            }
            $r = new XML_RPC_Response($v, $errno, $errstr_v->scalarval());
        } else {
            $r = new XML_RPC_Response($v);
        }
        $r->headers = $this->xh[$pname]['headers'];
        return $r;
    }

Usage Example

    function event_hook($event, &$bag, &$eventData)
    {
        global $serendipity;
        $hooks =& $bag->get('event_hooks');
        if (isset($hooks[$event])) {
            switch ($event) {
                case 'backend_display':
                    ?>
                    <fieldset style="margin: 5px">
                        <legend><?php 
                    echo PLUGIN_EVENT_WEBLOGPING_PING;
                    ?>
</legend>
<?php 
                    $noneclick = '';
                    foreach ($this->services as $index => $service) {
                        // Detect if the current checkbox needs to be saved. We use the field chk_timestamp to see,
                        // if the form has already been submitted and individual changes shall be preserved
                        $selected = $serendipity['POST']['chk_timestamp'] && $serendipity['POST']['announce_entries_' . $service['name']] || !isset($serendipity['POST']['chk_timestamp']) && $this->get_config($service['name']) == 'true' ? 'checked="checked"' : '';
                        $noneclick .= 'document.getElementById(\'serendipity[announce_entries_' . $service['name'] . ']\').checked = false; ';
                        $onclick = '';
                        if (!empty($service['supersedes'])) {
                            $onclick = 'onclick="';
                            $supersedes = explode(', ', $service['supersedes']);
                            foreach ($supersedes as $sid => $servicename) {
                                $onclick .= 'document.getElementById(\'serendipity[announce_entries_' . $servicename . ']\').checked = false; ';
                            }
                            $onclick .= '"';
                        }
                        $title = sprintf(PLUGIN_EVENT_WEBLOGPING_SENDINGPING, $service['name']) . (!empty($service['supersedes']) ? ' ' . sprintf(PLUGIN_EVENT_WEBLOGPING_SUPERSEDES, $service['supersedes']) : '');
                        ?>
                            <input <?php 
                        echo $onclick;
                        ?>
 class="input_checkbox" style="margin: 0px; padding: 0px; vertical-align: bottom;" type="checkbox" name="serendipity[announce_entries_<?php 
                        echo $service['name'];
                        ?>
]" id="serendipity[announce_entries_<?php 
                        echo $service['name'];
                        ?>
]" value="true" <?php 
                        echo $selected;
                        ?>
 />
                                <label title="<?php 
                        echo $title;
                        ?>
" style="vertical-align: bottom; margin: 0px; padding: 0px;" for="serendipity[announce_entries_<?php 
                        echo $service['name'];
                        ?>
]">&nbsp;<?php 
                        echo $service['name'];
                        ?>
&nbsp;&nbsp;</label><br />
<?php 
                    }
                    ?>
                            <input onclick="<?php 
                    echo $noneclick;
                    ?>
" class="input_checkbox" style="margin: 0px; padding: 0px; vertical-align: bottom;" type="checkbox" value="none" id="serendipity[announce_entries_none]" />
                                <label title="<?php 
                    echo NONE;
                    ?>
" style="vertical-align: bottom; margin: 0px; padding: 0px;" for="serendipity[announce_entries_none]">&nbsp;<?php 
                    echo NONE;
                    ?>
&nbsp;&nbsp;</label><br />
                    </fieldset>
<?php 
                    return true;
                    break;
                case 'backend_publish':
                    if (!class_exists('XML_RPC_Base')) {
                        include_once S9Y_PEAR_PATH . "XML/RPC.php";
                    }
                    // First cycle through list of services to remove superseding services which may have been checked
                    foreach ($this->services as $index => $service) {
                        if (!empty($service['supersedes']) && isset($serendipity['POST']['announce_entries_' . $service['name']])) {
                            $supersedes = explode(', ', $service['supersedes']);
                            foreach ($supersedes as $sid => $servicename) {
                                // A service has been checked that is superseded by another checked meta-service. Remove that service from the list of services to be ping'd
                                unset($serendipity['POST']['announce_entries_' . $servicename]);
                            }
                        }
                    }
                    foreach ($this->services as $index => $service) {
                        if (isset($serendipity['POST']['announce_entries_' . $service['name']]) || defined('SERENDIPITY_IS_XMLRPC') && serendipity_db_bool($this->get_config($service['name']))) {
                            if (!defined('SERENDIPITY_IS_XMLRPC') || defined('SERENDIPITY_XMLRPC_VERBOSE')) {
                                printf(PLUGIN_EVENT_WEBLOGPING_SENDINGPING . '...', $service['host']);
                            }
                            flush();
                            # XXX append $serendipity['indexFile'] to baseURL?
                            $args = array(new XML_RPC_Value($serendipity['blogTitle'], 'string'), new XML_RPC_Value($serendipity['baseURL'], 'string'));
                            if ($service['extended']) {
                                # the checkUrl: for when the main page is not really the main page
                                $args[] = new XML_RPC_Value('', 'string');
                                # the rssUrl
                                $args[] = new XML_RPC_Value($serendipity['baseURL'] . 'rss.php?version=2.0', 'string');
                            }
                            $message = new XML_RPC_Message($service['extended'] ? 'weblogUpdates.extendedPing' : 'weblogUpdates.ping', $args);
                            $client = new XML_RPC_Client(trim($service['path']), trim($service['host']));
                            # 15 second timeout may not be long enough for weblogs.com
                            $message->createPayload();
                            $options = array();
                            serendipity_plugin_api::hook_event('backend_http_request', $options, 'weblogping');
                            serendipity_request_start();
                            $req = new HTTP_Request("http://" . $service['host'] . $service['path'], $options);
                            $req->setMethod(HTTP_REQUEST_METHOD_POST);
                            $req->addHeader("Content-Type", "text/xml");
                            if (strtoupper(LANG_CHARSET) != 'UTF-8') {
                                $payload = utf8_encode($message->payload);
                            } else {
                                $payload = $message->payload;
                            }
                            $req->addRawPostData($payload);
                            $http_result = $req->sendRequest();
                            $http_response = $req->getResponseBody();
                            $xmlrpc_result = $message->parseResponse($http_response);
                            if ($xmlrpc_result->faultCode()) {
                                $out = sprintf(PLUGIN_EVENT_WEBLOGPING_SEND_FAILURE . "<br />", htmlspecialchars($xmlrpc_result->faultString()));
                            } else {
                                $out = PLUGIN_EVENT_WEBLOGPING_SEND_SUCCESS . "<br />";
                            }
                            serendipity_request_end();
                            if (!defined('SERENDIPITY_IS_XMLRPC') || defined('SERENDIPITY_XMLRPC_VERBOSE')) {
                                echo $out;
                            }
                        }
                    }
                    return true;
                    break;
                case 'external_plugin':
                    if ($eventData == 'xmlrpc_ping') {
                        echo "XMLRPC START\n";
                        @define('SERENDIPITY_IS_XMLRPC', true);
                        @define('SERENDIPITY_XMLRPC_VERBOSE', true);
                        $this->event_hook('backend_publish', $bag, $eventData);
                        echo "XMLRPC DONE\n";
                    }
                    return true;
                case 'frontend_display':
                case 'backend_insert':
                case 'backend_update':
                case 'backend_draft':
                default:
                    return false;
                    break;
            }
        } else {
            return false;
        }
    }