Random thoughts of mine

Menu

Category Archives: tips & tricks

NuSOAP (link in archive.org) is a library that allows you to quickly and easily create SOAP-based webservices in PHP. The problem that you may encounter, however, is the fact that there is no obvious way to put some common code that you want to run in all (or almost all) of your SOAP functions. Think eg. about connecting to a database, or checking some username and password (token) or doing some logging. I’ll explain in this post how you may achieve that. I was using NuSOAP 0.9.5.

Let’s start with some slightly modified PHP code from NuSOAP intro page (archive.org). Obviously, it is all about server-side, so we’ll be dealing with nusoap_server class.

OK, so we have three SOAP functions: hello1, hello2 and hello3. Nothing special. However, what to do if you want to run some common code on the beginning of all these three functions? Sure, you can put it in some another function (let’s call it ini_code()) and then just to call it from each function, ie. put ini_code(); after opening parenthesis of each function. The problem with this approach is twofold, however:

you will have to remember to add this line in each new SOAP function that you implement

you can’t return from SOAP function without checking for errors returned from ini_code which will make common code even bigger

it is ugly, unelegant and just simply lame (OK, this is a third reason).

The solution is to extend nusoap_server class and override its invoke_method method. If you open the file required in our example above (ie. lib/nusoap.php) you will notice that invoke_method is the place where your implemented SOAP functions are actually called from (near end of the method, via call_user_func_array or some more perverse methods if you are using PHP version without this function). So let’s create the file “nusoap_server_wrapper.php” and put the following code in it:

<?php
// see https://bartlomiejb.wordpress.com/2014/03/11/common-code-in-nusoap-soap-functions/
/*
* We use this class to overwrite invoke_method() method
* in order to put some common code in all of our implemented SOAP functions.
*/
class nusoap_server_wrapper extends nusoap_server {
public function invoke_method() {
// our common code here
// you can use in it:
// - $this->methodname - name of the called function
// - $this->methodparams - parameters of the called function; it is an associative
// array with parameters' names as keys and actual values as array values
// - $this->methodreturn - use it as an lvalue (ie. write to it) and then
// just |return;| to return from implemented SOAP function with a given value
// as an example, let's write a called function name to a file
$fp = fopen('nusoap-ext-test.txt', 'a'); // in production check for errors etc.
fwrite($fp, 'called method is: ' . $this->methodname . "\n");
fclose($fp);
// invoke original NuSOAP code to handle our function
parent::invoke_method();
}
}

Read comments in this piece of code and all will be – hopefully – clear. You should now modify your server-side code to use this class instead of nusoap_server. So, assuming that “nusoap_server_wrapper.php” is in the same directory as our example from the top of the page, you would have to add require_once('nusoap_server_wrapper.php'); after require‘ing NuSOAP lib and then replace new nusoap_server with new nusoap_server_wrapper.

After running your client and calling all three SOAP functions you’ll notice not only that they work as usual, but that also their names are written to a file (obviously, you have to check write permissions etc. first) which proves that this code is indeed executed each time a SOAP function is called.

You should replace fopen/fwrite/fclose with your code, of course.

That’s it! We extended NuSOAP and run common code in an elegant and easily maintainable way.

Update (2014-12-09): added links to archive.org as it seems that NuSOAP page is gone.

If you’re using rpm-based Linux distro you may find this tip useful: if you want to list all packages installed or upgraded today (and by “today” I mean the current “today”, i.e. not hardcoded 2013/12/14, but the present time), just copy & paste the following snippet to the console window (this is ONE line!):
rpm -qa --qf '%{NAME} %{INSTALLTIME}\n' | perl -nale '($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst)=localtime($F[1]);($Nsec,$Nmin,$Nhour,$Nmday,$Nmon,$Nyear,$Nwday,$Nyday,$Nisdst)=localtime(time);print $F[0] if ($year==$Nyear && $mon==$Nmon && $mday==$Nmday)'

Here is how it works: we list all packages in a format “packagename installtime”. “installtime” is in a common Unix/Linux format: it is a number of seconds after a date called “epoch”. To convert it to something more readable/useful we can use perl and its function localtime, which converts it to an array of numbers of various meaning (like elements of the date: year, month, day, etc.). localtime(time) returns, on the other hand, the same data, but for the present time. So we just compare these two sets of values and if they match – we print the package name. Easy, isn’t it? 😉

I recently was struggling a little bit with running Skype in my distro. The problem was that I had to configure chroot environment (because my native OS is 64-bit and Skype is a 32-bit application), and then also solve some problems with PulseAudio to get sound.

OK, so here are my findings and some useful shell scripts. First, we have to make sure that all important pieces of native system are also available in chrooted environment. Hence chroot_mount.sh script:

Then you have to configure PulseAudio so it can be used from different user than logged in (I prefer to run closed-source apps, like Skype, from a separate account.) Here is my ~/.pulse/default.pa file on main account:

Why it is needed? Well, without first line (export PULSE_SERVER=127.0.0.1) there was no sound and paplay always was saying Connection refused. Read PulseAudio’s FAQ about details how do the PulseAudio libraries decide where to connect to.

The second line (PULSE_LATENCY_MSEC=60 skype) was/is important to work around the bug in Skype that was adding some “funny” effects, like no sound at all or only some noises. Read this post from PulseAudio developer to learn more. I experienced these problems with PulseAudio 4.0 and Skype 4.2.0.11. This line works like a charm and all works OK.

OK, now when everything is configured (remember also to install and configure dchroot) you can run 32-bit Skype on a separate account by only running this command on your main account:$ su -c 'dchroot -d skype-wrapper.sh' - user2
where “user2” is your secondary account.
You can make it an alias or put it in a one-line shell script to save some typing each time when you want to run Skype.

On Linux there is a standard related with desktop interactions and configuration. The standard describes, among other things, .desktop files. Important thing to remember when editing these files by hand (as I have done recently) is that when you want to pass multiple files as an argument to an app in “Exec” line, you have to give %F as an argument, like so: