2019-08-15 07:07:28 -05:00
|
|
|
// Copyright 2019 The Gitea Authors. All rights reserved.
|
2022-11-27 13:20:29 -05:00
|
|
|
// SPDX-License-Identifier: MIT
|
2019-08-15 07:07:28 -05:00
|
|
|
|
|
|
|
package charset
|
|
|
|
|
|
|
|
import (
|
2022-05-21 08:06:24 -05:00
|
|
|
"bytes"
|
|
|
|
"io"
|
2020-08-23 08:15:29 -05:00
|
|
|
"strings"
|
2019-08-15 07:07:28 -05:00
|
|
|
"testing"
|
|
|
|
|
|
|
|
"code.gitea.io/gitea/modules/setting"
|
|
|
|
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
|
|
)
|
|
|
|
|
2020-08-23 08:15:29 -05:00
|
|
|
func resetDefaultCharsetsOrder() {
|
|
|
|
defaultDetectedCharsetsOrder := make([]string, 0, len(setting.Repository.DetectedCharsetsOrder))
|
|
|
|
for _, charset := range setting.Repository.DetectedCharsetsOrder {
|
|
|
|
defaultDetectedCharsetsOrder = append(defaultDetectedCharsetsOrder, strings.ToLower(strings.TrimSpace(charset)))
|
|
|
|
}
|
|
|
|
setting.Repository.DetectedCharsetScore = map[string]int{}
|
|
|
|
i := 0
|
|
|
|
for _, charset := range defaultDetectedCharsetsOrder {
|
|
|
|
canonicalCharset := strings.ToLower(strings.TrimSpace(charset))
|
|
|
|
if _, has := setting.Repository.DetectedCharsetScore[canonicalCharset]; !has {
|
|
|
|
setting.Repository.DetectedCharsetScore[canonicalCharset] = i
|
|
|
|
i++
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-08-15 07:07:28 -05:00
|
|
|
func TestRemoveBOMIfPresent(t *testing.T) {
|
|
|
|
res := RemoveBOMIfPresent([]byte{0xc3, 0xa1, 0xc3, 0xa9, 0xc3, 0xad, 0xc3, 0xb3, 0xc3, 0xba})
|
|
|
|
assert.Equal(t, []byte{0xc3, 0xa1, 0xc3, 0xa9, 0xc3, 0xad, 0xc3, 0xb3, 0xc3, 0xba}, res)
|
|
|
|
|
|
|
|
res = RemoveBOMIfPresent([]byte{0xef, 0xbb, 0xbf, 0xc3, 0xa1, 0xc3, 0xa9, 0xc3, 0xad, 0xc3, 0xb3, 0xc3, 0xba})
|
|
|
|
assert.Equal(t, []byte{0xc3, 0xa1, 0xc3, 0xa9, 0xc3, 0xad, 0xc3, 0xb3, 0xc3, 0xba}, res)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestToUTF8WithErr(t *testing.T) {
|
2020-08-23 08:15:29 -05:00
|
|
|
resetDefaultCharsetsOrder()
|
2019-08-15 07:07:28 -05:00
|
|
|
var res string
|
|
|
|
var err error
|
|
|
|
|
2019-09-21 12:01:34 -05:00
|
|
|
// Note: golang compiler seems so behave differently depending on the current
|
|
|
|
// locale, so some conversions might behave differently. For that reason, we don't
|
|
|
|
// depend on particular conversions but in expected behaviors.
|
|
|
|
|
2019-08-15 07:07:28 -05:00
|
|
|
res, err = ToUTF8WithErr([]byte{0x41, 0x42, 0x43})
|
|
|
|
assert.NoError(t, err)
|
2019-09-21 12:01:34 -05:00
|
|
|
assert.Equal(t, "ABC", res)
|
2019-08-15 07:07:28 -05:00
|
|
|
|
2019-09-21 12:01:34 -05:00
|
|
|
// "áéíóú"
|
2019-08-15 07:07:28 -05:00
|
|
|
res, err = ToUTF8WithErr([]byte{0xc3, 0xa1, 0xc3, 0xa9, 0xc3, 0xad, 0xc3, 0xb3, 0xc3, 0xba})
|
|
|
|
assert.NoError(t, err)
|
2019-09-21 12:01:34 -05:00
|
|
|
assert.Equal(t, []byte{0xc3, 0xa1, 0xc3, 0xa9, 0xc3, 0xad, 0xc3, 0xb3, 0xc3, 0xba}, []byte(res))
|
2019-08-15 07:07:28 -05:00
|
|
|
|
2019-09-21 12:01:34 -05:00
|
|
|
// "áéíóú"
|
2022-01-20 12:46:10 -05:00
|
|
|
res, err = ToUTF8WithErr([]byte{
|
|
|
|
0xef, 0xbb, 0xbf, 0xc3, 0xa1, 0xc3, 0xa9, 0xc3, 0xad, 0xc3, 0xb3,
|
|
|
|
0xc3, 0xba,
|
|
|
|
})
|
2019-08-15 07:07:28 -05:00
|
|
|
assert.NoError(t, err)
|
2019-09-21 12:01:34 -05:00
|
|
|
assert.Equal(t, []byte{0xc3, 0xa1, 0xc3, 0xa9, 0xc3, 0xad, 0xc3, 0xb3, 0xc3, 0xba}, []byte(res))
|
2019-08-15 07:07:28 -05:00
|
|
|
|
2022-01-20 12:46:10 -05:00
|
|
|
res, err = ToUTF8WithErr([]byte{
|
|
|
|
0x48, 0x6F, 0x6C, 0x61, 0x2C, 0x20, 0x61, 0x73, 0xED, 0x20, 0x63,
|
|
|
|
0xF3, 0x6D, 0x6F, 0x20, 0xF1, 0x6F, 0x73, 0x41, 0x41, 0x41, 0x2e,
|
|
|
|
})
|
2019-08-15 07:07:28 -05:00
|
|
|
assert.NoError(t, err)
|
2019-09-21 12:01:34 -05:00
|
|
|
stringMustStartWith(t, "Hola,", res)
|
|
|
|
stringMustEndWith(t, "AAA.", res)
|
2019-08-15 07:07:28 -05:00
|
|
|
|
2022-01-20 12:46:10 -05:00
|
|
|
res, err = ToUTF8WithErr([]byte{
|
|
|
|
0x48, 0x6F, 0x6C, 0x61, 0x2C, 0x20, 0x61, 0x73, 0xED, 0x20, 0x63,
|
|
|
|
0xF3, 0x6D, 0x6F, 0x20, 0x07, 0xA4, 0x6F, 0x73, 0x41, 0x41, 0x41, 0x2e,
|
|
|
|
})
|
2019-08-15 07:07:28 -05:00
|
|
|
assert.NoError(t, err)
|
2019-09-21 12:01:34 -05:00
|
|
|
stringMustStartWith(t, "Hola,", res)
|
|
|
|
stringMustEndWith(t, "AAA.", res)
|
2019-08-15 07:07:28 -05:00
|
|
|
|
2022-01-20 12:46:10 -05:00
|
|
|
res, err = ToUTF8WithErr([]byte{
|
|
|
|
0x48, 0x6F, 0x6C, 0x61, 0x2C, 0x20, 0x61, 0x73, 0xED, 0x20, 0x63,
|
|
|
|
0xF3, 0x6D, 0x6F, 0x20, 0x81, 0xA4, 0x6F, 0x73, 0x41, 0x41, 0x41, 0x2e,
|
|
|
|
})
|
2019-08-15 07:07:28 -05:00
|
|
|
assert.NoError(t, err)
|
2019-09-21 12:01:34 -05:00
|
|
|
stringMustStartWith(t, "Hola,", res)
|
|
|
|
stringMustEndWith(t, "AAA.", res)
|
2019-08-15 07:07:28 -05:00
|
|
|
|
|
|
|
// Japanese (Shift-JIS)
|
2019-09-21 12:01:34 -05:00
|
|
|
// 日属秘ぞしちゅ。
|
2022-01-20 12:46:10 -05:00
|
|
|
res, err = ToUTF8WithErr([]byte{
|
|
|
|
0x93, 0xFA, 0x91, 0xAE, 0x94, 0xE9, 0x82, 0xBC, 0x82, 0xB5, 0x82,
|
|
|
|
0xBF, 0x82, 0xE3, 0x81, 0x42,
|
|
|
|
})
|
2019-08-15 07:07:28 -05:00
|
|
|
assert.NoError(t, err)
|
2022-01-20 12:46:10 -05:00
|
|
|
assert.Equal(t, []byte{
|
|
|
|
0xE6, 0x97, 0xA5, 0xE5, 0xB1, 0x9E, 0xE7, 0xA7, 0x98, 0xE3,
|
|
|
|
0x81, 0x9E, 0xE3, 0x81, 0x97, 0xE3, 0x81, 0xA1, 0xE3, 0x82, 0x85, 0xE3, 0x80, 0x82,
|
|
|
|
},
|
2019-09-21 12:01:34 -05:00
|
|
|
[]byte(res))
|
2019-08-15 07:07:28 -05:00
|
|
|
|
|
|
|
res, err = ToUTF8WithErr([]byte{0x00, 0x00, 0x00, 0x00})
|
|
|
|
assert.NoError(t, err)
|
2019-09-21 12:01:34 -05:00
|
|
|
assert.Equal(t, []byte{0x00, 0x00, 0x00, 0x00}, []byte(res))
|
2019-08-15 07:07:28 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestToUTF8WithFallback(t *testing.T) {
|
2020-08-23 08:15:29 -05:00
|
|
|
resetDefaultCharsetsOrder()
|
2019-09-02 18:08:07 -05:00
|
|
|
// "ABC"
|
2019-08-15 07:07:28 -05:00
|
|
|
res := ToUTF8WithFallback([]byte{0x41, 0x42, 0x43})
|
2019-09-02 18:08:07 -05:00
|
|
|
assert.Equal(t, []byte{0x41, 0x42, 0x43}, res)
|
2019-08-15 07:07:28 -05:00
|
|
|
|
2019-09-02 18:08:07 -05:00
|
|
|
// "áéíóú"
|
2019-08-15 07:07:28 -05:00
|
|
|
res = ToUTF8WithFallback([]byte{0xc3, 0xa1, 0xc3, 0xa9, 0xc3, 0xad, 0xc3, 0xb3, 0xc3, 0xba})
|
2019-09-02 18:08:07 -05:00
|
|
|
assert.Equal(t, []byte{0xc3, 0xa1, 0xc3, 0xa9, 0xc3, 0xad, 0xc3, 0xb3, 0xc3, 0xba}, res)
|
2019-08-15 07:07:28 -05:00
|
|
|
|
2019-09-02 18:08:07 -05:00
|
|
|
// UTF8 BOM + "áéíóú"
|
2019-08-15 07:07:28 -05:00
|
|
|
res = ToUTF8WithFallback([]byte{0xef, 0xbb, 0xbf, 0xc3, 0xa1, 0xc3, 0xa9, 0xc3, 0xad, 0xc3, 0xb3, 0xc3, 0xba})
|
2019-09-02 18:08:07 -05:00
|
|
|
assert.Equal(t, []byte{0xc3, 0xa1, 0xc3, 0xa9, 0xc3, 0xad, 0xc3, 0xb3, 0xc3, 0xba}, res)
|
2019-08-15 07:07:28 -05:00
|
|
|
|
2019-09-02 18:08:07 -05:00
|
|
|
// "Hola, así cómo ños"
|
2022-01-20 12:46:10 -05:00
|
|
|
res = ToUTF8WithFallback([]byte{
|
|
|
|
0x48, 0x6F, 0x6C, 0x61, 0x2C, 0x20, 0x61, 0x73, 0xED, 0x20, 0x63,
|
|
|
|
0xF3, 0x6D, 0x6F, 0x20, 0xF1, 0x6F, 0x73,
|
|
|
|
})
|
|
|
|
assert.Equal(t, []byte{
|
|
|
|
0x48, 0x6F, 0x6C, 0x61, 0x2C, 0x20, 0x61, 0x73, 0xC3, 0xAD, 0x20, 0x63,
|
|
|
|
0xC3, 0xB3, 0x6D, 0x6F, 0x20, 0xC3, 0xB1, 0x6F, 0x73,
|
|
|
|
}, res)
|
2019-08-15 07:07:28 -05:00
|
|
|
|
2019-09-02 18:08:07 -05:00
|
|
|
// "Hola, así cómo "
|
|
|
|
minmatch := []byte{0x48, 0x6F, 0x6C, 0x61, 0x2C, 0x20, 0x61, 0x73, 0xC3, 0xAD, 0x20, 0x63, 0xC3, 0xB3, 0x6D, 0x6F, 0x20}
|
2019-08-15 07:07:28 -05:00
|
|
|
|
|
|
|
res = ToUTF8WithFallback([]byte{0x48, 0x6F, 0x6C, 0x61, 0x2C, 0x20, 0x61, 0x73, 0xED, 0x20, 0x63, 0xF3, 0x6D, 0x6F, 0x20, 0x07, 0xA4, 0x6F, 0x73})
|
|
|
|
// Do not fail for differences in invalid cases, as the library might change the conversion criteria for those
|
|
|
|
assert.Equal(t, minmatch, res[0:len(minmatch)])
|
|
|
|
|
|
|
|
res = ToUTF8WithFallback([]byte{0x48, 0x6F, 0x6C, 0x61, 0x2C, 0x20, 0x61, 0x73, 0xED, 0x20, 0x63, 0xF3, 0x6D, 0x6F, 0x20, 0x81, 0xA4, 0x6F, 0x73})
|
|
|
|
// Do not fail for differences in invalid cases, as the library might change the conversion criteria for those
|
|
|
|
assert.Equal(t, minmatch, res[0:len(minmatch)])
|
|
|
|
|
|
|
|
// Japanese (Shift-JIS)
|
2019-09-02 18:08:07 -05:00
|
|
|
// "日属秘ぞしちゅ。"
|
2019-08-15 07:07:28 -05:00
|
|
|
res = ToUTF8WithFallback([]byte{0x93, 0xFA, 0x91, 0xAE, 0x94, 0xE9, 0x82, 0xBC, 0x82, 0xB5, 0x82, 0xBF, 0x82, 0xE3, 0x81, 0x42})
|
2022-01-20 12:46:10 -05:00
|
|
|
assert.Equal(t, []byte{
|
|
|
|
0xE6, 0x97, 0xA5, 0xE5, 0xB1, 0x9E, 0xE7, 0xA7, 0x98, 0xE3,
|
|
|
|
0x81, 0x9E, 0xE3, 0x81, 0x97, 0xE3, 0x81, 0xA1, 0xE3, 0x82, 0x85, 0xE3, 0x80, 0x82,
|
|
|
|
}, res)
|
2019-08-15 07:07:28 -05:00
|
|
|
|
|
|
|
res = ToUTF8WithFallback([]byte{0x00, 0x00, 0x00, 0x00})
|
|
|
|
assert.Equal(t, []byte{0x00, 0x00, 0x00, 0x00}, res)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestToUTF8(t *testing.T) {
|
2020-08-23 08:15:29 -05:00
|
|
|
resetDefaultCharsetsOrder()
|
2019-09-21 12:01:34 -05:00
|
|
|
// Note: golang compiler seems so behave differently depending on the current
|
|
|
|
// locale, so some conversions might behave differently. For that reason, we don't
|
|
|
|
// depend on particular conversions but in expected behaviors.
|
2019-08-15 07:07:28 -05:00
|
|
|
|
2019-09-21 12:01:34 -05:00
|
|
|
res := ToUTF8(string([]byte{0x41, 0x42, 0x43}))
|
|
|
|
assert.Equal(t, "ABC", res)
|
2019-08-15 07:07:28 -05:00
|
|
|
|
2019-09-21 12:01:34 -05:00
|
|
|
// "áéíóú"
|
|
|
|
res = ToUTF8(string([]byte{0xc3, 0xa1, 0xc3, 0xa9, 0xc3, 0xad, 0xc3, 0xb3, 0xc3, 0xba}))
|
|
|
|
assert.Equal(t, []byte{0xc3, 0xa1, 0xc3, 0xa9, 0xc3, 0xad, 0xc3, 0xb3, 0xc3, 0xba}, []byte(res))
|
|
|
|
|
|
|
|
// BOM + "áéíóú"
|
2022-01-20 12:46:10 -05:00
|
|
|
res = ToUTF8(string([]byte{
|
|
|
|
0xef, 0xbb, 0xbf, 0xc3, 0xa1, 0xc3, 0xa9, 0xc3, 0xad, 0xc3, 0xb3,
|
|
|
|
0xc3, 0xba,
|
|
|
|
}))
|
2019-09-21 12:01:34 -05:00
|
|
|
assert.Equal(t, []byte{0xc3, 0xa1, 0xc3, 0xa9, 0xc3, 0xad, 0xc3, 0xb3, 0xc3, 0xba}, []byte(res))
|
|
|
|
|
|
|
|
// Latin1
|
|
|
|
// Hola, así cómo ños
|
2022-01-20 12:46:10 -05:00
|
|
|
res = ToUTF8(string([]byte{
|
|
|
|
0x48, 0x6F, 0x6C, 0x61, 0x2C, 0x20, 0x61, 0x73, 0xED, 0x20, 0x63,
|
|
|
|
0xF3, 0x6D, 0x6F, 0x20, 0xF1, 0x6F, 0x73,
|
|
|
|
}))
|
|
|
|
assert.Equal(t, []byte{
|
|
|
|
0x48, 0x6f, 0x6c, 0x61, 0x2c, 0x20, 0x61, 0x73, 0xc3, 0xad, 0x20, 0x63,
|
|
|
|
0xc3, 0xb3, 0x6d, 0x6f, 0x20, 0xc3, 0xb1, 0x6f, 0x73,
|
|
|
|
}, []byte(res))
|
2019-09-21 12:01:34 -05:00
|
|
|
|
|
|
|
// Latin1
|
|
|
|
// Hola, así cómo \x07ños
|
2022-01-20 12:46:10 -05:00
|
|
|
res = ToUTF8(string([]byte{
|
|
|
|
0x48, 0x6F, 0x6C, 0x61, 0x2C, 0x20, 0x61, 0x73, 0xED, 0x20, 0x63,
|
|
|
|
0xF3, 0x6D, 0x6F, 0x20, 0x07, 0xA4, 0x6F, 0x73,
|
|
|
|
}))
|
2019-09-21 12:01:34 -05:00
|
|
|
// Hola,
|
|
|
|
bytesMustStartWith(t, []byte{0x48, 0x6F, 0x6C, 0x61, 0x2C}, []byte(res))
|
2019-08-15 07:07:28 -05:00
|
|
|
|
|
|
|
// This test FAILS
|
|
|
|
// res = ToUTF8("Hola, así cómo \x81ños")
|
|
|
|
// Do not fail for differences in invalid cases, as the library might change the conversion criteria for those
|
|
|
|
// assert.Regexp(t, "^Hola, así cómo", res)
|
|
|
|
|
|
|
|
// Japanese (Shift-JIS)
|
2019-09-21 12:01:34 -05:00
|
|
|
// 日属秘ぞしちゅ。
|
2022-01-20 12:46:10 -05:00
|
|
|
res = ToUTF8(string([]byte{
|
|
|
|
0x93, 0xFA, 0x91, 0xAE, 0x94, 0xE9, 0x82, 0xBC, 0x82, 0xB5, 0x82,
|
|
|
|
0xBF, 0x82, 0xE3, 0x81, 0x42,
|
|
|
|
}))
|
|
|
|
assert.Equal(t, []byte{
|
|
|
|
0xE6, 0x97, 0xA5, 0xE5, 0xB1, 0x9E, 0xE7, 0xA7, 0x98, 0xE3,
|
|
|
|
0x81, 0x9E, 0xE3, 0x81, 0x97, 0xE3, 0x81, 0xA1, 0xE3, 0x82, 0x85, 0xE3, 0x80, 0x82,
|
|
|
|
},
|
2019-09-21 12:01:34 -05:00
|
|
|
[]byte(res))
|
2019-08-15 07:07:28 -05:00
|
|
|
|
|
|
|
res = ToUTF8("\x00\x00\x00\x00")
|
2019-09-21 12:01:34 -05:00
|
|
|
assert.Equal(t, []byte{0x00, 0x00, 0x00, 0x00}, []byte(res))
|
2019-08-15 07:07:28 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestToUTF8DropErrors(t *testing.T) {
|
2020-08-23 08:15:29 -05:00
|
|
|
resetDefaultCharsetsOrder()
|
2019-09-02 18:08:07 -05:00
|
|
|
// "ABC"
|
2019-08-15 07:07:28 -05:00
|
|
|
res := ToUTF8DropErrors([]byte{0x41, 0x42, 0x43})
|
2019-09-02 18:08:07 -05:00
|
|
|
assert.Equal(t, []byte{0x41, 0x42, 0x43}, res)
|
2019-08-15 07:07:28 -05:00
|
|
|
|
2019-09-02 18:08:07 -05:00
|
|
|
// "áéíóú"
|
2019-08-15 07:07:28 -05:00
|
|
|
res = ToUTF8DropErrors([]byte{0xc3, 0xa1, 0xc3, 0xa9, 0xc3, 0xad, 0xc3, 0xb3, 0xc3, 0xba})
|
2019-09-02 18:08:07 -05:00
|
|
|
assert.Equal(t, []byte{0xc3, 0xa1, 0xc3, 0xa9, 0xc3, 0xad, 0xc3, 0xb3, 0xc3, 0xba}, res)
|
2019-08-15 07:07:28 -05:00
|
|
|
|
2019-09-02 18:08:07 -05:00
|
|
|
// UTF8 BOM + "áéíóú"
|
2019-08-15 07:07:28 -05:00
|
|
|
res = ToUTF8DropErrors([]byte{0xef, 0xbb, 0xbf, 0xc3, 0xa1, 0xc3, 0xa9, 0xc3, 0xad, 0xc3, 0xb3, 0xc3, 0xba})
|
2019-09-02 18:08:07 -05:00
|
|
|
assert.Equal(t, []byte{0xc3, 0xa1, 0xc3, 0xa9, 0xc3, 0xad, 0xc3, 0xb3, 0xc3, 0xba}, res)
|
2019-08-15 07:07:28 -05:00
|
|
|
|
2019-09-02 18:08:07 -05:00
|
|
|
// "Hola, así cómo ños"
|
2019-08-15 07:07:28 -05:00
|
|
|
res = ToUTF8DropErrors([]byte{0x48, 0x6F, 0x6C, 0x61, 0x2C, 0x20, 0x61, 0x73, 0xED, 0x20, 0x63, 0xF3, 0x6D, 0x6F, 0x20, 0xF1, 0x6F, 0x73})
|
2019-10-07 00:49:14 -05:00
|
|
|
assert.Equal(t, []byte{0x48, 0x6F, 0x6C, 0x61, 0x2C, 0x20, 0x61, 0x73}, res[:8])
|
|
|
|
assert.Equal(t, []byte{0x73}, res[len(res)-1:])
|
2019-08-15 07:07:28 -05:00
|
|
|
|
2019-09-02 18:08:07 -05:00
|
|
|
// "Hola, así cómo "
|
|
|
|
minmatch := []byte{0x48, 0x6F, 0x6C, 0x61, 0x2C, 0x20, 0x61, 0x73, 0xC3, 0xAD, 0x20, 0x63, 0xC3, 0xB3, 0x6D, 0x6F, 0x20}
|
2019-08-15 07:07:28 -05:00
|
|
|
|
|
|
|
res = ToUTF8DropErrors([]byte{0x48, 0x6F, 0x6C, 0x61, 0x2C, 0x20, 0x61, 0x73, 0xED, 0x20, 0x63, 0xF3, 0x6D, 0x6F, 0x20, 0x07, 0xA4, 0x6F, 0x73})
|
|
|
|
// Do not fail for differences in invalid cases, as the library might change the conversion criteria for those
|
|
|
|
assert.Equal(t, minmatch, res[0:len(minmatch)])
|
|
|
|
|
|
|
|
res = ToUTF8DropErrors([]byte{0x48, 0x6F, 0x6C, 0x61, 0x2C, 0x20, 0x61, 0x73, 0xED, 0x20, 0x63, 0xF3, 0x6D, 0x6F, 0x20, 0x81, 0xA4, 0x6F, 0x73})
|
|
|
|
// Do not fail for differences in invalid cases, as the library might change the conversion criteria for those
|
|
|
|
assert.Equal(t, minmatch, res[0:len(minmatch)])
|
|
|
|
|
|
|
|
// Japanese (Shift-JIS)
|
2019-09-02 18:08:07 -05:00
|
|
|
// "日属秘ぞしちゅ。"
|
2019-08-15 07:07:28 -05:00
|
|
|
res = ToUTF8DropErrors([]byte{0x93, 0xFA, 0x91, 0xAE, 0x94, 0xE9, 0x82, 0xBC, 0x82, 0xB5, 0x82, 0xBF, 0x82, 0xE3, 0x81, 0x42})
|
2022-01-20 12:46:10 -05:00
|
|
|
assert.Equal(t, []byte{
|
|
|
|
0xE6, 0x97, 0xA5, 0xE5, 0xB1, 0x9E, 0xE7, 0xA7, 0x98, 0xE3,
|
|
|
|
0x81, 0x9E, 0xE3, 0x81, 0x97, 0xE3, 0x81, 0xA1, 0xE3, 0x82, 0x85, 0xE3, 0x80, 0x82,
|
|
|
|
}, res)
|
2019-08-15 07:07:28 -05:00
|
|
|
|
|
|
|
res = ToUTF8DropErrors([]byte{0x00, 0x00, 0x00, 0x00})
|
|
|
|
assert.Equal(t, []byte{0x00, 0x00, 0x00, 0x00}, res)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestDetectEncoding(t *testing.T) {
|
2020-08-23 08:15:29 -05:00
|
|
|
resetDefaultCharsetsOrder()
|
2019-08-15 07:07:28 -05:00
|
|
|
testSuccess := func(b []byte, expected string) {
|
|
|
|
encoding, err := DetectEncoding(b)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
assert.Equal(t, expected, encoding)
|
|
|
|
}
|
|
|
|
// utf-8
|
|
|
|
b := []byte("just some ascii")
|
|
|
|
testSuccess(b, "UTF-8")
|
|
|
|
|
|
|
|
// utf-8-sig: "hey" (with BOM)
|
|
|
|
b = []byte{0xef, 0xbb, 0xbf, 0x68, 0x65, 0x79}
|
|
|
|
testSuccess(b, "UTF-8")
|
|
|
|
|
|
|
|
// utf-16: "hey<accented G>"
|
|
|
|
b = []byte{0xff, 0xfe, 0x68, 0x00, 0x65, 0x00, 0x79, 0x00, 0xf4, 0x01}
|
|
|
|
testSuccess(b, "UTF-16LE")
|
|
|
|
|
|
|
|
// iso-8859-1: d<accented e>cor<newline>
|
|
|
|
b = []byte{0x44, 0xe9, 0x63, 0x6f, 0x72, 0x0a}
|
|
|
|
encoding, err := DetectEncoding(b)
|
|
|
|
assert.NoError(t, err)
|
2020-08-23 08:15:29 -05:00
|
|
|
assert.Contains(t, encoding, "ISO-8859-1")
|
2019-08-15 07:07:28 -05:00
|
|
|
|
2020-06-02 17:20:19 -05:00
|
|
|
old := setting.Repository.AnsiCharset
|
2019-08-15 07:07:28 -05:00
|
|
|
setting.Repository.AnsiCharset = "placeholder"
|
2020-06-02 17:20:19 -05:00
|
|
|
defer func() {
|
|
|
|
setting.Repository.AnsiCharset = old
|
|
|
|
}()
|
2019-08-15 07:07:28 -05:00
|
|
|
testSuccess(b, "placeholder")
|
|
|
|
|
|
|
|
// invalid bytes
|
|
|
|
b = []byte{0xfa}
|
|
|
|
_, err = DetectEncoding(b)
|
|
|
|
assert.Error(t, err)
|
|
|
|
}
|
2019-09-21 12:01:34 -05:00
|
|
|
|
2021-12-19 23:41:31 -05:00
|
|
|
func stringMustStartWith(t *testing.T, expected, value string) {
|
2022-06-20 05:02:49 -05:00
|
|
|
assert.Equal(t, expected, value[:len(expected)])
|
2019-09-21 12:01:34 -05:00
|
|
|
}
|
|
|
|
|
2021-12-19 23:41:31 -05:00
|
|
|
func stringMustEndWith(t *testing.T, expected, value string) {
|
2022-06-20 05:02:49 -05:00
|
|
|
assert.Equal(t, expected, value[len(value)-len(expected):])
|
2019-09-21 12:01:34 -05:00
|
|
|
}
|
|
|
|
|
2021-12-19 23:41:31 -05:00
|
|
|
func bytesMustStartWith(t *testing.T, expected, value []byte) {
|
2019-09-21 12:01:34 -05:00
|
|
|
assert.Equal(t, expected, value[:len(expected)])
|
|
|
|
}
|
2022-05-21 08:06:24 -05:00
|
|
|
|
|
|
|
func TestToUTF8WithFallbackReader(t *testing.T) {
|
|
|
|
resetDefaultCharsetsOrder()
|
|
|
|
|
|
|
|
for testLen := 0; testLen < 2048; testLen++ {
|
|
|
|
pattern := " test { () }\n"
|
|
|
|
input := ""
|
|
|
|
for len(input) < testLen {
|
|
|
|
input += pattern
|
|
|
|
}
|
|
|
|
input = input[:testLen]
|
|
|
|
input += "// Выключаем"
|
|
|
|
rd := ToUTF8WithFallbackReader(bytes.NewReader([]byte(input)))
|
|
|
|
r, _ := io.ReadAll(rd)
|
|
|
|
assert.EqualValuesf(t, input, string(r), "testing string len=%d", testLen)
|
|
|
|
}
|
|
|
|
|
|
|
|
truncatedOneByteExtension := failFastBytes
|
|
|
|
encoding, _ := DetectEncoding(truncatedOneByteExtension)
|
|
|
|
assert.Equal(t, "UTF-8", encoding)
|
|
|
|
|
|
|
|
truncatedTwoByteExtension := failFastBytes
|
|
|
|
truncatedTwoByteExtension[len(failFastBytes)-1] = 0x9b
|
|
|
|
truncatedTwoByteExtension[len(failFastBytes)-2] = 0xe2
|
|
|
|
|
|
|
|
encoding, _ = DetectEncoding(truncatedTwoByteExtension)
|
|
|
|
assert.Equal(t, "UTF-8", encoding)
|
|
|
|
|
|
|
|
truncatedThreeByteExtension := failFastBytes
|
|
|
|
truncatedThreeByteExtension[len(failFastBytes)-1] = 0x92
|
|
|
|
truncatedThreeByteExtension[len(failFastBytes)-2] = 0x9f
|
|
|
|
truncatedThreeByteExtension[len(failFastBytes)-3] = 0xf0
|
|
|
|
|
|
|
|
encoding, _ = DetectEncoding(truncatedThreeByteExtension)
|
|
|
|
assert.Equal(t, "UTF-8", encoding)
|
|
|
|
}
|
|
|
|
|
|
|
|
var failFastBytes = []byte{
|
|
|
|
0x69, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x20, 0x6f, 0x72, 0x67, 0x2e, 0x61, 0x70, 0x61, 0x63, 0x68, 0x65, 0x2e, 0x74, 0x6f,
|
|
|
|
0x6f, 0x6c, 0x73, 0x2e, 0x61, 0x6e, 0x74, 0x2e, 0x74, 0x61, 0x73, 0x6b, 0x64, 0x65, 0x66, 0x73, 0x2e, 0x63, 0x6f, 0x6e,
|
|
|
|
0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x4f, 0x73, 0x0a, 0x69, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x20, 0x6f, 0x72, 0x67,
|
|
|
|
0x2e, 0x73, 0x70, 0x72, 0x69, 0x6e, 0x67, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x77, 0x6f, 0x72, 0x6b, 0x2e, 0x62, 0x6f, 0x6f,
|
|
|
|
0x74, 0x2e, 0x67, 0x72, 0x61, 0x64, 0x6c, 0x65, 0x2e, 0x74, 0x61, 0x73, 0x6b, 0x73, 0x2e, 0x72, 0x75, 0x6e, 0x2e, 0x42,
|
|
|
|
0x6f, 0x6f, 0x74, 0x52, 0x75, 0x6e, 0x0a, 0x0a, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x73, 0x20, 0x7b, 0x0a, 0x20, 0x20,
|
|
|
|
0x20, 0x20, 0x69, 0x64, 0x28, 0x22, 0x6f, 0x72, 0x67, 0x2e, 0x73, 0x70, 0x72, 0x69, 0x6e, 0x67, 0x66, 0x72, 0x61, 0x6d,
|
|
|
|
0x65, 0x77, 0x6f, 0x72, 0x6b, 0x2e, 0x62, 0x6f, 0x6f, 0x74, 0x22, 0x29, 0x0a, 0x7d, 0x0a, 0x0a, 0x64, 0x65, 0x70, 0x65,
|
|
|
|
0x6e, 0x64, 0x65, 0x6e, 0x63, 0x69, 0x65, 0x73, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x6d, 0x70, 0x6c, 0x65,
|
|
|
|
0x6d, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x28, 0x22, 0x3a,
|
|
|
|
0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x3a, 0x61, 0x70, 0x69, 0x22, 0x29, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x6d,
|
|
|
|
0x70, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74,
|
|
|
|
0x28, 0x22, 0x3a, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x3a, 0x61, 0x70, 0x69, 0x2d, 0x64, 0x6f, 0x63, 0x73, 0x22, 0x29,
|
|
|
|
0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e,
|
|
|
|
0x28, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x28, 0x22, 0x3a, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x3a, 0x64, 0x62,
|
|
|
|
0x22, 0x29, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69,
|
|
|
|
0x6f, 0x6e, 0x28, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x28, 0x22, 0x3a, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x3a,
|
|
|
|
0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x22, 0x29, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x6d, 0x70, 0x6c, 0x65,
|
|
|
|
0x6d, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x28, 0x22, 0x3a,
|
|
|
|
0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x3a, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2d, 0x66,
|
|
|
|
0x73, 0x22, 0x29, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x74,
|
|
|
|
0x69, 0x6f, 0x6e, 0x28, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x28, 0x22, 0x3a, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72,
|
|
|
|
0x3a, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2d, 0x6d, 0x71, 0x22, 0x29, 0x29, 0x0a, 0x0a,
|
|
|
|
0x20, 0x20, 0x20, 0x20, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x22,
|
|
|
|
0x6a, 0x66, 0x75, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x65, 0x3a, 0x70, 0x65, 0x2d, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e,
|
|
|
|
0x2d, 0x61, 0x75, 0x74, 0x68, 0x2d, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2d, 0x73, 0x74, 0x61, 0x72, 0x74,
|
|
|
|
0x65, 0x72, 0x22, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x74,
|
|
|
|
0x69, 0x6f, 0x6e, 0x28, 0x22, 0x6a, 0x66, 0x75, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x65, 0x3a, 0x70, 0x65, 0x2d, 0x63,
|
|
|
|
0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2d, 0x68, 0x61, 0x6c, 0x22, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x6d, 0x70, 0x6c,
|
|
|
|
0x65, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x22, 0x6a, 0x66, 0x75, 0x73, 0x69, 0x6f, 0x6e, 0x2e,
|
|
|
|
0x70, 0x65, 0x3a, 0x70, 0x65, 0x2d, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x22, 0x29, 0x0a,
|
|
|
|
0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x28,
|
|
|
|
0x22, 0x6f, 0x72, 0x67, 0x2e, 0x73, 0x70, 0x72, 0x69, 0x6e, 0x67, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x77, 0x6f, 0x72, 0x6b,
|
|
|
|
0x2e, 0x62, 0x6f, 0x6f, 0x74, 0x3a, 0x73, 0x70, 0x72, 0x69, 0x6e, 0x67, 0x2d, 0x62, 0x6f, 0x6f, 0x74, 0x2d, 0x73, 0x74,
|
|
|
|
0x61, 0x72, 0x74, 0x65, 0x72, 0x2d, 0x77, 0x65, 0x62, 0x22, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x6d, 0x70, 0x6c,
|
|
|
|
0x65, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x22, 0x6f, 0x72, 0x67, 0x2e, 0x73, 0x70, 0x72, 0x69,
|
|
|
|
0x6e, 0x67, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x77, 0x6f, 0x72, 0x6b, 0x2e, 0x62, 0x6f, 0x6f, 0x74, 0x3a, 0x73, 0x70, 0x72,
|
|
|
|
0x69, 0x6e, 0x67, 0x2d, 0x62, 0x6f, 0x6f, 0x74, 0x2d, 0x73, 0x74, 0x61, 0x72, 0x74, 0x65, 0x72, 0x2d, 0x61, 0x6f, 0x70,
|
|
|
|
0x22, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f,
|
|
|
|
0x6e, 0x28, 0x22, 0x6f, 0x72, 0x67, 0x2e, 0x73, 0x70, 0x72, 0x69, 0x6e, 0x67, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x77, 0x6f,
|
|
|
|
0x72, 0x6b, 0x2e, 0x62, 0x6f, 0x6f, 0x74, 0x3a, 0x73, 0x70, 0x72, 0x69, 0x6e, 0x67, 0x2d, 0x62, 0x6f, 0x6f, 0x74, 0x2d,
|
|
|
|
0x73, 0x74, 0x61, 0x72, 0x74, 0x65, 0x72, 0x2d, 0x61, 0x63, 0x74, 0x75, 0x61, 0x74, 0x6f, 0x72, 0x22, 0x29, 0x0a, 0x20,
|
|
|
|
0x20, 0x20, 0x20, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x22, 0x6f,
|
|
|
|
0x72, 0x67, 0x2e, 0x73, 0x70, 0x72, 0x69, 0x6e, 0x67, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x77, 0x6f, 0x72, 0x6b, 0x2e, 0x63,
|
|
|
|
0x6c, 0x6f, 0x75, 0x64, 0x3a, 0x73, 0x70, 0x72, 0x69, 0x6e, 0x67, 0x2d, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2d, 0x73, 0x74,
|
|
|
|
0x61, 0x72, 0x74, 0x65, 0x72, 0x2d, 0x62, 0x6f, 0x6f, 0x74, 0x73, 0x74, 0x72, 0x61, 0x70, 0x22, 0x29, 0x0a, 0x20, 0x20,
|
|
|
|
0x20, 0x20, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x22, 0x6f, 0x72,
|
|
|
|
0x67, 0x2e, 0x73, 0x70, 0x72, 0x69, 0x6e, 0x67, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x77, 0x6f, 0x72, 0x6b, 0x2e, 0x63, 0x6c,
|
|
|
|
0x6f, 0x75, 0x64, 0x3a, 0x73, 0x70, 0x72, 0x69, 0x6e, 0x67, 0x2d, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2d, 0x73, 0x74, 0x61,
|
|
|
|
0x72, 0x74, 0x65, 0x72, 0x2d, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2d, 0x61, 0x6c, 0x6c, 0x22, 0x29, 0x0a, 0x20, 0x20,
|
|
|
|
0x20, 0x20, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x22, 0x6f, 0x72,
|
|
|
|
0x67, 0x2e, 0x73, 0x70, 0x72, 0x69, 0x6e, 0x67, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x77, 0x6f, 0x72, 0x6b, 0x2e, 0x63, 0x6c,
|
|
|
|
0x6f, 0x75, 0x64, 0x3a, 0x73, 0x70, 0x72, 0x69, 0x6e, 0x67, 0x2d, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2d, 0x73, 0x74, 0x61,
|
|
|
|
0x72, 0x74, 0x65, 0x72, 0x2d, 0x73, 0x6c, 0x65, 0x75, 0x74, 0x68, 0x22, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x6d,
|
|
|
|
0x70, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x22, 0x6f, 0x72, 0x67, 0x2e, 0x73, 0x70,
|
|
|
|
0x72, 0x69, 0x6e, 0x67, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x77, 0x6f, 0x72, 0x6b, 0x2e, 0x72, 0x65, 0x74, 0x72, 0x79, 0x3a,
|
|
|
|
0x73, 0x70, 0x72, 0x69, 0x6e, 0x67, 0x2d, 0x72, 0x65, 0x74, 0x72, 0x79, 0x22, 0x29, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x20,
|
|
|
|
0x69, 0x6d, 0x70, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x22, 0x63, 0x68, 0x2e, 0x71,
|
|
|
|
0x6f, 0x73, 0x2e, 0x6c, 0x6f, 0x67, 0x62, 0x61, 0x63, 0x6b, 0x3a, 0x6c, 0x6f, 0x67, 0x62, 0x61, 0x63, 0x6b, 0x2d, 0x63,
|
|
|
|
0x6c, 0x61, 0x73, 0x73, 0x69, 0x63, 0x22, 0x29, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x6d,
|
|
|
|
0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x22, 0x69, 0x6f, 0x2e, 0x6d, 0x69, 0x63, 0x72, 0x6f, 0x6d, 0x65,
|
|
|
|
0x74, 0x65, 0x72, 0x3a, 0x6d, 0x69, 0x63, 0x72, 0x6f, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x2d, 0x72, 0x65, 0x67, 0x69, 0x73,
|
|
|
|
0x74, 0x72, 0x79, 0x2d, 0x70, 0x72, 0x6f, 0x6d, 0x65, 0x74, 0x68, 0x65, 0x75, 0x73, 0x22, 0x29, 0x0a, 0x0a, 0x20, 0x20,
|
|
|
|
0x20, 0x20, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x6b, 0x6f, 0x74,
|
|
|
|
0x6c, 0x69, 0x6e, 0x28, 0x22, 0x73, 0x74, 0x64, 0x6c, 0x69, 0x62, 0x22, 0x29, 0x29, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x20,
|
|
|
|
0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f,
|
|
|
|
0x2f, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2f, 0x2f, 0x20, 0x54, 0x65, 0x73, 0x74, 0x20, 0x64, 0x65, 0x70, 0x65, 0x6e, 0x64,
|
|
|
|
0x65, 0x6e, 0x63, 0x69, 0x65, 0x73, 0x2e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f,
|
|
|
|
0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x74,
|
|
|
|
0x65, 0x73, 0x74, 0x49, 0x6d, 0x70, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x22, 0x6a,
|
|
|
|
0x66, 0x75, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x65, 0x3a, 0x70, 0x65, 0x2d, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2d,
|
|
|
|
0x74, 0x65, 0x73, 0x74, 0x22, 0x29, 0x0a, 0x7d, 0x0a, 0x0a, 0x76, 0x61, 0x6c, 0x20, 0x70, 0x61, 0x74, 0x63, 0x68, 0x4a,
|
|
|
|
0x61, 0x72, 0x20, 0x62, 0x79, 0x20, 0x74, 0x61, 0x73, 0x6b, 0x73, 0x2e, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72,
|
|
|
|
0x69, 0x6e, 0x67, 0x28, 0x4a, 0x61, 0x72, 0x3a, 0x3a, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20,
|
|
|
|
0x20, 0x20, 0x61, 0x72, 0x63, 0x68, 0x69, 0x76, 0x65, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x69, 0x66, 0x69, 0x65, 0x72, 0x2e,
|
|
|
|
0x73, 0x65, 0x74, 0x28, 0x22, 0x70, 0x61, 0x74, 0x63, 0x68, 0x65, 0x64, 0x22, 0x29, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x20,
|
|
|
|
0x76, 0x61, 0x6c, 0x20, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x70, 0x61, 0x74, 0x68,
|
|
|
|
0x20, 0x62, 0x79, 0x20, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x67,
|
|
|
|
0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6d, 0x61, 0x6e, 0x69, 0x66, 0x65, 0x73, 0x74,
|
|
|
|
0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65,
|
|
|
|
0x73, 0x28, 0x22, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x2d, 0x50, 0x61, 0x74, 0x68, 0x22, 0x20, 0x74, 0x6f, 0x20, 0x6f, 0x62,
|
|
|
|
0x6a, 0x65, 0x63, 0x74, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x70,
|
|
|
|
0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x20, 0x76, 0x61, 0x6c, 0x20, 0x70, 0x61, 0x74, 0x74, 0x65, 0x72, 0x6e, 0x20, 0x3d,
|
|
|
|
0x20, 0x22, 0x66, 0x69, 0x6c, 0x65, 0x3a, 0x2f, 0x2b, 0x22, 0x2e, 0x74, 0x6f, 0x52, 0x65, 0x67, 0x65, 0x78, 0x28, 0x29,
|
|
|
|
0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64,
|
|
|
|
0x65, 0x20, 0x66, 0x75, 0x6e, 0x20, 0x74, 0x6f, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x28, 0x29, 0x3a, 0x20, 0x53, 0x74,
|
|
|
|
0x72, 0x69, 0x6e, 0x67, 0x20, 0x3d, 0x20, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x70,
|
|
|
|
0x61, 0x74, 0x68, 0x2e, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x2e, 0x6a, 0x6f, 0x69, 0x6e, 0x54, 0x6f, 0x53, 0x74, 0x72, 0x69,
|
|
|
|
0x6e, 0x67, 0x28, 0x22, 0x20, 0x22, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
|
|
|
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x69, 0x74, 0x2e, 0x74, 0x6f, 0x55, 0x52, 0x49, 0x28, 0x29, 0x2e, 0x74, 0x6f, 0x55,
|
|
|
|
0x52, 0x4c, 0x28, 0x29, 0x2e, 0x74, 0x6f, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x28, 0x29, 0x2e, 0x72, 0x65, 0x70, 0x6c,
|
|
|
|
0x61, 0x63, 0x65, 0x46, 0x69, 0x72, 0x73, 0x74, 0x28, 0x70, 0x61, 0x74, 0x74, 0x65, 0x72, 0x6e, 0x2c, 0x20, 0x22, 0x2f,
|
|
|
|
0x22, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0a, 0x20, 0x20, 0x20,
|
|
|
|
0x20, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0a, 0x7d, 0x0a, 0x0a, 0x74, 0x61, 0x73,
|
|
|
|
0x6b, 0x73, 0x2e, 0x6e, 0x61, 0x6d, 0x65, 0x64, 0x3c, 0x42, 0x6f, 0x6f, 0x74, 0x52, 0x75, 0x6e, 0x3e, 0x28, 0x22, 0x62,
|
|
|
|
0x6f, 0x6f, 0x74, 0x52, 0x75, 0x6e, 0x22, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20, 0x28, 0x4f,
|
|
|
|
0x73, 0x2e, 0x69, 0x73, 0x46, 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x28, 0x4f, 0x73, 0x2e, 0x46, 0x41, 0x4d, 0x49, 0x4c, 0x59,
|
|
|
|
0x5f, 0x57, 0x49, 0x4e, 0x44, 0x4f, 0x57, 0x53, 0x29, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
|
|
|
0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x70, 0x61, 0x74, 0x68, 0x20, 0x3d, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x28, 0x73,
|
|
|
|
0x6f, 0x75, 0x72, 0x63, 0x65, 0x53, 0x65, 0x74, 0x73, 0x2e, 0x6e, 0x61, 0x6d, 0x65, 0x64, 0x28, 0x22, 0x6d, 0x61, 0x69,
|
|
|
|
0x6e, 0x22, 0x29, 0x2e, 0x6d, 0x61, 0x70, 0x20, 0x7b, 0x20, 0x69, 0x74, 0x2e, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x20,
|
|
|
|
0x7d, 0x2c, 0x20, 0x70, 0x61, 0x74, 0x63, 0x68, 0x4a, 0x61, 0x72, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0a, 0x0a,
|
|
|
|
0x20, 0x20, 0x20, 0x20, 0x2f, 0x2f, 0x20, 0xd0,
|
|
|
|
}
|