Sametime photos served up by IHS

Between customer work I have been working on replacing our internal Sametime servers with shiny new 9.0.1 servers using AD instead of Domino LDAP.

The final piece of the puzzle is photos. Anyone who knows Sametime knows that something as simple as a photo is not made simple by the applications. The Sametime Proxy requires an LDAP attribute (PhotoURL) to be used which points STProxy to the image retrieving it for the client. Meetings doesn’t use the same approach, grr. It can use a binary object saved in LDAP or offload the retrieval to a web server like PhotoURL for STProxy but uses a “string” where all photos must be named Confusing? Yep.

I was about to roll over and say it’s not possible but it seems that it is possible to cover all use cases.

  1. Notes/Sametime clients using ImagePath URL
  2. STProxy web client using PhotoURL
  3. Meetings off loading to a web server
  4. Stop external access to photos

The nice thing STProxy does is that it will “proxy” the photos so the web browser doesn’t need direct connectivity to the jpgs. That is great because I can put the photos on an internal facing web server. The STProxy then calls the URL specified in the user’s LDAP entry (PhotoURL), caches it locally and then serves it up. Brilliant, I can lock the photos away so that no one can browse them from the internet if they know our email addresses.

You’ll need to update stproxyconfig.xml adding proxyServerURL otherwise it will not work. Don’t forget to sync and restart STProxy.


Ah, the Meeting server doesn’t follow the same logic. Clients (thick or web browser or mobile) need direct access to the photo to render it in the client. This means I’m back to square one….

Let’s jump back a step. How do we get the photos up to a web server?

Photos from Connections

At present our Sametime and Connections servers are using different LDAPs so SSO is not possible and even if it was retrieving photos from Connections via is not possible for guests because the photos require authentication so using the Connections business card for STProxy and Meetings is a show stopper.

Luckily in the Connections TDISOL there is an AL we can use called dump_photos_to_files. I won’t go into too much details about this but you can copy and paste the AL and then alter it. I altered it to return all user’s email addresses as well as UID and then dump the photos in the format of emailaddress.jpg which is the format needed by the Meeting server.

You may find the email addresses are capitalised. If so you will need to add some JavaScript to the lookup_user process to get it all in lower case


Once you have the photos in the correct format you need to get them from the server running TDI to a web server.

Web server

The logical way to serve the photos is using IHS in front of Connections. To get the files there I needed to scp them from the TDI server to IHS. I had to create ssh-keygens detailed in so I could scp the files wrapped in a shell script. Incidentally , the shell script called the AL and then scp’d the photos to the IHS server. Then add the shell script to cron so it is called on a schedule.

I wanted to lock down access to the photos so that people couldn’t browse to them. This is a little difficult to do but you can use IP ranges for all your internal offices and/or VPNs so that they are allowed to access the photos. The problem is guests who are truly external.

I created a new virtual host in httpd.conf with the following details.

# Sametime photos
<VirtualHost *:80>
DocumentRoot “/opt/IBM/HTTPServer/photos”
RewriteEngine On
RewriteCond %{HTTP_COOKIE} !LtpaToken2=.*$ [NC]
RewriteCond %{HTTP_COOKIE} !LtpaToken=.*$ [NC]
RewriteCond %{HTTP_COOKIE} !STPluginActivePage=stMeetingroom [NC]
# Old subnets and staff VPN
RewriteCond %{REMOTE_ADDR} !^xxx\.xx\.(x[x-x]|x[x-x])\.([x-x]|[x-x][x-x]|x([x-x][x-x])|x([x-x][x-x]|x[x-x]))$
# UK
RewriteCond %{REMOTE_ADDR} !^xxx\.xx\.(x[x-x]|x[x-x])\.([x-x]|[x-x][x-x]|x([x-x][x-x])|x([x-x][x-x]|x[x-x]))$
# India
RewriteCond %{REMOTE_ADDR} !^xxx\.xx\.(x[x-x]|x[x-x])\.([x-x]|[x-x][x-x]|x([x-x][x-x])|x([x-x][x-x]|x[x-x]))$
# Sametime Proxy
RewriteCond %{REMOTE_ADDR} !^xxx\.xx\.xx\.xxx$ [NC]
RewriteRule ^(.*)$ [R,L]

In a nutshell this allows all clients on certain IP range s to access photos. It also allows any web browser whether it is internal or on the internet to access photos IF it has either one of three cookies, LtpaToken/LtpaToken2 which is provided to the browser when someone authenticates or the cookie STPluginActivePage which the browser stores when you enter a meeting room. STPluginActivePage is in the browser whether you are a guest or an authenticated user, you just need to enter a meeting room.

I included both LtpaToken and LtpaToken2. I found the Sametime client was sending only LtpaToken with the HTTP GET for the photos. This may be due to the fact that I allow both LtpaToken and LtpaToken2 in the Domino web SSO configuration document. If you only allow LtpaToken2 then you may find that the client sends LtpaToken2 with the GET.

If you are a web browser outside of the IP ranges and you do not have any of the three cookies then you will be redirected to You could change this to a static html page of your choice.

I’m no whiz when it comes to Apache but I have tested this quite a bit and it seems pretty secure and should cover most bases. Of course it doesn’t stop a meeting guest from guessing email addresses and browsing other people’s photos but since you have invited them to a meeting, provided them with the meeting room password there is an element of familiarity that should stop them from being malicious in this way. If you back this up with changing the meeting room passwords often you should be in a strong position to keep these photos relatively secure.

If anyone has any thoughts on the httpd.conf I am all ears as I would like to tie it down further if it needs it.


