Passed
Push — master ( 2d5b6d...8a7d5c )
by Gaetano
11:38
created

exampleMethods::addTwoDouble()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
eloc 3
c 0
b 0
f 0
nc 1
nop 1
dl 0
loc 6
ccs 0
cts 2
cp 0
crap 2
rs 10
1
<?php
2
/**
3
 * Defines functions and signatures which can be registered as methods exposed by an XML-RPC Server
4
 *
5
 * To use this, use something akin to:
6
 * $signatures = include('functions.php');
7
 *
8
 * Demoes a simple possible way to implement webservices without cluttering the global scope: create xml-rpc-aware static
9
 * methods in a class, and use them for the Server's dispatch map without the need to instantiate an object.
10
 *
11
 * Alternative implementation strategies are possible as well:
12
 * 1. same as above, but use non-static class methods
13
 * 2. define functions in the global scope to be used as xml-rpc method handlers: see interop.php, validator1.php
14
 * 3. define xml-rpc method handlers as anonymous functions directly within the dispatch map
15
 * 4. use php methods or functions which are not aware of xml-rpc and let the Server do all the necessary type conversion:
16
 *    see discuss.php
17
 * 5. use the PhpXmlRpc\Wrapper class to achieve the same as in point 4, with no need to manually write the dispatch map
18
 *    configuration (but taking instead a performance hit)
19 559
 * 6. use the PhpXmlRpc\Wrapper class to generate php code in offline mode, achieving the same as in point 5 with no
20
 *    performance hit at runtime
21
 */
