@@ -21,21 +21,21 @@ import (
21
21
"testing"
22
22
)
23
23
24
+ // createLockBody comes from the example in Section 9.10.7.
25
+ const createLockBody = `<?xml version="1.0" encoding="utf-8" ?>
26
+ <D:lockinfo xmlns:D='DAV:'>
27
+ <D:lockscope><D:exclusive/></D:lockscope>
28
+ <D:locktype><D:write/></D:locktype>
29
+ <D:owner>
30
+ <D:href>http://example.org/~ejw/contact.html</D:href>
31
+ </D:owner>
32
+ </D:lockinfo>
33
+ `
34
+
24
35
// TODO: add tests to check XML responses with the expected prefix path
25
36
func TestPrefix (t * testing.T ) {
26
37
const dst , blah = "Destination" , "blah blah blah"
27
38
28
- // createLockBody comes from the example in Section 9.10.7.
29
- const createLockBody = `<?xml version="1.0" encoding="utf-8" ?>
30
- <D:lockinfo xmlns:D='DAV:'>
31
- <D:lockscope><D:exclusive/></D:lockscope>
32
- <D:locktype><D:write/></D:locktype>
33
- <D:owner>
34
- <D:href>http://example.org/~ejw/contact.html</D:href>
35
- </D:owner>
36
- </D:lockinfo>
37
- `
38
-
39
39
do := func (method , urlStr string , body string , wantStatusCode int , headers ... string ) (http.Header , error ) {
40
40
var bodyReader io.Reader
41
41
if body != "" {
@@ -347,3 +347,92 @@ func TestFilenameEscape(t *testing.T) {
347
347
}
348
348
}
349
349
}
350
+
351
+ func TestLockrootEscape (t * testing.T ) {
352
+ lockrootRe := regexp .MustCompile (`<D:lockroot><D:href>([^<]*)</D:href></D:lockroot>` )
353
+ do := func (urlStr string ) (string , error ) {
354
+ bodyReader := strings .NewReader (createLockBody )
355
+ req , err := http .NewRequest ("LOCK" , urlStr , bodyReader )
356
+ if err != nil {
357
+ return "" , err
358
+ }
359
+ res , err := http .DefaultClient .Do (req )
360
+ if err != nil {
361
+ return "" , err
362
+ }
363
+ defer res .Body .Close ()
364
+
365
+ b , err := ioutil .ReadAll (res .Body )
366
+ if err != nil {
367
+ return "" , err
368
+ }
369
+ lockrootMatch := lockrootRe .FindStringSubmatch (string (b ))
370
+ if len (lockrootMatch ) != 2 {
371
+ return "" , errors .New ("D:lockroot not found" )
372
+ }
373
+
374
+ return lockrootMatch [1 ], nil
375
+ }
376
+
377
+ testCases := []struct {
378
+ name , wantLockroot string
379
+ }{{
380
+ name : `/foo%bar` ,
381
+ wantLockroot : `/foo%25bar` ,
382
+ }, {
383
+ name : `/こんにちわ世界` ,
384
+ wantLockroot : `/%E3%81%93%E3%82%93%E3%81%AB%E3%81%A1%E3%82%8F%E4%B8%96%E7%95%8C` ,
385
+ }, {
386
+ name : `/Program Files/` ,
387
+ wantLockroot : `/Program%20Files/` ,
388
+ }, {
389
+ name : `/go+lang` ,
390
+ wantLockroot : `/go+lang` ,
391
+ }, {
392
+ name : `/go&lang` ,
393
+ wantLockroot : `/go&lang` ,
394
+ }, {
395
+ name : `/go<lang` ,
396
+ wantLockroot : `/go%3Clang` ,
397
+ }}
398
+ ctx := context .Background ()
399
+ fs := NewMemFS ()
400
+ for _ , tc := range testCases {
401
+ if tc .name != "/" {
402
+ if strings .HasSuffix (tc .name , "/" ) {
403
+ if err := fs .Mkdir (ctx , tc .name , 0755 ); err != nil {
404
+ t .Fatalf ("name=%q: Mkdir: %v" , tc .name , err )
405
+ }
406
+ } else {
407
+ f , err := fs .OpenFile (ctx , tc .name , os .O_CREATE , 0644 )
408
+ if err != nil {
409
+ t .Fatalf ("name=%q: OpenFile: %v" , tc .name , err )
410
+ }
411
+ f .Close ()
412
+ }
413
+ }
414
+ }
415
+
416
+ srv := httptest .NewServer (& Handler {
417
+ FileSystem : fs ,
418
+ LockSystem : NewMemLS (),
419
+ })
420
+ defer srv .Close ()
421
+
422
+ u , err := url .Parse (srv .URL )
423
+ if err != nil {
424
+ t .Fatal (err )
425
+ }
426
+
427
+ for _ , tc := range testCases {
428
+ u .Path = tc .name
429
+ gotLockroot , err := do (u .String ())
430
+ if err != nil {
431
+ t .Errorf ("name=%q: LOCK: %v" , tc .name , err )
432
+ continue
433
+ }
434
+ if gotLockroot != tc .wantLockroot {
435
+ t .Errorf ("name=%q: got lockroot %q, want %q" , tc .name , gotLockroot , tc .wantLockroot )
436
+ }
437
+ }
438
+ }
0 commit comments