Showing posts with label PHP. Show all posts
Showing posts with label PHP. Show all posts

Wednesday, 4 May 2011

PHP .htaccess redirect

I have been helping a neighbour of mine who is an Optician in Spalding, and he was trying to make sure that when people were searching for "Opticians in Spalding" they would make sure that the old pages on his website that were already listed in Google, would still link through to his new site that he's spent ages on.

Being a windows server man, I know how to do this in IIS, but as his new website is hosted on a linux server, it needed to be compatible with that. So anyway, I found out that you can do 301 redirects on Apache using a .htaccess file.

In this case, it was real simple, create a blank file called .htaccess and the place an entry for each for each file that needs redirecting, i.e:

Redirect 301 /HTML/Consultations.htm http://www.molsom.co.uk/eye-tests.htm

Excellent, and I now know that visitors to my local Optician in Spalding will still get there from any old bookmarks!

Thursday, 31 December 2009

Making changes to overall_header.php in phpBB do not take effect

I have been, for some time, trying to make changes to the code in the header file for phpBB. These were not changes for functionality, rather links required to other parts of the site.

Anyway, I had made the changes locally in my local copy of the overall_header.php file of the prosilver theme, but I ftp'd them up, the changes didn't happen.

Frustrated, I spent some time checking what phpBBs admin area said was in the file using the built in editor, and it said my changes were done.

However, what it doesn't say is that once you've made any changes to page files or style documents, you have to run the PURGE ALL feature from the admin control panel to flush out cached copies!

Ran that, and hey presto, fixed.

Tuesday, 17 November 2009

PHP C# WCF Rijndael

I have been working with .NET and webservices for some time, but a colleague of mine has now moved over to using WCF instead of basic webservices.

After many, many problems dealing with simple soap message exchanges, we finally got our WCF service to talk to PHP (using NuSOAP) by setting the encoding to UTF8 and the binding to type basicHttpBinding.

My next problem was why when I was encoding data using Rijndael, was the encoded data returned from WCF not being decoded by mcrypt in PHP correctly.

Eventually, after some digging around, I found a really good article at http://benvanmol.blogspot.com/2009/10/secure-communication-between-net-and.html that summises the following points:

• You need to enable padding in the .net rijndael class. This ensures any blocks are padded with 0’s to fill them. This is done with Padding.Zeros
• Specifically set Cipher Block Chaining in the .Net class.
• The Initialisation Vector (IV) needs to be 16 bytes.
• You need to specifically set the encryption to the MD5 Hash algorithm, and change this to return the 32 character hash.
• Setup base64 encoding either end.

So, from this article by Ben van Mol I was able to produce a class from his code as follows:


public class PhpRijndael
{
System.Security.Cryptography.Rijndael r = null;

public void InitializePhpRijndael(string iv, string key,int blockSize)
{
byte[] keyBytes = Encoding.ASCII.GetBytes(EncodeTo64(key));
byte[] hash = MD5.Create().ComputeHash(keyBytes);
string ret = "";
foreach (byte a in hash)
{
ret += a.ToString("x2");
}
string iv64 = EncodeTo64(iv);
byte[] ivBytes = Convert.FromBase64String(iv64);

r = System.Security.Cryptography.Rijndael.Create();

r.Padding = PaddingMode.Zeros;
r.BlockSize = blockSize;
r.Key = Encoding.ASCII.GetBytes(ret);
r.IV = ivBytes;

}

public string Decrypt(string str)
{
byte[] encryptedBytes = Convert.FromBase64String(str);
byte[] decryptedBytes = transformBytes(
r.CreateDecryptor(), encryptedBytes);

string plaintext = Encoding.ASCII.GetString(decryptedBytes);
int idx = plaintext.IndexOf("\0");
if (idx > -1)
plaintext = plaintext.Substring(0, idx);

return plaintext;
}

public string Encrypt(string plaintext)
{
byte[] plainBytes = Encoding.ASCII.GetBytes(plaintext);
byte[] encryptedBytes = transformBytes(
r.CreateEncryptor(), plainBytes);

return Convert.ToBase64String(encryptedBytes);
}

private byte[] transformBytes(ICryptoTransform transform,
byte[] plainBytes)
{
MemoryStream memStream = new MemoryStream();
CryptoStream cryptStream =
new CryptoStream(memStream, transform,
CryptoStreamMode.Write);
cryptStream.Write(plainBytes, 0, plainBytes.Length);
cryptStream.Close();
byte[] encryptedBytes = memStream.ToArray();
memStream.Close();

return encryptedBytes;
}

private string EncodeTo64(string toEncode)
{
byte[] toEncodeAsBytes = System.Text.ASCIIEncoding.ASCII.GetBytes(toEncode);
string returnValue = System.Convert.ToBase64String(toEncodeAsBytes);

return returnValue;

}
}


In WCF I expose this in my endpoint as:

private string passPhrase = "secret";
private string initVector = "ujkrtadxcfrzpj1Bs5fpM18doZQDGYS4";
private int keySize = 256;

public string EncryptData(string value)
{

PhpRijndael r = new PhpRijndael();
r.InitializePhpRijndael(initVector, passPhrase, keySize);
string ret = "";
ret = r.Encrypt(value);
return ret;
}
public string ReturnTestData()
{
return EncryptData("Test Encrypted Data");
}

Note: Both of these are expose on the interface as OperationContracts inside the ServiceContract.

Now, in the PHP world, we need to create a page to call this, so inside a normal html form, we do the following:

if( isset($_POST['Submit']) )
{
//Show me all errors please
error_reporting(E_ALL);
ini_set('display_errors', '1');
//load nusoap
require_once('../lib/nusoap.php');
//client config to CZ
$client = new nusoap_client('http://example/Service?wsdl',true);
$client->setEndpoint("http://example/Service/EndpointName");
$client->setUseCurl(0);
//set utf-8, or else it breaks.
$client->soap_defencoding='UTF-8';
$client->setDebugLevel( 1 );
//any errors?
$err = $client->getError();
if ($err) {
echo '

Constructor error

' . $err . '
';
echo '

Debug

' . htmlspecialchars($client->getDebug(), ENT_QUOTES) . '
';
exit();
}
// This is a paramter list that can be used later, but not used at the moment
$params = array(
'value' => "666"
);
//Call dummy method for some test info
$result = $client->call('ReturnTestData',$params);
//is there a fault?
if ($client->fault) {
echo '

Fault

'; print_r($result); echo '
';
} else {
$err = $client->getError();
if ($err) {
echo '

Error

' . $err . '
';
} else {
echo '

Result

'; print_r($result); echo '
';
}
}

//decode the base sixty four encoded data returned
$bsf = base64_decode(trim($result["ReturnTestDataResult"]));

//setup auth
$key = 'secret';
$iv='ujkrtadxcfrzpj1Bs5fpM18doZQDGYS4';

//a function to configure Rijndael from the afforementioned article
function init_rijndael ($key,$iv) {
$rj = mcrypt_module_open('rijndael-256', '', 'cbc', '');
if ($rj !== FALSE)
{
$expected_key_size = mcrypt_enc_get_key_size($rj);

$key = substr(md5(base64_encode($key)), 0, $expected_key_size);

mcrypt_generic_init($rj, $key, $iv);
}
return $rj;
}
//setup Rijndael
$rj = init_rijndael($key,$iv);

//decrypt result
$decryptedResult = mdecrypt_generic($rj, $bsf);
//print out.
echo '

Result

'; echo($decryptedResult); echo '
';
}


And hey presto - finally! a working php to WCF communication in Rijndael!