Sep 27

ITJungle publishes announcement of distributor status for ‘EASYCOM for PHP’

ITJungle published an article about Shield Advanced Solutions becoming a distributor for EASYCOM for PHP. They extracted information from our Blog and website without any interviews with us. They seem to have hit the proverbial ‘nail on the head’ and bring up a number of important messages about EASYCOM for PHP and the current Zend situation. We are not saying Zend is a bad thing, just that we have an alternative that you should strongly consider.

I think you will see a lot more from AURA Equipments around PHP for the IBMi as the year progresses. We are certainly seeing a lot of new technology and improvements to the existing i5 tookit which have not been integrated into the Zend PHP stack and probably never will be. Separation from IBM and Zend may be the best thing that has happened to AURA? Only time will tell..

Chris…

Sep 27

14 Years and counting Shield Advanced Solutions.


I have just realized that I have now been running Shield Advanced Solutions for over 14 years! What happened? It seems like a few years ago we first arrived in Canada to settle and make a new life for ourselves. The company was meant to be a duplicate of the UK company re-selling HA products, but having eventually sold the UK company (after running it for 10 years) we decided to concentrate on the development side with our JobQGenie product. A lot has changed in that time and so has the market place, but we are still here and so is the IBM i(AS/400,Systemi,iSeries etc). HA4i and DR4i are gaining momentum in the market place which is ensuring we can continue to develop and support products for the IBMi market, but we are also very excited about the new EASYCOM for PHP product which allows us to spread our wings into new platforms and areas of expertise.

So here is to the future and hoping the IBMi platform continues to exist….

Chris…

Sep 23

Re-test of the new XMLSERVICE after optimizing the RPG programs.

The discussion about the new XMLSERVICE performance on the iSeriesNetwork forums pointed us to a possible improvement for the XMLSERVICE which is not shipped as standard. The poster suggested that we change the Compiler options for the RPG programs to *FULL optimization and try the tests again. I would question why the CL programs which are shipped do not have this already set if its a known improvement. But we dutifully went through the CL programs and set the Optimization parameters and created the programs again.

Here is the result of the tests now, it should be noted that the initial call is a lot slower than a subsequent call so we took the liberty of refreshing the screen a couple of times before copying the results.

New Zend Toolkit. Input value is changing on each call.

Time (loop=5000) total=22.32 sec (4.46 ms per call)

Parameter name Input value Output value
var1 Y C
var2 Z D
var3 001.0001 321.1234
var4 0000000003.04 1234567890.12
ds1 A E
ds2 B F
ds3 005.0007 333.3330
ds4 0000000006.08 4444444444.44

As you can see it does show an improvement over the previous test, but it is still far slower than the EASYCOM for PHP process. The poster does mention that we should be running on the latest version 1.5 which we checked, the programs are not noted with the release level (maybe that would be a good idea) but the Zip file we downloaded is xmlservice-rpg-1.5 which should indicate the contents are the version 1.5 code level? If not maybe the above numbers will also improve with the correct level of code.

These tests were run on a fairly low end system, maybe the use of a bigger system with lots of memory and CPU will change the span between the 2 processes? If you do have a big system and want to run the same tests we did we will be happy to publish your results.

We have also created a new group on LinkedIn which will discuss the use of EASYCOM for PHP, you can join the group and engage with us in making PHP for IBM i a great solution for application modernization.

Chris…

Sep 22

LinkedIn group formed for EASYCOM for PHP.


We have started a group for EASYCOM for PHP on LinkedIn. If you are interested in getting involved or have some questions about EASYCOM for PHP it is a place to visit. We are hoping to increase the awareness of the product and its capabilities plus engage others in discussing coding issues around the IBM i PHP environment.

If you are using LinkedIn or just want to get involved take a look and post your questions etc. We hope to make the group a lively and engaging place for people to discuss EASYCOM for PHP and the IBM i.

Chris…

Sep 21

Secure password storage for i5_connect connections.

