Blog Archives

Extract all content to disk from a SPS2007 content DB using PHP

Today I ran into a problem. We needed to migrate a huge amount of data from an old SharePoint 2007 content database without the availability of the MOSS front-end. All i had was the database and a corrupted sharepoint install that wasnt going to help me allot.

To overcome this problem I decided to write a little PHP application that would do this task for me. I allready had WAMP setup on my desktop, so i figured this to be the quickest route. Then i figured, maybe other people face this problem as well. So here it is, the code, and some helpers to get you going.

* @name           : index.php - MSSql Content connector
* @Author        : Chris Gralike
* @version        :
* @copyright     : WETFYWTDWI - what ever ** you want to do with it, no guarantees 🙂
*  This script ONLY READS the database tables, so dont give it more permissions 🙂

// What to search for in the directory structure.
$search = '';
// Where too put the files
$createdir = './Downloaded';
// What server too connect to.
$ServerName = 'amisnt05.amis.local';
// Database connection parameters.
$connectionInfo = array('Database' => 'MOSS_PROD_WSS_Content_WebApp02',
'UID' => 'php_login',
'PWD' => 'welcome12345678');
// This can be a very long task to complete, so disable the timelimit.
// Create a connection
$conn = sqlsrv_connect($ServerName, $connectionInfo)
or die( print_r( sqlsrv_errors(), true));

// The SQL statment to query the AllDocs tables.
$tsql = "SELECT dbo.AllDocs.Id,
dbo.AllDocStreams.Id as StreamId,
FROM dbo.AllDocs
RIGHT OUTER JOIN dbo.AllDocStreams ON dbo.AllDocs.Id = dbo.AllDocStreams.Id
WHERE AllDocs.DirName LIKE '%{$search}%'
AND AllDocs.SetupPath IS NULL
AND AllDocs.Extension != ''
// The result set
$result = sqlsrv_query($conn, $tsql);

