15 April 2012

I received an email from David K. He took the Windows shortcut extraction code and applied it to his web-based directory browser to support multiple access methods by his users.

David K Describes His Use Case

Just wanted to thank you for your post on extracting the path from a windows .lnk. I used it in the following scenario:

Server: WebDAV server over SSL

Client: windows: mapped drive letter Z, uses a lot of .lnk shortcuts for various locations on the shared folders


  1. Clients accessing through a browser can’t use .lnk
  2. DAV doesn’t support symlinks through mapped drive (though it works through a browser)
  3. Windows mapped drive clients can’t create symlinks for browsers to use.

In apache httpd.conf, under appropriate virtualhost, include .conf file:

include /usr/local/apache2/conf/winlink.conf

see [below] .conf and .php for usage

hope you can use this or share it with someone who can at some point.

Apache Configuration (winlink.conf)

<IF "%{HTTP_USER_AGENT} =~ /(Avant|Mozilla|Opera|Itunes|Links|ELinks|Lynx|Konqueror|MSIE|Dillo|Uzbl|w3m|NetSurf|Polaris|BlackBerry|HTC|LG|MOT|Nokia|SAMSUNG|SEC|SonyEricsson|Vodafone)/">
  addhandler winlink .lnk
  Action winlink /cgi-bin/winlink.php?id=

Apache (PHP) Handler (winlink.php, slightly modified for readability/error-checks)

Using code found at http://witti.ws/blog/2011/02/21/extract-path-lnk-file-using-php:
The following script was derived from the above source and adapted for my personal use.
David Kelley 4/15/2012
// Ensure paths, url, and driveletter of shortcuts are correct or script will fail.
$basepath = "/storage/webdav/public";// no trailing slash
$baseurl = "http://example.com";// no trailing slash
$driveletter = "Q:";// the driveletter you are mapping the shared resource to, and making shortcuts with
$id = preg_replace('@\.+/@s', '', $_GET['id']);
$id = realpath($basepath . $id);
if (!$id || !is_file($id) || strpos($id, $basepath) !== 0) {
  die("Shortcut does not exist inside the configured path.");
$contents = file_get_contents($id);
$contents = preg_replace('@^.*\00([A-Z]:)(?:\\\\.*?\\\\\\\\.*?\00|[\00\\\\])(.*?)\00.*[email protected]', '$1\\\\$2', $contents);
$contents = str_replace("\\","/",$contents);
if (substr($contents, 0, strlen($driveletter)) !== $driveletter) {
  die("Invalid drive letter.");
$uri = $baseurl . substr($contents, strlen($driveletter));
header('Location: ' . $uri);
// assemble a header redirect from all supplied values.

My Notes on the Scripts

This is a quick script for handling .lnk files, and it does not pretend to do anything else. It does nothing internally for authentication or security, and the die() statements catch the most obvious hack attempts but do nothing to handle them gracefully. The realpath() check will avoid path-related hacks that try to access non-existent files, but nothing is done to confirm that the user is not being redirected into oblivion. The Apache configuration could also be easily translated into a RewriteRule, if a system already uses that module.

All that being said, for a protected intranet WebDAV system that needs a lightweight redirection system, this seems to do the trick. Presumably, such a DAV system is implementing its own layer of security (possibly Basic or Digest HTTP Authentication). Since there does seem to be a use case for it, I thought I'd go ahead and post it.


blog comments powered by Disqus