/** * Make an XML_RPC request. * * @param $method * @return stdClass */ protected function xmlRpcRequest($method/** $args */) { $url = $this->fillPdfServiceEndpoint; $args = func_get_args(); // Fix up the array for Drupal 7 xmlrpc() function style $args = [$args[0] => array_slice($args, 1)]; $result = xmlrpc($url, $args); $ret = new \stdClass; if (isset($result['error'])) { drupal_set_message($result['error'], 'error'); $ret->error = TRUE; } elseif ($result == FALSE || xmlrpc_error()) { $error = xmlrpc_error(); $ret->error = TRUE; drupal_set_message(t('There was a problem contacting the FillPDF service. It may be down, or you may not have internet access. [ERROR @code: @message]', ['@code' => $error->code, '@message' => $error->message]), 'error'); } else { $ret->data = $result['data']; $ret->error = FALSE; } return $ret; }
function xmlrpc_exception(Exception $e) { if ($e instanceof XmlrpcServerException && get_class($e) == 'XmlrpcServerException') { $e->handle_exception(); return; } elseif ($e instanceof MaharaException && get_class($e) == 'MaharaException') { throw new XmlrpcServerException($e->getMessage(), $e->getCode()); return; } xmlrpc_error('An unexpected error has occurred: ' . $e->getMessage(), $e->getCode()); log_message($e->getMessage(), LOG_LEVEL_WARN, true, true, $e->getFile(), $e->getLine(), $e->getTrace()); }
function ewiki_pingback_rpc($source_url, $target_url) { global $ewiki_config; #-- does the target URL refer to a known WikiPage ? $id = ewiki_url2id($target_url); if (!$id) { xmlrpc_send_response(xmlrpc_error(0x21, "Could not determine PageName for the given target URL.")); } if (!($data = ewiki_db::GET($id))) { xmlrpc_send_response(xmlrpc_error(0x20, "The given target page does not exist.")); } #-- check if the caller really has a link as he claims ini_set("user_agent", $ewiki_config["ua"]); if (strpos($source_url, "http://") === 0 && ($test = ewiki_http_asis($source_url, 96256))) { $test = strtolower($test); $test_url = strtolower($target_url); if (!strpos($test, $test_url) and !strpos($test, htmlentities($test_url))) { return xmlrpc_error(0x11, "Sorry, but couldn't find a link to '{$target_url}' on your given '{$source_url}' page."); } } else { return xmlrpc_error(0x10, "Your given source URL does not exist, could not be retrieved."); } #-- reject other frivolous links if (preg_match('#^http://[^/]+/?$#', $source_url)) { return xmlrpc_error(0x11, "Rejected '{$source_url}' as frivolous."); } #-- check write permissions if (EWIKI_DB_F_TEXT != $data["flags"] & EWIKI_DB_F_TYPE or $data["flags"] & EWIKI_DB_F_READONLY) { return xmlrpc_error(0x31, "Sorry, but this page is write-protected or not a system page."); } #-- already on page if (strpos($data["content"], $source_url)) { return xmlrpc_error(0x30, "The given link does already exist on this page."); } #-- other go-away cases if (function_exists("ewiki_banned_url") && ewiki_banned_url($source_url) || function_exists("ewiki_blocked_url") && ewiki_blocked_url($source_url)) { return xmlrpc_error(0x100, "Your link is unwanted here (registered on BlockedLinks or BannedLinks)."); } #-- else update page $data["content"] = rtrim($data["content"]) . "\n* {$source_url} (PingBack)\n"; ewiki_db::UPDATE($data); $data["version"]++; $ok = ewiki_db::WRITE($data); #-- fin response if ($ok) { return "Link to '{$source_url}' was added to page '{$id}'."; } else { return xmlrpc_error(0x101, "Seems like a database/writing error occoured."); } }
public final function handle_exception() { if (!empty($this->log)) { log_message($this->getMessage(), LOG_LEVEL_WARN, true, true, $this->getFile(), $this->getLine(), $this->getTrace()); } if (defined('JSON')) { // behave differently @header('Content-type: text/plain'); @header('Pragma: no-cache'); echo json_encode(array('error' => true, 'message' => $this->render_exception())); exit; } if (defined('TESTSRUNNING')) { exit; // let it be caught by phpunit } if (defined('CRON') || defined('CLI')) { echo $this->render_exception(); exit; } if (defined('XMLRPC')) { // it's preferable to throw an XmlrpcServerException echo xmlrpc_error($this->render_exception(), $this->getCode()); exit; } if (headers_sent()) { echo '<span style="color: red;">ERROR - something bad happened after headers have been sent. Check the error log for more information.</span>'; die; } $outputtitle = $this->get_string('title'); $outputmessage = trim($this->render_exception()); if (function_exists('smarty') && !$this instanceof ConfigSanityException) { try { $smarty = smarty(array(), array(), array(), array('sidebars' => false)); $smarty->assign('title', $outputtitle); $smarty->assign('message', $outputmessage); $smarty->display('error.tpl'); die; } catch (Exception $e) { // If an exception is thrown in smarty(), ignore it // and print the message out the ugly way log_warn("Exception thrown by smarty call while handling exception"); } } $outputtitle = htmlspecialchars($outputtitle, ENT_COMPAT, 'UTF-8'); $outputmessage = nl2br(htmlspecialchars($outputmessage, ENT_COMPAT, 'UTF-8')); echo <<<EOF <html> <head> <title>{$outputtitle}</title> <style type="text/css"> html { margin: 0; padding: 0; font-family: Arial, sans-serif; } body { width: 600px; margin: 100px auto; font-size: 12px; } h1 { color: #547c22; font-size: 20px; font-weight: normal; margin: 0 0 5px 0; padding: 0; text-transform: capitalize; border-bottom: 1px solid #819f18; text-align: center; } #message { width: 90%; margin: 0 auto; text-align: justify; } #reason { margin: 0 3em; } </style> </head> <body> EOF; echo <<<EOF <h1>{$outputtitle}</h1> <div id="message">{$outputmessage}</div> </body> </html> EOF; // end of printing stuff to the screen... die; }
function xmlrpc_decode_value($value) { $val = NULL; foreach ($value as $i => $d) { #-- use single (text) content xml2array entry as actual $d var if (is_array($d) && isset($d[",0"])) { $d = $d[",0"]; } #-- convert into PHP var based on type $type = strtok($i, ","); switch ($type) { case "array": $val = array(); foreach ($d["data,0"] as $i => $value) { $val[] = xmlrpc_decode_value($value); } break; case "struct": $val = array(); foreach ($d as $uu => $d2) { if (($in = $d2["name,0"][",0"]) && ($pos2 = 1) || ($in = $d2["name,1"][",0"]) && ($pos2 = 0)) { $val[$in] = xmlrpc_decode_value($d2["value,{$pos2}"]); } } break; case "": # handles also '<value>s</value>' instead # handles also '<value>s</value>' instead case "0": # of '<value><string>s</string></value>' # of '<value><string>s</string></value>' case "string": $val = is_array($d) ? "" : (string) $d; break; case "base64": $val = XMLRPC_AUTO_TYPES >= 2 ? base64_decode($d) : (string) $d; if (XMLRPC_AUTO_UTF8 >= 2 && ($uu = utf8_decode($val))) { $val = $uu; } break; // case "real": case "float": // neither is allowed // case "real": case "float": // neither is allowed case "double": $val = (double) $d; break; case "i4": case "int": $val = (int) $d; break; case "boolean": $val = (bool) $d; break; case "dateTime.iso8601": $val = xmlrpc_strtotime($d); break; default: if (defined("XMLRPC_SERVER")) { xmlrpc_send_response(xmlrpc_error(-32600, "Unknown data type '{$type}'")); } else { echo $xmlrpc_error = "UNKNOWN XML-RPC DATA TYPE '{$type}'<br>\n"; $xmlrpc_errorcode = -32207; } # echo "<!-- UNKNOWN TYPE $type -->\n"; # xmlrpc_log("bad data type '$type' enountered"); } } return $val; }
/** * Returns the last XML-RPC client error message */ function xmlrpc_error_msg() { $error = xmlrpc_error(); return $error != NULL ? $error->message : NULL; }
function xmlrpc_custom_error($error_number, $error_string, $filename, $line, $vars) { if (error_reporting() & $error_number) { $error_string .= sprintf("\nFilename: %s\nLine: %s", $filename, $line); xmlrpc_error(1005, $error_string); } }
/** * For XML-RPC - we want to check for enc / sigs * * @return $xml */ protected function modify_payload() { global $HTTP_RAW_POST_DATA; $xml = null; // check for encryption and signatures if ($this->authmethod == WEBSERVICE_AUTHMETHOD_PERMANENT_TOKEN) { // we need the token so that we can find the key if (!($dbtoken = get_record('external_tokens', 'token', $this->token, 'tokentype', EXTERNAL_TOKEN_PERMANENT))) { // log failed login attempts throw new WebserviceAccessException(get_string('invalidtoken', 'auth.webservice')); } // is WS-Security active ? if ($dbtoken->wssigenc) { $this->publickey = $dbtoken->publickey; } } else { if ($this->authmethod == WEBSERVICE_AUTHMETHOD_USERNAME) { // get the user $user = get_record('usr', 'username', $this->username); if (empty($user)) { throw new WebserviceAccessException(get_string('wrongusernamepassword', 'auth.webservice')); } // get the institution from the external user $ext_user = get_record('external_services_users', 'userid', $user->id); if (empty($ext_user)) { throw new WebserviceAccessException(get_string('wrongusernamepassword', 'auth.webservice')); } // is WS-Security active ? if ($ext_user->wssigenc) { $this->publickey = $ext_user->publickey; } } } // only both if we can find a public key if (!empty($this->publickey)) { // A singleton provides our site's SSL info require_once get_config('docroot') . 'api/xmlrpc/lib.php'; $HTTP_RAW_POST_DATA = file_get_contents('php://input'); $openssl = OpenSslRepo::singleton(); $payload = $HTTP_RAW_POST_DATA; $this->payload_encrypted = false; $this->payload_signed = false; try { $xml = new SimpleXMLElement($payload); } catch (Exception $e) { throw new XmlrpcServerException('Payload is not a valid XML document', 6001); } // Cascading switch. Kinda. try { if ($xml->getName() == 'encryptedMessage') { $this->payload_encrypted = true; $payload = xmlenc_envelope_strip($xml); } if ($xml->getName() == 'signedMessage') { $this->payload_signed = true; $payload = xmldsig_envelope_strip($xml); } $xml = $payload; } catch (CryptException $e) { if ($e->getCode() == 7025) { // The key they used to contact us is old, respond with the new key correctly // This sucks. Error handling of our mnet code needs to improve ob_start(); xmlrpc_error($e->getMessage(), $e->getCode()); $response = ob_get_contents(); ob_end_clean(); // Sign and encrypt our response, even though we don't know if the // request was signed and encrypted $response = xmldsig_envelope($response); $response = xmlenc_envelope($response, $this->publickey); $xml = $response; } } } // if XML has been grabbed already then it must be turned into a request object if ($xml) { $request = new Zend_XmlRpc_Request(); $request->loadXML($xml); $xml = $request; } return $xml; }
if ($xml->getName() == 'encryptedMessage') { $payload_encrypted = true; $REMOTEWWWROOT = (string) $xml->wwwroot; $payload = xmlenc_envelope_strip($xml); } if ($xml->getName() == 'signedMessage') { $payload_signed = true; $REMOTEWWWROOT = (string) $xml->wwwroot; $payload = xmldsig_envelope_strip($xml); } } catch (CryptException $e) { if ($e->getCode() == 7025) { // The key they used to contact us is old, respond with the new key correctly // This sucks. Error handling of our mnet code needs to improve ob_start(); xmlrpc_error($e->getMessage(), $e->getCode()); $response = ob_get_contents(); ob_end_clean(); // Sign and encrypt our response, even though we don't know if the // request was signed and encrypted $response = xmldsig_envelope($response); $peer = get_peer($REMOTEWWWROOT); $response = xmlenc_envelope($response, $peer->certificate); echo $response; exit; } } if ($xml->getName() == 'methodCall') { // $payload ? if (empty($xml->methodName)) { throw new XmlrpcServerException('Payload is not an XML-RPC document', 6008);
/** * For SOAP - we want to inspect for auth headers * and do decrypt / sigs * * @return $xml */ protected function modify_payload() { $xml = null; // don't do any of this if we are in the WSDL phase if (param_boolean('wsdl', 0)) { return $xml; } // check for encryption and signatures if ($this->authmethod == WEBSERVICE_AUTHMETHOD_PERMANENT_TOKEN) { // we need the token so that we can find the key if (!($dbtoken = get_record('external_tokens', 'token', $this->token, 'tokentype', EXTERNAL_TOKEN_PERMANENT))) { // log failed login attempts throw new WebserviceAccessException(get_string('invalidtoken', 'auth.webservice')); } // is WS-Security active ? if ($dbtoken->wssigenc) { $this->publickey = $dbtoken->publickey; } } else { if ($this->authmethod == WEBSERVICE_AUTHMETHOD_USERNAME && !empty($this->username)) { // get the user $user = get_record('usr', 'username', $this->username); if (empty($user)) { throw new WebserviceAccessException(get_string('wrongusernamepassword', 'auth.webservice')); } // get the institution from the external user $ext_user = get_record('external_services_users', 'userid', $user->id); if (empty($ext_user)) { throw new WebserviceAccessException(get_string('wrongusernamepassword', 'auth.webservice')); } // is WS-Security active ? if ($ext_user->wssigenc) { $this->publickey = $ext_user->publickey; } } } // only both if we can find a public key if (!empty($this->publickey)) { // A singleton provides our site's SSL info require_once get_config('docroot') . 'api/xmlrpc/lib.php'; $HTTP_RAW_POST_DATA = file_get_contents('php://input'); $openssl = OpenSslRepo::singleton(); $payload = $HTTP_RAW_POST_DATA; $this->payload_encrypted = false; $this->payload_signed = false; try { $xml = new SimpleXMLElement($payload); } catch (Exception $e) { throw new XmlrpcServerException('Payload is not a valid XML document', 6001); } // Cascading switch. Kinda. try { if ($xml->getName() == 'encryptedMessage') { $this->payload_encrypted = true; $payload = xmlenc_envelope_strip($xml); } if ($xml->getName() == 'signedMessage') { $this->payload_signed = true; $signature = base64_decode($xml->Signature->SignatureValue); $payload = base64_decode($xml->object); $timestamp = $xml->timestamp; // Does the signature match the data and the public cert? $signature_verified = openssl_verify($payload, $signature, $this->publickey); if ($signature_verified == 1) { // Parse the XML try { $xml = new SimpleXMLElement($payload); } catch (Exception $e) { throw new MaharaException('Signed payload is not a valid XML document', 6007); } } else { throw new MaharaException('An error occurred while trying to verify your message signature', 6004); } } $xml = $payload; } catch (CryptException $e) { if ($e->getCode() == 7025) { // The key they used to contact us is old, respond with the new key correctly // This sucks. Error handling of our mnet code needs to improve ob_start(); xmlrpc_error($e->getMessage(), $e->getCode()); $response = ob_get_contents(); ob_end_clean(); // Sign and encrypt our response, even though we don't know if the // request was signed and encrypted $response = xmldsig_envelope($response); $response = xmlenc_envelope($response, $this->publickey); $xml = $response; } } } // standard auth if (!isset($_REQUEST['wsusername']) && $this->authmethod == WEBSERVICE_AUTHMETHOD_USERNAME || !empty($this->publickey)) { // wsse auth // we may already have the xml if sig/enc if (empty($xml)) { $xml = file_get_contents('php://input'); } $dom = new DOMDocument(); if (strlen($xml) == 0 || !$dom->loadXML($xml)) { require_once 'Zend/Soap/Server/Exception.php'; throw new Zend_Soap_Server_Exception('Invalid XML'); } else { // now hunt for the user and password from the headers $xpath = new DOMXpath($dom); $xpath->registerNamespace('wsse', 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd'); if ($q = $xpath->query("//wsse:Security/wsse:UsernameToken/wsse:Username/text()", $dom)) { if ($q->item(0)) { $this->username = (string) $q->item(0)->data; $this->password = (string) $xpath->query("//wsse:Security/wsse:UsernameToken/wsse:Password/text()", $dom)->item(0)->data; $this->authmethod = WEBSERVICE_AUTHMETHOD_USERNAME; } } } } return $xml; }
/** * XMLRPC login * * @param string $method_name * @param array $parameters */ function xmlrpc_login($method_name, $parameters) { $p = $parameters[0]; if (isset($p['domain']) && $p['domain']) { $username = $p['username'] . '@' . $p['domain']; } else { $username = $p['username']; } $sessionid = $GLOBALS['phpgw']->session->create($username, $p['password']); $kp3 = $GLOBALS['phpgw']->session->kp3; $domain = $GLOBALS['phpgw']->session->account_domain; if ($sessionid && $kp3) { return array('sessionid' => $sessionid, 'kp3' => $kp3, 'domain' => $domain); } else { xmlrpc_error(1001, 'Login failed'); } }
<?php require_once '/Users/anj/Sites/drupals/drupal-6/includes/xmlrpc.inc'; // Get anon session. system.connect is the only service that does // not require a sessionid even when you have 'Use Sess ID' checked. $xmlrpc_url = 'http://localhost.domd/~anj/drupals/drupal-6/services/xmlrpc'; $anon_session = xmlrpc($xmlrpc_url, 'system.connect'); // Use anon session id to login with authentication $user = '******'; $password = ''; $authenticated_session = xmlrpc($xmlrpc_url, 'user.login', $anon_session['sessid'], $user, $password); // Now we have an anuthenticated session, and when this ID is passed to services, it will run under that user's permissions $xmlrpc_result = xmlrpc($xmlrpc_url, 'user.get', $authenticated_session['sessid'], 0); if ($xmlrpc_result === FALSE) { print '<pre>' . print_r(xmlrpc_error(), TRUE) . '<pre>'; } else { print '<pre>' . print_r($xmlrpc_result, TRUE) . '<pre>'; }