Common code in NuSOAP SOAP functions

NuSOAP (link in 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 ( Obviously, it is all about server-side, so we’ll be dealing with nusoap_server class.


// Pull in the NuSOAP code
// Create the server instance
$server = new nusoap_server;
// Register the method to expose
// Define the methods as a PHP functions
function hello1() {
    return 'Hello1';
function hello2() {
    return 'Hello2';
function hello3() {
    return 'Hello3';
// Use the request to (try to) invoke the service

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:

// see

 * 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");

        // invoke original NuSOAP code to handle our function

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 as it seems that NuSOAP page is gone.


rpm: How to list packages installed/upgraded today

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? 😉

Chroot 32-bit + Skype + PulseAudio = problems (solved!)

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 script:

#!/bin/sh -x

cp -L /etc/resolv.conf $CHROOTPATH/etc/
mount --bind /dev $CHROOTPATH/dev
mount --bind /dev/pts $CHROOTPATH/dev/pts
mount --bind /dev/shm $CHROOTPATH/dev/shm
mount --bind /tmp $CHROOTPATH/tmp
mount -t proc proc $CHROOTPATH/proc
mount -t sysfs none $CHROOTPATH/sys
mount --bind /var/lib/dbus $CHROOTPATH/var/lib/dbus
mount --bind /var/run/dbus $CHROOTPATH/var/run/dbus
mount --bind /run/udev $CHROOTPATH/run/udev
mount --bind /home $CHROOTPATH/home

Run it from root. (Obviously, you have to create /mychroot dir earlier and install there base system. This part is out of scope of this blog post.)

After using your chrooted environment you may also want to umount all resources. Hence script:

#!/bin/sh -x

umount $CHROOTPATH/dev/pts
umount $CHROOTPATH/dev/shm
umount $CHROOTPATH/dev
umount $CHROOTPATH/tmp
umount $CHROOTPATH/proc
umount $CHROOTPATH/sys
umount $CHROOTPATH/home
umount $CHROOTPATH/var/lib/dbus
umount $CHROOTPATH/var/run/dbus
umount $CHROOTPATH/run/udev

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/ file on main account:

load-module module-device-restore
load-module module-stream-restore
load-module module-card-restore
load-module module-augment-properties
load-module module-udev-detect
load-module module-detect
load-module module-jackdbus-detect
load-module module-bluetooth-discover
load-module module-esound-protocol-unix
load-module module-native-protocol-unix
load-module module-gconf
load-module module-default-device-restore
load-module module-rescue-streams
load-module module-always-sink
load-module module-intended-roles
load-module module-suspend-on-idle
load-module module-console-kit
load-module module-systemd-login
load-module module-position-event-sounds
load-module module-role-cork
load-module module-filter-heuristics
load-module module-filter-apply
load-module module-dbus-protocol
load-module module-switch-on-port-available
load-module module-native-protocol-tcp auth-ip-acl=

On the secondary account I have only this in ~/.pulse/client.conf file:

default-server =

Also I have there in the PATH:

#!/bin/sh -x

Why it is needed? Well, without first line (export PULSE_SERVER= 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 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' - 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.

“Open with…” with multiple files

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:

Exec=coolapp %F

See The Exec key on

Jak usunąć ogonki z polskich znaków używając perla

Edycja (2013-08-11): dodałem info o Windows.

Edycja (2013-09-28): dodałem info o konwersji pliku w UTF8 na Windows.

Zakładam, że używamy Linuksa na terminalu obsługującym UTF8. Testowane na perlu 5.18.0.

Nasz plik (polskie znaki w UTF8):

$ cat tmp.txt
ęóąśłźżćń ĘÓĄŚŁŹŻĆŃ
ĘÓĄŚŁŹŻĆŃ ęóąśłźżćń
W Strzebrzeszynie chrząszcz brzmi w trzcinie i Strzebrzeszyn z tego słynie.
Zażółć gęślą jaźń.

Jednolinijkowiec w perlu:

$ cat tmp.txt | perl -Mutf8 -MEncode -wple '$_=decode("utf8",$_);tr/ęóąśłźżćńĘÓĄŚŁŹŻĆŃ/eoaslzzcnEOASLZZCN/'
eoaslzzcn EOASLZZCN
EOASLZZCN eoaslzzcn
W Strzebrzeszynie chrzaszcz brzmi w trzcinie i Strzebrzeszyn z tego slynie.
Zazolc gesla jazn.

W Windows (XP PL; Activestate Perl 5.8.9) wystarczy (plik tmp.txt kodowany w lokalnym standardzie CP1250):

type tmp.txt | perl -wple "tr/ęóąśłźżćńĘÓĄŚŁŹŻĆŃ/eoaslzzcnEOASLZZCN/"

Okazuje się, że polskie znaki w wierszu poleceń Windows są w którymś miejscu niejawnie konwertowane do CP1250 (mimo że normalnie na konsoli obowiązuje CP852).

Konwersja pliku zapisanego w UTF8 (Notatnik umożliwia zapis w tym kodowaniu; dodaje wtedy też BOM na początku, więc trzeba go usunąć) wymaga nieco więcej zachodu…:

type tmp.txt | perl -MEncode=decode -wple "BEGIN { $pl='ęóąśłżźćńĘÓĄŚŁŻŹĆŃ';$pl=decode('CP1250', $pl); $bom = join'',map(chr,(0xef,0xbb,0xbf))} s/^$bom//; $_=decode('UTF8', $_); eval 'tr/' . $pl . '/eoaslzzcnEOASLZZCN/'"

eval pod koniec jest niezbędne, bo operator “tr” nie obsługuje normalnie zmiennych w listach do zamiany.
Testowane z ActiveState perlem 5.10.1 na Windows 7 Starter PL SP1 oraz ActiveState perlem 5.12.4 na Windows XP PL SP3.