One of the questions which gets asked a lot is how do I store passwords for connections to the IBM i. If I am doing internal development (does not require security to be too strict) I will usually store the password in plain text because for anyone to get to the passwords they would have to be able to access the IBM i IFS and look through the correct directory to find the appropriate session data to get to the password. Then they have to link that up with an appropriate profile! That is not something anyone in our company will spend the time doing or in most instances have the knowledge to do.

In a production application which could be exposed to outside influences we would need to harden up the security somewhat. Normal users may still have problems getting to the data but a determined hacker will not be phased by having to troll through the session variables.. So we have to come up with a way to store the data in an encrypted manner and which requires a number of session data variables to be combined to make it work. We would still strongly advise those of you who are walking down this route to consider additional security measures such as locking down the directory where the session variables are stored to PUBLIC *EXCLUDE, as a minimum.

PHP provides a number of encryption modules which have to be enabled for the following code to work, if you need help on setting this up there are plenty of links in Google to help you and it is beyond the scope of this post to add here. Once the modules are enabled and the servers re-started you can start to code up something similar to the following.

First of all we need a few functions which will be called to do the encryption for us. We have 3 functions defined, one to generate the initialization value and the unique key value we will use to encrypt and decrypt the data, another one to encrypt the plain text password and another to decrypt it.

Here is the code for the unique value generation.


/*
* function create hex value
* Used to create initialization variables and unique keys
* @parms
*
*/

function get_unique_key($len) {
// create a unique value in the string for the specified number of bytes
$data = '';
do {
$data .= hash('sha256', uniqid(mt_rand(), TRUE), TRUE) ;
} while ( strlen($data) < $len ) ;
return $data;
}

All it is doing is creating a unique string to the length passed in and returning that string to the calling function. The PHP manual gives you the information on the functions used and plenty of examples. We are passing in a random number as a prefix to the uniqid() function which generates a 23 character string that is hashed and appended to the previous request until the required minimum length is reached (in fact it will normally be exceeded unless the required length is an exact multiple of 23).

The next function will do the encryption.

/*
* function to encrypt password
*/

function e_pwd($pwd) {
$alg = MCRYPT_RIJNDAEL_256 ;
$m = MCRYPT_MODE_CBC ;

// get the length the initialization value
$_SESSION['i_len'] = mcrypt_get_iv_size($alg, $m);
$_SESSION['init_val'] = substr(get_unique_key($i_len), 0, $i_len) ;
// get the length the key needs to be for the encryption
$_SESSION['key_len'] = mcrypt_get_key_size($alg, $m);
// the returned value will be padded with 0's so strip off
$_SESSION['key'] = substr(get_unique_key($_SESSION['key_len']),0,$_SESSION['key_len']);
$_SESSION['pwd'] = mcrypt_encrypt($alg, $_SESSION['key'], $pwd, $m, $_SESSION['init_val']);
return;
}

The above code is using session variables to store the keys and lengths plus the encrypted password. The above function receives the plaintext password via the login script that is called when the form submit button is pressed. The password is passed to the script in a POST variable called 'pwd'. We store the various initialization and key values as SESSION variables in the above module so we can use them in the decrypt function.

Here is the decrypt function, as you can see it is very simple. We could store the algorithm and mode as well outside of the script but for this test it was not important. All we have to do is pass in the session variables to the decrypt() function and return the results.


/*
* function to de-encrypt password
*/

function d_pwd() {
$alg = MCRYPT_RIJNDAEL_256 ;
$m = MCRYPT_MODE_CBC ;

return mcrypt_decrypt($alg, $_SESSION['key'], $_SESSION['pwd'], $m, $_SESSION['init_val']);
}

So based on the above functions here is how we used them in our pages. First when a user logs in we have a form which has a password field and user field defined. This is only part of the script to generate the page, before this we have a check to see if the user is already signed on. We only show this bit so you can see where we manipulate the password data.

<h3>Sign On</h3>
<form name=login method="post" action="scripts/login.php">
<table width="20%" align="center" border="1" cellpadding="1">
<tr><td><label>User ID :</label></td><td><input type="text" name="usr" /></td></tr>
<tr><td>Password:</td><td><input type="password" name="pwd" /></td></tr>
<tr><td colspan="2" align=center><input type="submit" value="Log in" /></td></tr><?php
if(isset($_SESSION['Pwd_Err'])) {
if($_SESSION['Pwd_Err'] == 1) { ?>
<tr><td colspan="2" align=center>Sorry the credentials were rejected by the <?php echo($_SESSION['sys']); ?> System</td></tr><?php
$_SESSION['Pwd_Err'] = 0;
}
} ?>
</table>
</form>

Here is part of the login script that encrypts the password and stores the user name etc.

// store the user and password(encrypted)
$_SESSION['usr'] = $_POST['usr'];
e_pwd($_POST['pwd']);
$_SESSION['server'] = "ServerName";
// if failed to connect set the $_SESSION variables to empty
if(connect($conn) == -1) {
$_SESSION['Pwd_Err'] = 1;
$_SESSION['usr'] = "";
$_SESSION['pwd'] = "";
header('Location: /index.php');
exit(0);
}

And finally this is a function which does the connection.


function connect(&$conn) {
// connect to the i5
$conId = 0;
if (isset($_SESSION['ConnectionID'])) {
$conId = $_SESSION['ConnectionID'];
}
$server = $_SESSION['server'];
// options array for the private connection
$options = array(I5_OPTIONS_PRIVATE_CONNECTION => $conId,
I5_OPTIONS_IDLE_TIMEOUT => $_SESSION['timeout'],
I5_OPTIONS_JOBNAME => 'PHPTSTSVR');
// connect to the system
$conn = i5_pconnect($server,$_SESSION['usr'],d_pwd($_SESSION['pwd']),$options);
// if connect failed
if(is_bool($conn) && $conn == FALSE) {
$errorTab = i5_error();
if ($errorTab['cat'] == 9 && $errorTab['num'] == 285){
$_SESSION['ConnectionID'] = 0;
$_SESSION['Err_Msg'] = "Failed to connect";
return -1;
}
else {
//set the error message
$_SESSION['Err_Msg'] = "Connection Failed " .i5_errormsg();
// send back to the sign on screen
$_SESSION['ConnectionID'] = 0;
return -1;
}
}
return 1;
}

That's it, now when a user gets past the login screen the data is stored in session variables that can be retrieved and decrypted. We have used the i5_toolkit functions to do the connections because we use them for all data and object collection from the IBM i but, you could use the same principle for other connections as well. To force the user to sign back in you can use the session_destroy() function to remove all of the session variables at once.

Hope you find this interesting, if you have any questions or suggestions for improving the code let us know.

Chris...

Sep 20

Passing a Data Structure to a remote Service program on the IBMi


We recently converted an application developed to manage our products and license keys from UIM (User Interface Manager) and C programs to a PHP based solution. Most of the C programs became redundant as we were no longer managing the interfaces under UIM, however some programs could not be replaced because they call IBM API’s so we had to create service programs to call these API’s from. One thing we had never done before was pass a completed structure into an i5_program() request, we had set up structures to receive data but never initialized one in before passing it in.

The Easycom for PHP documentation is definitely getting better but we still had a hard time understanding how to code the requests. Below is our version of the simple mans guide to passing initialized structures into i5_program() calls.

First of all we had to define the structure we would be passing in.
The structure would carry all of the information we required to create a license key using the IBM software product API’s Plus we would pass in a pointer to a return array which we would use to return any messages back to the PHP program. We limited the array length to 100 characters but it could have been a lot larger.