I found that my original RewriteCond  for the IP addresses were not working. I was originally using the following method because it seemed nice and easy to just enter the CIDR but reading further the following approach only works with Apache 2.4 and IHS is using 2.2.8. You can find out by running apachectl -V.

RewriteCond expr “-R ‘xxx.xx.xx.0/xx'”

So regex was the only way to go and trying to work it out was going to be a headache. To my rescue came to convert the CIDR to all the IP addresses (well the first and last) and then I put these values into to give me the regex.

CCM file downloads via IHS randomly does not work

I wrote an entry previously about how to configure this and nuances around the syntax but this post is to put out there some very odd behaviour.

I have a working 5.5 environment migrated from 4.5 on Windows 2012 R2. Downloads via IHS work for files over 1MB. On restart of the CCM application server some times downloading via IHS does not work.

When the CCM application servers starts up it write out something like the following. This tells you everything is OK and you can expect CCM files of over 1MB to download OK.

[4/28/16 16:10:07:655 CEST] 00000147 LCDAUtil      I getLCDA CDHC enabled
[4/28/16 16:10:07:655 CEST] 00000147 LCDAUtil      I getLCDA CDHC cacheId = fncs-cdhc-*******-9445
[4/28/16 16:10:07:655 CEST] 00000147 LCDAUtil      I getLCDA CDHC cdhc_rootPath = D:/IBM/Connections/data/shared/ccmcache
[4/28/16 16:10:07:655 CEST] 00000147 LCDAUtil      I getLCDA CDHC cdhc_maxCachedFiles = 10000
[4/28/16 16:10:07:655 CEST] 00000147 LCDAUtil      I getLCDA CDHC cdhc_maxCacheSize_kb = 10485760
[4/28/16 16:10:07:655 CEST] 00000147 LCDAUtil      I getLCDA CDHC cdhc_maxCleanupTime_ms = 5000
[4/28/16 16:10:07:655 CEST] 00000147 LCDAUtil      I getLCDA CDHC cdhc_cleanupInterval_s = 3600
[4/28/16 16:10:07:655 CEST] 00000147 LCDAUtil      I getLCDA CDHC cdhc_minContentLifetime_s = 3600

On a couple of occasions the application server has been restarted and the above text has not been written to the SystemOut.log. I get the usual “open for e-business” but unless you look for the above lines you won’t know there’s a problem until you get on to the system and more importantly your users try to down load files.

If it doesn’t work you will see something like

[4/27/16 19:09:58:679 CEST] 0000019b LCDAUtil      E dumpErrorInfo CDHC enabled but configuration error found

You will see that for every time someone tries to down load a plus 1MB CCM file. The user will get a nasty error in the UI. Oddly, if you navigate to the VERSIONS tab of the file you can download it that way. That makes me believe that approach uses WAS to down load the file as opposed to IHS but only from the VERSIONS tab…. Odd.

The way I resolved it was as follows, mind I had to restart the application server twice.

  • Stopped the CCMCluster server
  • Renamed D:\IBM\Connections\data\shared\ccmcache\fncs-cdhc-******-9445
  • Deleted D:\IBM\WebSphere\AppServer\profiles\AppSrv01\temp\Node01\CCMCluster_server1
  • Started the server
  • I could not download a previus file and nor could I down load a plus 1MB file after uploading it
  • The directory in D:\IBM\Connections\data\shared\ccmcache\ was not created
  • Stopped the CCMCluster server
  • Deleted D:\IBM\WebSphere\AppServer\profiles\AppSrv01\temp\Node01\CCMCluster_server1
  • Started the server
  • Tried uploading various files and then downloading them and then I saw the text written to the systemOut.log and a file downloaded.
  • All other files worked

It baffled me since I didn’t make any configuration changes to get this working. This has happened twice now and I envisage it will happen again. I have opened a PMR to see whether IBM can shed any light on this.

IBM Connections CCM downloads via IHS syntax

It’s important to configure IHS to handle downloading of files. I have seen customer environments fail due to out or memory conditions when WAS handles the downloading of files which is not it’s primary role.

Configuring IHS downloads for CCM always stumps me so for once I will write it down in the form of this blog. A frustration is that IBM’s Connections Knowledge Center fails, with each version of Connections, to provide an easy to follow guide. It should only take about 30 minutes to do this but inevitably it takes longer due to poor documentation.

My current project is on Windows so the paths below will differ on *nix.

You need to update httpd.conf as follows.

Alias /library_content_cache “D:/IBM/Connections/data/shared/ccmcache”

<Directory “D:/IBM/Connections/data/shared/ccmcache”>
Order Deny,Allow
Deny from all

<Location /dm>
IBMLocalRedirect On
IBMLocalRedirectKeepHeaders X-LConn-Auth,Cache-Control,Content-Type,Content-Disposition,Last-Modified,ETag,Content-Language,Set-Cookie,Title,X-UA-Compatible

RequestHeader append LIBRARIES_CONTENT true

Now you need to update

The documentation says you need to update D:\IBM\Connections\FNCS\configure\explodedformat\fncs\WEB-INF\classes\ with the following


This is all good an well but these values will not make their way into the application unless you redeploy it which is a pain. Michael Urspringer provided a nice work around by adding the values to D:\IBM\WebSphere\AppServer\profiles\AppSrv01\installedApps\Cell01\navigator.ear\fncs.war\WEB-INF\classes\ which will, after a CCMCluster restart, apply the changes circumnavigating deploying the application.

You need to make sure that the above file and D:\IBM\Connections\FNCS\configure\explodedformat\fncs\WEB-INF\classes\ are the same in case you redeploy the application which will over write the same file in navigator.ear.

There was a bit of trial and error to get the correct syntax in The value for cdhc_rootPath did not like “” nor did it like backwards slashes as detailed in various IBM documents.