Passed
Push — master ( b81870...2e14d2 )
by Gaetano
08:05
created

forward_request()   C

Complexity

Conditions 17
Paths 4

Size

Total Lines 75
Code Lines 44

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 222.7341

Importance

Changes 2
Bugs 0 Features 1
Metric Value
cc 17
eloc 44
c 2
b 0
f 1
nc 4
nop 1
dl 0
loc 75
ccs 3
cts 28
cp 0.1071
crap 222.7341
rs 5.2166

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/**
3
 * XML-RPC server acting as proxy for requests to other servers
4
 * (useful e.g. for js-originated calls that can only connect back to the originating server because of the same-domain policy).
5
 * NB: this is an OPEN RELAY. It is meant as a demo, not to be used in production!
6
 * For an example of a transparent reverse-proxy, see the ReverseProxy class in package phpxmlrpc/extras.
7
 *
8
 * The source code demonstrates:
9
 * - usage of the PhpXmlRpc\Encoder class to convert between php values and xml-rpc Value objects
10
 * - setting of options related to the http transport to a Client
11
 * - usage of multiple signatures for one xml-rpc method
12
 *
13
 * @author Gaetano Giunta
14
 * @copyright (C) 2006-2023 G. Giunta
15
 * @license code licensed under the BSD License: see file license.txt
16
 */
17
18
require_once __DIR__ . "/_prepend.php";
19
20
// *** NB: WE BLOCK THIS FROM RUNNING BY DEFAULT IN CASE ACCESS IS GRANTED TO IT IN PRODUCTION BY MISTAKE ***
21
// Comment out the following safeguard if you want to use it as is, but remember: this is an open relay !!!
22
// Open relays can easily be abused as trojan horses, allowing access to your private network.
23
if (!defined('TESTMODE')) {
24
    die("Server disabled by default for safety");
25
}
26
27
use PhpXmlRpc\Client;
28
use PhpXmlRpc\Encoder;
29
use PhpXmlRpc\Request;
30
use PhpXmlRpc\Server;
31
32
/**
33
 * Forward an xml-rpc request to another server, and return to client the response received.
34
 *
35
 * @param PhpXmlRpc\Request $req (see method docs below for a description of the expected parameters)
36
 * @return PhpXmlRpc\Response
37
 */
38
function forward_request($req)
39
{
40
    $encoder = new Encoder();
41
42
    // create client
43
    $timeout = 0;
44
    $url = $req->getParam(0)->scalarval();
45
    // *** NB *** here we should validate the received url, using f.e. a whitelist of approved servers _and protocols_...
46
    //            fe. any url using the 'file://' protocol might be considered a hacking attempt
47
    $client = new Client($url);
48
49
    if ($req->getNumParams() > 3) {
50
        // We have to set some options onto the client.
51
        // Note that if we do not untaint the received values, warnings might be generated...
52
        $options = $encoder->decode($req->getParam(3));
53
        foreach ($options as $key => $val) {
54
            switch ($key) {
55
                case 'authType':
56
                    /// @todo add support for this if needed
57
                    break;
58
                case 'followRedirects':
59
                    // requires cURL to be enabled
60
                    if ($val) {
61
                        $client->use_curl = Client::USE_CURL_ALWAYS;
62
                        $client->setCurlOptions(array(CURLOPT_FOLLOWLOCATION => true, CURLOPT_POSTREDIR => 3));
63
                    }
64
                case 'Cookies':
65
                    /// @todo add support for this if needed
66
                    break;
67
                case 'Credentials':
68
                    /// @todo add support for this as well if needed
69
                    break;
70
                case 'HTTPProxy':
71
                case 'HTTPProxyCredentials':
72
                    /// @todo add support for this as well if needed
73
                    break;
74
                case 'RequestCharsetEncoding':
75
                    // allow the server to work as charset transcoder.
76
                    // NB: works best with mbstring enabled
77
                    $client->request_charset_encoding = $val;
78
                    break;
79
                case 'RequestCompression':
80 1
                    $client->setRequestCompression($val);
81
                    break;
82
                case 'SSLVerifyHost':
83 1
                    $client->setSSLVerifyHost($val);
84
                    break;
85
                case 'SSLVerifyPeer':
86
                    $client->setSSLVerifyPeer($val);
87
                    break;
88
                case 'Timeout':
89
                    $timeout = (integer)$val;
90
                    break;
91
            } // switch
92
        }
93 1
    }
94
95
    // build call for remote server
96
    /// @todo find a way to forward client info (such as IP) to the upstream server, either
97
    ///       - as xml comments in the payload, or
98
    ///       - using std http header conventions, such as X-forwarded-for (but public servers should strip
99
    ///         X-forwarded-for anyway, unless they consider this server as trusted...)
100
    $reqMethod = $req->getParam(1)->scalarval();
101
    $req = new Request($reqMethod);
102
    if ($req->getNumParams() > 1) {
103
        $pars = $req->getParam(2);
104
        foreach ($pars as $par) {
105
            $req->addParam($par);
106
        }
107
    }
108
109
    // add debug info into response we give back to caller
110
    Server::xmlrpc_debugmsg("Sending to server $url the payload: " . $req->serialize());
111
112
    return $client->send($req, $timeout);
113
}
114
115
// Given that the target server is left to be picked by the caller, it might support the '<NIL/>' xml-rpc extension
116
PhpXmlRpc\PhpXmlRpc::$xmlrpc_null_extension = true;
117
118
// Run the server
119
// NB: take care not to output anything else after this call, as it will mess up the responses and it will be hard to
120
// debug. In case you have to do so, at least re-emit a correct Content-Length http header (requires output buffering)
121
$server = new Server(
122
    array(
123
        'xmlrpcproxy.call' => array(
124
            'function' => 'forward_request',
125
            'signature' => array(
126
                array('mixed', 'string', 'string'),
127
                array('mixed', 'string', 'string', 'array'),
128
                array('mixed', 'string', 'string', 'array', 'struct'),
129
            ),
130
            'docstring' => 'forwards xml-rpc calls to remote servers. Returns remote method\'s response. Accepts params: remote server url (might include basic auth credentials), method name, array of params (optional), and a struct containing call options (optional)',
131
        ),
132
    )
133
);
134