$desc = array(
array("DSName" =>"keyinfo", "DSParm" => array(
array("Name" => "custnbr", "io" => I5_IN, "type" => I5_TYPE_INT),
array("Name" => "prdid", "io" => I5_IN, "type" => I5_TYPE_CHAR, "length" => "7"),
array("Name" => "rlslvl", "io" => I5_IN, "type" => I5_TYPE_CHAR, "length" => "6"),
array("Name" => "licterm", "io" => I5_IN, "type" => I5_TYPE_CHAR, "length" => "6"),
array("Name" => "feat", "io" => I5_IN, "type" => I5_TYPE_CHAR, "length" => "4"),
array("Name" => "usglmt", "io" => I5_IN, "type" => I5_TYPE_INT),
array("Name" => "expdate", "io" => I5_IN, "type" => I5_TYPE_CHAR, "length" => "7"),
array("Name" => "v_pwd", "io" => I5_IN, "type" => I5_TYPE_CHAR, "length" => "10"),
array("Name" => "srlnbr", "io" => I5_IN, "type" => I5_TYPE_CHAR, "length" => "8"),
array("Name" => "prcgrp", "io" => I5_IN, "type" => I5_TYPE_CHAR, "length" => "4"),
array("Name" => "vdata", "io" => I5_IN, "type" => I5_TYPE_CHAR, "length" => "8"))),
array("Name" => 'err', "io" => I5_OUT, "type" => I5_TYPE_CHAR, "length" =>"100"));

Once we have create the structure we need to tel the IBMi server what to expect so we call the IBM prepare passing in the description of the parameters.


$prog = i5_program_prepare ( "SVRPGM(gen_lic_key)", $desc,$conn);
if ($prog === FALSE) {
echo("Error code: " .i5_errno() ."\n");
echo("Error message: " .i5_errormsg() ."\n");
die ();
}

The data which needs to be sent to the program is collected in a form so we simply set the ‘keyinfo’ data accordingly. To do this we created a new array of arrays called DsParameter which we set the content of.

$DsParameter = array(
"custnbr" => $_POST['custnbr'],
"prdid" => $_POST['Prod'],
"rlslvl" => $_POST['Version'],
"licterm" => $_POST['Term'],
"feat" => $_POST['feat'],
"usglmt" => $usg_lmt,
"expdate" => $exp_date,
"v_pwd" => strtoupper($_POST['v_pwd']),
"srlnbr" => $_POST['srlnbr'],
"prcgrp" => $_POST['prcgrp'],
"vdata" => strtoupper($_POST['vdata']));

Next we set up the parameters which we are going to pass into the i5_program() call. Because we initialized the DsParameter array we can use it to be the data structure ‘keyinfo’.


$parameter = array("keyinfo" => $DsParameter);
$parmOut = array("err" => "errmsg");

Now all we have to do is call the program.

$ret = i5_program_call($prog, $parameter, $parmOut);
if (!$ret) {
throw_error("i5_program_call");
exit();
}
i5_program_close($prog);

That is it, it all worked perfectly.. The trick was setting up the $DsParameter array and passing it in as the content of the $parameter variable.

Just for completeness here is the structure of the C program we are calling.


// define the structure which is passed in
typedef _Packed struct Lic_Req_x {
int CustNbr;
char PID[7];
char Rls_Lvl[6];
char Lic_Term[6];
char Feat[4];
int UsgLmt;
char Exp_Date[7];
char V_Pwd[10];
char Srl_Nbr[8];
char Prc_Grp[4];
char V_Data[10];
} Lic_Req_t;

