Hi IIS guys,
I found a UTF-8 problem in WebDAV module. Could you take a look and fix this issue? It must be very easy to fix.
Problem Summary
===============
IIS7: WebDAV module cannot handle UTF-8 in MOVE method
Repro Steps
===========
1. Install WebDAV module on IIS7
2. Create a folder named "xyz" under the root directory.
3. Send the following request with WFetch.
REQUEST: **************
MOVE /xyz HTTP/1.1
Host: localhost
Overwrite: F
Destination: http://localhost/%E3%83%86%E3%82%B9%E3%83%88
Translate: f
Accept: */*
Authorization: Basic xxxxx
You can see the following message from the IIS.
RESPONSE: **************
HTTP/1.1 201 Created
Server: Microsoft-IIS/7.0
X-Powered-By: ASP.NET
Date: Fri, 21 Nov 2008 08:03:07 GMT
Content-Length: 0
Expected Result
===============
A folder named "テスト" is created.
# "テスト" means 'test' in Japanese.
Actual Result
=============
A resultant folder name is invalid.
Debug Information
=================
WebDAV module must URL decode HTTP header line before MultiByteToWideChar.
I confirmed that a directory is created with a correct name if Distination
HTTP header line is URL decoded before MBTWC call.
I digged into this issue. The debug log is as follows.
Set two break points.
0:006> bl
0 e 77025cae 0001 (0001) 0:**** kernel32!MultiByteToWideChar
1 e 7702d198 0001 (0001) 0:**** kernel32!WideCharToMultiByte
0:006> g
Breakpoint 0 hit
eax=00000000 ebx=77025cae ecx=00000000 edx=00000000 esi=01ebf4f4 edi=01c3c7d0
eip=77025cae esp=01ebf3c0 ebp=01ebf3ec iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
kernel32!MultiByteToWideChar:
77025cae 8bff mov edi,edi
0:006> kbn
# ChildEBP RetAddr Args to Child
00 01ebf3bc 6e952d32 0000fde9 00000008 01ebf430 kernel32!MultiByteToWideChar
WARNING: Stack unwind information not available. Following frames may be wrong.
01 01ebf3ec 6e949a69 01ebf430 0000001c 00000000 webdav!RegisterModule+0x5e97
02 01ebf40c 6e94a2e1 01ebf430 00000000 01c26b78 webdav+0x9a69
03 01ebf494 6e947d40 01c25d68 01ebf4f4 00000000 webdav+0xa2e1
04 01ebf528 6e94bb7f 01152950 00000100 0115938c webdav+0x7d40
05 01ebf544 70db7035 0115bd18 01c25dc0 01c25d6c webdav+0xbb7f
...
13 01ebf978 77c0e4b6 01136eb8 7cd3a7d1 00000000 kernel32!BaseThreadInitThunk+0xe
0:006> dc 01ebf3bc
01ebf3bc 01ebf4f4 6e952d32 0000fde9 00000008 ....2-.n........
01ebf3cc 01ebf430 0000001c 01c3c7d0 000000b8 0...............
01ebf3dc 01ebf4f4 01c255f5 01c25d00 00000000 .....U...]......
...
0:006> da 01ebf430
01ebf430 "/%E3%83%86%E3%82%B9%E3%83%88"
I found that MultiByteToWideChar tried to convert the URL encoded string to Unicode directly. This is a problem.
The URL encoded string must be decoded before MultiByteToWideChar.
So I URL encoded the string directly like this,
0:006> eb 01ebf430 2f e3 83 86 e3 82 b9 e3 83 88 00
0:006> dc 01ebf430
01ebf430 8683e32f e3b982e3 45008883 32382533 /..........E3%82
01ebf440 25394225 38253345 38382533 01c26b00 %B9%E3%83%88.k..
and adjusted the fourth param of MBTWC so as to handle null-terminated string.
0:006> ed 01ebf3d0 ffffffff
Run IIS...
0:006> g 6e952d32
eax=00000005 ebx=77025cae ecx=6dfb7879 edx=0000000b esi=01ebf4f4 edi=01c3c7d0
eip=6e952d32 esp=01ebf3dc ebp=01ebf3ec iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
webdav!RegisterModule+0x5e97:
6e952d32 8945fc mov dword ptr [ebp-4],eax ss:0023:01ebf3e8=00000000
0:006> du 01c3c7d0
01c3c7d0 "/テスト"
I confirmed that a correct directory was created.
Appendix
========
1) Confirmed MKCOL method can handle UTF-8 correctly.
I confirmed that MKCOL method can create a directory with UTF-8 directory name.
REQUEST: **************
MKCOL /%E3%83%86%E3%82%B9%E3%83%88 HTTP/1.1
Host: localhost
Accept: */*
Authorization: Basic xxxxx
RESPONSE: **************
HTTP/1.1 201 Created
Server: Microsoft-IIS/7.0
X-Powered-By: ASP.NET
Date: Fri, 21 Nov 2008 07:57:59 GMT
Content-Length: 0
A directory named "テスト" was created. "テスト" means "test" in Japanese.
And the UTF-8 code is "E38386E382B9E38388"
2) Confirmed MOVE method cannot handle UTF-8 correctly.
REQUEST: **************
MOVE /xyz HTTP/1.1
Host: localhost
Overwrite: F
Destination: http://localhost/%E3%83%86%E3%82%B9%E3%83%88
Translate: f
Accept: */*
Authorization: Basic xxxxx
RESPONSE: **************
HTTP/1.1 201 Created
Server: Microsoft-IIS/7.0
X-Powered-By: ASP.NET
Date: Fri, 21 Nov 2008 08:03:07 GMT
Content-Length: 0
But the resultant directory name was unreadable.
Thank you,
Keisuke Oyama
E-mail: dadosan@keicode.com
URL: http://keicode.com/