I have the following code...
<?php
include("lib/xmlrpc.inc");
$email='whatever#hotmail.com';
$c=new xmlrpc_client("/register/index.php", "ws.myserver.com", 80);
$f=new xmlrpcmsg('existsEmail', array(new xmlrpcval($email, "base64")));
print "<pre>" . htmlentities($f->serialize( )) . "</pre>";
$r=$c->send($f);
$v=$r->value( );
if (!$r->faultCode( )) {
print "Email is". $email . " is " .
$v->scalarval( ) . "<br />";
print "<hr />I got this value back<br /><pre>" .
htmlentities($r->serialize( )). "</pre><hr />\n";
} else {
print "Fault: ";
print "Code: " . $r->faultCode( ) .
" Reason '" .$r->faultString( )."'<br />";
}
?>
I need to consume the WebService located at http://ws.myserver.com/register/index.php.
I pass the email as a parameter and then the XMLRPC.inc library will encode it using base64.
I've got a good XML request shown below:
<?xml version="1.0"?>
<methodCall>
<methodName>existsEmail</methodName>
<params>
<param>
<value><base64>dnJvZHJpZ3VlekBpY2NrLm5ldC5jbw==</base64></value>
</param>
</params>
</methodCall>
BUUUT, when I tried to get a response from the server I've to the following error
Fault: Code: -32601 Reason 'server error. requested method not found'
Any ideas? I'm getting crazy about how to call the existsEmail method from my PHP code...I'm sure it is there but I don't know if I'm missing something..
You are getting an error message (Specification for Fault Code Interoperability, version 20010516) from the XMLRPC endpoint you're communicating with.
It is a defined error code:
-32601 ---> server error. requested method not found
The RPC method you requested was not found by the server. Contact the support of the service you consume to get a list of all available methods. If that method should be available, contact the support and discuss the issue with them.
You asked in comment:
Is there any way [to] verify which methods are available?
That depends on the service. XMLRPC on sourceforge has a suggestion of defined methods you can call to list information about the functions available:
XML-RPC Introspection
system.listMethods
system.methodSignature
system.methodHelp
You can try if it works with your service, too. AFAIK those are common, I wrapped up a quick example, you find the full code below. See the output below the code as well.
$path = 'http://xmlrpc-c.sourceforge.net/api/sample.php';
printf("\n XMLRPC Service Discovery\n\n for: '%s'\n\n", $path);
$discovery = new Discovery($path);
$methods = $discovery->getMethods();
printf(" Method Summary:\n ===============\n", count($methods));
foreach ($methods as $i => $method)
{
printf(" %'.-2d %s\n", $i + 1, $method->getName());
}
printf("\n Method Details (%d):\n ===================\n", count($methods));
foreach ($methods as $i => $method)
{
printf(" %'.-2d %s\n", $i + 1, $method->getName());
printf("\n %s\n", $method);
printf("\n%s\n\n", preg_replace('/^/um', ' ', wordwrap($method->getHelp(), 46)));
}
Output:
XMLRPC Service Discovery
for: 'http://xmlrpc-c.sourceforge.net/api/sample.php'
Method Summary:
===============
1. debug.authInfo
2. sample.add
3. sample.sumAndDifference
4. system.listMethods
5. system.methodHelp
6. system.methodSignature
Method Details (6):
===================
1. debug.authInfo
<struct> debug.authInfo
Report any HTTP authentication in use
2. sample.add
<int> sample.add (<int>, <int>)
Add two numbers
3. sample.sumAndDifference
<struct> sample.sumAndDifference (<int>, <int>)
Add and subtract two numbers
4. system.listMethods
<array> system.listMethods (<string>)
This method lists all the methods that the
XML-RPC server knows how to dispatch
5. system.methodHelp
<string> system.methodHelp (<string>)
Returns help text if defined for the method
passed, otherwise returns an empty string
6. system.methodSignature
<array> system.methodSignature (<string>)
Returns an array of known signatures (an array
of arrays) for the method name passed. If no
signatures are known, returns a none-array
(test for type != array to detect missing
signature)
You can find the sourcecode here: XMLRPC Discovery Service
Related
I'm trying to do a RRSIG validation, I'm trying to use the openssl lib in PHP. But I'm having a problem to pass the public key to the openssl_verify function.
This is a base code,
using the Net/DNS2 library to do a DNS query with DNSSEC option.
and get the DNSKEY and RRSIG.
<?php
require_once 'Net/DNS2.php';
$r = new Net_DNS2_Resolver(array('nameservers' => array('127.0.0.1')));
$r->dnssec = true;
try {
$result = $r->query('ip4afrika.nl', 'DNSKEY');
} catch(Net_DNS2_Exception $e) {
echo "::query() failed: ", $e->getMessage(), "\n";
die(); //
}
// print_r($result->answer);
$public_key_bin = base64_decode( $result->answer[0]->key ) ;
$public_key_str = $result->answer[0]->key; //echo $public_key_str; die();
// $public_key_res = openssl_x509_parse($public_key_bin);
$public_key_res = openssl_x509_read($public_key_str);
// $public_key_res = openssl_pkey_get_public($public_key_str);
while ($msg = openssl_error_string()) echo $msg . PHP_EOL;
I get this error messages,
when using:
$public_key_res = openssl_x509_read($public_key_str);
PHP Warning: openssl_x509_read(): supplied parameter cannot be
coerced into an X509 certificate! in /src/Net_DNS2-1.4.3/i.php on line
34 PHP Stack trace: PHP 1. {main}() /src/Net_DNS2-1.4.3/i.php:0 PHP
2. openssl_x509_read() /src/Net_DNS2-1.4.3/i.php:34 error:0906D06C:PEM routines:PEM_read_bio:no start line
so i tried adding the BEGIN/END headers
$public_key_str = '-----BEGIN CERTIFICATE-----' . PHP_EOL . $result->answer[0]->key . PHP_EOL . '-----END CERTIFICATE-----' ;
And got this error messages,
error:0D0680A8:asn1 encoding routines:ASN1_CHECK_TLEN:wrong tag
error:0D07803A:asn1 encoding routines:ASN1_ITEM_EX_D2I:nested asn1 error
error:0906700D:PEM routines:PEM_ASN1_read_bio:ASN1 lib
So it seems I'm feeding the function the wrong format, I'm still googling but any help would be welcome.
Eventually I like to validate the signature with:
openssl_verify($data, $signature, $public_key_res, 'RSA-SHA256');
Short answer:
If you just need the capability in PHP, you can just use https://github.com/metaregistrar/php-dnssec-validator .
Long Answer:
The reason you can't load the KEY data is because it's in a slightly different format. According to rfc3110:
Field Size
----- ----
exponent length 1 or 3 octets (see text)
exponent as specified by length field
modulus remaining space
Whereas RSA public keys are a bit more complex -- aside from the exponent and modulus, you need to prefix it with the correct OID as such (2nd answer).
After that the process is a bit gnarly:
Get the RRSIG record to get the signature and key tag (to determine which key to use)
Use the public keys from the correct DNSKEY RR to verify the signature against.
There's also a process described here (in python)
PHP_EOL is platform specific, not sure what platform you're testing this code on but try replacing the constant with '\n' explicitly. See if that helps.
I am submitting a URL request to a RESTful webservice. When I submit a variable in the url e.g "NGF and trkA", I am able to retrieve an XML responses from the remote server. However, when I input "NGF/trkA", my request fails. I really do not understand why as I have used rawurlendcode(). See the code below:
<?php
/*After pdf parsing, the result is contained in $fullText.*/
$fullText="NGF/TrkA*";
/*Remove line breaks.*/
$fullText_clean = str_replace("\n", " ", $fullText);
/*Excise the first 2 sentences of $fullText_clean (or 100 characters).*/
$truncated = substr($fullText_clean,0);
// Properly encode $truncated.
$truncated_encode = rawurlencode($truncated);
// Plug this variable, $truncated_encode, into the search url.
$xml = 'http://www.ebi.ac.uk/europepmc/webservices/rest/search/query='.$truncated_encode.'&resulttype=core';
// Return SimpleXMLElement object
$xmlObject = simplexml_load_file($xml);
if($xmlObject){
//Return information within the desired tag(s).
$title = $xmlObject->resultList->result[0]->title;
echo $fullText."<br />".
$fullText_clean."<br />".
$truncated."<br />".
$truncated_encode."<br />".
$title;
/*echo $title."<br />".$truncated;*/
}else{
echo "Failed to retreive SimpleXMLElement object.";
}
?>
This is the error that I get when $fullText="NGF/trkA":
Warning: simplexml_load_file(): I/O warning : failed to load external entity "http://www.ebi.ac.uk/europepmc/webservices/rest/search/query=NGF%2FTrkA%2A&result type=core" in /Applications/XAMPP/xamppfiles/htdocs/Lifescieco_pdfUpload/puttingitTogether.php on line 21
Failed to retreive SimpleXMLElement object.
How can parse XML with this structure :
<sdk:sdk-repository xmlns:sdk="http://schemas.android.com/sdk/android/repository/7" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<!--
Generated on Thu Oct 22 10:16:34 PDT 2009 using eclair-sdk 17704: Platform. Addon. Tools. Doc.
-->
<sdk:platform>
<sdk:version>2.0</sdk:version>
<sdk:api-level>5</sdk:api-level>
<sdk:codename/>
<sdk:revision>01</sdk:revision>
<sdk:min-tools-rev>
<sdk:major>3</sdk:major>
</sdk:min-tools-rev>
<sdk:description>Android SDK Platform 2.0, revision 1</sdk:description>
<sdk:desc-url>http://developer.android.com/sdk/android-2.0.html</sdk:desc-url>
<sdk:obsolete/>
<sdk:archives>
<sdk:archive arch="any" os="linux">
<sdk:size>75095268</sdk:size>
<sdk:checksum type="sha1">be9be6a99ca32875c96ec7f91160ca9fce7e3c7d</sdk:checksum>
<sdk:url>android-2.0_r01-linux.zip</sdk:url>
</sdk:archive>
<sdk:archive arch="any" os="macosx">
<sdk:size>74956356</sdk:size>
<sdk:checksum type="sha1">2a866d0870dbba18e0503cd41e5fae988a21b314</sdk:checksum>
<sdk:url>android-2.0_r01-macosx.zip</sdk:url>
</sdk:archive>
<sdk:archive arch="any" os="windows">
<sdk:size>76288040</sdk:size>
<sdk:checksum type="sha1">aeb623217ff88b87216d6eb7dbc846ed53f68f57</sdk:checksum>
<sdk:url>android-2.0_r01-windows.zip</sdk:url>
</sdk:archive>
</sdk:archives>
<sdk:layoutlib>
<sdk:api>4</sdk:api>
</sdk:layoutlib>
<sdk:uses-license ref="android-sdk-license"/>
</sdk:platform>
...
how can get Version? and size?
and even get Generated date ?( on Thu Oct 22 10:16:34 PDT 2009 using eclair-sdk 17704: Platform. Addon. Tools. Doc. ) for each SDK Platform(sdk:platform)
very very TNX
Parsing the XML and parsing the comment in the file are two completely separate things.
Regarding the XML itself, you can use PHP's SimpleXml to parse it, but you'll have to remember to specify the namespace when accessing the children-elements.
We know we want namespaces, and we know which one we want, because each node that we're interested in is prefixed with something:. For example:
<sdk:version>2.0</sdk:version>
So, in this case, we are interested in the sdk namespace. You can find where the namespaces are defined in the top-most declaration node:
<sdk:sdk-repository xmlns:sdk="http://schemas.android.com/sdk/android/repository/7" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
This declares the sdk namespace to be http://schemas.android.com/sdk/android/repository/7. The 7 is a version number, so keep this in mind if you ever need to update to use different SDKs.
A small example of parsing the XML, using your sample XML, would be:
// load the file and create the XML element
$feed = file_get_contents("repository.xml");
$xml = new SimpleXmlElement($feed);
// define the namespace you need to use (we want xmlns:sdk)
$sdk = $xml->children("http://schemas.android.com/sdk/android/repository/7");
// get the "platform" root element and start using it's nodes
$platform = $sdk->platform;
echo 'Version: ' . $platform->version . "<br />";
echo 'Description: ' . $platform->description . "<br />";
foreach ($platform->archives->archive as $archive) {
echo 'Archive: ' . $archive->url . ", size: " . $archive->size . "<br />";
}
To match the Generated on ... line, you'll either need to use substring parsing or build a regex that can parse it. I'm opting for the latter option to save lines-of-code, but it's really up to you how you'd prefer to go about it.
If you wanted to use a regex, and this is very-specific to the output in your sample XML so you may need to adjust it to be more dynamic, you can use PHP's preg_match and a very verbose pattern:
$pattern = '/<!--[\r\n\s]*Generated on (.*) using eclair-sdk 17704: Platform\. Addon\. Tools\. Doc\.[\r\n\s]*-->/';
$comments = array();
preg_match($pattern, $feed, $comments);
echo $comments[1];
Output:
Thu Oct 22 10:16:34 PDT 2009
i am developing an app in php it pulls data from Reuters API i am trying to add the request parameters before making SOAP call , i have the xml which must be generated from my request it must look like this :
<HeadlineMLRequest>
<Filter>
<MetaDataConstraint class="companies" xmlns="http://schemas.reuters.com/ns/2006/04/14/rmds/webservices/news/filter">
<Value>MSFT.O</Value>
</MetaDataConstraint>
</Filter>
</HeadlineMLRequest>
when i build my request parameter object i tried this
protected function getRequest() {
$retval->HeadlineMLRequest->MaxCount = 10;
$retval->HeadlineMLRequest->Filter->MetaDataConstraint->class = "companies";
$retval->HeadlineMLRequest->Filter->MetaDataConstraint->Value = "MSFT.O";
return $retval;
}
but when i echo last xml request i find it like this
<ns1:headlinemlrequest>
<ns1:maxcount>
10
</ns1:maxcount>
<ns1:filter>
<ns2:metadataconstraint class="companies">
<ns2:value>
</ns2:value>
</ns2:metadataconstraint>
</ns1:filter>
if you notice Value is empty although i set it with "MSFT.O" , any help please?
Complex requests with php soap are not well documented and most examples show only basic techniques.
Try the following:
$metaData = '<MetaDataConstraint class="companies" xmlns="http://schemas.reuters.com/ns/2006/04/14/rmds/webservices/news/filter">
<Value>MSFT.O</Value>
</MetaDataConstraint>';
$xmlvar = new SoapVar($metaData, XSD_ANYXML);
$retval->HeadlineMLRequest->Filter->MetaDataConstraint = $xmlVar;
we want to create a PHP WSO2 Webservice Client which uses WS Security, but without signature nor encryption. Instead we want to use a simple Password. Problem is: we always get an certificate error (see below). Do we really have to install a certificate, and if so: where ? Java Keystore ?
Environment: PHP 5.3.10, WSO2 PHP 2.10, Apache 2.2.x
wfs_client_log:
[error] key_mgr.c(295) [rampart][rampart_signature] Public key certificate file is not specified.
[error] rampart_signature.c(856) [rampart][rampart_signature] Cannot get certificate
[error] rampart_sec_header_builder.c(131) [rampart][shb] Signing failed. ERROR
[error] rampart_sec_header_builder.c(601) [rampart][shb] Asymmetric Binding failed
[error] rampart_out_handler.c(130) [rampart]Security header building failed.
[error] phase.c(224) Handler RampartOutHandler invoke failed within phase Security
[error] engine.c(657) Invoking phase Security failed
PHP Code is:
<?php
// Endpoint WebService
$endPoint = 'http://xxx.xxxx.xxx:7000/orabpel/selfservice/passwortAendernMBE/1.0';
// Security-Payload
$user = 'mustermann123';
$passwortAlt = 'foo';
$passwortNeu = 'bar';
// create Security-Token
$secToken = new WSSecurityToken(array(
"user" => $user,
"password" => $passwortAlt,
"passwordType" => "PlainText"));
// create SecurityPolicy
$policy = new WSPolicy(array(
"security" => array(
"useUsernameToken" => TRUE)));
// create WS-Client
$client = new WSClient( array(
"to" => $endPoint,
"useSOAP" => "1.1",
"action" => "process",
"policy" => $policy,
"securityToken" => $secToken));
// create SOAP-Payload
$soapPayload = '
<ns1:passwortAendern_processElement xmlns:ns1="http://xxxx.xxxx.xxxxxe/Integration/prozesse/xxxxxxSchema"
xmlns:ns2="http://xxxx.xxxx.xxx/types/xx.xxx.xxxx.selfService.prozesse.xxx.xxxxMessage">
<ns1:passwortAendernMessage>
<ns2:benutzerkennung>' . $user . '</ns2:benutzerkennung>
<ns2:passwortAlt>' . $passwortAlt . '</ns2:passwortAlt>
<ns2:passwortNeu>' . $passwortNeu . '</ns2:passwortNeu>
</ns1:passwortAendernMessage>
</ns1:passwortAendern_processElement>';
// Request
$soapResponse = null;
try {
// soap Request
$soapResponse = $client->request( $soapPayload );
// print out Response
echo '<pre>';
print_r(htmlspecialchars( str_replace('>','>'.PHP_EOL,$soapResponse->str ) ));
echo '</pre>';
} catch(Exception $e) {
echo '<h1>Error:</h1>' . PHP_EOL;
var_dump($e);
}
// dump Soap-Parameters
echo '<h1>Soap-Parameter</h1>' . PHP_EOL;
var_dump($soapPayload);
// dump Soap-Response
echo '<h1>Soap-Response</h1>' . PHP_EOL;
var_dump($soapResponse);
Finally successful! Calling the Webservice (with above mentioned vector/intent) now works.
Many attempts and another example by Nandika later we've found out that for us (Matthias and I) changing the creation of the WS-SecurityPolicy -object did the trick.
Instead of using above array as initialisation-parameter:
// create SecurityPolicy
$policy = new WSPolicy(array(
"security" => array(
"useUsernameToken" => TRUE)));
...we now use a xml-policy-file like so:
// load Policy (xml) file...
$policy_file = file_get_contents("policy.xml");
// ...and create SecurityPolicy
$policy = new WSPolicy($policy_file);
Content of "policy.xml":
<wsp:Policy xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy"
xmlns:sp="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702">
<wsp:ExactlyOne>
<wsp:All>
<sp:TransportBinding>
<wsp:Policy>
</wsp:Policy>
</sp:TransportBinding>
<sp:SignedSupportingTokens>
<wsp:Policy>
<sp:UsernameToken
sp:IncludeToken="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702/IncludeToken/AlwaysToRecipient">
<wsp:Policy>
<sp:WssUsernameToken10 />
</wsp:Policy>
</sp:UsernameToken>
</wsp:Policy>
</sp:SignedSupportingTokens>
</wsp:All>
</wsp:ExactlyOne>
</wsp:Policy>
Beginning to use WSO2 with WS-Security WSF/PHP 2.1 feels rather touchy. Therefore I'll try to list some thoughts that knowing (would have) helped me save time:
most common error reflected to me by wsf/php is (an exception-object with the message): "Error , NO Response Received". This now happens almost whenever anything goes wrong, for example:
my request-xml (-structure) is not valid
a parameter has an incorrect type
the webservice throws an Exception (any exception really: be it because of a wrong WS-Security user/password, missing/unknown namespace, even some exceptions of type 'WS-Fault')
anything going wrong on the service-side really
a misconfiguration / configuration-change on php/wsf -side that disallowes anything relevant
network problems? (...not confirmed)
no request is sent by wso2 (for example when having trouble with TransportBinding -confinguration)
sometimes I do get a WS-Fault -ojbect (in a resopnse envelope) which I can check for my client-code [$e typeof WSFault]
always have a tool with proxy-capabilities nearby to route through + inspect your request and response. At the moment I use Oracles JDeveloper 10 and 11 which both have a neat little "HTTP Analyzer" inside (but there sure are smaller and/or better tools out there for this purpose).
Playing around with the settings in policy.xml a comrad and I found out that:
having a instead of the needed node (in your security_policy.xml) you'll get a WS-Fault: "policy requires authentication token"
having an empty node results in connection terminated in browser and wsf/php crashing (without signifficant error message - as far as i can see).
Thanks everyone (especially Nandika) for your help!
I've encountered the same issue once, but it was concerning WSServer, not WSClient. Since version 2.1 (or even earlier) WSF consideres WS-Policy signed by default, you need a WSPolicy file which declared signatureless behaviour. I've posted an article on this topic, but it's in Russian. Use Google Translate.
http://habrahabr.ru/post/132353/
The default generated policy is failing because, wsf/php 2.1.0 version is expecting signed messages for default generated policy for
$policy = new WSPolicy(array( "security" => array("useUsernameToken" => TRUE)));
Try with the following policy file.
https://svn.wso2.org/repos/wso2/trunk/wsf/php/samples/security/username_token/call_back/policy.xml
You can load the policy as
$policy_file = file_get_contents("policy.xml");
$policy = new WSPolicy($policy_file);