22
23
use PhpXmlRpc\Encoder;
24
use PhpXmlRpc\Response;
25
use PhpXmlRpc\Server;
26
use PhpXmlRpc\Value;
27
28
class exampleMethods
29
{
30
    public static $stateNames = array(
31 559
        "Alabama", "Alaska", "Arizona", "Arkansas", "California",
32
        "Colorado", "Columbia", "Connecticut", "Delaware", "Florida",
33 559
        "Georgia", "Hawaii", "Idaho", "Illinois", "Indiana", "Iowa", "Kansas",
34
        "Kentucky", "Louisiana", "Maine", "Maryland", "Massachusetts", "Michigan",
35
        "Minnesota", "Mississippi", "Missouri", "Montana", "Nebraska", "Nevada",
36 22
        "New Hampshire", "New Jersey", "New Mexico", "New York", "North Carolina",
37
        "North Dakota", "Ohio", "Oklahoma", "Oregon", "Pennsylvania", "Rhode Island",
38 22
        "South Carolina", "South Dakota", "Tennessee", "Texas", "Utah", "Vermont",
39
        "Virginia", "Washington", "West Virginia", "Wisconsin", "Wyoming",
40
    );
41
42
    public static $findstate_sig = array(array('string', 'int'));
43 22
    public static $findstate_doc = 'When passed an integer between 1 and 51 returns the name of a US state, where the integer is the index of that state name in an alphabetic order.';
44
    public static function findState($req)
45 22
    {
46 22
        $err = '';
47
48
        // get the first param
49
        // param must be there and of the correct type: server object does the validation for us
50
        $sno = $req->getParam(0);
51
52
        // extract the value of the state number
53 22
        $snv = $sno->scalarval();
54
55
        // look it up in our array (zero-based)
56
        if (isset(self::$stateNames[$snv - 1])) {
57 22
            $stateName = self::$stateNames[$snv - 1];
58
        } else {
59
            // not there, so complain
60
            $err = "I don't have a state for the index '" . $snv . "'";
61
        }
62
63
        if ($err != '') {
64
            // if we generated an error, create an error return response
65
            return new Response(0, PhpXmlRpc\PhpXmlRpc::$xmlrpcerruser, $err);
66
        } else {
67
            // otherwise, we create the right response with the state name
68
            return new Response(new Value($stateName));
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $stateName does not seem to be defined for all execution paths leading up to this point.
Loading history...
69
        }
70
    }
71
72
    public static $agesorter_sig = array(array('array', 'array'));
73
    public static $agesorter_doc = 'Send this method an array of [string, int] structs, eg:
74
<pre>
75
 Dave   35
76
 Edd    45
77
 Fred   23
78
 Barney 37
79
</pre>
80
And the array will be returned with the entries sorted by their numbers.';
81
    public static function ageSorter($req)
82
    {
83
        Server::xmlrpc_debugmsg("Entering 'agesorter'");
84
85
        // error string for [if|when] things go wrong
86
        $err = '';
87
88 559
        // get the parameter, turn it into an easy-to-manipulate php array
89 559
        $enc = new Encoder();
90
        $v = $enc->decode($req->getParam(0));
91
92
        $max = count($v);
93
        Server::xmlrpc_debugmsg("Found $max array elements");
94
95
        // extract name and age from struct. The values nested inside it were not type-checked, so we do it
96
        $agar = array();
97
        foreach ($v as $i => $rec) {
98
            if (!is_array($rec)) {
99
                $err = "Found non-struct in array at element $i";
100
                break;
101
            }
102
            if (!isset($rec['name']) || !isset($rec['age'])) {
103
                Server::xmlrpc_debugmsg("Invalid array element $i: miss name or age");
104
                continue;
105
            }
106
            $agar[$rec["name"]] = $rec["age"];
107
        }
108
109
        if ($err != '') {
110
            Server::xmlrpc_debugmsg("Aborting 'agesorter'");
111
            return new Response(0, PhpXmlRpc\PhpXmlRpc::$xmlrpcerruser, $err);
112
        }
113
114
        asort($agar);
115
116
        // create the output value
117
        $o = array();
118
        foreach ($agar as $name => $age) {
119
            $o[] = array("name" => $name, "age" => $age);
120
        }
121
122
        Server::xmlrpc_debugmsg("Leaving 'agesorter'");
123
124
        return new Response($enc->encode($o));
125
    }
126
127
    public static $addtwo_sig = array(array('int', 'int', 'int'));
128
    public static $addtwo_doc = 'Add two integers together and return the result';
129
    public static function addTwo($req)
130
    {
131
        $s = $req->getParam(0);
132
        $t = $req->getParam(1);
133
134
        return new Response(new Value($s->scalarval() + $t->scalarval(), Value::$xmlrpcInt));
135
    }
136
137
    public static $addtwodouble_sig = array(array('double', 'double', 'double'));
138
    public static $addtwodouble_doc = 'Add two doubles together and return the result';
139
    public static function addTwoDouble($req)
140
    {
141
        $s = $req->getParam(0);
142
        $t = $req->getParam(1);
143
144
        return new Response(new Value($s->scalarval() + $t->scalarval(), Value::$xmlrpcDouble));
145
    }
146
147
    public static $stringecho_sig = array(array('string', 'string'));
148
    public static $stringecho_doc = 'Accepts a string parameter, returns the string.';
149 559
    function stringEcho($req)
150 559
    {
151
        // just sends back a string
152
        return new Response(new Value($req->getParam(0)->scalarval()));
153 43
    }
154 43
155
    public static $echoback_sig = array(array('string', 'string'));
156 43
    public static $echoback_doc = 'Accepts a string parameter, returns the entire incoming payload';
157
    function echoBack($req)
158
    {
159 559
        // just sends back a string with what I got sent to me, that's all (escaping for xml is automatic)
160 559
        $s = "I got the following message:\n" . $req->serialize();
161
162
        return new Response(new Value($s));
163 22
    }
164 22
165
    public static $echosixtyfour_sig = array(array('string', 'base64'));
166 22
    public static $echosixtyfour_doc = 'Accepts a base64 parameter and returns it decoded as a string';
167
    function echoSixtyFour($req)
168
    {
169 559
        // Accepts an encoded value, but sends it back as a normal string.
170 559
        // This is to test that base64 encoding is working as expected
171
        $incoming = $req->getParam(0);
172
173
        return new Response(new Value($incoming->scalarval(), Value::$xmlrpcString));
174 72
    }
175
176
    public static $bitflipper_sig = array(array('array', 'array'));
177 559
    public static $bitflipper_doc = 'Accepts an array of booleans, and returns them inverted';
178 559
    function bitFlipper($req)
179
    {
180
        $v = $req->getParam(0);
181
        $rv = new Value(array(), Value::$xmlrpcArray);
182
183
        foreach ($v as $b) {
184
            if ($b->scalarval()) {
185
                $rv[] = new Value(false, Value::$xmlrpcBoolean);
186
            } else {
187 559
                $rv[] = new Value(true, Value::$xmlrpcBoolean);
188 559
            }
189
        }
190
191
        return new Response($rv);
192
    }
193 22
194
    public static $mailsend_sig = array(array(
195 22
        'boolean', 'string', 'string',
196
        'string', 'string', 'string',
197
        'string', 'string',
198 559
    ));
199 559
    public static $mailsend_doc = 'mail.send(recipient, subject, text, sender, cc, bcc, mimetype)<br/>
200
recipient, cc, and bcc are strings, comma-separated lists of email addresses, as described above.<br/>
201
subject is a string, the subject of the message.<br/>
202 22
sender is a string, it\'s the email address of the person sending the message. This string can not be
203 22
a comma-separated list, it must contain a single email address only.<br/>
204
text is a string, it contains the body of the message.<br/>
205 22
mimetype, a string, is a standard MIME type, for example, text/plain.';
206 22
    /**
207 22
     * WARNING: this functionality depends on the sendmail -t option, it may not work with Windows machines properly;
208
     * particularly the Bcc option.
209 22
     * Sneak on your friends at your own risk!
210
     */
211
    public static function mailSend($req)
212
    {
213 22
        $err = "";
214
215
        $mTo = $req->getParam(0);
216 559
        $mSub = $req->getParam(1);
217 559
        $mBody = $req->getParam(2);
218
        $mFrom = $req->getParam(3);
219
        $mCc = $req->getParam(4);
220
        $mBcc = $req->getParam(5);
221
        $mMime = $req->getParam(6);
222
223
        if ($mTo->scalarval() == "") {
224
            $err = "Error, no 'To' field specified";
225
        }
226
227
        if ($mFrom->scalarval() == "") {
228
            $err = "Error, no 'From' field specified";
229
        }
230
231
        /// @todo in real life, we should check for presence of return characters to avoid header injection!
232
233
        $msgHdr = "From: " . $mFrom->scalarval() . "\n";
234
        $msgHdr .= "To: " . $mTo->scalarval() . "\n";
235
236
        if ($mCc->scalarval() != "") {
237
            $msgHdr .= "Cc: " . $mCc->scalarval() . "\n";
238 559
        }
239 559
        if ($mBcc->scalarval() != "") {
240
            $msgHdr .= "Bcc: " . $mBcc->scalarval() . "\n";
241
        }
242 22
        if ($mMime->scalarval() != "") {
243 22
            $msgHdr .= "Content-type: " . $mMime->scalarval() . "\n";
244 22
        }
245 22
        $msgHdr .= "X-Mailer: XML-RPC for PHP mailer 1.0";
246 22
247
        if ($err == "") {
248
            if (!mail("", $mSub->scalarval(), $mBody->scalarval(), $msgHdr)) {
249 22
                $err = "Error, could not send the mail.";
250
            }
251
        }
252 559
253 559
        if ($err) {
254
            return new Response(0, PhpXmlRpc\PhpXmlRpc::$xmlrpcerruser, $err);
255
        } else {
256 1
            return new Response(new Value(true, Value::$xmlrpcBoolean));
257 1
        }
258
    }
259
260
}
261 559
262 559
return array(
263 559
    "examples.getStateName" => array(
264
        "function" => array("exampleMethods", "findState"),
265 559
        "signature" => exampleMethods::$findstate_sig,
266
        "docstring" => exampleMethods::$findstate_doc,
267
    ),
268
    "examples.sortByAge" => array(
269
        "function" => array("exampleMethods", "ageSorter"),
270
        "signature" => exampleMethods::$agesorter_sig,
271
        "docstring" => exampleMethods::$agesorter_doc,
272
    ),
273
    "examples.addtwo" => array(
274
        "function" => array("exampleMethods", "addTwo"),
275
        "signature" => exampleMethods::$addtwo_sig,
276
        "docstring" => exampleMethods::$addtwo_doc,
277
    ),
278
    "examples.addtwodouble" => array(
279
        "function" => array("exampleMethods", "addTwoDouble"),
280
        "signature" => exampleMethods::$addtwodouble_sig,
281
        "docstring" => exampleMethods::$addtwodouble_doc,
282
    ),
283
    "examples.stringecho" => array(
284
        "function" => array("exampleMethods", "stringEcho"),
285
        "signature" => exampleMethods::$stringecho_sig,
286
        "docstring" => exampleMethods::$stringecho_doc,
287
    ),
288
    "examples.echo" => array(
289
        "function" => array("exampleMethods", "echoBack"),
290
        "signature" => exampleMethods::$echoback_sig,
291
        "docstring" => exampleMethods::$echoback_doc,
292
    ),
293
    "examples.decode64" => array(
294
        "function" => array("exampleMethods", "echoSixtyFour"),
295
        "signature" => exampleMethods::$echosixtyfour_sig,
296
        "docstring" => exampleMethods::$echosixtyfour_doc,
297
    ),
298
    "examples.invertBooleans" => array(
299
        "function" => array("exampleMethods", "bitFlipper"),
300
        "signature" => exampleMethods::$bitflipper_sig,
301
        "docstring" => exampleMethods::$bitflipper_doc,
302
    ),
303
304
    // left in as an example, but disabled by default, to avoid this being abused if left on an open server
305
    /*"mail.send" => array(
306
        "function" => array("exampleMethods", "mailSend"),
307
        "signature" => exampleMethods::$mailsend_sig,
308
        "docstring" => exampleMethods::$mailsend_doc,
309
    ),*/
310
);
311