// gen_lic_key function passed 2 character pointers
int gen_lic_key(char *input,char *err) {
// declare the structure pointer
Lic_Req_t *Req;
// assign the structure pointer to the data passed in.
Req = (Lic_Req_t *)input;

Chris…

Sep 19

Easycom Server for IBMi distributorship.


We have been working closely with Aura Equipments in France on their Easycom Server product for sometime. We absolutely love the product and even though we feel an IBMi centric solution is preferable where possible, using Easycom server on the IBMi with the web service running on a remote server (Windows or Linux, doesn’t matter) provides too many benefits to ignore.

For a long time we have been involved in posting on the set up of the Zend product on the IBMi, we have seen the product improve significantly since Zend introduced the Zend Server product to replace the Zend Core product but have always been impressed with the speed and capabilities of running Easycom server on a separate server accessing the IBMi. Even though Zend is easier now it is still difficult for many and a lack of support after the first year without considerable cost is causing many to give up before the real benefits are seen.

A recent post about the new XMLSERVICE made up our minds, we wanted to be a part of the Easycom network. We have seen a lot of FUD in the market stating the new XMLSERVICE is far better than the existing i5_toolkit which is one of the reasons for the recent posts. Looking at what you get from the i5_toolkit in terms of access to IBMi objects and data the XMLSERVICE is severely lacking and the existing release does not perform as well as Zend would have us believe. I am sure they will improve the functionality eventually and I expect they will come out with a wrapper which will mask the i5_toolkit calls to run the XMLSERVICE under the covers but that will add even more overhead to the process and I am sure cause a number of issues when converting the existing calls into the new ones.

This has prompted us to become a distributor for the Easycom Server product. If you are interested in seeing a demo of the product or would like more information and costs associated with the Easycom server let us know. The UK company will also provide a focus on the Easycom Server product for those companies in the UK which need support and information. If you go to our website you will find a new page which provides some information on the Easycom Server. As time progresses you will be seeing a lot more from us about the Easycom Server and how to implement it to access the IBMi objects and data.

I am sure Aura Equipments will continue to improve their product line and bring new and exciting innovation to the IBMi PHP environment. I know of some new enhancements which I hope to share with you soon..

Chris…

Sep 16

5733SC1 Downloads, we are still getting lots of requests for downloads


If you are looking for the 5733SC1 downloads please contact IBM. We have removed the downloads for a number of reasons but mainly because IBM legal has an issue with anyone but IBM providing their software for download even if it is a free option.

My suggestion is you contact your IBM representative to get hold of the download links from the IBM website, the software is non chargeable but you need a maintenance agreement to have access to the IBM download area.

If you are stuck without maintenance and still want to run PHP with access to the IBMi I would suggest one of the following options.

Firstly you could install the XMLSERVICE which is available from the Yips Wiki. This should allow you to connect to the IBMi and use the functions available to access your data. We have not tested the DB2 access only the program calling (see the Blog entry) which was not as fast as we had been expecting considering all of the statements we had seen. There are a number of articles around that discuss the capabilities of the XMLSERVICE so we will not discuss them here.

If you would like to have a much more comprehensive solution you can opt for the EasyCom Server which is supplied by Aura Equipments of France. This is our preferred option because it allows us to run the PHP code on Windows and Linux access the IBMi via the EasyCom Server port. This is the very same EasyCom server provided by Zend that allows the i5_toolkit to function but it can be accessed from remote servers (except the Zend Version is usually way behind the Aura Equipments version). Not sure how long the i5_toolkit will be included in the Zend Server product but the word on the street is Zend are looking to replace it with the XMLSERVICE toolkit? I think this is a bad move on a number of fronts but for those who are looking for an open source option with access to the source code to allow updating by yourself this is a valid option. The i5_toolkit has a lot more capabilities than the XMLSERVICE toolkit to-date (its still only in BETA) and I am sure there are lots of sites out there now which are going to need to continue to use the EasyCom Server so not sure how Zend will overcome that. If you are interested in the EasyCom Server option gives us a call and we will be happy to supply you with the information you need.

If IBM does put up any additional links for 5733SC1 we will post them..

Chris…

Sep 15

New Features for HA4i


We have finally managed to get the latest PTF for HA4i fixed and uploaded to the download area. The PTF had been put on hold due to a couple of issues with the build process and the IBM API’s. Basically there was a flaw which caused the exit program to be called when it should not have been. IBM has since provided us with a fix that now ensures the build process correctly sets the program calls for the APYPTF process.

This PTF brings a number of new features to the product.

The Sync Manager has seen a number of improvements, here are a couple of note worthy changes.
Firstly we no longer drop a request if the object is locked, the request is now added back to the queue so it will keep trying the request until it does get the object saved and transported to the target system for restore. Where an object is constantly locked delays are added to ensure the job does not consume too much system resource.
Next we add more information within the process so you can now see the progress of the requests with percentage sent status showing just how much data is left to be transported to the target system. We also added information about the object being replicated so users can see which object is being processed and what stage it is in such as Lock wait etc.
Finally we added options to reduce the lock time and send time by allowing access paths to be left out when doing the save which can significantly reduce the save and send time. We also added compression to the object to ensure we send as small amount of data as possible. If you have a very low bandwidth connection between your systems you can now sync objects manually using tape saves etc while still ensuring the restore process lines up with the data apply process.

As we have posted many times in the past the IBM save and restore processes on the IBMi are not the most reliable, many times we have found attributes are ignored during the restore when the object already exists. We are now checking for the existence of the object prior to the restore and deleting the existing object, Logical files were a particular problem when restoring Physical files so a new process has been added which ensures the physical file can be deleted while the logical files are maintained. This has had a significant impact on the Sync Manager Process which would often show a successful operation where in fact the object was restored but the logical files were left over a renamed object.

Audits are very import to ensure the data and objects are consistent between the systems. Its not that the apply process is inconsistent but we have found user interaction can affect the quality of the replication processes. This PTF adds a couple of new features which allow the automation of the data audits which take into account the apply process used by HA4i.

Role-swaps are one area HA4i is constantly improving, the role-swap process has been enhanced to allow the request to be run on the source system and it will automatically carry out the role-swap of the target system in line. This ensures the systems are managed as a pair so any problems found reflect in the switch stage of both systems. We have also added strategically placed exit points which allow user defined programs to be called as required as the role-swap progresses.

Our challenge has always been to keep the management of the systems simple, if we can automate a process which would normally require user interaction we do while still ensuring the processes run as effectively as possible. Notification of problems is always something we look at, in this PTF we have added a new process which auto-reloads via the IBM Job Scheduler that goes out and checks to make sure all of the HA4i processes are running correctly. If any processes are found to be in the wrong status or even not running, we will notify QSYSOPR via the message queue which processes are affected. These notifications can be sent via email to registered users requesting they rectify the issue.

We are constantly updating the products and provide access to any new changes as soon as possible via our remote support links. These changes are available prior to making it into a PTF which provides a very convenient method to fulfill customer needs. Customer requests are welcome and probably drive the majority of the changes we make so if you have any suggestions about missing features or requirements we are always glad to look at them.

If you are currently running a competitive product and would like to know if HA4i is an option to reduce cost or complexity let us know, we will be glad to give you a demo of the product and provide pricing.

Chris…

Sep 14

IBM PTF adds significant improvement to JQG data collection


We have been working with IBM to improve the data collection using one the the IBM API’s, the API seemed to be missing a lot of information at times and returned partial information at others. One of the tests we run for data collection is to have many jobs running all at once on a *NOMAX job queue, originally we were lucky to capture any of the data when the job first transitioned to the Job Queue and had to rely on capturing the data once the job became active. After some experimentation and code changes we did manage to get to the stage where we could capture the data once the job went into the active state except for a one or two instances. Capturing the data on the Job Queue simply did not work so we contacted IBM to ask if they could look at the API we use. They found a small problem where the job transitioned causing data to be incorrectly collected or totally missed so they set about working on a PTF to fix the issue.

A couple of days ago we received the test PTF, after installation we found the data collection has improved significantly where we now lose absolutely no data even when submitting 15 jobs all at once on the *NOMAX job queue. The jobs all finished within 1 second and yet the data collection worked perfectly.

IBM has yet to release the PTF into the wild but once it is we will release the information so the customers using JQG can benefit.

Chris…