├── .gitmodules ├── README.md └── php-client ├── .gitignore ├── api-config.dist.php ├── class.phpipam-api.php └── example.php /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "powershell-client"] 2 | path = powershell-client 3 | url = https://github.com/yoke88/PSPHPIPAM.git 4 | [submodule "phpipam-pyclient"] 5 | path = phpipam-pyclient 6 | url = https://github.com/viniarck/phpipam-pyclient.git 7 | [submodule "phpipamsdk"] 8 | path = phpipamsdk 9 | url = https://github.com/efenian/phpipamsdk.git 10 | [submodule "python-phpipam"] 11 | path = python-phpipam 12 | url = https://github.com/kompetenzbolzen/python-phpipam 13 | [submodule "phpypam"] 14 | path = phpypam 15 | url = https://github.com/codeaffen/phpypam.git 16 | [submodule "phpipam-ansible-modules"] 17 | path = phpipam-ansible-modules 18 | url = https://github.com/codeaffen/phpipam-ansible-modules.git -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## phpipam-api-clients 2 | 3 | Collection of phpipam API clients in various languages to use with phpIPAM API server. 4 | -------------------------------------------------------------------------------- /php-client/.gitignore: -------------------------------------------------------------------------------- 1 | api-config.php 2 | token.txt 3 | -------------------------------------------------------------------------------- /php-client/api-config.dist.php: -------------------------------------------------------------------------------- 1 | dont save, check each time 17 | # filename => will save token to filename provided 18 | $token_file = "token.txt"; 19 | 20 | # set result format json/object/array/xml 21 | $result_format = "json"; 22 | 23 | ?> -------------------------------------------------------------------------------- /php-client/class.phpipam-api.php: -------------------------------------------------------------------------------- 1 | "OK", 151 | 201 => "Created", 152 | 202 => "Accepted", 153 | 204 => "No Content", 154 | // Client errors 155 | 400 => "Bad Request", 156 | 401 => "Unauthorized", 157 | 403 => "Forbidden", 158 | 404 => "Not Found", 159 | 405 => "Method Not Allowed", 160 | 415 => "Unsupported Media Type", 161 | // Server errors 162 | 500 => "Internal Server Error", 163 | 501 => "Not Implemented", 164 | 503 => "Service Unavailable", 165 | 505 => "HTTP Version Not Supported", 166 | 511 => "Network Authentication Required" 167 | ); 168 | 169 | /** 170 | * Set result format 171 | * 172 | * (default value: array("json", "array", "object", "xml")) 173 | * 174 | * @var string 175 | * @access private 176 | */ 177 | private $result_format_available = array("json", "array", "object", "xml"); 178 | 179 | /** 180 | * Result format 181 | * 182 | * json/array/object/xml 183 | * 184 | * (default value: "json") 185 | * 186 | * @var string 187 | * @access private 188 | */ 189 | private $result_format = "json"; 190 | 191 | /** 192 | * To store result 193 | * 194 | * @var mixed 195 | * @access private 196 | */ 197 | public $result = array( 198 | "success" => true, 199 | "code" => 204, 200 | "message" => "" 201 | ); 202 | 203 | /** 204 | * Reponse headers 205 | * 206 | * @var array 207 | */ 208 | public $response_headers = array (); 209 | 210 | 211 | 212 | 213 | /** 214 | * __construct function. 215 | * 216 | * @access public 217 | * @param bool|mixed $api_url (default: false) 218 | * @param bool|mixed $app_id (default: false) 219 | * @param bool|mixed $api_key (default: false) 220 | * @param bool|mixed $username (default: false) 221 | * @param bool|mixed $password (default: false) 222 | * @param mixed $result_format (default: "json") 223 | */ 224 | public function __construct($api_url = false, $app_id = false, $api_key = false, $username = false, $password = false, $result_format = "json") { 225 | // set app server URL if provided 226 | if ($api_url!==false) { 227 | $this->set_api_url ($api_url); 228 | } 229 | // set app_id if provided 230 | if ($app_id!==false) { 231 | $this->set_api_app_id ($app_id); 232 | } 233 | // set api key if provided 234 | if ($api_key!==false) { 235 | $this->set_api_key ($api_key); 236 | } 237 | // set user/pass if provided 238 | if ($username!==false && $password!==false) { 239 | $this->set_api_authparams ($username, $password); 240 | } 241 | // set result format if provided 242 | if (strlen($result_format)>0) { 243 | $this->set_result_format ($result_format); 244 | } 245 | // check for required php extensions 246 | $this->validate_php_extensions (); 247 | } 248 | 249 | /** 250 | * Saves error and exits script 251 | * 252 | * @access public 253 | * @param mixed $content 254 | * @return void 255 | */ 256 | public function exception ($content) { 257 | //set result parameters 258 | $this->result = array( 259 | 'code' => 400, 260 | 'success' => false, 261 | 'message' => $content 262 | ); 263 | // print result 264 | $this->print_result (); 265 | // die 266 | die(); 267 | } 268 | 269 | /** 270 | * Returns last result 271 | * 272 | * @access public 273 | * @return void 274 | */ 275 | public function get_result () { 276 | # output result 277 | if ($this->result_format=="json") { 278 | return json_encode($this->result); 279 | } 280 | elseif ($this->result_format=="array") { 281 | return $this->result; 282 | } 283 | elseif ($this->result_format=="object") { 284 | return (object) $this->result; 285 | } 286 | elseif ($this->result_format=="xml") { 287 | // new SimpleXMLElement object 288 | $xml = new SimpleXMLElement('<'.$_GET['controller'].'/>'); 289 | // generate xml from result 290 | $this->array_to_xml($xml, $this->result); 291 | // return XML result 292 | return $xml->asXML(); 293 | } 294 | } 295 | 296 | /** 297 | * Prints last result 298 | * 299 | * @access public 300 | * @return void 301 | */ 302 | public function print_result () { 303 | # output result 304 | if ($this->result_format=="json") { 305 | print json_encode($this->result); 306 | } 307 | elseif ($this->result_format=="array") { 308 | var_dump($this->result); 309 | } 310 | elseif ($this->result_format=="object") { 311 | var_dump( (object) $this->result); 312 | } 313 | elseif ($this->result_format=="xml") { 314 | // new SimpleXMLElement object 315 | $xml = new SimpleXMLElement(''); 316 | // generate xml from result 317 | $this->array_to_xml($xml, $this->result); 318 | // return XML result 319 | print $xml->asXML(); 320 | } 321 | } 322 | 323 | /** 324 | * Transforms array to XML 325 | * 326 | * @access private 327 | * @param SimpleXMLElement $object 328 | * @param array $data 329 | * @return void 330 | */ 331 | private function array_to_xml(SimpleXMLElement $object, array $data) { 332 | // loop through values 333 | foreach ($data as $key => $value) { 334 | // if spaces exist in key replace them with underscores 335 | if(strpos($key, " ")>0) { $key = str_replace(" ", "_", $key); } 336 | 337 | // if key is numeric append item 338 | if(is_numeric($key)) $key = "item".$key; 339 | 340 | // if array add child 341 | if (is_array($value)) { 342 | $new_object = $object->addChild($key); 343 | $this->array_to_xml($new_object, $value); 344 | } 345 | // else write value 346 | else { 347 | $object->addChild($key, $value); 348 | } 349 | } 350 | } 351 | 352 | /** 353 | * Check if all extensions are present 354 | * 355 | * @access private 356 | * @return void 357 | */ 358 | private function validate_php_extensions () { 359 | // Required extensions 360 | $required_ext = array("openssl", "curl"); 361 | // mcrypt for crypted extensions 362 | if($this->api_key !== false) 363 | $required_ext[] = "mcrypt"; 364 | // json 365 | if($this->result_format == "json") 366 | $required_ext[] = "json"; 367 | // xml 368 | if($this->result_format == "xml") 369 | $required_ext[] = "xmlreader"; 370 | 371 | // Available extensions 372 | $available_ext = get_loaded_extensions(); 373 | 374 | // check 375 | foreach ($required_ext as $e) { 376 | if(!in_array($e, $available_ext)) { 377 | $this->exception("Missing php extension ($e)"); 378 | } 379 | } 380 | } 381 | 382 | /** 383 | * Debugging flag 384 | * 385 | * @access public 386 | * @param bool $debug (default: false) 387 | * @return void 388 | */ 389 | public function set_debug ($debug = false) { 390 | if(is_bool($debug)) { 391 | $this->debug = $debug; 392 | } 393 | } 394 | 395 | /** 396 | * Checks requested result format and saves it 397 | * 398 | * @access public 399 | * @param string $result_format (default: "json") 400 | * @return void 401 | */ 402 | public function set_result_format ($result_format = "json") { 403 | if (strlen($result_format)>0) { 404 | if (!in_array($result_format, $this->result_format_available)) { 405 | $this->exception ("Invalid result format"); 406 | } 407 | else { 408 | // recheck extensions 409 | $this->validate_php_extensions (); 410 | // set 411 | $this->result_format = $result_format; 412 | } 413 | } 414 | } 415 | 416 | /** 417 | * Set API url parameter 418 | * 419 | * @access public 420 | * @param mixed $api_url 421 | * @return void 422 | */ 423 | public function set_api_url ($api_url) { 424 | // we need http/https 425 | if(strpos($api_url, "http://")!==false || strpos($api_url, "https://")!==false) { 426 | // trim 427 | $api_url = trim($api_url); 428 | // add last / if missing 429 | if (substr($api_url, -1)!=="/") { $api_url .= "/"; } 430 | // save 431 | $this->api_url = $api_url; 432 | } 433 | else { 434 | $this->exception("Invalid APP id"); 435 | } 436 | } 437 | 438 | /** 439 | * Sets api app_id variable 440 | * 441 | * @access public 442 | * @param bool $id (default: false) 443 | * @return void 444 | */ 445 | public function set_api_app_id ($app_id = false) { 446 | if ($app_id!==false) { 447 | // name must be more than 2 and alphanumberic 448 | if(strlen($app_id)<3 || strlen($app_id)>12 || !ctype_alnum($app_id)) { 449 | $this->exception("Invalid APP id"); 450 | } 451 | else { 452 | $this->api_app_id = $app_id; 453 | } 454 | } 455 | else { 456 | $this->exception("Invalid APP id"); 457 | } 458 | } 459 | 460 | /** 461 | * Set api key 462 | * 463 | * @access public 464 | * @param bool $api_key (default: false) 465 | * @return void 466 | */ 467 | public function set_api_key ($api_key = false) { 468 | if ($api_key!==false) { 469 | $this->api_key = $api_key; 470 | 471 | // set encrypt flag 472 | $this->api_encrypt = true; 473 | } 474 | else { 475 | $this->exception("Invalid APP id"); 476 | } 477 | } 478 | 479 | /** 480 | * Sets username/password for URL auth 481 | * 482 | * @access public 483 | * @param bool $username (default: false) 484 | * @param bool $password (default: false) 485 | * @return void 486 | */ 487 | public function set_api_authparams ($username = false, $password = false) { 488 | if($username===false || $password===false) { 489 | $this->exception("Invalid username or password"); 490 | } 491 | else { 492 | $this->api_username = $username; 493 | $this->api_password = $password; 494 | } 495 | } 496 | 497 | /** 498 | * Sreets api method. 499 | * 500 | * @access public 501 | * @param string $method (default: "GET") 502 | * @return void 503 | */ 504 | public function set_api_method ($method = "GET") { 505 | // validate 506 | $this->set_api_method_validate ($method); 507 | // set 508 | $this->api_server_method = strtoupper($method); 509 | } 510 | 511 | /** 512 | * Validates API method against available 513 | * 514 | * @access private 515 | * @param mixed $method 516 | * @return void 517 | */ 518 | private function set_api_method_validate ($method) { 519 | if(!in_array(strtoupper($method), $this->api_server_valid_methods)) { 520 | $this->exception("Invalid method $method"); 521 | } 522 | } 523 | 524 | /** 525 | * Sets API controller - required 526 | * 527 | * @access public 528 | * @param bool $controller (default: false) 529 | * @return void 530 | */ 531 | public function set_api_controller ($controller = false) { 532 | if($controller!==false) { 533 | $this->api_server_controller = strtolower($controller); 534 | } 535 | } 536 | 537 | /** 538 | * Sets additional identifiers to be passed to URL directly 539 | * 540 | * e.g.: /api/appid/controller/// 541 | * 542 | * @access public 543 | * @param mixed $identifiers 544 | * @return void 545 | */ 546 | public function set_api_identifiers ($identifiers) { 547 | $this->api_server_identifiers = false; // clear this to forget any previous settings 548 | if(is_array($identifiers)) { 549 | if(sizeof($identifiers)>0 && !$this->api_encrypt) { 550 | // reset 551 | $this->api_server_identifiers = implode("/", $identifiers); 552 | } 553 | elseif (sizeof($identifiers)>0 && $this->api_encrypt) { 554 | $this->api_server_identifiers = array(); 555 | foreach ($identifiers as $cnt=>$i) { 556 | if($cnt==0) { $this->api_server_identifiers['id'] = $i; } 557 | else { $this->api_server_identifiers['id'.($cnt+1)] = $i; } 558 | } 559 | 560 | } 561 | } 562 | } 563 | 564 | 565 | 566 | 567 | 568 | 569 | 570 | 571 | 572 | 573 | 574 | /* @api-server communication --------------- */ 575 | 576 | /** 577 | * Executes request to API server 578 | * 579 | * @access public 580 | * @param bool $method (default: false) 581 | * @param bool $controller (default: false) 582 | * @param array $identifiers (default: array()) 583 | * @param array $params (default: array()) 584 | * @param bool $token_file (default: false) 585 | * @return void 586 | */ 587 | public function execute ($method = false, $controller = false, $identifiers = array(), $params = array(), $token_file = false) { 588 | // check and set method 589 | $this->set_api_method ($method); 590 | // set api controller 591 | $this->set_api_controller ($controller); 592 | // set api identifiers 593 | $this->set_api_identifiers ($identifiers); 594 | 595 | // set connection 596 | $this->curl_set_connection ($token_file); 597 | // save params 598 | $this->curl_set_params ($params); 599 | // set HTTP method 600 | $this->curl_set_http_method (); 601 | 602 | // if not encrypted set params 603 | if(!$this->api_encrypt) { 604 | // add token to header, authenticate if it fails 605 | $this->curl_add_token_header ($token_file); 606 | } 607 | // if token is set execute 608 | if ($this->token !== false) { 609 | // execute 610 | $res = $this->curl_execute (); 611 | // save result 612 | $this->result = (array) $res; 613 | 614 | // check for invalid token and retry 615 | if ($this->result['code']=="401" && $token_file!==false) { 616 | // remove old token 617 | $this->delete_token_file ($token_file); 618 | // auth again 619 | $this->curl_add_token_header ($token_file); 620 | // execute 621 | $res = $this->curl_execute (); 622 | // save result 623 | $this->result = (array) $res; 624 | } 625 | } 626 | // exncrypted request 627 | elseif ($this->api_encrypt) { 628 | // execute 629 | $res = $this->curl_execute (); 630 | // save result 631 | $this->result = (array) $res; 632 | } 633 | // save reult 634 | $this->curl_save_headers (); 635 | } 636 | 637 | /** 638 | * Opens cURL resource and sets initial parameters 639 | * 640 | * @access private 641 | * @param mixed $token_file 642 | * @return void 643 | */ 644 | private function curl_set_connection ($token_file) { 645 | // check if it exists 646 | if ($this->Connection===false) { 647 | // Get cURL resource 648 | $this->Connection = curl_init(); 649 | 650 | // set URL 651 | if($this->api_server_controller===false) { $url = $this->api_url.$this->api_app_id."/"; } 652 | else { $url = $this->api_url.$this->api_app_id.str_replace("//", "/", "/".$this->api_server_controller."/".$this->api_server_identifiers."/"); } 653 | 654 | // set default curl options and params 655 | curl_setopt_array($this->Connection, array( 656 | CURLOPT_RETURNTRANSFER => 1, 657 | CURLOPT_URL => $url, 658 | CURLOPT_HEADER => 0, 659 | CURLOPT_VERBOSE => $this->debug, 660 | CURLOPT_TIMEOUT => 30, 661 | CURLOPT_HTTPHEADER => array("Content-Type: application/json"), 662 | CURLOPT_USERAGENT => 'phpipam-api php class', 663 | // ssl 664 | CURLOPT_SSL_VERIFYHOST => false, 665 | CURLOPT_SSL_VERIFYPEER => false, 666 | // save headers 667 | CURLINFO_HEADER_OUT => true 668 | ) 669 | ); 670 | } 671 | } 672 | 673 | /** 674 | * Adds params to request if required 675 | * 676 | * @access private 677 | * @param mixed $params 678 | * @return void 679 | */ 680 | private function curl_set_params ($params) { 681 | // params set ? 682 | if (is_array($params) && !$this->api_encrypt ) { 683 | if (sizeof($params)>0) { 684 | if ($this->api_server_method === 'GET') 685 | curl_setopt($this->Connection, CURLOPT_URL, $this->api_url.$this->api_app_id.str_replace("//", "/", "/".$this->api_server_controller."/".$this->api_server_identifiers."/?".http_build_query($params))); 686 | else 687 | curl_setopt($this->Connection, CURLOPT_POSTFIELDS, json_encode($params)); 688 | } 689 | } 690 | // encrypt 691 | elseif ($this->api_encrypt) { 692 | // empty 693 | if(!is_array($params)) $params = array(); 694 | if(!is_array($this->api_server_identifiers)) $this->api_server_identifiers = array(); 695 | 696 | // join identifiers and parameters 697 | $params = array_merge($this->api_server_identifiers, $params); 698 | $params['controller'] = $this->api_server_controller; 699 | 700 | // create encrypted request 701 | $ivlen = openssl_cipher_iv_length($cipher="AES-128-CBC"); 702 | $iv = openssl_random_pseudo_bytes($ivlen); 703 | $encrypted_request = base64_encode(openssl_encrypt(json_encode($params),$cipher,$this->api_key,$options=OPENSSL_RAW_DATA, $iv)); 704 | 705 | // escape + 706 | $encrypted_request = urlencode($encrypted_request); 707 | 708 | // reset url 709 | curl_setopt($this->Connection, CURLOPT_URL, $this->api_url."?app_id=".$this->api_app_id."&enc_request=".$encrypted_request); 710 | } 711 | } 712 | 713 | /** 714 | * Sets HTTP method to use for queries 715 | * 716 | * @access private 717 | * @return void 718 | */ 719 | private function curl_set_http_method () { 720 | curl_setopt($this->Connection, CURLOPT_CUSTOMREQUEST, $this->api_server_method); 721 | } 722 | 723 | /** 724 | * Adds token to http header 725 | * 726 | * @access private 727 | * @param mixed $token_file 728 | * @return void 729 | */ 730 | private function curl_add_token_header ($token_file) { 731 | if($token_file!==false) { 732 | // open file and save token 733 | $token = @file($token_file); 734 | // save token 735 | if(isset($token[0])) { 736 | $this->token = trim($token[0]); 737 | $this->token_expires = trim($token[1]); 738 | 739 | // is token still valid ? 740 | if (strlen($this->token)<2 && $this->token_expires < time()) { 741 | // initiate authentication 742 | $this->curl_authenticate (); 743 | //save token to file 744 | $this->write_token_file ($token_file); 745 | } 746 | } 747 | else { 748 | $this->curl_authenticate (); 749 | //save token to file 750 | $this->write_token_file ($token_file); 751 | 752 | } 753 | } 754 | // token not saved, try to retrieve it 755 | else { 756 | $this->curl_authenticate (); 757 | } 758 | 759 | // add token to headers 760 | $this->curl_add_http_header ("token", $this->token); 761 | } 762 | 763 | /** 764 | * Adds http headers 765 | * 766 | * @access private 767 | * @param mixed $name 768 | * @param mixed $value 769 | * @return void 770 | */ 771 | private function curl_add_http_header ($name, $value) { 772 | $headers = array( 773 | "Content-Type: application/json", 774 | "$name: $value" 775 | ); 776 | // save 777 | curl_setopt($this->Connection, CURLOPT_HTTPHEADER, $headers); 778 | } 779 | 780 | /** 781 | * Writes token to token file 782 | * 783 | * @access private 784 | * @param mixed $filename 785 | * @return void 786 | */ 787 | private function write_token_file ($filename) { 788 | //save token 789 | try { 790 | $myfile = fopen($filename, "w"); 791 | fwrite($myfile, $this->token); 792 | fwrite($myfile, "\n"); 793 | fwrite($myfile, $this->token_expires); 794 | // close file 795 | fclose($myfile); 796 | } 797 | catch ( Exception $e ) { 798 | $this->exception("Cannot write file $filename"); 799 | } 800 | } 801 | 802 | /** 803 | * Removes token file if expired / invalid 804 | * 805 | * @access private 806 | * @param mixed $token_file 807 | * @return void 808 | */ 809 | private function delete_token_file ($token_file) { 810 | //save token 811 | try { 812 | $myfile = fopen($token_file, "w"); 813 | fwrite($myfile, ""); 814 | // close file 815 | fclose($myfile); 816 | } 817 | catch ( Exception $e ) { 818 | $this->exception("Cannot write file $token_file"); 819 | } 820 | } 821 | 822 | /** 823 | * Executes request. 824 | * 825 | * @access private 826 | * @return void 827 | */ 828 | private function curl_execute () { 829 | // send request and save response 830 | $resp = curl_exec($this->Connection); 831 | 832 | // curl error check 833 | if (curl_errno($this->Connection)) { 834 | $this->exception("Curl error: ".curl_error($this->Connection)); 835 | } 836 | else { 837 | // return result object 838 | return json_decode($resp); 839 | } 840 | } 841 | 842 | /** 843 | * Store result code 844 | * 845 | * @method curl_save_result_code 846 | * @return void 847 | */ 848 | private function curl_save_headers () { 849 | // save result and result code 850 | $this->response_headers = curl_getinfo($this->Connection); 851 | } 852 | 853 | /** 854 | * send authenticate request and save token if provided, otherwise throw error. 855 | * 856 | * @access private 857 | * @return void 858 | */ 859 | private function curl_authenticate () { 860 | // Get cURL resource 861 | $c_auth = curl_init(); 862 | 863 | // set default curl options and params 864 | curl_setopt_array($c_auth, array( 865 | CURLOPT_RETURNTRANSFER => 1, 866 | CURLOPT_URL => $this->api_url.$this->api_app_id."/user/", 867 | CURLOPT_HEADER => 0, 868 | CURLOPT_VERBOSE => $this->debug, 869 | CURLOPT_TIMEOUT => 30, 870 | CURLOPT_USERAGENT => 'phpipam-api php class', 871 | // ssl 872 | CURLOPT_SSL_VERIFYHOST => 0, 873 | CURLOPT_SSL_VERIFYPEER => 0, 874 | CURLOPT_POST => true, 875 | CURLOPT_HTTPHEADER => array( 876 | 'Content-Length: 0', 877 | 'Authorization: Basic '. base64_encode($this->api_username.":".$this->api_password) 878 | ) 879 | ) 880 | ); 881 | // send request and save response 882 | $resp = curl_exec($c_auth); 883 | 884 | // curl error check 885 | if (curl_errno($c_auth)) { 886 | $this->exception("Curl error: ".curl_error($c_auth)); 887 | } 888 | else { 889 | // return result object 890 | $auth_resp = json_decode($resp); 891 | // ok ? 892 | if ($auth_resp->code == 200) { 893 | if (isset($auth_resp->data->token)) { 894 | // save token 895 | $this->token = $auth_resp->data->token; 896 | $this->token_expires = strtotime($auth_resp->data->expires); 897 | } 898 | else { 899 | $this->exception("Cannot obtain access token"); 900 | } 901 | } 902 | // error 903 | else { 904 | // save response 905 | $this->result = $auth_resp; 906 | } 907 | } 908 | } 909 | 910 | } 911 | 912 | 913 | ?> 914 | -------------------------------------------------------------------------------- /php-client/example.php: -------------------------------------------------------------------------------- 1 | set_debug (true); 18 | # execute - result is stored to $API->result, save it to own array if multiple calls needed after execute 19 | $API->execute ("GET", "addresses", array("first_free", "7"), array(), $token_file); 20 | # get result 21 | $result = $API->get_result(); 22 | 23 | /** 24 | * Some examples 25 | * 26 | * Delete, POST examples 27 | * $API->execute ("DELETE", "subnets", array(7, "permissions"), array(), $token_file); 28 | * $API->execute ("POST", "vrf", array(), array("number"=>"114","name"=>"API"), $token_file); 29 | * 30 | * Get headers in array 31 | * $response_headers = $API->response_headers (); 32 | */ 33 | 34 | # print result 35 | print_r($response_headers); 36 | print_r(json_decode($result, true)); 37 | ?> 38 | --------------------------------------------------------------------------------