robrichards / wse-php Goto Github PK
View Code? Open in Web Editor NEWLibraries for adding WS-* support to ext/soap in PHP
Libraries for adding WS-* support to ext/soap in PHP
Hello
Would you please do a new release (2.0.1) for the commit d18b46a that includes the fix for the depreciated/removed split() function?
Thanks in advance
Hello,
in file src/WSSESoap.php on line 255 we have following code:
$sigNode = $this->secNode->firstChild->nextSibling;
I think that it works fine if node with signature is not only child node of wsse::Security (in this case firstChild is of type DOMNode). But if we have wsse:Security structure like this:
<wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
<ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:SignedInfo>
<ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
<ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
<ds:Reference URI="#pfx860017e8-f940-8539-ff1c-6cf9ab4114a2">
<ds:Transforms>
<ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
</ds:Transforms>
<ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
<ds:DigestValue>6T2....=</ds:DigestValue>
</ds:Reference>
</ds:SignedInfo>
<ds:SignatureValue>fEq7klMc....==</ds:SignatureValue>
</ds:Signature>
</wsse:Security>
there is no nextSibling, so after execution of above code we have $sigNode = null and next line in code generate error (we cannot do $sigNode->ownerDocument on null); To fix it you must change line:
$sigNode = $this->secNode->firstChild->nextSibling;
to
$sigNode = $this->secNode->firstChild;
In this case secNode is of type DomElement and it's firstChild is node (DOMElement) with signature.
Probably using of nextSibling should depends on type of firstChild (also some error could be issued when $sigNode is null)
Thank you!
What steps will reproduce the problem?
1. Decrypt a Signed + Encrypted SOAP message using $WSSE->decryptSoapDoc()
2. As the decryption is done in place, it does not cleanup the DataReferences
which are now dangling as the previously pointed element has been replaced
Solution:
1. Initially attempted to fix through xmlseclibs but it's cleaner to patch via
WSSE to leave undecryptable references in place still
1. Cleanup the parent + ancestors leading to EncryptedKey when all
DataReferences are removed
What version of the product are you using? On what operating system?
1.1.0-dev (ubuntu 10 LTS)
Original issue reported on code.google.com by [email protected]
on 17 Jul 2014 at 12:07
Attachments:
Hi!
According to the forum, the 1.2 releases have been deleted. However, the message that this branch is still maintained and supported is still there. If there is a reason (security?) to withdraw older releases, please document that, and also don't call that branch supported. If the tags were deleted accidentally, please restore them!
Thanks!
Uli
I think is necessary a reference to an Issuer and Serial Number
Change over the createID to correct the namespace from uudi: to urn:uuid:
Original issue reported on code.google.com by [email protected]
on 10 Oct 2012 at 11:29
Attachments:
Hi how I can add raw XML in request before send? I want to add XML after current tag in body. For example right after " add BMWAudi". Thanks.
I found that the function:
private function createID() {
$uuid = md5(uniqid(rand(), true));
$guid = 'uudi:'.substr($uuid,0,8)."-".
substr($uuid,8,4)."-".
substr($uuid,12,4)."-".
substr($uuid,16,4)."-".
substr($uuid,20,12);
return $guid;
}
contains a typo. It should read uuid. Besides that, I enhanched it to read
urn:uuid
Original issue reported on code.google.com by [email protected]
on 3 Jun 2010 at 11:50
Filename: soap-wsse.php
function attachTokentoSig
Set attribute of token reference:
$reference->setAttribute('ValueType',
'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#
X509v3');
Original issue reported on code.google.com by [email protected]
on 19 May 2013 at 9:32
The WSSESoapServer
class lets you validate WSS Soap, (thank you!), but you can't get access to the certificate/key/thumbprint. The class is simple enough to extend and modify, but an easy fix would be to store $objKey
as an instance property so we can do:
$server = new WSSESoapServer($xml);
if ($server->verify()) {
$thumbprint = $server->objKey->getX509Thumbprint();
}
Also, adding an example along with the others would be nice. I can do a pull request if you'd like.
Hi everyone, is it possible to force the connection through TLS protocol instead SSL? Because with SSL protocol show me this error: "SSL operation failed with code 1. OpenSSL Error messages: error:140940E5:SSL routines:SSL3_READ_BYTES:ssl handshake failure". I will be grateful find help.
I'm trying to connect to a Webservice with Encryption, Signing, and a X509
certificate who doesn't have the "extension" part filled. Therefore, at line
321 of soap-wsse.php, the variable $data is empty, resulting in a base64
encoded null value in the <Reference tag of <wsse:SecurityTokenReference> tag.
I think it should raise an exception or return an error in this case.
Therefore, I tried to disable the X509SubjectKeyIdentifier option.
1. Line 42 of examples/ soap-sign-encrypt.php use empty array as third
parameter (options)
2. Run examples/ soap-sign-encrypt.php
The I got an error about getAttributeNS called on a non object line 328 of
soap-wsse.php.
I think I fixed the issue by :
Adding the following line :
$binarySecurityToken = $lastToken;
between these too lines (l287-288) :
if ($lastToken) {
$lastToken = $lastToken->nextSibling;
replacing $token by $binarySecurityToken in the following line (l328) :
$tokenURI = '#'.$token->getAttributeNS(WSSESoap::WSUNS, "Id");
It's a kind of dirty fix but it seemed to be the safer I could do without
breaking the rest.
I'm using the latest version on Ubuntu 8.04 LTS (PHP 5.2) and Ubuntu 10.04 LTS
(PHP 5.3).
Original issue reported on code.google.com by [email protected]
on 2 Nov 2010 at 9:53
https://github.com/robrichards/wse-php/blob/master/src/WSSESoapServer.php#L149
The third parameter should be true, since you're passing in a certificate:
$objKey->loadKey($x509cert, false, true);
Hello @robrichards,
Thanks for this awesome package!
I am using this one for adding WSA and WSSE middlewares to our soap-client.
I was trying to use the X509 encryption options as you showed in the examples.
I bounced against following 2 issues (in PHP7.1):
Function mcrypt_module_open() is deprecated:
https://wiki.php.net/rfc/mcrypt-viking-funeral
In the next major version, mcrypt will be removed. Maybe it's a good idea to look at alternative solutions?
Error: Call to undefined function RobRichards\WsePhp\split():
http://php.net/manual/en/function.split.php
This function is deprecated since 5.3 so shouldn't be used anymore.
This one is blocking the encryption functionality for the moment.
More information and a failing test are located here:
https://github.com/veewee/soap-client/blob/e0e594d5d130776d0941777afb819e879e06a56f/test/PhproTest/SoapClient/Unit/Middleware/WsseMiddlewareTest.php#L236
The WSSE middleware is located at this location:
https://github.com/veewee/soap-client/blob/e0e594d5d130776d0941777afb819e879e06a56f/src/Phpro/SoapClient/Middleware/WsseMiddleware.php
Can you give me some feedback on this? Thanks!
I used this example https://github.com/robrichards/wse-php/blob/master/examples/soap-sign-encrypt.php. I created own Public/Private Keys and followed exact steps in this example.
The webservice i am using is returning encrypted response. I tried to decrypt the response according to the example. But the decryption always fails and throws me an exception "Failure decrypting Data".
Could you please help ?
Currently I generate the security headers for a request as follows:
$doc = new DOMDocument('1.0');
$doc->formatOutput = true;
$doc->preserveWhiteSpace = false;
$doc->loadXML($request);
$objWSSE = new WSSESoap($doc, false);
/* Sign all headers to include signing the WS-Addressing headers /
$objWSSE->signAllHeaders = true;
$objWSSE->signBody = true;
$objWSSE->addTimestamp();
$objWSSE->addUserToken($this->_username, $this->_password, false);
/ create new XMLSec Key using RSA SHA-1 and type is private key /
$objKey = new XMLSecurityKey(XMLSecurityKey::RSA_SHA1, array('type' => 'private'));
/ load the private key from file - last arg is bool if key in file (true) or is string (FALSE) /
$objKey->loadKey(PRIVATE_KEY, true);
/ Sign the message - also signs appropraite WS-Security items /
$objWSSE->signSoapDoc($objKey);
/ Add certificate (BinarySecurityToken) to the message and attach pointer to Signature */
$token = $objWSSE->addBinaryToken(file_get_contents(CERT_FILE));
$objWSSE->attachTokentoSig($token);
$request = $objWSSE->saveXML();
When I make the request to the service I get the error message Hash values do not match
Not all SOAP servers require signing of body, so looking at the code this could
be built into the API with an option to explicitly state signing of the body as
is for headers for consistency
Original issue reported on code.google.com by [email protected]
on 27 Jan 2014 at 2:49
Attachments:
Hi, thank you for your package!
I found some security leaks for olders versions of robrichards/xmlseclibs . Do you think you can update dependencies in your composer.json?
For example if you are using newest version of Roave/SecurityAdvisories, they do not let you install your package.
I prepared PR here: #42
I hope I did it well
Thank you for your work on open source project
Have a great time :)
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">soap:Bodysoap:Faultsoap:ServerThese policy alternatives can not be satisfied:
{http://schemas.xmlsoap.org/ws/2005/07/securitypolicy}AsymmetricBinding: Received Timestamp does not match the requirements
{http://schemas.xmlsoap.org/ws/2005/07/securitypolicy}InitiatorToken
{http://schemas.xmlsoap.org/ws/2005/07/securitypolicy}X509Token: The received token does not match the token inclusion requirement
{http://schemas.xmlsoap.org/ws/2005/07/securitypolicy}RecipientToken
{http://schemas.xmlsoap.org/ws/2005/07/securitypolicy}IncludeTimestamp
{http://schemas.xmlsoap.org/ws/2005/07/securitypolicy}OnlySignEntireHeadersAndBody
{http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702}SignedEncryptedSupportingTokens: The received token does not match the signed encrypted supporting token requirement
{http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702}SignedParts: {http://schemas.xmlsoap.org/soap/envelope/}Body not SIGNED
{http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702}EncryptedParts: {http://schemas.xmlsoap.org/soap/envelope/}Body not ENCRYPTED</soap:Fault></soap:Body></soap:Envelope>
I'm talking to a SOAP service implemented in Axis2 with JAX-WS. The service requires authentication. I can only get the authentication to succeed if I include an EncodingType for the Nonce. If I don't include it, I get a service error.
The Nonce has to look like this:
<wsse:Nonce EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary">...DATA...</wsse:Nonce>
I have to inject the parameter in addUserToken() like this:
$nonceNode->setAttribute('EncodingType', 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary');
This obviously works for my scenario. Can it be added as default? Would it work for all other scenarios?
Lines 438 to 447 in c9611f5
The $refNode
variable is not used on this method, even more, I couldn't find the use of this method anywhere.
It seems there's two way to encrypt the Body, this mentioned method and the encryptSoapDoc
method which can also encrypt the Signature.
So, why thereś two way to do the same thing?, any advantage of one over the other?, and what about the unused variable? 😄
Greets and thanks.
Ernesto
Hi, I have the following problem. One part of parameters that we pass (like array) do not show in "echo $ objWSSE-> saveXML ();". How is that possible?
When I print_r array, keys and values are there, but when I "echo $ objWSSE-> saveXML ();" only one part there are the others gone. Any idea?
There is no example for the serverside code. Something with signing and
encryption would be nice.
Original issue reported on code.google.com by haavard.pedersen
on 13 Aug 2014 at 1:54
Hello,
according to OASIS Standard 1.0 for SOAP Message Security - probably implemented in library - (http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0.pdf) there are two MUST be used namespaces in Security header (line 179 - 2.2 Namespaces):
but inside metod WSSESoap::locateSecurityHeader() only one is added:
$secnode = $this->soapDoc->createElementNS(self::WSSENS, self::WSSEPFX.':Security');
$header->appendChild($secnode);
I fixed it by adding line:
$secnode->setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns'.':'.WSSESoap::WSUPFX, WSSESoap::WSUNS);
before
$header->appendChild($secnode);
Thank you!
Hi,
I have started the webservice integration for Income Tax bulk ITR but i am not able to encrypt the data by using public key of income tax getting following error.
Fatal error: Uncaught Exception: Unknown key size for type "http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p"
Hi, I had to consume a webservice that required WS-A, so I tried your library.
However, I was only successful after I changed the namespace:
diff -ruw wse-php_orig/src/WSASoap.php wse-php/src/WSASoap.php
--- wse-php_orig/src/WSASoap.php 2017-03-09 16:42:34.000000000 +0000
+++ wse-php/src/WSASoap.php 2017-07-19 10:46:54.672342000 +0000
@@ -48,7 +48,8 @@
*/
class WSASoap
{
- const WSANS = 'http://schemas.xmlsoap.org/ws/2004/08/addressing';
+ const WSANS = 'http://www.w3.org/2005/08/addressing';
const WSAPFX = 'wsa';
private $soapNS, $soapPFX;
private $soapDoc = null;
(To be of general use, this should probably be configurable, but the above change was enough to work for me)
Regards
Typo
Original issue reported on code.google.com by [email protected]
on 15 Dec 2012 at 10:33
Attachments:
Im trying to sign a SOAP envelope from a WSDL using WSSESoap PHP plugin. I cant make it work as it throws a 'Hash values do not match' issue. The WSDL is:
https://efactura.dgi.gub.uy:6470/ePrueba/ws_personaGetActEmpresarialPrueba?wsdl
Im calling from
$sc = new MySoap($wsdl);
$out = $sc->Execute(array("Rut"=>"123456789"));
And getting the 'Hash values do not match' error.
I did a research and seems the problem is when canonizing the Body from the envelop as there is using Inclusivenamespace and prefixes list. I get this working request from SOAPUI.
Here is te reference tag pointing to the Body object.
<ds:Reference URI="#id-99A5113916FE1B896D152461497086267">
<ds:Transforms>
<ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#">
<ec:InclusiveNamespaces xmlns:ec="http://www.w3.org/2001/10/xml-exc-c14n#" PrefixList="dgi"/>
</ds:Transform>
</ds:Transforms>
<ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
<ds:DigestValue>iWbErI+zKd+Go3r88YKrh+nZmmE=</ds:DigestValue>
</ds:Reference>
I also tried to Canonize the SOAP BODY with C14N, but didnt work.
Any workaround for that??
Hello!
I know that you maintain this wonderful xmlseclib library which I am currently using.
And I have a question about it, maybe you could help me with finding a proper soultion.
Here is a problem:
This is the WS-POLICY for the service:
<wsp:Policy wsu:Id="CustomBinding_IServiceCustomer_policy">
<wsp:ExactlyOne>
<wsp:All>
<sp:SymmetricBinding xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy">
<wsp:Policy>
<sp:ProtectionToken>
<wsp:Policy>
<sp:X509Token sp:IncludeToken="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy/IncludeToken/Never">
<wsp:Policy>
<sp:RequireDerivedKeys/>
<sp:RequireThumbprintReference/>
<sp:WssX509V3Token10/>
</wsp:Policy>
</sp:X509Token>
</wsp:Policy>
</sp:ProtectionToken>
<sp:AlgorithmSuite>
<wsp:Policy>
<sp:Basic128Rsa15/>
</wsp:Policy>
</sp:AlgorithmSuite>
<sp:Layout>
<wsp:Policy>
<sp:Strict/>
</wsp:Policy>
</sp:Layout>
<sp:IncludeTimestamp/>
<sp:OnlySignEntireHeadersAndBody/>
</wsp:Policy>
</sp:SymmetricBinding>
<sp:EndorsingSupportingTokens xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy">
<wsp:Policy>
<sp:X509Token sp:IncludeToken="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy/IncludeToken/AlwaysToRecipient">
<wsp:Policy>
<sp:RequireThumbprintReference/>
<sp:WssX509V3Token10/>
</wsp:Policy>
</sp:X509Token>
</wsp:Policy>
</sp:EndorsingSupportingTokens>
<sp:Wss11 xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy">
<wsp:Policy>
<sp:MustSupportRefThumbprint/>
<sp:MustSupportRefEncryptedKey/>
<sp:RequireSignatureConfirmation/>
</wsp:Policy>
</sp:Wss11>
<sp:Trust10 xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy">
<wsp:Policy>
<sp:MustSupportIssuedTokens/>
<sp:RequireClientEntropy/>
<sp:RequireServerEntropy/>
</wsp:Policy>
</sp:Trust10>
<sp:TransportBinding xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy">
<wsp:Policy>
<sp:TransportToken>
<wsp:Policy>
<sp:HttpsToken RequireClientCertificate="false"/>
</wsp:Policy>
</sp:TransportToken>
<sp:AlgorithmSuite>
<wsp:Policy>
<sp:Basic256/>
</wsp:Policy>
</sp:AlgorithmSuite>
<sp:Layout>
<wsp:Policy>
<sp:Strict/>
</wsp:Policy>
</sp:Layout>
<sp:IncludeTimestamp/>
</wsp:Policy>
</sp:TransportBinding>
<wsaw:UsingAddressing/>
</wsp:All>
</wsp:ExactlyOne>
</wsp:Policy>
The problem is following:
According to POLICY (RequireDerivedKeys), user needs 2 DerivedKeyTokens (one for signing, other for encrypting).
And soap-wsse.php, unfortunatelly, lacks this functionality.
Therefore I added my own functions to cover that.
To create keys, I use following p-sha1 function: http://stackoverflow.com/questions/19590675/implementation-of-p-sha1-algorithm-in-php
According to POLICY (EndorsingSupportingTokens), we need to sign already created signature.
This implementation is also missing in soap-wssse.php.
I created my own function for that, but I'm not sure if it works correctly.
As a result, I receive following response after I send generated XML:
CryptographicException: Unable to resolve the '#...' URI in the signature to compute the digest.
Can you please help me with those tokens? Do you find it reasonable to add such support for DerivedKeyToken into your class?
Thank you!
Hello,
I have error during execution of this code:
/* create new XMLSec Key using AES256_CBC and type is private key */
$objKey = new XMLSecurityKey(XMLSecurityKey::RSA_SHA1, array('type' => 'private'));
/* load the private key from file - last arg is bool if key in file (true) or is string (false) */
$objKey->loadKey(PRIVATE_KEY, true);
/* Sign the message - also signs appropiate WS-Security items */
$options = ["insertBefore" => true, "KeyInfo" => ["X509SubjectKeyIdentifier" => true]];
$objWSSE->signSoapDoc($objKey, $options);
The problem is related to following code (line 265 inside WSSESoap.php::signSoapDoc():
$x509 = openssl_x509_parse($objKey->getX509Certificate());
$keyid = $x509["extensions"]["subjectKeyIdentifier"];
$arkeyid = split(":", $keyid);
$data = "";
foreach ($arkeyid AS $hexchar) {
$data .= chr(hexdec($hexchar));
}
$dataNode = new DOMText(base64_encode($data));
$reference->appendChild($dataNode);
There is no X.509 certificate inside $objKey and there is no way to attach it, because $objKey has already contains private key (and it OK, because I need it to sign message, what is done in line 243 of this method).
The above code should also issue some error in such case rather then be continued as is now.
Is there any way to build $objKey to fulfill requirmenst of options ["KeyInfo"]["X509SubjectKeyIdentifier"]?
Thank you!
Fatal error: Uncaught SoapFault exception: [Client] Class 'XMLSecurityKey' not found in
Following the example in soap-sign-encrypt.php, I show the related calls to the problem 😄 :
wse-php/examples/soap-sign-encrypt.php
Line 47 in c9611f5
Line 450 in c9611f5
Line 476 in c9611f5
encryptSoapDoc calls addEncryptedKey with $siteKey as the third parameter which is a XMLSecurityKey
Line 324 in c9611f5
addEncryptedKey receives the XMLSecurityKey on the variable $token
Line 390 in c9611f5
and tries to use it as a DOMElement::getAttributeNS call which is incorrect 😞
Greets
Ernesto
Hello,
this is not an issue which breaks code or make message invalid but leads to inconsistent namespace prefixing. Everywhere in code namespace http://www.w3.org/2000/09/xmldsig has prefix "ds" (from XMLSecurityDSig class) but in WSSESoap::addEncryptedKey() this namspace is introduced with prefix "dsig".
Line 318:
$keyInfo = $objDoc->createElementNS('http://www.w3.org/2000/09/xmldsig#', 'dsig:KeyInfo');
Thank you!
Could you told me if any of your classes could be used as ws-trust client? because they have different name which I don't know what they mean.
Hello,
the problem is in WSSESoap::addEncryptedKey() method and it is related to inserting EncryptedKey element on position which is based on lastToken.
For the following flow:
The xenc:EncryptedKey node is added as last child becase of code:
$lastToken = null;
$findTokens = $security->firstChild;
while ($findTokens) {
if ($findTokens->localName == 'BinarySecurityToken') {
$lastToken = $findTokens;
}
$findTokens = $findTokens->nextSibling;
}
if ($lastToken) {
$lastToken = $lastToken->nextSibling;
}
There is no BinarySecurityToken so $lastToken is null and following line:
$security->insertBefore($encKey, $lastToken);
adds xenc:EncryptedKey as the last child of wsse:Security. However in presented flow xenc:EncryptedKey should appeared before ds:Signature. This is becase of fact that the signing/encryption order is specified within the wsse:Security header.
If document is signed prior to encryption the xenc:EncryptedKey should be before ds:Signature.
Thank you.
Hello Rob
im use this library to get a webservice but i have a problem:
the receiver send this error message and success request xml to me:
error messgae:
Expected : thumbprint , Actual : ski. Ensure that a compatible policy is attached at the client side.
i found that my request xml has diffent nodes some like that:
mine:
<wsse:KeyIdentifier ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509SubjectKeyIdentifier" EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary">AA==</wsse:KeyIdentifier>
their:
<wsse:KeyIdentifier ValueType="http://docs.oasis-open.org/wss/oasis-wss-soap-message-security-1.1#ThumbprintSHA1" EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary">l5C+mmfqnkYYf6GcwjIsbCRpa4g=</wsse:KeyIdentifier>
could u help me? Thank you...
wse-php uses mcrypt extension, which was removed from PHP 7.2 https://secure.php.net/manual/en/intro.mcrypt.php
Do you have plan to switch to OpenSSL?
hi all,
I discover soap with wse.
But i am confronted to a problem, i use a certificat x509 to reach a webservice but this server need a signed timestamp.
Anybody have already tried to sign a timestamp ?
Can we get MTOM support please. Your library is the only PHP solution in the world.
Hi Rob!
Im' using your https://github.com/robrichards/wse-php
What do you think about these?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.