// Process the results
while($row = sqlsrv_fetch_array($result,  SQLSRV_FETCH_ASSOC)){
// When create is true, then it will create the folders in
// in the foreach
$create = false;
$dirptr = $createdir;

// Find the folders and recreate them starting from the searchstring.
$folders = explode('/', $row['DirName']);
foreach ($folders as $val){
if($val == $search || $create == true || empty($search)){
$create = true;
$dirptr .= '/'.$val;
echo "INFO: created $dirptr <br/>";
echo "WARN: skipping $dirptr allready exists. <br />";

// Recreate the file
$filepath = $dirptr.'/'.$row['LeafName'];
if($fp = fopen($filepath,'w')){
fwrite($fp, $row['Content']);
echo "INFO: file {$row['LeafName']} written. <br />";
echo "ERROR: file {$row['LeafName']} could not be written in $filepath. <br />";
// Close the database connection.

Simply configure the first vars in the script and run the file. It might take a huge while before you get some output.

TIP: Use the $search to narrow down the query a bit.
It searches the DirName (I.e. Site\DocLib\Folder\SubFolder\)

The output will look like this.

INFO: created ./Downloaded/SearchCenter
INFO: created ./Downloaded/SearchCenter/Pages
INFO: file facetedsearch.aspx written.
WARN: skipping ./Downloaded/SearchCenter allready exists.
WARN: skipping ./Downloaded/SearchCenter/Pages allready exists.
INFO: file resultskeyword.aspx written.

Then please leave a comment 🙂

WARNING!: YOU NEED THE Microsoft MSSQL DRIVER FOR PHP, not the old php equivalent.
here are some tips on where to get it. My version was php 5.3.8

First off, mssql isnt supported out of the box anymore. when using PHP 5.2 and up, you need to get the Microsoft for PHP driver. Check this site for more information :

Its a bit of an hassle ill give you that.
Challenge: I needed 1.5hours to find the correct Lib,Install,Coding info and get it working.

Basically it requires you to download the native client, the drivers and an correct update of the php.ini your wamp instance is using.

Tip: Use <?php phpinfo() ?> to find the right version for your PHP compilation.
Search for : PHP Extension Build : API20090626,TS,VC9


Be sure to verify the SQL query inside the $tsql=” var and alter it accordingly. The other part should be pretty straight forward.

peimg.exe missing? here is how to fix it :)


peimg is not being used anymore in the WAIK for windows 7. Instead you need to use the dism command. because the help is hidden pretty well, here is the Help you prob. are looking for 🙂

To get all the available options on the “offline” wim image provided by dism you need to run the following.

# Mount the image as usual (use the WAIK command line from the start menu

imagex /mountrw C:\path\to\image.wim {1/2}* C:\path\to\mount-dir\

*There can be multiple images in a wim image, for boot.wim these are 1 = Microsoft Windows PE, 2= Microsoft Windows Setup. The 1 or 2 in the given command selects the required image.

#To get all the dism options type the following;
dism /image:C:\path\to\mount-dir /?

Keep in mind that sub options have new help menus. For example, adding additional drivers has new help instructions that are accasible by calling;

dism /image:c:\path\to\mounted\image /add-driver /?

All the base options provided by dism

Image Version: 6.1.7600.16385

The following commands may be used to service the image:

/Apply-Unattend - Applies an unattend file to an image.

/Remove-Driver - Removes driver packages from an offline image.
/Add-Driver - Adds driver packages to an offline image.
/Get-DriverInfo - Displays information about a specific driver
in an offline image or a running operating system.
/Get-Drivers - Displays information about all drivers in
an offline image or a running operating system.

/Apply-Profiles - Applies profiles to the Windows PE image.
/Disable-Profiling - Disables profiling.
/Enable-Profiling - Enables profiling.
/Get-PESettings - Displays Windows PE image information.
/Get-Profiling - Gets the enabled/disabled state of the Windows PE
/Get-ScratchSpace - Gets the configured amount of Windows PE system
volume scratch space.
/Get-TargetPath - Gets the target path of the Windows PE image.
/Set-ScratchSpace - Sets the scratch space of the Windows PE image.
/Set-TargetPath - Sets the target path of the Windows PE image.

/Set-LayeredDriver - Sets keyboard layered driver.
/Set-UILang - Sets the default system UI language that is used
in the mounted offline image.
/Set-UILangFallback - Sets the fallback default language for the system
UI in the mounted offline image.
/Set-UserLocale - Sets the user locale in the mounted offline image.
/Set-SysLocale - Sets the language for non-Unicode programs (also
called system locale) and font settings in the
mounted offline image.
/Set-InputLocale - Sets the input locales and keyboard layouts to
use in the mounted offline image.
/Set-TimeZone - Sets the default time zone in the mounted offline
/Set-AllIntl - Sets all international settings in the mounted
offline image.
/Set-SKUIntlDefaults - Sets all international settings to the default
values for the specified SKU language in the
mounted offline image.
/Gen-LangIni - Generates a new lang.ini file.
/Set-SetupUILang - Defines the default language that will be used
by setup.
/Get-Intl - Displays information about the international
settings and languages.

/Add-Package - Adds packages to the image.
/Remove-Package - Removes packages from the image.
/Enable-Feature - Enables a specific feature in the image.
/Disable-Feature - Disables a specific feature in the image.
/Get-Packages - Displays information about all packages in
the image.
/Get-PackageInfo - Displays information about a specific package.
/Get-Features - Displays information about all features in
a package.
/Get-FeatureInfo - Displays information about a specific feature.
/Cleanup-Image - Performs cleanup and recovery operations on the

For more information about these servicing commands and their arguments,
specify a command immediately before /?.

DISM.exe /Image:C:\test\offline /Apply-Unattend /?
DISM.exe /Image:C:\test\offline /Get-Features /?
DISM.exe /Online /Get-Drivers /?

RHEL5 init script for tomcat catalina

I have written an init script for Tomcat Catalina running in RHEL version 5. I have tested this script using Oracle Enterprise Linux 5.5 Carthage. The script should comply to the init standards defined for RedHat Enterprise Linux using the INIT Functions lib.

The script also alows the use of chkconfig eventhough you might want to alter the used priorities (56 10)

# "$Id: catalina ,v 1.0 2010/08/10 Chris_g Exp $"
#   Startup/shutdown script for tomcat(Catalina) Application server.
#   Linux chkconfig stuff:
#   chkconfig: 2345 56 10
#   description: Startup/shutdown script for the tomcat application server.

# Source function library.
. /etc/init.d/functions

# Define where the script is located.
CATALINA_BIN='/u01/tomcat/bin/ 1> /dev/null';

# Find the catalina process using ps / awk.
# The match function will return 0 when no match is found with the string "java".
# Position $9 should contain the path to the Java executable used by catalina.
PROC=`ps -efc | grep apache.catalina | awk 'BEGIN { FS=" "}; { if( match($9, "java") != 0 ) print $9;}'`

# Replace a potential empty string with a fake process so the RH daemon functions are able to parse
# it properly
if [[ "$PROC" == '' ]]; then

# Define the application name that is listed in the daemonize step.
PROG='Tomcat JVM';


start () {
        echo -n $"Starting $PROG: "

        # start daemon
        daemon $CATALINA_BIN start
        [ $RETVAL = 0 ] && touch $LOCK
        return $RETVAL

stop () {
        # stop daemon
        echo -n $"Stopping $PROG: "
        killproc $PROC
        [ $RETVAL = 0 ] && rm -f $LOCK

restart() {

case $1 in
                status $PROC

        echo $"Usage: $prog {start|stop|restart|status}"
        exit 3

exit $RETVAL

1. Touch a new tomcat file in your init directory.
>touch /etc/init.d/tomcat
2. Copy paste the code above into this file using vi
vi /etc/init.d/tomcat
(putty users)
press the insert button (this should put vi in insert mode)
Alter the tomcat path and copy the altered code to your clipboard and paste it into putty using a richt mouse click.
press esc (this should get you out of insert mode)
next press ” shift + : “, “w”, “enter” (this should save the file)
3. If was able to start tomcat (all vars/java configured) then now the tomcat script should be able to handle the startup.
4. If catalina was allready running, try;

     service tomcat status
     This should allready give a result equal to;
     java (pid 14389) is running…

5. Add tomcat to the chkconfig for automatic startup
     chkconfig –level 2345 tomcat on

Hope this helps 😉

Migrating a running OVS to a new OVM (howto)

What is this article about?

When reading the Oracle Documentation you might discover that the method of ‘migrating’ a running OVS-server into a new POOL is not very well documented. In this article I will explain in steps that allow you to add a running OVS-Server into a new POOL on a new OVS-Manager.

Setup used to write this article.

  1. two ovs-managers (ovs-manager1 / ovs-manager2).
    Both version 2.2.0
  2. one ovs-server (ovs-server1) that has two running domain ontop of it.
    version 2.2.1


In my setup I didnt create a OCFS cluster (shared storage) from which the domains are ran. Even though the domains use fysical paths to the actual domain components, even though the cluster file service service will not allow the cluster to be broken (service stopped) with running domains I cannot assume this article is applicable… You are adviced to ‘TEST’ a migration in a LAB situation first! This article might help you get an idea of the required steps.

This article will describe the steps taken to migrate the “ovs-server1” which was managed on “ovs-manager1” to the new manager “ovs-manager2”. Any reason to do this might be iron-replacement without a decent backup of the ovs-manager, ovs-manager1 was fysically destroyed and needs to be restored, etc…


  1. Make sure you have a backup of the ovs-managers database (see ovs-manager documentation no how a backup is created)
  2. Logon to ‘ovs-manager1’ in which the ovs-server is member of an existing pool.
  3. Select the ‘Server Pools’ tab.
  4. “!Make sure you have all the CIs if this server documented!”
  5. Select the pool in which the ‘ovs-server1’  is listed and select “Delete”
  6. In the delete form “ONLY SELECT FORCE REMOVE”. DO NOT SELECT  any other option!
  7. When the pool is succesfully deleted logon to the ovs-server1 using a ssh-client.
  8. verify that all the domains are still in the state we left them using the following command;
    xm list
  9. Document the root repository used by the ovs-agent. You need to document it because the repositories are part of the ovs-agents local database thats being cleaned in the next step. You can find the current repository by running the following command;
    /opt/ovs-agent-2.3/utils/ -l

    It should return a string simular to this one;
    [ * ] e3514a86-a763-4eee-84b5-0fedcc03416d => /dev/sdb1

    We need this string to verify the repository when we recreate it.

  10. The next step is to clean the ovs-agents local database in which the ovs-manager is registered. This entry prevents us from linking any other ovs-manager to this agent. The ovs-agent, version 2.3 contains a cleanup script located in /opt/ovs-agent-2.3/utils/ that is needed to perform this cleanup. If the cleanup script is not there, you are probably using ovs-server version 2.2.0. You can check the ovs-server release by issuing the following command;
    cat /etc/*-release

    Oracle VM server release 2.2.1

    In the situation you indeed using version 2.2.0, you might simply copy the script from a ovs-server version 2.2.1 and put it in the path mentioned above. (yeah, same ovs-agent versions but still minor differences 😉 ).

  11. If the is in place, run it;
    Confirm the question
  12. The result of this action is that the agents local database has been cleaned. As a result of this you might notice that the /OVS mapping is gone as well. Not to worry, using the xm list command you are able to verify that the various domains are still up and running. This is because they are being configured to use the fysical path to its template directory somewhere in the /var/ovs/mount/ which is still mounted.
  13. Before you add the ovs-server to the new manager we need to restore the agents entry for the root repository. For this we need the information documented in step 9. Use the information, specific the devices listed in step 9 to restore that config. Initially you need to add the various repositories, afterward (step 14) we need to assign the ‘root’ label to one of them, in our case the one created here.
    /opt/ovs-agent-2.3/utils/ -n /dev/sdb1
  14. As a result the previous command returned a rule that also contains the UUID for this repository. verify that the UUID is the same as the one listed in step 9. The recreated UUID should be the same!
  15. Assign the ‘root’ label to this repository (that might be a different one if you used multiple repositories)
    /opt/ovs-agent-2.3/utils/ -r e3514a86-a763-4eee-84b5-0fedcc03416d
  16. When you have are finished restoring the repo config you can start adding the server to a new POOL on ovs-manager2.
  17. Logon to ovs-manager2 (the new ovs-manager)
  18. Select the “Servers Pools” tab.
  19. Select “Create pool”.
  20. Fill out all the required fields and use the cleaned ovs-server1 machine as to be added server.
  21. Finish all the required steps so a new pool is created.
  22. You might notice you have a new pool with the ovs-server1 in it, but with no virtual machines. This is because we need to “discover / reimport” these from the ovs-server. This is done as followed.
  23. Select “Resources”
  24. Select “Virtual machine Images”
  25. Select “Import”
  26. Select “Select from server pool (discover and register)”
  27. Select the Server POOL you have just created.
  28. Select the “running?” Virtual machine image name in the pulldown and fill out all the fields required (It might be wise to match these with the initial configuration of the VM Image you are trying to register)
  29. Finish all the steps and repeat step 25 > 29 for each VM image you like to import.

This should be all you need to do to restore the machine and all of its (running?) images into the new OVS-manager.

If all is well, after creating the new POOL in step 19 / 21 the /OVS share should be remounted by the ovs-agent / ovs-manager. You might want to verify this on the ovs-server box.

Hope this helps 🙂
Rgrds, chris

Recovering from Mcafee DAT 5958 update.

Yesterday Mcafee released a new DAT update that caused mcafee to identify svchost.exe as an infected file. Mcafee next attempts to quarantine this file which results in windows rebooting with a shutdown message some of us will remember from the Sass worm chaos.

Result of this is that the machine can be used anymore. svchost.exe is a name for general hostprocesses ran from DLLs, and pretty important for windows. If you would like to get an idea of the impact on you system this article might be all you need 🙂

Now how to recover?
1st i would advice to follow any manual mcafee brings out describing how to recover using the mcafee scanner console. In the cases where the quarantine is deleted (some of our machines) follow the instructions below…

If you are unable to restore svchost.exe from the quarantine you might follow these steps to recover your system.

0. Get the corrected Superdat from Mcafee and put it on a USB, CD or other available media, No network locations.
1. Boot from the windows CD and select the recovery console.
2. Select the correct windows partition and logon as the local administrator.
3. Browse to C:\windows\system32 using the command : cd \windows\system32\
4. open de CD-rom player using the allocated drive letter, usually D:\ by typing D:
5. Browse to the i386 directory located on the CD using : cd \i386\
6. copy the original svchost.ex_ to your windows drive using the command:
expand svchost.ex_ C: (C: is the drive you where on in step 3, this might differ,
in which case you need to change the drive letter to your system specific drive)
7. Boot the system in savemode. The selection can be done by pressing F8 repeatedly during boot.
8. While in savemode run and execute the superdat you accuired in step 0.
9. After the update reboot your system normally.

This is a pretty long road, but will fix the problem in all cases.

Thanks to Benjamin van Ditmars for suggesting the Expand option. We used a “good” copy of svchost before this suggestion. The expand option is “saver” 🙂

Phase one, Check IOStat for Nagios.

Full Working version can be found here



Thanks, Rgrds,

Simple php function to filter out unwanted text char types.

Just wrote a little function that will remove all char types from a string or text (if thats in the string) that are not given in the chars list. In my example I only wanted alpha chars and spaces. It also converts all to lower caps.

It walks through the given string using a substr function to locate the char to be evaluated. If the char is found in the given allowed string using a strstr function it will add it to the return string, else it will simply discard it. Before evaluation it also converts the val to a lowercap.


function cleanstr($s, $c, $l=true){
                $v=substr($s, $i, 1);
                if(strstr($c, $v)){ $r .=$v;}
        return $r;

$string='abcdef $%%# Chris';
$chars=' abcdefhijklmnopqrstuvwxyz';
echo cleanstr($string, $chars);

Prints out…

php ./test.php
abcdef  chris

Howto Linux X-Server on windows.

Whats this?
Oke here a small but hopefully “strong” little tutorial on how to “display” linux X compontents on your windows desktop. This might help you administer linux machines easier without the need to install a VNC deamon or have X enabled or even installed on the remote Linux box.

Read the rest of this entry

Personal Memo – Make delete and others function in a terminal.

Set the terminal delete backspace and such using the stty command. On some linux distros these are not defined by default and might be needed to work inside the terminal. Behind the -More- the so called stty commands for erase, kill and other terminal functions…

Read the rest of this entry

Altering the Nagios daemon startup script to include NDO.

previously I wrote an article on how to create a deamon script for ndo. But when you are using Centreon the only “nice” way to do this is by altering the Nagios startupscript to include the ndo part.

Here is what i have done to make this possible.

First i wrote a function to find the PIDs for the ndo deamon process based on a specific config. In this one the config is hardcoded,
but you might also replace the $NagiosNdoConfig with $1 instead and call the function like;

getNdoPid “/usr/local/nagios/etc/yourconfig.cfg”

getNdoPid ()
 #Declare a var containing the correct ndo PID, there are processes being forked from ndo so we need to
 #do some awk filtering also to fetch the correct one.
 #Not that the parent process always has a parent pid "1" so we use that to filter the parent from the childs.
 ndoPID=`ps -ef | grep $NagiosNdoConf | grep "?" | awk -F ' '  '{if($3 == '1') print $2}'`
        #next we validate if we got an pid returned to us, and fill a wrapper that we will use like $? that ill convieniently call "ls" LastState.
        if [[ "$ndoPID" == '' ]]; then

Next using the getNdoPid function u wrote another two functions to start and to stop the ndo daemon. I choose this method so i can include these function inside the existing start stop scripting used by nagios. In effect when you start nagios, th start case select is used which will call our ndo start script.

The ndo kill function

kill_ndo ()
        #Find the actual PID
        if [[ "$ndoPID" == '' ]]; then
             #No process running to kill...
             kill $ndoPID;
             sleep 2 #parent needs some time to kill the child processes if any
             if [[ "$ls" == '1' ]]; then

and the start portion…
The ndo start function

start_ndo ()
        #always make sure ndo isnt running!
        $NagiosNdo -c $NagiosNdoConf;
        if [[ "$?" == '0' ]]; then

Again i am using the ls (laststate) var to save the last state of the executed command. This is important because the state of a command can only be tested right after execution of that command. by using the ls var i make sure i am always testing the correct result. this is because the $? is also overwritten when performing an var assignment, if test etc.

Next I added a few vars for configuration, stuff like where the ndo2db bin is located, and the config file.


naturally the NDO bin could also be found like;
NagiosNdo=`which ndo2db`;
Bu this will require the ndo2db bin to be somewhere in the path var. We are not sure this is always the case because there is no consensus on where these nagios bins should be placed. This may vary from distro to distro and from user to user. In my case, it being placed inside /user/bin this whould also work.

I also extended the functionality of the startupscript by adding new options to start, stop and restart the ndo deamon by using the nagios startupscript. This is what i did.

inside the “case” statement where the “/etc/init.d/nagios args” are tested i added some new options namely “startndo, stopndo, restartndo” and this is what it looks like.

For the option “/etc/init.d/nagios startndo”

                if [[ "$ls" == '1' ]]; then
                    if [[ "$ls" == '0' ]]; then
                        echo 'NDO deamon started succesfully';
                        exit 0;
                        echo 'Failed to start NDO, check your logging for more info';
                        exit 1;
                    echo "Ndo deamon allready running with PID : $ndoPID";
                    exit 1;

for the “/etc/init.d/nagios stopndo” option

                if [[ "$ls" == '1' ]]; then
                     echo "$ls";
                     exit 1;
                     sleep 2 #it needs some time to kill the childs (that get ppid 1 when the parent quits)
                     if [[ "$ls" == '1' ]]; then
                         echo "Ndo stopped succesfully";
                         exit 0;
                         echo "Unable to kill ndo, please review you logging";
                         exit 1;

And a restart option “/etc/init.d/nagios restartndo”

                $0 stopndo
                $0 startndo

To include the start and stop options in the nagios start and stop process all you need to do is add the start and or stop options in there.
Here is an example

                echo -n "Starting nagios:"
                $NagiosBin -v $NagiosCfgFile > /dev/null 2>&1;
                if [ $? -eq 0 ]; then
                        su - $NagiosUser -c "touch $NagiosVarDir/nagios.log $NagiosRetentionFile"
                        rm -f $NagiosCommandFile
                        touch $NagiosRunFile
                        chown $NagiosUser:$NagiosGroup $NagiosRunFile
                        $NagiosBin -d $NagiosCfgFile
                        if [ -d $NagiosLockDir ]; then touch $NagiosLockDir/$NagiosLockFile; fi
                        #chmod 777 $NagiosCommandFile
                        echo " done."
                        exit 0
                        echo "CONFIG ERROR!  Start aborted.  Check your Nagios configuration."
                        exit 1
#Stop portion
                echo -n "Stopping nagios: "

                killproc_nagios nagios
                # now we have to wait for nagios to exit and remove its
                # own NagiosRunFile, otherwise a following "start" could
                # happen, and then the exiting nagios will remove the
                # new NagiosRunFile, allowing multiple nagios daemons
                # to (sooner or later) run - John Sellens
                #echo -n 'Waiting for nagios to exit .'
                for i in 1 2 3 4 5 6 7 8 9 10 ; do
                    if status_nagios > /dev/null; then
                        echo -n '.'
                        sleep 1
                if status_nagios > /dev/null; then
                    echo ''
                    echo 'Warning - nagios did not exit in a timely manner'
                    echo 'done.'

                rm -f $NagiosStatusFile $NagiosRunFile $NagiosLockDir/$NagiosLockFile $NagiosCommandFile

                printstatus_nagios nagios

Now when i start and stop nagios using the centreon “start / stop / reload” options my ndo daemon is also started / stopped. Ps. This manual uses Nagios 3.0 and Centreon 2.2

This is what a restart looks like 😉

[root@UX127 var]# service nagios restartndo
Ndo stopped succesfully
NDO deamon started succesfully