'----------------------------------------------------------------------- ' smburl3b.vbs (C) Walter Doekes 2007-2008, license: public domain '----------------------------------------------------------------------- ' ' Call with "register" argument to add the smb:// url handler. ' Call with "unregister" argument to undo "register". ' Call with any "smb://..." url to open the windows file:// url ' handler. ' ' Why? ' Because Firefox and Opera try to "download" file:// urls ' instead of "opening" them. With this, you can use smb:// urls instead. ' This script creates the smb://-protocol and handles it by passing ' fixed urls on to explorer which _can_ "open" the files. ' ' Obviously it would've been better if we could hijack the ' file://-protocol handler. Any suggestions how to do this will be ' highly appreciated. ' ' Where? ' Use it on any Windows that has WScript/VBS. ' ' See: http://wjd.nu/articles/2004/00/opening_smb_files_using_opera ' '----------------------------------------------------------------------- ' CHANGES '----------------------------------------------------------------------- ' 20070426 smburl3: ' Initial version ' ' 20080907 smburl3a: ' For a while now, browsers escape spaces (that were illegal in URLs ' in the first place) in URLs. If you're going to present a user with ' smb://-file links, you must make sure you urlencode all spaces and ' percent-signs. This version replaces all (non-reserved) encoded ' characters with their decoded equivalents. Any smb://-links that ' you provide must have at least space and percent-signs urlencoded! ' ' 20080922 smburl3b: ' Browsers nowadays assume that unicode in URLs must be in UTF-8. I ' added decoding of UTF-8 urlencoded entities. ' E.g. %C3%A5 becomes "a-ring". ' '----------------------------------------------------------------------- ' FUNCTIONS '----------------------------------------------------------------------- ' option explicit ' Returns a numeric value (0..15) or null for hex-char c (0..f) function chr0x(c) chr0x = null c = asc(ucase(c)) if c >= 48 and c <= 57 then chr0x = c - 48 if c >= 65 and c <= 70 then chr0x = c - 55 end function ' Reallows disallowed characters in URIs and normalizes encoded legal characters. function urlNormalize(url) dim rfc3986reserved, i, j, cnum, utf8len, tmp rfc3986reserved = "!*'();:@&=+$,/?#[]" ' "%" (percent) is removed from this list i = 1 do while i + 2 <= len(url) if mid(url, i, 1) = "%" then cnum = chr0x(mid(url, i + 1, 1)) * 16 + chr0x(mid(url, i + 2, 1)) if not isnull(cnum) then ' We have an urlencoded entity. The probability that it is UTF-8 ' encoded, is high. if (cnum and &h80) = 0 then utf8len = 0 elseif (cnum and &he0) = &hc0 then utf8len = 1 cnum = cnum and &h1f elseif (cnum and &hf0) = &he0 then utf8len = 2 cnum = cnum and &h0f elseif (cnum and &hf8) = &hf0 then utf8len = 3 cnum = cnum and &h07 end if for j = 3 to utf8len * 3 step 3 if i + j + 2 > len(url) then exit for ' too short tmp = null if mid(url, i + j, 1) = "%" then tmp = chr0x(mid(url, i + j + 1, 1)) * 16 + chr0x(mid(url, i + j + 2, 1)) if not isnull(tmp) then cnum = cnum * 64 ' << 6 cnum = cnum or (tmp and &h3f) end if end if if isnull(tmp) then exit for ' bad UTF-8 next cnum = chr(cnum) if instr(rfc3986reserved, cnum) = 0 then url = left(url, i - 1) & cnum & mid(url, i + j) end if end if end if i = i + 1 loop urlNormalize = url end function '----------------------------------------------------------------------- ' Main '----------------------------------------------------------------------- ' dim objWshell, objWnetwork on error resume next ' putting "argc == 1 and" here doesn't work because of vb-"and" if wscript.arguments(0) <> "register" and wscript.arguments(0) <> "unregister" _ and left(wscript.arguments(0), 7) <> "file://" _ and left(wscript.arguments(0), 6) <> "smb://" then wscript.echo _ "Usage: " & wscript.scriptName & " URL/COMMAND" & vbcrlf & _ " URL must be an ""smb://""-style url" & vbcrlf & _ " COMMAND must be ""register"" or ""unregister""" & vbcrlf & _ vbcrlf & _ "If you're unsure about how to install this, follow these simple steps:" & vbcrlf & _ " - copy this file to the ""C:\WINDOWS\"" directory" & vbcrlf & _ " - start -> run -> type """ & wscript.scriptName & " register"" [enter]" & vbcrlf & _ " (without the quotes)" wscript.quit 1 end if on error goto 0 set objWshell = wscript.createObject("wscript.shell") if wscript.arguments(0) = "register" then objWshell.regWrite "HKEY_LOCAL_MACHINE\SOFTWARE\Classes\smb\", "URL:SMB URI" objWshell.regWrite "HKEY_LOCAL_MACHINE\SOFTWARE\Classes\smb\URL Protocol", "", "REG_SZ" objWshell.regWrite "HKEY_LOCAL_MACHINE\SOFTWARE\Classes\smb\Shell\Open\Command\", _ """" & wscript.fullName & """ """ & wscript.scriptFullName & """ ""%l""" wscript.echo "Registered the smb:// protocol in the registry." elseif wscript.arguments(0) = "unregister" then on error resume next objWshell.regDelete "HKEY_LOCAL_MACHINE\SOFTWARE\Classes\smb\Shell\Open\Command\" objWshell.regDelete "HKEY_LOCAL_MACHINE\SOFTWARE\Classes\smb\Shell\Open\" objWshell.regDelete "HKEY_LOCAL_MACHINE\SOFTWARE\Classes\smb\Shell\" objWshell.regDelete "HKEY_LOCAL_MACHINE\SOFTWARE\Classes\smb\URL Protocol" objWshell.regDelete "HKEY_LOCAL_MACHINE\SOFTWARE\Classes\smb\" on error goto 0 wscript.echo "Removed the smb:// protocol from the registry." else dim strFile, strComputer, pos if left(wscript.arguments(0), 4) = "file" then strFile = mid(wscript.arguments(0), 6) else strFile = mid(wscript.arguments(0), 5) end if ' Replace urlencoded (ONLY illegal and non-reserved) chars. ' If the URLs you feed this contain spaces or percent signs, you MUST use percent-encoding. strFile = urlNormalize(strFile) ' Replace forward slash with backslash, for \\drive\share-notation strFile = replace(strFile, "/", "\") ' Escape double quotes strFile = replace(strFile, """", """""") ' If the computer asks for credentials, the ProtocolHandler will fail. ' Therefore we map the computer as a guest user first. pos = instr(3, strFile, "\") if pos = 0 then strComputer = strFile else strComputer = left(strFile, pos - 1) set objWnetwork = wscript.CreateObject("WScript.Network") ' Try to make a connection either way on error resume next objWnetwork.mapNetworkDrive "", strComputer, false, "guest" objWnetwork.mapNetworkDrive "", strComputer, false, "usernamethatdoesntexist" on error goto 0 ' Now we can open the share(d file).. hopefully objWshell.run "rundll32.exe url.dll,FileProtocolHandler """ & strFile & """" end if ' vim: set ts=8 sts=4 sw=4 et