diff --git a/conf/locale/locale_en-US.ini b/conf/locale/locale_en-US.ini index b3728843d..e7dd41f88 100644 --- a/conf/locale/locale_en-US.ini +++ b/conf/locale/locale_en-US.ini @@ -43,6 +43,10 @@ issues = Issues cancel = Cancel +[status] +page_not_found = Page Not Found +internal_server_error = Internal Server Error + [install] install = Installation title = Install Steps For First-time Run diff --git a/internal/assets/conf/conf_gen.go b/internal/assets/conf/conf_gen.go index 3df70c34c..882fd6872 100644 --- a/internal/assets/conf/conf_gen.go +++ b/internal/assets/conf/conf_gen.go @@ -213,7 +213,7 @@ // ../../../conf/locale/locale_cs-CZ.ini (72.893kB) // ../../../conf/locale/locale_de-DE.ini (73.666kB) // ../../../conf/locale/locale_en-GB.ini (66.468kB) -// ../../../conf/locale/locale_en-US.ini (69.108kB) +// ../../../conf/locale/locale_en-US.ini (69.196kB) // ../../../conf/locale/locale_es-ES.ini (74.188kB) // ../../../conf/locale/locale_fa-IR.ini (92.107kB) // ../../../conf/locale/locale_fi-FI.ini (70.349kB) @@ -324,7 +324,7 @@ func confAppIni() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "conf/app.ini", size: 18756, mode: os.FileMode(0644), modTime: time.Unix(1583566264, 0)} + info := bindataFileInfo{name: "conf/app.ini", size: 18756, mode: os.FileMode(0644), modTime: time.Unix(1583774435, 0)} a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x5, 0xf4, 0x94, 0xf6, 0xab, 0x5c, 0xeb, 0x3, 0x9, 0x8c, 0x61, 0x6, 0x6f, 0xa2, 0xd9, 0x7c, 0x2, 0x1d, 0x69, 0x1a, 0x2c, 0x63, 0x65, 0x58, 0xed, 0x43, 0xd1, 0x15, 0xd4, 0x34, 0x67, 0x9a}} return a, nil } @@ -4504,7 +4504,7 @@ func confLocaleLocale_bgBgIni() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "conf/locale/locale_bg-BG.ini", size: 97715, mode: os.FileMode(0644), modTime: time.Unix(1583417659, 0)} + info := bindataFileInfo{name: "conf/locale/locale_bg-BG.ini", size: 97715, mode: os.FileMode(0644), modTime: time.Unix(1583774435, 0)} a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xdb, 0xa0, 0x41, 0xdc, 0xc0, 0xb0, 0x2e, 0x3d, 0x23, 0x2f, 0xdb, 0xc7, 0x85, 0x19, 0x1e, 0xcb, 0x45, 0x11, 0x41, 0xc0, 0x2e, 0x16, 0x34, 0xf5, 0xb3, 0xe3, 0xc3, 0x76, 0xa8, 0x64, 0x1d, 0x73}} return a, nil } @@ -4524,7 +4524,7 @@ func confLocaleLocale_csCzIni() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "conf/locale/locale_cs-CZ.ini", size: 72893, mode: os.FileMode(0644), modTime: time.Unix(1583417659, 0)} + info := bindataFileInfo{name: "conf/locale/locale_cs-CZ.ini", size: 72893, mode: os.FileMode(0644), modTime: time.Unix(1583774435, 0)} a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xfc, 0x61, 0xd0, 0xc3, 0x26, 0xd0, 0xfa, 0x83, 0x7, 0xad, 0x67, 0xc8, 0x36, 0xa7, 0xde, 0x28, 0xce, 0x4f, 0x39, 0x86, 0x6e, 0xdb, 0x66, 0x69, 0x19, 0x16, 0xb6, 0x62, 0x83, 0xff, 0xf9, 0xa}} return a, nil } @@ -4544,7 +4544,7 @@ func confLocaleLocale_deDeIni() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "conf/locale/locale_de-DE.ini", size: 73666, mode: os.FileMode(0644), modTime: time.Unix(1583417659, 0)} + info := bindataFileInfo{name: "conf/locale/locale_de-DE.ini", size: 73666, mode: os.FileMode(0644), modTime: time.Unix(1583774435, 0)} a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x9a, 0x1c, 0x6f, 0xfd, 0xaf, 0xcb, 0x80, 0x4f, 0xb3, 0xdd, 0xe9, 0x5f, 0xe9, 0x95, 0x8f, 0x9b, 0xbe, 0x3d, 0xba, 0xb2, 0x3e, 0xa5, 0xc2, 0xc6, 0x5a, 0x5f, 0xe0, 0xbe, 0x9f, 0x88, 0xed, 0xf3}} return a, nil } @@ -4564,12 +4564,12 @@ func confLocaleLocale_enGbIni() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "conf/locale/locale_en-GB.ini", size: 66468, mode: os.FileMode(0644), modTime: time.Unix(1583417659, 0)} + info := bindataFileInfo{name: "conf/locale/locale_en-GB.ini", size: 66468, mode: os.FileMode(0644), modTime: time.Unix(1583774435, 0)} a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xf7, 0x0, 0x33, 0xbd, 0x58, 0x14, 0x7e, 0x91, 0xc8, 0xa3, 0x18, 0xf7, 0xb0, 0xb8, 0x45, 0x61, 0x7e, 0xf1, 0xf7, 0x10, 0x21, 0x16, 0x82, 0x7e, 0x78, 0xd9, 0x5c, 0xf1, 0x6, 0x35, 0x7a, 0x42}} return a, nil } -var _confLocaleLocale_enUsIni = "\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xb4\xbd\xeb\x72\xdc\xb8\x92\x30\xf8\x9f\x4f\x81\xee\x09\x85\xbb\x23\xe4\x72\xf4\x39\xdf\x7c\xbb\xd1\x61\xf9\xac\xda\x6e\x5f\x66\x64\x5b\x63\xd9\x73\xbe\x59\xaf\x83\x8d\x22\x51\x55\x18\xb1\x00\x1e\x02\x54\xb9\x7a\xe2\xbc\xc1\x3e\xc0\x3e\xdf\x3e\xc9\x06\xf2\x82\x0b\xc9\x92\xed\x3e\xb3\x7f\xa4\x22\x90\x48\xdc\x13\x99\x89\xcc\x84\xec\xfb\xba\x55\xae\x11\x17\xe2\x52\xf4\x52\x9b\x4e\x39\x27\x9c\xea\x36\x0f\x77\xd6\x79\xd5\x8a\x17\xda\x0b\xa7\x86\x3b\xdd\xa8\xaa\xda\xd9\xbd\x12\x17\xe2\xa5\xdd\xab\xaa\x95\x6e\xb7\xb6\x72\x68\xc5\x85\x78\xc6\xbf\x2b\xf5\xb9\xef\xec\x10\x80\x7e\xc5\x5f\xd5\x4e\x75\x7d\x28\xa3\xba\xbe\x72\x7a\x6b\x6a\x6d\xc4\x85\xb8\xd1\x5b\x23\x5e\x19\x4c\xb1\xa3\xe7\xa4\xb7\xa3\xc7\xb4\xb1\xe7\xa4\x0f\x7d\x35\xa8\xad\x76\x5e\x0d\xe2\x42\xbc\xa3\x9f\xd5\x41\xad\x9d\xf6\xa1\xa6\xbf\xe2\xaf\xaa\x97\xdb\xf0\x79\x2d\xb7\xaa\xf2\x6a\xdf\x77\x12\xb2\xdf\xd3\xcf\xaa\x93\x66\x3b\x22\xcc\x15\xfd\xac\x9a\x41\x49\xaf\x6a\xa3\x0e\xe2\x42\x3c\x85\x8f\xd5\x6a\x55\x8d\x4e\x0d\x75\x3f\xd8\x8d\xee\x54\x2d\x4d\x5b\xef\xb1\x53\x1f\x9c\x1a\x04\xa5\x0b\x69\x5a\x11\xd2\xa1\xc1\xaa\xad\xb5\xa9\xa5\xa3\x56\xab\x56\x68\x23\xa4\xab\x00\x95\x91\x7b\x2e\x1d\x7e\x56\x6a\x2f\x75\x17\xc6\x28\xfc\xaf\x7a\xe9\xdc\xc1\xc2\x40\x5e\xd3\xcf\x6a\x50\xb5\x3f\xf6\x0a\x3a\xfc\xf0\xfd\xb1\x57\x55\x23\x7b\xdf\xec\x64\x68\x26\xfe\xaa\xaa\x41\xf5\xd6\x69\x6f\x87\x23\xc0\xf1\x47\x65\x87\xad\x34\xfa\x77\xe9\xb5\x0d\x63\xfd\x36\xfb\xac\xf6\x7a\x18\x6c\x18\xc8\xd7\xf0\xa3\x32\xea\x50\x07\x3c\xe2\x42\xbc\x51\x87\x1c\x4b\xc8\xd9\xeb\xed\x80\xa3\x18\x32\x5f\xc3\x57\xc0\x82\x79\x84\x09\xb3\x22\xb6\x8d\x1d\x6e\x29\xf5\x79\xf8\x39\x41\x69\x87\x2d\xe5\x96\xed\x92\x46\x6e\x15\xe5\xbe\x86\x8f\x02\xc0\x55\xb2\xdd\x6b\x53\xf7\xd2\xa8\x30\x74\x97\xe1\x4b\x5c\x87\xaf\x4a\x36\x8d\x1d\x8d\xaf\x9d\xf2\x5e\x9b\x6d\x98\x83\x4b\x4c\x12\x37\x94\x54\x65\x79\x31\xed\x68\xc7\x38\xcb\xe2\x42\xfc\x87\x1d\x07\x71\x8d\x9f\x98\x97\x15\x82\xcc\x58\xb2\x92\x8d\xd7\x77\xda\x6b\x85\x95\xf1\x47\xd5\x8f\x5d\x57\x0f\xea\x6f\xa3\x72\x3e\x64\x5d\x8f\x5d\x27\xde\xd1\x77\xa5\x9d\x1b\xa1\xc4\x2b\xf8\x51\x55\x8d\x34\x0d\x74\xe7\x29\xfc\xa8\xaa\x8f\xda\x38\x2f\xbb\xee\x53\x45\x3f\x02\x30\xfe\xc2\x71\xf2\xda\x43\x63\x29\x51\xdc\x78\xd5\xbb\x30\xd0\xe2\xb9\x1e\x9c\x7f\xe8\xf5\x5e\x89\x77\xa3\xa9\x5a\xdb\xdc\xaa\xa1\x0e\xdb\x0f\x36\xce\xab\x8d\x38\xda\xf1\xc1\xa0\xc4\x30\x1a\xa3\xcd\x56\xbc\xb0\x5b\x27\xb4\x71\xba\x55\xe2\x19\x40\x9f\x8b\xbe\x53\xd2\x29\x31\x28\xd9\x8a\xc7\x52\x78\x39\x6c\x95\xbf\xf8\xbe\x5e\x77\xd2\xdc\x7e\x2f\x76\x83\xda\x5c\x7c\x7f\xe6\xbe\x7f\xf2\x62\xd4\xad\xea\xb4\x51\xee\xf1\x23\xf9\x44\x34\x72\x50\x9b\xb1\xeb\x8e\x62\xad\x36\x61\xaf\x1c\xed\x28\x9a\x9d\x34\xdb\xb0\x4f\x8e\x7e\x17\x2a\xd4\x46\xf8\x9d\x76\x22\x6c\xd4\xef\xaa\x30\x4a\xda\xab\xba\x5d\x33\x09\x82\x06\x41\xf2\xa0\x9c\x78\x7d\xbc\xf9\xb7\xab\x73\x71\x6d\x9d\xdf\x0e\x0a\x7e\xdf\xfc\xdb\x95\xf6\xea\xcf\xe7\xe2\xf5\xcd\xcd\xbf\x5d\x09\x3b\x88\xf7\xfa\xd9\x2f\xab\xaa\x5d\xd7\x3c\x2e\xcf\xa4\x97\xeb\xd0\x85\x38\x57\x21\x13\xb7\x52\xcc\x83\x0d\x15\x08\x1c\x10\x33\xe7\x61\x93\xd2\x06\x5d\xdc\x8e\xed\xba\xa6\x3d\x1c\x71\xbc\x09\x1b\xb9\x5d\xa7\x01\xbe\xc6\xa1\x1b\x9d\x12\xaf\xde\xbc\x79\xfb\xec\x17\xa1\xcc\x56\x1b\x25\x0e\xda\xef\xc4\xe8\x37\xff\x7b\xbd\x55\x46\x0d\xb2\xab\x1b\x1d\xc6\x66\x70\xca\x8b\x8d\x1d\xb0\xa7\xab\xca\xb9\xae\xde\xdb\x36\xd4\x72\x73\x73\x25\x5e\xdb\x36\xd0\x34\xbf\x83\x86\xf8\x5d\xe5\xfe\xd6\x85\xf1\x8a\x15\xbe\xdf\x29\x01\x4b\x17\x80\xec\x86\x87\x47\xb4\xd4\xc6\x95\x78\xbc\x1e\x9e\x64\xed\x92\x6b\x67\xbb\xd1\x53\x89\xc3\x4e\x19\x98\x27\xe7\xe5\xe0\x85\x74\x4c\xe8\x57\x95\x1a\x86\x5a\xed\x7b\x7f\x0c\xb3\x43\x6d\x98\x62\x47\x24\x8d\x34\xc6\x7a\xb1\x56\x02\xe0\x57\x95\xb1\x35\xee\xd4\x40\x36\x5b\xed\xe4\xba\x53\x35\x12\xf0\x81\x29\xd2\x7f\x84\xc5\x81\x05\x09\x42\x14\x10\x61\xc4\xc2\xa1\x00\xd4\x39\xac\x1c\x69\x04\x20\x15\xb4\xd5\xf3\x16\x32\x5d\x88\xb3\x86\xa4\x21\x26\xcc\x5a\x58\xf1\x34\xf0\x9a\xb9\xec\xfb\x4e\x37\x58\xf5\x0b\xcc\x4b\xcb\x27\x1c\x91\x34\xf7\x39\x1c\x4c\x3f\xe7\x65\x8b\x60\xf4\x61\x48\x07\x51\xd0\x60\x28\xbf\x53\x83\x12\xbb\x71\x8b\x07\x47\x67\xc7\xf6\x3b\xa0\xe0\x3c\xbe\x89\x4e\x8a\x77\xd6\x7a\x9c\xf3\x08\x90\xaa\xb8\xec\x3a\x38\x95\x07\xb5\xb7\x3e\x0c\x1c\x15\x0b\xb4\xe8\xa0\xbb\x2e\xf4\xd4\xc9\x3b\xd5\x0a\x6f\x71\xbf\xb5\x7a\x50\x4d\x40\xbc\xaa\x86\xd1\xd4\xb4\xd8\xdf\x8d\x06\x17\x3c\xa7\x95\x2b\x0b\xa0\xf6\xa3\xf3\x62\x27\xef\x54\x18\xf8\xc0\x1a\x78\xbb\xd8\x4e\xe8\xd2\x30\x1a\xd8\xc2\xab\xaa\xb5\x7b\x09\xc7\xfc\x33\xf8\x41\xdf\x39\x7e\xed\x84\xdc\x6c\x54\xe3\x9d\xb8\xb9\x79\x29\x9a\xce\x1a\x25\x3e\xbc\xbb\x72\x61\x1b\xec\xea\xde\x0e\xc0\x12\xdc\xbc\x14\xd7\x76\xf0\x31\x2d\x1b\xe8\x00\x61\xc6\xfd\x5a\x0d\xe2\xb0\xd3\xcd\x0e\x87\x3d\x94\x08\xab\x58\x0d\x42\x3b\x31\x3a\x6d\xb6\xe7\xa2\x53\xa1\x07\xda\xe3\x02\x08\x7d\xe0\x55\x17\xc0\x37\x4a\xfa\x71\x50\x70\xe8\xd7\xeb\x51\x77\x5e\x9b\x3a\x54\x48\x78\x80\x2c\x88\x5f\x30\x03\x4a\xdc\x40\xc6\x09\xf8\xba\xb7\x3d\x32\x2f\xb0\xab\xd6\x59\x39\x42\x18\xb6\x7c\x98\x40\xdb\x2b\x5c\xef\x8e\x9a\x14\x16\xdc\xa8\xdd\x4e\x6c\x06\xbb\x17\xee\xe8\xbc\xda\x43\xc1\x56\xaa\xbd\x35\xab\x6a\xe7\x7d\xcf\x63\xf3\xf2\xfd\xfb\x6b\x1c\x9c\x98\x7a\xdf\xe8\xc8\x6c\xed\xc2\x2a\xe9\x02\x1b\x65\x44\x40\x1b\x96\xf1\x38\x74\x93\x15\xfe\xe1\xdd\x15\xe7\x9c\x98\xb9\xd0\x84\x47\xe1\xcf\x4d\x9a\x40\x58\x09\xce\xee\xd5\x01\xd6\xbb\x36\x02\x98\x9d\x55\xd5\xd9\x6d\x3d\x58\xeb\x79\xb9\x5f\xd9\x2d\x2e\xf1\x22\x23\xd5\xf4\x8c\x17\x6d\x18\x9c\xc3\x10\x58\xbd\xce\x6e\x81\xe0\x85\xf1\x5a\x55\xca\x00\x69\x69\xac\x71\xb6\x53\x4c\x39\x7f\x85\x54\xf1\x14\x53\x91\x88\x2e\x40\xc6\x59\x7a\x15\x28\x4b\xab\xa1\xc7\xde\x22\x3d\x0d\x00\xe7\x42\x76\xce\x8a\x7e\xd0\xc6\x87\x8a\x61\x8e\x08\xc3\xaa\xaa\x6c\x1f\x4a\x64\x34\xe4\x2d\x25\x24\xc2\x01\xfd\x8e\xf9\xc0\xea\xc1\xca\xd1\x4d\x76\x38\xb9\xbd\xef\x6b\x3a\x89\x6e\x5e\xbf\xbf\xc6\xe3\x08\x52\x61\x11\x5c\x88\xe7\x83\xdd\xa7\x84\x34\x3e\xaf\x03\x3e\x80\x91\x6d\x3b\x28\xe7\xce\xc5\xbb\xe7\x4f\xc5\x3f\xff\xf9\x4f\x7f\x5a\x89\x57\x3e\x90\xbd\x40\x09\xfe\x33\xec\x60\x49\xb3\x90\x40\xed\x20\xfc\x4e\x89\xef\x03\x19\xfb\x5e\x3c\x86\xdc\xff\x43\x7d\x96\xfb\xbe\x53\xab\xc6\xee\x9f\x84\x55\xba\x97\x7e\x55\x85\x1c\x35\x30\xd1\xb8\x51\xa6\x55\x03\x31\xae\x94\x95\x91\x5e\xca\xce\xd8\x58\xe4\xd6\xc3\xd8\x6f\xf4\xb0\x4f\x13\xc4\x7c\x7c\x98\xa9\x90\xc3\x5c\xa0\xee\x6a\x63\xbd\xde\x1c\x13\x28\xf4\xf4\x4d\x48\xa4\xa5\x59\xd1\x4e\xa3\xe3\x2a\x8e\x31\xee\x4b\x58\x81\x6f\xfd\x4e\x0d\x3c\xdc\x2e\x8d\xb7\xdd\x6c\x02\xd3\x32\x59\x2d\x6f\x31\x15\x57\x4b\x0e\x12\x97\xc9\x33\x22\x18\x4f\x9f\xbd\x11\xea\x4e\x99\xb0\xb0\xfb\xc1\xb6\x63\x03\x2b\x87\x57\x4c\x27\x06\xe5\xec\x38\x34\x8a\x16\x6a\x24\xc8\xa1\x69\x81\xea\x37\xb2\xeb\x8e\xab\x8a\x0f\xc6\xed\x20\xef\xa4\x97\x43\x56\xc5\x0b\x4e\xa2\xd6\xcf\x60\x67\x8d\x8a\x25\x42\xcf\x9b\xd1\xf9\x40\x3d\xa0\x15\x0e\x1b\x85\xd9\x4e\xc8\x41\x89\xb1\xef\xac\x6c\x55\x2b\xd6\x47\xa0\xf1\x2e\xac\x85\x56\x6d\xe4\xd8\xf9\x55\xb5\x51\x6d\x20\x4a\xaa\xad\xa9\xae\xce\xda\x5b\xa8\x8c\x86\xea\x39\x03\x88\x4b\x42\x7a\x05\x10\xa7\x4a\xc6\xc6\x52\xf9\x08\x16\x1b\x45\x35\x78\x0b\x2c\x4a\xca\xb7\xbd\x32\xd4\x0d\x66\x4c\x44\xe0\x3b\x5a\x61\x8d\xe8\xf4\x9a\x3a\x9d\xc6\x72\xc2\x64\xf0\xe8\xdc\x04\x69\x36\xcf\x5b\x2c\x30\x1b\x54\x58\xf0\x6e\x5a\xf6\x5c\x58\xd3\x1d\x89\x19\x09\x5b\x0c\x05\x48\xe6\x4b\x5c\x22\x4b\x51\x5c\x63\x8a\x44\x52\x5b\x99\x1f\xab\x7d\x87\x6c\xaf\xb8\x93\x9d\x6e\x03\x46\x46\x10\x4e\x8b\xe5\xb6\xac\x2a\xe2\x95\x6b\x92\xab\xeb\x3b\x0d\x72\x6c\xdc\x62\x88\x92\x64\xed\x30\xc2\xff\x1e\x00\x82\x80\xec\x16\xcb\xc6\xd6\xbc\x0d\x9d\x74\x51\x8e\xc5\x75\x12\xba\x0b\x35\x04\xfe\xdd\x9d\x8b\x3b\x0d\x6c\x00\x2d\x72\x18\x97\x75\xe0\x31\x3b\x15\xaa\x72\x4a\x01\x06\xa1\xcd\xa3\xb1\xc7\x32\x2b\x12\xe2\x48\xae\x62\xbe\x3f\xb0\x83\xad\x35\x0f\xbc\x30\x0a\xd9\x16\x1e\xd5\x09\xdb\x27\x06\xbd\xdd\x79\x61\xec\x61\x45\xdc\xef\xe0\x3c\x8e\x0e\xc8\x16\x8a\x5a\xea\xa1\x11\xbc\xf7\xe4\xe8\x6d\xa0\x2f\xb0\xf5\xc4\x76\x90\x06\x96\x1f\x23\x56\x2e\xb6\x2b\x32\x84\x90\x37\x93\x21\x11\x68\x2a\xcc\xcf\xf8\xcf\x48\xfd\x88\xe8\xe5\x79\x44\xed\x12\x0c\x96\x66\x85\x00\x56\x8c\xd4\x95\x04\xc0\x7a\x6b\x41\x00\x65\x81\x2f\x70\x58\x95\x57\xce\xd7\x5b\xed\xeb\x4d\x20\xc1\x01\xf1\x73\xfc\x11\x58\x3e\xe5\xbc\x78\xb0\xd5\xfe\x81\x68\xec\x7e\x2f\x4d\xfb\xb3\x38\xbb\x23\xe9\xe1\xcf\x81\xba\x86\x1d\xaa\x3b\x18\x23\x12\x6c\x07\x85\x42\xc2\x9d\x1a\x5c\xd8\x3d\xad\x55\x4e\x04\xae\xd9\x8d\x3d\xf0\x1b\x51\xf2\x22\x01\xb1\xb5\x07\x13\xe8\x08\x0c\xba\xdd\x6c\x74\xa3\x65\x27\xd6\xda\xc8\xe1\x18\xb1\xc0\xe9\x74\xe6\xce\xc5\x9b\xb7\xef\x01\x70\x6b\x03\x3b\xd4\x32\xc0\xaa\xd2\x06\xd6\x7b\x90\x32\x68\x4d\xe4\x22\x16\x27\x69\x6c\x4b\x63\x87\xc0\x12\x40\x6f\xb8\xe0\x09\x06\x3a\xf0\x13\x28\x9f\xe8\x20\xe2\x02\x2c\x94\x8b\xbc\x6e\x18\x86\xbd\xf4\xcd\x8e\x38\x61\x5c\x44\x2e\x2c\xc2\xd0\xd2\x66\x1c\x06\x65\x70\x6d\xfd\x2c\xce\x9c\x78\xf8\x44\x9c\x65\xc7\x75\xbd\xd7\x2e\x30\x97\x91\x53\xe5\xb3\x5b\x40\x02\xe5\x16\xe7\x73\xea\x6d\x7e\xbc\x43\xc1\x70\xc6\x8b\x8d\x56\x5d\x3b\x6d\x6f\x60\xe4\xf1\xf0\xdc\x2e\xcd\x75\xc8\x16\x98\x3d\x22\x51\xa0\xd1\x59\x5e\x1a\x21\x5d\xcb\x4e\xff\xae\x72\x7e\xb0\x18\xd0\x62\x83\xc6\x15\xc9\xfb\x2f\x9b\x91\xbc\x95\xbc\x54\xdd\x88\x52\xc2\x85\xf8\xab\xea\x1a\xbb\x57\xdf\x89\xbf\xaa\x07\x83\x12\xdb\x0e\x96\x8a\xf4\xa4\x17\xb0\x4e\xc1\x42\x3e\x47\xe1\x62\x33\x1a\x38\xbb\xbc\xbc\x55\xa0\x4a\x48\x63\xb5\xc4\x36\x9e\x9c\xdd\xea\xe3\xce\xee\xd5\xa7\x6a\x44\xa1\xcc\x76\x6d\x14\xeb\x61\xd7\xda\x01\xf9\xa0\x28\xe3\x27\x98\xb8\x21\xdd\x41\xfb\x66\x57\x47\xf5\x66\x18\x7d\xaf\x3e\xc3\x24\x43\x56\xd2\x76\x86\xdd\x1c\xb2\xaa\xfd\x11\x16\x62\xe8\xf8\xeb\x63\x5a\x87\x5a\xb9\xca\xed\xec\x01\xb4\x87\x11\xe2\x66\x67\x0f\xa0\x37\x2c\x44\xb7\xd5\x6a\x55\x35\xb6\xeb\xe4\xda\x86\x89\xbc\x4b\xf0\x4f\xf3\xd4\x12\xf9\xfe\x58\xdb\x61\x4b\xd5\x96\xda\xb2\xfd\x91\x14\x74\x94\x8b\x0a\x3a\x57\x01\x99\x27\x3d\x2e\x9c\x06\x67\xae\x22\xbd\xd4\x4a\x9b\x1a\xd4\x5e\x5c\xf3\x2b\x83\x42\x55\xde\xce\xaa\xfa\x48\x3a\xde\x4f\x15\xc3\x15\x6d\x42\x0a\x8c\x83\xee\x0a\x55\xa4\x9b\xe8\x22\x5d\xe5\x94\x1c\x60\x07\xde\xc0\x8f\xaa\xfa\x28\x47\xbf\xfb\x94\x69\x65\x6b\x5e\x79\xac\x9d\x05\xcd\x21\x51\xe6\xc4\x5e\xee\x54\x1f\x38\xd1\xbd\x83\x25\xdb\x0d\x4a\xb6\x47\x92\x5b\xe3\xe2\xfd\x0b\x1e\x84\xda\x84\xf3\xe3\xbb\xca\xd9\x40\xb2\xea\x6f\x44\xf1\x8b\x36\x2d\x96\x2f\x99\x08\x54\x17\xef\x7b\x58\x26\x76\x18\x8e\xe7\xa5\x46\x63\x27\x9d\x58\x2b\x65\x58\xf2\x6c\x57\xac\x2f\x0a\xcb\x4b\x36\x48\x75\x40\xa1\x0d\x3b\x10\x4b\xda\x19\x77\x13\x5a\x88\x47\x05\xd5\x82\x27\x87\x63\x46\x37\x70\x78\xdf\x5c\x45\x18\xf4\x9a\x38\xad\x0b\x71\x39\xfa\x9d\x32\x9e\xc5\xc0\x1b\x48\xaf\x80\x73\x85\xfd\xd7\xc8\xae\x1a\xd4\x5e\x05\xe1\xb2\xde\xa3\x8a\x1a\xbf\xc4\x6b\x55\x6d\xec\xb0\x85\xdd\x8a\xdb\xe9\x42\x3c\x87\x84\xb4\xbf\x02\x80\xf2\xf9\x99\x48\x10\x9c\xf2\x17\xbe\x00\xa8\x8d\x3d\x80\xaa\x38\x9c\xd6\xd3\x69\x1c\x7b\x60\x03\xf8\x8c\x45\x1e\x0e\xc4\x07\xa7\x8c\x4f\x93\x71\x29\x8c\x3a\x88\x1c\x8a\x86\x2c\xce\x48\x80\x0f\xc4\xf1\xf1\xfa\xc9\x99\x7b\xfc\x68\xfd\x24\x1e\x72\xcd\x4e\x35\xb7\xb8\x05\xb4\x59\xdb\xcf\xa0\x97\x22\x46\xc3\x04\x92\x70\xd6\x8a\x9d\x1d\x07\x92\x0d\x83\xec\xe4\x15\xe4\x16\x73\xdf\x0f\x96\x98\x8c\x06\x36\x36\xec\xb1\xb4\xae\x41\x7b\x1c\x56\x36\x9c\xc4\xbc\xb4\xfb\xc1\xee\xf4\x5a\xfb\x40\x00\x41\x95\x72\x05\xff\xaf\x29\x59\xb5\x13\x88\x8c\x97\x1a\x22\xb9\xd6\x4e\xf4\xb1\x00\x1e\x46\x9d\xdd\x6e\x51\x17\xfb\x85\xe5\x11\xb8\x4b\x18\xca\x4e\xef\xb5\x9f\xad\xee\x40\xc7\x25\xed\x12\xd2\x77\xf3\x34\x41\x77\xd2\x40\x0f\xaa\x51\xc6\x77\xc7\x58\xdf\x41\x6a\x2f\xfe\x2c\xf6\xda\x8c\x3e\xc8\xf2\x3b\x65\x84\x1f\x8e\x42\x6e\x65\xa8\x76\x27\x5d\x3d\x1a\x9a\x31\xd5\xf2\x7a\x7f\xa9\x81\x95\x08\xf5\xf2\xae\xcc\xa0\x4a\xf9\x56\xfc\x10\x27\xf3\xc7\x15\x69\xbe\xa1\x54\x38\xde\x43\x7b\x74\x10\xc6\xe4\xd2\xb2\xb0\x43\x64\x42\x09\x50\x48\x58\x42\xd6\xa8\xb4\x30\x3a\xdd\xdc\xc2\x78\xad\x47\xef\x6d\x10\xb4\xbb\xb0\x18\x61\xc4\x62\x8b\x9f\x02\x14\xa8\x41\x00\x5b\xc8\xc3\xd5\x34\x1d\xa3\x0a\x8a\x05\x08\xbf\x5c\xf8\x87\x41\xfd\x98\x8a\xc7\xbd\x03\x25\x08\x05\x96\xce\xb6\xd5\x3b\xc8\xc4\x4b\x0d\xde\x7c\x7c\xaa\x36\xa4\x66\x8e\x73\x39\x94\x63\x01\xf9\x61\x87\xa8\xcf\xbd\x1e\x82\xc8\x35\x00\x0b\x06\xa5\x57\x93\xba\x92\x4e\x62\xde\x63\x5f\xb6\x38\x1d\xbc\xde\xda\xda\xed\x90\x79\xe2\xe6\x89\x4e\x99\xad\xdf\xa1\xd6\x31\x30\xee\x5e\x84\xf1\xf6\xe2\x7f\x82\xba\x5c\x36\x5e\x0d\x6e\x55\x19\x6b\x6a\x20\x47\xd9\x26\x7a\x63\xcd\x43\x24\x51\x2c\x89\xb1\xde\x97\x2e\x21\xb8\xe2\xb0\xde\x06\x3b\x6e\x77\xa4\xaa\xac\x70\xf7\xf8\x83\xad\x37\xb2\xf1\x70\xa1\xf5\xfe\x60\x1f\xd2\x47\x49\x0c\x67\xc0\x30\x06\x34\x98\x13\xba\x79\x4d\x39\xf3\x32\xca\x04\x32\x3e\xa8\xc6\xde\xa9\xe1\xc8\x73\xf1\x6b\x48\x15\x52\xf8\x54\x39\x83\x88\x65\x3c\x31\xbb\x68\xf1\x3b\x4a\x3d\x0d\xcf\x35\x32\xa4\x78\x7a\x4f\x33\xb3\x0e\x2e\xb4\xb0\x3f\xd9\xc9\xc4\xa0\x9f\xa8\x14\xbe\x99\x82\x8c\x0e\xd7\x18\x95\x5a\x55\xd5\xc7\xb0\xa8\x3f\x55\xb4\x53\x54\x36\xd5\x44\x45\x38\x87\x77\x14\x92\xcd\x08\xcf\x12\xd5\xbf\xab\x41\x6f\x8e\x08\x54\xd0\x88\x53\x1b\xa6\x5c\xaf\xf1\xd4\x4d\xac\xed\xbb\x9c\xb6\x53\xf2\x66\xec\xce\xc5\x01\x79\xde\x54\x26\x2a\xb2\x88\x1b\x16\x81\x52\xc0\x35\x79\xf5\x71\x6f\x5b\xd9\x7d\xaa\x8e\x70\x1d\xf8\x1f\xca\x55\x06\xae\x60\x6d\xb5\xb7\x2d\x16\x7a\x0d\x3f\xaa\xea\xe3\xc6\x0e\xfb\x4f\x55\xe0\xa7\xde\x4c\x44\xcf\xc0\x78\x51\x5a\x26\xfc\x40\xd6\xaf\xf9\x15\x73\xec\xf3\xf5\x82\x94\xfa\x4e\xa5\x9b\x66\xf8\x15\x3b\x7f\x73\xf3\xf2\x3d\xab\xd6\x6e\x5e\x8a\x5b\x45\xb8\x5f\x7a\xdf\xbb\x0f\xa0\x30\x46\xed\xef\x87\x77\x57\xd5\xb5\x3c\x06\x81\x10\x93\xe9\x03\x32\xde\x2b\xb9\xa7\x46\x86\x9f\x88\x22\x6c\x16\x4a\x0c\x3f\xed\x90\x5f\x95\x54\x20\x74\xfc\x5a\xc8\xc4\x48\xe4\xaa\x37\xea\xf0\xcb\x20\x4d\xc3\x85\x03\x37\xb8\x86\x04\x2c\xf9\xd4\xee\xf7\xda\xdf\x8c\xfb\xbd\x84\x8d\x81\xdf\xc2\x61\x02\x65\xbf\x56\xce\xa1\x1d\x00\x65\xef\x31\x81\xb2\x9f\xee\xac\x6e\xb2\xdc\x06\xbe\xab\xf7\x83\x52\x54\xeb\x73\xbe\x75\xab\x40\x02\x40\xf6\x14\x7f\x55\x51\xb1\xa2\xe8\x7a\xfc\xb7\xd9\x0d\xd4\x6f\x95\xec\xfa\x9d\x04\x19\x23\x03\x8b\x64\x2f\x64\x9a\x71\xaf\x06\xdd\x80\x72\x4e\xba\xdd\x0f\x0f\xeb\x1f\x73\x22\x58\xa0\x68\xad\xff\x16\x34\xe1\x37\x12\xc6\x93\xd8\x5c\xf7\xe5\xa6\x9d\x03\x46\x11\x50\x9e\x03\x42\x3b\x08\x28\x57\x62\x76\xfa\x77\x1e\x0b\x40\x15\xbe\x23\xbe\xb3\x00\x01\x02\x67\x82\x8a\xf5\x01\x5f\x12\x84\x4f\x3e\x06\xce\x5c\x89\x7a\x2f\x3f\x7f\xa9\xe0\xde\x2e\x94\x43\xcd\x7c\x2a\x44\xfa\x05\x89\xc7\x5b\x49\x26\x56\xbf\x55\xe3\x70\x0f\xf0\x87\x77\x57\xab\xdf\x2a\x6d\x9a\x6e\x6c\x4f\x36\xc4\x8d\x6b\xe7\x87\xc0\x76\x3d\x38\x73\x0f\x02\x4a\x73\x6b\xec\xc1\x44\xf8\x0f\xf8\x2d\xe0\xfb\x67\xb6\xf5\xa8\xb5\x21\x9d\x47\xb2\xfa\x10\xad\x6e\x03\x17\x03\xba\x8b\x55\x3a\x4f\x73\x7d\x46\xdc\xe5\xa0\x0f\x26\x8d\x53\x24\x74\x41\x44\x00\xd5\x8e\xdc\xab\x55\xb2\x4f\xa9\x03\x33\x5c\x07\x09\xdc\xe4\x22\x73\x60\x02\x98\x4a\x03\xbb\x0c\x10\x2b\xbc\x98\x9c\x97\x9b\x90\xa1\x93\xc5\xed\xb0\x5d\x28\xfd\x76\x7e\x69\x7a\xa2\xbc\x57\x72\xbf\x80\x20\x12\x98\x93\x05\x71\xee\xa1\x10\x1c\x3a\x13\x0a\x39\x2f\x17\xa0\x56\x69\x94\xe2\x80\xe7\x73\x93\x2b\x18\xe2\x38\x97\x5a\xab\x42\xca\xaa\xf7\xda\xf1\x64\xbd\xdf\x81\x86\x32\x67\x1d\xa2\xd2\xbb\x53\x4d\xe0\xaa\x79\xc9\x39\x90\x59\x43\x0a\x98\x14\xb0\xbe\x73\x55\xc1\x51\x3d\x80\x09\x52\xa6\x16\x23\x45\x25\x9d\x97\x7b\x79\xab\x84\x1b\x03\x6b\xb6\x93\x9e\xa4\x94\x72\xb2\x02\x97\x0c\xa8\xb0\xce\xd8\xf2\x19\x7a\x7b\x30\xe1\x78\xfb\x12\x7e\x00\xfb\x46\xd4\xb9\x1e\x75\x8e\x98\x90\x47\xa0\x53\x68\xa3\x8a\x4f\x7d\xd6\x70\xb7\xf6\x42\xdf\x29\x52\xf2\x45\xdd\x26\xe4\xad\xaa\x4e\x3a\x5f\x87\xf5\x88\xcd\x05\x71\xd6\xde\x85\xcd\x1a\xea\x0b\xb9\x62\x08\xab\x06\x6c\x66\x00\x03\x6a\xf5\x0c\xf5\x2f\x2c\xc5\x38\x45\x5d\x67\x0f\xaa\x3d\x17\x61\x15\x99\xd2\x08\x00\x28\x82\xec\x0e\xf2\xe8\x48\x82\x61\xba\x66\x0d\x8d\xd5\xaa\x4a\x3a\x42\xb7\xab\xc3\x81\x1b\x99\xf4\xbb\xc0\xc8\xf0\x0a\xb1\x9b\x74\xdd\x1d\xa0\x50\xd7\xf7\xb3\x38\x73\xd5\x88\xf7\x0b\x00\x7e\xcc\xd0\x80\x71\x0d\x9d\x44\x77\x19\x53\x44\x28\xce\x83\x28\x23\xb4\x7f\xe0\xc2\x3a\x1b\xf7\x28\x02\xad\xe9\x42\x22\xca\x6e\xad\x1d\xd7\x9d\x7a\x88\x92\xb1\xe6\x55\x1d\x55\x8d\x13\x1e\x38\x36\xeb\xae\xaa\x9c\xd7\x5d\x17\xc6\x98\xcd\xcd\x0a\x49\x15\x72\x61\xf3\xc1\x40\xb8\x9d\xee\x85\x85\xcb\xbc\x7c\x90\xd2\x82\xcd\x04\x41\x6f\x45\xab\x40\xf2\xb6\x83\xf0\x83\x34\x6e\xa3\xe0\x76\x73\x8f\xf7\x03\x2b\xaa\x3a\xc8\x95\x68\x5e\x76\xa2\x66\x54\x62\x40\xd5\xf9\xa9\x03\xb3\x93\x4d\x64\x59\x35\xda\x16\xc0\x15\x1a\xb4\x01\xc6\x34\x61\x72\xdc\x86\xb0\xc0\x66\x43\x00\xb7\xe9\xc5\x22\x59\x1c\x87\x4d\xa1\x81\xc3\xfa\x61\x35\x7d\xa1\xdf\x15\x9a\x6f\xd5\xc8\x20\x15\xfb\xe1\x3d\xe4\x30\xeb\x34\xdd\x12\xd5\xc7\xb0\xce\x3f\x55\x28\x3b\xd5\xf1\x8a\xf2\x29\xca\x52\xc8\x71\x43\x62\xf5\x9f\x56\x9b\x1a\xee\xdb\xfe\xc5\x6a\x03\x97\x73\x55\x61\x92\x32\x51\x0f\x92\xe1\xdc\x11\x6c\x65\xd6\x9d\x6e\xd8\x7a\xee\x58\x6d\x2c\xec\x1e\xd0\x1e\x3e\xe7\xdf\x95\xf3\x32\x10\x08\x32\xa8\x08\xbf\x0a\x75\x24\x16\x42\x5d\xf5\x73\xfe\x4d\xa9\x31\xa9\x1a\x4d\x4c\xf9\x40\x3f\xab\x2a\xf0\xd5\x2b\x20\xea\x41\x14\x80\xfb\xd9\x8c\x94\x87\x93\x3a\x6c\x6b\xce\x5b\x65\xf0\xbd\xf4\x5e\x0d\x06\xef\x52\x70\xcb\xe7\x45\x29\x3b\xa2\xc8\x28\x43\x18\x5b\xb6\x2a\xfc\x54\x25\xdb\x43\x36\x3b\x5c\xba\x46\x8a\xc3\x8f\x37\xae\x15\xed\x69\x47\x6c\xf9\xbf\xaa\xa3\xab\x9c\x6a\xc6\x01\x87\xf5\x86\x7e\x2e\xab\x67\x49\x5f\x3c\x31\xad\x4c\x97\x01\xae\xb4\x02\x71\x15\xad\xb1\x0b\xf1\x0c\x7f\xb0\x82\xaa\xea\x61\xfa\x32\xfb\x49\x9a\xcf\xd8\x15\x32\x9f\xcd\x15\x53\xa5\x96\x46\x3b\x81\x48\x80\x51\xe1\xeb\x3a\x38\x96\x37\x76\x10\xd2\x1c\xd3\xc5\x9f\xea\xe0\xe0\x33\x99\x19\x80\x3b\x87\x72\x01\xec\xa0\xd6\x7c\x37\x9c\x8c\x6a\xf6\xb2\x55\xe2\x4e\xcb\xa8\xd8\xca\xd8\xa5\x78\x9e\xb3\xb2\xb4\xd0\x21\x80\x18\x84\x8a\x6c\xe6\x96\x78\x9a\xbd\x65\x8d\x82\xdf\x29\x8d\x57\xb3\x06\x38\xa9\xcd\xd8\x75\x7c\x26\x3e\x1f\xbb\x0e\x4d\xc4\xe6\x66\xca\xa1\x0a\xba\xa2\xbe\xa2\x9f\xd5\xd8\xb7\x41\x68\x4d\x63\xf9\x01\x12\xe2\x58\x96\xf9\x99\x30\x0a\xa3\xca\xc5\xa2\x4a\x13\xc1\xdb\x4c\x3a\xed\x8e\x2b\xde\xcd\x0b\x06\xc9\xb4\xb1\xdb\x29\x48\xd2\xfa\x01\xa5\xa2\x8e\xc3\x44\xa1\x0d\x10\x0c\xed\x41\x1e\xc5\xce\x1e\x44\xa7\xcd\xad\xa3\x99\x0a\xe3\x94\x0b\xe6\xa0\xa8\xf5\xda\x8c\x8a\x44\xa5\xf0\x73\x6e\xfe\x4a\x36\x03\x64\x41\xb0\x3e\xb2\x36\x0c\x6d\x0c\x68\x03\x88\xf5\x51\x80\x34\x78\xda\x58\x61\x6a\xa5\xc0\x46\x0a\x7c\xf9\x0e\x36\x12\x89\xae\x7d\x70\x4a\x3c\x45\xbb\x09\xda\x63\xcd\xce\x5a\x47\x37\x10\x89\xfa\x85\x34\x50\x06\x12\xf1\xa3\x69\x49\x78\x70\xd6\x2e\xd9\x7e\x03\xf6\x39\xed\xa0\x9a\xae\x14\x13\x34\x6d\xa8\xa7\x74\xd5\x78\xc9\x38\xd1\x3e\x83\xfb\x04\x34\xa6\xd6\x7b\x14\x58\x3f\xb0\xf5\x06\x4c\x78\x94\x45\x20\x7b\x55\xb6\x67\xba\x4a\xa8\x5e\xbe\xc2\xfb\xc2\x62\xe1\xa5\x90\xdf\x5d\xe3\xf4\x47\xba\x64\xbb\x82\x5d\xe3\x7e\xc4\xfc\x30\x78\x59\xfe\x1b\x30\x3d\x88\x7a\x95\xb0\xc7\xea\x09\x08\xa9\x22\x0a\xc8\x45\x86\x9b\xeb\x3a\xc9\x6c\x4f\x5a\x3f\xdb\x31\x5c\xee\x20\x5d\xd1\x71\x5a\xe3\x24\x3a\x49\xb8\x2b\x2a\x88\x52\xa6\x3f\x4f\x4d\xa3\xda\xfe\x51\x5a\xc2\xf8\x56\x15\x8a\x29\x2e\x4a\x27\x97\x48\x31\x95\x63\x3b\xf9\x98\x4f\xa6\xf2\x05\x61\x55\x6c\x7c\x96\x93\xde\x7e\xd0\xa0\x13\x29\x49\xf0\x8c\xe8\x16\x04\x16\x46\xc1\x82\x29\x55\xa2\xab\xab\x8a\x51\x85\x63\x0b\x7e\x71\x4a\xd4\xba\xdd\x28\xb0\x27\xa6\x64\xde\x01\x9c\x8b\x0b\x3f\xb6\xb1\x53\x44\x0e\xb1\xaf\xcf\x28\x61\x92\xcf\x9d\xc1\x6c\xe0\xce\xb5\x5b\xea\xcd\x10\xd8\x77\x15\x4f\x0c\x6d\xd0\x92\x2d\x1a\x24\x14\x64\x49\x3c\x03\x3a\x25\x0e\x12\x2f\x81\x98\x4a\xfd\x65\x5a\x7b\x5a\x40\xbf\x96\xd7\x47\xd8\xb7\x72\xfb\x7c\x57\xc9\xb6\x85\xc5\x9d\x0c\x3b\x5a\x20\x1c\xa5\x0a\x32\x40\xe5\x10\x68\xf8\x11\x53\xeb\xe2\x72\xcb\xa1\x9e\xe9\xeb\x2f\xb4\x02\xfb\xf1\xdf\x70\x97\x55\x54\x95\xee\xb2\x62\x23\x27\x5b\x6b\xd6\xcb\xf9\x1e\x93\x6d\x0b\x9c\x10\xad\xe5\x8c\x9f\xa1\xd5\x1c\xd9\x9a\x50\x0b\x8a\x2f\x61\x78\xfe\x55\x1d\x81\xf9\xa1\x95\x00\x67\x92\x76\x42\x82\x2d\x2b\x18\xc0\xa3\x2c\xe3\x66\xa2\x72\x39\xe7\x97\x70\xe9\xe4\x14\xc1\x02\x63\x28\xcd\x31\x30\xfa\x60\x31\x8c\x4c\xb4\xb7\x62\x2b\xa3\x89\x50\x3c\xd0\x4a\x56\x5c\xc3\x25\xdb\x4e\x6f\x77\xdd\x51\xe8\x7d\x6f\x07\x0f\x2b\x89\x4d\x1d\x92\xf0\x1a\xbe\x06\xd5\xd8\xad\xd1\xbf\xc3\xc0\xee\xd1\xd4\x39\x5e\x9e\x3c\x76\x7e\xb0\x66\xfb\xe4\x19\x58\x42\xdd\x06\xc2\xb3\xb3\x87\xbf\x3c\x7e\x44\xe9\xe2\x29\x4c\xa1\x1d\xbd\x78\xa1\xfd\xcb\x71\xfd\xc0\x89\xed\xa8\x5b\x38\x6b\x1f\xcb\xcc\x37\x83\xac\xa7\xd0\x0e\xfd\x60\xe2\xb0\x80\xa7\x86\x1d\x84\xb3\xdd\x9d\x9a\x14\xb1\xfb\x3d\x4e\xef\xba\x53\x7b\x84\x84\xf6\x83\xc1\x95\x32\x30\x72\x6a\xa0\xf1\xb9\xb9\x79\xb9\x8a\x4b\x3c\xcd\x0f\x4d\x1b\x33\xa8\x85\x96\x85\x98\xc3\x00\xdc\x90\xce\x34\x9d\x40\xa0\x62\xe1\x52\xc0\x78\xcc\x4b\xc1\x3c\xba\xc0\xac\xcc\xf4\x3b\x20\xb5\x04\x14\x5c\x5c\x5c\x84\x76\x20\x03\x16\xd2\x9a\x99\x96\x96\x16\x56\xb6\x78\xc3\xa1\xc3\xe2\x34\x30\xee\xb1\x79\xb0\x5c\x27\xfb\x9b\x28\x1a\xf6\x9d\xe8\x19\x77\x20\xa3\x68\x34\x22\x89\xa6\x4d\x61\x0a\xaa\xa6\x90\xa6\x71\x2b\x72\x6a\x86\xa6\xa5\x48\xd1\x70\x41\x2a\x07\xf4\xfa\x2b\xa9\xd9\xac\xde\xd4\x71\xae\xee\x2b\x28\x1a\xf4\xe9\x12\x86\xc3\x1a\x54\x9c\xd0\x44\x5d\x49\x34\xc4\x83\x0c\x63\xeb\x4c\xcc\x7b\x63\xe9\x0a\x58\x70\x22\xcc\x89\xf3\x81\x55\xc9\xb7\x72\x68\x04\x18\xed\xa3\xd1\x21\x68\x5e\xfe\x37\xd1\xca\xa3\xab\xbc\xbd\x55\x66\xa1\x08\xa4\x9f\x2a\x54\x7d\xe5\xa5\x5e\x76\x6b\x15\x6a\x18\x1d\xca\x9a\x7e\x74\x3f\xe7\x79\xe8\x4b\x57\x80\xdb\xcd\x26\xa4\x6d\x36\x55\x71\x6f\x46\x96\x75\x68\x86\x99\x67\xb1\xdb\x41\xb4\x32\xcd\x33\xc1\x32\xa7\xb8\x2e\x73\x6c\xa3\x03\x36\xf5\xb2\xdc\xb3\x61\xd7\x12\x41\xca\x6e\xd4\x70\xe7\x06\xaa\x25\x9c\xdc\x28\xd1\x77\xb2\x51\x2b\x76\xb8\x01\x0b\x5b\x20\x6e\xe1\x70\xe6\x9b\x3d\x8d\xf7\xe3\x9d\x75\x6a\x4a\xec\x26\x8a\xc9\x4c\x4e\x5c\xe5\x4d\xdf\x79\xdf\xa3\x21\x47\xee\x13\x90\x58\x06\x32\x17\x00\xf6\x47\x74\xd6\x6c\xd5\x10\xed\x44\x43\x93\xfa\x4e\x92\x95\x29\xec\xde\xd0\xdd\xc8\x0b\x45\x2b\x05\x36\x09\x6d\xa1\x48\x1a\x89\x8f\x3f\x7d\x72\x67\x1f\xff\xf4\xc9\x7d\xff\xe4\x5a\x0d\x0e\x8c\xf0\x2f\xb1\x1b\xef\xc3\xf2\x80\x11\x91\x8e\x6e\xb9\x07\xd5\x86\x0e\xc9\xee\x5c\xa8\xd5\x76\x25\x1e\x87\x21\x78\x72\xf6\xf1\xcf\x9f\xdc\xe3\x47\xf0\x7b\x35\x9f\xcc\x64\xc5\x8f\x73\xfb\x75\x6b\xa9\x91\xa6\xfe\xdb\xc4\x33\xec\x0b\xa3\x0a\x36\x7d\x61\xa2\xc2\xc1\x0b\x4c\x7d\xb9\x04\xf9\x56\xd6\xa9\x66\x50\x1e\xe4\x78\xd4\x7f\xa2\x8c\x0b\xa9\x45\x89\x50\xd1\xfc\x26\xf7\xfd\x4e\x19\x2a\xc7\xa9\x45\x29\xd2\x0f\xf2\xed\x69\xb5\x70\xaf\x5b\x62\x4b\x8b\x69\xa2\x91\x8d\x46\x03\x91\x11\x89\x96\x1e\xdf\x55\xc5\xdd\x74\xd8\xc1\x5f\x85\x75\x51\x43\x5f\xa2\x37\xc4\xb3\x1a\xf5\xdd\xc2\x64\xf2\xa5\xcb\x7c\x32\xe5\x49\xf5\xe5\x1c\x4b\x22\xa0\xa7\x11\x80\x05\x85\x41\x99\x60\x4a\xac\x27\xe4\xf5\xd4\x3d\xbd\x8b\x6b\xef\xe4\xa2\x2b\x2f\xf2\xdd\x3d\xa8\x88\x74\x16\x77\xf0\xe4\x15\x10\xe8\x67\x74\x08\xf4\x2a\x70\x32\x72\xd0\xdd\xf1\x5b\xc9\x82\xf8\x55\x36\xbb\x92\x26\x01\xe5\x61\xf3\x70\x3a\x23\x1a\x75\x2e\x1e\xaf\x9f\xd0\xa4\xdd\x2a\xd5\x13\x4b\x86\x4d\x9a\x10\xb0\xc7\x8f\xd6\xe5\xb6\x1c\x14\xfa\xf0\x79\x35\xa7\x98\xef\x62\xde\xbd\x03\x73\x02\x41\x5c\x1d\x19\x9a\x92\xc2\x9e\x58\x16\xa7\x31\x96\x3c\xc6\x04\x59\x3c\x75\xb9\xf4\xf4\xdc\x9d\x1f\x1f\xc9\xd7\x95\x8e\x93\xaf\x22\x47\x5c\x78\xc9\x4e\x2c\x6a\x0f\x3b\x75\xa7\x3a\x64\x3c\xda\x40\x4c\xc0\xd0\x62\x13\xe8\x44\x94\x6d\xfd\xa9\xd5\x7e\x0f\xf7\xb1\xd0\x8c\xaf\xdd\x3e\xb1\xde\x72\x54\x58\x76\xc0\x85\x59\x23\x1f\x10\xe5\x87\xc5\x73\xc0\x55\x71\x82\x02\xdb\xca\x45\x5e\xf0\x2c\x87\xc9\x01\x40\xe4\x36\xe2\x6e\xc1\xc2\x49\xe9\x9f\x26\x0a\xb8\x7c\xf2\xb3\x82\x75\xed\x6d\xdc\x29\x3b\x34\x70\x16\x97\xd7\xaf\xdc\xaa\x8a\x15\x32\x52\xd8\x25\xd8\x84\x03\x6a\xfc\xc1\x0c\xba\xeb\x66\x5b\x8d\xf5\x67\x58\x9c\xb8\x5b\x68\x13\xf2\xb7\xb1\x53\xb3\x0e\x61\x67\xca\x7c\x1c\x77\xe5\xb2\x15\x80\xb5\x41\x4b\xa6\x82\x5a\xec\xea\x77\xe2\x75\xba\x85\x0b\x33\xdb\x1f\x83\xe8\x13\xdd\x31\xce\xe9\x80\x15\x07\x10\x5e\x26\x6e\x20\xda\x23\xc5\x17\x81\x7f\x1d\x22\xf3\xcc\x0d\x26\xf6\x39\x9f\xca\x9c\x87\x5e\x9c\xcc\xc4\x51\x2f\x16\x5b\x62\xab\x7b\xc6\x53\xf6\xf9\x4b\x4c\xb6\xdd\x94\xf4\xed\xe4\x22\xcf\x7b\x95\x2d\xef\xeb\xc5\x6a\xe3\xb6\xc7\xaa\x27\xcb\x5b\xa0\x0c\x88\xa6\xb2\xc0\x24\xa1\x62\x11\x57\x44\xc6\x2e\x48\x27\x0e\xaa\xeb\xf2\xd5\x81\x57\x3c\x2e\x2e\x92\x89\xdc\x54\xc8\x4c\x6e\x55\xc1\x85\xc0\xca\x04\xd9\x17\x1d\x71\xa2\x92\x8a\x6e\xb1\x60\x00\xcc\xb1\xb8\xa6\x72\x2b\x2c\x06\x97\x5f\x91\x1c\x5d\xd1\x55\x58\x16\xd5\x21\x83\xca\x7c\x7d\xd0\xff\xb4\x3c\x57\x70\xec\xb3\x7b\x23\xf0\x07\x50\x72\xef\x88\x00\x01\x8b\xaa\x36\x74\xb3\x9c\x55\x72\xcf\x94\xe0\x15\x08\x36\x80\x1b\x98\xa7\x4d\x9a\x9e\xae\x17\x0b\xa0\x2f\xb4\x7c\x72\x93\x5e\xb6\xf6\x9e\xc6\xe5\x55\x14\x3a\x14\x24\x06\xd0\xd7\x0c\x2f\xc8\xa4\x13\x22\x48\x4b\x2e\xd9\xc6\xd1\x7a\x2f\x2c\x89\x09\x28\x53\xe5\xab\xc4\x9a\x33\xad\x4f\x77\x97\x8c\xac\x57\xc3\x5e\x1a\xb0\xdc\xc5\x7b\x16\xd6\x4f\x3c\xbd\x7c\xf3\xe6\xed\xfb\xa4\x96\x08\xc4\xcf\xb4\xc0\x6b\xb1\xc3\xd3\xac\x5d\xec\xf6\x14\x77\x6d\x09\x91\x1c\xaf\xa8\xc4\x29\xb8\x5c\xf6\xcb\x8c\x9c\xb7\x16\xb4\x36\x70\x5f\xcd\xd2\x6b\xd1\xfe\xf6\xe4\x0a\xf9\x18\x86\xf8\x53\xc5\x77\xff\x6f\xc3\xff\x2a\x37\x9f\xc8\x2c\x5a\x80\xde\x26\xc3\x97\xe4\x91\x2f\xb6\xd6\xb6\x33\x73\x0a\x10\x4b\x47\x70\x3a\x6b\xec\xbe\xb7\xc0\xf9\x6c\x04\x58\xbd\x9e\x87\xdd\x65\x07\xa0\x92\x20\xd2\x18\xfd\xb7\x11\x14\x52\x60\xa4\xba\xaa\xee\xb4\xd3\x6b\xdd\xa1\x08\xfd\xef\xf1\x03\xd3\xc3\xaf\x89\x4f\x76\x56\xb9\x76\xe2\xb1\xeb\xa5\x11\x4d\x27\x9d\xbb\xf8\x7e\xd4\x22\xf0\xcd\x5e\x7d\xf6\xdf\x3f\xb9\x1e\xc0\x3e\xf2\xf1\xa3\x00\xf1\x64\x86\xae\xde\xd8\xa1\xc1\xdb\xd6\x68\x09\x0e\xc4\x8a\xd2\xc3\x36\x35\xc0\xc5\x64\x5b\x15\x07\xfe\x0f\xd4\xb9\xb1\xc3\x6d\xea\xc7\x0f\x74\xc1\x60\x37\x48\xb0\xef\x64\x37\x96\xb7\x4d\xa1\xf6\x50\xc6\xfd\x58\x81\xc3\x79\x2a\x0b\x4e\x02\x10\x6a\x28\x64\x68\xb3\xfd\x0b\x0c\x9a\xbf\x3f\x88\xc9\x4b\xd5\xf5\x41\x3c\xfc\xae\x82\x96\xd0\xad\xfc\x34\x6a\x0d\xe4\xb1\x37\x76\xc8\x03\x97\x6c\x48\x5d\x98\x8d\x2c\xb6\x85\xec\x58\x32\xcb\x66\x33\x90\x53\xe8\x44\x7e\x93\x7d\x24\x83\xaa\x78\x6c\xb9\x66\xd0\xe0\x51\x8e\xe9\x9d\x84\x0b\xee\x18\xb6\x08\x12\xb7\xda\xeb\xad\xb1\x43\x36\x0c\x37\x60\x32\x24\x56\x31\x4b\x70\x20\x24\x57\x75\xba\x51\xc6\x01\xb5\xc3\x5f\x9c\x32\x2b\x2e\x05\xc3\xc2\xe5\x63\x38\x30\x68\x2b\x84\x1f\xf4\xbd\x50\x8a\x00\xb9\xca\x4a\x8e\xde\xd6\xda\x68\x0f\xbe\x44\xd1\xf5\xcc\x4f\xd6\x2b\x9e\x50\x6c\xec\x84\x7e\xd3\x48\xfd\x09\x0f\xb9\x03\xd1\xf4\x90\x1f\x50\x36\x41\xe4\xbd\x4c\x76\x0e\x30\x7e\x90\x20\xd0\x54\x94\x62\x1e\xd5\xfd\x30\x1a\xbc\x6b\x1f\x8d\x2a\x12\x93\x60\x84\x7c\x80\x39\x52\x74\x8d\x87\x7e\x90\xcd\x6d\x20\x2e\x83\xda\xa8\x41\x99\x06\x1c\x16\xa4\xcf\x14\x19\x68\x52\x61\x0d\x1d\x04\xa1\x18\x23\xd7\x41\x64\xbd\x03\xbf\x19\xf4\xbf\x12\xaf\x38\xe5\x87\x9d\x1d\x87\x1f\x19\x90\x55\xe5\x11\x8e\x2e\x7c\x26\xf9\xdc\x4e\x52\x28\x90\xd5\xa1\x30\x2a\x1c\x0a\x72\x40\x87\xee\x4c\xc7\xe1\xd8\x2d\x36\xba\x20\x12\x3e\x50\xdd\xb9\xa3\x69\x92\xf2\xee\x06\xbe\xaa\x83\xf4\xcd\x0e\x6d\x30\xfe\x4a\x3f\xc1\x04\x63\x2b\x7f\xc7\xd4\x9b\xf8\x01\x5b\xc0\xd1\xa6\x70\x69\x01\xd3\xca\xcd\x42\x39\xa4\xc4\xc2\x98\xe5\xb8\x12\xaf\xe5\x67\xbd\x1f\xf7\xe2\x9f\x7f\xfa\x53\x66\xa3\x49\x8e\x00\xab\x39\x4e\xf2\x10\x00\x5b\x08\x72\x61\x4d\xc5\xc8\xa4\x63\x50\xb2\xd9\x91\xdb\x8a\xdd\xd4\x18\x44\x06\x58\xc9\xf7\xd1\x28\x2d\x90\x34\x80\x53\xad\xd8\x53\x1b\x22\x20\x14\x0d\x2d\x3d\x2b\x8d\x4d\x56\xcb\x26\x23\x53\x9b\xc7\x6f\xb7\x1c\x99\x62\xb8\xdf\x80\xc4\x28\xd5\xd6\x41\x54\x62\xba\x57\x58\x50\x57\x14\xb3\x8b\x83\x1e\xc5\xa0\x5d\x18\xf5\x28\xcf\x3d\x7d\x84\x44\xd7\xe9\x92\xaa\x83\x1f\xe4\xba\x1b\xd5\xf7\x4f\x70\x21\x31\x49\x67\xac\xb4\x45\x5f\x53\xd8\xb0\x6c\x8f\x12\xc4\x0a\xe9\x76\x5a\xef\x4f\x21\x70\x48\x5a\xee\x0b\x50\xc5\xa9\x4f\xe2\x96\xcc\x14\x8d\x8f\x5e\xbc\x7a\x0f\x76\xb8\xf7\x14\xaf\xf1\x6e\xa6\x66\x37\xb6\xff\xc0\x50\x58\x10\xe3\x23\xbb\x8e\xe5\x78\x67\x32\x1f\x8c\xf5\x11\xe3\x36\x70\xfc\x96\x5e\x86\xa5\xc9\x75\x05\x3e\x43\x3b\x87\x42\x87\xd1\x30\x9f\x05\x1f\x9d\xb0\x63\x1b\x08\x59\xb9\xb0\x18\x5b\x72\x7b\x6d\x64\xc7\x3e\xaf\xaf\x30\x91\x0a\x86\x44\xb8\x78\x2a\xad\xb6\xd8\x45\x47\xe6\xe1\x7e\x18\x6d\x34\xd0\x4b\xab\x21\xb7\xcd\x23\xaa\x40\x67\x1c\x05\x76\xb3\x9b\x0a\x8f\x29\x4e\xa7\x43\x2b\x7c\x55\x41\x02\xac\x3b\x6d\x6e\x81\xb9\xeb\x8f\x29\x21\xe3\x65\x9f\xda\x5e\xab\xf6\xbb\x2c\x8f\x95\x2b\xd7\x30\xfb\xff\xef\xff\xfd\xff\x3c\x7c\x1a\xda\xfd\xd4\x0f\xdd\xc3\xa7\x2c\x59\x06\x78\x1c\x47\x44\x20\xde\xfe\x6b\x35\x9a\x03\xd9\xcb\x7e\xc0\x5f\x15\x7f\x03\x95\xaa\x46\xe3\xc8\x04\x03\x7e\x54\xf4\x15\x88\x55\x45\x01\xe9\x02\x95\xaa\x2a\x13\x0f\xd9\x37\xb6\x38\x67\xff\x36\xea\xe6\xb6\xc6\x0b\xb5\x0b\xf1\x6f\xe1\x4b\x40\x90\x33\x62\x35\xc2\xa9\x15\x8f\x20\x58\xb4\x93\x73\x2c\xf7\x5a\x05\xba\x45\xde\xf7\xe9\xc8\x92\x25\xeb\x74\xe4\x43\x83\x01\x3b\x6d\x54\xd5\x8f\x6e\x87\x32\x1c\xd7\x76\x3d\xba\x1d\x84\x70\xf9\x8c\x21\x82\x72\x0c\x30\x35\x33\x1c\x6b\x39\xa8\x7a\x1f\xbd\x1c\xa6\xbb\x3b\x2e\x1c\x72\xa4\x4b\x57\x72\x47\xe5\x57\x55\x85\x47\x30\xba\x39\xb8\x2a\x9e\xaa\x74\x9a\xfa\x41\x01\xd2\x41\xa9\x00\xe9\xd5\xc0\x06\x86\xd2\xb4\xb5\x97\x5b\x2c\x19\x58\x1f\x2a\x6a\x07\xe1\xe5\x96\x10\x01\xe6\x5f\xe8\x67\xe5\x25\x98\xa3\xbd\x97\xdb\x79\x74\xbc\x7e\xec\xba\x79\x0c\xbd\x4e\xae\x15\x24\x5f\xc1\x8f\x6a\x1f\x1a\xe9\xad\x51\x78\x7a\xf2\x47\xd5\x80\xf3\x86\x8b\x6e\x1c\xae\xda\x6a\x66\x11\xca\x36\x50\xf0\x03\xd4\x1d\xe2\x4f\x18\x82\x7a\x90\x87\x90\x26\x0f\xf8\xb9\xd3\x8e\x62\x2d\xbe\xc4\x5f\x98\x8c\xf7\x36\x00\x0a\x97\x35\x11\x1e\x24\x10\xda\x23\xd7\xfc\x1b\xb3\xbc\x0d\x3c\xdd\x90\x66\x87\xcd\x79\xbc\xb5\x02\x33\x90\xa9\x76\x3b\x7b\x30\xd5\x9d\x6e\x95\x85\x33\x83\xe2\x31\x60\xb4\xc9\xf5\x60\x0f\x8e\x99\xce\x30\xda\xf8\x19\xa6\xd7\x3c\x48\xb1\x1b\x5e\xbe\x7f\x7d\xf5\xcf\x02\x70\x84\x79\x58\x55\x71\x26\x56\xf6\x4e\x0d\x14\x34\xe4\x2d\xfd\x4c\x99\xe4\xae\x9a\x0d\x19\x98\x6a\xaa\x34\x72\x11\xd4\x79\xd9\x15\x90\x37\x21\x61\x01\x10\x23\x1a\x5e\x76\xdd\x42\x1e\x19\x22\xd5\xeb\x63\x34\xa5\x6a\x05\x5c\xef\x04\x12\x0c\x57\x3c\x09\x98\x4d\x6e\xa6\xac\x1f\xc9\x10\x13\x0e\xb0\x52\x6d\x58\xfa\x2b\x88\x4f\x89\x16\x76\x6f\xd4\x01\xd9\x5b\xca\x42\xbb\xab\x3a\xda\xdf\x81\xff\x52\x0e\x10\xfe\x71\xf6\xaf\xad\xf6\x45\x66\x3f\x28\x58\x07\xd8\x2c\x87\x24\x0e\x46\x16\x1b\xe4\x18\x10\x45\x83\x1a\x90\x19\x6b\xea\x70\xa4\xd6\xbc\xe1\x9e\xa2\xdc\x10\x32\x85\xb1\xe6\x21\x9c\xb7\x90\x59\x34\x02\x48\x51\xde\x12\xcf\x4b\x88\xc1\xf6\xa3\xf3\xf5\x5a\xd5\xd6\xd4\x32\x8d\xcd\x7f\xb0\xdd\xf0\x1a\x5c\xd1\x24\xef\xcf\x70\xf0\xc9\x5b\xf4\x5e\x18\x6c\x10\x54\x05\xf7\x83\x43\xc8\xe5\xc8\x41\xf2\xc1\x30\x8f\xd0\x8f\x1c\x33\xd0\xda\x29\x83\x4f\x21\x21\x03\x2c\x9b\xd5\xe7\xf8\x58\x71\x96\xf5\x2a\xd7\xdb\xcd\xfa\x15\xa8\x56\x0d\x11\xc1\x48\xfd\x9b\x37\x00\x48\x1a\x86\x0b\x4b\x2a\x9a\x6f\xea\x1d\xda\xac\x42\x93\xd2\x51\x06\x1e\x5f\xa5\x59\xc0\xf2\x35\x39\x2f\xb4\xc0\xec\x81\xa3\x37\x2f\x37\xf2\x82\x18\xa0\xb2\xd5\x6a\x95\xd7\x17\xd5\x09\xa0\xb5\x0b\xdc\x7a\x3a\xc4\xcf\x31\x84\x17\x70\x73\xda\xe3\xdd\x28\x9c\x9e\x8f\x56\x01\x96\x55\x97\x79\x81\xad\x65\xbd\xd4\x5a\x6d\x35\x06\xfb\x04\xa1\x5a\x51\x90\x91\x84\x64\x2d\x9b\x5b\xd7\x4b\x88\xf9\x88\xed\x81\xf3\xd9\x0e\xd9\x7a\x6d\x54\x57\x83\x31\xb6\xb8\x10\xf8\x19\x33\x81\xb2\x66\x8b\x9e\x3c\xe6\x26\x6b\x5e\xb6\x6d\xed\xf7\x3d\x5b\x39\x3d\x38\x73\x8f\x1e\x73\xb7\x9f\x3c\xc8\xa0\x12\xc0\x83\xb4\x2d\x5b\x0c\x40\x4b\xb6\x95\x79\xde\xd4\x34\x39\xcf\xa3\xa6\xd1\x21\x18\x83\x1c\xb7\xe0\xa3\xce\xd1\xdb\x84\xfa\xec\x95\x69\x55\x2b\x32\x19\x23\x9b\x1b\x42\x82\x43\xdb\x1d\x6b\x6f\x71\x95\x26\x6a\x83\xfd\x65\x00\x1e\x76\x52\x95\x31\xdb\x8c\xe0\x0f\x43\x77\xbf\x07\xb7\xf4\xa8\x3a\x83\x8c\x54\x5d\x62\x20\x52\x0d\xcc\x3a\xb0\xfa\xcd\x44\x8f\xc7\x84\x67\x03\xe1\xdc\xc0\x01\x06\xda\x03\xf6\x02\x18\xd4\x53\x84\x53\x94\x3d\xf4\x57\x39\x1d\x64\xaf\x00\xb0\x82\x26\x96\xa8\xf4\xa6\xcc\x47\x62\x62\xa9\x3b\x5d\xbc\x44\xd6\xd6\x0a\x83\x72\xd2\x8e\x01\x61\x66\x16\x7f\x93\xca\x32\xd3\x80\x0a\xe9\xa4\xb6\x46\x92\x8d\x9b\xad\xd4\x56\xc7\x00\xb2\xb9\xde\x84\xd7\x02\x2f\xff\x5a\xbb\x5a\x46\xea\x68\x3c\xab\x4e\x49\x12\xee\x25\x19\x8e\x62\xf4\x18\x89\x27\xef\x84\x71\xbe\xaf\x22\xa0\x0f\x50\x87\x3b\xee\xe9\x74\x8f\x91\x58\x59\x60\x93\x82\x33\xf9\x8e\x88\x86\x00\xbc\x7b\x35\x07\x63\x00\xeb\x69\xb5\x16\x84\x7a\x36\xaa\x50\x4d\x6a\x55\xaa\xa8\x90\x33\x73\xd6\xf0\xeb\xbb\x40\xd4\xb8\x36\xb6\x46\x45\x46\x76\x71\x50\x74\x87\x4d\x37\x98\x7c\x4f\x34\x1f\x51\xc7\x70\xaa\x22\xb2\xa8\xad\x0f\xbb\xac\x5a\x26\xa9\x33\x5b\x30\xb6\xbf\x75\xda\x34\x2a\x45\xa7\x55\x2d\xd7\xbf\xba\x5f\xa5\x97\x42\x10\x80\xdd\x07\xdd\x40\x1d\xc2\x2c\xc0\xd1\x50\x54\x62\x87\xb8\xad\x90\x1c\xf2\xfe\xd9\x4a\x6d\xd2\xf6\xf2\x16\x7c\x91\xf0\x54\xf1\xbb\xec\x04\x29\x7b\x3a\x5b\xca\x97\x38\x8c\xa0\xe0\x4a\x53\xf6\xf5\x8b\xda\x58\xa6\xad\x81\xf4\x04\x5e\x10\x67\x27\x48\xae\x68\x4c\x93\x9d\x64\x21\x3b\xb5\x07\x62\x4f\xda\x9a\x2c\xc2\x69\x3b\xa4\x48\x50\x98\xfe\x88\x8c\x6a\xd2\x64\x43\x53\xd1\x0b\x35\x48\x86\x13\x6c\x74\x2c\xce\xb0\x11\x21\xfe\x12\x9a\x70\x0e\xb8\x71\xdd\xea\x81\x48\x31\x7e\x90\xb0\x9a\x88\x0d\xb9\xb0\x41\xf3\x23\x53\xe6\x26\xed\x8f\xfc\x99\x63\x5b\xd7\x13\xb5\xe6\x38\xa0\x13\x7a\x28\x19\xbc\x88\xa0\x62\xa1\x81\x09\x7f\xe2\xf8\x89\xd0\x33\xe3\x5f\xc2\xe5\x42\x06\xe7\x4c\x42\x1b\xd1\xca\x4a\xf9\x1b\x0d\x92\xe1\x73\x6d\xda\x98\x26\x41\x8f\x13\x5d\xe2\x63\x7a\x92\xe4\xc8\x73\x3d\xe6\xd0\xd9\xf8\x0c\xb4\xa4\x94\xc6\x11\xad\xde\x86\xff\x31\xd5\xa8\x03\x29\xca\x0f\x6a\x88\x11\x9f\x30\xee\x7d\x20\xfb\x20\x73\x65\xc9\xab\xa9\x9c\x95\x65\x05\x92\x11\x12\x51\x88\x86\xfc\x3c\xbb\xe9\x94\x1c\xea\x58\xfe\x69\xf8\x14\xdd\x0c\x4b\x14\xdc\x72\xb9\x6d\x52\x4d\x0e\xf3\xc6\x2e\x83\x61\x75\x39\x24\xd6\xb8\x5f\x02\xb6\xbd\x32\x05\xec\xdb\x5e\x99\x5c\x6c\x2c\x10\x5b\xa7\xda\x09\x66\xb8\xc5\x59\x86\x97\x0e\x22\x26\xc2\x3d\x16\xfd\x9c\xb7\x33\x03\xc2\x66\xca\x05\x50\x63\x73\xb8\x37\x76\x06\x44\xfb\x36\xb2\x07\xd3\xd9\x4b\xf3\xa3\x0e\xb3\x09\xc2\xcc\x1a\x2c\x6b\x62\xfc\x33\x00\x8a\xa7\x7e\x51\x4d\x44\x46\x95\x15\xf8\x10\x57\xbc\x65\x58\xc5\x1b\xd5\xb0\xbb\x64\xe0\x32\x5b\xb5\x01\xc7\x40\xa7\x40\xa7\x5a\x2e\x84\x69\x71\x6d\x36\x36\xa7\x71\x41\x8e\x95\xe6\x48\xa5\x40\x3f\x11\x8d\x19\x31\x0a\x0f\xe9\x50\xbe\x8f\x3d\xfd\x9e\x83\xf2\xc8\xb5\x45\x1f\x4d\x1a\x2d\x74\xe4\xc4\x40\xe8\xd3\x86\x51\x00\x9f\x13\xad\x5a\xb8\x20\x81\x21\x71\xca\x9f\x2a\x32\x3a\x72\xb0\x42\xe2\xfe\x45\x78\x26\xb1\xb9\x10\x9a\xc8\x1d\xd0\x2a\xc4\x11\x5f\xb6\x88\xd4\x16\x43\xf0\x21\x5a\x58\xdf\x5e\xae\xc5\x85\x38\x6b\x61\x71\xc7\xb9\x0c\x4b\x37\x65\xe1\x4a\xe6\x4c\xd2\xe3\xf0\x44\x17\x33\x9c\xe7\x05\x6e\x01\x6f\x6a\x70\x5d\xc6\x5b\x9b\x6e\xa1\xc4\xbd\x1b\x7c\x0a\x73\x12\xf3\x6c\x1b\x53\xc9\x7b\x76\x5b\x82\xd8\x6a\xa3\x4e\xa3\x3e\x51\x8e\x14\xe7\xa0\x2e\x9f\xe7\xac\x64\xd7\xd5\x51\x55\x75\xd9\x75\x02\x3f\x16\x41\x1d\x3d\x0d\xe2\x6d\x10\x06\x53\x53\x5b\xb2\xef\x59\x2a\x84\xab\xb5\xad\xd7\x47\x2a\x83\xdb\x0e\x02\xf6\x9e\x28\xb2\x57\x26\x48\x2e\x81\x9d\xc3\x22\xaf\x63\xc2\x42\x11\x47\x21\x2b\xed\xe0\x17\x72\x56\xb0\x1e\x3d\x1d\x15\x6e\x11\x24\x10\x0d\x00\x79\x0b\x3f\x96\x40\xd0\xe4\x3b\x4a\x6f\xef\x28\x08\x18\x7b\x9b\x2d\x56\xac\xa4\x4b\x25\xae\x14\x7a\xde\x7f\xb9\xdc\xde\x3a\x1f\x8e\x39\xb4\xf0\x7f\x6d\x21\xf0\x06\x7c\xde\x53\x4f\x2a\x80\x15\xcd\x4a\x84\x9d\xc4\xca\x28\xfc\x9d\x74\x51\x99\xf1\x31\xd8\x1d\x93\xf9\xb0\x7c\x32\x2b\x5c\x6f\xe4\xad\x5a\xc0\x80\xda\x2c\x82\x06\xe5\x91\x1d\xa3\xd6\xc8\x8e\xd9\xb9\xf2\x19\xa7\xe2\xb3\x2f\xb7\x78\x0c\x3b\x3e\xd9\xe1\x6d\xcc\x2a\x77\xb8\x19\xf7\x35\xf5\xd1\x21\x05\xe0\xaf\x58\x9c\x47\xa0\x96\xa1\xca\xdf\xe2\x77\xea\xee\x3f\x05\x0e\xfb\x0c\x7a\xfa\x1b\x17\x63\xef\x46\x84\xce\x02\x7d\x5f\x92\xd3\x4b\xf4\x7e\x61\xeb\x8b\x36\x53\xee\x50\xb1\xbf\xc4\x66\xda\xcc\x59\x03\x4f\x01\xb8\xff\x2a\x35\xd4\x05\x49\x83\x0f\xee\x6f\x99\xc5\x8d\x8a\x20\x34\xe9\xe0\xdc\x97\x83\x0f\x0a\x46\x95\xe1\xde\xc1\xe7\x24\xf3\x3e\x64\x43\x51\x80\x8e\xcd\xb4\xc4\x08\x74\x32\x51\x34\xcc\xc8\x52\x3c\x96\x42\xb7\x64\xcd\xfe\x7d\x1c\x6e\xf8\x7a\x02\x8b\xa5\x18\x74\xac\x2f\xe2\xe0\xcf\x6f\xc4\x42\x5c\xee\xa0\x36\x11\x0f\x5d\x72\xb7\x38\x3b\xd8\x55\x0c\x77\xc1\xb2\xd1\xb7\x55\xd1\x5b\x7a\xb7\xe9\x1a\x7e\xa4\x9a\x39\xa6\x29\xf0\xbb\x4f\xb3\xcf\xb8\xcc\x0b\x8b\x1c\x4a\xe4\x60\xd5\x1c\x63\x89\xf4\x16\x85\x2b\x13\x45\xf9\x64\xf1\xef\x3f\x2d\x0b\x58\x8d\x35\x77\x6a\x70\xe4\xbe\x40\x18\x49\x81\xf9\x6b\xab\xd3\xf4\x4c\x74\x1d\x5c\x37\x1a\x91\xdd\xc8\x3b\x35\x39\xc4\x99\xe5\x89\x2c\x54\x99\xdf\xd8\xce\x26\x16\x0b\xbe\xa6\x00\x68\x25\x75\xd6\x2e\x72\x47\x69\x69\xd2\xce\x85\xc8\xe8\xe5\xa9\x83\x90\x0b\x9d\xc1\x8c\x89\xa6\xac\xcc\x8c\x11\xc7\xb0\x81\x10\x77\x8c\x0d\x88\xe7\x58\xc8\x73\x1d\x40\xa3\x99\xd6\x22\xd8\xb2\xc7\x26\xf2\x18\xb9\xd9\xa5\x06\x21\x38\x79\x69\x6a\x53\x58\x62\x12\xee\xd3\x86\x74\xcb\x95\x27\xdd\x2d\xb6\xf5\x0b\x7a\xdb\x8c\x4c\xf6\x72\xf0\xba\xd1\xbd\x8c\xa4\xf2\x3a\x4b\x61\x48\xe9\xbd\x6c\x76\x61\x5b\xe7\x4c\xd7\x6f\xa8\x7f\x20\xb5\x43\x58\x8f\x68\xcb\x1e\x04\x2d\x2f\xd7\xbf\x2d\x94\x8e\xa1\xb4\xf3\xd2\x31\x31\xa0\xf8\xad\xc2\xbb\xb0\x4c\x5c\xcb\xef\xc4\x28\xb3\xb1\xfb\x5e\x0e\xaa\xd4\xc6\x86\x94\xa8\x8e\x5d\x84\xe3\x59\x62\x60\x7f\xb0\x22\x5e\xe4\xc0\x13\x67\xe1\x04\x2b\xf5\x88\xa0\x70\x8c\x2a\x90\x12\x2d\x44\xee\xbe\x80\x68\x0c\xd3\x0a\xa9\x86\x0b\x41\xbf\x28\xbf\xb8\x44\x9c\x5e\x1e\x72\xcf\x6d\x3d\x28\x37\x76\x30\x23\xe0\x51\x86\x1f\x1b\x3b\x9a\x76\x15\x81\xe0\x9d\xa9\xc0\x6d\xa5\xba\xb2\x43\x04\x5f\xa1\x22\xff\xd6\x90\xbb\x56\x8d\x0c\x8c\x3a\xb4\x39\xf4\x75\xa7\x64\x9b\xf5\x7e\x50\xf0\xd8\xc3\x14\xff\x5e\x0d\xdb\xd8\xd1\xaf\xc1\x5f\x8c\xe9\x0e\x63\x76\xa3\x87\x6d\x77\x14\xad\xde\x00\xd5\xf5\x82\xd4\x0d\x5c\xdd\x4e\xba\x3a\x7f\x4f\x2c\x2c\x90\x58\x1b\x2b\x91\x26\x13\xb3\x56\xfe\x00\xd1\xae\xc0\x99\x22\xd4\x8b\xaa\x32\xf7\xf3\xc4\x63\xea\x11\xd4\xf1\x28\x70\x2e\x2d\x11\xee\x7f\x82\x0f\x24\xdf\x34\x73\x13\x31\x73\x61\xd5\x01\xf1\xe3\x35\x74\x80\x2d\xe3\xad\x80\x11\x02\x6e\xa7\x65\xcd\x07\x1e\x23\xec\x6e\xf5\xa7\xe8\x6e\x25\xb4\xf1\x76\xc1\x0d\x8b\xf0\x03\x26\x62\x6a\xb8\x1a\x4c\xfb\xc7\xd0\x8b\xb3\x8f\xff\xe3\x13\x6f\x09\x2f\xd7\x75\x7e\x3a\xa0\xc5\x6a\xfc\x2c\xa0\xa6\x0a\x9f\x94\x57\x5c\x9b\xb3\x8e\x91\xf2\x89\x87\xf0\x16\x17\x4f\xb2\xe1\xc2\x0c\xb2\x50\xcf\x67\xd2\x5b\xd1\xab\x21\x50\x45\x1a\xcd\x68\xb3\xbb\x2a\x86\x06\xb8\xfd\x21\xd5\x14\x56\x4d\xcc\x79\x3f\x43\x1b\xc9\x20\xc1\x94\x54\x10\x51\xb4\xd2\xcb\x7a\x3d\xb0\x79\xbe\xf4\x32\xda\x64\x2e\xe3\x22\xd8\x76\x4c\xd1\x98\xc8\xd6\x0b\xee\x03\x33\xe2\xce\x6d\xd7\xae\x06\x8f\x74\x54\x05\xbf\x27\x37\xf3\x4e\x37\x5e\xc4\x74\xed\x28\x1c\x12\xbe\xb5\xb2\xc5\x97\x6b\xe2\x0b\x75\x9b\x41\xb9\x1d\xbc\x2b\x11\x00\x36\xea\x20\xf6\x16\x18\xda\x48\x91\xa4\xa9\xc1\x04\x11\xf7\x6b\x6e\x45\x54\x74\x83\x4c\x8a\x68\x40\x8a\xd7\x22\x32\x54\x60\xb1\xf5\x75\xd8\xd0\x03\x62\x09\x5f\xa2\x08\x51\x89\xcb\xfd\x76\xa7\xeb\x9a\x3e\x31\x87\xeb\x61\x2f\x0d\x1a\x17\x6b\x23\xec\xd0\xaa\x81\x62\xee\x82\x73\xb7\xdf\x2d\x61\x46\xbe\x14\x91\x12\x3b\x97\xdd\x30\x21\x5a\x4c\x8f\xcb\x36\x50\x39\xbe\xec\x0d\x00\x38\x61\xef\x20\x9d\x2f\x76\x29\x3d\x91\x7b\xb8\x34\xcb\x8c\xfe\xa2\xfe\x34\x37\xb8\xc9\x16\xf1\x94\xcc\xc1\x82\x5e\xa2\x36\xb0\x89\x46\x43\x44\x01\x4a\x45\x65\xfb\x6f\xa4\x17\x7a\xe0\xe3\xc6\xa1\xcd\x95\xac\xdd\xcb\xe1\xcf\xc9\xa8\x41\xae\xaa\x98\xca\x1f\xfe\xe9\xac\xfd\x91\x1e\xe3\x92\x7b\x35\xb7\x59\x0d\x89\x38\x6a\x39\xff\x12\x0e\x12\xed\x20\xcc\x35\xbc\x01\x61\x07\x1e\xa1\x15\x13\x56\x12\x9a\x32\x83\x55\xe0\xcf\x7e\xc9\x8f\xbc\x02\x06\xa2\x97\x19\x75\xc8\x08\x10\xdd\x93\xa5\xbb\x25\x66\x6c\xb8\x93\x1a\x77\x28\x86\x8b\xc0\x52\xe8\x9c\x00\x4d\x36\x8d\x5a\x55\x99\xf5\x4c\xc6\x5c\x24\x65\x4d\x96\xbd\xa0\x59\xca\x72\x97\xb5\x4b\x53\x80\x36\xa9\x50\xcf\x5c\x51\xb7\xad\xdb\x51\xd5\x24\xfa\xbf\xb1\x40\x4a\xc2\xd7\xb4\x05\x2c\xf2\x4e\x31\x47\xf9\xaf\xec\x50\xed\xc6\x75\x38\xd3\x31\x3a\x35\x2e\xf4\xcc\x60\xc8\x5b\xf6\x24\xa1\xbb\x79\xe2\xce\x0a\xf4\x93\x33\x70\x71\x70\xa2\x8f\x66\xf8\x9f\x67\x2c\x18\x74\xe7\xb9\xa9\xcf\xcf\x46\x05\x6a\x7c\xf1\x03\x5f\x4e\xff\x58\x76\x52\x61\x0c\xa2\xf0\x3f\xcf\x88\x2f\xa8\x10\xaa\x1a\xd7\x21\x61\x04\xe4\x94\x92\xde\xca\x38\x8f\x56\x20\x0f\x8e\xc7\xe3\xf1\xe1\x7e\xff\xb0\x6d\x1f\x2c\xf4\x3a\x63\xa2\x63\xb7\x27\x56\x10\xa4\xad\x9a\x9c\x23\x19\xa6\x4c\x26\x59\x1e\x3b\x30\x69\xc9\xe7\xe9\x03\x28\x68\xd7\xca\x83\xdf\x61\x46\x46\x60\x27\xa5\xd9\x73\xe1\x84\xb4\x7d\xa7\x92\xd7\x59\x20\x79\x18\x4d\x22\xef\xcb\x44\x9e\xcb\xb2\x26\xc1\x96\xef\x6d\x60\xb4\x6a\x24\xfe\xda\x6e\x52\x63\x26\x83\x82\xcf\x2f\x9e\x1c\x92\x4c\x8e\x4a\xc3\x1a\x65\xa9\x05\xc0\x65\x49\x2a\xd5\xfe\xdf\x29\x4d\x2d\x55\xbf\xb4\x0c\xbe\x20\x4f\x55\x07\x7d\xab\xc5\x85\xf8\xab\xbe\xd5\xf0\x7b\x45\xe1\xb1\xb3\x70\xd8\xde\x42\xf6\x77\x45\x3e\xf7\x35\xe4\x80\x45\xdc\x8e\x9c\x80\x05\xbe\x28\x88\x5e\x86\x63\xd7\x8a\x4e\xdf\x22\xbf\x61\x9b\x11\x14\x2d\x47\x0a\x86\xf6\x9f\x10\x99\xcc\x6e\x15\x78\x81\x47\x19\x46\x7b\x5a\x54\x2b\xac\x90\xd6\x38\x04\x4b\xac\xe9\xf1\x68\xda\xe4\x3e\x3e\x2e\x15\xd2\x11\x3c\x7f\x5e\x1a\x12\x48\x6e\xa1\x74\x92\x5a\x12\x3c\xc6\xb6\xca\xb1\xbe\xa1\xc7\xb7\x30\x9f\x4d\xd7\x4a\x4b\x95\xd0\x73\xb4\x5e\x0a\x02\x85\x12\x72\x6d\x47\x32\xf0\x22\xd5\x68\x22\x10\xd4\x0f\x78\x23\x88\x6a\xba\x09\xc2\x45\xaa\x03\xec\xfc\xa9\x02\xba\x5a\x39\x73\x70\x93\xce\x2a\x1e\x28\x77\xe6\x10\x1c\x56\x7a\x48\xa9\xe9\x0a\x85\x74\x09\x45\x7f\x52\xde\xb4\x3f\xe8\x67\x56\x80\xd0\xc1\xb6\x0c\x65\xac\xd7\x8d\xaa\x7f\x62\x3e\x2a\xf7\x45\x43\x5b\x8d\xad\x22\xd6\x3d\x88\xc1\x1c\x9f\x81\xd9\xa0\xb0\xdf\xd5\xe0\xe1\xd1\x88\x38\x43\xf3\x4b\x78\x58\x48\x80\xea\x0b\xae\x90\x11\x87\xa3\x69\x76\xd9\x20\x72\x94\x34\x0e\x75\xc2\xe6\x89\xae\x5a\x7c\x5a\x9a\xd3\x56\x38\x59\x2e\xbe\x10\x99\x65\x65\xcf\xfd\x10\x8f\x94\x7d\x9f\x00\x5b\xa1\x47\x16\x45\x45\x3f\x05\x84\x96\x0a\xb4\x92\x4e\x01\xc1\x1b\xcf\xe8\xd4\x73\x0a\x64\x34\x7c\x47\x76\x21\x3e\xf0\xef\x04\xbc\x64\x4c\x3b\xcb\xac\xd7\x28\x87\x67\x7e\x51\xe8\xbb\x9d\x24\xe2\x40\xd7\x01\x2a\xf7\x0c\xa1\x49\xee\x47\xb7\x83\xf7\x44\xa3\x06\x98\x83\xba\x72\x45\x5f\xf2\xfe\x39\x01\x98\x38\x78\xc5\xcf\x1f\xb2\xed\x13\xea\x0a\x9d\x6e\x21\xde\x04\xdc\x2e\x06\x76\xf7\x7b\xce\x07\xed\x07\x04\x36\x40\xb6\xea\xbc\x60\x1b\x29\x6a\x9a\x81\x17\x25\xd9\x68\x25\xb5\x62\x62\xd0\x36\xcd\x98\x58\xb4\xd6\xa3\x89\x26\xbf\xc9\xba\x75\xde\xde\xec\xad\x36\xbc\x29\x02\x07\x74\xed\xe3\x5b\x6c\xd6\x90\xfb\xc2\xac\x29\xd3\x1a\x13\xb1\x7f\x56\x56\xc3\x32\x60\xc6\x06\xdf\x1b\x44\xf0\xbb\x54\x53\x3f\x58\x0f\x77\x6e\xb9\x8d\xf0\x35\x27\x2e\xac\x9e\x79\x81\xe8\xfb\x84\x39\xd9\xea\x81\xc7\xd3\xec\xd0\xe0\x62\x81\x17\x7f\x65\xd3\xe8\x56\x19\x2f\xbb\x24\x8d\x42\x8c\xd1\x9d\xf6\x0a\xa2\x85\x65\xf3\x87\xaf\x8a\xa4\x2d\x80\xa1\x1f\x65\x6e\x53\x0c\x81\x1f\xd9\x5e\x76\xb5\x5a\x4d\x97\x79\x4d\xed\xc5\x8d\x4c\x9c\xf9\x75\x4c\xbb\x07\x7c\xe2\xd2\x85\x95\x0b\xca\x17\x4c\x3d\x60\x87\x20\xd6\xf8\xb2\xcd\x6a\x36\x5a\x13\xe3\x44\x1e\x29\x98\xb4\xf5\x64\x33\x2c\x14\x89\x5c\x06\x85\x95\x48\x63\x4a\x9a\xc0\x7e\x50\x77\xb0\x03\xc3\x88\xf3\xb8\x2e\x34\x83\xb5\xf3\x13\xa9\x8e\xdf\xa3\x2c\x64\x2c\x6d\x9c\x0f\x84\x08\xed\x80\x78\x06\xbf\x0e\x67\x0c\xa6\x80\x81\x5c\xa0\x9f\x38\x62\xf9\x1b\xcf\x25\xe6\x68\xf3\x4b\x73\xc9\x7a\x9c\x18\xd0\x79\x4d\x5d\xc6\x68\x0e\x14\x49\xc6\x58\xf3\x30\x2e\x49\x9e\x09\x60\x2c\x50\xc8\x2f\x91\xc6\x27\x66\x4a\xdb\xcb\x59\x9f\xe2\x6a\xac\xd3\x42\x0c\x54\x3b\x2e\xd2\xc3\xce\x82\x76\x02\x88\x60\x59\xc7\xd7\x61\xcb\xed\x5e\x89\x57\xb6\x03\xb9\xd5\x7b\x9b\x6d\x07\xbb\xc9\xc7\x69\x36\x48\xf0\x98\x5b\x60\x25\x53\x09\x74\x11\x3b\xf6\xd2\xc5\x37\xfb\x27\x8a\x90\x9d\x6a\x6e\xef\xed\x75\xf1\x54\xdc\x1f\xed\x2c\x1a\x5a\x45\x5c\x64\x6e\x05\x9f\xf7\x15\xc3\x31\xc0\x17\x03\x70\x7f\xe1\x3b\xd9\x14\xba\x9b\xec\xa5\xf7\xff\x40\x8b\xb8\x06\x6a\x11\x7c\xce\x68\x2f\x97\x9e\xd1\xde\xeb\x05\x0a\x90\x2f\xb1\xaf\xa5\xbc\x3b\x6b\x6f\xf1\x41\xc6\x35\xfc\x4c\x39\x5b\xed\x39\x33\x1c\x14\x2f\xcb\xdc\xb5\x74\xba\xa9\x33\xd6\xe6\x97\x90\xb0\xc0\xe0\x90\xef\x58\x06\x49\x2e\xac\x73\x50\x77\x34\x0d\xbd\x4a\x18\xc6\xe5\x68\x1a\xf1\xc6\x1e\xe6\xa8\x02\x98\x36\x35\xeb\xfc\x12\xca\x90\x13\x9f\x9f\xfc\xb2\x4e\x10\x79\x67\x49\x2f\x8d\x65\x4b\x91\x22\x32\xbf\xe5\x77\x4b\x6f\xf4\xc2\x41\x9c\xf5\x88\x6c\xcf\xe7\x3d\x22\x2f\x94\x70\x22\x7e\x5d\xbc\xe4\xa5\x38\xc9\x53\xe3\xd9\x88\x5d\xb6\x77\x41\x62\x6d\xf3\xa6\x5c\x52\xda\x42\x63\x02\xb3\x3a\x21\x89\x20\x84\xe1\x43\xf2\x59\xff\x9c\x42\xcf\x64\x23\xbb\x9a\xc4\xb4\x20\x73\xf3\x53\xf5\x21\x29\x6b\x44\xd7\xd9\x43\x4d\xc1\xbe\xf3\x2a\x2e\x21\x6e\x26\x07\xf0\x8e\xbe\x16\x80\x10\x22\x49\x95\x21\x09\x7a\x0c\x02\x50\x36\x43\x7d\x9e\x37\x83\xd3\x26\xed\x28\x40\xe9\xb9\xfa\x5f\x19\x14\x78\xfc\x0f\xef\xae\xee\x01\xe7\x66\xff\x7b\xf1\x6a\xf1\x3a\x0c\x3d\x52\x3e\x24\xe3\x1f\xde\x5d\x61\xeb\xfd\x4e\x1d\x4b\x13\x33\x2f\xd7\xd9\xe4\xa0\x20\x3d\x19\x6f\xbc\x30\x07\xa7\x71\x35\x9c\x18\x71\x80\xa9\x09\x66\x32\xf4\x9d\xde\xee\xfc\x41\x41\x58\x9d\x13\xb8\x8a\xf9\x28\x1b\x71\x62\x46\xe8\xea\xf8\x9b\xe7\x64\xa9\xa1\x71\x72\x4e\xb4\x2e\x16\xa6\x9c\xe9\x44\x81\xa1\xa2\x78\x4f\x38\x97\x67\x2c\x2b\xfa\xdf\x3d\x69\x39\xea\xa8\x28\x3b\xdd\x38\xf1\x1c\x60\xe6\xe5\x71\x68\x9c\x3f\xa2\x97\xc1\x32\x82\x37\x72\x0f\xc1\x52\x03\xd4\xcf\xf7\xe2\x58\xf1\x33\x4d\x17\xe2\x0d\xfe\xba\x1f\xbc\x78\xda\x29\xcc\x7b\xfa\xbc\xaf\xaf\x79\x24\x1b\x8e\x06\x99\x5b\x81\xa2\xa8\xfd\x5f\xe1\xec\xfc\xbb\xf8\xaf\xb0\x54\xfe\x2e\xfe\x4b\x9b\x56\x7d\xfe\x3b\xdf\x9a\xc5\xd7\xc8\x03\xb9\x3b\x9f\x85\x3c\x41\xd5\x77\x18\x04\x28\x96\x9f\xfe\x63\xd7\x4d\x77\x4b\x29\x35\x51\xf0\xac\x1e\x9f\x4d\x1a\xf4\x7a\xc4\x93\x8f\xaf\x34\x67\xd1\x81\xd6\x73\xa9\x01\xef\x96\x30\x28\x06\x1c\xc8\xe0\xdb\x24\x2e\xc4\x2b\x8c\x86\xc1\x77\xe3\xcc\xc9\x40\xf6\xb4\x3c\xee\x30\xba\xfa\xe0\xeb\x3a\xdc\x5b\x23\x9c\x32\x70\xf7\x11\x6f\x39\xd9\xb2\x3b\xc9\x99\x12\xdc\x29\x7e\x47\xcb\xc7\x67\xf0\x25\xfe\x4f\x6b\x72\x49\x1c\xef\x78\xc0\x93\xce\xdb\xda\x85\xb3\x83\x0d\x5e\x32\x41\x19\x6e\xcf\x0a\x5f\xf4\xb0\x9d\xbd\x13\x76\xd0\x5b\x1d\x56\x1c\x3d\x1b\x13\x11\x1b\x75\xa0\xd7\x79\x76\xd2\x21\xde\xf8\xd6\x08\x86\xae\xc7\x6a\x64\x7c\xe0\xd6\x95\x15\x94\x3a\x92\xd5\x44\x2e\x89\xfc\x30\xbc\x78\x90\x69\x0d\xcc\x9d\x1a\x7c\xbc\x36\xf5\xe2\xbd\x15\xef\xd4\x76\xec\xe4\x90\x07\x01\x98\x16\x98\x2e\x48\xc6\x43\xea\x4d\x38\xf3\xc3\xb2\x10\x03\xe1\xca\x15\x04\x1c\x0e\x80\x6e\x3f\x82\x6c\x32\x60\x20\xe1\x69\x2d\xa8\x67\x72\xa0\x68\x7a\x48\x8f\xae\x94\x01\x90\x8a\x8a\xb3\xd1\xa0\x36\xc0\x1d\xf2\x52\x2b\x38\x4c\x3c\xb5\x01\xe3\x20\x2d\xb4\x20\x59\xc5\x71\x24\x24\xba\x5f\x9e\x68\x7a\x10\x1a\x63\xb4\x4d\x02\x43\x24\x8d\x3b\x42\xf1\x1b\xa5\xd8\x24\xb0\x59\x2d\x23\xf8\xe7\x84\x00\xdf\x86\xb9\x08\xa4\x09\x7f\xbe\xe5\xd7\x65\xe6\x60\x51\x31\x92\x9e\x94\x29\x07\x25\x93\x8b\x80\x14\xd0\x24\x4d\x9e\x3b\xc2\x2d\xd6\xec\xb2\x17\x5b\x41\x75\x05\x31\xe3\xdc\x42\xf3\x26\xd3\xb4\x18\x6e\x4b\x6f\xb2\x35\x0c\x7e\x56\xda\xb4\xfa\x4e\xb7\xa3\xec\xe8\x2d\xac\xd3\x78\xff\x54\xe2\x6d\xac\x01\x8d\xc8\x49\xdc\x93\x0e\x01\x6d\x83\x50\xb9\x0f\x06\x32\x26\xdf\xa4\x67\xae\x16\x7b\x14\xc8\x6e\x34\x0f\xa3\x9d\x84\x61\x57\xd3\xb3\x35\xb9\xae\x1e\x15\xf1\xb0\x3e\x30\x78\x37\xaf\xd2\x9f\x67\x5c\x1e\xd9\x73\xfd\x3a\x04\x9c\xc0\xfe\x3c\x93\x5e\x2e\x82\xf1\x84\xbe\x65\x8f\x2a\x05\x85\x80\xe5\x6a\xa5\x97\xe9\x36\xd4\x58\x0a\xa5\xb5\x96\xcd\xed\xa2\x9e\x75\x11\xff\xc2\xfe\xca\x55\xb9\x61\xe0\x58\x18\x07\x8f\xb7\x50\x71\x38\x48\xce\xe6\xcc\xeb\xec\xc2\xe1\x5d\x4e\x9a\xb8\xc1\xc9\x93\x0b\xba\x32\x7d\xbb\x22\xd3\xf8\x95\x0e\xa2\xd0\xb4\x25\x7a\x74\x62\xa0\xb8\x03\xc5\xc3\x53\x7f\x64\xb4\x4e\x0f\x54\x22\x44\x5f\x8c\xaf\x76\x1a\xdf\x9f\x4e\x12\xb6\x2c\x0a\x1a\xf7\x26\xd0\xc9\x23\x9a\x2a\xcd\x5d\xcf\xce\x29\xa8\x50\xc8\x0d\x52\x61\x18\xee\x73\xe2\x20\xcf\xa3\xc9\x30\x3d\x2c\x98\xd9\x70\xe2\x1e\x3a\xdd\x42\x38\xe9\xb0\xdb\x97\x1c\xc4\x8b\x99\x39\xb8\x0b\x0a\xfc\x42\xaf\x4c\x0b\x16\xb5\x18\x71\x74\xae\x60\xba\x7f\x7d\x7c\xe1\x46\xea\x94\x7c\xb7\x8c\x8c\xe5\xee\x2f\x3c\x93\x32\xdf\xf3\x7c\x8c\xbf\x51\x07\xb2\x5d\x4d\xf2\xad\xbc\x05\x7e\x9a\xa9\x31\xc4\xd4\x64\x32\xbb\x80\x6a\xf1\x1c\x48\xef\x82\xc5\xa6\x71\x81\xe1\x74\xf3\xca\xc8\x7c\x4b\x11\xf9\x32\xa9\xb3\xad\x27\xf6\xb9\x97\x6d\x0b\xfd\x29\xec\x74\x4f\x16\x98\x04\xbc\x2d\x70\x95\x41\xf5\xe7\xeb\x65\x52\x31\x47\xd6\x9f\x5f\x4f\xd8\x21\x37\x47\xcd\x1b\xb6\xd0\xa5\xc5\x62\x85\x09\x0f\x1c\x64\xb0\x1e\x93\x7b\x2b\x19\xea\xe5\x97\x34\x79\xd4\xc7\xf2\x50\x9c\xac\xd9\x7b\x22\xf1\x73\xa3\xf0\xbe\xf6\xd4\xc8\x3d\x5d\x1c\x35\x8a\x16\x9a\xab\x32\x92\xfa\x6b\xe2\xd1\x95\x69\xc2\x0a\x8d\x35\x3c\xbd\x99\xc2\x4f\x05\xfe\x73\x3d\x1b\xf8\xe2\x25\xce\x32\x02\x15\x29\x49\xf1\x55\x04\x60\x1f\xf3\xb2\xab\x72\x5d\x1c\x50\xed\x44\x6b\x88\x94\x50\x13\xed\x54\xbc\xf1\x25\x15\x15\x98\x45\xed\xc7\x66\x87\x37\xbc\xa0\x89\x82\x70\x4f\xe2\xfa\xed\xcd\x7b\x81\x3a\x68\x3f\xe8\xed\x36\x1c\xbb\xe2\xaf\x3b\x65\x02\x4d\x83\x5b\x22\xa4\x6b\xb6\x69\x46\xd4\x57\xbe\xb0\x5b\x77\x2e\x0e\x8a\xa3\xec\x9a\x96\x0e\xa1\xfc\x9d\x1b\x56\xc2\xa0\xa9\xa4\xd8\x59\x87\x8f\x77\xb8\x5e\x35\x7a\x73\x5c\x89\x2b\x25\x07\x23\xf6\x41\x82\x60\x92\x79\xaf\x13\x72\xec\x09\x04\x10\x7a\xfc\x48\xe6\xca\x7a\x1a\x92\x7c\xf9\xd2\xf1\x34\x1b\x9e\x29\xe8\x52\x58\x5b\x1e\xe1\xfb\x6c\x00\xe0\x99\x34\x3c\x90\x35\xc4\x9e\x66\x4b\xd3\xaf\x58\xa6\xb3\x36\xa4\x35\x4a\xed\xfd\x6a\xc2\x4b\xa8\x56\x1e\x75\xf7\xd4\x96\x0b\xf1\x5e\x39\x08\xf9\x09\xdf\x5f\x00\xe7\x21\xb8\x51\xa1\x4f\x02\xdc\x6b\x40\x3f\x8b\xcb\x22\x62\x0d\x53\xaa\x1c\xd9\x04\xf0\x18\xb9\xb9\xce\x6c\xb1\x8e\x2c\x38\x75\xc0\x71\x98\xf6\x13\xd7\x3e\x9a\x3a\x62\x75\x7f\x1b\xd5\xa8\x56\xe2\x95\x17\x7b\x79\x84\xb7\x66\xc1\x22\xd1\xa9\xc6\x9a\xd6\xb1\xa1\x9c\xf6\xe0\xa5\xed\xc4\xd8\xb3\xd7\xfc\x6c\x4a\xe6\x6d\x1b\x54\x36\x56\xef\xe2\xc7\x7d\x80\x59\x0f\x5e\x86\x96\x7b\xe9\x6e\x27\x36\x2a\x41\xfe\xfb\xc6\x5e\xa4\x40\xc4\xb1\x04\x3d\x98\xa1\xcd\xbd\xed\xcf\x6f\x80\x94\xf3\x4b\x20\xae\xb7\x18\x9c\xf2\x1d\xfd\x9c\x03\xa1\x81\x10\xf4\x09\x7f\xcd\x41\x7a\x7a\x77\x3c\xbe\x40\x3e\x07\x59\xdb\x36\x8c\xe3\x2f\xb6\x3d\xce\x75\xe1\xbc\xba\xa2\x42\x1c\x68\x51\x6f\x0f\x70\x13\xbc\x3e\x42\x86\xf6\x4e\x75\x1b\x7c\xd3\x22\x48\xad\x8a\x83\x01\xc1\xad\x41\xba\x85\x45\x12\x40\xf3\x0c\x77\x26\xe0\x65\x9a\x5b\xf6\xe2\x43\x74\xc5\xe3\x5a\xd3\x36\x61\xa8\x20\x6a\xd7\x2b\x94\x38\x60\x35\x82\x12\x1c\x63\x34\x9d\x07\x89\xbd\xcf\xc2\x29\xb0\x9a\xac\x1f\x94\x03\x1f\x2e\xa0\x61\xf0\xa8\x2d\x83\xa0\xc8\x86\xd1\x3a\xb2\x48\xab\x89\x51\xd7\x0e\xea\x59\x68\x11\x45\xc6\x85\x95\x05\x31\x71\x67\x10\xc9\x87\x0b\x80\xf8\xd5\x9d\x29\x0b\x46\xe0\x49\xc3\xfe\xb2\x20\x7f\xd9\x01\x12\x27\xc6\x6e\x89\x6f\x74\x48\x00\x50\x67\x15\x0e\x06\x56\x51\x65\x06\xd4\x61\xac\x3e\xbc\xbb\xca\x89\xf9\xb9\x90\xe1\x78\x47\x3d\x47\xab\x3c\x3c\xa3\x36\xa8\xad\x1c\x5a\x8e\x4d\x44\x07\xcc\x4e\x7a\x3c\x48\x86\x30\x7c\xac\xa2\x80\x88\x81\x84\x0b\xc3\x4a\xdc\x6a\x03\x71\x7d\x41\x32\x21\xa5\x62\x10\x12\x93\x81\x52\x38\x54\xc6\x3e\x9c\x33\x78\x68\x71\x45\xd0\xf7\x1f\xfe\xe5\xe6\xed\x9b\x73\xf1\xf9\xe1\xe1\x70\x78\x18\x8a\x3f\x1c\x87\x4e\x99\xd0\x97\xf6\x5c\xfc\xaf\xd7\x57\xe7\x42\xf9\xe6\xc7\x95\x78\x8d\xc7\x4f\xa2\xea\x64\xb7\x0c\x2e\x10\x60\x04\x3c\x0e\xff\xc0\xb1\x44\x5b\x87\x14\xb6\xf9\x03\xfe\x39\x13\x19\xa6\x91\x1d\x64\xf9\xed\x7b\x70\x94\xcd\x18\x12\x7a\x9a\xe4\x06\x7e\x4c\x33\x12\xfd\x06\x30\x5e\xa8\xf0\x66\x99\x74\xe2\xe6\xe5\xe5\x9f\xfe\xf9\x7f\x8a\x97\xaf\x2f\x9f\x8a\x9d\xfa\x2c\x5a\xbd\x55\x78\x3d\xc9\x5b\xfb\x4e\xf3\xa4\xff\xaf\x87\x61\x35\x3c\xbc\xd1\x5b\x23\xfd\x38\x28\x5e\x00\x48\x27\x72\x1e\xa9\x93\xcd\xed\xd2\xbb\x97\x53\x10\xdd\x58\x43\x03\xf0\xaa\xb1\xa6\xec\x3d\x82\xb0\x33\xd7\x53\x70\xe3\x4a\xca\xeb\xb0\x66\x22\x23\xb3\x53\x26\x10\xfa\xb1\x6b\xcb\x33\x7a\xad\x78\x09\xa8\xf6\x2f\xd3\xc2\x10\xf8\x0f\x9e\xc9\xb8\x10\xff\x02\x21\x9f\x76\x6c\xfd\x14\xb2\xb8\x77\x00\x3c\x2d\x1b\x36\x43\x9d\x09\x76\x17\xe2\x95\x30\x41\x74\x60\xa1\x32\xe5\x45\xc1\x72\x8a\x83\x54\x7c\x17\xe2\x4a\x79\xb1\x8f\x2a\x3f\x58\xe3\x88\x6d\x56\xa2\x34\x8d\x5d\xce\xe6\x41\xf9\x25\x8f\x05\xc8\x66\xa3\xf3\x01\x2c\xfd\xd4\x16\xb3\x97\x31\x12\xef\x31\x2d\x92\x07\x7f\x5c\xc8\x4a\x91\x7f\x53\x48\x45\x08\x73\xb9\x34\x3b\x14\x8b\x71\x71\xe2\xb2\x83\x83\xaf\x8b\x73\xb5\xc1\xb4\xcc\x34\xd6\xe1\x62\x76\xa4\xfa\xa0\x51\x47\x17\xcf\x73\x74\x5c\x6d\xcf\x05\x3b\x7d\x9e\x93\x3d\xdf\x39\x47\x89\x68\xcf\xc5\x68\xd2\x6f\x74\xb8\x23\xf1\x95\x3f\xc1\x9e\x38\x7c\x46\x73\xcf\xf6\x1c\x5f\xb1\x4e\x09\xab\x79\x47\x0b\x7b\x8e\xc2\x3e\xff\x1e\xd0\x68\xe2\x92\x5b\x07\xfc\xff\xdf\x9b\xbc\x2b\xd0\x37\x77\x34\xcd\x6e\xb0\x46\xff\xbe\xd0\x37\xbc\x5e\x49\x2e\xbb\x38\xe6\xec\xb8\x7b\x1f\x70\x39\x4b\x8c\x81\x16\x78\xea\x4e\x7c\x22\x7c\x5e\x37\x05\xa0\x4c\xf1\x27\x4f\x00\xa4\xc5\xca\xb6\x71\xeb\x4e\x83\xa9\x0a\xf8\x18\x2e\xdf\x21\x63\xc8\x46\x8e\xdd\x38\xcd\xc8\x83\x34\x9f\x3e\x0b\x51\x91\x1b\x49\x57\x3a\xbc\x98\x7c\x13\x3f\x88\x02\x21\xbe\x48\x51\x9c\xe2\x70\x84\x97\x6a\x81\x65\xa6\x7a\x6e\x9d\x96\x24\x48\xe2\x11\x66\x52\x12\x01\x4e\xea\x98\x09\x27\xb4\x66\xe6\x3a\x87\x54\xc3\x29\x39\x0c\xa3\x10\xb0\x7c\xc0\xaf\x9a\xc3\x9b\x76\xcf\x62\x5a\x29\xd5\xf2\x21\x09\xfc\x4f\x79\x42\x42\x18\x24\x38\x4c\x72\xce\x26\xc8\xc7\xa5\x1f\x73\x00\xa1\xe7\xdc\xbc\xe2\xb0\xbd\xb3\x67\x28\x8f\x93\xa1\x6e\xb5\x6b\xec\xd0\xde\x8f\xfb\x19\x02\xfd\x11\xec\x66\xeb\x65\xf7\x85\xa6\x3f\x23\xa8\x6f\xc3\x8f\x63\xc2\xaf\xc2\xe0\xeb\x35\x93\xcc\xd6\xee\x25\x98\xbf\x3e\x83\x1f\xb3\xc3\x79\x27\x8d\x41\x53\x7f\xfc\x95\xcf\x75\xdf\xd9\x23\xbf\x33\xfa\x0c\xbe\xf8\xe9\xf4\x39\x48\xf6\x2a\xe7\xfa\xc9\x53\x7c\x1b\xf3\x85\xf5\xcd\x4e\x7e\xf7\xf8\xd1\xfa\x49\xe0\xc3\xe9\x1e\xa0\xb3\xf6\x96\xbd\x7c\x64\x0b\xfb\x26\x3e\x34\xd3\xc7\xd7\x2b\x93\x8d\x8a\x6c\x5b\x34\x2c\xd2\x06\x87\x62\xf2\xa4\x5f\x7a\x92\x09\x5b\x35\xe1\xd2\x60\x0e\x62\x3b\x69\xec\x53\x6f\x96\x3a\x93\x94\x06\x00\x05\x23\xb0\xc3\xe7\x4e\x64\xfb\x10\x18\x0e\xd2\xde\x8a\xf7\x3b\x75\x8c\x81\xab\xe1\x45\x39\xb8\xd4\x2d\xdf\xce\x81\xe6\xf1\x93\xa2\xf9\xd5\xa3\xad\xcb\x41\xe6\xa7\x4c\x20\x86\x0f\x6a\x8b\xcc\x51\xb4\xa9\x19\xb9\xfa\xb4\x70\xa0\x59\xea\xc5\xfc\x0d\xcf\x08\x35\x7d\x6b\x34\xf5\xf4\xe4\x5b\xa3\x79\xd1\xfc\xc1\xd1\xac\x28\x48\x08\x71\x10\x16\x2d\xc6\x8b\x69\x99\x3f\x27\x9a\xba\xfa\x15\x2f\x8a\x2e\xcf\xdc\x54\x45\xf4\xc5\xa9\xbe\xcf\x61\xa4\xcd\x3b\xf7\x15\x6f\x8b\x4e\xc3\xd2\x7d\x85\xb6\x68\xa9\x2d\xb9\x41\x71\x6c\xc0\xd7\xea\x8c\xf2\xe0\xff\x73\x67\xaa\x6f\x7c\x4e\x60\x11\xeb\x17\x9e\x14\x68\xf5\x66\xb3\xc2\xd0\xca\xb5\xb3\xe3\x00\xe6\x04\xbf\xc0\xb7\xb8\x81\x6f\x04\xa1\xc0\x92\x17\x14\x61\x12\x13\xa3\x93\x25\x79\x55\x42\x22\xb8\xd7\x82\x06\x36\x56\x78\x21\x9e\xe9\xcd\x06\x5d\x6d\xdf\x58\x9f\x9a\xb2\xc2\x22\x6e\x67\x0f\x75\xf8\x05\x2f\x94\x82\x55\xe1\xce\x1e\xb0\xd0\x4d\x48\xc9\xc0\x5c\xdf\x69\x5f\x53\x54\xe7\x9b\xf0\x01\x71\xa9\x33\x88\xd1\x40\x0c\x4a\x86\xf9\x80\x9f\x39\x54\x40\x19\x83\x6b\xf0\x45\xd4\x59\x1b\x03\x27\x82\xb6\x23\x5d\x51\xc1\x56\x61\xb8\xb3\x16\x08\x21\xa8\x33\x12\x48\xfe\x82\xd0\x59\x1b\x15\xe5\x09\x82\x06\x1a\xa8\xfb\x2f\xaf\xde\xe0\x27\xc4\x54\xa6\x68\x58\x10\x5c\xfb\xb9\xee\x68\xbc\x21\xe2\xa2\x1b\x7b\x08\xdc\xa8\x5a\x0e\x28\x19\xf2\x44\x96\x9c\x39\x43\xe6\xe1\xb5\x11\x87\xb7\xb6\xde\x4b\x73\x8c\xae\xdb\x37\x76\xaf\x48\x95\x73\x50\x44\x07\x21\x04\x77\xf2\x1c\xb5\x56\x84\x22\x04\xc5\x03\xc2\x6a\xe1\x80\xb6\xe2\x88\xe2\xab\xa5\xc8\xe2\x9c\x87\x61\xe2\x99\xf1\x0b\xe4\x82\x99\x3f\x86\x68\x07\xb9\x01\x47\xbe\xf0\x3f\xa6\xf6\x83\x4a\xc5\xae\x07\xf5\x70\x5a\x8c\x1c\xee\xc2\xbf\x98\x26\x77\xe8\xec\x91\x66\x20\xcd\x0c\xfb\x86\x7a\x2b\xce\x1c\xc5\xdd\xa4\x9d\x5f\x22\xc6\xd5\x5f\xd3\xfb\x9c\xb8\xf6\xe1\x65\xc5\xa2\x4f\xb9\x27\xdf\x35\x32\xa8\x22\x8e\x03\x98\xaf\xe0\xeb\x74\xfd\x60\xdb\xb1\xf1\xab\xa2\xdd\x45\x69\xe4\x48\x15\xaf\x3a\xd1\xd9\x2d\xe8\x3c\x20\x50\x32\xda\xfb\x8e\xa6\x55\x83\xf3\x68\xda\x2f\x33\x32\xaf\xf7\xfd\x80\x37\x25\x8c\xde\xcb\x6d\x7c\x3d\x4f\x6e\x31\x4c\x4b\xca\x03\xc5\x7f\xc8\x09\x3f\x8a\x32\x91\x13\x60\x2f\x80\x2c\xda\xaa\x97\x5b\x60\xec\x9b\x3c\xbe\x7f\x10\x46\xad\x61\xe6\x3c\x6b\x40\x71\xc4\x71\xea\xfc\x58\xe3\x9c\xd2\x89\x27\x9b\x7e\xda\xb6\x14\x60\x3c\xe6\x74\x56\xb6\x28\xfb\x5f\xe1\xaf\xd5\x6a\xb5\xb0\x6a\xe6\xaf\xa7\xf7\x83\x7a\x38\x9d\xeb\x0c\x3e\x0e\xc0\x5f\xd5\x83\xae\x13\xbd\xd5\xc6\x0b\x74\x4a\x93\xbe\x58\x29\x7c\x51\x44\x53\xab\xad\x79\x08\xe7\x65\x6a\xc6\xd4\x15\x33\x56\x47\x0b\x25\x2d\x99\xe9\xaa\x06\x27\x37\xde\x11\xe0\xe5\x56\x6e\x0b\x58\x3d\x69\x63\x80\xbb\xe9\x6c\x43\x21\xbf\x9f\xa0\x4a\xb3\x80\x05\x60\x3c\x7b\x59\xde\x8a\x17\x8b\x53\x98\xe5\xe3\x96\xeb\x99\xba\xb5\x35\x76\x40\x7d\x77\xbc\x65\xf7\x72\x7b\xef\x43\x71\x93\xda\xf2\x0b\x6b\xac\xe2\x0b\xa7\xe9\x74\x0f\x94\x4e\x72\x19\x1e\xe2\x79\x02\xa5\xa4\x3d\x32\xe3\x79\x66\xb8\xc8\xa9\x38\xdb\x57\xc5\xc3\xbf\xa9\x04\xc7\xb4\x01\x4e\x80\x7f\x57\xd5\x47\x3b\x6c\x3f\x55\x70\x2b\x09\x61\xd0\x63\xfc\xd2\xfc\x0a\x12\xd4\xcc\x01\x26\xf4\xe8\x3e\xc0\xe7\x63\xd7\x25\xe8\xf2\x9d\xb6\x17\x61\x9b\x96\x46\x3d\x01\x00\x95\xfc\xf0\x2c\x1b\xf9\x74\xd0\xcb\x6c\x2b\x7e\xd2\xc3\x0e\xdb\xe4\xc5\x99\x57\x87\x0f\x14\x25\xdf\x40\x7a\xb5\xa0\x22\x5f\x8b\x0b\x71\x0d\x3f\x2a\x6d\xee\xb4\x0f\xfc\xc3\x5e\xa1\x55\xe0\x2b\x48\x80\xf3\xc6\x1a\x55\x15\xde\x08\x15\x04\x5b\xaf\xd9\x13\xe1\x82\x7d\x12\x28\xbd\xb0\x83\xbc\x28\xcc\x22\xf3\x27\x48\x02\xca\xd2\xf5\x34\x20\x87\x51\x59\x70\x4a\x0f\xd0\x91\x3c\x86\x92\x30\x84\x90\x7a\x1f\x74\xf1\xec\x59\xa0\x0e\x23\x07\xbc\x04\x5c\x60\x23\x69\x50\xf2\x83\x45\x15\x30\x6b\x53\x44\xe2\x72\xab\x54\x4d\x46\x6b\x76\xe8\xb1\x9e\x8a\x05\x2e\x15\x0c\xfa\xff\x82\xf0\xc5\xbb\x3b\xa4\x76\x95\xf8\x6c\x21\x26\xd3\x63\xb6\xb9\x1e\x16\x10\x05\x91\xe4\x2f\xd5\xf2\x53\x4e\x6f\xa7\x6b\xe3\x0f\x3c\xe6\x34\xc7\x71\xef\x73\x4e\x80\x2e\x0d\x68\xd6\x18\x98\x87\x13\x8d\x88\xac\xec\xb7\x3a\x9d\xc6\xfd\x13\x18\xa6\xb8\x57\xf2\x5b\x32\x72\x8e\xf8\x2b\xfe\x4a\x59\x9d\x6d\xd8\x53\xf5\x8a\x7e\x9e\xb4\xa9\xb9\xcf\x67\xa2\x04\xcd\x88\x59\x31\x70\x11\xd3\xd7\x1a\xe0\x90\x2b\x86\x1d\xb6\xff\x98\x27\x46\xf1\xb4\xe8\xac\xd5\xf2\x4e\x7a\x39\x9c\x6a\x34\xe6\x72\xdb\xbf\xba\xe9\x53\x33\xb5\x82\xc2\x4c\xb5\x55\xb3\xc7\x3e\xa1\x83\xf7\x16\x29\x9f\xfe\xcc\x1b\x1c\xef\x09\x33\x33\x31\xb2\x31\xc1\x47\x3f\xd1\xd6\xe1\xcb\x2f\x7f\x9e\x30\x34\xba\xef\x09\xd0\x69\x2b\x03\x65\x8a\x61\x2d\xf3\x46\xde\x5b\x22\xe7\x66\xec\xc4\x68\xe5\x8f\x3f\x0b\xba\x6c\xa0\x72\xd9\xb6\xac\xb6\xa4\x57\x00\x79\xfc\x92\x6a\x74\x93\xc5\x94\x9f\xbe\x69\x9b\x46\x0e\xf8\x56\x72\x58\x2c\xd6\x5b\x45\xb4\x7e\x45\xff\x77\xba\xaf\x8b\xa7\x40\x5f\xc7\xf4\xec\x55\xd0\x9f\x63\x31\x52\x39\x11\x1f\xd5\x4c\xd2\x13\x7d\x85\x80\x08\xec\xfe\x11\x81\xf0\x1b\x78\xcb\xc5\x9c\x69\xf9\xb2\x0e\xfc\x5f\x0f\xb6\x53\xb1\xa1\xe2\x9d\xed\x54\x6a\x5e\x19\xd4\xb1\x2c\x18\xcb\xc4\x74\xd2\x4f\xf0\xbb\x8c\x31\xbd\x7c\xcf\x97\x53\xe9\x8c\xcd\x5f\xfa\x00\x7e\x9c\xb0\x83\x78\xf3\xf3\x14\xda\x40\x48\x7d\x3a\x8d\xdf\xd8\x43\x85\x47\xf1\x0a\xa2\x46\x5e\x88\x7f\xb1\xda\x50\x4a\x59\x29\xa6\x05\xce\x28\xbd\x41\xf3\x2e\xc8\x58\xf8\x48\xf5\x3c\x7f\xf2\xd6\x1e\x9c\x44\xf1\x95\x3d\x7a\x2b\x1b\x18\x7b\x8a\x4d\x6a\xd0\x8a\xa7\x7c\x25\x0e\xb1\x4e\x9e\xbe\xc1\x70\x11\x45\xbd\x39\xc4\xd7\x54\x0c\xa1\x00\xa6\xd5\x9d\xb3\x2e\x1f\x14\x80\xd1\x05\x52\xed\xb9\x1d\x60\xcf\x9d\xda\x01\x11\x09\xca\x76\xe4\x10\x5f\xd3\x8e\x50\x0b\x04\xa6\x63\x3f\x87\x93\xed\x91\x6d\x2b\xd0\x04\x3d\x37\x3e\x73\xd3\x26\xa6\xd7\xde\xde\x67\xe7\x3f\x98\xee\xb6\x13\x7e\xc6\xad\x96\x8e\x54\xcc\x41\x9b\xcb\x05\x96\x03\xcd\xe8\x17\x5f\x6f\xff\x32\x11\x80\x80\x83\xa1\x64\x04\xcd\x0c\xe4\x8b\xd7\x27\xe6\xe7\x12\xb6\x2b\xb1\x88\xc0\x2b\x10\x6d\xa0\xcc\x2f\x1f\xc9\x08\xc7\xcf\x2f\x21\xbf\x98\x1f\x2a\xc0\x30\xf2\x4c\xb6\x00\x51\xc7\xbd\x1a\x36\x58\x56\xeb\x1c\x59\x24\xe6\x00\x15\x89\xf8\x1c\x8e\x77\x6c\xce\xed\x65\x17\x4b\x0a\xae\xcf\x0a\xbf\x5c\x86\xda\xcb\xe3\xf4\x35\x6e\x08\x15\x51\xec\x9a\xd3\x82\xd5\xbc\x29\xe9\x5c\x7f\xa1\xef\x94\x49\x0b\xe6\xa4\x70\xb5\xca\xb7\xfa\x7c\x81\x64\xe4\x5a\xe7\x4c\xf0\x76\x80\x50\x89\x3c\xf3\x81\x74\x64\x0b\x03\xd0\xff\x1c\xfb\xdc\x48\x33\xa5\x0d\x60\xae\xa8\xe4\xfe\xc1\x7d\x24\xe2\x0f\x37\x07\x48\xca\xfd\xed\x01\x92\x81\x91\x81\x4d\x9b\x93\x87\xfb\x9a\x85\xf4\xe0\x0f\x37\x0b\x28\xcc\x57\x36\xeb\x9c\xdb\x84\x7c\x4c\xa0\x17\x4b\x94\xe2\xbe\xd6\x4e\x04\x2d\x58\xc6\xef\x72\x69\x8b\xc9\x06\x58\xe0\x82\x24\xb8\x68\x81\x9b\x29\xa8\x57\xab\xe9\x7e\xca\x4c\x88\xb3\x3d\x95\xf9\x28\x70\x5b\xc0\x58\x98\x7c\xb9\xe8\x3c\x4c\xa8\x8c\x35\x20\x9f\xe3\x65\x71\xf4\xf7\xca\x90\xd3\x75\x95\x1f\x8e\xc4\x13\xc1\x23\x63\xc5\x0b\xa2\xf1\x8e\x8a\xd4\x59\x3a\xc6\x5a\xa9\x3e\xc2\xcc\x7d\xaa\x5a\xe9\x76\x6b\x2b\x07\xb8\x2a\xe1\xdf\x55\xe1\xc7\x5f\xe5\x84\x6a\xca\x21\xe3\x2b\xc1\xd9\xa0\x16\xe3\x29\x47\xbf\x0b\xe2\x62\x94\x33\x2e\x8b\x04\x87\xef\xcb\x6f\x99\x99\xdc\x8e\x14\x2a\x87\x9c\x0c\xc0\xa7\xdc\x79\xb5\x17\x6f\x30\xa1\xda\x5b\xa3\xd1\x9e\xf9\x35\xfe\xd2\x66\x5b\x15\xf1\x9e\x9e\x87\x8f\x0a\x22\xfc\x50\xca\x95\x74\xbe\xf2\xd6\xc3\x33\xb1\xef\xc3\xff\x9f\xc5\x59\x5b\xa5\xae\xaf\xd6\xa3\xee\x5a\x0e\xa7\xf4\x4b\xf8\x10\xaf\x92\x59\x56\x06\x28\xfb\xbe\xbe\x43\x62\xd9\xf7\x1d\x77\x8b\xdd\xbe\x12\xdc\x56\xfb\x9a\xe3\xb4\x5c\xe4\x51\x5b\x72\x18\x9b\x83\xd8\x05\x08\x6c\x96\xd7\x20\xda\x61\xb3\xc2\xc7\x0c\x22\xde\x49\x20\x0c\xdf\x4c\x44\x28\xe7\xa5\xd7\xce\x03\x17\x79\xc3\xbf\x5d\x06\x90\xac\x15\x31\x1a\x1f\x7d\xe4\x28\x60\x1a\x6a\x32\x0e\x8d\xd3\x42\x93\x00\x58\x47\xb7\x54\x25\x8f\x2a\x98\xf9\xb5\xd2\xcb\x35\x6b\xb7\x1e\xaf\x41\x69\xbd\x7e\x82\x9a\xdf\xf3\x2c\xa1\x58\x70\x79\x46\x71\xff\x9a\x92\x4b\xa6\x22\xa5\xe3\xd3\xd7\x45\x92\xf3\xb2\xac\x4b\x36\xb3\x5a\xf8\xca\x2c\x4f\x63\x87\x99\x94\xc2\xae\x33\x05\x76\x0b\xd1\x07\x48\x46\x2a\xb2\xd0\x3f\xac\x48\x42\x5f\xc4\x49\x4f\x50\xaf\x9e\xa7\x75\x76\xab\x8d\x40\x5d\x7d\xd9\x3d\x92\x5c\x4a\x9c\x1c\xec\xad\x40\x01\x41\xc8\xf3\x94\x1d\x1b\x11\x17\xa9\x40\x7f\xf2\x04\xb2\x0e\x9e\x01\xa6\x68\xd7\x6e\xb5\xb4\x90\x58\x21\x11\x17\x13\x6a\x25\x96\x20\xdd\x41\xe3\xbb\xbf\x37\xf0\x63\x11\x66\x18\x41\x6b\x3b\xe6\xbb\xa3\xe9\x94\x34\xf5\x68\xd6\xda\xb4\xb5\xa5\xd7\xb3\x9f\x86\x44\x31\x9a\x35\x98\x50\xbe\x05\x72\xe3\xee\x2d\x94\x71\x08\x97\x5d\x27\x30\x8b\x4b\x66\x7e\x69\xcb\xac\x42\xc2\x4c\x4c\x07\x19\xf0\xca\x24\x29\xbb\xc4\x83\x49\x08\x7d\x4b\x06\x3c\x9c\xfd\x55\x38\x26\xad\x4c\x10\x11\xcd\xb7\x37\x15\xce\xb7\x70\x9e\xe9\x3b\x35\x69\x64\xe9\x99\x4d\x20\x5f\xc0\x30\x69\xe2\x22\x8a\x6f\x6f\x24\xf0\x15\x66\x8b\xa7\xea\x89\x46\x1e\xc5\xa0\x1a\x3b\xb4\x24\xc2\x77\xd6\x79\xa0\xb9\xf8\xce\xea\xfd\x28\x4f\xb5\xfa\x5e\x9c\xdf\xd0\x8d\x70\x12\x6c\x9b\xd4\x7c\x2b\xb6\x72\x58\xcb\x2d\xfa\x21\x51\x80\x29\x5b\xfa\xc2\x9f\x28\x7e\xdf\x00\x43\x83\xda\xc0\x47\x2e\xa0\x3f\xd5\xb6\x41\x41\x60\x16\xd9\x75\xb5\x73\x3b\xb2\xf1\x78\xa7\xf0\x9a\xea\xc1\xca\xb9\xdd\x23\x49\x0f\xd1\x2b\xb0\x86\x70\x0f\xf0\x8d\xa2\x1f\x1a\x09\xae\xfc\x3f\x43\x18\x25\x20\xed\x50\x9a\x79\xfc\x30\x5a\x3f\xde\x5b\xd1\xa4\x2f\x19\x5d\xcf\xc6\x76\x80\xa6\x78\xf5\x55\x3d\xe0\xc8\x37\xef\x20\x89\xae\xc0\x1a\x05\xb6\xf4\x44\xc5\x80\xaf\xb5\xce\x73\x06\xd9\xf3\xdb\xcd\x6c\xcd\xdf\x53\xc5\x3d\xb3\xf0\xe0\x5b\x6a\xcd\xbb\x19\x6a\xb8\x67\x0d\x0d\x4a\x1b\xed\x67\x5b\xe1\x1d\x24\x6b\xd9\xe9\xdf\xff\xe0\x86\x58\x42\xfc\x8f\x6e\x88\x21\x6b\xd5\xb4\x4b\x39\x83\x00\xa1\xeb\xea\xb1\x27\xf6\xe6\x06\x5f\xe2\xff\xd0\x4f\x38\x1c\xb0\xd6\x37\xbe\xde\xda\xc1\x8e\x5e\xe3\x9b\x6d\x98\x26\x5e\x70\x9a\x5b\x28\x00\x77\x3e\xc7\x7a\xa4\x10\x9c\x5c\xe6\x35\x24\x8b\x0f\xf0\xe8\x5e\x2a\x05\xec\x21\x97\x91\x1d\x68\xc6\x51\x65\x0f\x7c\x23\x95\xba\xe4\x8c\xac\x24\x95\xb1\x6b\x2f\x29\xae\x22\x01\xbf\xa5\x94\x0c\x16\x6e\x5a\xd5\x50\x77\xd6\xde\x8e\x3d\x70\x76\x10\x19\x0a\x93\xc5\x15\x24\x8b\xf7\x21\x79\x5e\x03\xb7\x2a\x16\x9b\x34\xea\x54\xb9\xcd\xa0\x66\x65\x9e\x0f\x6a\x0e\xcf\x23\xb7\x53\xb2\x9f\x8d\xdb\x4b\x25\xfb\xd9\xa8\x01\xe4\x7c\x00\x00\xf6\xf4\x28\xe4\xa5\x74\x0b\x0a\x85\xbc\xc4\xab\xb6\x3b\x55\x87\x06\x83\xb0\x29\xbc\x09\x62\xca\x89\x12\xc4\x4f\x4d\x5b\x45\xb7\xa3\xb3\x56\xd9\xf5\x7f\xaa\xc6\x3b\x86\x7e\x8b\x9f\x39\xc3\x6d\xad\x77\x7e\x90\x7d\x60\x85\xc1\x05\x01\x87\xe9\x17\x4e\x0f\xac\x70\x73\x3b\x1b\x29\x84\x9e\x0f\x15\x42\x9f\x1e\xab\xbd\xeb\xa5\xa9\x9d\x1f\xc6\xc6\x8f\x83\x72\xb1\xc2\xd7\x37\xbd\x34\xe2\x26\x66\xcc\x6a\x9c\x95\xcc\x57\xe8\xb4\xf0\x52\xcd\x8d\x6c\x76\x6a\xb1\xea\xa7\x21\xe7\xde\xba\x67\x65\xf3\xca\x67\xc5\x97\x76\xca\x60\x37\xba\x0b\x44\x69\x3d\x36\xb7\xca\xd7\x3b\xe9\x76\xb5\x87\x57\x44\x33\x5c\xd7\x0c\x26\x7e\x01\x30\xf1\x52\xba\x9d\x78\x0f\xda\xc7\x05\xac\xdb\xa6\xde\x2b\x2f\xc1\x5c\x2b\xc3\xf2\xe2\xa9\x78\x4d\xc9\x4b\xa5\x40\x2b\x59\x93\x04\x44\xbb\x30\x30\xa5\x19\x86\xb7\xa0\xb8\x24\xa1\xe8\x32\x82\x2c\x61\x33\xea\x33\x1d\xe9\xcd\xb1\xa1\x77\xeb\x3f\xfb\xd0\x86\x77\x98\x92\xc1\x82\x14\xbb\x6d\x58\x04\xbc\x01\x4b\x1e\x88\x56\xfb\xe2\x29\x6c\xdf\x19\x05\x4b\xc0\x48\xb8\x5e\x3c\x15\xd7\x72\x74\x8b\x80\xbd\xc4\xcd\x74\x12\x92\xab\x67\x40\xae\x79\x0a\x47\x95\x3a\x1c\x4a\x24\x2b\xa8\x42\x58\x81\x17\x33\x46\x87\xad\x7b\x89\x96\xbc\x1f\x9c\x1a\xc4\x6b\x8c\x18\x7b\x1d\xd2\x08\xd6\xa8\x43\x7e\xbb\x94\xae\xb9\x2f\x31\x91\xc1\x50\xb2\x00\x79\x02\x53\x98\x17\x6e\xd9\x28\x1e\x48\x34\xe5\x15\xd1\x75\x31\x2d\x1d\xa0\xbd\x75\x94\xc6\x51\xcf\xe3\xe3\x7c\x94\x0e\x7e\x38\x83\xda\x6a\xe7\x29\xf0\x08\x44\x17\x07\x67\xd5\x77\x90\xcc\xf2\x4d\xee\x7e\xfc\xde\x42\x2f\xb3\x8e\x95\x76\xa4\xdc\xcd\x2f\x47\x5e\x5f\x11\x8e\xfc\x21\x28\xea\x19\x08\x2f\x6c\xbf\x58\x2a\x56\xd8\x8e\x11\x21\xc3\x72\xec\xe8\x92\xb7\xcb\x4b\x83\x64\xc9\xa2\xda\x04\xc3\x15\x48\x9d\xd9\x28\xf7\xd2\xb9\x03\xd8\xa1\xb3\xda\x1f\x2e\x4e\x84\xf6\xe4\x73\x08\xd7\x0e\x60\xcd\x3d\x1a\xb2\xa2\xe3\xd6\xa7\xd8\x88\x64\xe4\x17\x59\x0c\x1a\x08\xca\xf9\xd2\x05\x6b\x1a\x8b\x6c\xa5\x80\x65\x50\xb9\x46\xf6\xf2\x33\x0a\x27\x30\xa4\x14\x98\x9d\x2c\x49\x33\xc7\xa0\xa7\x9c\x7b\xa5\xf7\xfa\x64\x59\xd6\x69\xfe\x70\xa3\xbc\x78\xf8\x13\x38\xcd\x3a\x25\xb6\x9d\x5d\x43\x34\x5a\x0c\xa9\xdb\x05\x14\x3f\x12\x0e\xed\xea\x7c\x51\x82\xee\x9d\x1b\x0c\x3f\xcb\x45\xda\x0f\x76\xa7\xd7\xda\xe3\x84\x2c\x14\x60\x00\x7e\x3b\x74\x1b\xd7\x72\xa8\x89\x96\x78\x51\x08\xc2\x40\x85\x0c\x5c\xa1\x76\xc8\xec\x28\x78\xcd\x63\x58\xac\x20\x62\x90\xb7\xc4\x0c\x43\x56\x26\x7b\x76\x35\xb0\x7d\x18\x7a\x32\xc7\xa3\xf7\xbd\x1d\x42\x17\x70\xb1\x7d\x09\x17\x82\x0b\x04\x2f\x78\xef\xa5\x25\x93\xee\x3a\x78\xc5\x20\xe9\xe7\xc5\x79\xef\x55\x7a\xb9\x36\xe0\x05\x9a\xda\x1e\x4c\xd2\xab\x66\x2d\xc5\xf7\x69\x42\x7b\x53\x58\x0e\x1b\x38\xd3\xc0\xf3\xc2\xbb\x92\x41\xc8\xca\xc3\xab\xc4\x68\x48\xe9\x21\x44\x3b\xc4\x08\x1e\xe8\x1a\x40\x5a\xd7\xbc\x01\x3b\xe9\xc8\x0a\xe9\x44\xfd\xfb\x42\x85\x5e\x54\x9f\xeb\xc7\xca\x06\xe0\x9d\x66\xf4\x4c\x9a\xdd\x33\xb9\xb2\x29\x0b\x06\x68\x97\xd9\x94\xdd\xf7\x1a\x80\x1d\x28\xf2\xc4\x84\xba\x17\x17\xfd\x05\x95\x87\x12\x39\xf5\x86\x84\xd2\x50\x0a\x92\xd2\x25\x18\xdf\x7f\xa1\x92\x19\x08\xf7\xb4\xbe\x6c\x3b\x17\xb5\x61\x89\xf2\x7a\x1a\xd3\xf2\x26\x60\xca\xfc\x9a\x1c\xd3\x49\x7f\x28\x2e\xc4\x5f\xf1\x17\xa5\x83\x12\x11\xb9\xb7\x81\xd3\xa6\xfe\x7f\x04\x19\x64\xb3\x70\x72\xff\xae\x2a\xd0\x86\x17\x74\xdb\x9d\x22\xdc\x8e\x60\xf1\x05\x17\x0e\xd6\x42\x44\x9d\xb2\xb2\x5e\x60\x4a\xfe\xca\x2d\xa6\x28\x88\xca\xd7\xc6\xf8\x7c\x2d\xa5\x33\xcd\x8a\x01\xc1\x29\x7d\x6e\xf6\x96\x35\x99\xd0\x4f\xda\x9b\xd5\x06\x50\xcb\x87\x49\xd6\x4a\xa7\x9a\x71\xd0\xfe\x08\x81\x72\x6d\x63\x3b\x74\x1d\x86\x34\x88\x91\x1b\xd2\xb8\x9d\x13\xe7\x20\x4c\x85\x68\x1e\x17\xe2\xa5\x75\xdc\xee\x1e\xdf\xbf\xbd\xb6\x03\xa7\x80\x7e\xaf\x05\xcb\x73\x6d\x5a\xf1\xec\x4d\x99\x5e\x58\xb9\xc5\xc8\x89\xf8\x96\xbf\x2b\x22\x28\x72\x78\x44\x8c\x8e\xa8\x56\xdb\x95\x78\xf6\xf6\xf5\xff\x75\xe6\x72\x84\x7c\x34\x72\x75\xd7\xf4\xbd\x04\x93\x59\xc4\xc9\xc1\x68\xb3\xfd\x99\x9e\x9c\x62\x1c\xf0\x48\x96\x1d\xd0\x04\xbd\xef\xc2\x00\x78\xf5\xd9\xc3\xad\xa7\xb1\x9e\x5e\xbb\xde\xe9\xed\x0e\xcc\x3d\x74\xa7\xb6\xe8\xe6\x11\xb6\xed\x8a\x67\x32\xf0\x5d\xf4\x9e\x1d\xf0\x5b\x74\x73\xf5\x8b\x74\x2a\x07\x81\x21\x02\x80\x38\x44\xd2\x63\xa8\x46\xb5\xe4\x5f\x2d\x2e\x39\xf7\x24\xf4\xf4\x19\x72\xa0\x48\x91\x43\x08\xad\x77\x7a\x6b\x1e\x6a\x78\xfd\x25\x90\x46\xd5\xb5\x14\xaf\xa0\x88\x45\xb9\x9a\xd5\xc0\x46\x6e\xf0\x8c\xc7\x9b\xfb\x5b\xe3\x46\x6e\xfa\xcd\xf8\xa5\x96\xef\xa5\x86\x90\xa6\xf0\x7f\x0a\x76\xa7\x06\xbd\x39\xd6\xdb\xc1\x8e\x7d\x9d\xd1\xe4\x0b\xf1\xef\x90\x23\x20\x27\xa3\xd6\x54\x0e\x0b\xd0\x55\x22\x04\x9e\x84\xb1\x7e\x01\xd0\xd9\x6c\xa4\x81\xc7\x12\xf8\x06\x49\x84\xc4\x47\x48\x0a\x88\xd4\xf0\xc6\x9a\x20\x5f\x60\xac\xa0\x0e\x0d\x7f\xb1\x58\xec\x05\x18\xa1\x4b\x0d\x0f\x47\x5f\x51\x5c\x70\xbc\xd5\xcb\x56\x41\xc2\x18\x90\xa8\x36\x08\xda\xd8\x2d\x5a\x1c\x09\xdd\x15\x00\x40\x20\x9e\x00\x30\x1d\x4b\x17\x8a\x82\x06\xfd\x42\x3c\x57\xbe\xd9\x89\x94\x15\x0a\xd1\x6e\x44\x2f\xae\xcf\xbc\x5b\x63\x9f\xa1\xb2\xa2\xcb\x78\xc1\x1c\x01\xd0\x24\xa5\x80\xd8\x07\x0e\xa8\x76\x32\x1c\x17\x4e\x5c\xb6\xe2\xe6\x92\x49\xcd\xde\xf7\x35\x5d\x0c\xdc\xbc\x7e\x7f\x7d\x0f\xed\x0a\xa0\x44\x57\x00\x32\x23\x2e\x21\x8b\x08\x0c\x64\x65\x54\x86\x03\x2e\x21\x9d\x72\x1c\x54\x54\xb5\x44\xb0\xdc\x32\xdc\x7d\x1c\x74\xd8\xe1\x83\x72\x7e\xd0\x0d\xbe\x93\x4f\x65\x56\xe2\xf5\xd8\x79\xdd\x77\x8a\x53\xd8\x0e\x16\x62\x2d\xf4\x72\xe0\x17\xc5\x1b\xbb\xdf\x4b\xf1\xe0\xfc\xc1\xaa\x38\x05\x6a\xdf\xb9\x14\xa8\xf5\xfd\xd5\x8d\xf8\xd5\x34\xc3\x11\xcd\x65\xa8\xa7\xb7\xba\x0f\x60\x35\xae\xf9\xd0\xe1\x5b\xdd\x03\x2c\xae\x75\x26\xb7\x72\x5f\x3b\x35\xdc\xe9\x26\xee\xc9\xeb\xcb\xd7\xa0\xc2\xd3\x8d\xca\x89\x3d\x55\x0d\x2f\xdf\xb1\x10\x95\x1a\x71\x39\x7a\x5b\x08\x51\x5c\x2a\x7b\x60\x6a\x7a\x3c\xa2\xa5\x0b\x8f\xeb\x8c\xc7\x2e\xa1\x0b\x56\xbb\x38\xfa\x78\x59\x9c\x2a\x16\xb9\xfa\xec\xee\x2d\x9d\xc9\x53\x69\xae\x2c\xfe\x25\xcf\xc0\x55\x71\xda\xe6\xac\x57\x89\xe7\x2b\x8d\x4e\x73\x64\x19\x9b\x7c\xdf\xb8\x2d\x46\x51\x2c\x4b\x14\x90\x35\x32\x00\x64\xfd\x33\x41\x1d\xed\x80\xe6\x25\x72\x4b\xad\xf9\x18\x2f\x18\x73\xde\x63\xc0\x49\x4b\x14\x78\x67\x1d\x1d\x43\x4f\xa0\x46\x2e\x1a\x60\xd6\x47\xb4\x20\xa2\x4b\x66\x32\x88\x48\x8c\x7a\x0a\x14\xab\x1c\x41\xe5\xf1\x50\x71\x01\x00\xef\x43\x9c\x73\xd6\xcd\x09\xe7\x5c\x36\xe3\x0b\x0c\x34\xa2\x41\x09\x9c\xfc\xb0\xd8\x77\xe3\x2a\x5b\x74\xc4\x94\x4c\x5c\x36\xe8\x38\xd0\x7e\x37\xae\x6b\xd9\xeb\x5a\x99\x16\xdd\x78\x2e\xc4\xe5\xf5\x2b\xf1\x2b\x7d\x56\x64\x60\xb1\x32\xd6\xd7\x0e\x1c\xa2\x7e\x00\x0f\x38\xe5\x7f\xe4\x2c\xd2\xc4\x47\x4b\x0c\xd2\xc4\x37\x85\x41\x06\xc1\xae\x07\x69\x5a\xde\xf3\xbf\x84\x0f\x74\xbb\xa2\xec\x61\xc4\xb3\x08\xef\x6a\x61\x30\xf3\xac\x3d\xfa\x99\x85\xac\xf0\xb3\x6c\x40\x8a\x16\x3e\x09\x30\xfe\xe1\xdd\xd5\x04\x72\xca\x16\x96\xb9\x19\x5f\x19\xd9\xc9\x12\x62\xe7\xc3\xb9\xd0\xb6\xa1\x9d\x10\x85\x2e\xfc\x56\xce\x2d\x81\x11\xe5\x07\xb0\xf0\x7b\x02\xd3\xa8\xc1\xb3\x3b\xe3\x53\x35\x90\x0a\x08\x3d\x0e\x27\xa0\xb7\xea\xc8\x90\xff\xaa\x8e\x4b\x10\x81\xf4\x86\xd3\x2e\x99\x85\xbc\xd6\x06\x74\x16\x81\x04\xb3\x7d\x48\x59\x66\x34\xfa\x73\xed\x2c\xe8\x48\x33\x4f\x09\xf0\x01\xfd\x2c\x30\x23\x13\xbd\x27\xa5\x41\xfa\xae\x07\x6b\x3d\x8d\xfa\x15\x8a\xe3\xd6\xfa\x85\x71\xb7\x9b\x4d\xa7\x8d\xe2\x79\x7c\x8b\x9f\x4b\x73\x49\x31\xa7\xea\xc1\x8e\x78\xdf\xb1\xcd\x5e\xa1\xc1\xc4\xb0\xb3\xa6\x2b\x00\x4f\x8b\xed\xef\xc0\x5e\xd1\x21\xf1\xe2\x77\xdd\x4f\xe0\x64\xdf\xd7\xa0\xc3\xed\x25\xba\xf9\x66\xb6\x38\xa0\xc4\x0d\xe9\xb3\x9e\xca\xb6\x96\xce\x29\xef\xea\xcd\x60\xf7\x75\xab\xdd\x2d\x79\xd6\x09\x4c\xa7\x57\x70\xb4\xbb\x9d\x96\x95\xe0\xd8\xc5\x43\x84\x5f\x30\x3e\x11\xd0\xed\xb2\x0d\x74\xf3\x72\x79\xf7\x38\xb7\x5b\x10\xc9\xb2\xcc\xb8\xb0\x7f\xfd\xdc\xc3\x9b\x9a\x6d\xb9\xc0\xdd\x8e\x45\x1d\x06\x28\x96\xa4\xdb\xad\x60\x2a\x69\x58\xde\x85\x59\x2c\x86\xc2\xed\xc2\x2a\xdc\x2a\xc3\x20\xff\x0a\x5f\x4b\x40\x35\xc4\xcf\x4b\x60\x18\x7b\x6f\x0a\xb8\xc7\xf5\x89\x9e\xf2\xfa\x77\x85\x4f\x00\x67\x0b\xf7\x56\x1d\x05\xc8\xc0\x90\x71\x5f\x51\xb7\x50\xca\x15\x5d\x53\x64\x04\x5d\x5e\x49\xd7\xd2\xd7\x41\x1e\xf7\xd9\xdd\xf5\xf7\x13\x98\xef\x85\xf4\x60\xf9\x53\x8c\x15\x24\xd4\xf4\x50\x43\x8d\x73\x4d\x42\xbd\x8f\xef\x37\x60\x72\x5e\x0c\x58\x64\x53\x13\xb7\x08\xfc\xb0\x81\x08\x93\x0b\x40\x34\x5b\x04\x34\x9d\x2c\xa6\xbc\xba\xdf\xf1\x53\x37\x48\x7a\x31\x21\xae\x2e\xd4\x46\xf2\xf2\xca\x14\x1e\x8b\xab\x2c\x40\xdf\xbf\x0e\x00\x02\x6d\xa5\x59\xaa\xbf\x81\x2f\x38\xe7\x0a\x28\x69\x9c\xae\x9b\x9d\xf4\x78\x78\x5c\xbe\xb9\x79\x05\xbe\xf4\x4e\xf9\x02\x0e\x5e\x96\xaa\x93\x1e\xe5\x39\xbe\x34\x45\xda\x94\x1c\x72\x2f\x3f\x27\xcd\x2a\x28\x4d\x51\x37\x2b\xa2\xaa\x16\x12\x8b\x32\xfd\xa0\x30\x18\x6e\xdd\xe9\x46\x19\x47\x8f\x8d\x51\xa2\xe0\xc4\xa2\x0c\x93\x20\xa0\xe2\x5b\xa8\x85\x09\x10\x10\xf3\x17\x93\x3a\x88\xf8\x20\x45\x0c\xa3\x55\xef\xf5\x36\xbe\xe4\x47\xc4\x08\xb5\x95\x30\xae\x31\x77\x09\xcb\x20\xd1\xc9\xbd\x1e\x94\x69\xd5\xc0\x14\x93\xb0\x0c\xf2\x80\x76\x14\x98\x5b\x10\x50\xc0\x42\x0e\xdc\xf5\x26\x48\x50\x61\xe6\xf1\x6a\xb6\x39\xa6\x57\xca\x05\xe4\x89\x2c\xaf\x6c\x47\x1b\x56\xc8\x0a\xc8\xf5\x61\x90\x3d\xbc\x01\x62\x1c\x99\xf8\xfd\x0a\xb9\x02\xa8\x77\xc8\x15\x29\x77\x09\x0b\x79\x28\x43\xcf\xa0\x57\xa1\xc1\x19\x9e\x2c\x1f\xfb\x05\xf9\x05\xa6\xb1\x0f\x04\x38\xa3\x7e\x1f\x20\x41\xa8\x92\x08\xe6\xb0\x5e\xed\x7b\x5e\xc2\x04\x1d\x92\xec\x20\x87\xe3\x7c\x39\x53\xa1\x18\x02\xf7\xd8\x2b\x97\x0a\xc6\x40\xb7\x21\x79\xa9\x1c\x76\x4b\x7e\xae\x49\x61\x47\xe5\xa0\x37\x90\x34\x5f\x94\x54\x32\x14\xe2\x60\x03\x59\x29\x47\x25\xb8\x48\xbb\x4e\x3b\xf8\x19\x9b\x41\x2e\xee\xdf\x76\x5d\x68\xf2\x52\x6a\xae\xf7\x4a\xa9\xb9\x1e\x30\xa5\x12\x17\xf6\x21\xe3\xc0\xda\xf5\xca\xb9\x8e\x97\xe2\xcd\xcd\x55\xb1\xee\xb2\xdc\x24\x9e\xfe\xb0\xb1\x83\xf8\xbe\xb7\xce\x6f\x07\xe5\xbe\x17\xd6\x74\xc7\x1f\xb3\x12\x34\x3b\xd7\xd9\x64\x50\xea\x14\x87\xfb\x5b\xa7\xbd\xfa\xf3\xf7\x88\x21\x9d\xaf\xa4\x0b\xcc\x98\x4f\xd2\x04\x2e\x1f\xa0\x94\x4b\x6c\xf3\xa0\xc8\x41\xa9\x95\x60\xba\x84\x7c\x33\xa7\x8a\x90\x3a\x2b\xd9\x58\x7b\xab\x55\x2a\x4a\xc3\xf7\x8e\x0b\x61\xfe\xa9\x62\x4b\x1a\xb1\xfb\x4b\xc0\x77\xb6\xf7\xe9\xfb\x44\x21\x7a\xf2\xa2\xee\x07\xfb\xf9\x88\x32\x14\xf3\xd3\x98\x23\x20\x67\x2a\xf1\x60\x80\x85\x19\xb6\x48\xd2\x40\xc6\x00\x13\xdd\x1a\x2b\xce\x29\x1a\xc8\x1a\x68\xd7\x7b\xa2\x55\x0b\x08\x78\xdc\xae\x16\x8a\x73\x79\xb5\x97\xba\x4b\x53\x8b\xea\xb5\xc5\x79\x05\xc8\xd3\xac\x11\x66\xbb\x11\xac\x31\xea\x70\x18\xe8\xcf\xa0\xd8\x83\x04\x81\x09\x25\xf0\xc2\x5e\xc1\x0c\xe0\xf1\x2e\xc4\xf3\xc1\xee\xcb\x8c\x85\x1d\x83\x19\xf1\x20\x51\x9d\xcd\x0f\x91\x5f\xaf\xde\x4e\xea\x54\x9d\x05\xb6\x80\xa3\xa9\xfe\x7a\xf5\x56\xf0\xf7\xa4\x2f\xb7\xba\x9f\x68\x59\x9a\x4c\x7a\xc0\x9c\x59\xfb\xea\x1c\x06\x5f\x6f\xa2\x70\xb3\x59\x46\x59\xea\x6b\xe4\x13\x84\xbc\x47\x3c\x49\x0d\x00\x75\x74\xed\xd5\x67\x4f\xf5\x27\xfd\x74\x09\x2c\xdb\x36\x03\xae\x25\x5c\x36\xc0\x9b\x85\xb1\x80\x90\x1d\x48\x78\x10\xc4\xae\x1c\x1d\x65\x5a\xe4\x3f\x49\x33\x0b\xb7\xed\xc0\x80\x02\x40\x09\x1d\x01\xeb\x0d\x06\x17\xb9\x10\xcf\xf1\x87\xb7\x18\x53\x36\x95\x0c\x49\x41\xa0\xfe\x59\x9c\xdd\x9d\xc2\xe2\x30\x78\xc7\xfb\x54\x28\xbd\x02\x4e\x61\x76\x03\x8a\x55\x5c\xe7\xb0\x4d\xe3\x32\x9f\x68\x01\x16\xd7\x7b\x28\x11\x95\x57\x10\x7e\xa5\xee\xc8\x08\x97\xed\x17\xf0\x39\x53\x48\x2d\x4a\x0d\xca\x05\x49\x8f\x2f\x13\x8a\xb2\xef\x42\x5e\xba\x48\x38\x89\x01\xdf\xdd\xcc\xb6\x27\xbc\x63\xc3\x8f\x79\xaa\xb4\x4f\xd9\x01\x62\xa9\xb8\xd3\x5b\x53\x07\x61\x15\x63\x97\x70\xe9\x90\x2c\x34\x7a\x37\x15\xe5\xa2\x48\x98\x1b\x4d\x64\x42\x61\xae\x06\xcc\xcb\x31\x47\x95\xe5\xd7\x8d\xec\x7d\xb3\x93\x19\x47\x95\x23\xa5\xdc\x65\x2c\x53\xfa\x5a\x78\xa7\x44\x6c\xa7\x69\xed\x57\x61\xb5\xd3\x5e\x9e\x42\x6c\x4f\xf7\xfb\xbe\xa6\xd6\x31\xa2\xce\xd7\x1c\x0b\x8c\x16\x54\xfd\x71\x9d\x82\xaa\x7d\x71\x75\xc2\xfb\x02\xd4\x35\x5c\x24\xd1\xec\x85\xfa\x81\x4b\x24\x0f\xb8\x9f\x1d\xe9\xe8\x07\x96\x9d\xe8\xa8\x91\x38\x71\xa0\x43\xe6\xaa\x1f\xec\x9d\xa6\x08\x43\xf4\xf3\x14\x48\xc2\xcc\x90\x84\x7a\x5a\xa0\x3c\xa8\x9e\x4e\x8e\x36\x84\x09\xc2\x81\xe3\x10\xbd\x41\x2c\xb8\x01\x1e\x67\x0a\xb6\x6d\xf0\xb1\xbf\x3b\xb0\x6c\x78\xf1\x54\xf0\xd7\x14\x30\x30\x83\x9d\xde\x28\x36\xc2\x0a\x72\x4d\xf8\x46\xbf\x9d\x69\x03\xdd\xb0\x99\x1c\xa7\x4f\x6f\xde\x3d\x9f\x1e\xa3\x68\x4b\x17\x7b\x8d\xd6\x73\x8b\xa3\x09\x90\x2b\xd9\xca\x9e\x2f\x4b\xe0\x57\x99\x7d\x7f\x47\x10\x26\x3f\x3d\x39\x07\xe4\xa8\xd8\x0a\x10\xa1\x16\x1b\x11\xe0\x56\xe4\x20\x0c\xcf\xbe\xd9\x0e\x43\x69\xd4\xf8\xc4\x19\x9a\x18\x28\xe7\x04\xe5\x22\x73\x4e\x0f\xa0\x25\xa2\x1a\x1d\x4c\x32\xd2\x1a\xd3\x4e\x90\xd5\x98\x7f\x9a\x97\xc8\x60\x16\xb8\xd7\x2c\x77\x2a\x49\x5c\x2e\x89\x10\x19\x7c\x26\x3c\xdc\xcc\x04\x86\x09\x1c\xcb\x0b\xcf\x17\x04\x05\x0e\xd2\x94\xc9\xfb\xe4\xc3\xb7\x2c\xec\x53\x38\xb0\xa5\xae\x67\xe3\x35\x93\xb3\x66\xc5\x66\xfd\x4d\x85\x4f\x48\x4f\x33\x14\xd9\x10\x64\xa5\x97\xc4\xa7\xc5\xa2\x3c\x2a\x59\xd9\x25\x49\xaa\xd7\x60\x36\x9a\xd1\x01\x4c\x58\x1e\x20\x82\x5e\x51\x98\x0f\x14\xda\xa2\x58\x19\x68\x20\x85\xf8\xc0\x9c\x42\xb0\xe4\xb2\xe8\xe6\xb2\x84\x20\xd3\xc5\x7c\x19\xcd\x76\xe0\x58\x23\x6c\xb4\xf7\x62\xe0\xf8\x22\x78\xc1\x34\x29\xc0\x47\x26\x17\xcc\x8e\x4b\x2e\x39\x2d\x42\x64\x7b\xa3\x5a\x88\xc9\xd6\xd6\xb1\x24\x91\xee\x98\x43\x0d\x4e\x5a\x26\x7a\xab\x37\x0e\x2b\xbd\xd0\xbb\x38\xaa\x08\x1b\x2f\xd3\x32\x9a\xc2\x2f\xcc\x47\xc2\xc2\x45\x38\xec\x7f\xc4\xcf\xe1\x7c\x17\x2b\x88\xaf\x78\xd0\x6a\x7c\x9f\x2f\x3d\xce\xa4\xe8\xbd\x40\x6c\xed\x48\x56\x5f\x21\x45\x50\xca\xb4\xc0\x3d\x17\x9c\xc4\x72\x73\x89\xad\xce\xe8\xce\x0b\x7d\x82\xe0\x6c\xb5\x8f\x93\x04\xb1\x1c\x77\x7a\xbb\x83\x17\x5f\xb3\xa9\xc2\xf8\x85\x47\xe3\xe5\x67\x11\xf3\x73\x0c\x61\xed\x43\xe9\x4e\x1b\x74\xc4\x0a\x25\xf0\x03\x15\x64\x20\x43\x4b\xe1\xb4\xd9\x92\x8a\xe5\xc7\x93\x08\xea\x2c\x4a\x26\xa1\xca\xe3\x66\x2e\xe0\x0b\xa5\x96\xf1\xf1\x8e\x04\x2c\xd9\x5e\x9c\x20\x08\xb0\x05\x82\x6d\x53\xcb\x61\x4b\xf6\xc0\x72\xd8\x8e\xe0\x28\x58\x54\x01\xda\x33\x95\x4d\xdd\xeb\xa8\x6d\x9b\x4c\x1e\x82\xc3\xda\xcc\xa1\x61\x71\xa2\x12\x6c\xa1\x00\xf8\xd4\x67\xf0\x4f\xd1\xc7\x7e\x0e\x08\x61\xcd\x13\x1c\x44\x34\x5f\x00\x23\x13\x67\x04\x7a\xf1\x34\x82\x30\x4c\x67\xb7\x69\xbd\x5c\xd9\xed\xf2\x7a\x09\x50\xa8\x16\xcc\xd4\xb3\x01\x1a\xb5\x81\x53\x3d\x6d\x00\x27\x75\xcd\xeb\x4c\x55\x13\x92\xe7\xf1\xa0\xd8\x35\x7a\xd5\x0c\xf8\x80\x56\xf8\xf7\x5e\xba\xdb\xe8\x34\x5d\xa8\x8a\x38\xcd\x35\x3b\xd5\x8e\x1d\xea\x80\xf1\x67\x82\x47\x39\x0f\xec\xd3\xc1\xda\x9c\x33\x40\xe1\x67\x47\xc7\x31\x0b\xc3\xcf\x02\x40\x7d\x56\xcd\x98\xb9\xaa\xfc\x8a\xdf\x64\x1b\x9e\xd0\x58\x0e\xb4\x32\x1a\xb0\x50\xb9\xc6\x94\x0c\x66\x21\x56\x59\x6c\x3a\x69\xfd\x51\x61\x7f\xb2\xfe\x58\x3d\x98\x7c\x04\x28\x76\x2f\x67\xaf\x66\xfc\x64\x03\x9a\x89\xc7\x39\xc3\x42\xe0\x52\x7c\x5e\x24\xb1\xdf\x10\xc1\x14\x21\x29\xb8\x65\x84\x27\xbf\x62\x12\xe9\xc2\x0c\xc5\x5a\x55\xa7\x1a\x88\x2f\x06\xec\x71\xf8\x08\xdc\x45\xcc\x6f\x55\x01\xf1\x8c\x3e\x0b\x18\x6d\x50\x3a\xc0\x2c\x14\x32\x5e\x61\x1a\xa1\xcc\xdc\xe8\xf9\x4e\x1e\x81\x29\x2a\x32\xdc\x7f\xdf\x50\xca\x14\x92\x6b\x06\xa0\xcb\xae\x9b\x8d\x46\xae\xa1\xcc\xd3\xe0\x45\xc0\x2c\xd6\x41\xd6\xa7\xe9\x34\x72\x96\xed\x61\x15\xaf\x66\xad\x8d\x17\xeb\x34\x23\x1c\x14\xe0\x4b\xce\x97\xd5\x47\x1c\xfb\x4f\x1c\x3c\x8f\xec\x7c\xd9\xbc\x3e\x73\x69\x2b\x62\x9c\x9f\x41\x68\xee\x6a\x50\x26\x7b\x64\x17\xbf\x8a\x42\xa0\x42\xc2\x67\x3c\xce\x3e\xfe\xf4\xc9\xf1\x3b\x1e\xde\x66\xf8\x3e\xfe\xe9\x53\x40\xf9\xf1\xcf\x9f\x10\x2b\xaa\xf4\x19\x6b\x3f\x42\x90\xff\xb2\xc4\x4f\x9f\xdc\x23\x37\x34\x8f\xa6\x65\x85\xf4\x13\xb0\x90\xf9\x3f\x12\xe2\x5e\x0e\xaa\xe6\xa0\xaf\xb4\x28\x31\x59\x3b\x6b\x28\xf0\xb3\x72\x0a\xe2\xfd\xd2\xdb\xc6\xf1\x49\x42\x6a\x11\x7f\x4f\xc6\x07\x7b\xb9\xdc\xc5\x34\x64\x34\xce\xf8\x4e\xf4\x85\xf8\x0d\x1f\x7e\xa0\x77\xa3\xb3\x02\x8f\xd0\x48\xf6\x11\x16\xfd\x27\xe8\x68\x40\xf0\x5b\x05\x8f\x46\x24\x04\xf8\x86\xc4\xb7\x20\xc0\xd7\x26\x12\x06\x7e\x7d\xe2\x9b\x1a\x41\xcf\x3f\xa4\x66\x60\x82\x6a\x05\x98\x95\x7c\x3d\x22\x1c\x8f\xc9\xeb\x1a\xbf\xf1\x02\xcc\x5f\xc9\x2e\x10\xc2\x6b\xd5\x27\x47\x67\x86\x0e\x07\xe9\x9b\xb1\xd1\x50\x4d\xd1\xc5\x11\xfb\x66\x84\xf0\x6a\xf6\x0c\x1f\xa4\xfe\x91\xce\xe2\xe0\xe1\x5b\xe0\xd9\xb6\x35\xea\x40\x0f\x84\xff\xe3\x9b\x86\x48\x4c\xac\x83\x09\x09\xe3\xa7\xcd\xfd\xa7\xb4\xb9\x17\xd1\xf1\xe6\x86\xf7\x62\xbc\xdc\x66\x3b\x5b\x6e\x8b\xce\x42\x13\xa1\x0c\xf5\x73\xbe\xf7\x73\x84\x1c\xc1\x08\x50\x72\xe3\x00\xe7\x37\xb6\x0c\x5e\xc4\xa1\x2d\x8e\xcf\xe0\xcc\x5e\x1f\x5f\xda\xd0\xc4\x6f\x81\xe7\x33\xbd\x93\x43\x3e\xca\x59\x6c\xe9\x7f\x74\x16\x90\x90\x62\x55\x45\x8d\xf1\x15\x22\xaa\x33\xcc\x3c\x5c\xf6\x2a\xd3\xa8\x7f\x60\x58\x4f\x56\x18\xed\xe1\xa8\x42\x78\xdf\x98\x46\x3d\xab\xf8\xdb\xc6\xbe\xa8\xad\xfa\xe8\xad\xed\x3e\x55\x72\x1b\x66\x42\x6e\x6d\x05\x46\x28\x18\xac\x0e\x00\x8d\x3d\x54\xf8\x19\x7e\xfd\x14\x08\xf9\x4f\xf4\x4e\x9f\x38\x73\xd5\x4f\x7b\x48\xd8\x6b\x13\xf8\xa8\x90\xb0\x83\x84\x9d\x1d\xe1\xd9\xe5\x9f\x5a\xf8\x6c\xe5\x11\xbe\x0e\xf0\x75\x50\xea\x16\x0b\x03\x83\xf0\x93\xd8\x5b\xe3\x77\x90\x72\x84\xef\xa3\x92\xf4\x68\x33\xbe\x07\x78\x11\x8e\x08\xfe\x38\x73\x15\x56\x47\xe9\xfc\x71\xe6\xaa\x50\x2b\xa5\xe2\xcf\x33\x57\xd1\x25\xdc\x59\x0b\x17\x6f\x21\x25\x54\x4f\x49\xf8\xf3\x0c\xf8\x3a\xbf\x63\x84\xf8\xfb\xcc\x55\xa1\x1d\x94\x88\x3f\xcf\x5c\x35\xc8\x43\x9d\xda\x45\xbf\x20\x35\xb5\x8a\x7e\x41\x2a\xb7\x09\xfe\x57\xd5\xc7\x76\xb0\xfd\xef\xd6\xa8\x4f\x15\x8b\xa9\x7b\xe5\xc8\x85\xf5\xd9\x60\x7b\xf6\x5c\x57\x03\xda\x01\x76\xba\xb9\xc5\x07\x11\xe1\x5e\xb7\xa2\x28\xc8\xb5\x36\xfd\x18\xed\x24\xc8\x5d\xe0\x81\x67\x41\x3f\xbe\x12\x88\x31\xae\x8e\xbd\x5a\x55\xc0\xe2\x7b\x6b\xeb\x35\x88\x03\xcf\xe3\x25\xf2\x0f\xff\xf5\x5f\x00\xaf\x7f\x57\x7f\xff\xbb\x78\xfd\xcb\x8f\x42\x7d\x6e\x94\x6a\x9d\xd8\x93\x73\x1a\x83\xed\xe5\xe7\xe7\x05\xe4\xaa\xa2\x80\x51\x74\x47\x83\x01\xa3\xf0\x9a\xe6\xff\x0b\x00\x00\xff\xff\x44\x2e\x85\x4c\xf4\x0d\x01\x00" +var _confLocaleLocale_enUsIni = "\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xb4\xbd\xeb\x72\xdc\xb8\x92\x30\xf8\x9f\x4f\x81\xee\x09\x85\xbb\x23\xe4\x72\xf4\x39\xdf\x7c\xbb\xd1\x61\xf9\xac\xda\x6e\x5f\x66\x64\x5b\x63\xd9\x73\xbe\x59\xaf\x83\x8d\x22\x51\x55\x18\xb1\x00\x1e\x02\x54\xb9\x7a\xe2\xbc\xc1\x3e\xc0\x3e\xdf\x3e\xc9\x06\xf2\x82\x0b\xc9\x92\xed\x3e\xb3\x7f\xa4\x22\x90\x48\xdc\x13\x99\x89\xcc\x84\xec\xfb\xba\x55\xae\x11\x17\xe2\x52\xf4\x52\x9b\x4e\x39\x27\x9c\xea\x36\x0f\x77\xd6\x79\xd5\x8a\x17\xda\x0b\xa7\x86\x3b\xdd\xa8\xaa\xda\xd9\xbd\x12\x17\xe2\xa5\xdd\xab\xaa\x95\x6e\xb7\xb6\x72\x68\xc5\x85\x78\xc6\xbf\x2b\xf5\xb9\xef\xec\x10\x80\x7e\xc5\x5f\xd5\x4e\x75\x7d\x28\xa3\xba\xbe\x72\x7a\x6b\x6a\x6d\xc4\x85\xb8\xd1\x5b\x23\x5e\x19\x4c\xb1\xa3\xe7\xa4\xb7\xa3\xc7\xb4\xb1\xe7\xa4\x0f\x7d\x35\xa8\xad\x76\x5e\x0d\xe2\x42\xbc\xa3\x9f\xd5\x41\xad\x9d\xf6\xa1\xa6\xbf\xe2\xaf\xaa\x97\xdb\xf0\x79\x2d\xb7\xaa\xf2\x6a\xdf\x77\x12\xb2\xdf\xd3\xcf\xaa\x93\x66\x3b\x22\xcc\x15\xfd\xac\x9a\x41\x49\xaf\x6a\xa3\x0e\xe2\x42\x3c\x85\x8f\xd5\x6a\x55\x8d\x4e\x0d\x75\x3f\xd8\x8d\xee\x54\x2d\x4d\x5b\xef\xb1\x53\x1f\x9c\x1a\x04\xa5\x0b\x69\x5a\x11\xd2\xa1\xc1\xaa\xad\xb5\xa9\xa5\xa3\x56\xab\x56\x68\x23\xa4\xab\x00\x95\x91\x7b\x2e\x1d\x7e\x56\x6a\x2f\x75\x17\xc6\x28\xfc\xaf\x7a\xe9\xdc\xc1\xc2\x40\x5e\xd3\xcf\x6a\x50\xb5\x3f\xf6\x0a\x3a\xfc\xf0\xfd\xb1\x57\x55\x23\x7b\xdf\xec\x64\x68\x26\xfe\xaa\xaa\x41\xf5\xd6\x69\x6f\x87\x23\xc0\xf1\x47\x65\x87\xad\x34\xfa\x77\xe9\xb5\x0d\x63\xfd\x36\xfb\xac\xf6\x7a\x18\x6c\x18\xc8\xd7\xf0\xa3\x32\xea\x50\x07\x3c\xe2\x42\xbc\x51\x87\x1c\x4b\xc8\xd9\xeb\xed\x80\xa3\x18\x32\x5f\xc3\x57\xc0\x82\x79\x84\x09\xb3\x22\xb6\x8d\x1d\x6e\x29\xf5\x79\xf8\x39\x41\x69\x87\x2d\xe5\x96\xed\x92\x46\x6e\x15\xe5\xbe\x86\x8f\x02\xc0\x55\xb2\xdd\x6b\x53\xf7\xd2\xa8\x30\x74\x97\xe1\x4b\x5c\x87\xaf\x4a\x36\x8d\x1d\x8d\xaf\x9d\xf2\x5e\x9b\x6d\x98\x83\x4b\x4c\x12\x37\x94\x54\x65\x79\x31\xed\x68\xc7\x38\xcb\xe2\x42\xfc\x87\x1d\x07\x71\x8d\x9f\x98\x97\x15\x82\xcc\x58\xb2\x92\x8d\xd7\x77\xda\x6b\x85\x95\xf1\x47\xd5\x8f\x5d\x57\x0f\xea\x6f\xa3\x72\x3e\x64\x5d\x8f\x5d\x27\xde\xd1\x77\xa5\x9d\x1b\xa1\xc4\x2b\xf8\x51\x55\x8d\x34\x0d\x74\xe7\x29\xfc\xa8\xaa\x8f\xce\x4b\x3f\xba\x4f\xb0\x98\x6b\x63\x7d\xbd\xb1\xa3\x69\x69\x59\x8b\x37\xd6\x8b\xe7\x21\xa1\xd2\xc6\x87\xc5\xd4\xd5\x61\x73\xaa\xa1\x56\x34\x19\xaf\x28\x5d\xdc\x40\xba\xf8\x15\xe6\xa5\xfa\xa8\x8d\xf3\xb2\xeb\x3e\x55\xf4\x03\x40\xe1\x17\x8e\xbf\xd7\x1e\x06\x81\x12\xc5\x8d\x57\xbd\x0b\x13\x28\x9e\xeb\xc1\xf9\x87\x5e\xef\x95\x78\x37\x9a\xaa\xb5\xcd\xad\x1a\xea\xb0\xad\x61\x43\xbe\xda\x88\xa3\x1d\x1f\x0c\x4a\x0c\xa3\x31\xda\x6c\xc5\x0b\xbb\x75\x42\x1b\xa7\x5b\x25\x9e\x01\xf4\xb9\xe8\x3b\x25\x9d\x12\x83\x92\xad\x78\x2c\x85\x97\xc3\x56\xf9\x8b\xef\xeb\x75\x27\xcd\xed\xf7\x62\x37\xa8\xcd\xc5\xf7\x67\xee\xfb\x27\x2f\x46\xdd\xaa\x4e\x1b\xe5\x1e\x3f\x92\x4f\x44\x23\x07\xb5\x19\xbb\xee\x28\xd6\x6a\x13\xf6\xe0\xd1\x8e\xa2\xd9\x49\xb3\x0d\xfb\xef\xe8\x77\xa1\x42\x6d\x84\xdf\x69\x27\xc2\x98\x7d\x57\x85\xd1\xd7\x5e\xd5\xed\x9a\x49\x1b\x34\x08\x92\x07\xe5\xc4\xeb\xe3\xcd\xbf\x5d\x9d\x8b\x6b\xeb\xfc\x76\x50\xf0\xfb\xe6\xdf\xae\xb4\x57\x7f\x3e\x17\xaf\x6f\x6e\xfe\xed\x4a\xd8\x41\xbc\xd7\xcf\x7e\x59\x55\xed\xba\xe6\x71\x79\x26\xbd\x5c\x87\x2e\xc4\x35\x10\x32\x71\x8b\xc6\x3c\xd8\xa8\x81\x70\x02\x91\x74\x1e\x36\x3f\x6d\xfc\xc5\x6d\xde\xae\x6b\xa2\x0d\x11\xc7\x9b\x40\x20\xda\x75\x1a\xe0\x6b\x1c\xba\xd1\x29\xf1\xea\xcd\x9b\xb7\xcf\x7e\x11\xca\x6c\xb5\x51\xe2\xa0\xfd\x4e\x8c\x7e\xf3\xbf\xd7\x5b\x65\xd4\x20\xbb\xba\xd1\x61\x6c\x06\xa7\xbc\xd8\xd8\x01\x7b\xba\xaa\x9c\xeb\xea\xbd\x6d\x43\x2d\x37\x37\x57\xe2\xb5\x6d\x03\xad\xf4\x3b\x68\x88\xdf\x55\xee\x6f\x5d\x18\xaf\x58\xe1\xfb\x9d\x12\xb0\x25\x00\xc8\x6e\x78\x78\x44\x4b\x6d\x5c\x89\xc7\xeb\xe1\x49\xd6\x2e\xb9\x76\xb6\x1b\x3d\x95\x38\xec\x94\x81\x79\x72\x5e\x0e\x5e\x48\xc7\x07\xc8\xaa\x52\xc3\x50\xab\x7d\xef\x8f\x61\x76\xa8\x0d\x53\xec\x88\xa4\x91\xc6\x58\x2f\xd6\x4a\x00\xfc\xaa\x32\xb6\x46\x0a\x10\xc8\x71\xab\x9d\x5c\x77\xaa\xc6\x83\x61\x60\x4a\xf7\x1f\x61\x71\x60\x41\x82\x10\x05\x44\x18\xb1\x70\xd8\x00\xd5\x0f\x2b\x47\x1a\x01\x48\x05\x91\x90\xbc\x85\x4c\x6f\xe2\xac\x21\xc9\x89\x09\xb3\x16\x56\x3c\x0d\xbc\x66\x2e\xfb\xbe\xd3\x0d\x56\xfd\x02\xf3\xd2\xf2\x09\x47\x2f\xcd\x7d\x0e\x07\xd3\xcf\x79\xd9\x22\x18\x7d\x18\xd2\x41\x14\xb4\x1d\xca\xef\xd4\xa0\xc4\x6e\xdc\xe2\x81\xd4\xd9\xb1\xfd\x0e\x4e\x06\x1e\xdf\x44\x7f\xc5\x3b\x6b\x3d\xce\x79\x04\x48\x55\x5c\x76\x1d\x9c\xf6\x83\xda\x5b\x1f\x06\x8e\x8a\x05\x1a\x77\xd0\x5d\x17\x7a\xea\xe4\x9d\x6a\x85\xb7\xb8\xdf\x5a\x3d\xa8\x26\x20\x5e\x55\xc3\x68\x6a\x5a\xec\xef\x46\x83\x0b\x9e\xd3\xca\x95\x05\x50\xfb\xd1\x79\xb1\x93\x77\x2a\x0c\x7c\x60\x39\xbc\x5d\x6c\x27\x74\x69\x18\x0d\x6c\xe1\x55\xd5\xda\xbd\x04\xf6\xe1\x19\xfc\xa0\xef\x1c\xbf\x76\x42\x6e\x36\xaa\xf1\x4e\xdc\xdc\xbc\x14\x4d\x67\x8d\x12\x1f\xde\x5d\xb9\xb0\x0d\x76\x75\x6f\x07\x60\x35\x6e\x5e\x8a\x6b\x3b\xf8\x98\x96\x0d\x74\x80\x30\xe3\x7e\xad\x06\x71\xd8\xe9\x66\x87\xc3\x1e\x4a\x20\xa5\x15\xda\x89\xd1\x69\xb3\x3d\x17\x9d\x0a\x3d\xd0\x1e\x17\x40\xe8\x03\xaf\xba\x00\xbe\x51\xd2\x8f\x83\x02\x66\xa2\x5e\x8f\xba\xf3\xda\xd4\xa1\x42\xc2\x03\x64\x41\xfc\x82\x19\x50\x02\x49\xf6\x09\xf8\xba\xb7\x3d\x32\x45\xb0\xab\xd6\x59\x39\x42\x18\xb6\x7c\x98\x40\xdb\x2b\x5c\xef\x8e\x9a\x14\x16\xdc\xa8\xdd\x4e\x6c\x06\xbb\x17\xee\xe8\xbc\xda\x43\xc1\x56\xaa\xbd\x35\xab\x6a\xe7\x7d\xcf\x63\xf3\xf2\xfd\xfb\x6b\x1c\x9c\x98\x7a\xdf\xe8\xc8\x6c\xed\xc2\x2a\xe9\x02\x7b\x66\x44\x40\x1b\x96\xf1\x38\x74\x93\x15\xfe\xe1\xdd\x15\xe7\x9c\x98\xb9\xd0\x84\x47\xe1\xcf\x4d\x9a\x40\x58\x09\xce\xee\xd5\x01\xd6\xbb\x36\x02\x98\xa8\x55\xd5\xd9\x6d\x3d\x58\xeb\x79\xb9\x5f\xd9\x2d\x2e\xf1\x22\x23\xd5\xf4\x8c\x17\x6d\x18\x9c\xc3\x10\x58\xc8\xce\x6e\x81\xe0\x85\xf1\x5a\x55\xca\x00\x69\x69\xac\x71\xb6\x53\x4c\x39\x7f\x85\x54\xf1\x14\x53\x91\x88\x2e\x40\xc6\x59\x7a\x15\x28\x4b\xab\xa1\xc7\xde\x22\x3d\x0d\x00\xe7\x42\x76\xce\x8a\x7e\xd0\xc6\x87\x8a\x61\x8e\x08\xc3\xaa\xaa\x6c\x1f\x4a\x64\x34\xe4\x2d\x25\x24\xc2\x01\xfd\x8e\xf9\xc0\x42\xc2\xca\xd1\x4d\x76\x38\xb9\xbd\xef\x6b\x3a\x89\x6e\x5e\xbf\xbf\xc6\xe3\x08\x52\x61\x11\x5c\x88\xe7\x83\xdd\xa7\x84\x34\x3e\xaf\x03\x3e\x80\x91\x6d\x3b\x28\xe7\xce\xc5\xbb\xe7\x4f\xc5\x3f\xff\xf9\x4f\x7f\x5a\x89\x57\x3e\x90\xbd\x40\x09\xfe\x33\xec\x60\x49\xb3\x90\x40\xed\x20\xfc\x4e\x89\xef\x03\x19\xfb\x5e\x3c\x86\xdc\xff\x43\x7d\x96\xfb\xbe\x53\xab\xc6\xee\x9f\x84\x55\xba\x97\x7e\x55\x85\x1c\x35\x30\xd1\xb8\x51\xa6\x0d\xdc\x0a\x30\xc4\x94\x95\x91\x5e\xca\xce\xd8\x63\x94\x02\xc2\xd8\x6f\xf4\xb0\x4f\x13\xc4\xf2\x41\x98\xa9\x90\xc3\xdc\xa5\xee\x02\x37\xa5\x37\xc7\x04\x0a\x3d\x7d\x13\x12\x69\x69\x56\xb4\xd3\xe8\xb8\x8a\x63\x4c\xac\x54\x58\x81\x6f\xfd\x4e\x0d\x3c\xdc\x2e\x8d\xb7\xdd\x6c\x02\xd3\x32\x59\x2d\x6f\x31\x15\x57\x4b\x0e\x12\x97\xc9\x33\x22\x18\x4f\x9f\xbd\x11\xea\x4e\x99\xb0\xb0\xfb\xc1\xb6\x63\x03\x2b\x87\x57\x4c\x27\x06\xe5\xec\x38\x34\x8a\x16\x6a\x24\xc8\xa1\x69\x81\xea\x37\xb2\xeb\x8e\xab\x8a\x0f\xc6\xed\x20\xef\xa4\x97\x43\x56\xc5\x0b\x4e\xa2\xd6\xcf\x60\x67\x8d\x8a\x25\x42\xcf\x9b\xd1\xf9\x40\x3d\xa0\x15\x0e\x1b\x85\xd9\x4e\xc8\x41\x89\xb1\xef\xac\x6c\x55\x2b\xd6\x47\xa0\xf1\x2e\xac\x85\x56\x6d\xe4\xd8\xf9\x55\xb5\x51\x6d\x20\x4a\xaa\xad\xa9\xae\xce\xda\x5b\xa8\x8c\x86\xea\x39\x03\x88\x4b\x42\x7a\x05\x10\xa7\x4a\xc6\xc6\x52\xf9\x08\x16\x1b\x45\x35\x78\x0b\x2c\x4a\xca\xb7\xbd\x32\xd4\x0d\x66\x4c\x44\xe0\x3b\x5a\x61\x8d\xe8\xf4\x9a\x3a\x9d\xc6\x72\xc2\x64\xf0\xe8\xdc\x04\x29\x39\xcf\x5b\x2c\x30\x1b\x54\x58\xf0\x6e\x5a\xf6\x5c\x58\xd3\x1d\x89\x19\x09\x5b\x0c\x05\x53\xe6\x4b\x5c\x22\x4b\x51\x0c\x64\x8a\x44\xd2\x60\x99\x1f\xab\x7d\x87\x6c\xaf\xb8\x93\x9d\x6e\x03\x46\x46\x10\x4e\x8b\xe5\xb6\xac\x2a\xe2\x95\x6b\x92\xd7\xeb\x3b\x0d\xf2\x71\xdc\x62\x88\x92\x64\xf8\x30\xc2\xff\x1e\x00\x82\x84\xe2\x16\xcb\xc6\xd6\xbc\x0d\x9d\x74\x51\x3e\xc6\x75\x12\xba\x0b\x35\x04\xfe\xdd\x9d\x8b\x3b\x0d\x6c\x00\x2d\x72\x18\x97\x75\xe0\x31\x3b\x15\xaa\x72\x4a\x01\x06\xa1\xcd\xa3\xb1\xc7\x32\x2b\x12\x0e\x49\x5e\x63\xbe\x3f\xb0\x83\xad\x35\x0f\xbc\x30\x0a\xd9\x16\x1e\xd5\x09\xdb\x27\x06\xbd\xdd\x79\x61\xec\x61\x45\xdc\xef\xe0\x3c\x8e\x0e\xc8\x16\x8a\x5a\xea\xa1\x11\xbc\xf7\xe4\xe8\x6d\xa0\x2f\xb0\xf5\xc4\x76\x90\x06\x96\x1f\x23\x56\x2e\xb6\x2b\x32\x84\x90\x37\x93\x4d\x11\x68\xaa\x24\x98\xf1\x9f\x91\xfa\x11\xd1\xcb\xf3\x88\xda\x25\x18\x2c\xcd\x8a\x06\xac\x18\xa9\x2b\x09\x80\xf5\xd6\x82\x60\xcb\x02\x5f\xe0\xb0\x2a\xaf\x9c\xaf\xb7\xda\xd7\x9b\x40\x82\x03\xe2\xe7\xf8\x23\xb0\x7c\xca\x79\xf1\x60\xab\xfd\x03\xd1\xd8\xfd\x5e\x9a\xf6\x67\x71\x76\x47\xd2\xc3\x9f\x41\x56\x95\x77\x52\x77\x30\x46\x24\x30\x0f\x0a\x85\x84\x3b\x35\xb8\xb0\x7b\x5a\xab\x9c\x08\x5c\xb3\x1b\x7b\xe0\x37\xa2\xe4\x45\x02\x62\x6b\x0f\x26\xd0\x11\x18\x74\xbb\xd9\xe8\x46\xcb\x4e\xac\xb5\x91\xc3\x31\x62\x81\xd3\xe9\xcc\x9d\x8b\x37\x6f\xdf\x03\xe0\xd6\x06\x76\xa8\x65\x80\x55\xa5\x0d\xac\xf7\x20\x65\xd0\x9a\xc8\x45\x2c\x4e\xd2\xd8\x96\xc6\x0e\x81\x25\x80\xde\x70\xc1\x13\x0c\x74\xe0\x27\x50\x3e\xd1\x41\xc4\x05\x58\x28\x17\x79\xdd\x30\x0c\x7b\xe9\x9b\x1d\x71\xc2\xb8\x88\x5c\x58\x84\xa1\xa5\xcd\x38\x0c\xca\xe0\xda\xfa\x59\x9c\x39\xf1\xf0\x89\x38\xcb\x8e\xeb\x7a\xaf\x5d\x60\x2e\x23\xa7\xca\x67\xb7\x80\x04\xca\x2d\xce\xe7\xd4\xdb\xfc\x78\x87\x82\xe1\x8c\x17\x1b\xad\xba\x76\xda\xde\xc0\xc8\xe3\xe1\xb9\x5d\x9a\xeb\x90\x2d\x30\x7b\x44\xa2\x40\xa3\xb3\xbc\x34\x42\xba\x96\x9d\xfe\x5d\xe5\xfc\x60\x31\xa0\xc5\x06\x8d\x2b\x92\xf7\x5f\x36\x23\x79\x2b\x79\xa9\xba\x11\xa5\x84\x0b\xf1\x57\xd5\x35\x76\xaf\xbe\x13\x7f\x55\x0f\x06\x25\xb6\x1d\x2c\x15\xe9\x49\x2f\x60\x9d\x82\x85\x7c\x8e\xc2\xc5\x66\x34\x70\x76\x79\x79\xab\x40\x95\x90\xc6\x6a\x89\x6d\x3c\x39\xbb\xd5\xc7\x9d\xdd\xab\x4f\xd5\x88\x42\x99\xed\xda\x28\xd6\xc3\xae\xb5\x03\xf2\x41\x51\xc6\x4f\x30\x71\x43\xba\x83\xf6\xcd\xae\x8e\x6a\xd3\x30\xfa\x5e\x7d\x86\x49\x86\xac\xa4\x45\x0d\xbb\x39\x64\x55\xfb\x23\x2c\xc4\xd0\xf1\xd7\xc7\xb4\x0e\xb5\x72\x95\xdb\xd9\x03\x68\x25\x23\xc4\xcd\xce\x1e\x40\x1f\x59\x88\x6e\xab\xd5\xaa\x6a\x6c\xd7\xc9\xb5\x0d\x13\x79\x97\xe0\x9f\xe6\xa9\x25\xf2\xfd\xb1\xb6\xc3\x96\xaa\x2d\xb5\x70\xfb\x23\x29\xfe\x28\x17\x15\x7f\xae\x02\x32\x4f\xfa\x61\x38\x0d\xce\x5c\x45\xfa\xae\x95\x36\x35\xa8\xd3\xb8\xe6\x57\x06\x85\xaa\xbc\x9d\x55\xf5\x91\x74\xc7\x9f\x2a\x86\x2b\xda\x84\x14\x18\x07\xdd\x15\x2a\x4e\x37\xd1\x71\xba\xca\x29\x39\xc0\x0e\xbc\x81\x1f\x55\xf5\x51\x8e\x7e\xf7\x29\xd3\xf6\xd6\xbc\xf2\x58\xeb\x0b\x1a\x49\xa2\xcc\x89\xbd\xdc\xa9\x3e\x70\xa2\x7b\x07\x4b\xb6\x1b\x94\x6c\x8f\x24\xb7\xc6\xc5\xfb\x17\x3c\x08\xb5\x09\xe7\xc7\x77\x95\xb3\x81\x64\xd5\xdf\x88\xe2\x17\x6d\x5a\x2c\x5f\x32\x11\xa8\x86\xde\xf7\xb0\x4c\xec\x30\x1c\xcf\x4b\x8d\xc6\x4e\x3a\xb1\x56\xca\xb0\xe4\xd9\xae\x58\x5f\x14\x96\x97\x6c\x90\xea\x80\xa2\x1c\x76\x20\x96\xb4\x33\xee\x26\xb4\x10\x8f\x0a\xaa\x05\x4f\x0e\xc7\x8c\x6e\xe0\xf0\xbe\xb9\x8a\x30\xe8\x35\x71\x5a\x17\xe2\x72\xf4\x3b\x65\x3c\x8b\x81\x37\x90\x5e\x01\xe7\x0a\xfb\xaf\x91\x5d\x35\xa8\xbd\x0a\xc2\x65\xbd\x47\xd5\x37\x7e\x89\xd7\xaa\xda\xd8\x61\x0b\xbb\x15\xb7\xd3\x85\x78\x0e\x09\x69\x7f\x05\x00\xe5\xf3\x33\x91\x20\x38\xe5\x2f\x7c\xb1\x50\x1b\x7b\x00\x15\x74\x38\xad\xa7\xd3\x38\xf6\xc0\x06\xf0\x19\x8b\x3c\x1c\x88\x0f\x4e\x19\x9f\x26\xe3\x52\x18\x75\x10\x39\x14\x0d\x59\x9c\x91\x00\x1f\x88\xe3\xe3\xf5\x93\x33\xf7\xf8\xd1\xfa\x49\x3c\xe4\x9a\x9d\x6a\x6e\x71\x0b\x68\xb3\xb6\x9f\x41\x2f\x45\x8c\x86\x09\x24\xe1\xac\x15\x3b\x3b\x0e\x24\x1b\x06\xd9\xc9\x2b\xc8\x2d\xe6\xbe\x1f\x2c\x31\x19\x0d\x6c\x6c\xd8\x63\x69\x5d\x83\x56\x3a\xac\x6c\x38\x89\x79\x69\xf7\x83\xdd\xe9\xb5\xf6\x81\x00\x82\x2a\xe5\x0a\xfe\x5f\x53\xb2\x6a\x27\x10\x19\x2f\x35\x44\x72\xad\x9d\xe8\x63\x01\x3c\x8c\x3a\xbb\xdd\xa2\x2e\xf6\x0b\xcb\x23\x70\x97\x30\x94\x9d\xde\x6b\x3f\x5b\xdd\x81\x8e\x4b\xda\x25\xa4\x47\xe7\x69\x82\xee\xa4\x81\x1e\x54\xa3\x8c\xef\x8e\xb1\xbe\x83\xd4\x5e\xfc\x59\xec\xb5\x19\x7d\x90\xe5\x77\xca\x08\x3f\x1c\x85\xdc\xca\x50\xed\x4e\xba\x7a\x34\x34\x63\xaa\xe5\xf5\xfe\x52\x03\x2b\x11\xea\xe5\x5d\x99\x41\x95\xf2\xad\xf8\x21\x4e\xe6\x8f\x2b\xd2\x7c\x43\xa9\x70\xbc\x87\xf6\xe8\x20\x8c\xc9\xa5\x65\x61\x87\xc8\x84\x12\xa0\x90\xb0\x84\xac\x51\x69\x61\x74\xba\xb9\x85\xf1\x5a\x8f\xde\xdb\x20\x68\x77\x61\x31\xc2\x88\xc5\x16\x3f\x05\x28\x50\x83\x00\xb6\x90\x87\xab\x69\x3a\x46\x15\x14\x0b\x10\x7e\xb9\xf0\x0f\x83\xfa\x31\x15\x8f\x7b\x07\x4a\x10\x0a\x2c\x9d\x6d\xab\x77\x90\x89\x97\x25\xbc\xf9\xf8\x54\x6d\x48\xcd\x1c\xe7\x72\x28\xc7\x02\xf2\xc3\x0e\x51\x9f\x7b\x3d\x04\x91\x6b\x00\x16\x0c\x4a\xaf\x26\x75\x25\x9d\xc4\xbc\xc7\xbe\x6c\x71\x3a\x78\xbd\xb5\xb5\xdb\x21\xf3\xc4\xcd\x13\x9d\x32\x5b\xbf\x43\xad\x63\x60\xdc\xbd\x08\xe3\xed\xc5\xff\x04\x75\xb9\x6c\xbc\x1a\xdc\xaa\x32\xd6\xd4\x40\x8e\xb2\x4d\xf4\xc6\x9a\x87\x48\xa2\x58\x12\x63\xbd\x2f\x5d\x42\x70\xc5\x61\xbd\x0d\x76\xdc\xee\x48\x55\x59\xe1\xee\xf1\x07\x5b\x6f\x64\xe3\xe1\x6e\xe6\xfd\xc1\x3e\xa4\x8f\x92\x18\xce\x80\x61\x0c\x68\x30\x27\x74\xf3\x9a\x72\xe6\x65\x94\x09\x64\x7c\x50\x8d\xbd\x53\xc3\x91\xe7\xe2\xd7\x90\x2a\xa4\xf0\xa9\x72\x06\x11\xcb\x78\x62\x76\xd1\xe2\x77\x94\x7a\x1a\x9e\x6b\x64\x48\xf1\xf4\x9e\x66\x66\x1d\x5c\x68\x61\x7f\xb2\x93\x89\x41\x3f\x51\x29\x7c\x33\x05\x19\x1d\xae\x31\x2a\xb5\xaa\xaa\x8f\x61\x51\x7f\xaa\x68\xa7\xa8\x6c\xaa\x89\x8a\x70\x0e\xef\x28\x24\x9b\x11\x9e\x25\xaa\x7f\x57\x83\xde\x1c\x11\xa8\xa0\x11\xa7\x36\x4c\xb9\x5e\xe3\xa9\x9b\x58\xdb\x77\x39\x6d\xa7\xe4\xcd\xd8\x9d\x8b\x03\xf2\xbc\xa9\x4c\x54\x64\x11\x37\x2c\x02\xa5\x80\xeb\xf7\xea\xe3\xde\xb6\xb2\xfb\x54\x1d\xe1\x9a\xf1\x3f\x94\xab\x0c\x5c\xed\xda\x6a\x6f\x5b\x2c\xf4\x1a\x7e\x54\xd5\xc7\x8d\x1d\xf6\x9f\xaa\xc0\x4f\xbd\x99\x88\x9e\x81\xf1\xa2\xb4\x4c\xf8\x81\xac\x5f\xf3\xab\xeb\xd8\xe7\xeb\x05\x29\xf5\x9d\x4a\x37\xd8\xf0\x2b\x76\xfe\xe6\xe6\xe5\x7b\x56\xad\xdd\xbc\x14\xb7\x8a\x70\xbf\xf4\xbe\x77\x1f\x40\x61\x8c\xda\xdf\x0f\xef\xae\xaa\x6b\x79\x0c\x02\x21\x26\xd3\x07\x64\xbc\x57\x72\x4f\x8d\x0c\x3f\x11\x45\xd8\x2c\x94\x18\x7e\xda\x21\xbf\x2a\xa9\x40\xe8\xf8\xb5\x90\x89\x91\xc8\x55\x6f\xd4\xe1\x97\x41\x9a\x86\x0b\x07\x6e\x70\x0d\x09\x58\xf2\xa9\xdd\xef\xb5\xbf\x19\xf7\x7b\x09\x1b\x03\xbf\x85\xc3\x04\xca\x7e\xad\x9c\x43\xfb\x02\xca\xde\x63\x02\x65\x3f\xdd\x59\xdd\x64\xb9\x0d\x7c\x57\xef\x07\xa5\xa8\xd6\xe7\x7c\xeb\x56\x81\x04\x80\xec\x29\xfe\xaa\xa2\x62\x85\x6f\x7a\x7f\x9b\xdd\x40\xfd\x56\xc9\xae\xdf\x49\x90\x31\x32\xb0\x48\xf6\x42\xa6\x19\xf7\x6a\xd0\x0d\x28\xe7\xa4\xdb\xfd\xf0\xb0\xfe\x31\x27\x82\x05\x8a\xd6\xfa\x6f\x41\x13\x7e\x23\x61\x3c\x89\xcd\x75\x5f\x6e\xda\x39\x60\x14\x01\xe5\x39\x20\xb4\x83\x80\x72\x25\x66\xa7\x7f\xe7\xb1\x00\x54\xe1\x3b\xe2\x3b\x0b\x10\x20\x70\x26\xa8\x58\x1f\xf0\x25\x41\xf8\xe4\x63\xe0\xcc\x95\xa8\xf7\xf2\xf3\x97\x0a\xee\xed\x42\x39\xd4\xcc\xa7\x42\xa4\x5f\x90\x78\xbc\x95\x64\x62\xf5\x5b\x35\x0e\xf7\x00\x7f\x78\x77\xb5\xfa\xad\xd2\xa6\xe9\xc6\xf6\x64\x43\xdc\xb8\x76\x7e\x08\x6c\xd7\x83\x33\xf7\x20\xa0\x34\xb7\xc6\x1e\x4c\x84\xff\x80\xdf\x02\xbe\x7f\x66\x1b\x92\x5a\x1b\xd2\x79\x24\x6b\x12\xd1\xea\x36\x70\x31\xa0\xbb\x58\xa5\xf3\x34\xd7\x67\xc4\x5d\x0e\xfa\x60\xd2\x38\x45\x42\x17\x44\x04\x50\xed\xc8\xbd\x5a\x25\xbb\x97\x3a\x30\xc3\x75\x90\xc0\x4d\x2e\x32\x07\x26\x80\xa9\x34\xb0\xcb\x00\xb1\xc2\x8b\xc9\x79\xb9\x09\x19\x3a\x59\xdc\x0e\xdb\x85\xd2\x6f\xe7\x97\xa6\x27\xca\x7b\x25\xf7\x0b\x08\x22\x81\x39\x59\x10\xe7\x1e\x0a\xc1\xa1\x33\xa1\x90\xf3\x72\x01\x6a\x95\x46\x29\x0e\x78\x3e\x37\xb9\x82\x21\x8e\x73\xa9\xb5\x2a\xa4\xac\x7a\xaf\x1d\x4f\xd6\xfb\x1d\x68\x28\x73\xd6\x21\x2a\xbd\x3b\xd5\x04\xae\x9a\x97\x9c\x03\x99\x35\xa4\x80\x49\x01\xeb\x3b\x57\x15\x1c\xd5\x03\x98\x36\x65\x6a\x31\x52\x54\xd2\x79\xb9\x97\xb7\x4a\xb8\x31\xb0\x66\x3b\xe9\x49\x4a\x29\x27\x2b\x70\xc9\x80\x0a\xeb\x8c\x2d\x9f\xa1\xb7\x07\x13\x8e\xb7\x2f\xe1\x07\xb0\x6f\x44\x9d\xeb\x51\xe7\x88\x09\x79\x04\x3a\x85\x36\xaa\xf8\xd4\x67\x0d\x77\x6b\x2f\xf4\x9d\x22\x25\x5f\xd4\x6d\x42\xde\xaa\xea\xa4\xf3\x75\x58\x8f\xd8\x5c\x10\x67\xed\x5d\xd8\xac\xa1\xbe\x90\x2b\x86\xb0\x6a\xc0\x66\x06\x30\xa0\x56\xcf\x50\xff\xc2\x52\x8c\x53\xd4\x75\xf6\xa0\xda\x73\x11\x56\x91\x29\x8d\x00\x80\x22\xc8\xee\x20\x8f\x8e\x24\x18\xa6\x6b\xd6\xd0\x58\xad\xaa\xa4\x23\x74\xbb\x3a\x1c\xb8\x91\x49\xbf\x0b\x8c\x0c\xaf\x10\xbb\x49\xd7\xdd\x01\x0a\x75\x7d\x3f\x8b\x33\x57\x8d\x78\xbf\x00\xe0\xc7\x0c\x0d\x18\xd7\xd0\x49\x74\x97\x31\x45\x84\xe2\x3c\x88\x32\x42\xfb\x07\x2e\xac\xb3\x71\x8f\x22\xd0\x9a\x2e\x24\xa2\xec\xd6\xda\x71\xdd\xa9\x87\x28\x19\x6b\x5e\xd5\x51\xd5\x38\xe1\x81\x63\xb3\xee\xaa\xca\x79\xdd\x75\x61\x8c\xd9\x8c\xad\x90\x54\x21\x17\x36\x1f\x0c\x84\xdb\xe9\x5e\x58\xb8\xcc\xcb\x07\x29\x2d\xd8\x4c\x10\xf4\x56\xb4\x0a\x24\x6f\x3b\x08\x3f\x48\xe3\x36\x0a\x6e\x37\xf7\x78\x3f\xb0\xa2\xaa\x83\x5c\x89\x66\x6b\x27\x6a\x46\x25\x06\x54\x9d\x9f\x3a\x30\x3b\xd9\x44\x96\x55\xa3\x6d\x01\x5c\xa1\x41\x1b\x60\x4c\x13\x26\xc7\x6d\x08\x0b\x6c\x36\x04\x70\x9b\x5e\x2c\x92\xc5\x71\xd8\x14\x1a\x38\xac\x1f\x56\xd3\x17\xfa\x5d\xa1\xf9\x56\x8d\x0c\x52\xb1\x1f\xde\x43\x0e\xb3\x4e\xd3\x2d\x51\x7d\x0c\xeb\xfc\x53\x85\xb2\x53\x1d\xaf\x28\x9f\xa2\x2c\x85\x1c\x37\x24\x56\xff\x69\xb5\xa9\xe1\xbe\xed\x5f\xac\x36\x70\x39\x57\x15\x26\x29\x13\xf5\x20\x19\xe4\x1d\xc1\x56\x66\xdd\xe9\x86\xad\xf2\x8e\xd5\xc6\xc2\xee\x01\xed\xe1\x73\xfe\x5d\x39\x2f\x03\x81\x20\x83\x8a\xf0\xab\x50\x47\x62\x21\xd4\x55\x3f\xe7\xdf\x94\x1a\x93\xaa\xd1\xc4\x94\x0f\xf4\xb3\xaa\x02\x5f\xbd\x02\xa2\x1e\x44\x01\xb8\x9f\xcd\x48\x79\x38\xa9\xc3\xb6\xe6\xbc\x55\x06\xdf\x4b\xef\xd5\x60\xf0\x2e\x05\xb7\x7c\x5e\x94\xb2\x23\x8a\x8c\x32\x84\xb1\x65\x6b\xc5\x4f\x55\xb2\x69\x64\x73\xc6\xa5\x6b\xa4\x38\xfc\x78\xe3\x5a\xd1\x9e\x76\xc4\x96\xff\xab\x3a\xba\xca\xa9\x66\x1c\x70\x58\x6f\xe8\xe7\xb2\x7a\x96\xf4\xc5\x13\x93\xcd\x74\x19\xe0\x4a\x2b\x10\x57\xd1\x1a\xbb\x10\xcf\xf0\x07\x2b\xa8\xaa\x1e\xa6\x2f\xb3\xcb\xa4\xf9\x8c\x5d\x21\xb3\xdc\x5c\x31\x55\x6a\x69\xb4\x13\x88\x04\x18\x15\xbe\xae\x83\x63\x79\x63\x07\x21\xcd\x31\x5d\xfc\xa9\x0e\x0e\x3e\x93\x99\x01\xb8\x73\x28\x17\xc0\x0e\x6a\xcd\x77\xc3\xc9\xa8\x66\x2f\x5b\x25\xee\xb4\x8c\x8a\xad\x8c\x5d\x8a\xe7\x39\x2b\x4b\x0b\x1d\x02\x88\x41\xa8\xc8\x66\x6e\x89\xa7\xd9\x5b\xd6\x28\xf8\x9d\xd2\x78\x35\x6b\x80\x93\xda\x8c\x5d\xc7\x67\xe2\xf3\xb1\xeb\xd0\x44\x6c\x6e\xfe\x1c\xaa\xa0\x2b\xea\x2b\xfa\x59\x8d\x7d\x1b\x84\xd6\x34\x96\x1f\x20\x21\x8e\x65\x99\x9f\x09\xa3\x30\xaa\x5c\x2c\xaa\x34\x11\xbc\xcd\xa4\xd3\xee\xb8\xe2\xdd\xbc\x60\xe8\x4c\x1b\xbb\x9d\x82\x24\xad\x1f\x50\x2a\xea\x38\x4c\x14\xda\x00\xc1\xd0\x1e\xe4\x51\xec\xec\x41\x74\xda\xdc\x3a\x9a\xa9\x30\x4e\xb9\x60\x0e\x8a\x5a\xaf\xcd\xa8\x48\x54\x0a\x3f\xe7\x66\xb5\x64\x33\x40\x16\x04\xeb\x23\x6b\xc3\xd0\xc6\x80\x36\x80\x58\x1f\x05\x48\x83\xa7\x8d\x15\xa6\x56\x0a\x6c\xa4\xc0\x97\xef\x60\x23\x91\xe8\xda\x07\xa7\xc4\x53\xb4\x9b\xa0\x3d\xd6\xec\xac\x75\x74\x03\x91\xa8\x5f\x48\x03\x65\x20\x11\x3f\x9a\x96\x84\x07\x67\xed\x92\xed\x37\x60\x9f\xd3\x0e\xaa\xe9\x4a\x31\x41\xd3\x86\x7a\x4a\x57\x8d\x97\x8c\x13\xed\x33\xb8\x4f\x40\x63\x6a\xbd\x47\x81\xf5\x03\x5b\x6f\xc0\x84\x47\x59\x04\xb2\x57\x65\x7b\xa6\xab\x84\xea\xe5\x2b\xbc\x2f\x2c\x16\x5e\x0a\xf9\xdd\x35\x4e\x7f\xa4\x4b\xb6\x2b\xd8\x35\xee\x47\xcc\x0f\x83\x97\xe5\xbf\x01\xd3\x83\xa8\x57\x09\x7b\xac\x9e\x80\x90\x2a\xa2\x80\x5c\x64\xb8\xb9\xae\x93\xcc\xf6\xa4\xf5\xb3\x1d\xc3\xe5\x0e\xd2\x15\x1d\xa7\x35\x4e\xa2\x93\x84\xbb\xa2\x82\x28\x65\xfa\xf3\xd4\x34\xaa\xed\x1f\xa5\x25\x8c\x6f\x55\xa1\x98\xe2\xa2\x74\x72\x89\x14\x53\x39\xb6\xbf\x8f\xf9\x64\x82\x5f\x10\x56\xc5\xc6\x67\x39\xe9\xed\x07\x0d\x3a\x91\x92\x04\xcf\x88\x6e\x41\x60\x61\x14\x2c\x98\x52\x25\xba\xba\xaa\x18\x55\x38\xb6\xe0\x17\xa7\x44\xad\xdb\x8d\x02\x7b\x62\x4a\xe6\x1d\xc0\xb9\xb8\xf0\x63\x1b\x3b\x45\xe4\x10\xfb\xfa\x8c\x12\x26\xf9\xdc\x19\xcc\x06\xee\x5c\xbb\xa5\xde\x0c\x81\x7d\x57\xf1\xc4\xd0\x06\x2d\xd9\xa2\x41\x42\x41\x96\xc4\x33\xa0\x53\xe2\x20\xf1\x12\x88\xa9\xd4\x5f\xa6\xb5\xa7\x05\xf4\x6b\x79\x7d\x84\x7d\x2b\xb7\xcf\x77\x95\x6c\x5b\x58\xdc\xc9\xb0\xa3\x05\xc2\x51\xaa\x20\x03\x54\x0e\x81\x86\x1f\x31\xb5\x2e\x2e\xb7\x1c\xea\x99\xbe\xfe\x42\x2b\xb0\x1f\xff\x0d\x77\x59\x45\x55\xe9\x2e\x2b\x36\x72\xb2\xb5\x66\xbd\x9c\xef\x31\xd9\xb6\xc0\x09\xd1\x5a\xce\xf8\x19\x5a\xcd\x91\xad\x09\xb5\xa0\xf8\x12\x86\xe7\x5f\xd5\x11\x98\x1f\x5a\x09\x70\x26\x69\x27\x24\xd8\xb2\x82\x01\x3c\xca\x32\x6e\x26\x2a\x97\x73\x7e\x09\x97\x4e\x4e\x11\x2c\x30\x86\xd2\x1c\x03\xa3\x0f\x16\xc3\xc8\x44\x7b\x2b\xb6\x32\x9a\x08\xc5\x03\xad\x64\xc5\x35\x5c\xb2\xed\xf4\x76\xd7\x1d\x85\xde\xf7\x76\xf0\xb0\x92\xd8\xd4\x21\x09\xaf\xe1\x6b\x50\x8d\xdd\x1a\xfd\x3b\x0c\xec\x1e\x4d\x9d\xe3\xe5\xc9\x63\xe7\x07\x6b\xb6\x4f\x9e\x81\x25\xd4\x6d\x20\x3c\x3b\x7b\xf8\xcb\xe3\x47\x94\x2e\x9e\xc2\x14\xda\xd1\x8b\x17\xda\xbf\x1c\xd7\x0f\x9c\xd8\x8e\xba\x85\xb3\xf6\xb1\xcc\x7c\x33\xc8\x7a\x0a\xed\xd0\x0f\x26\x0e\x0b\x78\x6a\xd8\x41\x38\xdb\xdd\xa9\x49\x11\xbb\xdf\xe3\xf4\xae\x3b\xb5\x47\x48\x68\x3f\x18\x5c\x29\x03\x23\xa7\x06\x1a\x9f\x9b\x9b\x97\xab\xb8\xc4\xd3\xfc\xd0\xb4\x31\x83\x5a\x68\x59\x88\x39\x0c\xc0\x0d\xe9\x4c\xd3\x09\x04\x2a\x16\x2e\x05\x8c\xc7\xbc\x14\xcc\xa3\x0b\xcc\xca\x4c\xbf\x03\x52\x4b\x40\xc1\xc5\xc5\x45\x68\x07\x32\x60\x21\xad\x99\x69\x69\x69\x61\x65\x8b\x37\x1c\x3a\x2c\x4e\x03\xe3\x1e\x9b\x07\xcb\x75\xb2\xbf\x89\xa2\x61\xdf\x89\x9e\x71\x07\x32\x8a\x46\x23\x92\x68\xda\x14\xa6\xa0\x6a\x0a\x69\x1a\xb7\x22\xa7\x66\x68\x5a\x8a\x14\x0d\x17\xa4\x72\x40\xaf\xbf\x92\x9a\xcd\xea\x4d\x1d\xe7\xea\xbe\x82\xa2\x41\x9f\x2e\x61\x38\xac\x41\xc5\x09\x4d\xd4\x95\x44\x43\x3c\xc8\x30\xb6\xce\xc4\xbc\x37\x96\xae\x80\x05\x27\xc2\x9c\x38\x1f\x58\x95\x7c\x2b\x87\x46\x80\xd1\x3e\x1a\x1d\x82\xe6\xe5\x7f\x13\xad\x3c\xba\xca\xdb\x5b\x65\x16\x8a\x40\xfa\xa9\x42\xd5\x57\x5e\xea\x65\xb7\x56\xe8\xd5\x85\xb2\xa6\x1f\xdd\xcf\x79\x1e\xfa\xe8\x15\xe0\x76\xb3\x09\x69\x9b\x4d\x55\xdc\x9b\x91\x65\x1d\x9a\x61\xe6\x59\xec\x76\x10\xad\x4c\xf3\x4c\xb0\xcc\x29\xae\xcb\x1c\xdb\xe8\x80\x4d\xbd\x2c\xf7\x6c\xd8\xb5\x44\x90\xb2\x1b\x35\xdc\xb9\x81\x6a\x09\x27\x37\x4a\xf4\x9d\x6c\xd4\x8a\x1d\x6e\xc0\xc2\x16\x88\x5b\x38\x9c\xf9\x66\x4f\xe3\xfd\x78\x67\x9d\x9a\x12\xbb\x89\x62\x32\x93\x13\x57\x79\xd3\x77\xde\xf7\x68\xc8\x91\xfb\x04\x24\x96\x81\xcc\x05\x80\xfd\x11\x9d\x35\x5b\x35\x44\x3b\xd1\xd0\xa4\xbe\x93\x64\x65\x0a\xbb\x37\x74\x37\xf2\x42\xd1\x4a\x81\x4d\x42\x5b\x28\x92\x46\xe2\xe3\x4f\x9f\xdc\xd9\xc7\x3f\x7d\x72\xdf\x3f\xb9\x56\x83\x03\x23\xfc\x4b\xec\xc6\xfb\xb0\x3c\x60\x44\xa4\xa3\x5b\xee\x41\xb5\xa1\x43\xb2\x3b\x17\x6a\xb5\x5d\x89\xc7\x61\x08\x9e\x9c\x7d\xfc\xf3\x27\xf7\xf8\x11\xfc\x5e\xcd\x27\x33\x59\xf1\xe3\xdc\x7e\xdd\x5a\x6a\xa4\xa9\xff\x36\xf1\x0c\xfb\xc2\xa8\x82\x4d\x5f\x98\xa8\x70\xf0\x02\x53\x5f\x2e\x41\xbe\x95\x75\xaa\x19\x94\x07\x39\x1e\xf5\x9f\x28\xe3\x42\x6a\x51\x22\x54\x34\xbf\xc9\x7d\xbf\x53\x86\xca\x71\x6a\x51\x8a\xf4\x83\x7c\x7b\x5a\x2d\xdc\xeb\x96\xd8\xd2\x62\x9a\x68\x64\xa3\xd1\x40\x64\x44\xa2\xa5\xc7\x77\x55\x71\x37\x1d\x76\xf0\x57\x61\x5d\xd4\xd0\x97\xe8\x0d\xf1\xac\x46\x7d\xb7\x30\x99\x7c\xe9\x32\x9f\x4c\x79\x52\x7d\x39\xc7\x92\x08\xe8\x69\x04\x60\x41\x61\x50\x26\x98\x12\xeb\x09\x79\x3d\x75\x4f\xef\xe2\xda\x3b\xb9\xe8\xca\x8b\x7c\x77\x0f\x2a\x22\x9d\xc5\x1d\x3c\x79\x05\x04\xfa\x19\x1d\x02\xbd\x0a\x9c\x8c\x1c\x74\x77\xfc\x56\xb2\x20\x7e\x95\xcd\xae\xa4\x49\x40\x79\xd8\x3c\x9c\xce\x88\x46\x9d\x8b\xc7\xeb\x27\x34\x69\xb7\x4a\xf5\xc4\x92\x61\x93\x26\x04\xec\xf1\xa3\x75\xb9\x2d\x07\x85\x3e\x7c\x5e\xcd\x29\xe6\xbb\x98\x77\xef\xc0\x9c\x40\x10\x57\x47\x86\xa6\xa4\xb0\x27\x96\xc5\x69\x8c\x25\x8f\x31\x41\x16\x4f\x5d\x2e\x3d\x3d\x77\xe7\xc7\x47\xf2\x75\xa5\xe3\xe4\xab\xc8\x11\x17\x5e\xb2\x13\x8b\xda\xc3\x4e\xdd\xa9\x0e\x19\x8f\x36\x10\x13\x30\xb4\xd8\x04\x3a\x11\x65\x5b\x7f\x6a\xb5\xdf\xc3\x7d\x2c\x34\xe3\x6b\xb7\x4f\xac\xb7\x1c\x15\x96\x1d\x70\x61\xd6\xc8\x07\x44\xf9\x61\xf1\x1c\x70\x55\x9c\xa0\xc0\xb6\x72\x91\x17\x3c\xcb\x61\x72\x00\x10\xb9\x8d\xb8\x5b\xb0\x70\x52\xfa\xa7\x89\x02\x2e\x9f\xfc\xac\x60\x5d\x7b\x1b\x77\xca\x0e\x0d\x9c\xc5\xe5\xf5\x2b\xb7\xaa\x62\x85\x8c\x14\x76\x09\x36\xe1\x80\x1a\x7f\x30\x83\xee\xba\xd9\x56\x63\xfd\x19\x16\x27\xee\x16\xda\x84\xfc\x6d\xec\xd4\xac\x43\xd8\x99\x32\x1f\xc7\x5d\xb9\x6c\x05\x60\x6d\xd0\x92\xa9\xa0\x16\xbb\xfa\x9d\x78\x9d\x6e\xe1\xc2\xcc\xf6\xc7\x20\xfa\x44\x77\x8c\x73\x3a\x60\xc5\x01\x84\x97\x89\x1b\x88\xf6\x48\xf1\x45\xe0\x5f\x87\xc8\x3c\x73\x83\x89\x7d\xce\xa7\x32\xe7\xa1\x17\x27\x33\x71\xd4\x8b\xc5\x96\xd8\xea\x9e\xf1\x94\x7d\xfe\x12\x93\x6d\x37\x25\x7d\x3b\xb9\xc8\xf3\x5e\x65\xcb\xfb\x7a\xb1\xda\xb8\xed\xb1\xea\xc9\xf2\x16\x28\x03\xa2\xa9\x2c\x30\x49\xa8\x58\xc4\x15\x91\xb1\x0b\xd2\x89\x83\xea\xba\x7c\x75\xe0\x15\x8f\x8b\x8b\x64\x22\x37\x15\x32\x93\x5b\x55\x70\x21\xb0\x32\x41\xf6\x45\x47\x9c\xa8\xa4\xa2\x5b\x2c\x18\x00\x73\x2c\xae\xa9\xdc\x0a\x8b\xc1\xe5\x57\x24\x47\x57\x74\x15\x96\x45\x8b\xc8\xa0\x32\x5f\x1f\xf4\x3f\x2d\xcf\x15\x1c\xfb\xec\xde\x08\xfc\x01\x94\xdc\x3b\x22\x40\xc0\xa2\xaa\x0d\xdd\x2c\x67\x95\xdc\x33\x25\x78\x05\x82\x0d\xe0\x06\xe6\x69\x93\xa6\xa7\xeb\xc5\x02\xe8\x0b\x2d\x9f\xdc\xa4\x97\xad\xbd\xa7\x71\x79\x15\x85\x0e\x05\x89\x01\xf4\x35\xc3\x0b\x32\xe9\x84\x08\xd2\x92\x4b\xb6\x71\xb4\xde\x0b\x4b\x62\x02\xca\x54\xf9\x2a\xb1\xe6\x4c\xeb\xd3\xdd\x25\x23\xeb\xd5\xb0\x97\x06\x2c\x77\xf1\x9e\x85\xf5\x13\x4f\x2f\xdf\xbc\x79\xfb\x3e\xa9\x25\x02\xf1\x33\x2d\xf0\x5a\xec\xf0\x34\x6b\x17\xbb\x3d\xc5\x5d\x5b\x42\x24\xc7\x2b\x2a\x71\x0a\x2e\x97\xfd\x32\x23\xe7\xad\x05\xad\x0d\xdc\x57\xb3\xf4\x5a\xb4\xbf\x3d\xb9\x42\x3e\x86\x21\xfe\x54\xf1\xdd\xff\xdb\xf0\xbf\xca\xcd\x27\x32\x8b\x16\xa0\xb7\xc9\xf0\x25\x79\xe4\x8b\xad\xb5\xed\xcc\x9c\x02\xc4\xd2\x11\x9c\xce\x1a\xbb\xef\x2d\x70\x3e\x1b\x01\x56\xaf\xe7\x61\x77\xd9\x01\xa8\x24\x88\x34\x46\xff\x6d\x04\x85\x14\x18\xa9\xae\xaa\x3b\xed\xf4\x5a\x77\x28\x42\xff\x7b\xfc\xc0\xf4\xf0\x6b\xe2\x93\x9d\x55\xae\x9d\x78\xec\x7a\x69\x44\xd3\x49\xe7\x2e\xbe\x1f\xb5\x08\x7c\xb3\x57\x9f\xfd\xf7\x4f\xae\x07\xb0\x8f\x7c\xfc\x28\x40\x3c\x99\xa1\xab\x37\x76\x68\xf0\xb6\x35\x5a\x82\x03\xb1\xa2\xf4\xb0\x4d\x0d\x70\x31\xd9\x56\xc5\x81\xff\x03\x75\x6e\xec\x70\x9b\xfa\xf1\x03\x5d\x30\xd8\x0d\x12\xec\x3b\xd9\x8d\xe5\x6d\x53\xa8\x3d\x94\x71\x3f\x56\xe0\x70\x9e\xca\x82\x93\x00\x84\x30\x0a\x19\xda\x6c\xff\x02\x83\xe6\xef\x0f\x62\xf2\x52\x75\x7d\x10\x0f\xbf\xab\xa0\x25\x74\x2b\x3f\x8d\x86\x03\x79\xec\x8d\x1d\xf2\xc0\x25\x1b\x52\x17\x66\x23\x8b\x6d\x21\x3b\x96\xcc\xb2\xd9\x0c\xe4\x14\x3a\x91\xdf\x64\x1f\xc9\xa0\x2a\x1e\x5b\xae\x19\x34\x78\x94\x63\x7a\x27\xe1\x82\x3b\x86\x43\x82\xc4\xad\xf6\x7a\x6b\xec\x90\x0d\xc3\x0d\x98\x0c\x89\x55\xcc\x12\x1c\x60\xc9\x55\x9d\x6e\x94\x71\x40\xed\xf0\x17\xa7\xcc\x8a\x4b\xc1\xb0\x70\xf9\x18\x0e\x0c\xda\x0a\xe1\x07\x7d\x2f\x94\x22\x40\xae\xb2\x92\xa3\xb7\xb5\x36\xda\x83\x2f\x51\x74\x3d\xf3\x93\xf5\x8a\x27\x14\x1b\x3b\xa1\xdf\x34\x52\x7f\xc2\x43\xee\x40\x34\x3d\xe4\x07\x94\x4d\x10\x79\x2f\x93\x9d\x03\x8c\x1f\x24\x08\x34\x15\xa5\x58\x4a\x75\x3f\x8c\x06\xef\xda\x47\xa3\x8a\xc4\x24\x18\x21\x1f\x60\x8e\x14\x5d\xe3\xa1\x1f\x64\x73\x1b\x88\xcb\xa0\x36\x6a\x50\xa6\x01\x87\x05\xe9\x33\x45\x06\x9a\x54\x58\x43\x07\x41\x28\xc6\xc8\x21\xf8\xcf\x1d\xf8\xcd\xa0\xff\x15\x86\xfd\x09\x29\x3f\xec\xec\x38\xfc\xc8\x80\xac\x2a\x8f\x70\x74\xe1\x33\xc9\xe7\x76\x92\x42\x81\xac\x0e\x85\x51\xe1\x50\x90\x03\x3a\x74\x67\x3a\x0e\xc7\x6e\xb1\xd1\x05\x91\xf0\x81\xea\xce\x1d\x4d\x93\x94\x77\x37\xf0\x55\x1d\xa4\x6f\x76\x68\x83\xf1\x57\xfa\x09\x26\x18\x5b\xf9\x3b\xa6\xde\xc4\x0f\xd8\x02\x8e\x36\x85\x4b\x0b\x98\x56\x6e\x16\xca\x21\x25\x16\xc6\x2c\xc7\x95\x78\x2d\x3f\xeb\xfd\xb8\x17\xff\xfc\xd3\x9f\x32\x1b\x4d\x72\x04\x58\xcd\x71\x92\x87\x00\xd8\x42\x90\x0b\x6b\x2a\x46\x26\x1d\x83\x92\xcd\x8e\xdc\x56\xec\xa6\xc6\x20\x32\xc0\x4a\xbe\x8f\x46\x69\x81\xa4\x01\x9c\x6a\xc5\x9e\xda\x10\x01\xa1\x68\x68\xe9\x59\x69\x6c\xb2\x5a\x36\x19\x99\xda\x3c\x7e\xbb\xe5\xc8\x14\xc3\xfd\x06\x24\x46\xa9\xb6\x0e\xa2\x12\xd3\xbd\xc2\x82\xba\xa2\x58\x60\x1c\xf4\x28\x06\x03\xc3\xa8\x47\x79\xee\xe9\x23\x24\xba\x4e\x97\x54\x1d\xfc\x20\xd7\xdd\xa8\xbe\x7f\x82\x0b\x89\x49\x3a\x63\xa5\x2d\xfa\x9a\xc2\x91\x65\x7b\x94\x20\x56\x48\xb7\xd3\x7a\x7f\x0a\x81\x43\xd2\x72\x5f\x80\x2a\x4e\x7d\x12\xb7\x64\xa6\x68\x7c\xf4\xe2\xd5\x7b\xb0\xc3\xbd\xa7\x78\x8d\x77\x33\x35\xbb\xb1\xfd\x07\x86\xc2\x82\x18\x1f\xd9\x75\x2c\xc7\x51\x93\xf9\x60\xac\x8f\x18\xb7\x81\xe3\xb7\xf4\x32\x2c\x4d\xae\x2b\xf0\x19\xda\x39\x14\x3a\x8c\x86\xf9\x2c\xf8\xe8\x84\x1d\xdb\x40\xc8\xca\x85\xc5\xd8\x92\xdb\x6b\x23\x3b\xf6\x79\x7d\x85\x89\x54\x30\x24\xc2\xc5\x53\x69\xb5\xc5\x2e\x3a\x32\x0f\xf7\xc3\x68\xa3\x81\x5e\x5a\x0d\xb9\x6d\x1e\x51\x05\x3a\xe3\x28\x60\x9c\xdd\x54\x78\x4c\x71\x3a\x1d\x5a\xe1\xab\x0a\x12\x60\xdd\x69\x73\x0b\xcc\x5d\x7f\x4c\x09\x19\x2f\xfb\xd4\xf6\x5a\xb5\xdf\x65\x79\xac\x5c\xb9\x86\xd9\xff\x7f\xff\xef\xff\xe7\xe1\xd3\xd0\xee\xa7\x7e\xe8\x1e\x3e\x65\xc9\x32\xc0\xe3\x38\x22\x02\xf1\xf6\x5f\xab\xd1\x1c\xc8\x5e\xf6\x03\xfe\xaa\xf8\x1b\xa8\x54\x35\x1a\x47\x26\x18\xf0\xa3\xa2\xaf\x40\xac\x2a\x0a\x74\x17\xa8\x54\x55\x99\x78\xc8\xbe\xb1\xc5\x39\xfb\xb7\x51\x37\xb7\x35\x5e\xa8\x5d\x88\x7f\x0b\x5f\x02\x82\x9c\x11\xab\x11\x4e\xad\x78\x04\xc1\xa2\x9d\x9c\x63\xb9\xd7\x2a\xd0\x2d\xf2\xbe\x4f\x47\x96\x2c\x59\xa7\x23\x1f\x1a\x0c\xd8\x69\xa3\xaa\x7e\x74\x3b\x94\xe1\xb8\xb6\xeb\xd1\xed\x20\x84\xcb\x67\x0c\x11\x94\x63\x80\xa9\x99\xe1\x58\xcb\x41\xd5\xfb\xe8\xe5\x30\xdd\xdd\x71\xe1\x90\x23\x5d\xba\x92\x3b\x2a\xbf\xaa\x2a\x3c\x82\xd1\xcd\xc1\x55\xf1\x54\xa5\xd3\xd4\x0f\x0a\x90\x0e\x4a\x05\x48\xaf\x06\x36\x30\x94\xa6\xad\xbd\xdc\x62\xc9\xc0\xfa\x50\x51\x3b\x08\x2f\xb7\x84\x08\x30\xff\x42\x3f\x2b\x2f\xc1\x1c\xed\xbd\xdc\xce\xa3\xee\xf5\x63\xd7\xcd\x63\xf3\x75\x72\xad\x20\xf9\x0a\x7e\x54\xfb\xd0\x48\x6f\x8d\xc2\xd3\x93\x3f\xaa\x06\x9c\x37\x5c\x74\xe3\x70\xd5\x56\x33\x8b\x50\xb6\x81\x82\x1f\xa0\xee\x10\x7f\xc2\x10\xd4\x83\x3c\x84\x34\x79\xc0\xcf\x9d\x76\x14\xc3\xf1\x25\xfe\xc2\x64\xbc\xb7\x01\x50\xb8\xac\x89\xf0\x20\x81\xd0\x1e\xb9\xe6\xdf\x98\xe5\x6d\xe0\xe9\x86\x34\x3b\x6c\xce\xe3\xad\x15\x98\x81\x4c\xb5\xdb\xd9\x83\xa9\xee\x74\xab\x2c\x9c\x19\x14\x8f\x01\xa3\x58\xae\x07\x7b\x70\xcc\x74\x86\xd1\xc6\xcf\x30\xbd\xe6\x41\x8a\xdd\xf0\xf2\xfd\xeb\xab\x7f\x16\x80\x23\xcc\xc3\xaa\x8a\x33\xb1\xb2\x77\x6a\xa0\xa0\x21\x6f\xe9\x67\xca\x24\x77\xd5\x6c\xc8\xc0\x54\x53\xa5\x91\x8b\xa0\xce\xcb\xae\x80\xbc\x09\x09\x0b\x80\x18\xd1\xf0\xb2\xeb\x16\xf2\xc8\x10\xa9\x5e\x1f\xa3\x29\x55\x2b\xe0\x7a\x27\x90\x60\xb8\xe2\x49\xc0\x6c\x72\x33\x65\xfd\x48\x86\x98\x70\x80\x95\x6a\xc3\xd2\x5f\x41\xdc\x4b\xb4\xb0\x7b\xa3\x0e\xc8\xde\x52\x16\xda\x5d\xd5\xd1\xfe\x0e\xfc\x97\x72\x80\xf0\x8f\xb3\x7f\x6d\xb5\x2f\x32\xfb\x41\xc1\x3a\xc0\x66\x39\x24\x71\x30\xb2\xd8\x20\xc7\x80\x28\x1a\xd4\x80\xcc\x58\x53\x87\x23\xb5\xe6\x0d\xf7\x14\xe5\x86\x90\x29\x8c\x35\x0f\xe1\xbc\x85\xcc\xa2\x11\x40\x8a\xf2\x96\x78\x5e\x42\x0c\xb6\x1f\x9d\xaf\xd7\xaa\xb6\xa6\x96\x69\x6c\xfe\x83\xed\x86\xd7\xe0\x8a\x26\x79\x7f\x86\x83\x4f\xde\xa2\xf7\xc2\x60\x83\xa0\x2a\xb8\x1f\x1c\x42\x2e\x47\x0e\x92\x0f\x86\x79\x84\x7e\xe4\x98\x81\xd6\x4e\x19\x7c\x0a\x09\x19\x60\xd9\xac\x3e\xc7\xc7\x8a\xb3\xac\x57\xb9\xde\x6e\xd6\xaf\x40\xb5\x6a\x88\x08\x46\xea\xdf\xbc\x01\x40\xd2\x30\x5c\x58\x52\xd1\x7c\x53\xef\xd0\x66\x15\x9a\x94\x8e\x32\xf0\xf8\x2a\xcd\x02\x96\xaf\xc9\x79\xa1\x05\x66\x0f\x1c\xbd\x79\xb9\x91\x17\xc4\x00\x95\xad\x56\xab\xbc\xbe\xa8\x4e\x00\xad\x5d\xe0\xd6\xd3\x21\x7e\x8e\x21\xbc\x80\x9b\xd3\x1e\xef\x46\xe1\xf4\x7c\xb4\x0a\xb0\xac\xba\xcc\x0b\x6c\x2d\xeb\xa5\xd6\x6a\xab\x31\xd8\x27\x08\xd5\x8a\x82\x8c\x24\x24\x6b\xd9\xdc\xba\x5e\x42\xcc\x47\x6c\x0f\x9c\xcf\x76\xc8\xd6\x6b\xa3\xba\x1a\x8c\xb1\xc5\x85\xc0\xcf\x98\x09\x94\x35\x5b\xf4\xe4\x31\x37\x59\xf3\xb2\x6d\x6b\xbf\xef\xd9\xca\xe9\xc1\x99\x7b\xf4\x98\xbb\xfd\xe4\x41\x06\x95\x00\x1e\xa4\x6d\xd9\x62\x60\x5b\xb2\xad\xcc\xf3\xa6\xa6\xc9\x79\x1e\x35\x8d\x0e\xc1\x18\x3c\xb9\x05\x1f\x75\x8e\xde\x26\xd4\x67\xaf\x4c\xab\x5a\x91\xc9\x18\xd9\xdc\x10\x12\x1c\xda\xee\x58\x7b\x8b\xab\x34\x51\x1b\xec\x2f\x03\xf0\xb0\x93\xaa\x8c\xd9\x66\x04\x7f\x18\xba\xfb\x3d\xb8\xa5\x47\xd5\x19\x64\xa4\xea\x12\x03\x91\x6a\x60\xd6\x81\xd5\x6f\x26\x7a\x3c\x26\x3c\x1b\x08\xe7\x06\x0e\x30\xd0\x1e\xb0\x17\xc0\xa0\x9e\x22\x9c\xa2\xec\xa1\xbf\xca\xe9\x20\x7b\x05\x80\x15\x34\xb1\x44\xa5\x37\x65\x3e\x12\x13\x4b\xdd\xe9\xe2\x25\xb2\xb6\x56\x18\x94\x93\x76\x0c\x08\x33\xb3\xf8\x9b\x54\x96\x99\x06\x54\x48\x27\xb5\x35\x92\x6c\xdc\x6c\xa5\xb6\x3a\x06\x90\xcd\xf5\x26\xbc\x16\x78\xf9\xd7\xda\xd5\x32\x52\x47\xe3\x59\x75\x4a\x92\x70\x2f\xc9\x70\x14\xa3\xc7\x48\x3c\x79\x27\x8c\xf3\x7d\x15\x01\x7d\x80\x3a\xdc\x71\x4f\xa7\x7b\x8c\xc4\xca\x02\x9b\x14\x9c\xc9\x77\x44\x34\x04\xe0\xdd\xab\x39\x18\x03\x58\x4f\xab\xb5\x20\xd4\xb3\x51\x85\x6a\x52\xab\x52\x45\x85\x9c\x99\xb3\x86\x5f\xdf\x05\xa2\xc6\xb5\xb1\x35\x2a\x32\xb2\x8b\x83\xa2\x3b\x6c\xba\xc1\xe4\x7b\xa2\xf9\x88\x3a\x86\x53\x15\x91\x45\x6d\x7d\xd8\x65\xd5\x32\x49\x9d\xd9\x82\xb1\xfd\xad\xd3\xa6\x51\x29\x3a\xad\x6a\xb9\xfe\xd5\xfd\x2a\xbd\x14\x82\x00\xec\x3e\xe8\x06\xea\x10\x66\x01\x8e\x86\xa2\x12\x3b\xc4\x6d\x85\xe4\x90\xf7\xcf\x56\x6a\x93\xb6\x97\xb7\xe0\x8b\x84\xa7\x8a\xdf\x65\x27\x48\xd9\xd3\xd9\x52\xbe\xc4\x61\x04\x05\x57\x9a\xb2\xaf\x5f\xd4\xc6\x32\x6d\x0d\xa4\x27\xf0\x82\x38\x3b\x41\x72\x45\x63\x9a\xec\x24\x0b\xd9\xa9\x3d\x10\x7b\xd2\xd6\x64\x11\x4e\xdb\x21\x45\x82\xc2\xf4\x47\x64\x54\x93\x26\x1b\x9a\x8a\x5e\xa8\x41\x32\x9c\x60\xa3\x63\x71\x86\x8d\x08\xf1\x97\xd0\x84\x73\xc0\x8d\xeb\x56\x0f\x44\x8a\xf1\x83\x84\xd5\x44\x6c\xc8\x85\x0d\x9a\x1f\x99\x32\x37\x69\x7f\xe4\xcf\x1c\xdb\xba\x9e\xa8\x35\xc7\x01\x9d\xd0\x43\xc9\xe0\x45\x04\x15\x0b\x0d\x4c\xf8\x13\xc7\x4f\x84\x9e\x19\xff\x12\x2e\x17\x32\x38\x67\x12\xda\x88\x56\x56\xca\xdf\x68\x90\x0c\x9f\x6b\xd3\xc6\x34\x09\x7a\x9c\xe8\x12\x1f\xd3\x93\x24\x47\x9e\xeb\x31\x87\xce\xc6\x67\xa0\x25\xa5\x34\x8e\x68\xf5\x36\xfc\x8f\xa9\x46\x1d\x48\x51\x7e\x50\x43\x8c\xf8\x84\xf1\xf4\x03\xd9\x07\x99\x2b\x4b\x5e\x4d\xe5\xac\x2c\x2b\x90\x8c\x90\x88\x42\x34\xe4\xe7\xd9\x4d\xa7\xe4\x50\xc7\xf2\x4f\xc3\xa7\xe8\x66\x58\xa2\xe0\x96\xcb\x6d\x93\x6a\x72\x98\x37\x76\x19\x0c\xab\xcb\x21\xb1\xc6\xfd\x12\xb0\xed\x95\x29\x60\xdf\xf6\xca\xe4\x62\x63\x81\xd8\x3a\xd5\x4e\x30\xc3\x2d\xce\x32\xbc\x74\x10\x31\x11\xee\xb1\xe8\xe7\xbc\x9d\x19\x10\x36\x53\x2e\x80\x1a\x9b\xc3\xbd\xb1\x33\x20\xda\xb7\x91\x3d\x98\xce\x5e\x9a\x1f\x75\x98\x4d\x10\x66\xd6\x60\x59\x13\xe3\x9f\x01\x50\x3c\xf5\x8b\x6a\x22\x32\xaa\xac\xc0\x87\xb8\xe2\x2d\xc3\x2a\xde\xa8\x86\xdd\x25\x03\x97\xd9\xaa\x0d\x38\x06\x3a\x05\x3a\xd5\x72\x21\x4c\x8b\x6b\xb3\xb1\x39\x8d\x0b\x72\xac\x34\x47\x2a\x05\xfa\x89\x68\xcc\x88\x51\x78\x48\x87\xf2\x7d\xec\xe9\xf7\x1c\x94\x47\xae\x2d\xfa\x68\xd2\x68\xa1\x23\x27\x06\x42\x9f\x36\x8c\x02\xf8\x9c\x68\xd5\xc2\x05\x09\x0c\x89\x53\xfe\x54\x91\xd1\x91\x83\x15\x12\xf7\x2f\xc2\x33\x89\xcd\x85\xd0\x44\xee\x80\x56\x21\x8e\xf8\x62\x46\xa4\xb6\x18\x82\x0f\xd1\xc2\xfa\xf6\x72\x2d\x2e\xc4\x59\x0b\x8b\x3b\xce\x65\x58\xba\x29\x0b\x57\x32\x67\x92\x1e\x87\x27\xba\x98\xe1\x3c\x2f\x70\x0b\x78\x53\x83\xeb\x32\xde\xda\x74\x0b\x25\xee\xdd\xe0\x53\x98\x93\x98\x67\xdb\x98\x4a\xde\xb3\xdb\x12\xc4\x56\x1b\x75\x1a\xf5\x89\x72\xa4\x38\x07\x75\xf9\x3c\x67\x25\xbb\xae\x8e\xaa\xaa\xcb\xae\x13\xf8\xb1\x08\xea\xe8\xc9\x11\x6f\x83\x30\x98\x9a\xda\x92\x7d\xcf\x52\x21\x5c\xad\x6d\xbd\x3e\x52\x19\xdc\x76\x10\xb0\xf7\x44\x91\xbd\x32\x41\x72\x09\xec\x1c\x16\x79\x1d\x13\x16\x8a\x38\x0a\x59\x69\x07\xbf\x90\xb3\x82\xf5\xe8\xe9\xa8\x70\x8b\x20\x81\x68\x00\xc8\x5b\xf8\xb1\x04\x82\x26\xdf\x51\x7a\x7b\x47\x41\xc0\xd8\xdb\x6c\xb1\x62\x25\x5d\x2a\x71\xa5\xd0\xf3\xfe\xcb\xe5\xf6\xd6\xf9\x70\xcc\xa1\x85\xff\x6b\x0b\x81\x37\xe0\xf3\x9e\x7a\x52\x01\xac\x68\x56\x22\xec\x24\x56\x46\xe1\xef\xa4\x8b\xca\x8c\x8f\xc1\xee\x98\xcc\x87\xe5\x93\x59\xe1\x7a\x23\x6f\xd5\x02\x06\xd4\x66\x11\x34\x28\x8f\xec\x18\xb5\x46\x76\xcc\xce\x95\xcf\x38\x15\x9f\x7d\xb9\xc5\x63\xd8\xf1\xc9\x0e\x6f\x63\x56\xb9\xc3\xcd\xb8\xaf\xa9\x8f\x0e\x29\x00\x7f\xc5\xe2\x3c\x02\xb5\x0c\x55\xfe\x16\xbf\x53\x77\xff\x29\x70\xd8\x67\xd0\xd3\xdf\xb8\x18\x7b\x37\x22\x74\x16\xe8\xfb\x92\x9c\x5e\xa2\xf7\x0b\x5b\x5f\xb4\x99\x72\x87\x8a\xfd\x25\x36\xd3\x66\xce\x1a\x78\x0a\xc0\xfd\x57\xa9\xa1\x2e\x48\x1a\x7c\x70\x7f\xcb\x2c\x6e\x54\x04\xa1\x49\x07\xe7\xbe\x1c\x7c\x50\x30\xaa\x0c\xf7\x0e\x3e\x27\x99\xf7\x21\x1b\x8a\x02\x74\x6c\xa6\x25\x46\xa0\x93\x89\xa2\x61\x46\x96\xe2\xb1\x14\xba\x25\x6b\xf6\xef\xe3\x70\xc3\xd7\x13\x58\x2c\xc5\xa0\x63\x7d\x11\x07\x7f\x7e\x23\x16\xe2\x72\x07\xb5\x89\x78\xe8\x92\xbb\xc5\xd9\xc1\xae\x62\xb8\x0b\x96\x8d\xbe\xad\x8a\xde\xd2\x7b\x50\xd7\xf0\x23\xd5\xcc\x31\x4d\x81\xdf\x7d\x9a\x7d\xc6\x65\x5e\x58\xe4\x50\x22\x07\xab\xe6\x18\x4b\xa4\xb7\x28\x5c\x99\x28\xca\x27\x8b\x7f\xff\x69\x59\xc0\x6a\xac\xb9\x53\x83\x23\xf7\x05\xc2\x48\x0a\xcc\x5f\x5b\x9d\xa6\x67\xa2\xeb\xe0\xba\xd1\x88\xec\x46\xde\xa9\xc9\x21\xce\x2c\x4f\x64\xa1\xca\xfc\xc6\x76\x36\xb1\x58\xf0\x35\x05\x40\x2b\xa9\xb3\x76\x91\x3b\x4a\x4b\x93\x76\x2e\x44\x46\x2f\x4f\x1d\x84\x5c\xe8\x0c\x66\x4c\x34\x65\x65\x66\x8c\x38\x86\x0d\x84\xb8\x63\x6c\x40\x3c\xc7\x42\x9e\xeb\x00\x1a\xcd\xb4\x16\xc1\x96\x3d\x36\x91\xc7\xc8\xcd\x2e\x35\x08\xc1\xc9\x4b\x53\x9b\xc2\x12\x93\x70\x9f\x36\xa4\x5b\xae\x3c\xe9\x6e\xb1\xad\x5f\xd0\xdb\x66\x64\xb2\x97\x83\xd7\x8d\xee\x65\x24\x95\xd7\x59\x0a\x43\x4a\xef\x65\xb3\x0b\xdb\x3a\x67\xba\x7e\x43\xfd\x03\xa9\x1d\xc2\x7a\x44\x5b\xf6\x20\x68\x79\xb9\xfe\x6d\xa1\x74\x0c\xa5\x9d\x97\x8e\x89\x01\xc5\x6f\x15\xde\x85\x65\xe2\x5a\x7e\x27\x46\x99\x8d\xdd\xf7\x72\x50\xa5\x36\x36\xa4\x44\x75\xec\x22\x1c\xcf\x12\x03\xfb\x83\x15\xf1\x22\x07\x9e\x4e\x0b\x27\x58\xa9\x47\x04\x85\x63\x54\x81\x94\x68\x21\x72\xf7\x05\x44\x63\x98\x56\x48\x35\x5c\x08\xfa\x45\xf9\xc5\x25\xe2\xf4\xf2\x90\x7b\x6e\xeb\x41\xb9\xb1\x83\x19\x01\x8f\x32\xfc\x80\x57\xb7\x56\x11\x08\xde\x99\x0a\xdc\x56\xaa\x2b\x3b\x44\xf0\x15\x2a\xf2\x6f\x0d\xb9\x6b\xd5\xc8\xc0\xa8\x43\x9b\x43\x5f\x77\x4a\xb6\x59\xef\x07\x05\x8f\x3d\x4c\xf1\xef\xd5\xb0\x8d\x1d\xfd\x1a\xfc\xc5\x98\xee\x30\x66\x37\x7a\xd8\x76\x47\xd1\xea\x0d\x50\x5d\x2f\x48\xdd\xc0\xd5\xed\xa4\xab\xf3\x77\xca\xc2\x02\x89\xb5\xb1\x12\x69\x32\x31\x6b\xe5\x0f\x10\xed\x0a\x9c\x29\x42\xbd\xa8\x2a\x73\x3f\x4f\x3c\xa6\x1e\x41\x1d\x8f\x02\xe7\xd2\x12\xe1\xfe\x27\xf8\x40\xf2\x4d\x33\x37\x11\x33\x17\x56\x1d\x10\x3f\x5e\x43\x07\xd8\x32\xde\x0a\x18\x21\xe0\x76\x5a\xd6\x7c\xe0\x31\xc2\xee\x56\x7f\x8a\xee\x56\x42\x1b\x6f\x17\xdc\xb0\x08\x3f\x60\x22\xa6\x86\xab\xc1\xb4\x7f\x0c\xbd\x38\xfb\xf8\x3f\x3e\xf1\x96\xf0\x72\x5d\xe7\xa7\x03\x5a\xac\xc6\xcf\x02\x6a\xaa\xf0\x49\x79\xc5\xb5\x39\xeb\x18\x29\x9f\x78\x08\x6f\x71\xf1\x24\x1b\x2e\xcc\x20\x0b\xf5\x7c\x26\xbd\x15\xbd\x1a\x02\x55\xa4\xd1\x8c\x36\xbb\xab\x62\x68\x80\xdb\x1f\x52\x4d\x61\xd5\xc4\x9c\xf7\x33\xb4\x91\x0c\x12\x4c\x49\x05\x11\x45\x2b\xbd\xac\xd7\x03\x9b\xe7\x4b\x2f\xa3\x4d\xe6\x32\x2e\x82\x6d\xc7\x14\x8d\x89\x6c\xbd\xe0\x3e\x30\x23\xee\xdc\x76\xed\x6a\xf0\x48\x47\x55\xf0\x7b\x72\x33\xef\x74\xe3\x45\x4c\xd7\x8e\xc2\x21\xe1\x5b\x2b\x5b\x7c\xb9\x26\xbe\x50\xb7\x19\x94\xdb\xc1\xbb\x12\x01\x60\xa3\x0e\x62\x6f\x81\xa1\x8d\x14\x49\x9a\x1a\x4c\x10\x71\xbf\xe6\x56\x44\x45\x37\xc8\xa4\x88\x06\xa4\x78\x2d\x22\x43\x05\x16\x5b\x5f\x87\x0d\x3d\x20\x96\xf0\x25\x8a\x10\x95\xb8\xdc\x6f\x77\xba\xae\xe9\x13\x73\xb8\x1e\xf6\xd2\xa0\x71\xb1\x36\xc2\x0e\xad\x1a\x28\xe6\x2e\x38\x77\xfb\xdd\x12\x66\xe4\x4b\x11\x29\xb1\x73\xd9\x0d\x13\xa2\xc5\xf4\xb8\x6c\x03\x95\xe3\xcb\xde\x00\x80\x13\xf6\x0e\xd2\xf9\x62\x97\xd2\x13\xb9\x87\x4b\xb3\xcc\xe8\x2f\xea\x4f\x73\x83\x9b\x6c\x11\x4f\xc9\x1c\x2c\xe8\x25\x6a\x03\x9b\x68\x34\x44\x14\xa0\x54\x54\xb6\xff\x46\x7a\xa1\x07\x3e\x6e\x1c\xda\x5c\xc9\xda\xbd\x1c\xfe\x9c\x8c\x1a\xe4\xaa\x8a\xa9\xfc\xe1\x9f\xce\xda\x1f\xe9\x31\x2e\xb9\x57\x73\x9b\xd5\x90\x88\xa3\x96\xf3\x2f\xe1\x20\xd1\x0e\xc2\x5c\xc3\x1b\x10\x76\xe0\x11\x5a\x31\x61\x25\xa1\x29\x33\x58\x05\xfe\xec\x97\xfc\xc8\x2b\x60\x20\x7a\x99\x51\x87\x8c\x00\xd1\x3d\x59\xba\x5b\x62\xc6\x86\x3b\xa9\x71\x87\x62\xb8\x08\x2c\x85\xce\x09\xd0\x64\xd3\xa8\x55\x95\x59\xcf\x64\xcc\x45\x52\xd6\x64\xd9\x0b\x9a\xa5\x2c\x77\x59\xbb\x34\x05\x68\x93\x0a\xf5\xcc\x15\x75\xdb\xba\x1d\x55\x4d\xa2\xff\x1b\x0b\xa4\x24\x7c\x4d\x5b\xc0\x22\xef\x14\x73\x94\xff\xca\x0e\xd5\x6e\x5c\x87\x33\x1d\xa3\x53\xe3\x42\xcf\x0c\x86\xbc\x65\x4f\x12\xba\x9b\x27\xee\xac\x40\x3f\x39\x03\x17\x07\x27\xfa\x68\x86\xff\x79\xc6\x82\x41\x77\x9e\x9b\xfa\xfc\x6c\x54\xa0\xc6\x17\x3f\xf0\xe5\xf4\x8f\x65\x27\x15\xc6\x20\x0a\xff\xf3\x8c\xf8\x82\x0a\xa1\xaa\x71\x1d\x12\x46\x40\x4e\x29\xe9\xad\x8c\xf3\x68\x05\xf2\xe0\x78\x3c\x1e\x1f\xee\xf7\x0f\xdb\xf6\xc1\x42\xaf\x33\x26\x3a\x76\x7b\x62\x05\x41\xda\xaa\xc9\x39\x92\x61\xca\x64\x92\xe5\xb1\x03\x93\x96\x7c\x9e\x3e\x80\x82\x76\xad\x3c\xf8\x1d\x66\x64\x04\x76\x52\x9a\x3d\x17\x4e\x48\xdb\x77\x2a\x79\x9d\x05\x92\x87\xd1\x24\xf2\xbe\x4c\xe4\xb9\x2c\x6b\x12\x6c\xf9\xde\x06\x46\xab\x46\xe2\xaf\xed\x26\x35\x66\x32\x28\xf8\xfc\xe2\xc9\x21\xc9\xe4\xa8\x34\xac\x51\x96\x5a\x00\x5c\x96\xa4\x52\xed\xff\x9d\xd2\xd4\x52\xf5\x4b\xcb\xe0\x0b\xf2\x54\x75\xd0\xb7\x5a\x5c\x88\xbf\xea\x5b\x0d\xbf\x57\x14\x1e\x3b\x0b\x87\xed\x2d\x64\x7f\x57\xe4\x73\x5f\x43\x0e\x58\xc4\xed\xc8\x09\x58\xe0\x8b\x82\xe8\x65\x38\x76\xad\xe8\xf4\x2d\xf2\x1b\xb6\x19\x41\xd1\x72\xa4\x60\x68\xff\x09\x91\xc9\xec\x56\x81\x17\x78\x94\x61\xb4\xa7\x45\xb5\xc2\x0a\x69\x8d\x43\xb0\xc4\x9a\x1e\xa5\xa6\x4d\xee\xe3\xe3\x52\x21\x1d\xc1\xf3\x67\xab\x21\x81\xe4\x16\x4a\x27\xa9\x25\xc1\x63\x6c\xab\x1c\xeb\x1b\x7a\x7c\x0b\xf3\xd9\x74\xad\xb4\x54\x09\x3d\x47\xeb\xa5\x20\x50\x28\x21\xd7\x76\x24\x03\x2f\x52\x8d\x26\x02\x41\xfd\x80\x37\x82\xa8\xa6\x9b\x20\x5c\xa4\x3a\xc0\xce\x9f\x2a\xa0\xab\x95\x33\x07\x37\xe9\xac\xe2\x81\x72\x67\x0e\xc1\x61\xa5\xc3\x8b\xc6\x74\x85\x42\xba\x84\xa2\x3f\x29\x6f\xda\x1f\xf4\x33\x2b\x40\xe8\x60\x5b\x86\x32\xd6\xeb\x46\xd5\x3f\x31\x1f\x95\xfb\xa2\xa1\xad\xc6\x56\x11\xeb\x1e\xc4\x60\x8e\xcf\xc0\x6c\x50\xd8\xef\x6a\xf0\xf0\x68\x44\x9c\xa1\xf9\x25\x3c\x2c\x24\x40\xf5\x05\x57\xc8\x88\xc3\xd1\x34\xbb\x6c\x10\x39\x4a\x1a\x87\x3a\x61\xf3\x44\x57\x2d\x3e\x59\xcd\x69\x2b\x9c\x2c\x17\x5f\x88\xcc\xb2\xb2\xe7\x7e\x88\x47\xca\xbe\x4f\x80\xad\xd0\x23\x8b\xa2\xa2\x9f\x02\x42\x4b\x05\x5a\x49\xa7\x80\xe0\x8d\x67\x74\xea\x39\x05\x32\x1a\xbe\x23\xbb\x10\x1f\xf8\x77\x02\x5e\x32\xa6\x9d\x65\xd6\x6b\x94\xc3\x33\xbf\x28\xf4\xdd\x4e\x12\x71\xa0\xeb\x00\x95\x7b\x86\xd0\x24\xf7\xa3\xdb\xc1\x7b\xa2\x51\x03\xcc\x41\x5d\xb9\xa2\x2f\x79\xff\x9c\x00\x4c\x1c\xbc\xe2\xe7\x0f\xd9\xf6\x09\x75\x85\x4e\xb7\x10\x6f\x02\x6e\x17\x03\xbb\xfb\x3d\xe7\x83\xf6\x03\x02\x1b\x20\x5b\x75\x5e\xb0\x8d\x14\x35\xcd\xc0\x8b\x92\x6c\xb4\x92\x5a\x31\x31\x68\x9b\x66\x4c\x2c\x5a\xeb\xd1\x44\x93\xdf\x64\xdd\x3a\x6f\x6f\xf6\x56\x1b\xde\x14\x81\x03\xba\xf6\xf1\x2d\x36\x6b\xc8\x7d\x61\xd6\x94\x69\x8d\x89\xd8\x3f\x2b\xab\x61\x19\x30\x63\x83\xef\x0d\x22\xf8\x5d\xaa\xa9\x1f\xac\x87\x3b\xb7\xdc\x46\xf8\x9a\x13\x17\x56\xcf\xbc\x40\xf4\x7d\xc2\x9c\x6c\xf5\xc0\xe3\x69\x76\x68\x70\xb1\xc0\x8b\xbf\xb2\x69\x74\xab\x8c\x97\x5d\x92\x46\x21\xc6\xe8\x4e\x7b\x05\xd1\xc2\xb2\xf9\xc3\x57\x45\xd2\x16\xc0\xd0\x8f\x32\xb7\x29\x86\xc0\x8f\x6c\x2f\xbb\x5a\xad\xa6\xcb\xbc\xa6\xf6\xe2\x46\x26\xce\xfc\x3a\xa6\xdd\x03\x3e\x71\xe9\xc2\xca\x05\xe5\x0b\xa6\x1e\xb0\x43\x10\x6b\x7c\xd9\x66\x35\x1b\xad\x89\x71\x22\x8f\x14\x4c\xda\x7a\xb2\x19\x16\x8a\x44\x2e\x83\xc2\x4a\xa4\x31\x25\x4d\x60\x3f\xa8\x3b\xd8\x81\x61\xc4\x79\x5c\x17\x9a\xc1\xda\xf9\x89\x54\xc7\xef\x51\x16\x32\x96\x36\xce\x07\x42\x84\x76\x40\x3c\x83\x5f\x87\x33\x06\x53\xc0\x40\x2e\xd0\x4f\x1c\xb1\xfc\x8d\xe7\x12\x73\xb4\xf9\xa5\xb9\x64\x3d\x4e\x0c\xe8\xbc\xa6\x2e\x63\x34\x07\x8a\x24\x63\xac\x79\x18\x97\x24\xcf\x04\x30\x16\x28\xe4\x97\x48\xe3\x13\x33\xa5\xed\xe5\xac\x4f\x71\x35\xd6\x69\x21\x06\xaa\x1d\x17\xe9\x61\x67\x41\x3b\x01\x44\xb0\xac\xe3\xeb\xb0\xe5\x76\xaf\xc4\x2b\xdb\x81\xdc\xea\xbd\xcd\xb6\x83\xdd\xe4\xe3\x34\x1b\x24\x78\xcc\x2d\xb0\x92\xa9\x04\xba\x88\x1d\x7b\xe9\xe2\x9b\xfd\x13\x45\xc8\x4e\x35\xb7\xf7\xf6\xba\x78\x2a\xee\x8f\x76\x16\x0d\xad\x22\x2e\x32\xb7\x82\xcf\xfb\x8a\xe1\x18\xe0\x8b\x01\xb8\xbf\xf0\x9d\x6c\x0a\xdd\x4d\xf6\xd2\xfb\x7f\xa0\x45\x5c\x03\xb5\x08\x3e\x67\xb4\x97\x4b\xcf\x68\xef\xf5\x02\x05\xc8\x97\xd8\xd7\x52\xde\x9d\xb5\xb7\xf8\x20\xe3\x1a\x7e\xa6\x9c\xad\xf6\x9c\x19\x0e\x8a\x97\x65\xee\x5a\x3a\xdd\xd4\x19\x6b\xf3\x4b\x48\x58\x60\x70\xc8\x77\x2c\x83\x24\x17\xd6\x39\xa8\x3b\x9a\x86\x5e\x25\x0c\xe3\x72\x34\x8d\x78\x63\x0f\x73\x54\x01\x4c\x9b\x9a\x75\x7e\x09\x65\xc8\x89\xcf\x4f\x7e\x59\x27\x88\xbc\xb3\xa4\x97\xc6\xb2\xa5\x48\x11\x99\xdf\xf2\xbb\xa5\x37\x7a\xe1\x20\xce\x7a\x44\xb6\xe7\xf3\x1e\x91\x17\x4a\x38\x11\xbf\x2e\x5e\xf2\x52\x9c\xe4\xa9\xf1\x6c\xc4\x2e\xdb\xbb\x20\xb1\xb6\x79\x53\x2e\x29\x6d\xa1\x31\x81\x59\x9d\x90\x44\x10\xc2\xf0\x21\xf9\xac\x7f\x4e\xa1\x67\xb2\x91\x5d\x4d\x62\x5a\x90\xb9\xf9\xa9\xfa\x90\x94\x35\xa2\xeb\xec\xa1\xa6\x60\xdf\x79\x15\x97\x10\x37\x93\x03\x78\x47\x5f\x0b\x40\x08\x91\xa4\xca\x90\x04\x3d\x06\x01\x28\x9b\xa1\x3e\xcf\x9b\xc1\x69\x93\x76\x14\xa0\xf4\x5c\xfd\xaf\x0c\x0a\x3c\xfe\x87\x77\x57\xf7\x80\x73\xb3\xff\xbd\x78\xb5\x78\x1d\x86\x1e\x29\x1f\x92\xf1\x0f\xef\xae\xb0\xf5\x7e\xa7\x8e\xa5\x89\x99\x97\xeb\x6c\x72\x50\x90\x9e\x8c\x37\x5e\x98\x83\xd3\xb8\x1a\x4e\x8c\x38\xc0\xd4\x04\x33\x19\xfa\x4e\x6f\x77\xfe\xa0\x20\xac\xce\x09\x5c\xc5\x7c\x94\x8d\x38\x31\x23\x74\x75\xfc\xcd\x73\xb2\xd4\xd0\x38\x39\x27\x5a\x17\x0b\x53\xce\x74\xa2\xc0\x50\x51\xbc\x27\x9c\xcb\x33\x96\x15\xfd\xef\x9e\xb4\x1c\x75\x54\x94\x9d\x6e\x9c\x78\x0e\x30\xf3\xf2\x38\x34\xce\x1f\xd1\xcb\x60\x19\xc1\x1b\xb9\x87\x60\xa9\x01\xea\xe7\x7b\x71\xac\xf8\x99\xa6\x0b\xf1\x06\x7f\xdd\x0f\x5e\x3c\xed\x14\xe6\x3d\x7d\xde\xd7\xd7\x3c\x92\x0d\x47\x83\xcc\xad\x40\x51\xd4\xfe\xaf\x70\x76\xfe\x5d\xfc\x57\x58\x2a\x7f\x17\xff\xa5\x4d\xab\x3e\xff\x9d\x6f\xcd\xe2\x6b\xe4\x81\xdc\x9d\xcf\x42\x9e\xa0\xea\x3b\x0c\x02\x14\xcb\x4f\xff\xb1\xeb\xa6\xbb\xa5\x94\x9a\x28\x78\x56\x8f\xcf\x26\x0d\x7a\x3d\xe2\xc9\xc7\x57\x9a\xb3\xe8\x40\xeb\xb9\xd4\x80\x77\x4b\x18\x14\x03\x0e\x64\xf0\x6d\x12\x17\xe2\x15\x46\xc3\xe0\xbb\x71\xe6\x64\x20\x7b\x5a\x1e\x77\x18\x5d\x7d\xf0\x75\x1d\xee\xad\x11\x4e\x19\xb8\xfb\x88\xb7\x9c\x6c\xd9\x9d\xe4\x4c\x09\xee\x14\xbf\xa3\xe5\xe3\x33\xf8\x12\xff\xa7\x35\xb9\x24\x8e\x77\x3c\xe0\x49\xe7\x6d\xed\xc2\xd9\xc1\x06\x2f\x99\xa0\x0c\xb7\x67\x85\x2f\x7a\xd8\xce\xde\x09\x3b\xe8\xad\x0e\x2b\x8e\x9e\x8d\x89\x88\x8d\x3a\xd0\xeb\x3c\x3b\xe9\x10\x6f\x7c\x6b\x04\x43\xd7\x63\x35\x32\x3e\x70\xeb\xca\x0a\x4a\x1d\xc9\x6a\x22\x97\x44\x7e\x18\x5e\x3c\xc8\xb4\x06\xe6\x4e\x0d\x3e\x5e\x9b\x7a\xf1\xde\x8a\x77\x6a\x3b\x76\x72\xc8\x83\x00\x4c\x0b\x4c\x17\x24\xe3\x21\xf5\x26\x9c\xf9\x61\x59\x88\x81\x70\xe5\x0a\x02\x0e\x07\x40\xb7\x1f\x41\x36\x19\x30\x90\xf0\xb4\x16\xd4\x33\x39\x50\x34\x3d\xa4\x47\x57\xca\x00\x48\x45\xc5\xd9\x68\x50\x1b\xe0\x0e\x79\xa9\x15\x1c\x26\x9e\xda\x80\x71\x90\x16\x5a\x90\xac\xe2\x38\x12\x12\xdd\x2f\x4f\x34\x3d\x08\x8d\x31\xda\x26\x81\x21\x92\xc6\x1d\xa1\xf8\x8d\x52\x6c\x12\xd8\xac\x96\x11\xfc\x73\x42\x80\x6f\xc3\x5c\x04\xd2\x84\x3f\xdf\xf2\xeb\x32\x73\xb0\xa8\x18\x49\x4f\xca\x94\x83\x92\xc9\x45\x40\x0a\x68\x92\x26\xcf\x1d\xe1\x16\x6b\x76\xd9\x8b\xad\xa0\xba\x82\x98\x71\x6e\xa1\x79\x93\x69\x5a\x0c\xb7\xa5\x37\xd9\x1a\x06\x3f\x2b\x6d\x5a\x7d\xa7\xdb\x51\x76\xf4\x16\xd6\x69\xbc\x7f\x2a\xf1\x36\xd6\x80\x46\xe4\x24\xee\x49\x87\x80\xb6\x41\xa8\xdc\x07\x03\x19\x93\x6f\xd2\x33\x57\x8b\x3d\x0a\x64\x37\x9a\x87\xd1\x4e\xc2\xb0\xab\xe9\xd9\x9a\x5c\x57\x8f\x8a\x78\x58\x1f\x18\xbc\x9b\x57\xe9\xcf\x33\x2e\x8f\xec\xb9\x7e\x1d\x02\x4e\x60\x7f\x9e\x49\x2f\x17\xc1\x78\x42\xdf\xb2\x47\x95\x82\x42\xc0\x72\xb5\xd2\xcb\x74\x1b\x6a\x2c\x85\xd2\x5a\xcb\xe6\x76\x51\xcf\xba\x88\x7f\x61\x7f\xe5\xaa\xdc\x30\x70\x2c\x8c\x83\xc7\x5b\xa8\x38\x1c\x24\x67\x73\xe6\x75\x76\xe1\xf0\x2e\x27\x4d\xdc\xe0\xe4\xc9\x05\x5d\x99\xbe\x5d\x91\x69\xfc\x4a\x07\x51\x68\xda\x12\x3d\x3a\x31\x50\xdc\x81\xe2\xe1\xa9\x3f\x32\x5a\xa7\x07\x2a\x11\xa2\x2f\xc6\x57\x3b\x8d\xef\x4f\x27\x09\x5b\x16\x05\x8d\x7b\x13\xe8\xe4\x11\x4d\x95\xe6\xae\x67\xe7\x14\x54\x28\xe4\x06\xa9\x30\x0c\xf7\x39\x71\x90\xe7\xd1\x64\x98\x1e\x16\xcc\x6c\x38\x71\x0f\x9d\x6e\x21\x9c\x74\xd8\xed\x4b\x0e\xe2\xc5\xcc\x1c\xdc\x05\x05\x7e\xa1\x57\xa6\x05\x8b\x5a\x8c\x38\x3a\x57\x30\xdd\xbf\x3e\xbe\x70\x23\x75\x4a\xbe\x5b\x46\xc6\x72\xf7\x17\x9e\x49\x99\xef\x79\x3e\xc6\xdf\xa8\x03\xd9\xae\x26\xf9\x56\xde\x02\x3f\xcd\xd4\x18\x62\x6a\x32\x99\x5d\x40\xb5\x78\x0e\xa4\x77\xc1\x62\xd3\xb8\xc0\x70\xba\x79\x65\x64\xbe\xa5\x88\x7c\x99\xd4\xd9\xd6\x13\xfb\xdc\xcb\xb6\x85\xfe\x14\x76\xba\x27\x0b\x4c\x02\xde\x16\xb8\xca\xa0\xfa\xf3\xf5\x32\xa9\x98\x23\xeb\xcf\xaf\x27\xec\x90\x9b\xa3\xe6\x0d\x5b\xe8\xd2\x62\xb1\xc2\x84\x07\x0e\x32\x58\x8f\xc9\xbd\x95\x0c\xf5\xf2\x4b\x9a\x3c\xea\x63\x79\x28\x4e\xd6\xec\x3d\x91\xf8\xb9\x51\x78\x5f\x7b\x6a\xe4\x9e\x2e\x8e\x1a\x45\x0b\xcd\x55\x19\x49\xfd\x35\xf1\xe8\xca\x34\x61\x85\xc6\x1a\x9e\xde\x4c\xe1\xa7\x02\xff\xb9\x9e\x0d\x7c\xf1\x12\x67\x19\x81\x8a\x94\xa4\xf8\x2a\x02\xb0\x8f\x79\xd9\x55\xb9\x2e\x0e\xa8\x76\xa2\x35\x44\x4a\xa8\x89\x76\x2a\xde\xf8\x92\x8a\x0a\xcc\xa2\xf6\x63\xb3\xc3\x1b\x5e\xd0\x44\x41\xb8\x27\x71\xfd\xf6\xe6\xbd\x40\x1d\xb4\x1f\xf4\x76\x1b\x8e\x5d\xf1\xd7\x9d\x32\x81\xa6\xc1\x2d\x11\xd2\x35\xdb\x34\x23\xea\x2b\x5f\xd8\xad\x3b\x17\x07\xc5\x51\x76\x4d\x4b\x87\x50\xfe\xce\x0d\x2b\x61\xd0\x54\x52\xec\xac\xc3\xc7\x3b\x5c\xaf\x1a\xbd\x39\xae\xc4\x95\x92\x83\x11\xfb\x20\x41\x30\xc9\xbc\xd7\x09\x39\xf6\x04\x02\x08\x3d\x7e\x24\x73\x65\x3d\x0d\x49\xbe\x7c\xe9\x78\x9a\x0d\xcf\x14\x74\x29\xac\x2d\x8f\xf0\x7d\x36\x00\xf0\x4c\x1a\x1e\xc8\x1a\x62\x4f\xb3\xa5\xe9\x57\x2c\xd3\x59\x1b\xd2\x1a\xa5\xf6\x7e\x35\xe1\x25\x54\x2b\x8f\xba\x7b\x6a\xcb\x85\x78\xaf\x1c\x84\xfc\x84\xef\x2f\x80\xf3\x10\xdc\xa8\xd0\x27\x01\xee\x35\xa0\x9f\xc5\x65\x11\xb1\x86\x29\x55\x8e\x6c\x02\x78\x8c\xdc\x5c\x67\xb6\x58\x47\x16\x9c\x3a\xe0\x38\x4c\xfb\x89\x6b\x1f\x4d\x1d\xb1\xba\xbf\x8d\x6a\x54\x2b\xf1\xca\x8b\xbd\x3c\xc2\x5b\xb3\x60\x91\xe8\x54\x63\x4d\xeb\xd8\x50\x4e\x7b\xf0\xd2\x76\x62\xec\xd9\x6b\x7e\x36\x25\xf3\xb6\x0d\x2a\x1b\xab\x77\xf1\xe3\x3e\xc0\xac\x07\x2f\x43\xcb\xbd\x74\xb7\x13\x1b\x95\x20\xff\x7d\x63\x2f\x52\x20\xe2\x58\x82\x1e\xcc\xd0\xe6\xde\xf6\xe7\x37\x40\xca\xf9\x25\x10\xd7\x5b\x0c\x4e\xf9\x8e\x7e\xce\x81\xd0\x40\x08\xfa\x84\xbf\xe6\x20\x3d\xbd\x3b\x1e\x5f\x20\x9f\x83\xac\x6d\x1b\xc6\xf1\x17\xdb\x1e\xe7\xba\x70\x5e\x5d\x51\x21\x0e\xb4\xa8\xb7\x07\xb8\x09\x5e\x1f\x21\x43\x7b\xa7\xba\x0d\xbe\x69\x11\xa4\x56\xc5\xc1\x80\xe0\xd6\x20\xdd\xc2\x22\x09\xa0\x79\x86\x3b\x13\xf0\x32\xcd\x2d\x7b\xf1\x21\xba\xe2\x71\xad\x69\x9b\x30\x54\x10\xb5\xeb\x15\x4a\x1c\xb0\x1a\x41\x09\x8e\x31\x9a\xce\x83\xc4\xde\x67\xe1\x14\x58\x4d\xd6\x0f\xca\x81\x0f\x17\xd0\x30\x78\xd4\x96\x41\x50\x64\xc3\x68\x1d\x59\xa4\xd5\xc4\xa8\x6b\x07\xf5\x2c\xb4\x88\x22\xe3\xc2\xca\x82\x98\xb8\x33\x88\xe4\xc3\x05\x40\xfc\xea\xce\x94\x05\x23\xf0\xa4\x61\x7f\x59\x90\xbf\xec\x00\x89\x13\x63\xb7\xc4\x37\x3a\x24\x00\xa8\xb3\x0a\x07\x03\xab\xa8\x32\x03\xea\x30\x56\x1f\xde\x5d\xe5\xc4\xfc\x5c\xc8\x70\xbc\xa3\x9e\xa3\x55\x1e\x9e\x51\x1b\xd4\x56\x0e\x2d\xc7\x26\xa2\x03\x66\x27\x3d\x1e\x24\x43\x18\x3e\x56\x51\x40\xc4\x40\xc2\x85\x61\x25\x6e\xb5\x81\xb8\xbe\x20\x99\x90\x52\x31\x08\x89\xc9\x40\x29\x1c\x2a\x63\x1f\xce\x19\x3c\xb4\xb8\x22\xe8\xfb\x0f\xff\x72\xf3\xf6\xcd\xb9\xf8\xfc\xf0\x70\x38\x3c\x0c\xc5\x1f\x8e\x43\xa7\x4c\xe8\x4b\x7b\x2e\xfe\xd7\xeb\xab\x73\xa1\x7c\xf3\xe3\x4a\xbc\xc6\xe3\x27\x51\x75\xb2\x5b\x06\x17\x08\x30\x02\x1e\x87\x7f\xe0\x58\xa2\xad\x43\x0a\xdb\xfc\x01\xff\x9c\x89\x0c\xd3\xc8\x0e\xb2\xfc\xf6\x3d\x38\xca\x66\x0c\x09\x3d\x4d\x72\x03\x3f\xa6\x19\x89\x7e\x03\x18\x2f\x54\x78\xb3\x4c\x3a\x71\xf3\xf2\xf2\x4f\xff\xfc\x3f\xc5\xcb\xd7\x97\x4f\xc5\x4e\x7d\x16\xad\xde\x2a\xbc\x9e\xe4\xad\x7d\xa7\x79\xd2\xff\xd7\xc3\xb0\x1a\x1e\xde\xe8\xad\x91\x7e\x1c\x14\x2f\x00\xa4\x13\x39\x8f\xd4\xc9\xe6\x76\xe9\xdd\xcb\x29\x88\x6e\xac\xa1\x01\x78\xd5\x58\x53\xf6\x1e\x41\xd8\x99\xeb\x29\xb8\x71\x25\xe5\x75\x58\x33\x91\x91\xd9\x29\x13\x08\xfd\xd8\xb5\xe5\x19\xbd\x56\xbc\x04\x54\xfb\x97\x69\x61\x08\xfc\x07\xcf\x64\x5c\x88\x7f\x81\x90\x4f\x3b\xb6\x7e\x0a\x59\xdc\x3b\x00\x9e\x96\x0d\x9b\xa1\xce\x04\xbb\x0b\xf1\x4a\x98\x20\x3a\xb0\x50\x99\xf2\xa2\x60\x39\xc5\x41\x2a\xbe\x0b\x71\xa5\xbc\xd8\x47\x95\x1f\xac\x71\xc4\x36\x2b\x51\x9a\xc6\x2e\x67\xf3\xa0\xfc\x92\xc7\x02\x64\xb3\xd1\xf9\x00\x96\x7e\x6a\x8b\xd9\xcb\x18\x89\xf7\x98\x16\xc9\x83\x3f\x2e\x64\xa5\xc8\xbf\x29\xa4\x22\x84\xb9\x5c\x9a\x1d\x8a\xc5\xb8\x38\x71\xd9\xc1\xc1\xd7\xc5\xb9\xda\x60\x5a\x66\x1a\xeb\x70\x31\x3b\x52\x7d\xd0\xa8\xa3\x8b\xe7\x39\x3a\xae\xb6\xe7\x82\x9d\x3e\xcf\xc9\x9e\xef\x9c\xa3\x44\xb4\xe7\x62\x34\xe9\x37\x3a\xdc\x91\xf8\xca\x9f\x60\x4f\x1c\x3e\xa3\xb9\x67\x7b\x8e\xaf\x58\xa7\x84\xd5\xbc\xa3\x85\x3d\x47\x61\x9f\x7f\x0f\x68\x34\x71\xc9\xad\x03\xfe\xff\xef\x4d\xde\x15\xe8\x9b\x3b\x9a\x66\x37\x58\xa3\x7f\x5f\xe8\x1b\x5e\xaf\x24\x97\x5d\x1c\x73\x76\xdc\xbd\x0f\xb8\x9c\x25\xc6\x40\x0b\x3c\x75\x27\x3e\x11\x3e\xaf\x9b\x02\x50\xa6\xf8\x93\x27\x00\xd2\x62\x65\xdb\xb8\x75\xa7\xc1\x54\x05\x7c\x0c\x97\xef\x90\x31\x64\x23\xc7\x6e\x9c\x66\xe4\x41\x9a\x4f\x9f\x85\xa8\xc8\x8d\xa4\x2b\x1d\x5e\x4c\xbe\x89\x1f\x44\x81\x10\x5f\xa4\x28\x4e\x71\x38\xc2\x4b\xb5\xc0\x32\x53\x3d\xb7\x4e\x4b\x12\x24\xf1\x08\x33\x29\x89\x00\x27\x75\xcc\x84\x13\x5a\x33\x73\x9d\x43\xaa\xe1\x94\x1c\x86\x51\x08\x58\x3e\xe0\x57\xcd\xe1\x4d\xbb\x67\x31\xad\x94\x6a\xf9\x90\x04\xfe\xa7\x3c\x21\x21\x0c\x12\x1c\x26\x39\x67\x13\xe4\xe3\xd2\x8f\x39\x80\xd0\x73\x6e\x5e\x71\xd8\xde\xd9\x33\x94\xc7\xc9\x50\xb7\xda\x35\x76\x68\xef\xc7\xfd\x0c\x81\xfe\x08\x76\xb3\xf5\xb2\xfb\x42\xd3\x9f\x11\xd4\xb7\xe1\xc7\x31\xe1\x57\x61\xf0\xf5\x9a\x49\x66\x6b\xf7\x12\xcc\x5f\x9f\xc1\x8f\xd9\xe1\xbc\x93\xc6\xa0\xa9\x3f\xfe\xca\xe7\xba\xef\xec\x91\xdf\x19\x7d\x06\x5f\xfc\x74\xfa\x1c\x24\x7b\x95\x73\xfd\xe4\x29\xbe\x8d\xf9\xc2\xfa\x66\x27\xbf\x7b\xfc\x68\xfd\x24\xf0\xe1\x74\x0f\xd0\x59\x7b\xcb\x5e\x3e\xb2\x85\x7d\x13\x1f\x9a\xe9\xe3\xeb\x95\xc9\x46\x45\xb6\x2d\x1a\x16\x69\x83\x43\x31\x79\xd2\x2f\x3d\xc9\x84\xad\x9a\x70\x69\x30\x07\xb1\x9d\x34\xf6\xa9\x37\x4b\x9d\x49\x4a\x03\x80\x82\x11\xd8\xe1\x73\x27\xb2\x7d\x08\x0c\x07\x69\x6f\xc5\xfb\x9d\x3a\xc6\xc0\xd5\xf0\xa2\x1c\x5c\xea\x96\x6f\xe7\x40\xf3\xf8\x49\xd1\xfc\xea\xd1\xd6\xe5\x20\xf3\x53\x26\x10\xc3\x07\xb5\x45\xe6\x28\xda\xd4\x8c\x5c\x7d\x5a\x38\xd0\x2c\xf5\x62\xfe\x86\x67\x84\x9a\xbe\x35\x9a\x7a\x7a\xf2\xad\xd1\xbc\x68\xfe\xe0\x68\x56\x14\x24\x84\x38\x08\x8b\x16\xe3\xc5\xb4\xcc\x9f\x13\x4d\x5d\xfd\x8a\x17\x45\x97\x67\x6e\xaa\x22\xfa\xe2\x54\xdf\xe7\x30\xd2\xe6\x9d\xfb\x8a\xb7\x45\xa7\x61\xe9\xbe\x42\x5b\xb4\xd4\x96\xdc\xa0\x38\x36\xe0\x6b\x75\x46\x79\xf0\xff\xb9\x33\xd5\x37\x3e\x27\xb0\x88\xf5\x0b\x4f\x0a\xb4\x7a\xb3\x59\x61\x68\xe5\xda\xd9\x71\x00\x73\x82\x5f\xe0\x5b\xdc\xc0\x37\x82\x50\x60\xc9\x0b\x8a\x30\x89\x89\xd1\xc9\x92\xbc\x2a\x21\x11\xdc\x6b\x41\x03\x1b\x2b\xbc\x10\xcf\xf4\x66\x83\xae\xb6\x6f\xac\x4f\x4d\x59\x61\x11\xb7\xb3\x87\x3a\xfc\x82\x17\x4a\xc1\xaa\x70\x67\x0f\x58\xe8\x26\xa4\x64\x60\xae\xef\xb4\xaf\x29\xaa\xf3\x4d\xf8\x80\xb8\xd4\x19\xc4\x68\x20\x06\x25\xc3\x7c\xc0\xcf\x1c\x2a\xa0\x8c\xc1\x35\xf8\x22\xea\xac\x8d\x81\x13\x41\xdb\x91\xae\xa8\x60\xab\x30\xdc\x59\x0b\x84\x10\xd4\x19\x09\x24\x7f\x41\xe8\xac\x8d\x8a\xf2\x04\x41\x03\x0d\xd4\xfd\x97\x57\x6f\xf0\x13\x62\x2a\x53\x34\x2c\x08\xae\xfd\x5c\x77\x34\xde\x10\x71\xd1\x8d\x3d\x04\x6e\x54\x2d\x07\x94\x0c\x79\x22\x4b\xce\x9c\x21\xf3\xf0\xda\x88\xc3\x5b\x5b\xef\xa5\x39\x46\xd7\xed\x1b\xbb\x57\xa4\xca\x39\x28\xa2\x83\x10\x82\x3b\x79\x8e\x5a\x2b\x42\x11\x82\xe2\x01\x61\xb5\x70\x40\x5b\x71\x44\xf1\xd5\x52\x64\x71\xce\xc3\x30\xf1\xcc\xf8\x05\x72\xc1\xcc\x1f\x43\xb4\x83\xdc\x80\x23\x5f\xf8\x1f\x53\xfb\x41\xa5\x62\xd7\x83\x7a\x38\x2d\x46\x0e\x77\xe1\x5f\x4c\x93\x3b\x74\xf6\x48\x33\x90\x66\x86\x7d\x43\xbd\x15\x67\x8e\xe2\x6e\xd2\xce\x2f\x11\xe3\xea\xaf\xe9\x7d\x4e\x5c\xfb\xf0\xb2\x62\xd1\xa7\xdc\x93\xef\x1a\x19\x54\x11\xc7\x01\xcc\x57\xf0\x75\xba\x7e\xb0\xed\xd8\xf8\x55\xd1\xee\xa2\x34\x72\xa4\x8a\x57\x9d\xe8\xec\x16\x74\x1e\x10\x28\x19\xed\x7d\x47\xd3\xaa\xc1\x79\x34\xed\x97\x19\x99\xd7\xfb\x7e\xc0\x9b\x12\x46\xef\xe5\x36\xbe\x9e\x27\xb7\x18\xa6\x25\xe5\x81\xe2\x3f\xe4\x84\x1f\x45\x99\xc8\x09\xb0\x17\x40\x16\x6d\xd5\xcb\x2d\x30\xf6\x4d\x1e\xdf\x3f\x08\xa3\xd6\x30\x73\x9e\x35\xa0\x38\xe2\x38\x75\x7e\xac\x71\x4e\xe9\xc4\x93\x4d\x3f\x6d\x5b\x0a\x30\x1e\x73\x3a\x2b\x5b\x94\xfd\xaf\xf0\xd7\x6a\xb5\x5a\x58\x35\xf3\xd7\xd3\xfb\x41\x3d\x9c\xce\x75\x06\x1f\x07\xe0\xaf\xea\x41\xd7\x89\xde\x6a\xe3\x05\x3a\xa5\x49\x5f\xac\x14\xbe\x28\xa2\xa9\xd5\xd6\x3c\x84\xf3\x32\x35\x63\xea\x8a\x19\xab\xa3\x85\x92\x96\xcc\x74\x55\x83\x93\x1b\xef\x08\xf0\x72\x2b\xb7\x05\xac\x9e\xb4\x31\xc0\xdd\x74\xb6\xa1\x90\xdf\x4f\x50\xa5\x59\xc0\x02\x30\x9e\xbd\x2c\x6f\xc5\x8b\xc5\x29\xcc\xf2\x71\xcb\xf5\x4c\xdd\xda\x1a\x3b\xa0\xbe\x3b\xde\xb2\x7b\xb9\xbd\xf7\xa1\xb8\x49\x6d\xf9\x85\x35\x56\xf1\x85\xd3\x74\xba\x07\x4a\x27\xb9\x0c\x0f\xf1\x3c\x81\x52\xd2\x1e\x99\xf1\x3c\x33\x5c\xe4\x54\x9c\xed\xab\xe2\xe1\xdf\x54\x82\x63\xda\x00\x27\xc0\xbf\xab\xea\xa3\x1d\xb6\x9f\x2a\xb8\x95\x84\x30\xe8\x31\x7e\x69\x7e\x05\x09\x6a\xe6\x00\x13\x7a\x74\x1f\xe0\xf3\xb1\xeb\x12\x74\xf9\x4e\xdb\x8b\xb0\x4d\x4b\xa3\x9e\x00\x80\x4a\x7e\x78\x96\x8d\x7c\x3a\xe8\x65\xb6\x15\x3f\xe9\x61\x87\x6d\xf2\xe2\xcc\xab\xc3\x07\x8a\x92\x6f\x20\xbd\x5a\x50\x91\xaf\xc5\x85\xb8\x86\x1f\x95\x36\x77\xda\x07\xfe\x61\xaf\xd0\x2a\xf0\x15\x24\xc0\x79\x63\x8d\xaa\x0a\x6f\x84\x0a\x82\xad\xd7\xec\x89\x70\xc1\x3e\x09\x94\x5e\xd8\x41\x5e\x14\x66\x91\xf9\x13\x24\x01\x65\xe9\x7a\x1a\x90\xc3\xa8\x2c\x38\xa5\x07\xe8\x48\x1e\x43\x49\x18\x42\x48\xbd\x0f\xba\x78\xf6\x2c\x50\x87\x91\x03\x5e\x02\x2e\xb0\x91\x34\x28\xf9\xc1\xa2\x0a\x98\xb5\x29\x22\x71\xb9\x55\xaa\x26\xa3\x35\x3b\xf4\x58\x4f\xc5\x02\x97\x0a\x06\xfd\x7f\x41\xf8\xe2\xdd\x1d\x52\xbb\x4a\x7c\xb6\x10\x93\xe9\x31\xdb\x5c\x0f\x0b\x88\x82\x48\xf2\x97\x6a\xf9\x29\xa7\xb7\xd3\xb5\xf1\x07\x1e\x73\x9a\xe3\xb8\xf7\x39\x27\x40\x97\x06\x34\x6b\x0c\xcc\xc3\x89\x46\x44\x56\xf6\x5b\x9d\x4e\xe3\xfe\x09\x0c\x53\xdc\x2b\xf9\x2d\x19\x39\x47\xfc\x15\x7f\xa5\xac\xce\x36\xec\xa9\x7a\x45\x3f\x4f\xda\xd4\xdc\xe7\x33\x51\x82\x66\xc4\xac\x18\xb8\x88\xe9\x6b\x0d\x70\xc8\x15\xc3\x0e\xdb\x7f\xcc\x13\xa3\x78\x5a\x74\xd6\x6a\x79\x27\xbd\x1c\x4e\x35\x1a\x73\xb9\xed\x5f\xdd\xf4\xa9\x99\x5a\x41\x61\xa6\xda\xaa\xd9\x63\x9f\xd0\xc1\x7b\x8b\x94\x4f\x7f\xe6\x0d\x8e\xf7\x84\x99\x99\x18\xd9\x98\xe0\xa3\x9f\x68\xeb\xf0\xe5\x97\x3f\x4f\x18\x1a\xdd\xf7\x04\xe8\xb4\x95\x81\x32\xc5\xb0\x96\x79\x23\xef\x2d\x91\x73\x33\x76\x62\xb4\xf2\xc7\x9f\x05\x5d\x36\x50\xb9\x6c\x5b\x56\x5b\xd2\x2b\x80\x3c\x7e\x49\x35\xba\xc9\x62\xca\x4f\xdf\xb4\x4d\x23\x07\x7c\x2b\x39\x2c\x16\xeb\xad\x22\x5a\xbf\xa2\xff\x3b\xdd\xd7\xc5\x53\xa0\xaf\x63\x7a\xf6\x2a\xe8\xcf\xb1\x18\xa9\x9c\x88\x8f\x6a\x26\xe9\x89\xbe\x42\x40\x04\x76\xff\x88\x40\xf8\x0d\xbc\xe5\x62\xce\xb4\x7c\x59\x07\xfe\xaf\x07\xdb\xa9\xd8\x50\xf1\xce\x76\x2a\x35\xaf\x0c\xea\x58\x16\x8c\x65\x62\x3a\xe9\x27\xf8\x5d\xc6\x98\x5e\xbe\xe7\xcb\xa9\x74\xc6\xe6\x2f\x7d\x00\x3f\x4e\xd8\x41\xbc\xf9\x79\x0a\x6d\x20\xa4\x3e\x9d\xc6\x6f\xec\xa1\xc2\xa3\x78\x05\x51\x23\x2f\xc4\xbf\x58\x6d\x28\xa5\xac\x14\xd3\x02\x67\x94\xde\xa0\x79\x17\x64\x2c\x7c\xa4\x7a\x9e\x3f\x79\x6b\x0f\x4e\xa2\xf8\xca\x1e\xbd\x95\x0d\x8c\x3d\xc5\x26\x35\x68\xc5\x53\xbe\x12\x87\x58\x27\x4f\xdf\x60\xb8\x88\xa2\xde\x1c\xe2\x6b\x2a\x86\x50\x00\xd3\xea\xce\x59\x97\x0f\x0a\xc0\xe8\x02\xa9\xf6\xdc\x0e\xb0\xe7\x4e\xed\x80\x88\x04\x65\x3b\x72\x88\xaf\x69\x47\xa8\x05\x02\xd3\xb1\x9f\xc3\xc9\xf6\xc8\xb6\x15\x68\x82\x9e\x1b\x9f\xb9\x69\x13\xd3\x6b\x6f\xef\xb3\xf3\x1f\x4c\x77\xdb\x09\x3f\xe3\x56\x4b\x47\x2a\xe6\xa0\xcd\xe5\x02\xcb\x81\x66\xf4\x8b\xaf\xb7\x7f\x99\x08\x40\xc0\xc1\x50\x32\x82\x66\x06\xf2\xc5\xeb\x13\xf3\x73\x09\xdb\x95\x58\x44\xe0\x15\x88\x36\x50\xe6\x97\x8f\x64\x84\xe3\xe7\x97\x90\x5f\xcc\x0f\x15\x60\x18\x79\x26\x5b\x80\xa8\xe3\x5e\x0d\x1b\x2c\xab\x75\x8e\x2c\x12\x73\x80\x8a\x44\x7c\x0e\xc7\x3b\x36\xe7\xf6\xb2\x8b\x25\x05\xd7\x67\x85\x5f\x2e\x43\xed\xe5\x71\xfa\x1a\x37\x84\x8a\x28\x76\xcd\x69\xc1\x6a\xde\x94\x74\xae\xbf\xd0\x77\xca\xa4\x05\x73\x52\xb8\x5a\xe5\x5b\x7d\xbe\x40\x32\x72\xad\x73\x26\x78\x3b\x40\xa8\x44\x9e\xf9\x40\x3a\xb2\x85\x01\xe8\x7f\x8e\x7d\x6e\xa4\x99\xd2\x06\x30\x57\x54\x72\xff\xe0\x3e\x12\xf1\x87\x9b\x03\x24\xe5\xfe\xf6\x00\xc9\xc0\xc8\xc0\xa6\xcd\xc9\xc3\x7d\xcd\x42\x7a\xf0\x87\x9b\x05\x14\xe6\x2b\x9b\x75\xce\x6d\x42\x3e\x26\xd0\x8b\x25\x4a\x71\x5f\x6b\x27\x82\x16\x2c\xe3\x77\xb9\xb4\xc5\x64\x03\x2c\x70\x41\x12\x5c\xb4\xc0\xcd\x14\xd4\xab\xd5\x74\x3f\x65\x26\xc4\xd9\x9e\xca\x7c\x14\xb8\x2d\x60\x2c\x4c\xbe\x5c\x74\x1e\x26\x54\xc6\x1a\x90\xcf\xf1\xb2\x38\xfa\x7b\x65\xc8\xe9\xba\xca\x0f\x47\xe2\x89\xe0\x91\xb1\xe2\x05\xd1\x78\x47\x45\xea\x2c\x1d\x63\xad\x54\x1f\x61\xe6\x3e\x55\xad\x74\xbb\xb5\x95\x03\x5c\x95\xf0\xef\xaa\xf0\xe3\xaf\x72\x42\x35\xe5\x90\xf1\x95\xe0\x6c\x50\x8b\xf1\x94\xa3\xdf\x05\x71\x31\xca\x19\x97\x45\x82\xc3\xf7\xe5\xb7\xcc\x4c\x6e\x47\x0a\x95\x43\x4e\x06\xe0\x53\xee\xbc\xda\x8b\x37\x98\x50\xed\xad\xd1\x68\xcf\xfc\x1a\x7f\x69\xb3\xad\x8a\x78\x4f\xcf\xc3\x47\x05\x11\x7e\x28\xe5\x4a\x3a\x5f\x79\xeb\xe1\x99\xd8\xf7\xe1\xff\xcf\xe2\xac\xad\x52\xd7\x57\xeb\x51\x77\x2d\x87\x53\xfa\x25\x7c\x88\x57\xc9\x2c\x2b\x03\x94\x7d\x5f\xdf\x21\xb1\xec\xfb\x8e\xbb\xc5\x6e\x5f\x09\x6e\xab\x7d\xcd\x71\x5a\x2e\xf2\xa8\x2d\x39\x8c\xcd\x41\xec\x02\x04\x36\xcb\x6b\x10\xed\xb0\x59\xe1\x63\x06\x11\xef\x24\x10\x86\x6f\x26\x22\x94\xf3\xd2\x6b\xe7\x81\x8b\xbc\xe1\xdf\x2e\x03\x48\xd6\x8a\x18\x8d\x8f\x3e\x72\x14\x30\x0d\x35\x19\x87\xc6\x69\xa1\x49\x00\xac\xa3\x5b\xaa\x92\x47\x15\xcc\xfc\x5a\xe9\xe5\x9a\xb5\x5b\x8f\xd7\xa0\xb4\x5e\x3f\x41\xcd\xef\x79\x96\x50\x2c\xb8\x3c\xa3\xb8\x7f\x4d\xc9\x25\x53\x91\xd2\xf1\xe9\xeb\x22\xc9\x79\x59\xd6\x25\x9b\x59\x2d\x7c\x65\x96\xa7\xb1\xc3\x4c\x4a\x61\xd7\x99\x02\xbb\x85\xe8\x03\x24\x23\x15\x59\xe8\x1f\x56\x24\xa1\x2f\xe2\xa4\x27\xa8\x57\xcf\xd3\x3a\xbb\xd5\x46\xa0\xae\xbe\xec\x1e\x49\x2e\x25\x4e\x0e\xf6\x56\xa0\x80\x20\xe4\x79\xca\x8e\x8d\x88\x8b\x54\xa0\x3f\x79\x02\x59\x07\xcf\x00\x53\xb4\x6b\xb7\x5a\x5a\x48\xac\x90\x88\x8b\x09\xb5\x12\x4b\x90\xee\xa0\xf1\xdd\xdf\x1b\xf8\xb1\x08\x33\x8c\xa0\xb5\x1d\xf3\xdd\xd1\x74\x4a\x9a\x7a\x34\x6b\x6d\xda\xda\xd2\xeb\xd9\x4f\x43\xa2\x18\xcd\x1a\x4c\x28\xdf\x02\xb9\x71\xf7\x16\xca\x38\x84\xcb\xae\x13\x98\xc5\x25\x33\xbf\xb4\x65\x56\x21\x61\x26\xa6\x83\x0c\x78\x65\x92\x94\x5d\xe2\xc1\x24\x84\xbe\x25\x03\x1e\xce\xfe\x2a\x1c\x93\x56\x26\x88\x88\xe6\xdb\x9b\x0a\xe7\x5b\x38\xcf\xf4\x9d\x9a\x34\xb2\xf4\xcc\x26\x90\x2f\x60\x98\x34\x71\x11\xc5\xb7\x37\x12\xf8\x0a\xb3\xc5\x53\xf5\x44\x23\x8f\x62\x50\x8d\x1d\x5a\x12\xe1\x3b\xeb\x3c\xd0\x5c\x7c\x67\xf5\x7e\x94\xa7\x5a\x7d\x2f\xce\x6f\xe8\x46\x38\x09\xb6\x4d\x6a\xbe\x15\x5b\x39\xac\xe5\x16\xfd\x90\x28\xc0\x94\x2d\x7d\xe1\x4f\x14\xbf\x6f\x80\xa1\x41\x6d\xe0\x23\x17\xd0\x9f\x6a\xdb\xa0\x20\x30\x8b\xec\xba\xda\xb9\x1d\xd9\x78\xbc\x53\x78\x4d\xf5\x60\xe5\xdc\xee\x91\xa4\x87\xe8\x15\x58\x43\xb8\x07\xf8\x46\xd1\x0f\x8d\x04\x57\xfe\x9f\x21\x8c\x12\x90\x76\x28\xcd\x3c\x7e\x18\xad\x1f\xef\xad\x68\xd2\x97\x8c\xae\x67\x63\x3b\x40\x53\xbc\xfa\xaa\x1e\x70\xe4\x9b\x77\x90\x44\x57\x60\x8d\x02\x5b\x7a\xa2\x62\xc0\xd7\x5a\xe7\x39\x83\xec\xf9\xed\x66\xb6\xe6\xef\xa9\xe2\x9e\x59\x78\xf0\x2d\xb5\xe6\xdd\x0c\x35\xdc\xb3\x86\x06\xa5\x8d\xf6\xb3\xad\xf0\x0e\x92\xb5\xec\xf4\xef\x7f\x70\x43\x2c\x21\xfe\x47\x37\xc4\x90\xb5\x6a\xda\xa5\x9c\x41\x80\xd0\x75\xf5\xd8\x13\x7b\x73\x83\x2f\xf1\x7f\xe8\x27\x1c\x0e\x58\xeb\x1b\x5f\x6f\xed\x60\x47\xaf\xf1\xcd\x36\x4c\x13\x2f\x38\xcd\x2d\x14\x80\x3b\x9f\x63\x3d\x52\x08\x4e\x2e\xf3\x1a\x92\xc5\x07\x78\x74\x2f\x95\x02\xf6\x90\xcb\xc8\x0e\x34\xe3\xa8\xb2\x07\xbe\x91\x4a\x5d\x72\x46\x56\x92\xca\xd8\xb5\x97\x14\x57\x91\x80\xdf\x52\x4a\x06\x0b\x37\xad\x6a\xa8\x3b\x6b\x6f\xc7\x1e\x38\x3b\x88\x0c\x85\xc9\xe2\x0a\x92\xc5\xfb\x90\x3c\xaf\x81\x5b\x15\x8b\x4d\x1a\x75\xaa\xdc\x66\x50\xb3\x32\xcf\x07\x35\x87\xe7\x91\xdb\x29\xd9\xcf\xc6\xed\xa5\x92\xfd\x6c\xd4\x00\x72\x3e\x00\x00\x7b\x7a\x14\xf2\x52\xba\x05\x85\x42\x5e\xe2\x55\xdb\x9d\xaa\x43\x83\x41\xd8\x14\xde\x04\x31\xe5\x44\x09\xe2\xa7\xa6\xad\xa2\xdb\xd1\x59\xab\xec\xfa\x3f\x55\xe3\x1d\x43\xbf\xc5\xcf\x9c\xe1\xb6\xd6\x3b\x3f\xc8\x3e\xb0\xc2\xe0\x82\x80\xc3\xf4\x0b\xa7\x07\x56\xb8\xb9\x9d\x8d\x14\x42\xcf\x87\x0a\xa1\x4f\x8f\xd5\xde\xf5\xd2\xd4\xce\x0f\x63\xe3\xc7\x41\xb9\x58\xe1\xeb\x9b\x5e\x1a\x71\x13\x33\x66\x35\xce\x4a\xe6\x2b\x74\x5a\x78\xa9\xe6\x46\x36\x3b\xb5\x58\xf5\xd3\x90\x73\x6f\xdd\xb3\xb2\x79\xe5\xb3\xe2\x4b\x3b\x65\xb0\x1b\xdd\x05\xa2\xb4\x1e\x9b\x5b\xe5\xeb\x9d\x74\xbb\xda\xc3\x2b\xa2\x19\xae\x6b\x06\x13\xbf\x00\x98\x78\x29\xdd\x4e\xbc\x07\xed\xe3\x02\xd6\x6d\x53\xef\x95\x97\x60\xae\x95\x61\x79\xf1\x54\xbc\xa6\xe4\xa5\x52\xa0\x95\xac\x49\x02\xa2\x5d\x18\x98\xd2\x0c\xc3\x5b\x50\x5c\x92\x50\x74\x19\x41\x96\xb0\x19\xf5\x99\x8e\xf4\xe6\xd8\xd0\xbb\xf5\x9f\x7d\x68\xc3\x3b\x4c\xc9\x60\x41\x8a\xdd\x36\x2c\x02\xde\x80\x25\x0f\x44\xab\x7d\xf1\x14\xb6\xef\x8c\x82\x25\x60\x24\x5c\x2f\x9e\x8a\x6b\x39\xba\x45\xc0\x5e\xe2\x66\x3a\x09\xc9\xd5\x33\x20\xd7\x3c\x85\xa3\x4a\x1d\x0e\x25\x92\x15\x54\x21\xac\xc0\x8b\x19\xa3\xc3\xd6\xbd\x44\x4b\xde\x0f\x4e\x0d\xe2\x35\x46\x8c\xbd\x0e\x69\x04\x6b\xd4\x21\xbf\x5d\x4a\xd7\xdc\x97\x98\xc8\x60\x28\x59\x80\x3c\x81\x29\xcc\x0b\xb7\x6c\x14\x0f\x24\x9a\xf2\x8a\xe8\xba\x98\x96\x0e\xd0\xde\x3a\x4a\xe3\xa8\xe7\xf1\x71\x3e\x4a\x07\x3f\x9c\x41\x6d\xb5\xf3\x14\x78\x04\xa2\x8b\x83\xb3\xea\x3b\x48\x66\xf9\x26\x77\x3f\x7e\x6f\xa1\x97\x59\xc7\x4a\x3b\x52\xee\xe6\x97\x23\xaf\xaf\x08\x47\xfe\x10\x14\xf5\x0c\x84\x17\xb6\x5f\x2c\x15\x2b\x6c\xc7\x88\x90\x61\x39\x76\x74\xc9\xdb\xe5\xa5\x41\xb2\x64\x51\x6d\x82\xe1\x0a\xa4\xce\x6c\x94\x7b\xe9\xdc\x01\xec\xd0\x59\xed\x0f\x17\x27\x42\x7b\xf2\x39\x84\x6b\x07\xb0\xe6\x1e\x0d\x59\xd1\x71\xeb\x53\x6c\x44\x32\xf2\x8b\x2c\x06\x0d\x04\xe5\x7c\xe9\x82\x35\x8d\x45\xb6\x52\xc0\x32\xa8\x5c\x23\x7b\xf9\x19\x85\x13\x18\x52\x0a\xcc\x4e\x96\xa4\x99\x63\xd0\x53\xce\xbd\xd2\x7b\x7d\xb2\x2c\xeb\x34\x7f\xb8\x51\x5e\x3c\xfc\x09\x9c\x66\x9d\x12\xdb\xce\xae\x21\x1a\x2d\x86\xd4\xed\x02\x8a\x1f\x09\x87\x76\x75\xbe\x28\x41\xf7\xce\x0d\x86\x9f\xe5\x22\xed\x07\xbb\xd3\x6b\xed\x71\x42\x16\x0a\x30\x00\xbf\x1d\xba\x8d\x6b\x39\xd4\x44\x4b\xbc\x28\x04\x61\xa0\x42\x06\xae\x50\x3b\x64\x76\x14\xbc\xe6\x31\x2c\x56\x10\x31\xc8\x5b\x62\x86\x21\x2b\x93\x3d\xbb\x1a\xd8\x3e\x0c\x3d\x99\xe3\xd1\xfb\xde\x0e\xa1\x0b\xb8\xd8\xbe\x84\x0b\xc1\x05\x82\x17\xbc\xf7\xd2\x92\x49\x77\x1d\xbc\x62\x90\xf4\xf3\xe2\xbc\xf7\x2a\xbd\x5c\x1b\xf0\x02\x4d\x6d\x0f\x26\xe9\x55\xb3\x96\xe2\xfb\x34\xa1\xbd\x29\x2c\x87\x0d\x9c\x69\xe0\x79\xe1\x5d\xc9\x20\x64\xe5\xe1\x55\x62\x34\xa4\xf4\x10\xa2\x1d\x62\x04\x0f\x74\x0d\x20\xad\x6b\xde\x80\x9d\x74\x64\x85\x74\xa2\xfe\x7d\xa1\x42\x2f\xaa\xcf\xf5\x63\x65\x03\xf0\x4e\x33\x7a\x26\xcd\xee\x99\x5c\xd9\x94\x05\x03\xb4\xcb\x6c\xca\xee\x7b\x0d\xc0\x0e\x14\x79\x62\x42\xdd\x8b\x8b\xfe\x82\xca\x43\x89\x9c\x7a\x43\x42\x69\x28\x05\x49\xe9\x12\x8c\xef\xbf\x50\xc9\x0c\x84\x7b\x5a\x5f\xb6\x9d\x8b\xda\xb0\x44\x79\x3d\x8d\x69\x79\x13\x30\x65\x7e\x4d\x8e\xe9\xa4\x3f\x14\x17\xe2\xaf\xf8\x8b\xd2\x41\x89\x88\xdc\xdb\xc0\x69\x53\xff\x3f\x82\x0c\xb2\x59\x38\xb9\x7f\x57\x15\x68\xc3\x0b\xba\xed\x4e\x11\x6e\x47\xb0\xf8\x82\x0b\x07\x6b\x21\xa2\x4e\x59\x59\x2f\x30\x25\x7f\xe5\x16\x53\x14\x44\xe5\x6b\x63\x7c\xbe\x96\xd2\x99\x66\xc5\x80\xe0\x94\x3e\x37\x7b\xcb\x9a\x4c\xe8\x27\xed\xcd\x6a\x03\xa8\xe5\xc3\x24\x6b\xa5\x53\xcd\x38\x68\x7f\x84\x40\xb9\xb6\xb1\x1d\xba\x0e\x43\x1a\xc4\xc8\x0d\x69\xdc\xce\x89\x73\x10\xa6\x42\x34\x8f\x0b\xf1\xd2\x3a\x6e\x77\x8f\xef\xdf\x5e\xdb\x81\x53\x40\xbf\xd7\x82\xe5\xb9\x36\xad\x78\xf6\xa6\x4c\x2f\xac\xdc\x62\xe4\x44\x7c\xcb\xdf\x15\x11\x14\x39\x3c\x22\x46\x47\x54\xab\xed\x4a\x3c\x7b\xfb\xfa\xff\x3a\x73\x39\x42\x3e\x1a\xb9\xba\x6b\xfa\x5e\x82\xc9\x2c\xe2\xe4\x60\xb4\xd9\xfe\x4c\x4f\x4e\x31\x0e\x78\x24\xcb\x0e\x68\x82\xde\x77\x61\x00\xbc\xfa\xec\xe1\xd6\xd3\x58\x4f\xaf\x5d\xef\xf4\x76\x07\xe6\x1e\xba\x53\x5b\x74\xf3\x08\xdb\x76\xc5\x33\x19\xf8\x2e\x7a\xcf\x0e\xf8\x2d\xba\xb9\xfa\x45\x3a\x95\x83\xc0\x10\x01\x40\x1c\x22\xe9\x31\x54\xa3\x5a\xf2\xaf\x16\x97\x9c\x7b\x12\x7a\xfa\x0c\x39\x50\xa4\xc8\x21\x84\xd6\x3b\xbd\x35\x0f\x35\xbc\xfe\x12\x48\xa3\xea\x5a\x8a\x57\x50\xc4\xa2\x5c\xcd\x6a\x60\x23\x37\x78\xc6\xe3\xcd\xfd\xad\x71\x23\x37\xfd\x66\xfc\x52\xcb\xf7\x52\x43\x48\x53\xf8\x3f\x05\xbb\x53\x83\xde\x1c\xeb\xed\x60\xc7\xbe\xce\x68\xf2\x85\xf8\x77\xc8\x11\x90\x93\x51\x6b\x2a\x87\x05\xe8\x2a\x11\x02\x4f\xc2\x58\xbf\x00\xe8\x6c\x36\xd2\xc0\x63\x09\x7c\x83\x24\x42\xe2\x23\x24\x05\x44\x6a\x78\x63\x4d\x90\x2f\x30\x56\x50\x87\x86\xbf\x58\x2c\xf6\x02\x8c\xd0\xa5\x86\x87\xa3\xaf\x28\x2e\x38\xde\xea\x65\xab\x20\x61\x0c\x48\x54\x1b\x04\x6d\xec\x16\x2d\x8e\x84\xee\x0a\x00\x20\x10\x4f\x00\x98\x8e\xa5\x0b\x45\x41\x83\x7e\x21\x9e\x2b\xdf\xec\x44\xca\x0a\x85\x68\x37\xa2\x17\xd7\x67\xde\xad\xb1\xcf\x50\x59\xd1\x65\xbc\x60\x8e\x00\x68\x92\x52\x40\xec\x03\x07\x54\x3b\x19\x8e\x0b\x27\x2e\x5b\x71\x73\xc9\xa4\x66\xef\xfb\x9a\x2e\x06\x6e\x5e\xbf\xbf\xbe\x87\x76\x05\x50\xa2\x2b\x00\x99\x11\x97\x90\x45\x04\x06\xb2\x32\x2a\xc3\x01\x97\x90\x4e\x39\x0e\x2a\xaa\x5a\x22\x58\x6e\x19\xee\x3e\x0e\x3a\xec\xf0\x41\x39\x3f\xe8\x06\xdf\xc9\xa7\x32\x2b\xf1\x7a\xec\xbc\xee\x3b\xc5\x29\x6c\x07\x0b\xb1\x16\x7a\x39\xf0\x8b\xe2\x8d\xdd\xef\xa5\x78\x70\xfe\x60\x55\x9c\x02\xb5\xef\x5c\x0a\xd4\xfa\xfe\xea\x46\xfc\x6a\x9a\xe1\x88\xe6\x32\xd4\xd3\x5b\xdd\x07\xb0\x1a\xd7\x7c\xe8\xf0\xad\xee\x01\x16\xd7\x3a\x93\x5b\xb9\xaf\x9d\x1a\xee\x74\x13\xf7\xe4\xf5\xe5\x6b\x50\xe1\xe9\x46\xe5\xc4\x9e\xaa\x86\x97\xef\x58\x88\x4a\x8d\xb8\x1c\xbd\x2d\x84\x28\x2e\x95\x3d\x30\x35\x3d\x1e\xd1\xd2\x85\xc7\x75\xc6\x63\x97\xd0\x05\xab\x5d\x1c\x7d\xbc\x2c\x4e\x15\x8b\x5c\x7d\x76\xf7\x96\xce\xe4\xa9\x34\x57\x16\xff\x92\x67\xe0\xaa\x38\x6d\x73\xd6\xab\xc4\xf3\x95\x46\xa7\x39\xb2\x8c\x4d\xbe\x6f\xdc\x16\xa3\x28\x96\x25\x0a\xc8\x1a\x19\x00\xb2\xfe\x99\xa0\x8e\x76\x40\xf3\x12\xb9\xa5\xd6\x7c\x8c\x17\x8c\x39\xef\x31\xe0\xa4\x25\x0a\xbc\xb3\x8e\x8e\xa1\x27\x50\x23\x17\x0d\x30\xeb\x23\x5a\x10\xd1\x25\x33\x19\x44\x24\x46\x3d\x05\x8a\x55\x8e\xa0\xf2\x78\xa8\xb8\x00\x80\xf7\x21\xce\x39\xeb\xe6\x84\x73\x2e\x9b\xf1\x05\x06\x1a\xd1\xa0\x04\x4e\x7e\x58\xec\xbb\x71\x95\x2d\x3a\x62\x4a\x26\x2e\x1b\x74\x1c\x68\xbf\x1b\xd7\xb5\xec\x75\xad\x4c\x8b\x6e\x3c\x17\xe2\xf2\xfa\x95\xf8\x95\x3e\x2b\x32\xb0\x58\x19\xeb\x6b\x07\x0e\x51\x3f\x80\x07\x9c\xf2\x3f\x72\x16\x69\xe2\xa3\x25\x06\x69\xe2\x9b\xc2\x20\x83\x60\xd7\x83\x34\x2d\xef\xf9\x5f\xc2\x07\xba\x5d\x51\xf6\x30\xe2\x59\x84\x77\xb5\x30\x98\x79\xd6\x1e\xfd\xcc\x42\x56\xf8\x59\x36\x20\x45\x0b\x9f\x04\x18\xff\xf0\xee\x6a\x02\x39\x65\x0b\xcb\xdc\x8c\xaf\x8c\xec\x64\x09\xb1\xf3\xe1\x5c\x68\xdb\xd0\x4e\x88\x42\x17\x7e\x2b\xe7\x96\xc0\x88\xf2\x03\x58\xf8\x3d\x81\x69\xd4\xe0\xd9\x9d\xf1\xa9\x1a\x48\x05\x84\x1e\x87\x13\xd0\x5b\x75\x64\xc8\x7f\x55\xc7\x25\x88\x40\x7a\xc3\x69\x97\xcc\x42\x5e\x6b\x03\x3a\x8b\x40\x82\xd9\x3e\xa4\x2c\x33\x1a\xfd\xb9\x76\x16\x74\xa4\x99\xa7\x04\xf8\x80\x7e\x16\x98\x91\x89\xde\x93\xd2\x20\x7d\xd7\x83\xb5\x9e\x46\xfd\x0a\xc5\x71\x6b\xfd\xc2\xb8\xdb\xcd\xa6\xd3\x46\xf1\x3c\xbe\xc5\xcf\xa5\xb9\xa4\x98\x53\xf5\x60\x47\xbc\xef\xd8\x66\xaf\xd0\x60\x62\xd8\x59\xd3\x15\x80\xa7\xc5\xf6\x77\x60\xaf\xe8\x90\x78\xf1\xbb\xee\x27\x70\xb2\xef\x6b\xd0\xe1\xf6\x12\xdd\x7c\x33\x5b\x1c\x50\xe2\x86\xf4\x59\x4f\x65\x5b\x4b\xe7\x94\x77\xf5\x66\xb0\xfb\xba\xd5\xee\x96\x3c\xeb\x04\xa6\xd3\x2b\x38\xda\xdd\x4e\xcb\x4a\x70\xec\xe2\x21\xc2\x2f\x18\x9f\x08\xe8\x76\xd9\x06\xba\x79\xb9\xbc\x7b\x9c\xdb\x2d\x88\x64\x59\x66\x5c\xd8\xbf\x7e\xee\xe1\x4d\xcd\xb6\x5c\xe0\x6e\xc7\xa2\x0e\x03\x14\x4b\xd2\xed\x56\x30\x95\x34\x2c\xef\xc2\x2c\x16\x43\xe1\x76\x61\x15\x6e\x95\x61\x90\x7f\x85\xaf\x25\xa0\x1a\xe2\xe7\x25\x30\x8c\xbd\x37\x05\xdc\xe3\xfa\x44\x4f\x79\xfd\xbb\xc2\x27\x80\xb3\x85\x7b\xab\x8e\x02\x64\x60\xc8\xb8\xaf\xa8\x5b\x28\xe5\x8a\xae\x29\x32\x82\x2e\xaf\xa4\x6b\xe9\xeb\x20\x8f\xfb\xec\xee\xfa\xfb\x09\xcc\xf7\x42\x7a\xb0\xfc\x29\xc6\x0a\x12\x6a\x7a\xa8\xa1\xc6\xb9\x26\xa1\xde\xc7\xf7\x1b\x30\x39\x2f\x06\x2c\xb2\xa9\x89\x5b\x04\x7e\xd8\x40\x84\xc9\x05\x20\x9a\x2d\x02\x9a\x4e\x16\x53\x5e\xdd\xef\xf8\xa9\x1b\x24\xbd\x98\x10\x57\x17\x6a\x23\x79\x79\x65\x0a\x8f\xc5\x55\x16\xa0\xef\x5f\x07\x00\x81\xb6\xd2\x2c\xd5\xdf\xc0\x17\x9c\x73\x05\x94\x34\x4e\xd7\xcd\x4e\x7a\x3c\x3c\x2e\xdf\xdc\xbc\x02\x5f\x7a\xa7\x7c\x01\x07\x2f\x4b\xd5\x49\x8f\xf2\x1c\x5f\x9a\x22\x6d\x4a\x0e\xb9\x97\x9f\x93\x66\x15\x94\xa6\xa8\x9b\x15\x51\x55\x0b\x89\x45\x99\x7e\x50\x18\x0c\xb7\xee\x74\xa3\x8c\xa3\xc7\xc6\x28\x51\x70\x62\x51\x86\x49\x10\x50\xf1\x2d\xd4\xc2\x04\x08\x88\xf9\x8b\x49\x1d\x44\x7c\x90\x22\x86\xd1\xaa\xf7\x7a\x1b\x5f\xf2\x23\x62\x84\xda\x4a\x18\xd7\x98\xbb\x84\x65\x90\xe8\xe4\x5e\x0f\xca\xb4\x6a\x60\x8a\x49\x58\x06\x79\x40\x3b\x0a\xcc\x2d\x08\x28\x60\x21\x07\xee\x7a\x13\x24\xa8\x30\xf3\x78\x35\xdb\x1c\xd3\x2b\xe5\x02\xf2\x44\x96\x57\xb6\xa3\x0d\x2b\x64\x05\xe4\xfa\x30\xc8\x1e\xde\x00\x31\x8e\x4c\xfc\x7e\x85\x5c\x01\xd4\x3b\xe4\x8a\x94\xbb\x84\x85\x3c\x94\xa1\x67\xd0\xab\xd0\xe0\x0c\x4f\x96\x8f\xfd\x82\xfc\x02\xd3\xd8\x07\x02\x9c\x51\xbf\x0f\x90\x20\x54\x49\x04\x73\x58\xaf\xf6\x3d\x2f\x61\x82\x0e\x49\x76\x90\xc3\x71\xbe\x9c\xa9\x50\x0c\x81\x7b\xec\x95\x4b\x05\x63\xa0\xdb\x90\xbc\x54\x0e\xbb\x25\x3f\xd7\xa4\xb0\xa3\x72\xd0\x1b\x48\x9a\x2f\x4a\x2a\x19\x0a\x71\xb0\x81\xac\x94\xa3\x12\x5c\xa4\x5d\xa7\x1d\xfc\x8c\xcd\x20\x17\xf7\x6f\xbb\x2e\x34\x79\x29\x35\xd7\x7b\xa5\xd4\x5c\x0f\x98\x52\x89\x0b\xfb\x90\x71\x60\xed\x7a\xe5\x5c\xc7\x4b\xf1\xe6\xe6\xaa\x58\x77\x59\x6e\x12\x4f\x7f\xd8\xd8\x41\x7c\xdf\x5b\xe7\xb7\x83\x72\xdf\x0b\x6b\xba\xe3\x8f\x59\x09\x9a\x9d\xeb\x6c\x32\x28\x75\x8a\xc3\xfd\xad\xd3\x5e\xfd\xf9\x7b\xc4\x90\xce\x57\xd2\x05\x66\xcc\x27\x69\x02\x97\x0f\x50\xca\x25\xb6\x79\x50\xe4\xa0\xd4\x4a\x30\x5d\x42\xbe\x99\x53\x45\x48\x9d\x95\x6c\xac\xbd\xd5\x2a\x15\xa5\xe1\x7b\xc7\x85\x30\xff\x54\xb1\x25\x8d\xd8\xfd\x25\xe0\x3b\xdb\xfb\xf4\x7d\xa2\x10\x3d\x79\x51\xf7\x83\xfd\x7c\x44\x19\x8a\xf9\x69\xcc\x11\x90\x33\x95\x78\x30\xc0\xc2\x0c\x5b\x24\x69\x20\x63\x80\x89\x6e\x8d\x15\xe7\x14\x0d\x64\x0d\xb4\xeb\x3d\xd1\xaa\x05\x04\x3c\x6e\x57\x0b\xc5\xb9\xbc\xda\x4b\xdd\xa5\xa9\x45\xf5\xda\xe2\xbc\x02\xe4\x69\xd6\x08\xb3\xdd\x08\xd6\x18\x75\x38\x0c\xf4\x67\x50\xec\x41\x82\xc0\x84\x12\x78\x61\xaf\x60\x06\xf0\x78\x17\xe2\xf9\x60\xf7\x65\xc6\xc2\x8e\xc1\x8c\x78\x90\xa8\xce\xe6\x87\xc8\xaf\x57\x6f\x27\x75\xaa\xce\x02\x5b\xc0\xd1\x54\x7f\xbd\x7a\x2b\xf8\x7b\xd2\x97\x5b\xdd\x4f\xb4\x2c\x4d\x26\x3d\x60\xce\xac\x7d\x75\x0e\x83\xaf\x37\x51\xb8\xd9\x2c\xa3\x2c\xf5\x35\xf2\x09\x42\xde\x23\x9e\xa4\x06\x80\x3a\xba\xf6\xea\xb3\xa7\xfa\x93\x7e\xba\x04\x96\x6d\x9b\x01\xd7\x12\x2e\x1b\xe0\xcd\xc2\x58\x40\xc8\x0e\x24\x3c\x08\x62\x57\x8e\x8e\x32\x2d\xf2\x9f\xa4\x99\x85\xdb\x76\x60\x40\x01\xa0\x84\x8e\x80\xf5\x06\x83\x8b\x5c\x88\xe7\xf8\xc3\x5b\x8c\x29\x9b\x4a\x86\xa4\x20\x50\xff\x2c\xce\xee\x4e\x61\x71\x18\xbc\xe3\x7d\x2a\x94\x5e\x01\xa7\x30\xbb\x01\xc5\x2a\xae\x73\xd8\xa6\x71\x99\x4f\xb4\x00\x8b\xeb\x3d\x94\x88\xca\x2b\x08\xbf\x52\x77\x64\x84\xcb\xf6\x0b\xf8\x9c\x29\xa4\x16\xa5\x06\xe5\x82\xa4\xc7\x97\x09\x45\xd9\x77\x21\x2f\x5d\x24\x9c\xc4\x80\xef\x6e\x66\xdb\x13\xde\xb1\xe1\xc7\x3c\x55\xda\xa7\xec\x00\xb1\x54\xdc\xe9\xad\xa9\x83\xb0\x8a\xb1\x4b\xb8\x74\x48\x16\x1a\xbd\x9b\x8a\x72\x51\x24\xcc\x8d\x26\x32\xa1\x30\x57\x03\xe6\xe5\x98\xa3\xca\xf2\xeb\x46\xf6\xbe\xd9\xc9\x8c\xa3\xca\x91\x52\xee\x32\x96\x29\x7d\x2d\xbc\x53\x22\xb6\xd3\xb4\xf6\xab\xb0\xda\x69\x2f\x4f\x21\xb6\xa7\xfb\x7d\x5f\x53\xeb\x18\x51\xe7\x6b\x8e\x05\x46\x0b\xaa\xfe\xb8\x4e\x41\xd5\xbe\xb8\x3a\xe1\x7d\x01\xea\x1a\x2e\x92\x68\xf6\x42\xfd\xc0\x25\x92\x07\xdc\xcf\x8e\x74\xf4\x03\xcb\x4e\x74\xd4\x48\x9c\x38\xd0\x21\x73\xd5\x0f\xf6\x4e\x53\x84\x21\xfa\x79\x0a\x24\x61\x66\x48\x42\x3d\x2d\x50\x1e\x54\x4f\x27\x47\x1b\xc2\x04\xe1\xc0\x71\x88\xde\x20\x16\xdc\x00\x8f\x33\x05\xdb\x36\xf8\xd8\xdf\x1d\x58\x36\xbc\x78\x2a\xf8\x6b\x0a\x18\x98\xc1\x4e\x6f\x14\x1b\x61\x05\xb9\x26\x7c\xa3\xdf\xce\xb4\x81\x6e\xd8\x4c\x8e\xd3\xa7\x37\xef\x9e\x4f\x8f\x51\xb4\xa5\x8b\xbd\x46\xeb\xb9\xc5\xd1\x04\xc8\x95\x6c\x65\xcf\x97\x25\xf0\xab\xcc\xbe\xbf\x23\x08\x93\x9f\x9e\x9c\x03\x72\x54\x6c\x05\x88\x50\x8b\x8d\x08\x70\x2b\x72\x10\x86\x67\xdf\x6c\x87\xa1\x34\x6a\x7c\xe2\x0c\x4d\x0c\x94\x73\x82\x72\x91\x39\xa7\x07\xd0\x12\x51\x8d\x0e\x26\x19\x69\x8d\x69\x27\xc8\x6a\xcc\x3f\xcd\x4b\x64\x30\x0b\xdc\x6b\x96\x3b\x95\x24\x2e\x97\x44\x88\x0c\x3e\x13\x1e\x6e\x66\x02\xc3\x04\x8e\xe5\x85\xe7\x0b\x82\x02\x07\x69\xca\xe4\x7d\xf2\xe1\x5b\x16\xf6\x29\x1c\xd8\x52\xd7\xb3\xf1\x9a\xc9\x59\xb3\x62\xb3\xfe\xa6\xc2\x27\xa4\xa7\x19\x8a\x6c\x08\xb2\xd2\x4b\xe2\xd3\x62\x51\x1e\x95\xac\xec\x92\x24\xd5\x6b\x30\x1b\xcd\xe8\x00\x26\x2c\x0f\x10\x41\xaf\x28\xcc\x07\x0a\x6d\x51\xac\x0c\x34\x90\x42\x7c\x60\x4e\x21\x58\x72\x59\x74\x73\x59\x42\x90\xe9\x62\xbe\x8c\x66\x3b\x70\xac\x11\x36\xda\x7b\x31\x70\x7c\x11\xbc\x60\x9a\x14\xe0\x23\x93\x0b\x66\xc7\x25\x97\x9c\x16\x21\xb2\xbd\x51\x2d\xc4\x64\x6b\xeb\x58\x92\x48\x77\xcc\xa1\x06\x27\x2d\x13\xbd\xd5\x1b\x87\x95\x5e\xe8\x5d\x1c\x55\x84\x8d\x97\x69\x19\x4d\xe1\x17\xe6\x23\x61\xe1\x22\x1c\xf6\x3f\xe2\xe7\x70\xbe\x8b\x15\xc4\x57\x3c\x68\x35\xbe\xcf\x97\x1e\x67\x52\xf4\x5e\x20\xb6\x76\x24\xab\xaf\x90\x22\x28\x65\x5a\xe0\x9e\x0b\x4e\x62\xb9\xb9\xc4\x56\x67\x74\xe7\x85\x3e\x41\x70\xb6\xda\xc7\x49\x82\x58\x8e\x3b\xbd\xdd\xc1\x8b\xaf\xd9\x54\x61\xfc\xc2\xa3\xf1\xf2\xb3\x88\xf9\x39\x86\xb0\xf6\xa1\x74\xa7\x0d\x3a\x62\x85\x12\xf8\x81\x0a\x32\x90\xa1\xa5\x70\xda\x6c\x49\xc5\xf2\xe3\x49\x04\x75\x16\x25\x93\x50\xe5\x71\x33\x17\xf0\x85\x52\xcb\xf8\x78\x47\x02\x96\x6c\x2f\x4e\x10\x04\xd8\x02\xc1\xb6\xa9\xe5\xb0\x25\x7b\x60\x39\x6c\x47\x70\x14\x2c\xaa\x00\xed\x99\xca\xa6\xee\x75\xd4\xb6\x4d\x26\x0f\xc1\x61\x6d\xe6\xd0\xb0\x38\x51\x09\xb6\x50\x00\x7c\xea\x33\xf8\xa7\xe8\x63\x3f\x07\x84\xb0\xe6\x09\x0e\x22\x9a\x2f\x80\x91\x89\x33\x02\xbd\x78\x1a\x41\x18\xa6\xb3\xdb\xb4\x5e\xae\xec\x76\x79\xbd\x04\x28\x54\x0b\x66\xea\xd9\x00\x8d\xda\xc0\xa9\x9e\x36\x80\x93\xba\xe6\x75\xa6\xaa\x09\xc9\xf3\x78\x50\xec\x1a\xbd\x6a\x06\x7c\x40\x2b\xfc\x7b\x2f\xdd\x6d\x74\x9a\x2e\x54\x45\x9c\xe6\x9a\x9d\x6a\xc7\x0e\x75\xc0\xf8\x33\xc1\xa3\x9c\x07\xf6\xe9\x60\x6d\xce\x19\xa0\xf0\xb3\xa3\xe3\x98\x85\xe1\x67\x01\xa0\x3e\xab\x66\xcc\x5c\x55\x7e\xc5\x6f\xb2\x0d\x4f\x68\x2c\x07\x5a\x19\x0d\x58\xa8\x5c\x63\x4a\x06\xb3\x10\xab\x2c\x36\x9d\xb4\xfe\xa8\xb0\x3f\x59\x7f\xac\x1e\x4c\x3e\x02\x14\xbb\x97\xb3\x57\x33\x7e\xb2\x01\xcd\xc4\xe3\x9c\x61\x21\x70\x29\x3e\x2f\x92\xd8\x6f\x88\x60\x8a\x90\x14\xdc\x32\xc2\x93\x5f\x31\x89\x74\x61\x86\x62\xad\xaa\x53\x0d\xc4\x17\x03\xf6\x38\x7c\x04\xee\x22\xe6\xb7\xaa\x80\x78\x46\x9f\x05\x8c\x36\x28\x1d\x60\x16\x0a\x19\xaf\x30\x8d\x50\x66\x6e\xf4\x7c\x27\x8f\xc0\x14\x15\x19\xee\xbf\x6f\x28\x65\x0a\xc9\x35\x03\xd0\x65\xd7\xcd\x46\x23\xd7\x50\xe6\x69\xf0\x22\x60\x16\xeb\x20\xeb\xd3\x74\x1a\x39\xcb\xf6\xb0\x8a\x57\xb3\xd6\xc6\x8b\x75\x9a\x11\x0e\x0a\xf0\x25\xe7\xcb\xea\x23\x8e\xfd\x27\x0e\x9e\x47\x76\xbe\x6c\x5e\x9f\xb9\xb4\x15\x31\xce\xcf\x20\x34\x77\x35\x28\x93\x3d\xb2\x8b\x5f\x45\x21\x50\x21\xe1\x33\x1e\x67\x1f\x7f\xfa\xe4\xf8\x1d\x0f\x6f\x33\x7c\x1f\xff\xf4\x29\xa0\xfc\xf8\xe7\x4f\x88\x15\x55\xfa\x8c\xb5\x1f\x21\xc8\x7f\x59\xe2\xa7\x4f\xee\x91\x1b\x9a\x47\xd3\xb2\x42\xfa\x09\x58\xc8\xfc\x1f\x09\x71\x2f\x07\x55\x73\xd0\x57\x5a\x94\x98\xac\x9d\x35\x14\xf8\x59\x39\x05\xf1\x7e\xe9\x6d\xe3\xf8\x24\x21\xb5\x88\xbf\x27\xe3\x83\xbd\x5c\xee\x62\x1a\x32\x1a\x67\x7c\x27\xfa\x42\xfc\x86\x0f\x3f\xd0\xbb\xd1\x59\x81\x47\x68\x24\xfb\x08\x8b\xfe\x13\x74\x34\x20\xf8\xad\x82\x47\x23\x12\x02\x7c\x43\xe2\x5b\x10\xe0\x6b\x13\x09\x03\xbf\x3e\xf1\x4d\x8d\xa0\xe7\x1f\x52\x33\x30\x41\xb5\x02\xcc\x4a\xbe\x1e\x11\x8e\xc7\xe4\x75\x8d\xdf\x78\x01\xe6\xaf\x64\x17\x08\xe1\xb5\xea\x93\xa3\x33\x43\x87\x83\xf4\xcd\xd8\x68\xa8\xa6\xe8\xe2\x88\x7d\x33\x42\x78\x35\x7b\x86\x0f\x52\xff\x48\x67\x71\xf0\xf0\x2d\xf0\x6c\xdb\x1a\x75\xa0\x07\xc2\xff\xf1\x4d\x43\x24\x26\xd6\xc1\x84\x84\xf1\xd3\xe6\xfe\x53\xda\xdc\x8b\xe8\x78\x73\xc3\x7b\x31\x5e\x6e\xb3\x9d\x2d\xb7\x45\x67\xa1\x89\x50\x86\xfa\x39\xdf\xfb\x39\x42\x8e\x60\x04\x28\xb9\x71\x80\xf3\x1b\x5b\x06\x2f\xe2\xd0\x16\xc7\x67\x70\x66\xaf\x8f\x2f\x6d\x68\xe2\xb7\xc0\xf3\x99\xde\xc9\x21\x1f\xe5\x2c\xb6\xf4\x3f\x3a\x0b\x48\x48\xb1\xaa\xa2\xc6\xf8\x0a\x11\xd5\x19\x66\x1e\x2e\x7b\x95\x69\xd4\x3f\x30\xac\x27\x2b\x8c\xf6\x70\x54\x21\xbc\x6f\x4c\xa3\x9e\x55\xfc\x6d\x63\x5f\xd4\x56\x7d\xf4\xd6\x76\x9f\x2a\xb9\x0d\x33\x21\xb7\xb6\x02\x23\x14\x0c\x56\x07\x80\xc6\x1e\x2a\xfc\x0c\xbf\x7e\x0a\x84\xfc\x27\x7a\xa7\x4f\x9c\xb9\xea\xa7\x3d\x24\xec\xb5\x09\x7c\x54\x48\xd8\x41\xc2\xce\x8e\xf0\xec\xf2\x4f\x2d\x7c\xb6\xf2\x08\x5f\x07\xf8\x3a\x28\x75\x8b\x85\x81\x41\xf8\x49\xec\xad\xf1\x3b\x48\x39\xc2\xf7\x51\x49\x7a\xb4\x19\xdf\x03\xbc\x08\x47\x04\x7f\x9c\xb9\x0a\xab\xa3\x74\xfe\x38\x73\x55\xa8\x95\x52\xf1\xe7\x99\xab\xe8\x12\xee\xac\x85\x8b\xb7\x90\x12\xaa\xa7\x24\xfc\x79\x06\x7c\x9d\xdf\x31\x42\xfc\x7d\xe6\xaa\xd0\x0e\x4a\xc4\x9f\x67\xae\x1a\xe4\xa1\x4e\xed\xa2\x5f\x90\x9a\x5a\x45\xbf\x20\x95\xdb\x04\xff\xab\xea\x63\x3b\xd8\xfe\x77\x6b\xd4\xa7\x8a\xc5\xd4\xbd\x72\xe4\xc2\xfa\x6c\xb0\x3d\x7b\xae\xab\x01\xed\x00\x3b\xdd\xdc\xe2\x83\x88\x70\xaf\x5b\x51\x14\xe4\x5a\x9b\x7e\x8c\x76\x12\xe4\x2e\xf0\xc0\xb3\xa0\x1f\x5f\x09\xc4\x18\x57\xc7\x5e\xad\x2a\x60\xf1\xbd\xb5\xf5\x1a\xc4\x81\xe7\xf1\x12\xf9\x87\xff\xfa\x2f\x80\xd7\xbf\xab\xbf\xff\x5d\xbc\xfe\xe5\x47\xa1\x3e\x37\x4a\xb5\x4e\xec\xc9\x39\x8d\xc1\xf6\xf2\xf3\xf3\x02\x72\x55\x51\xc0\x28\xba\xa3\xc1\x80\x51\x78\x4d\xf3\xff\x05\x00\x00\xff\xff\x13\xc6\x81\xfc\x4c\x0e\x01\x00" func confLocaleLocale_enUsIniBytes() ([]byte, error) { return bindataRead( @@ -4584,8 +4584,8 @@ func confLocaleLocale_enUsIni() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "conf/locale/locale_en-US.ini", size: 69108, mode: os.FileMode(0644), modTime: time.Unix(1583003971, 0)} - a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x9e, 0x87, 0x60, 0x3c, 0x8c, 0xf3, 0x5b, 0xe, 0xc8, 0x1a, 0x59, 0x31, 0xe4, 0xd4, 0xa0, 0x19, 0xec, 0xdf, 0x7d, 0x8f, 0x72, 0xb2, 0xc6, 0xa8, 0xc8, 0xf6, 0x33, 0xde, 0xd8, 0xf2, 0xee, 0x78}} + info := bindataFileInfo{name: "conf/locale/locale_en-US.ini", size: 69196, mode: os.FileMode(0644), modTime: time.Unix(1584278286, 0)} + a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x5c, 0x52, 0xde, 0xbf, 0x46, 0x5, 0x6, 0x86, 0xd4, 0xdf, 0xd6, 0xbe, 0xff, 0x55, 0xb6, 0x76, 0x8d, 0x82, 0x54, 0x8b, 0x77, 0x4f, 0xbf, 0x28, 0x1e, 0x12, 0xf3, 0x5c, 0xca, 0xfc, 0x91, 0xc6}} return a, nil } @@ -4604,7 +4604,7 @@ func confLocaleLocale_esEsIni() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "conf/locale/locale_es-ES.ini", size: 74188, mode: os.FileMode(0644), modTime: time.Unix(1583417659, 0)} + info := bindataFileInfo{name: "conf/locale/locale_es-ES.ini", size: 74188, mode: os.FileMode(0644), modTime: time.Unix(1583774435, 0)} a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xae, 0xb5, 0x87, 0x10, 0x69, 0x7a, 0x6e, 0xb4, 0x99, 0xf2, 0x6, 0xf1, 0x93, 0xc4, 0xc9, 0x6b, 0x10, 0x46, 0xed, 0xb9, 0x33, 0x76, 0x86, 0x71, 0xbf, 0xf7, 0xe3, 0xf3, 0xad, 0xa1, 0x96, 0x78}} return a, nil } @@ -4624,7 +4624,7 @@ func confLocaleLocale_faIrIni() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "conf/locale/locale_fa-IR.ini", size: 92107, mode: os.FileMode(0644), modTime: time.Unix(1583417659, 0)} + info := bindataFileInfo{name: "conf/locale/locale_fa-IR.ini", size: 92107, mode: os.FileMode(0644), modTime: time.Unix(1583774435, 0)} a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xe5, 0xee, 0x6d, 0xb, 0x6, 0xac, 0x63, 0xf0, 0xc5, 0x33, 0xbe, 0xde, 0xdd, 0xa4, 0xfb, 0xd5, 0x96, 0xbf, 0xf9, 0x45, 0x9b, 0x67, 0x4c, 0xe2, 0x7d, 0x9c, 0x67, 0xbc, 0x70, 0x0, 0xf9, 0x68}} return a, nil } @@ -4644,7 +4644,7 @@ func confLocaleLocale_fiFiIni() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "conf/locale/locale_fi-FI.ini", size: 70349, mode: os.FileMode(0644), modTime: time.Unix(1583417659, 0)} + info := bindataFileInfo{name: "conf/locale/locale_fi-FI.ini", size: 70349, mode: os.FileMode(0644), modTime: time.Unix(1583774435, 0)} a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xc, 0x4c, 0x67, 0x1d, 0xa8, 0x74, 0xd2, 0xa3, 0x88, 0x20, 0x6, 0x8d, 0x7, 0x58, 0x11, 0x13, 0xd3, 0xb1, 0xd6, 0x67, 0xda, 0x5, 0x5, 0x73, 0x58, 0x9d, 0x2d, 0x27, 0x49, 0x95, 0xa2, 0x24}} return a, nil } @@ -4664,7 +4664,7 @@ func confLocaleLocale_frFrIni() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "conf/locale/locale_fr-FR.ini", size: 74612, mode: os.FileMode(0644), modTime: time.Unix(1583417659, 0)} + info := bindataFileInfo{name: "conf/locale/locale_fr-FR.ini", size: 74612, mode: os.FileMode(0644), modTime: time.Unix(1583774435, 0)} a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xeb, 0xa5, 0xa2, 0xf5, 0x27, 0x67, 0xc2, 0x30, 0x28, 0x6e, 0x92, 0x1b, 0xc4, 0x3e, 0x6d, 0xfc, 0xa4, 0x44, 0xe7, 0xba, 0xc5, 0xa1, 0x7c, 0xfd, 0x8e, 0x9b, 0xdf, 0xc0, 0xa, 0x31, 0xb6, 0x8f}} return a, nil } @@ -4684,7 +4684,7 @@ func confLocaleLocale_glEsIni() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "conf/locale/locale_gl-ES.ini", size: 72149, mode: os.FileMode(0644), modTime: time.Unix(1583417659, 0)} + info := bindataFileInfo{name: "conf/locale/locale_gl-ES.ini", size: 72149, mode: os.FileMode(0644), modTime: time.Unix(1583774435, 0)} a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xab, 0xe2, 0xd3, 0x83, 0x1e, 0x78, 0xf8, 0x7d, 0x14, 0xe2, 0x0, 0x8c, 0xcd, 0x9f, 0x51, 0xcd, 0xbb, 0xbf, 0x38, 0x49, 0x81, 0xa9, 0x7e, 0x48, 0xd1, 0xef, 0x16, 0xb7, 0xb5, 0xd1, 0x2d, 0x95}} return a, nil } @@ -4704,7 +4704,7 @@ func confLocaleLocale_huHuIni() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "conf/locale/locale_hu-HU.ini", size: 73190, mode: os.FileMode(0644), modTime: time.Unix(1583417659, 0)} + info := bindataFileInfo{name: "conf/locale/locale_hu-HU.ini", size: 73190, mode: os.FileMode(0644), modTime: time.Unix(1583774435, 0)} a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x1e, 0x4a, 0x27, 0xce, 0xe4, 0xf0, 0x77, 0x1a, 0x12, 0xbf, 0x54, 0x2f, 0xbb, 0x9b, 0x36, 0x88, 0xf0, 0x19, 0x2f, 0x61, 0x71, 0x92, 0x76, 0x70, 0x34, 0x17, 0x94, 0xa, 0xd0, 0x5d, 0xf, 0xcb}} return a, nil } @@ -4724,7 +4724,7 @@ func confLocaleLocale_idIdIni() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "conf/locale/locale_id-ID.ini", size: 69120, mode: os.FileMode(0644), modTime: time.Unix(1583417659, 0)} + info := bindataFileInfo{name: "conf/locale/locale_id-ID.ini", size: 69120, mode: os.FileMode(0644), modTime: time.Unix(1583774435, 0)} a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x6, 0x61, 0x34, 0x9, 0xda, 0x7c, 0x95, 0xd, 0xcd, 0x70, 0xae, 0x70, 0xd, 0xdf, 0x29, 0x32, 0xa8, 0x1d, 0xdf, 0xa6, 0x34, 0xc9, 0xf1, 0xb4, 0x7c, 0xbc, 0xe0, 0xb3, 0x6f, 0xdd, 0xe4, 0x44}} return a, nil } @@ -4744,7 +4744,7 @@ func confLocaleLocale_itItIni() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "conf/locale/locale_it-IT.ini", size: 71188, mode: os.FileMode(0644), modTime: time.Unix(1583417659, 0)} + info := bindataFileInfo{name: "conf/locale/locale_it-IT.ini", size: 71188, mode: os.FileMode(0644), modTime: time.Unix(1583774435, 0)} a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xf7, 0x84, 0xdc, 0x57, 0x80, 0x33, 0x74, 0x43, 0x95, 0x6a, 0x52, 0xc3, 0x29, 0xc7, 0xf8, 0xb1, 0x44, 0x11, 0xaf, 0x74, 0xe, 0x2b, 0x37, 0x2d, 0xdb, 0xd4, 0xd0, 0x40, 0xb2, 0xc9, 0x87, 0x22}} return a, nil } @@ -4764,7 +4764,7 @@ func confLocaleLocale_jaJpIni() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "conf/locale/locale_ja-JP.ini", size: 83244, mode: os.FileMode(0644), modTime: time.Unix(1583417659, 0)} + info := bindataFileInfo{name: "conf/locale/locale_ja-JP.ini", size: 83244, mode: os.FileMode(0644), modTime: time.Unix(1583774435, 0)} a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x4e, 0x1a, 0xe4, 0xfa, 0x1d, 0xcf, 0x13, 0x3c, 0x10, 0xbc, 0x49, 0xbb, 0xd8, 0xcc, 0x8f, 0xb9, 0x24, 0xd1, 0x7f, 0xc7, 0x8d, 0x50, 0x92, 0x41, 0x14, 0x5d, 0xd3, 0xb3, 0xfc, 0xb4, 0x1f, 0x44}} return a, nil } @@ -4784,7 +4784,7 @@ func confLocaleLocale_koKrIni() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "conf/locale/locale_ko-KR.ini", size: 74362, mode: os.FileMode(0644), modTime: time.Unix(1583417659, 0)} + info := bindataFileInfo{name: "conf/locale/locale_ko-KR.ini", size: 74362, mode: os.FileMode(0644), modTime: time.Unix(1583774435, 0)} a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x5d, 0x1d, 0x12, 0x36, 0x64, 0xdf, 0x26, 0xf, 0x40, 0xd5, 0xbc, 0x2e, 0x4f, 0x9e, 0x5, 0x16, 0x16, 0x98, 0xd7, 0x8f, 0x59, 0xa1, 0x9c, 0xb2, 0x2a, 0x90, 0x6c, 0x54, 0xa1, 0x58, 0x78, 0x87}} return a, nil } @@ -4804,7 +4804,7 @@ func confLocaleLocale_lvLvIni() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "conf/locale/locale_lv-LV.ini", size: 73387, mode: os.FileMode(0644), modTime: time.Unix(1583417659, 0)} + info := bindataFileInfo{name: "conf/locale/locale_lv-LV.ini", size: 73387, mode: os.FileMode(0644), modTime: time.Unix(1583774435, 0)} a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x96, 0xd2, 0x9f, 0x1, 0xcd, 0x15, 0xdd, 0x29, 0x7, 0xe6, 0x7d, 0x2d, 0xa, 0x2b, 0x2a, 0x14, 0x70, 0x3d, 0xf4, 0xcb, 0xd2, 0x9d, 0xb7, 0xcd, 0x40, 0x88, 0x4, 0x8d, 0xdb, 0x92, 0xca, 0xcf}} return a, nil } @@ -4824,7 +4824,7 @@ func confLocaleLocale_nlNlIni() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "conf/locale/locale_nl-NL.ini", size: 69647, mode: os.FileMode(0644), modTime: time.Unix(1583417659, 0)} + info := bindataFileInfo{name: "conf/locale/locale_nl-NL.ini", size: 69647, mode: os.FileMode(0644), modTime: time.Unix(1583774435, 0)} a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xc2, 0xd7, 0x94, 0x4e, 0xfb, 0x59, 0xa1, 0x4c, 0x63, 0x5b, 0x8e, 0x51, 0xb0, 0x4a, 0xcc, 0x67, 0x51, 0x22, 0x8a, 0x6b, 0x2b, 0x66, 0x9a, 0xdc, 0xf5, 0x55, 0xe1, 0x99, 0x31, 0xc1, 0x1e, 0xd8}} return a, nil } @@ -4844,7 +4844,7 @@ func confLocaleLocale_plPlIni() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "conf/locale/locale_pl-PL.ini", size: 71796, mode: os.FileMode(0644), modTime: time.Unix(1583417659, 0)} + info := bindataFileInfo{name: "conf/locale/locale_pl-PL.ini", size: 71796, mode: os.FileMode(0644), modTime: time.Unix(1583774435, 0)} a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xc5, 0xe2, 0xed, 0x2f, 0x80, 0xc1, 0xc2, 0x32, 0x3f, 0x8a, 0x7b, 0x33, 0x87, 0x57, 0xaf, 0x68, 0x92, 0x32, 0xc5, 0xbf, 0x29, 0x12, 0x5a, 0x4d, 0xc6, 0x5b, 0x6a, 0x89, 0x18, 0x21, 0x94, 0x98}} return a, nil } @@ -4864,7 +4864,7 @@ func confLocaleLocale_ptBrIni() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "conf/locale/locale_pt-BR.ini", size: 71962, mode: os.FileMode(0644), modTime: time.Unix(1583417659, 0)} + info := bindataFileInfo{name: "conf/locale/locale_pt-BR.ini", size: 71962, mode: os.FileMode(0644), modTime: time.Unix(1583774435, 0)} a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x99, 0x5, 0xc2, 0xa9, 0x9d, 0xf6, 0xf8, 0xd2, 0x67, 0xb9, 0x6f, 0x53, 0x1c, 0x86, 0xaa, 0xac, 0x8e, 0xb8, 0x1a, 0x42, 0x13, 0x3, 0x82, 0x20, 0x41, 0x87, 0xf, 0xb5, 0x5c, 0xbd, 0xf4, 0x42}} return a, nil } @@ -4884,7 +4884,7 @@ func confLocaleLocale_ptPtIni() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "conf/locale/locale_pt-PT.ini", size: 72787, mode: os.FileMode(0644), modTime: time.Unix(1583417659, 0)} + info := bindataFileInfo{name: "conf/locale/locale_pt-PT.ini", size: 72787, mode: os.FileMode(0644), modTime: time.Unix(1583774435, 0)} a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x3a, 0x15, 0x1, 0xb0, 0x47, 0xc5, 0xcf, 0x15, 0xc2, 0x18, 0xfb, 0xa8, 0xb4, 0x4, 0xa4, 0xa, 0xda, 0xd1, 0xb0, 0x31, 0x35, 0x20, 0x5f, 0x9, 0x93, 0xbf, 0x4d, 0x23, 0x4b, 0xcc, 0x98, 0x35}} return a, nil } @@ -4904,7 +4904,7 @@ func confLocaleLocale_ruRuIni() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "conf/locale/locale_ru-RU.ini", size: 102179, mode: os.FileMode(0644), modTime: time.Unix(1583417659, 0)} + info := bindataFileInfo{name: "conf/locale/locale_ru-RU.ini", size: 102179, mode: os.FileMode(0644), modTime: time.Unix(1583774435, 0)} a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x2e, 0x6, 0x64, 0xb8, 0x9, 0x90, 0x8a, 0x31, 0x4c, 0xb7, 0x2a, 0xc9, 0x84, 0xd6, 0x2b, 0x52, 0xc4, 0x1b, 0x39, 0x2, 0xf8, 0xbd, 0x48, 0xd6, 0x9d, 0xdf, 0x1c, 0xa3, 0x28, 0x39, 0xdd, 0x67}} return a, nil } @@ -4924,7 +4924,7 @@ func confLocaleLocale_skSkIni() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "conf/locale/locale_sk-SK.ini", size: 72953, mode: os.FileMode(0644), modTime: time.Unix(1583417659, 0)} + info := bindataFileInfo{name: "conf/locale/locale_sk-SK.ini", size: 72953, mode: os.FileMode(0644), modTime: time.Unix(1583774435, 0)} a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x6b, 0x57, 0x7b, 0x43, 0xce, 0xce, 0x99, 0x75, 0x34, 0x6a, 0xbc, 0x61, 0xd1, 0xa0, 0xc3, 0xb3, 0xf8, 0xe1, 0xfd, 0x7b, 0x43, 0xa5, 0xfe, 0xbb, 0x19, 0xf5, 0xd2, 0x1, 0xa, 0xb6, 0xe7, 0x8f}} return a, nil } @@ -4944,7 +4944,7 @@ func confLocaleLocale_srSpIni() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "conf/locale/locale_sr-SP.ini", size: 94358, mode: os.FileMode(0644), modTime: time.Unix(1583417659, 0)} + info := bindataFileInfo{name: "conf/locale/locale_sr-SP.ini", size: 94358, mode: os.FileMode(0644), modTime: time.Unix(1583774435, 0)} a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x2, 0xd9, 0x39, 0x80, 0x9c, 0x3c, 0xe8, 0x5e, 0xd, 0xc1, 0x4c, 0xaf, 0xa5, 0x1c, 0x35, 0xd0, 0x31, 0x65, 0x90, 0x6a, 0x19, 0x61, 0x68, 0x4b, 0x0, 0xd4, 0xef, 0xc6, 0x9c, 0x36, 0xa4, 0xda}} return a, nil } @@ -4964,7 +4964,7 @@ func confLocaleLocale_svSeIni() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "conf/locale/locale_sv-SE.ini", size: 69522, mode: os.FileMode(0644), modTime: time.Unix(1583417659, 0)} + info := bindataFileInfo{name: "conf/locale/locale_sv-SE.ini", size: 69522, mode: os.FileMode(0644), modTime: time.Unix(1583774435, 0)} a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xa3, 0x14, 0x98, 0x48, 0xe1, 0xd5, 0x90, 0xd9, 0x4f, 0xf, 0x95, 0xe2, 0x61, 0xbf, 0x40, 0x56, 0x77, 0x96, 0xd6, 0x4e, 0x6a, 0xc1, 0x53, 0xbb, 0x8c, 0xf7, 0x43, 0xaa, 0x21, 0x53, 0xc4, 0xd7}} return a, nil } @@ -4984,7 +4984,7 @@ func confLocaleLocale_trTrIni() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "conf/locale/locale_tr-TR.ini", size: 72228, mode: os.FileMode(0644), modTime: time.Unix(1583417659, 0)} + info := bindataFileInfo{name: "conf/locale/locale_tr-TR.ini", size: 72228, mode: os.FileMode(0644), modTime: time.Unix(1583774435, 0)} a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xdb, 0x34, 0x3a, 0x24, 0x1f, 0xfb, 0xe1, 0xfe, 0xb4, 0x14, 0x1d, 0x7e, 0xd3, 0xb2, 0x4d, 0xd5, 0x3, 0xe7, 0xf0, 0xc8, 0xaa, 0xab, 0x66, 0x69, 0xb8, 0xca, 0xc1, 0x68, 0x88, 0xa6, 0x5a, 0x3}} return a, nil } @@ -5004,7 +5004,7 @@ func confLocaleLocale_ukUaIni() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "conf/locale/locale_uk-UA.ini", size: 99984, mode: os.FileMode(0644), modTime: time.Unix(1583417659, 0)} + info := bindataFileInfo{name: "conf/locale/locale_uk-UA.ini", size: 99984, mode: os.FileMode(0644), modTime: time.Unix(1583774435, 0)} a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x43, 0x39, 0xbf, 0x26, 0x8e, 0xad, 0x3f, 0x96, 0x45, 0x18, 0x0, 0xdb, 0x2e, 0x6c, 0x90, 0xb2, 0xdc, 0xe3, 0x1a, 0xe0, 0xfc, 0x91, 0xd6, 0x3f, 0xf0, 0x87, 0x69, 0xf1, 0x31, 0xa1, 0x25, 0x70}} return a, nil } @@ -5024,7 +5024,7 @@ func confLocaleLocale_viVnIni() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "conf/locale/locale_vi-VN.ini", size: 77434, mode: os.FileMode(0644), modTime: time.Unix(1583417659, 0)} + info := bindataFileInfo{name: "conf/locale/locale_vi-VN.ini", size: 77434, mode: os.FileMode(0644), modTime: time.Unix(1583774435, 0)} a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x8f, 0x5e, 0x6f, 0xbd, 0xce, 0x10, 0x93, 0x4f, 0x28, 0xc, 0x69, 0x9f, 0xbf, 0x64, 0xe3, 0x4f, 0xf3, 0xf3, 0x9b, 0xb5, 0x27, 0x25, 0xd4, 0x94, 0x55, 0xee, 0xa5, 0x97, 0x46, 0xca, 0x17, 0xf9}} return a, nil } @@ -5044,7 +5044,7 @@ func confLocaleLocale_zhCnIni() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "conf/locale/locale_zh-CN.ini", size: 65631, mode: os.FileMode(0644), modTime: time.Unix(1583417659, 0)} + info := bindataFileInfo{name: "conf/locale/locale_zh-CN.ini", size: 65631, mode: os.FileMode(0644), modTime: time.Unix(1583774435, 0)} a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xc1, 0x20, 0x90, 0xbb, 0xea, 0xa9, 0xa6, 0x64, 0xff, 0x7e, 0xa, 0x74, 0x0, 0x4, 0x94, 0x15, 0x53, 0x49, 0x46, 0x9e, 0xd1, 0xe5, 0xd, 0xb6, 0x93, 0x62, 0x1a, 0x6c, 0xd3, 0x31, 0xb7, 0x21}} return a, nil } @@ -5064,7 +5064,7 @@ func confLocaleLocale_zhHkIni() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "conf/locale/locale_zh-HK.ini", size: 66058, mode: os.FileMode(0644), modTime: time.Unix(1583417659, 0)} + info := bindataFileInfo{name: "conf/locale/locale_zh-HK.ini", size: 66058, mode: os.FileMode(0644), modTime: time.Unix(1583774435, 0)} a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x1d, 0xc3, 0xcc, 0xec, 0x99, 0x39, 0x91, 0x93, 0x9c, 0x56, 0x5e, 0x21, 0xa6, 0xf9, 0x9c, 0x45, 0xee, 0x57, 0xe4, 0x85, 0x56, 0xb1, 0xb, 0xb4, 0x6d, 0x63, 0xce, 0x1f, 0xed, 0x84, 0x33, 0x6b}} return a, nil } @@ -5084,7 +5084,7 @@ func confLocaleLocale_zhTwIni() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "conf/locale/locale_zh-TW.ini", size: 65354, mode: os.FileMode(0644), modTime: time.Unix(1583417659, 0)} + info := bindataFileInfo{name: "conf/locale/locale_zh-TW.ini", size: 65354, mode: os.FileMode(0644), modTime: time.Unix(1583774435, 0)} a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x78, 0x18, 0x4d, 0xc2, 0xb6, 0x5a, 0x16, 0x50, 0xe0, 0x1e, 0x6d, 0x10, 0x15, 0x7c, 0x48, 0x9f, 0x5f, 0x7e, 0x35, 0xc7, 0xe1, 0xc0, 0xf1, 0xdf, 0x46, 0xf7, 0xa5, 0x20, 0x5b, 0x23, 0xb9, 0x53}} return a, nil } diff --git a/internal/auth/auth.go b/internal/auth/auth.go index 4c34062f6..05751c050 100644 --- a/internal/auth/auth.go +++ b/internal/auth/auth.go @@ -15,7 +15,6 @@ import ( "gogs.io/gogs/internal/conf" "gogs.io/gogs/internal/db" - "gogs.io/gogs/internal/db/errors" "gogs.io/gogs/internal/tool" ) @@ -70,8 +69,8 @@ func SignedInID(c *macaron.Context, sess session.Store) (_ int64, isTokenAuth bo } if id, ok := uid.(int64); ok { if _, err := db.GetUserByID(id); err != nil { - if !errors.IsUserNotExist(err) { - log.Error("GetUserByID: %v", err) + if !db.IsErrUserNotExist(err) { + log.Error("Failed to get user by ID: %v", err) } return 0, false } @@ -95,8 +94,8 @@ func SignedInUser(ctx *macaron.Context, sess session.Store) (_ *db.User, isBasic if len(webAuthUser) > 0 { u, err := db.GetUserByName(webAuthUser) if err != nil { - if !errors.IsUserNotExist(err) { - log.Error("GetUserByName: %v", err) + if !db.IsErrUserNotExist(err) { + log.Error("Failed to get user by name: %v", err) return nil, false, false } @@ -110,7 +109,7 @@ func SignedInUser(ctx *macaron.Context, sess session.Store) (_ *db.User, isBasic } if err = db.CreateUser(u); err != nil { // FIXME: should I create a system notice? - log.Error("CreateUser: %v", err) + log.Error("Failed to create user: %v", err) return nil, false, false } else { return u, false, false @@ -130,8 +129,8 @@ func SignedInUser(ctx *macaron.Context, sess session.Store) (_ *db.User, isBasic u, err := db.UserLogin(uname, passwd, -1) if err != nil { - if !errors.IsUserNotExist(err) { - log.Error("UserLogin: %v", err) + if !db.IsErrUserNotExist(err) { + log.Error("Failed to authenticate user: %v", err) } return nil, false, false } diff --git a/internal/cmd/hook.go b/internal/cmd/hook.go index de95a57d3..0e9136b0a 100644 --- a/internal/cmd/hook.go +++ b/internal/cmd/hook.go @@ -23,7 +23,6 @@ import ( "gogs.io/gogs/internal/conf" "gogs.io/gogs/internal/db" - "gogs.io/gogs/internal/db/errors" "gogs.io/gogs/internal/email" "gogs.io/gogs/internal/httplib" ) @@ -93,7 +92,7 @@ func runHookPreReceive(c *cli.Context) error { repoID := com.StrTo(os.Getenv(db.ENV_REPO_ID)).MustInt64() protectBranch, err := db.GetProtectBranchOfRepoByName(repoID, branchName) if err != nil { - if errors.IsErrBranchNotExist(err) { + if db.IsErrBranchNotExist(err) { continue } fail("Internal error", "GetProtectBranchOfRepoByName [repo_id: %d, branch: %s]: %v", repoID, branchName, err) diff --git a/internal/cmd/serv.go b/internal/cmd/serv.go index 64e0f1d0f..8c6349e30 100644 --- a/internal/cmd/serv.go +++ b/internal/cmd/serv.go @@ -18,7 +18,6 @@ import ( "gogs.io/gogs/internal/conf" "gogs.io/gogs/internal/db" - "gogs.io/gogs/internal/db/errors" ) const ( @@ -164,7 +163,7 @@ func runServ(c *cli.Context) error { owner, err := db.GetUserByName(ownerName) if err != nil { - if errors.IsUserNotExist(err) { + if db.IsErrUserNotExist(err) { fail("Repository owner does not exist", "Unregistered owner: %s", ownerName) } fail("Internal error", "Failed to get repository owner '%s': %v", ownerName, err) @@ -172,7 +171,7 @@ func runServ(c *cli.Context) error { repo, err := db.GetRepositoryByName(owner.ID, repoName) if err != nil { - if errors.IsRepoNotExist(err) { + if db.IsErrRepoNotExist(err) { fail(_ACCESS_DENIED_MESSAGE, "Repository does not exist: %s/%s", owner.Name, repoName) } fail("Internal error", "Failed to get repository: %v", err) diff --git a/internal/cmd/web.go b/internal/cmd/web.go index 078678b42..1d78e4a6c 100644 --- a/internal/cmd/web.go +++ b/internal/cmd/web.go @@ -318,7 +318,7 @@ func runWeb(c *cli.Context) error { m.Get("/attachments/:uuid", func(c *context.Context) { attach, err := db.GetAttachmentByUUID(c.Params(":uuid")) if err != nil { - c.NotFoundOrServerError("GetAttachmentByUUID", db.IsErrAttachmentNotExist, err) + c.NotFoundOrError(err, "get attachment by UUID") return } else if !com.IsFile(attach.LocalPath()) { c.NotFound() @@ -327,7 +327,7 @@ func runWeb(c *cli.Context) error { fr, err := os.Open(attach.LocalPath()) if err != nil { - c.ServerError("open attachment file", err) + c.Error(err, "open attachment file") return } defer fr.Close() @@ -336,7 +336,7 @@ func runWeb(c *cli.Context) error { c.Header().Set("Content-Disposition", fmt.Sprintf(`inline; filename="%s"`, attach.Name)) if _, err = io.Copy(c.Resp, fr); err != nil { - c.ServerError("copy from file to response", err) + c.Error(err, "copy from file to response") return } }) diff --git a/internal/context/api.go b/internal/context/api.go index dfea976c0..938e207f3 100644 --- a/internal/context/api.go +++ b/internal/context/api.go @@ -14,6 +14,7 @@ import ( log "unknwon.dev/clog/v2" "gogs.io/gogs/internal/conf" + "gogs.io/gogs/internal/errutil" ) type APIContext struct { @@ -28,26 +29,6 @@ type APIContext struct { // FIXME: move this constant to github.com/gogs/go-gogs-client const DocURL = "https://github.com/gogs/docs-api" -// Error responses error message to client with given message. -// If status is 500, also it prints error to log. -func (c *APIContext) Error(status int, title string, obj interface{}) { - var message string - if err, ok := obj.(error); ok { - message = err.Error() - } else { - message = obj.(string) - } - - if status == http.StatusInternalServerError { - log.ErrorDepth(5, "%s: %s", title, message) - } - - c.JSON(status, map[string]string{ - "message": message, - "url": DocURL, - }) -} - // NoContent renders the 204 response. func (c *APIContext) NoContent() { c.Status(http.StatusNoContent) @@ -58,25 +39,34 @@ func (c *APIContext) NotFound() { c.Status(http.StatusNotFound) } -// ServerError renders the 500 response. -func (c *APIContext) ServerError(title string, err error) { - c.Error(http.StatusInternalServerError, title, err) +// ErrorStatus renders error with given status code. +func (c *APIContext) ErrorStatus(status int, err error) { + c.JSON(status, map[string]string{ + "message": err.Error(), + "url": DocURL, + }) +} + +// Error renders the 500 response. +func (c *APIContext) Error(err error, msg string) { + log.ErrorDepth(5, "%s: %v", msg, err) + c.ErrorStatus(http.StatusInternalServerError, err) } // Errorf renders the 500 response with formatted message. func (c *APIContext) Errorf(err error, format string, args ...interface{}) { - c.Error(http.StatusInternalServerError, fmt.Sprintf(format, args...), err) + c.Error(err, fmt.Sprintf(format, args...)) } -// NotFoundOrServerError use error check function to determine if the error +// NotFoundOrError use error check function to determine if the error // is about not found. It responses with 404 status code for not found error, // or error context description for logging purpose of 500 server error. -func (c *APIContext) NotFoundOrServerError(title string, errck func(error) bool, err error) { - if errck(err) { +func (c *APIContext) NotFoundOrError(err error, msg string) { + if errutil.IsNotFound(err) { c.NotFound() return } - c.ServerError(title, err) + c.Error(err, msg) } // SetLinkHeader sets pagination link header by given total number and page size. diff --git a/internal/context/auth.go b/internal/context/auth.go index f99a0bb2d..2a7a1aef3 100644 --- a/internal/context/auth.go +++ b/internal/context/auth.go @@ -28,26 +28,26 @@ func Toggle(options *ToggleOptions) macaron.Handler { return func(c *Context) { // Cannot view any page before installation. if !conf.Security.InstallLock { - c.Redirect(conf.Server.Subpath + "/install") + c.RedirectSubpath("/install") return } // Check prohibit login users. if c.IsLogged && c.User.ProhibitLogin { c.Data["Title"] = c.Tr("auth.prohibit_login") - c.HTML(200, "user/auth/prohibit_login") + c.Success( "user/auth/prohibit_login") return } // Check non-logged users landing page. if !c.IsLogged && c.Req.RequestURI == "/" && conf.Server.LandingURL != "/" { - c.SubURLRedirect(conf.Server.LandingURL) + c.RedirectSubpath(conf.Server.LandingURL) return } // Redirect to dashboard if user tries to visit any non-login page. if options.SignOutRequired && c.IsLogged && c.Req.RequestURI != "/" { - c.Redirect(conf.Server.Subpath + "/") + c.RedirectSubpath("/") return } @@ -62,18 +62,18 @@ func Toggle(options *ToggleOptions) macaron.Handler { if !c.IsLogged { // Restrict API calls with error message. if auth.IsAPIPath(c.Req.URL.Path) { - c.JSON(403, map[string]string{ - "message": "Only signed in user is allowed to call APIs.", + c.JSON(http.StatusForbidden, map[string]string{ + "message": "Only authenticated user is allowed to call APIs.", }) return } c.SetCookie("redirect_to", url.QueryEscape(conf.Server.Subpath+c.Req.RequestURI), 0, conf.Server.Subpath) - c.Redirect(conf.Server.Subpath + "/user/login") + c.RedirectSubpath("/user/login") return } else if !c.User.IsActive && conf.Auth.RequireEmailConfirmation { - c.Data["Title"] = c.Tr("auth.active_your_account") - c.HTML(200, "user/auth/activate") + c.Title("auth.active_your_account") + c.Success("user/auth/activate") return } } @@ -82,21 +82,21 @@ func Toggle(options *ToggleOptions) macaron.Handler { if !options.SignOutRequired && !c.IsLogged && !auth.IsAPIPath(c.Req.URL.Path) && len(c.GetCookie(conf.Security.CookieUsername)) > 0 { c.SetCookie("redirect_to", url.QueryEscape(conf.Server.Subpath+c.Req.RequestURI), 0, conf.Server.Subpath) - c.Redirect(conf.Server.Subpath + "/user/login") + c.RedirectSubpath("/user/login") return } if options.AdminRequired { if !c.User.IsAdmin { - c.Error(403) + c.Status(http.StatusForbidden) return } - c.Data["PageIsAdmin"] = true + c.PageIs("Admin") } } } -// RequireBasicAuth verifies HTTP Basic Authentication header with given credentials +// RequireBasicAuth verifies HTTP Basic Authentication header with given credentials. func (c *Context) RequireBasicAuth(username, password string) { fields := strings.Fields(c.Req.Header.Get("Authorization")) if len(fields) != 2 || fields[0] != "Basic" { diff --git a/internal/context/context.go b/internal/context/context.go index b4809ec79..142fd2411 100644 --- a/internal/context/context.go +++ b/internal/context/context.go @@ -23,7 +23,7 @@ import ( "gogs.io/gogs/internal/auth" "gogs.io/gogs/internal/conf" "gogs.io/gogs/internal/db" - "gogs.io/gogs/internal/db/errors" + "gogs.io/gogs/internal/errutil" "gogs.io/gogs/internal/form" "gogs.io/gogs/internal/template" ) @@ -149,15 +149,15 @@ func (c *Context) RawRedirect(location string, status ...int) { c.Context.Redirect(location, status...) } -// Redirect responses redirection wtih given location and status. +// Redirect responses redirection with given location and status. // It escapes special characters in the location string. func (c *Context) Redirect(location string, status ...int) { c.Context.Redirect(template.EscapePound(location), status...) } -// SubURLRedirect responses redirection wtih given location and status. +// RedirectSubpath responses redirection with given location and status. // It prepends setting.Server.Subpath to the location string. -func (c *Context) SubURLRedirect(location string, status ...int) { +func (c *Context) RedirectSubpath(location string, status ...int) { c.Redirect(conf.Server.Subpath+location, status...) } @@ -171,44 +171,46 @@ func (c *Context) RenderWithErr(msg, tpl string, f interface{}) { c.HTML(http.StatusOK, tpl) } -// Handle handles and logs error by given status. -func (c *Context) Handle(status int, msg string, err error) { - switch status { - case http.StatusNotFound: - c.Data["Title"] = "Page Not Found" - case http.StatusInternalServerError: - c.Data["Title"] = "Internal Server Error" - log.ErrorDepth(5, "%s: %v", msg, err) - if !conf.IsProdMode() || (c.IsLogged && c.User.IsAdmin) { - c.Data["ErrorMsg"] = err - } - } - c.HTML(status, fmt.Sprintf("status/%d", status)) -} - // NotFound renders the 404 page. func (c *Context) NotFound() { - c.Handle(http.StatusNotFound, "", nil) + c.Title("status.page_not_found") + c.HTML(http.StatusNotFound, fmt.Sprintf("status/%d", http.StatusNotFound)) } -// ServerError renders the 500 page. -func (c *Context) ServerError(msg string, err error) { - c.Handle(http.StatusInternalServerError, msg, err) +// Error renders the 500 page. +func (c *Context) Error(err error, msg string) { + log.ErrorDepth(5, "%s: %v", msg, err) + + c.Title("status.internal_server_error") + + // Only in non-production mode or admin can see the actual error message. + if !conf.IsProdMode() || (c.IsLogged && c.User.IsAdmin) { + c.Data["ErrorMsg"] = err + } + c.HTML(http.StatusInternalServerError, fmt.Sprintf("status/%d", http.StatusInternalServerError)) } -// NotFoundOrServerError use error check function to determine if the error -// is about not found. It responses with 404 status code for not found error, -// or error context description for logging purpose of 500 server error. -func (c *Context) NotFoundOrServerError(msg string, errck func(error) bool, err error) { - if errck(err) { +// Errorf renders the 500 response with formatted message. +func (c *Context) Errorf(err error, format string, args ...interface{}) { + c.Error(err, fmt.Sprintf(format, args...)) +} + +// NotFoundOrError responses with 404 page for not found error and 500 page otherwise. +func (c *Context) NotFoundOrError(err error, msg string) { + if errutil.IsNotFound(err) { c.NotFound() return } - c.ServerError(msg, err) + c.Error(err, msg) } -func (c *Context) HandleText(status int, msg string) { - c.PlainText(status, []byte(msg)) +// NotFoundOrErrorf is same as NotFoundOrError but with formatted message. +func (c *Context) NotFoundOrErrorf(err error, format string, args ...interface{}) { + c.NotFoundOrError(err, fmt.Sprintf(format, args...)) +} + +func (c *Context) PlainText(status int, msg string) { + c.Render.PlainText(status, []byte(msg)) } func (c *Context) ServeContent(name string, r io.ReadSeeker, params ...interface{}) { @@ -259,7 +261,7 @@ func Contexter() macaron.Handler { owner, err := db.GetUserByName(ownerName) if err != nil { - c.NotFoundOrServerError("GetUserByName", errors.IsUserNotExist, err) + c.NotFoundOrError(err, "get user by name") return } @@ -273,7 +275,7 @@ func Contexter() macaron.Handler { if !strings.HasPrefix(conf.Server.ExternalURL, "https://") { insecureFlag = "--insecure " } - c.PlainText(http.StatusOK, []byte(com.Expand(` + c.PlainText(http.StatusOK, com.Expand(` @@ -284,12 +286,12 @@ func Contexter() macaron.Handler { `, map[string]string{ - "GoGetImport": path.Join(conf.Server.URL.Host, conf.Server.Subpath, repo.FullName()), + "GoGetImport": path.Join(conf.Server.URL.Host, conf.Server.Subpath, ownerName, repoName), "CloneLink": db.ComposeHTTPSCloneURL(ownerName, repoName), "GoDocDirectory": prefix + "{/dir}", "GoDocFile": prefix + "{/dir}/{file}#L{line}", "InsecureFlag": insecureFlag, - }))) + })) return } @@ -318,7 +320,7 @@ func Contexter() macaron.Handler { // If request sends files, parse them here otherwise the Query() can't be parsed and the CsrfToken will be invalid. if c.Req.Method == "POST" && strings.Contains(c.Req.Header.Get("Content-Type"), "multipart/form-data") { if err := c.Req.ParseMultipartForm(conf.Attachment.MaxSize << 20); err != nil && !strings.Contains(err.Error(), "EOF") { // 32MB max size - c.ServerError("ParseMultipartForm", err) + c.Error(err, "parse multipart form") return } } diff --git a/internal/context/org.go b/internal/context/org.go index 02e154ca8..6ed35835e 100644 --- a/internal/context/org.go +++ b/internal/context/org.go @@ -11,7 +11,6 @@ import ( "gogs.io/gogs/internal/conf" "gogs.io/gogs/internal/db" - "gogs.io/gogs/internal/db/errors" ) type Organization struct { @@ -50,7 +49,7 @@ func HandleOrgAssignment(c *Context, args ...bool) { var err error c.Org.Organization, err = db.GetUserByName(orgName) if err != nil { - c.NotFoundOrServerError("GetUserByName", errors.IsUserNotExist, err) + c.NotFoundOrError(err, "get organization by name") return } org := c.Org.Organization @@ -85,7 +84,7 @@ func HandleOrgAssignment(c *Context, args ...bool) { } if (requireMember && !c.Org.IsMember) || (requireOwner && !c.Org.IsOwner) { - c.Handle(404, "OrgAssignment", err) + c.NotFound() return } c.Data["IsOrganizationOwner"] = c.Org.IsOwner @@ -98,13 +97,13 @@ func HandleOrgAssignment(c *Context, args ...bool) { if c.Org.IsMember { if c.Org.IsOwner { if err := org.GetTeams(); err != nil { - c.Handle(500, "GetTeams", err) + c.Error(err, "get teams") return } } else { org.Teams, err = org.GetUserTeams(c.User.ID) if err != nil { - c.Handle(500, "GetUserTeams", err) + c.Error(err, "get user teams") return } } @@ -124,20 +123,20 @@ func HandleOrgAssignment(c *Context, args ...bool) { } if !teamExists { - c.Handle(404, "OrgAssignment", err) + c.NotFound() return } c.Data["IsTeamMember"] = c.Org.IsTeamMember if requireTeamMember && !c.Org.IsTeamMember { - c.Handle(404, "OrgAssignment", err) + c.NotFound() return } c.Org.IsTeamAdmin = c.Org.Team.IsOwnerTeam() || c.Org.Team.Authorize >= db.ACCESS_MODE_ADMIN c.Data["IsTeamAdmin"] = c.Org.IsTeamAdmin if requireTeamAdmin && !c.Org.IsTeamAdmin { - c.Handle(404, "OrgAssignment", err) + c.NotFound() return } } diff --git a/internal/context/repo.go b/internal/context/repo.go index 73352e9c5..f2cac2772 100644 --- a/internal/context/repo.go +++ b/internal/context/repo.go @@ -18,7 +18,6 @@ import ( "gogs.io/gogs/internal/conf" "gogs.io/gogs/internal/db" - dberrors "gogs.io/gogs/internal/db/errors" ) type PullRequest struct { @@ -147,7 +146,7 @@ func RepoAssignment(pages ...bool) macaron.Handler { } else { owner, err = db.GetUserByName(ownerName) if err != nil { - c.NotFoundOrServerError("GetUserByName", dberrors.IsUserNotExist, err) + c.NotFoundOrError(err, "get user by name") return } } @@ -156,7 +155,7 @@ func RepoAssignment(pages ...bool) macaron.Handler { repo, err := db.GetRepositoryByName(owner.ID, repoName) if err != nil { - c.NotFoundOrServerError("GetRepositoryByName", dberrors.IsRepoNotExist, err) + c.NotFoundOrError(err, "get repository by name") return } @@ -173,7 +172,7 @@ func RepoAssignment(pages ...bool) macaron.Handler { } else { mode, err := db.UserAccessMode(c.UserID(), repo) if err != nil { - c.ServerError("UserAccessMode", err) + c.Error(err, "get user access mode") return } c.Repo.AccessMode = mode @@ -212,7 +211,7 @@ func RepoAssignment(pages ...bool) macaron.Handler { if repo.IsMirror { c.Repo.Mirror, err = db.GetMirrorByRepoID(repo.ID) if err != nil { - c.ServerError("GetMirror", err) + c.Error(err, "get mirror by repository ID") return } c.Data["MirrorEnablePrune"] = c.Repo.Mirror.EnablePrune @@ -222,14 +221,14 @@ func RepoAssignment(pages ...bool) macaron.Handler { gitRepo, err := git.Open(db.RepoPath(ownerName, repoName)) if err != nil { - c.ServerError("open repository", err) + c.Error(err, "open repository") return } c.Repo.GitRepo = gitRepo tags, err := c.Repo.GitRepo.Tags() if err != nil { - c.ServerError("get tags", err) + c.Error(err, "get tags") return } c.Data["Tags"] = tags @@ -260,7 +259,7 @@ func RepoAssignment(pages ...bool) macaron.Handler { c.Data["TagName"] = c.Repo.TagName branches, err := c.Repo.GitRepo.Branches() if err != nil { - c.ServerError("get branches", err) + c.Error(err, "get branches") return } c.Data["Branches"] = branches @@ -300,7 +299,7 @@ func RepoRef() macaron.Handler { repoPath := db.RepoPath(c.Repo.Owner.Name, c.Repo.Repository.Name) c.Repo.GitRepo, err = git.Open(repoPath) if err != nil { - c.Handle(500, "RepoRef Invalid repo "+repoPath, err) + c.Error(err, "open repository") return } } @@ -311,14 +310,14 @@ func RepoRef() macaron.Handler { if !c.Repo.GitRepo.HasBranch(refName) { branches, err := c.Repo.GitRepo.Branches() if err != nil { - c.ServerError("get branches", err) + c.Error(err, "get branches") return } refName = branches[0] } c.Repo.Commit, err = c.Repo.GitRepo.BranchCommit(refName) if err != nil { - c.ServerError("get branch commit", err) + c.Error(err, "get branch commit") return } c.Repo.CommitID = c.Repo.Commit.ID.String() @@ -349,7 +348,7 @@ func RepoRef() macaron.Handler { c.Repo.Commit, err = c.Repo.GitRepo.BranchCommit(refName) if err != nil { - c.ServerError("get branch commit", err) + c.Error(err, "get branch commit") return } c.Repo.CommitID = c.Repo.Commit.ID.String() @@ -358,7 +357,7 @@ func RepoRef() macaron.Handler { c.Repo.IsViewTag = true c.Repo.Commit, err = c.Repo.GitRepo.TagCommit(refName) if err != nil { - c.ServerError("get tag commit", err) + c.Error(err, "get tag commit") return } c.Repo.CommitID = c.Repo.Commit.ID.String() @@ -372,7 +371,7 @@ func RepoRef() macaron.Handler { return } } else { - c.Handle(404, "RepoRef invalid repo", fmt.Errorf("branch or tag not exist: %s", refName)) + c.NotFound() return } } diff --git a/internal/context/user.go b/internal/context/user.go index d16b93b7a..0d6ad67d3 100644 --- a/internal/context/user.go +++ b/internal/context/user.go @@ -8,7 +8,6 @@ import ( "gopkg.in/macaron.v1" "gogs.io/gogs/internal/db" - "gogs.io/gogs/internal/db/errors" ) // ParamsUser is the wrapper type of the target user defined by URL parameter, namely ':username'. @@ -22,7 +21,7 @@ func InjectParamsUser() macaron.Handler { return func(c *Context) { user, err := db.GetUserByName(c.Params(":username")) if err != nil { - c.NotFoundOrServerError("GetUserByName", errors.IsUserNotExist, err) + c.NotFoundOrError(err, "get user by name") return } c.Map(&ParamsUser{user}) diff --git a/internal/db/access.go b/internal/db/access.go index b5c6cd281..63911f8e3 100644 --- a/internal/db/access.go +++ b/internal/db/access.go @@ -8,8 +8,6 @@ import ( "fmt" log "unknwon.dev/clog/v2" - - "gogs.io/gogs/internal/db/errors" ) type AccessMode int @@ -110,8 +108,8 @@ func (u *User) GetRepositoryAccesses() (map[*Repository]AccessMode, error) { for _, access := range accesses { repo, err := GetRepositoryByID(access.RepoID) if err != nil { - if errors.IsRepoNotExist(err) { - log.Error("GetRepositoryByID: %v", err) + if IsErrRepoNotExist(err) { + log.Error("Failed to get repository by ID: %v", err) continue } return nil, err diff --git a/internal/db/action.go b/internal/db/action.go index 0b8038363..77938f02a 100644 --- a/internal/db/action.go +++ b/internal/db/action.go @@ -20,7 +20,6 @@ import ( api "github.com/gogs/go-gogs-client" "gogs.io/gogs/internal/conf" - "gogs.io/gogs/internal/db/errors" "gogs.io/gogs/internal/lazyregexp" "gogs.io/gogs/internal/tool" ) @@ -256,16 +255,16 @@ func (pc *PushCommits) ToApiPayloadCommits(repoPath, repoURL string) ([]*api.Pay author, err := GetUserByEmail(commit.AuthorEmail) if err == nil { authorUsername = author.Name - } else if !errors.IsUserNotExist(err) { - return nil, fmt.Errorf("GetUserByEmail: %v", err) + } else if !IsErrUserNotExist(err) { + return nil, fmt.Errorf("get user by email: %v", err) } committerUsername := "" committer, err := GetUserByEmail(commit.CommitterEmail) if err == nil { committerUsername = committer.Name - } else if !errors.IsUserNotExist(err) { - return nil, fmt.Errorf("GetUserByEmail: %v", err) + } else if !IsErrUserNotExist(err) { + return nil, fmt.Errorf("get user by email: %v", err) } nameStatus, err := git.RepoShowNameStatus(repoPath, commit.Sha1) @@ -304,8 +303,8 @@ func (pcs *PushCommits) AvatarLink(email string) string { u, err := GetUserByEmail(email) if err != nil { pcs.avatars[email] = tool.AvatarLink(email) - if !errors.IsUserNotExist(err) { - log.Error("GetUserByEmail: %v", err) + if !IsErrUserNotExist(err) { + log.Error("get user by email: %v", err) } } else { pcs.avatars[email] = u.RelAvatarLink() @@ -341,7 +340,7 @@ func UpdateIssuesCommit(doer *User, repo *Repository, commits []*PushCommit) err issue, err := GetIssueByRef(ref) if err != nil { - if errors.IsIssueNotExist(err) { + if IsErrIssueNotExist(err) { continue } return err @@ -383,7 +382,7 @@ func UpdateIssuesCommit(doer *User, repo *Repository, commits []*PushCommit) err issue, err := GetIssueByRef(ref) if err != nil { - if errors.IsIssueNotExist(err) { + if IsErrIssueNotExist(err) { continue } return err @@ -423,7 +422,7 @@ func UpdateIssuesCommit(doer *User, repo *Repository, commits []*PushCommit) err issue, err := GetIssueByRef(ref) if err != nil { - if errors.IsIssueNotExist(err) { + if IsErrIssueNotExist(err) { continue } return err diff --git a/internal/db/attachment.go b/internal/db/attachment.go index 44ac4fe25..75d927465 100644 --- a/internal/db/attachment.go +++ b/internal/db/attachment.go @@ -16,6 +16,7 @@ import ( "xorm.io/xorm" "gogs.io/gogs/internal/conf" + "gogs.io/gogs/internal/errutil" ) // Attachment represent a attachment of issue/comment/release. @@ -83,13 +84,32 @@ func NewAttachment(name string, buf []byte, file multipart.File) (_ *Attachment, return attach, nil } +var _ errutil.NotFound = (*ErrAttachmentNotExist)(nil) + +type ErrAttachmentNotExist struct { + args map[string]interface{} +} + +func IsErrAttachmentNotExist(err error) bool { + _, ok := err.(ErrAttachmentNotExist) + return ok +} + +func (err ErrAttachmentNotExist) Error() string { + return fmt.Sprintf("attachment does not exist: %v", err.args) +} + +func (ErrAttachmentNotExist) NotFound() bool { + return true +} + func getAttachmentByUUID(e Engine, uuid string) (*Attachment, error) { attach := &Attachment{UUID: uuid} - has, err := x.Get(attach) + has, err := e.Get(attach) if err != nil { return nil, err } else if !has { - return nil, ErrAttachmentNotExist{0, uuid} + return nil, ErrAttachmentNotExist{args: map[string]interface{}{"uuid": uuid}} } return attach, nil } diff --git a/internal/db/comment.go b/internal/db/comment.go index d0270302a..03f95eea4 100644 --- a/internal/db/comment.go +++ b/internal/db/comment.go @@ -15,7 +15,7 @@ import ( api "github.com/gogs/go-gogs-client" - "gogs.io/gogs/internal/db/errors" + "gogs.io/gogs/internal/errutil" "gogs.io/gogs/internal/markup" ) @@ -96,7 +96,7 @@ func (c *Comment) loadAttributes(e Engine) (err error) { if c.Poster == nil { c.Poster, err = GetUserByID(c.PosterID) if err != nil { - if errors.IsUserNotExist(err) { + if IsErrUserNotExist(err) { c.PosterID = -1 c.Poster = NewGhostUser() } else { @@ -391,6 +391,25 @@ func CreateRefComment(doer *User, repo *Repository, issue *Issue, content, commi return err } +var _ errutil.NotFound = (*ErrCommentNotExist)(nil) + +type ErrCommentNotExist struct { + args map[string]interface{} +} + +func IsErrCommentNotExist(err error) bool { + _, ok := err.(ErrCommentNotExist) + return ok +} + +func (err ErrCommentNotExist) Error() string { + return fmt.Sprintf("comment does not exist: %v", err.args) +} + +func (ErrCommentNotExist) NotFound() bool { + return true +} + // GetCommentByID returns the comment by given ID. func GetCommentByID(id int64) (*Comment, error) { c := new(Comment) @@ -398,7 +417,7 @@ func GetCommentByID(id int64) (*Comment, error) { if err != nil { return nil, err } else if !has { - return nil, ErrCommentNotExist{id, 0} + return nil, ErrCommentNotExist{args: map[string]interface{}{"commentID": id}} } return c, c.LoadAttributes() } diff --git a/internal/db/error.go b/internal/db/error.go index 033d631b7..dff234d90 100644 --- a/internal/db/error.go +++ b/internal/db/error.go @@ -190,21 +190,6 @@ func (err ErrKeyAccessDenied) Error() string { err.UserID, err.KeyID, err.Note) } -type ErrDeployKeyNotExist struct { - ID int64 - KeyID int64 - RepoID int64 -} - -func IsErrDeployKeyNotExist(err error) bool { - _, ok := err.(ErrDeployKeyNotExist) - return ok -} - -func (err ErrDeployKeyNotExist) Error() string { - return fmt.Sprintf("Deploy key does not exist [id: %d, key_id: %d, repo_id: %d]", err.ID, err.KeyID, err.RepoID) -} - type ErrDeployKeyAlreadyExist struct { KeyID int64 RepoID int64 @@ -348,20 +333,6 @@ func (err ErrReleaseAlreadyExist) Error() string { return fmt.Sprintf("release tag already exist [tag_name: %s]", err.TagName) } -type ErrReleaseNotExist struct { - ID int64 - TagName string -} - -func IsErrReleaseNotExist(err error) bool { - _, ok := err.(ErrReleaseNotExist) - return ok -} - -func (err ErrReleaseNotExist) Error() string { - return fmt.Sprintf("release tag does not exist [id: %d, tag_name: %s]", err.ID, err.TagName) -} - type ErrInvalidTagName struct { TagName string } @@ -388,116 +359,6 @@ func (err ErrRepoFileAlreadyExist) Error() string { return fmt.Sprintf("repository file already exists [file_name: %s]", err.FileName) } -// __________ .__ .__ __________ __ -// \______ \__ __| | | |\______ \ ____ ________ __ ____ _______/ |_ -// | ___/ | \ | | | | _// __ \/ ____/ | \_/ __ \ / ___/\ __\ -// | | | | / |_| |_| | \ ___< <_| | | /\ ___/ \___ \ | | -// |____| |____/|____/____/____|_ /\___ >__ |____/ \___ >____ > |__| -// \/ \/ |__| \/ \/ - -type ErrPullRequestNotExist struct { - ID int64 - IssueID int64 - HeadRepoID int64 - BaseRepoID int64 - HeadBarcnh string - BaseBranch string -} - -func IsErrPullRequestNotExist(err error) bool { - _, ok := err.(ErrPullRequestNotExist) - return ok -} - -func (err ErrPullRequestNotExist) Error() string { - return fmt.Sprintf("pull request does not exist [id: %d, issue_id: %d, head_repo_id: %d, base_repo_id: %d, head_branch: %s, base_branch: %s]", - err.ID, err.IssueID, err.HeadRepoID, err.BaseRepoID, err.HeadBarcnh, err.BaseBranch) -} - -// _________ __ -// \_ ___ \ ____ _____ _____ ____ _____/ |_ -// / \ \/ / _ \ / \ / \_/ __ \ / \ __\ -// \ \___( <_> ) Y Y \ Y Y \ ___/| | \ | -// \______ /\____/|__|_| /__|_| /\___ >___| /__| -// \/ \/ \/ \/ \/ - -type ErrCommentNotExist struct { - ID int64 - IssueID int64 -} - -func IsErrCommentNotExist(err error) bool { - _, ok := err.(ErrCommentNotExist) - return ok -} - -func (err ErrCommentNotExist) Error() string { - return fmt.Sprintf("comment does not exist [id: %d, issue_id: %d]", err.ID, err.IssueID) -} - -// .____ ___. .__ -// | | _____ \_ |__ ____ | | -// | | \__ \ | __ \_/ __ \| | -// | |___ / __ \| \_\ \ ___/| |__ -// |_______ (____ /___ /\___ >____/ -// \/ \/ \/ \/ - -type ErrLabelNotExist struct { - LabelID int64 - RepoID int64 -} - -func IsErrLabelNotExist(err error) bool { - _, ok := err.(ErrLabelNotExist) - return ok -} - -func (err ErrLabelNotExist) Error() string { - return fmt.Sprintf("label does not exist [label_id: %d, repo_id: %d]", err.LabelID, err.RepoID) -} - -// _____ .__.__ __ -// / \ |__| | ____ _______/ |_ ____ ____ ____ -// / \ / \| | | _/ __ \ / ___/\ __\/ _ \ / \_/ __ \ -// / Y \ | |_\ ___/ \___ \ | | ( <_> ) | \ ___/ -// \____|__ /__|____/\___ >____ > |__| \____/|___| /\___ > -// \/ \/ \/ \/ \/ - -type ErrMilestoneNotExist struct { - ID int64 - RepoID int64 -} - -func IsErrMilestoneNotExist(err error) bool { - _, ok := err.(ErrMilestoneNotExist) - return ok -} - -func (err ErrMilestoneNotExist) Error() string { - return fmt.Sprintf("milestone does not exist [id: %d, repo_id: %d]", err.ID, err.RepoID) -} - -// _____ __ __ .__ __ -// / _ \_/ |__/ |______ ____ | |__ _____ ____ _____/ |_ -// / /_\ \ __\ __\__ \ _/ ___\| | \ / \_/ __ \ / \ __\ -// / | \ | | | / __ \\ \___| Y \ Y Y \ ___/| | \ | -// \____|__ /__| |__| (____ /\___ >___| /__|_| /\___ >___| /__| -// \/ \/ \/ \/ \/ \/ \/ - -type ErrAttachmentNotExist struct { - ID int64 - UUID string -} - -func IsErrAttachmentNotExist(err error) bool { - _, ok := err.(ErrAttachmentNotExist) - return ok -} - -func (err ErrAttachmentNotExist) Error() string { - return fmt.Sprintf("attachment does not exist [id: %d, uuid: %s]", err.ID, err.UUID) -} - // .____ .__ _________ // | | ____ ____ |__| ____ / _____/ ____ __ _________ ____ ____ // | | / _ \ / ___\| |/ \ \_____ \ / _ \| | \_ __ \_/ ___\/ __ \ diff --git a/internal/db/errors/issue.go b/internal/db/errors/issue.go index 903cc977e..4ea898fb9 100644 --- a/internal/db/errors/issue.go +++ b/internal/db/errors/issue.go @@ -6,21 +6,6 @@ package errors import "fmt" -type IssueNotExist struct { - ID int64 - RepoID int64 - Index int64 -} - -func IsIssueNotExist(err error) bool { - _, ok := err.(IssueNotExist) - return ok -} - -func (err IssueNotExist) Error() string { - return fmt.Sprintf("issue does not exist [id: %d, repo_id: %d, index: %d]", err.ID, err.RepoID, err.Index) -} - type InvalidIssueReference struct { Ref string } diff --git a/internal/db/errors/org.go b/internal/db/errors/org.go deleted file mode 100644 index 565327464..000000000 --- a/internal/db/errors/org.go +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2018 The Gogs Authors. All rights reserved. -// Use of this source code is governed by a MIT-style -// license that can be found in the LICENSE file. - -package errors - -import "fmt" - -type TeamNotExist struct { - TeamID int64 - Name string -} - -func IsTeamNotExist(err error) bool { - _, ok := err.(TeamNotExist) - return ok -} - -func (err TeamNotExist) Error() string { - return fmt.Sprintf("team does not exist [team_id: %d, name: %s]", err.TeamID, err.Name) -} diff --git a/internal/db/errors/repo.go b/internal/db/errors/repo.go index c9894af91..ba6c502cf 100644 --- a/internal/db/errors/repo.go +++ b/internal/db/errors/repo.go @@ -4,35 +4,9 @@ package errors -import "fmt" - -type RepoNotExist struct { - ID int64 - UserID int64 - Name string -} - -func IsRepoNotExist(err error) bool { - _, ok := err.(RepoNotExist) - return ok -} - -func (err RepoNotExist) Error() string { - return fmt.Sprintf("repository does not exist [id: %d, user_id: %d, name: %s]", err.ID, err.UserID, err.Name) -} - -type ReachLimitOfRepo struct { - Limit int -} - -func IsReachLimitOfRepo(err error) bool { - _, ok := err.(ReachLimitOfRepo) - return ok -} - -func (err ReachLimitOfRepo) Error() string { - return fmt.Sprintf("user has reached maximum limit of repositories [limit: %d]", err.Limit) -} +import ( + "fmt" +) type InvalidRepoReference struct { Ref string @@ -72,16 +46,3 @@ func IsBranchAlreadyExists(err error) bool { func (err BranchAlreadyExists) Error() string { return fmt.Sprintf("branch already exists [name: %s]", err.Name) } - -type ErrBranchNotExist struct { - Name string -} - -func IsErrBranchNotExist(err error) bool { - _, ok := err.(ErrBranchNotExist) - return ok -} - -func (err ErrBranchNotExist) Error() string { - return fmt.Sprintf("branch does not exist [name: %s]", err.Name) -} diff --git a/internal/db/errors/user.go b/internal/db/errors/user.go index 526d4b2d0..54a6ad50f 100644 --- a/internal/db/errors/user.go +++ b/internal/db/errors/user.go @@ -4,7 +4,9 @@ package errors -import "fmt" +import ( + "fmt" +) type EmptyName struct{} @@ -17,20 +19,6 @@ func (err EmptyName) Error() string { return "empty name" } -type UserNotExist struct { - UserID int64 - Name string -} - -func IsUserNotExist(err error) bool { - _, ok := err.(UserNotExist) - return ok -} - -func (err UserNotExist) Error() string { - return fmt.Sprintf("user does not exist [user_id: %d, name: %s]", err.UserID, err.Name) -} - type UserNotKeyOwner struct { KeyID int64 } diff --git a/internal/db/errors/webhook.go b/internal/db/errors/webhook.go deleted file mode 100644 index 76cf8cb41..000000000 --- a/internal/db/errors/webhook.go +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright 2017 The Gogs Authors. All rights reserved. -// Use of this source code is governed by a MIT-style -// license that can be found in the LICENSE file. - -package errors - -import "fmt" - -type WebhookNotExist struct { - ID int64 -} - -func IsWebhookNotExist(err error) bool { - _, ok := err.(WebhookNotExist) - return ok -} - -func (err WebhookNotExist) Error() string { - return fmt.Sprintf("webhook does not exist [id: %d]", err.ID) -} - -type HookTaskNotExist struct { - HookID int64 - UUID string -} - -func IsHookTaskNotExist(err error) bool { - _, ok := err.(HookTaskNotExist) - return ok -} - -func (err HookTaskNotExist) Error() string { - return fmt.Sprintf("hook task does not exist [hook_id: %d, uuid: %s]", err.HookID, err.UUID) -} diff --git a/internal/db/issue.go b/internal/db/issue.go index 939152445..377e77b41 100644 --- a/internal/db/issue.go +++ b/internal/db/issue.go @@ -17,6 +17,7 @@ import ( "gogs.io/gogs/internal/conf" "gogs.io/gogs/internal/db/errors" + "gogs.io/gogs/internal/errutil" "gogs.io/gogs/internal/tool" ) @@ -90,7 +91,7 @@ func (issue *Issue) loadAttributes(e Engine) (err error) { if issue.Poster == nil { issue.Poster, err = getUserByID(e, issue.PosterID) if err != nil { - if errors.IsUserNotExist(err) { + if IsErrUserNotExist(err) { issue.PosterID = -1 issue.Poster = NewGhostUser() } else { @@ -395,7 +396,7 @@ func (issue *Issue) GetAssignee() (err error) { } issue.Assignee, err = GetUserByID(issue.AssigneeID) - if errors.IsUserNotExist(err) { + if IsErrUserNotExist(err) { return nil } return err @@ -600,8 +601,8 @@ func (issue *Issue) ChangeAssignee(doer *User, assigneeID int64) (err error) { } issue.Assignee, err = GetUserByID(issue.AssigneeID) - if err != nil && !errors.IsUserNotExist(err) { - log.Error("GetUserByID [assignee_id: %v]: %v", issue.AssigneeID, err) + if err != nil && !IsErrUserNotExist(err) { + log.Error("Failed to get user by ID: %v", err) return nil } @@ -673,8 +674,8 @@ func newIssue(e *xorm.Session, opts NewIssueOptions) (err error) { if opts.Issue.AssigneeID > 0 { assignee, err := getUserByID(e, opts.Issue.AssigneeID) - if err != nil && !errors.IsUserNotExist(err) { - return fmt.Errorf("getUserByID: %v", err) + if err != nil && !IsErrUserNotExist(err) { + return fmt.Errorf("get user by ID: %v", err) } // Assume assignee is invalid and drop silently. @@ -796,6 +797,25 @@ func NewIssue(repo *Repository, issue *Issue, labelIDs []int64, uuids []string) return nil } +var _ errutil.NotFound = (*ErrIssueNotExist)(nil) + +type ErrIssueNotExist struct { + args map[string]interface{} +} + +func IsErrIssueNotExist(err error) bool { + _, ok := err.(ErrIssueNotExist) + return ok +} + +func (err ErrIssueNotExist) Error() string { + return fmt.Sprintf("issue does not exist: %v", err.args) +} + +func (ErrIssueNotExist) NotFound() bool { + return true +} + // GetIssueByRef returns an Issue specified by a GFM reference. // See https://help.github.com/articles/writing-on-github#references for more information on the syntax. func GetIssueByRef(ref string) (*Issue, error) { @@ -806,7 +826,7 @@ func GetIssueByRef(ref string) (*Issue, error) { index := com.StrTo(ref[n+1:]).MustInt64() if index == 0 { - return nil, errors.IssueNotExist{} + return nil, ErrIssueNotExist{args: map[string]interface{}{"ref": ref}} } repo, err := GetRepositoryByRef(ref[:n]) @@ -832,7 +852,7 @@ func GetRawIssueByIndex(repoID, index int64) (*Issue, error) { if err != nil { return nil, err } else if !has { - return nil, errors.IssueNotExist{RepoID: repoID, Index: index} + return nil, ErrIssueNotExist{args: map[string]interface{}{"repoID": repoID, "index": index}} } return issue, nil } @@ -852,7 +872,7 @@ func getRawIssueByID(e Engine, id int64) (*Issue, error) { if err != nil { return nil, err } else if !has { - return nil, errors.IssueNotExist{ID: id} + return nil, ErrIssueNotExist{args: map[string]interface{}{"issueID": id}} } return issue, nil } diff --git a/internal/db/issue_label.go b/internal/db/issue_label.go index b7a6029a7..0eaa9b964 100644 --- a/internal/db/issue_label.go +++ b/internal/db/issue_label.go @@ -14,6 +14,7 @@ import ( api "github.com/gogs/go-gogs-client" + "gogs.io/gogs/internal/errutil" "gogs.io/gogs/internal/lazyregexp" "gogs.io/gogs/internal/tool" ) @@ -103,23 +104,42 @@ func NewLabels(labels ...*Label) error { return err } +var _ errutil.NotFound = (*ErrLabelNotExist)(nil) + +type ErrLabelNotExist struct { + args map[string]interface{} +} + +func IsErrLabelNotExist(err error) bool { + _, ok := err.(ErrLabelNotExist) + return ok +} + +func (err ErrLabelNotExist) Error() string { + return fmt.Sprintf("label does not exist: %v", err.args) +} + +func (ErrLabelNotExist) NotFound() bool { + return true +} + // getLabelOfRepoByName returns a label by Name in given repository. // If pass repoID as 0, then ORM will ignore limitation of repository // and can return arbitrary label with any valid ID. func getLabelOfRepoByName(e Engine, repoID int64, labelName string) (*Label, error) { if len(labelName) <= 0 { - return nil, ErrLabelNotExist{0, repoID} + return nil, ErrLabelNotExist{args: map[string]interface{}{"repoID": repoID}} } l := &Label{ Name: labelName, RepoID: repoID, } - has, err := x.Get(l) + has, err := e.Get(l) if err != nil { return nil, err } else if !has { - return nil, ErrLabelNotExist{0, l.RepoID} + return nil, ErrLabelNotExist{args: map[string]interface{}{"repoID": repoID}} } return l, nil } @@ -129,18 +149,18 @@ func getLabelOfRepoByName(e Engine, repoID int64, labelName string) (*Label, err // and can return arbitrary label with any valid ID. func getLabelOfRepoByID(e Engine, repoID, labelID int64) (*Label, error) { if labelID <= 0 { - return nil, ErrLabelNotExist{labelID, repoID} + return nil, ErrLabelNotExist{args: map[string]interface{}{"repoID": repoID, "labelID": labelID}} } l := &Label{ ID: labelID, RepoID: repoID, } - has, err := x.Get(l) + has, err := e.Get(l) if err != nil { return nil, err } else if !has { - return nil, ErrLabelNotExist{l.ID, l.RepoID} + return nil, ErrLabelNotExist{args: map[string]interface{}{"repoID": repoID, "labelID": labelID}} } return l, nil } diff --git a/internal/db/login_source.go b/internal/db/login_source.go index ee59cdbdc..80d65f6e9 100644 --- a/internal/db/login_source.go +++ b/internal/db/login_source.go @@ -556,7 +556,7 @@ func LoginViaLDAP(user *User, login, password string, source *LoginSource, autoR username, fn, sn, mail, isAdmin, succeed := source.Cfg.(*LDAPConfig).SearchEntry(login, password, source.Type == LOGIN_DLDAP) if !succeed { // User not in LDAP, do nothing - return nil, errors.UserNotExist{Name: login} + return nil, ErrUserNotExist{args: map[string]interface{}{"login": login}} } if !autoRegister { @@ -674,9 +674,9 @@ func LoginViaSMTP(user *User, login, password string, sourceID int64, cfg *SMTPC if len(cfg.AllowedDomains) > 0 { idx := strings.Index(login, "@") if idx == -1 { - return nil, errors.UserNotExist{Name: login} + return nil, ErrUserNotExist{args: map[string]interface{}{"login": login}} } else if !com.IsSliceContainsStr(strings.Split(cfg.AllowedDomains, ","), login[idx+1:]) { - return nil, errors.UserNotExist{Name: login} + return nil, ErrUserNotExist{args: map[string]interface{}{"login": login}} } } @@ -695,7 +695,7 @@ func LoginViaSMTP(user *User, login, password string, sourceID int64, cfg *SMTPC tperr, ok := err.(*textproto.Error) if (ok && tperr.Code == 535) || strings.Contains(err.Error(), "Username and Password not accepted") { - return nil, errors.UserNotExist{Name: login} + return nil, ErrUserNotExist{args: map[string]interface{}{"login": login}} } return nil, err } @@ -735,7 +735,7 @@ func LoginViaSMTP(user *User, login, password string, sourceID int64, cfg *SMTPC func LoginViaPAM(user *User, login, password string, sourceID int64, cfg *PAMConfig, autoRegister bool) (*User, error) { if err := pam.PAMAuth(cfg.ServiceName, login, password); err != nil { if strings.Contains(err.Error(), "Authentication failure") { - return nil, errors.UserNotExist{Name: login} + return nil, ErrUserNotExist{args: map[string]interface{}{"login": login}} } return nil, err } @@ -768,7 +768,7 @@ func LoginViaGitHub(user *User, login, password string, sourceID int64, cfg *Git fullname, email, url, location, err := github.Authenticate(cfg.APIEndpoint, login, password) if err != nil { if strings.Contains(err.Error(), "401") { - return nil, errors.UserNotExist{Name: login} + return nil, ErrUserNotExist{args: map[string]interface{}{"login": login}} } return nil, err } @@ -840,7 +840,7 @@ func UserLogin(username, password string, loginSourceID int64) (*User, error) { return user, nil } - return nil, errors.UserNotExist{UserID: user.ID, Name: user.Name} + return nil, ErrUserNotExist{args: map[string]interface{}{"userID": user.ID, "name": user.Name}} } // Remote login to the login source the user is associated with @@ -854,7 +854,7 @@ func UserLogin(username, password string, loginSourceID int64) (*User, error) { // Non-local login source is always greater than 0 if loginSourceID <= 0 { - return nil, errors.UserNotExist{UserID: -1, Name: username} + return nil, ErrUserNotExist{args: map[string]interface{}{"name": username}} } source, err := GetLoginSourceByID(loginSourceID) diff --git a/internal/db/milestone.go b/internal/db/milestone.go index 77f52f923..df059b304 100644 --- a/internal/db/milestone.go +++ b/internal/db/milestone.go @@ -14,6 +14,7 @@ import ( api "github.com/gogs/go-gogs-client" "gogs.io/gogs/internal/conf" + "gogs.io/gogs/internal/errutil" ) // Milestone represents a milestone of repository. @@ -130,6 +131,25 @@ func NewMilestone(m *Milestone) (err error) { return sess.Commit() } +var _ errutil.NotFound = (*ErrMilestoneNotExist)(nil) + +type ErrMilestoneNotExist struct { + args map[string]interface{} +} + +func IsErrMilestoneNotExist(err error) bool { + _, ok := err.(ErrMilestoneNotExist) + return ok +} + +func (err ErrMilestoneNotExist) Error() string { + return fmt.Sprintf("milestone does not exist: %v", err.args) +} + +func (ErrMilestoneNotExist) NotFound() bool { + return true +} + func getMilestoneByRepoID(e Engine, repoID, id int64) (*Milestone, error) { m := &Milestone{ ID: id, @@ -139,7 +159,7 @@ func getMilestoneByRepoID(e Engine, repoID, id int64) (*Milestone, error) { if err != nil { return nil, err } else if !has { - return nil, ErrMilestoneNotExist{id, repoID} + return nil, ErrMilestoneNotExist{args: map[string]interface{}{"repoID": repoID, "milestoneID": id}} } return m, nil } diff --git a/internal/db/org_team.go b/internal/db/org_team.go index accbfe5b7..418d4f6bd 100644 --- a/internal/db/org_team.go +++ b/internal/db/org_team.go @@ -11,6 +11,7 @@ import ( "xorm.io/xorm" "gogs.io/gogs/internal/db/errors" + "gogs.io/gogs/internal/errutil" ) const OWNER_TEAM = "Owners" @@ -266,6 +267,25 @@ func NewTeam(t *Team) error { return sess.Commit() } +var _ errutil.NotFound = (*ErrTeamNotExist)(nil) + +type ErrTeamNotExist struct { + args map[string]interface{} +} + +func IsErrTeamNotExist(err error) bool { + _, ok := err.(ErrTeamNotExist) + return ok +} + +func (err ErrTeamNotExist) Error() string { + return fmt.Sprintf("team does not exist: %v", err.args) +} + +func (ErrTeamNotExist) NotFound() bool { + return true +} + func getTeamOfOrgByName(e Engine, orgID int64, name string) (*Team, error) { t := &Team{ OrgID: orgID, @@ -275,7 +295,7 @@ func getTeamOfOrgByName(e Engine, orgID int64, name string) (*Team, error) { if err != nil { return nil, err } else if !has { - return nil, errors.TeamNotExist{Name: name} + return nil, ErrTeamNotExist{args: map[string]interface{}{"orgID": orgID, "name": name}} } return t, nil } @@ -291,7 +311,7 @@ func getTeamByID(e Engine, teamID int64) (*Team, error) { if err != nil { return nil, err } else if !has { - return nil, errors.TeamNotExist{TeamID: teamID} + return nil, ErrTeamNotExist{args: map[string]interface{}{"teamID": teamID}} } return t, nil } diff --git a/internal/db/pull.go b/internal/db/pull.go index cd08813f5..331bc3ddb 100644 --- a/internal/db/pull.go +++ b/internal/db/pull.go @@ -19,7 +19,7 @@ import ( api "github.com/gogs/go-gogs-client" "gogs.io/gogs/internal/conf" - "gogs.io/gogs/internal/db/errors" + "gogs.io/gogs/internal/errutil" "gogs.io/gogs/internal/osutil" "gogs.io/gogs/internal/process" "gogs.io/gogs/internal/sync" @@ -89,25 +89,25 @@ func (pr *PullRequest) AfterSet(colName string, _ xorm.Cell) { func (pr *PullRequest) loadAttributes(e Engine) (err error) { if pr.HeadRepo == nil { pr.HeadRepo, err = getRepositoryByID(e, pr.HeadRepoID) - if err != nil && !errors.IsRepoNotExist(err) { - return fmt.Errorf("getRepositoryByID.(HeadRepo) [%d]: %v", pr.HeadRepoID, err) + if err != nil && !IsErrRepoNotExist(err) { + return fmt.Errorf("get head repository by ID: %v", err) } } if pr.BaseRepo == nil { pr.BaseRepo, err = getRepositoryByID(e, pr.BaseRepoID) if err != nil { - return fmt.Errorf("getRepositoryByID.(BaseRepo) [%d]: %v", pr.BaseRepoID, err) + return fmt.Errorf("get base repository by ID: %v", err) } } if pr.HasMerged && pr.Merger == nil { pr.Merger, err = getUserByID(e, pr.MergerID) - if errors.IsUserNotExist(err) { + if IsErrUserNotExist(err) { pr.MergerID = -1 pr.Merger = NewGhostUser() } else if err != nil { - return fmt.Errorf("getUserByID [%d]: %v", pr.MergerID, err) + return fmt.Errorf("get merger by ID: %v", err) } } @@ -521,7 +521,12 @@ func GetUnmergedPullRequest(headRepoID, baseRepoID int64, headBranch, baseBranch if err != nil { return nil, err } else if !has { - return nil, ErrPullRequestNotExist{0, 0, headRepoID, baseRepoID, headBranch, baseBranch} + return nil, ErrPullRequestNotExist{args: map[string]interface{}{ + "headRepoID": headRepoID, + "baseRepoID": baseRepoID, + "headBranch": headBranch, + "baseBranch": baseBranch, + }} } return pr, nil @@ -545,13 +550,32 @@ func GetUnmergedPullRequestsByBaseInfo(repoID int64, branch string) ([]*PullRequ Join("INNER", "issue", "issue.id=pull_request.issue_id").Find(&prs) } +var _ errutil.NotFound = (*ErrPullRequestNotExist)(nil) + +type ErrPullRequestNotExist struct { + args map[string]interface{} +} + +func IsErrPullRequestNotExist(err error) bool { + _, ok := err.(ErrPullRequestNotExist) + return ok +} + +func (err ErrPullRequestNotExist) Error() string { + return fmt.Sprintf("pull request does not exist: %v", err.args) +} + +func (ErrPullRequestNotExist) NotFound() bool { + return true +} + func getPullRequestByID(e Engine, id int64) (*PullRequest, error) { pr := new(PullRequest) has, err := e.ID(id).Get(pr) if err != nil { return nil, err } else if !has { - return nil, ErrPullRequestNotExist{id, 0, 0, 0, "", ""} + return nil, ErrPullRequestNotExist{args: map[string]interface{}{"pullRequestID": id}} } return pr, pr.loadAttributes(e) } @@ -569,7 +593,7 @@ func getPullRequestByIssueID(e Engine, issueID int64) (*PullRequest, error) { if err != nil { return nil, err } else if !has { - return nil, ErrPullRequestNotExist{0, issueID, 0, 0, "", ""} + return nil, ErrPullRequestNotExist{args: map[string]interface{}{"issueID": issueID}} } return pr, pr.loadAttributes(e) } diff --git a/internal/db/release.go b/internal/db/release.go index fa69fba87..71a72dae0 100644 --- a/internal/db/release.go +++ b/internal/db/release.go @@ -16,7 +16,7 @@ import ( "github.com/gogs/git-module" api "github.com/gogs/go-gogs-client" - "gogs.io/gogs/internal/db/errors" + "gogs.io/gogs/internal/errutil" "gogs.io/gogs/internal/process" ) @@ -68,7 +68,7 @@ func (r *Release) loadAttributes(e Engine) (err error) { if r.Publisher == nil { r.Publisher, err = getUserByID(e, r.PublisherID) if err != nil { - if errors.IsUserNotExist(err) { + if IsErrUserNotExist(err) { r.PublisherID = -1 r.Publisher = NewGhostUser() } else { @@ -206,13 +206,32 @@ func NewRelease(gitRepo *git.Repository, r *Release, uuids []string) error { return nil } +var _ errutil.NotFound = (*ErrReleaseNotExist)(nil) + +type ErrReleaseNotExist struct { + args map[string]interface{} +} + +func IsErrReleaseNotExist(err error) bool { + _, ok := err.(ErrReleaseNotExist) + return ok +} + +func (err ErrReleaseNotExist) Error() string { + return fmt.Sprintf("release does not exist: %v", err.args) +} + +func (ErrReleaseNotExist) NotFound() bool { + return true +} + // GetRelease returns release by given ID. func GetRelease(repoID int64, tagName string) (*Release, error) { isExist, err := IsReleaseExist(repoID, tagName) if err != nil { return nil, err } else if !isExist { - return nil, ErrReleaseNotExist{0, tagName} + return nil, ErrReleaseNotExist{args: map[string]interface{}{"tag": tagName}} } r := &Release{RepoID: repoID, LowerTagName: strings.ToLower(tagName)} @@ -230,7 +249,7 @@ func GetReleaseByID(id int64) (*Release, error) { if err != nil { return nil, err } else if !has { - return nil, ErrReleaseNotExist{id, ""} + return nil, ErrReleaseNotExist{args: map[string]interface{}{"releaseID": id}} } return r, r.LoadAttributes() diff --git a/internal/db/repo.go b/internal/db/repo.go index 7e607dc0b..1a27a34af 100644 --- a/internal/db/repo.go +++ b/internal/db/repo.go @@ -33,6 +33,7 @@ import ( "gogs.io/gogs/internal/avatar" "gogs.io/gogs/internal/conf" "gogs.io/gogs/internal/db/errors" + "gogs.io/gogs/internal/errutil" "gogs.io/gogs/internal/markup" "gogs.io/gogs/internal/osutil" "gogs.io/gogs/internal/process" @@ -248,11 +249,11 @@ func (repo *Repository) loadAttributes(e Engine) (err error) { if repo.IsFork && repo.BaseRepo == nil { repo.BaseRepo, err = getRepositoryByID(e, repo.ForkID) if err != nil { - if errors.IsRepoNotExist(err) { + if IsErrRepoNotExist(err) { repo.IsFork = false repo.ForkID = 0 } else { - return fmt.Errorf("getRepositoryByID [%d]: %v", repo.ForkID, err) + return fmt.Errorf("get fork repository by ID: %v", err) } } } @@ -1104,10 +1105,23 @@ func createRepository(e *xorm.Session, doer, owner *User, repo *Repository) (err return repo.loadAttributes(e) } +type ErrReachLimitOfRepo struct { + Limit int +} + +func IsErrReachLimitOfRepo(err error) bool { + _, ok := err.(ErrReachLimitOfRepo) + return ok +} + +func (err ErrReachLimitOfRepo) Error() string { + return fmt.Sprintf("user has reached maximum limit of repositories [limit: %d]", err.Limit) +} + // CreateRepository creates a repository for given user or organization. func CreateRepository(doer, owner *User, opts CreateRepoOptions) (_ *Repository, err error) { if !owner.CanCreateRepo() { - return nil, errors.ReachLimitOfRepo{Limit: owner.RepoCreationNum()} + return nil, ErrReachLimitOfRepo{Limit: owner.RepoCreationNum()} } repo := &Repository{ @@ -1481,17 +1495,17 @@ func UpdateRepository(repo *Repository, visibilityChanged bool) (err error) { } // DeleteRepository deletes a repository for a user or organization. -func DeleteRepository(uid, repoID int64) error { - repo := &Repository{ID: repoID, OwnerID: uid} +func DeleteRepository(ownerID, repoID int64) error { + repo := &Repository{ID: repoID, OwnerID: ownerID} has, err := x.Get(repo) if err != nil { return err } else if !has { - return errors.RepoNotExist{ID: repoID, UserID: uid} + return ErrRepoNotExist{args: map[string]interface{}{"ownerID": ownerID, "repoID": repoID}} } // In case is a organization. - org, err := GetUserByID(uid) + org, err := GetUserByID(ownerID) if err != nil { return err } @@ -1571,7 +1585,7 @@ func DeleteRepository(uid, repoID int64) error { } } - if _, err = sess.Exec("UPDATE `user` SET num_repos=num_repos-1 WHERE id=?", uid); err != nil { + if _, err = sess.Exec("UPDATE `user` SET num_repos=num_repos-1 WHERE id=?", ownerID); err != nil { return err } @@ -1616,6 +1630,25 @@ func GetRepositoryByRef(ref string) (*Repository, error) { return GetRepositoryByName(user.ID, repoName) } +var _ errutil.NotFound = (*ErrRepoNotExist)(nil) + +type ErrRepoNotExist struct { + args map[string]interface{} +} + +func IsErrRepoNotExist(err error) bool { + _, ok := err.(ErrRepoNotExist) + return ok +} + +func (err ErrRepoNotExist) Error() string { + return fmt.Sprintf("repository does not exist: %v", err.args) +} + +func (ErrRepoNotExist) NotFound() bool { + return true +} + // GetRepositoryByName returns the repository by given name under user if exists. func GetRepositoryByName(ownerID int64, name string) (*Repository, error) { repo := &Repository{ @@ -1626,7 +1659,7 @@ func GetRepositoryByName(ownerID int64, name string) (*Repository, error) { if err != nil { return nil, err } else if !has { - return nil, errors.RepoNotExist{UserID: ownerID, Name: name} + return nil, ErrRepoNotExist{args: map[string]interface{}{"ownerID": ownerID, "name": name}} } return repo, repo.LoadAttributes() } @@ -1637,7 +1670,7 @@ func getRepositoryByID(e Engine, id int64) (*Repository, error) { if err != nil { return nil, err } else if !has { - return nil, errors.RepoNotExist{ID: id} + return nil, ErrRepoNotExist{args: map[string]interface{}{"repoID": id}} } return repo, repo.loadAttributes(e) } @@ -2361,7 +2394,7 @@ func HasForkedRepo(ownerID, repoID int64) (*Repository, bool, error) { // ForkRepository creates a fork of target repository under another user domain. func ForkRepository(doer, owner *User, baseRepo *Repository, name, desc string) (_ *Repository, err error) { if !owner.CanCreateRepo() { - return nil, errors.ReachLimitOfRepo{Limit: owner.RepoCreationNum()} + return nil, ErrReachLimitOfRepo{Limit: owner.RepoCreationNum()} } repo := &Repository{ diff --git a/internal/db/repo_branch.go b/internal/db/repo_branch.go index a4d38ecba..8da999457 100644 --- a/internal/db/repo_branch.go +++ b/internal/db/repo_branch.go @@ -11,7 +11,7 @@ import ( "github.com/gogs/git-module" "github.com/unknwon/com" - "gogs.io/gogs/internal/db/errors" + "gogs.io/gogs/internal/errutil" "gogs.io/gogs/internal/tool" ) @@ -44,9 +44,28 @@ func GetBranchesByPath(path string) ([]*Branch, error) { return branches, nil } +var _ errutil.NotFound = (*ErrBranchNotExist)(nil) + +type ErrBranchNotExist struct { + args map[string]interface{} +} + +func IsErrBranchNotExist(err error) bool { + _, ok := err.(ErrBranchNotExist) + return ok +} + +func (err ErrBranchNotExist) Error() string { + return fmt.Sprintf("branch does not exist: %v", err.args) +} + +func (ErrBranchNotExist) NotFound() bool { + return true +} + func (repo *Repository) GetBranch(name string) (*Branch, error) { if !git.RepoHasBranch(repo.RepoPath(), name) { - return nil, errors.ErrBranchNotExist{Name: name} + return nil, ErrBranchNotExist{args: map[string]interface{}{"name": name}} } return &Branch{ RepoPath: repo.RepoPath(), @@ -102,7 +121,7 @@ func GetProtectBranchOfRepoByName(repoID int64, name string) (*ProtectBranch, er if err != nil { return nil, err } else if !has { - return nil, errors.ErrBranchNotExist{Name: name} + return nil, ErrBranchNotExist{args: map[string]interface{}{"name": name}} } return protectBranch, nil } diff --git a/internal/db/ssh_key.go b/internal/db/ssh_key.go index b31c0da13..b82f81a61 100644 --- a/internal/db/ssh_key.go +++ b/internal/db/ssh_key.go @@ -24,6 +24,7 @@ import ( "xorm.io/xorm" "gogs.io/gogs/internal/conf" + "gogs.io/gogs/internal/errutil" "gogs.io/gogs/internal/process" ) @@ -684,6 +685,25 @@ func AddDeployKey(repoID int64, name, content string) (*DeployKey, error) { return key, sess.Commit() } +var _ errutil.NotFound = (*ErrDeployKeyNotExist)(nil) + +type ErrDeployKeyNotExist struct { + args map[string]interface{} +} + +func IsErrDeployKeyNotExist(err error) bool { + _, ok := err.(ErrDeployKeyNotExist) + return ok +} + +func (err ErrDeployKeyNotExist) Error() string { + return fmt.Sprintf("deploy key does not exist: %v", err.args) +} + +func (ErrDeployKeyNotExist) NotFound() bool { + return true +} + // GetDeployKeyByID returns deploy key by given ID. func GetDeployKeyByID(id int64) (*DeployKey, error) { key := new(DeployKey) @@ -691,7 +711,7 @@ func GetDeployKeyByID(id int64) (*DeployKey, error) { if err != nil { return nil, err } else if !has { - return nil, ErrDeployKeyNotExist{id, 0, 0} + return nil, ErrDeployKeyNotExist{args: map[string]interface{}{"deployKeyID": id}} } return key, nil } @@ -706,7 +726,7 @@ func GetDeployKeyByRepo(keyID, repoID int64) (*DeployKey, error) { if err != nil { return nil, err } else if !has { - return nil, ErrDeployKeyNotExist{0, keyID, repoID} + return nil, ErrDeployKeyNotExist{args: map[string]interface{}{"keyID": keyID, "repoID": repoID}} } return key, nil } diff --git a/internal/db/user.go b/internal/db/user.go index c3c3f31eb..0c793170d 100644 --- a/internal/db/user.go +++ b/internal/db/user.go @@ -31,6 +31,7 @@ import ( "gogs.io/gogs/internal/avatar" "gogs.io/gogs/internal/conf" "gogs.io/gogs/internal/db/errors" + "gogs.io/gogs/internal/errutil" "gogs.io/gogs/internal/tool" ) @@ -606,8 +607,8 @@ func parseUserFromCode(code string) (user *User) { if b, err := hex.DecodeString(hexStr); err == nil { if user, err = GetUserByName(string(b)); user != nil { return user - } else if !errors.IsUserNotExist(err) { - log.Error("GetUserByName: %v", err) + } else if !IsErrUserNotExist(err) { + log.Error("Failed to get user by name %q: %v", string(b), err) } } @@ -890,13 +891,32 @@ func GetUserByKeyID(keyID int64) (*User, error) { return user, nil } +var _ errutil.NotFound = (*ErrUserNotExist)(nil) + +type ErrUserNotExist struct { + args map[string]interface{} +} + +func IsErrUserNotExist(err error) bool { + _, ok := err.(ErrUserNotExist) + return ok +} + +func (err ErrUserNotExist) Error() string { + return fmt.Sprintf("user does not exist: %v", err.args) +} + +func (ErrUserNotExist) NotFound() bool { + return true +} + func getUserByID(e Engine, id int64) (*User, error) { u := new(User) has, err := e.ID(id).Get(u) if err != nil { return nil, err } else if !has { - return nil, errors.UserNotExist{UserID: id} + return nil, ErrUserNotExist{args: map[string]interface{}{"userID": id}} } return u, nil } @@ -912,7 +932,7 @@ func GetAssigneeByID(repo *Repository, userID int64) (*User, error) { if err != nil { return nil, err } else if !has { - return nil, errors.UserNotExist{UserID: userID} + return nil, ErrUserNotExist{args: map[string]interface{}{"userID": userID}} } return GetUserByID(userID) } @@ -920,14 +940,14 @@ func GetAssigneeByID(repo *Repository, userID int64) (*User, error) { // GetUserByName returns a user by given name. func GetUserByName(name string) (*User, error) { if len(name) == 0 { - return nil, errors.UserNotExist{Name: name} + return nil, ErrUserNotExist{args: map[string]interface{}{"name": name}} } u := &User{LowerName: strings.ToLower(name)} has, err := x.Get(u) if err != nil { return nil, err } else if !has { - return nil, errors.UserNotExist{Name: name} + return nil, ErrUserNotExist{args: map[string]interface{}{"name": name}} } return u, nil } @@ -999,7 +1019,7 @@ func ValidateCommitsWithEmails(oldCommits []*git.Commit) []*UserCommit { // GetUserByEmail returns the user object by given e-mail if exists. func GetUserByEmail(email string) (*User, error) { if len(email) == 0 { - return nil, errors.UserNotExist{Name: "email"} + return nil, ErrUserNotExist{args: map[string]interface{}{"email": email}} } email = strings.ToLower(email) @@ -1023,7 +1043,7 @@ func GetUserByEmail(email string) (*User, error) { return GetUserByID(emailAddress.UID) } - return nil, errors.UserNotExist{Name: email} + return nil, ErrUserNotExist{args: map[string]interface{}{"email": email}} } type SearchUserOptions struct { diff --git a/internal/db/user_mail.go b/internal/db/user_mail.go index 37f0c2c0a..1608dc195 100644 --- a/internal/db/user_mail.go +++ b/internal/db/user_mail.go @@ -181,7 +181,7 @@ func MakeEmailPrimary(userID int64, email *EmailAddress) error { if err != nil { return err } else if !has { - return errors.UserNotExist{UserID: email.UID} + return ErrUserNotExist{args: map[string]interface{}{"userID": email.UID}} } // Make sure the former primary email doesn't disappear. diff --git a/internal/db/webhook.go b/internal/db/webhook.go index 418f2729b..1547a2769 100644 --- a/internal/db/webhook.go +++ b/internal/db/webhook.go @@ -22,7 +22,7 @@ import ( api "github.com/gogs/go-gogs-client" "gogs.io/gogs/internal/conf" - "gogs.io/gogs/internal/db/errors" + "gogs.io/gogs/internal/errutil" "gogs.io/gogs/internal/httplib" "gogs.io/gogs/internal/sync" ) @@ -235,6 +235,25 @@ func CreateWebhook(w *Webhook) error { return err } +var _ errutil.NotFound = (*ErrWebhookNotExist)(nil) + +type ErrWebhookNotExist struct { + args map[string]interface{} +} + +func IsErrWebhookNotExist(err error) bool { + _, ok := err.(ErrWebhookNotExist) + return ok +} + +func (err ErrWebhookNotExist) Error() string { + return fmt.Sprintf("webhook does not exist: %v", err.args) +} + +func (ErrWebhookNotExist) NotFound() bool { + return true +} + // getWebhook uses argument bean as query condition, // ID must be specified and do not assign unnecessary fields. func getWebhook(bean *Webhook) (*Webhook, error) { @@ -242,7 +261,7 @@ func getWebhook(bean *Webhook) (*Webhook, error) { if err != nil { return nil, err } else if !has { - return nil, errors.WebhookNotExist{ID: bean.ID} + return nil, ErrWebhookNotExist{args: map[string]interface{}{"webhookID": bean.ID}} } return bean, nil } @@ -499,6 +518,25 @@ func createHookTask(e Engine, t *HookTask) error { return err } +var _ errutil.NotFound = (*ErrHookTaskNotExist)(nil) + +type ErrHookTaskNotExist struct { + args map[string]interface{} +} + +func IsHookTaskNotExist(err error) bool { + _, ok := err.(ErrHookTaskNotExist) + return ok +} + +func (err ErrHookTaskNotExist) Error() string { + return fmt.Sprintf("hook task does not exist: %v", err.args) +} + +func (ErrHookTaskNotExist) NotFound() bool { + return true +} + // GetHookTaskOfWebhookByUUID returns hook task of given webhook by UUID. func GetHookTaskOfWebhookByUUID(webhookID int64, uuid string) (*HookTask, error) { hookTask := &HookTask{ @@ -509,7 +547,7 @@ func GetHookTaskOfWebhookByUUID(webhookID int64, uuid string) (*HookTask, error) if err != nil { return nil, err } else if !has { - return nil, errors.HookTaskNotExist{HookID: webhookID, UUID: uuid} + return nil, ErrHookTaskNotExist{args: map[string]interface{}{"webhookID": webhookID, "uuid": uuid}} } return hookTask, nil } diff --git a/internal/errutil/errutil.go b/internal/errutil/errutil.go new file mode 100644 index 000000000..af6584109 --- /dev/null +++ b/internal/errutil/errutil.go @@ -0,0 +1,16 @@ +// Copyright 2020 The Gogs Authors. All rights reserved. +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file. + +package errutil + +// NotFound represents a not found error. +type NotFound interface { + NotFound() bool +} + +// IsNotFound returns true if the error is a not found error. +func IsNotFound(err error) bool { + e, ok := err.(NotFound) + return ok && e.NotFound() +} diff --git a/internal/gitutil/error.go b/internal/gitutil/error.go index d8023f943..20aa3b51d 100644 --- a/internal/gitutil/error.go +++ b/internal/gitutil/error.go @@ -6,8 +6,33 @@ package gitutil import ( "github.com/gogs/git-module" + + "gogs.io/gogs/internal/errutil" ) +var _ errutil.NotFound = (*Error)(nil) + +// Error is a wrapper of a Git error, which handles not found. +type Error struct { + error +} + +func (e Error) NotFound() bool { + return IsErrSubmoduleNotExist(e.error) || + IsErrRevisionNotExist(e.error) + +} + +// NewError wraps given error. +func NewError(err error) error { + return Error{error: err} +} + +// IsErrSubmoduleNotExist returns true if the error is git.ErrSubmoduleNotExist. +func IsErrSubmoduleNotExist(err error) bool { + return err == git.ErrSubmoduleNotExist +} + // IsErrRevisionNotExist returns true if the error is git.ErrRevisionNotExist. func IsErrRevisionNotExist(err error) bool { return err == git.ErrRevisionNotExist @@ -17,8 +42,3 @@ func IsErrRevisionNotExist(err error) bool { func IsErrNoMergeBase(err error) bool { return err == git.ErrNoMergeBase } - -// IsErrSubmoduleNotExist returns true if the error is git.ErrSubmoduleNotExist. -func IsErrSubmoduleNotExist(err error) bool { - return err == git.ErrSubmoduleNotExist -} diff --git a/internal/osutil/error.go b/internal/osutil/error.go new file mode 100644 index 000000000..8f312aa97 --- /dev/null +++ b/internal/osutil/error.go @@ -0,0 +1,27 @@ +// Copyright 2020 The Gogs Authors. All rights reserved. +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file. + +package osutil + +import ( + "os" + + "gogs.io/gogs/internal/errutil" +) + +var _ errutil.NotFound = (*Error)(nil) + +// Error is a wrapper of an OS error, which handles not found. +type Error struct { + error +} + +func (e Error) NotFound() bool { + return e.error == os.ErrNotExist +} + +// NewError wraps given error. +func NewError(err error) error { + return Error{error: err} +} diff --git a/internal/route/admin/admin.go b/internal/route/admin/admin.go index 25da73339..0adfac807 100644 --- a/internal/route/admin/admin.go +++ b/internal/route/admin/admin.go @@ -163,7 +163,7 @@ func Dashboard(c *context.Context) { } else { c.Flash.Success(success) } - c.SubURLRedirect("/admin") + c.RedirectSubpath("/admin") return } @@ -239,5 +239,5 @@ func Monitor(c *context.Context) { c.Data["PageIsAdminMonitor"] = true c.Data["Processes"] = process.Processes c.Data["Entries"] = cron.ListTasks() - c.HTML(200, MONITOR) + c.Success( MONITOR) } diff --git a/internal/route/admin/auths.go b/internal/route/admin/auths.go index 9896b5b96..bcf52e5e4 100644 --- a/internal/route/admin/auths.go +++ b/internal/route/admin/auths.go @@ -34,7 +34,7 @@ func Authentications(c *context.Context) { var err error c.Data["Sources"], err = db.LoginSources() if err != nil { - c.ServerError("LoginSources", err) + c.Error(err, "list login sources") return } @@ -146,7 +146,7 @@ func NewAuthSourcePost(c *context.Context, f form.Authentication) { APIEndpoint: strings.TrimSuffix(f.GitHubAPIEndpoint, "/") + "/", } default: - c.Error(http.StatusBadRequest) + c.Status(http.StatusBadRequest) return } c.Data["HasTLS"] = hasTLS @@ -167,7 +167,7 @@ func NewAuthSourcePost(c *context.Context, f form.Authentication) { c.FormErr("Name") c.RenderWithErr(c.Tr("admin.auths.login_source_exist", err.(db.ErrLoginSourceAlreadyExist).Name), AUTH_NEW, f) } else { - c.ServerError("CreateSource", err) + c.Error(err, "create login source") } return } @@ -188,7 +188,7 @@ func EditAuthSource(c *context.Context) { source, err := db.GetLoginSourceByID(c.ParamsInt64(":authid")) if err != nil { - c.ServerError("GetLoginSourceByID", err) + c.Error(err, "get login source by ID") return } c.Data["Source"] = source @@ -206,7 +206,7 @@ func EditAuthSourcePost(c *context.Context, f form.Authentication) { source, err := db.GetLoginSourceByID(c.ParamsInt64(":authid")) if err != nil { - c.ServerError("GetLoginSourceByID", err) + c.Error(err, "get login source by ID") return } c.Data["Source"] = source @@ -232,7 +232,7 @@ func EditAuthSourcePost(c *context.Context, f form.Authentication) { APIEndpoint: strings.TrimSuffix(f.GitHubAPIEndpoint, "/") + "/", } default: - c.Error(http.StatusBadRequest) + c.Status(http.StatusBadRequest) return } @@ -241,7 +241,7 @@ func EditAuthSourcePost(c *context.Context, f form.Authentication) { source.IsDefault = f.IsDefault source.Cfg = config if err := db.UpdateLoginSource(source); err != nil { - c.ServerError("UpdateLoginSource", err) + c.Error(err, "update login source") return } @@ -254,7 +254,7 @@ func EditAuthSourcePost(c *context.Context, f form.Authentication) { func DeleteAuthSource(c *context.Context) { source, err := db.GetLoginSourceByID(c.ParamsInt64(":authid")) if err != nil { - c.ServerError("GetLoginSourceByID", err) + c.Error(err, "get login source by ID") return } diff --git a/internal/route/admin/notice.go b/internal/route/admin/notice.go index 20ce1356c..94fc22cd0 100644 --- a/internal/route/admin/notice.go +++ b/internal/route/admin/notice.go @@ -5,6 +5,8 @@ package admin import ( + "net/http" + "github.com/unknwon/com" "github.com/unknwon/paginater" log "unknwon.dev/clog/v2" @@ -19,7 +21,7 @@ const ( ) func Notices(c *context.Context) { - c.Data["Title"] = c.Tr("admin.notices") + c.Title("admin.notices") c.Data["PageIsAdmin"] = true c.Data["PageIsAdminNotices"] = true @@ -32,13 +34,13 @@ func Notices(c *context.Context) { notices, err := db.Notices(page, conf.UI.Admin.NoticePagingNum) if err != nil { - c.Handle(500, "Notices", err) + c.Error(err, "list notices") return } c.Data["Notices"] = notices c.Data["Total"] = total - c.HTML(200, NOTICES) + c.Success(NOTICES) } func DeleteNotices(c *context.Context) { @@ -53,16 +55,16 @@ func DeleteNotices(c *context.Context) { if err := db.DeleteNoticesByIDs(ids); err != nil { c.Flash.Error("DeleteNoticesByIDs: " + err.Error()) - c.Status(500) + c.Status(http.StatusInternalServerError) } else { c.Flash.Success(c.Tr("admin.notices.delete_success")) - c.Status(200) + c.Status(http.StatusOK) } } func EmptyNotices(c *context.Context) { if err := db.DeleteNotices(0, 0); err != nil { - c.Handle(500, "DeleteNotices", err) + c.Error(err,"delete notices") return } diff --git a/internal/route/admin/repos.go b/internal/route/admin/repos.go index f8f485410..12560b025 100644 --- a/internal/route/admin/repos.go +++ b/internal/route/admin/repos.go @@ -37,7 +37,7 @@ func Repos(c *context.Context) { if len(keyword) == 0 { repos, err = db.Repositories(page, conf.UI.Admin.RepoPagingNum) if err != nil { - c.Handle(500, "Repositories", err) + c.Error(err, "list repositories") return } count = db.CountRepositories(true) @@ -50,7 +50,7 @@ func Repos(c *context.Context) { PageSize: conf.UI.Admin.RepoPagingNum, }) if err != nil { - c.Handle(500, "SearchRepositoryByName", err) + c.Error(err, "search repository by name") return } } @@ -59,29 +59,29 @@ func Repos(c *context.Context) { c.Data["Page"] = paginater.New(int(count), conf.UI.Admin.RepoPagingNum, page, 5) if err = db.RepositoryList(repos).LoadAttributes(); err != nil { - c.Handle(500, "LoadAttributes", err) + c.Error(err, "load attributes") return } c.Data["Repos"] = repos - c.HTML(200, REPOS) + c.Success(REPOS) } func DeleteRepo(c *context.Context) { repo, err := db.GetRepositoryByID(c.QueryInt64("id")) if err != nil { - c.Handle(500, "GetRepositoryByID", err) + c.Error(err, "get repository by ID") return } if err := db.DeleteRepository(repo.MustOwner().ID, repo.ID); err != nil { - c.Handle(500, "DeleteRepository", err) + c.Error(err, "delete repository") return } log.Trace("Repository deleted: %s/%s", repo.MustOwner().Name, repo.Name) c.Flash.Success(c.Tr("repo.settings.deletion_success")) - c.JSON(200, map[string]interface{}{ + c.JSONSuccess(map[string]interface{}{ "redirect": conf.Server.Subpath + "/admin/repos?page=" + c.Query("page"), }) } diff --git a/internal/route/admin/users.go b/internal/route/admin/users.go index 8d5035731..630fa4ca0 100644 --- a/internal/route/admin/users.go +++ b/internal/route/admin/users.go @@ -48,13 +48,13 @@ func NewUser(c *context.Context) { sources, err := db.LoginSources() if err != nil { - c.Handle(500, "LoginSources", err) + c.Error(err, "list login sources") return } c.Data["Sources"] = sources c.Data["CanSendEmail"] = conf.Email.Enabled - c.HTML(200, USER_NEW) + c.Success(USER_NEW) } func NewUserPost(c *context.Context, f form.AdminCrateUser) { @@ -64,7 +64,7 @@ func NewUserPost(c *context.Context, f form.AdminCrateUser) { sources, err := db.LoginSources() if err != nil { - c.Handle(500, "LoginSources", err) + c.Error(err, "list login sources") return } c.Data["Sources"] = sources @@ -72,7 +72,7 @@ func NewUserPost(c *context.Context, f form.AdminCrateUser) { c.Data["CanSendEmail"] = conf.Email.Enabled if c.HasError() { - c.HTML(200, USER_NEW) + c.Success(USER_NEW) return } @@ -108,7 +108,7 @@ func NewUserPost(c *context.Context, f form.AdminCrateUser) { c.Data["Err_UserName"] = true c.RenderWithErr(c.Tr("user.form.name_pattern_not_allowed", err.(db.ErrNamePatternNotAllowed).Pattern), USER_NEW, &f) default: - c.Handle(500, "CreateUser", err) + c.Error(err, "create user") } return } @@ -126,7 +126,7 @@ func NewUserPost(c *context.Context, f form.AdminCrateUser) { func prepareUserInfo(c *context.Context) *db.User { u, err := db.GetUserByID(c.ParamsInt64(":userid")) if err != nil { - c.Handle(500, "GetUserByID", err) + c.Error(err, "get user by ID") return nil } c.Data["User"] = u @@ -134,7 +134,7 @@ func prepareUserInfo(c *context.Context) *db.User { if u.LoginSource > 0 { c.Data["LoginSource"], err = db.GetLoginSourceByID(u.LoginSource) if err != nil { - c.Handle(500, "GetLoginSourceByID", err) + c.Error(err, "get login source by ID") return nil } } else { @@ -143,7 +143,7 @@ func prepareUserInfo(c *context.Context) *db.User { sources, err := db.LoginSources() if err != nil { - c.Handle(500, "LoginSources", err) + c.Error(err, "list login sources") return nil } c.Data["Sources"] = sources @@ -162,7 +162,7 @@ func EditUser(c *context.Context) { return } - c.HTML(200, USER_EDIT) + c.Success(USER_EDIT) } func EditUserPost(c *context.Context, f form.AdminEditUser) { @@ -177,7 +177,7 @@ func EditUserPost(c *context.Context, f form.AdminEditUser) { } if c.HasError() { - c.HTML(200, USER_EDIT) + c.Success(USER_EDIT) return } @@ -196,7 +196,7 @@ func EditUserPost(c *context.Context, f form.AdminEditUser) { u.Passwd = f.Password var err error if u.Salt, err = db.GetUserSalt(); err != nil { - c.Handle(500, "UpdateUser", err) + c.Error(err, "get user salt") return } u.EncodePasswd() @@ -219,7 +219,7 @@ func EditUserPost(c *context.Context, f form.AdminEditUser) { c.Data["Err_Email"] = true c.RenderWithErr(c.Tr("form.email_been_used"), USER_EDIT, &f) } else { - c.Handle(500, "UpdateUser", err) + c.Error(err, "update user") } return } @@ -232,7 +232,7 @@ func EditUserPost(c *context.Context, f form.AdminEditUser) { func DeleteUser(c *context.Context) { u, err := db.GetUserByID(c.ParamsInt64(":userid")) if err != nil { - c.Handle(500, "GetUserByID", err) + c.Error(err, "get user by ID") return } @@ -240,23 +240,23 @@ func DeleteUser(c *context.Context) { switch { case db.IsErrUserOwnRepos(err): c.Flash.Error(c.Tr("admin.users.still_own_repo")) - c.JSON(200, map[string]interface{}{ + c.JSONSuccess(map[string]interface{}{ "redirect": conf.Server.Subpath + "/admin/users/" + c.Params(":userid"), }) case db.IsErrUserHasOrgs(err): c.Flash.Error(c.Tr("admin.users.still_has_org")) - c.JSON(200, map[string]interface{}{ + c.JSONSuccess(map[string]interface{}{ "redirect": conf.Server.Subpath + "/admin/users/" + c.Params(":userid"), }) default: - c.Handle(500, "DeleteUser", err) + c.Error(err, "delete user") } return } log.Trace("Account deleted by admin (%s): %s", c.User.Name, u.Name) c.Flash.Success(c.Tr("admin.users.deletion_success")) - c.JSON(200, map[string]interface{}{ + c.JSONSuccess(map[string]interface{}{ "redirect": conf.Server.Subpath + "/admin/users", }) } diff --git a/internal/route/api/v1/admin/org.go b/internal/route/api/v1/admin/org.go index 758f41e61..14350b1cd 100644 --- a/internal/route/api/v1/admin/org.go +++ b/internal/route/api/v1/admin/org.go @@ -6,12 +6,12 @@ package admin import ( api "github.com/gogs/go-gogs-client" - org2 "gogs.io/gogs/internal/route/api/v1/org" - user2 "gogs.io/gogs/internal/route/api/v1/user" "gogs.io/gogs/internal/context" + "gogs.io/gogs/internal/route/api/v1/org" + "gogs.io/gogs/internal/route/api/v1/user" ) func CreateOrg(c *context.APIContext, form api.CreateOrgOption) { - org2.CreateOrgForUser(c, form, user2.GetUserByParams(c)) + org.CreateOrgForUser(c, form, user.GetUserByParams(c)) } diff --git a/internal/route/api/v1/admin/org_repo.go b/internal/route/api/v1/admin/org_repo.go index b17b1462f..63a638fad 100644 --- a/internal/route/api/v1/admin/org_repo.go +++ b/internal/route/api/v1/admin/org_repo.go @@ -7,13 +7,12 @@ package admin import ( "gogs.io/gogs/internal/context" "gogs.io/gogs/internal/db" - "gogs.io/gogs/internal/db/errors" ) func GetRepositoryByParams(c *context.APIContext) *db.Repository { repo, err := db.GetRepositoryByName(c.Org.Team.OrgID, c.Params(":reponame")) if err != nil { - c.NotFoundOrServerError("GetRepositoryByName", errors.IsRepoNotExist, err) + c.NotFoundOrError(err, "get repository by name") return nil } return repo @@ -25,7 +24,7 @@ func AddTeamRepository(c *context.APIContext) { return } if err := c.Org.Team.AddRepository(repo); err != nil { - c.ServerError("AddRepository", err) + c.Error(err, "add repository") return } @@ -38,7 +37,7 @@ func RemoveTeamRepository(c *context.APIContext) { return } if err := c.Org.Team.RemoveRepository(repo.ID); err != nil { - c.ServerError("RemoveRepository", err) + c.Error(err, "remove repository") return } diff --git a/internal/route/api/v1/admin/org_team.go b/internal/route/api/v1/admin/org_team.go index e81b6b1b9..953f0936f 100644 --- a/internal/route/api/v1/admin/org_team.go +++ b/internal/route/api/v1/admin/org_team.go @@ -5,14 +5,14 @@ package admin import ( - convert2 "gogs.io/gogs/internal/route/api/v1/convert" - user2 "gogs.io/gogs/internal/route/api/v1/user" "net/http" api "github.com/gogs/go-gogs-client" "gogs.io/gogs/internal/context" "gogs.io/gogs/internal/db" + "gogs.io/gogs/internal/route/api/v1/convert" + "gogs.io/gogs/internal/route/api/v1/user" ) func CreateTeam(c *context.APIContext, form api.CreateTeamOption) { @@ -24,23 +24,23 @@ func CreateTeam(c *context.APIContext, form api.CreateTeamOption) { } if err := db.NewTeam(team); err != nil { if db.IsErrTeamAlreadyExist(err) { - c.Error(http.StatusUnprocessableEntity, "", err) + c.ErrorStatus(http.StatusUnprocessableEntity, err) } else { - c.ServerError("NewTeam", err) + c.Error(err, "new team") } return } - c.JSON(http.StatusCreated, convert2.ToTeam(team)) + c.JSON(http.StatusCreated, convert.ToTeam(team)) } func AddTeamMember(c *context.APIContext) { - u := user2.GetUserByParams(c) + u := user.GetUserByParams(c) if c.Written() { return } if err := c.Org.Team.AddMember(u.ID); err != nil { - c.ServerError("AddMember", err) + c.Error(err, "add member") return } @@ -48,13 +48,13 @@ func AddTeamMember(c *context.APIContext) { } func RemoveTeamMember(c *context.APIContext) { - u := user2.GetUserByParams(c) + u := user.GetUserByParams(c) if c.Written() { return } if err := c.Org.Team.RemoveMember(u.ID); err != nil { - c.ServerError("RemoveMember", err) + c.Error(err, "remove member") return } diff --git a/internal/route/api/v1/admin/repo.go b/internal/route/api/v1/admin/repo.go index 68a262976..229310367 100644 --- a/internal/route/api/v1/admin/repo.go +++ b/internal/route/api/v1/admin/repo.go @@ -6,17 +6,17 @@ package admin import ( api "github.com/gogs/go-gogs-client" - repo2 "gogs.io/gogs/internal/route/api/v1/repo" - user2 "gogs.io/gogs/internal/route/api/v1/user" "gogs.io/gogs/internal/context" + "gogs.io/gogs/internal/route/api/v1/repo" + "gogs.io/gogs/internal/route/api/v1/user" ) func CreateRepo(c *context.APIContext, form api.CreateRepoOption) { - owner := user2.GetUserByParams(c) + owner := user.GetUserByParams(c) if c.Written() { return } - repo2.CreateUserRepo(c, owner, form) + repo.CreateUserRepo(c, owner, form) } diff --git a/internal/route/api/v1/admin/user.go b/internal/route/api/v1/admin/user.go index 00b13bfda..c339edd24 100644 --- a/internal/route/api/v1/admin/user.go +++ b/internal/route/api/v1/admin/user.go @@ -7,9 +7,8 @@ package admin import ( "net/http" - log "unknwon.dev/clog/v2" - api "github.com/gogs/go-gogs-client" + log "unknwon.dev/clog/v2" "gogs.io/gogs/internal/conf" "gogs.io/gogs/internal/context" @@ -27,9 +26,9 @@ func parseLoginSource(c *context.APIContext, u *db.User, sourceID int64, loginNa source, err := db.GetLoginSourceByID(sourceID) if err != nil { if errors.IsLoginSourceNotExist(err) { - c.Error(http.StatusUnprocessableEntity, "", err) + c.ErrorStatus(http.StatusUnprocessableEntity, err) } else { - c.ServerError("GetLoginSourceByID", err) + c.Error(err, "get login source by ID") } return } @@ -59,9 +58,9 @@ func CreateUser(c *context.APIContext, form api.CreateUserOption) { db.IsErrEmailAlreadyUsed(err) || db.IsErrNameReserved(err) || db.IsErrNamePatternNotAllowed(err) { - c.Error(http.StatusUnprocessableEntity, "", err) + c.ErrorStatus(http.StatusUnprocessableEntity, err) } else { - c.ServerError("CreateUser", err) + c.Error(err, "create user") } return } @@ -90,7 +89,7 @@ func EditUser(c *context.APIContext, form api.EditUserOption) { u.Passwd = form.Password var err error if u.Salt, err = db.GetUserSalt(); err != nil { - c.ServerError("GetUserSalt", err) + c.Error(err, "get user salt") return } u.EncodePasswd() @@ -119,9 +118,9 @@ func EditUser(c *context.APIContext, form api.EditUserOption) { if err := db.UpdateUser(u); err != nil { if db.IsErrEmailAlreadyUsed(err) { - c.Error(http.StatusUnprocessableEntity, "", err) + c.ErrorStatus(http.StatusUnprocessableEntity, err) } else { - c.ServerError("UpdateUser", err) + c.Error(err, "update user") } return } @@ -139,9 +138,9 @@ func DeleteUser(c *context.APIContext) { if err := db.DeleteUser(u); err != nil { if db.IsErrUserOwnRepos(err) || db.IsErrUserHasOrgs(err) { - c.Error(http.StatusUnprocessableEntity, "", err) + c.ErrorStatus(http.StatusUnprocessableEntity, err) } else { - c.ServerError("DeleteUser", err) + c.Error(err, "delete user") } return } diff --git a/internal/route/api/v1/api.go b/internal/route/api/v1/api.go index 983940492..b56d640b2 100644 --- a/internal/route/api/v1/api.go +++ b/internal/route/api/v1/api.go @@ -15,7 +15,6 @@ import ( "gogs.io/gogs/internal/context" "gogs.io/gogs/internal/db" - "gogs.io/gogs/internal/db/errors" "gogs.io/gogs/internal/form" "gogs.io/gogs/internal/route/api/v1/admin" "gogs.io/gogs/internal/route/api/v1/misc" @@ -40,7 +39,7 @@ func repoAssignment() macaron.Handler { } else { owner, err = db.GetUserByName(username) if err != nil { - c.NotFoundOrServerError("GetUserByName", errors.IsUserNotExist, err) + c.NotFoundOrError(err, "get user by name") return } } @@ -48,10 +47,10 @@ func repoAssignment() macaron.Handler { r, err := db.GetRepositoryByName(owner.ID, reponame) if err != nil { - c.NotFoundOrServerError("GetRepositoryByName", errors.IsRepoNotExist, err) + c.NotFoundOrError(err, "get repository by name") return } else if err = r.GetOwner(); err != nil { - c.ServerError("GetOwner", err) + c.Error(err, "get owner") return } @@ -60,7 +59,7 @@ func repoAssignment() macaron.Handler { } else { mode, err := db.UserAccessMode(c.UserID(), r) if err != nil { - c.ServerError("UserAccessMode", err) + c.Error(err, "get user access mode") return } c.Repo.AccessMode = mode @@ -94,7 +93,7 @@ func orgAssignment(args ...bool) macaron.Handler { if assignOrg { c.Org.Organization, err = db.GetUserByName(c.Params(":orgname")) if err != nil { - c.NotFoundOrServerError("GetUserByName", errors.IsUserNotExist, err) + c.NotFoundOrError(err, "get organization by name") return } } @@ -102,7 +101,7 @@ func orgAssignment(args ...bool) macaron.Handler { if assignTeam { c.Org.Team, err = db.GetTeamByID(c.ParamsInt64(":teamid")) if err != nil { - c.NotFoundOrServerError("GetTeamByID", errors.IsTeamNotExist, err) + c.NotFoundOrError(err, "get team by ID") return } } @@ -113,7 +112,7 @@ func orgAssignment(args ...bool) macaron.Handler { func reqToken() macaron.Handler { return func(c *context.Context) { if !c.IsTokenAuth { - c.Error(http.StatusUnauthorized) + c.Status(http.StatusUnauthorized) return } } @@ -123,7 +122,7 @@ func reqToken() macaron.Handler { func reqBasicAuth() macaron.Handler { return func(c *context.Context) { if !c.IsBasicAuth { - c.Error(http.StatusUnauthorized) + c.Status(http.StatusUnauthorized) return } } @@ -133,7 +132,7 @@ func reqBasicAuth() macaron.Handler { func reqAdmin() macaron.Handler { return func(c *context.Context) { if !c.IsLogged || !c.User.IsAdmin { - c.Error(http.StatusForbidden) + c.Status(http.StatusForbidden) return } } @@ -143,7 +142,7 @@ func reqAdmin() macaron.Handler { func reqRepoWriter() macaron.Handler { return func(c *context.Context) { if !c.Repo.IsWriter() { - c.Error(http.StatusForbidden) + c.Status(http.StatusForbidden) return } } @@ -153,7 +152,7 @@ func reqRepoWriter() macaron.Handler { func reqRepoAdmin() macaron.Handler { return func(c *context.Context) { if !c.Repo.IsAdmin() { - c.Error(http.StatusForbidden) + c.Status(http.StatusForbidden) return } } diff --git a/internal/route/api/v1/misc/markdown.go b/internal/route/api/v1/misc/markdown.go index 10889d3b6..be92a1648 100644 --- a/internal/route/api/v1/misc/markdown.go +++ b/internal/route/api/v1/misc/markdown.go @@ -5,8 +5,6 @@ package misc import ( - "net/http" - api "github.com/gogs/go-gogs-client" "gogs.io/gogs/internal/context" @@ -14,11 +12,6 @@ import ( ) func Markdown(c *context.APIContext, form api.MarkdownOption) { - if c.HasApiError() { - c.Error(http.StatusUnprocessableEntity, "", c.GetErrMsg()) - return - } - if len(form.Text) == 0 { _, _ = c.Write([]byte("")) return @@ -30,7 +23,7 @@ func Markdown(c *context.APIContext, form api.MarkdownOption) { func MarkdownRaw(c *context.APIContext) { body, err := c.Req.Body().Bytes() if err != nil { - c.Error(http.StatusUnprocessableEntity, "", err) + c.Error(err, "read body") return } _, _ = c.Write(markup.SanitizeBytes(markup.RawMarkdown(body, ""))) diff --git a/internal/route/api/v1/org/org.go b/internal/route/api/v1/org/org.go index dbb3e4dd3..0bcefbe4f 100644 --- a/internal/route/api/v1/org/org.go +++ b/internal/route/api/v1/org/org.go @@ -5,14 +5,14 @@ package org import ( - convert2 "gogs.io/gogs/internal/route/api/v1/convert" - user2 "gogs.io/gogs/internal/route/api/v1/user" "net/http" api "github.com/gogs/go-gogs-client" "gogs.io/gogs/internal/context" "gogs.io/gogs/internal/db" + "gogs.io/gogs/internal/route/api/v1/convert" + "gogs.io/gogs/internal/route/api/v1/user" ) func CreateOrgForUser(c *context.APIContext, apiForm api.CreateOrgOption, user *db.User) { @@ -33,25 +33,25 @@ func CreateOrgForUser(c *context.APIContext, apiForm api.CreateOrgOption, user * if db.IsErrUserAlreadyExist(err) || db.IsErrNameReserved(err) || db.IsErrNamePatternNotAllowed(err) { - c.Error(http.StatusUnprocessableEntity, "", err) + c.ErrorStatus(http.StatusUnprocessableEntity, err) } else { - c.ServerError("CreateOrganization", err) + c.Error(err, "create organization") } return } - c.JSON(201, convert2.ToOrganization(org)) + c.JSON(201, convert.ToOrganization(org)) } func listUserOrgs(c *context.APIContext, u *db.User, all bool) { if err := u.GetOrganizations(all); err != nil { - c.ServerError("GetOrganizations", err) + c.Error(err, "get organization") return } apiOrgs := make([]*api.Organization, len(u.Orgs)) for i := range u.Orgs { - apiOrgs[i] = convert2.ToOrganization(u.Orgs[i]) + apiOrgs[i] = convert.ToOrganization(u.Orgs[i]) } c.JSONSuccess(&apiOrgs) } @@ -65,7 +65,7 @@ func CreateMyOrg(c *context.APIContext, apiForm api.CreateOrgOption) { } func ListUserOrgs(c *context.APIContext) { - u := user2.GetUserByParams(c) + u := user.GetUserByParams(c) if c.Written() { return } @@ -73,7 +73,7 @@ func ListUserOrgs(c *context.APIContext) { } func Get(c *context.APIContext) { - c.JSONSuccess(convert2.ToOrganization(c.Org.Organization)) + c.JSONSuccess(convert.ToOrganization(c.Org.Organization)) } func Edit(c *context.APIContext, form api.EditOrgOption) { @@ -88,9 +88,9 @@ func Edit(c *context.APIContext, form api.EditOrgOption) { org.Website = form.Website org.Location = form.Location if err := db.UpdateUser(org); err != nil { - c.ServerError("UpdateUser", err) + c.Error(err, "update user") return } - c.JSONSuccess(convert2.ToOrganization(org)) + c.JSONSuccess(convert.ToOrganization(org)) } diff --git a/internal/route/api/v1/org/team.go b/internal/route/api/v1/org/team.go index 528e6183c..75a6ae112 100644 --- a/internal/route/api/v1/org/team.go +++ b/internal/route/api/v1/org/team.go @@ -6,21 +6,21 @@ package org import ( api "github.com/gogs/go-gogs-client" - convert2 "gogs.io/gogs/internal/route/api/v1/convert" "gogs.io/gogs/internal/context" + "gogs.io/gogs/internal/route/api/v1/convert" ) func ListTeams(c *context.APIContext) { org := c.Org.Organization if err := org.GetTeams(); err != nil { - c.Error(500, "GetTeams", err) + c.Error(err, "get teams") return } apiTeams := make([]*api.Team, len(org.Teams)) for i := range org.Teams { - apiTeams[i] = convert2.ToTeam(org.Teams[i]) + apiTeams[i] = convert.ToTeam(org.Teams[i]) } - c.JSON(200, apiTeams) + c.JSONSuccess(apiTeams) } diff --git a/internal/route/api/v1/repo/branch.go b/internal/route/api/v1/repo/branch.go index b90d1e245..3ddf62cc6 100644 --- a/internal/route/api/v1/repo/branch.go +++ b/internal/route/api/v1/repo/branch.go @@ -6,38 +6,33 @@ package repo import ( api "github.com/gogs/go-gogs-client" - convert2 "gogs.io/gogs/internal/route/api/v1/convert" "gogs.io/gogs/internal/context" - "gogs.io/gogs/internal/db/errors" + "gogs.io/gogs/internal/route/api/v1/convert" ) // https://github.com/gogs/go-gogs-client/wiki/Repositories#get-branch func GetBranch(c *context.APIContext) { branch, err := c.Repo.Repository.GetBranch(c.Params("*")) if err != nil { - if errors.IsErrBranchNotExist(err) { - c.Error(404, "GetBranch", err) - } else { - c.Error(500, "GetBranch", err) - } + c.NotFoundOrError(err, "get branch") return } commit, err := branch.GetCommit() if err != nil { - c.Error(500, "GetCommit", err) + c.Error(err, "get commit") return } - c.JSON(200, convert2.ToBranch(branch, commit)) + c.JSONSuccess( convert.ToBranch(branch, commit)) } // https://github.com/gogs/go-gogs-client/wiki/Repositories#list-branches func ListBranches(c *context.APIContext) { branches, err := c.Repo.Repository.GetBranches() if err != nil { - c.Error(500, "GetBranches", err) + c.Error(err, "get branches") return } @@ -45,11 +40,11 @@ func ListBranches(c *context.APIContext) { for i := range branches { commit, err := branches[i].GetCommit() if err != nil { - c.Error(500, "GetCommit", err) + c.Error(err, "get commit") return } - apiBranches[i] = convert2.ToBranch(branches[i], commit) + apiBranches[i] = convert.ToBranch(branches[i], commit) } - c.JSON(200, &apiBranches) + c.JSONSuccess( &apiBranches) } diff --git a/internal/route/api/v1/repo/collaborators.go b/internal/route/api/v1/repo/collaborators.go index e8f748484..c9d2ff301 100644 --- a/internal/route/api/v1/repo/collaborators.go +++ b/internal/route/api/v1/repo/collaborators.go @@ -5,17 +5,18 @@ package repo import ( + "net/http" + api "github.com/gogs/go-gogs-client" "gogs.io/gogs/internal/context" "gogs.io/gogs/internal/db" - "gogs.io/gogs/internal/db/errors" ) func ListCollaborators(c *context.APIContext) { collaborators, err := c.Repo.Repository.GetCollaborators() if err != nil { - c.ServerError("GetCollaborators", err) + c.Error(err, "get collaborators") return } @@ -29,62 +30,62 @@ func ListCollaborators(c *context.APIContext) { func AddCollaborator(c *context.APIContext, form api.AddCollaboratorOption) { collaborator, err := db.GetUserByName(c.Params(":collaborator")) if err != nil { - if errors.IsUserNotExist(err) { - c.Error(422, "", err) + if db.IsErrUserNotExist(err) { + c.Status(http.StatusUnprocessableEntity) } else { - c.Error(500, "GetUserByName", err) + c.Error(err, "get user by name") } return } if err := c.Repo.Repository.AddCollaborator(collaborator); err != nil { - c.Error(500, "AddCollaborator", err) + c.Error(err, "add collaborator") return } if form.Permission != nil { if err := c.Repo.Repository.ChangeCollaborationAccessMode(collaborator.ID, db.ParseAccessMode(*form.Permission)); err != nil { - c.Error(500, "ChangeCollaborationAccessMode", err) + c.Error(err, "change collaboration access mode") return } } - c.Status(204) + c.NoContent() } func IsCollaborator(c *context.APIContext) { collaborator, err := db.GetUserByName(c.Params(":collaborator")) if err != nil { - if errors.IsUserNotExist(err) { - c.Error(422, "", err) + if db.IsErrUserNotExist(err) { + c.Status(http.StatusUnprocessableEntity) } else { - c.Error(500, "GetUserByName", err) + c.Error(err, "get user by name") } return } if !c.Repo.Repository.IsCollaborator(collaborator.ID) { - c.Status(404) + c.NotFound() } else { - c.Status(204) + c.NoContent() } } func DeleteCollaborator(c *context.APIContext) { collaborator, err := db.GetUserByName(c.Params(":collaborator")) if err != nil { - if errors.IsUserNotExist(err) { - c.Error(422, "", err) + if db.IsErrUserNotExist(err) { + c.Status(http.StatusUnprocessableEntity) } else { - c.Error(500, "GetUserByName", err) + c.Error(err, "get user by name") } return } if err := c.Repo.Repository.DeleteCollaboration(collaborator.ID); err != nil { - c.Error(500, "DeleteCollaboration", err) + c.Error(err, "delete collaboration") return } - c.Status(204) + c.NoContent() } diff --git a/internal/route/api/v1/repo/commits.go b/internal/route/api/v1/repo/commits.go index b39030535..ea6590d7d 100644 --- a/internal/route/api/v1/repo/commits.go +++ b/internal/route/api/v1/repo/commits.go @@ -15,7 +15,6 @@ import ( "gogs.io/gogs/internal/conf" "gogs.io/gogs/internal/context" "gogs.io/gogs/internal/db" - "gogs.io/gogs/internal/db/errors" "gogs.io/gogs/internal/gitutil" ) @@ -28,20 +27,20 @@ func GetSingleCommit(c *context.APIContext) { gitRepo, err := git.Open(c.Repo.Repository.RepoPath()) if err != nil { - c.ServerError("open repository", err) + c.Error(err, "open repository") return } commit, err := gitRepo.CatFileCommit(c.Params(":sha")) if err != nil { - c.NotFoundOrServerError("get commit", gitutil.IsErrRevisionNotExist, err) + c.NotFoundOrError(gitutil.NewError(err), "get commit") return } // Retrieve author and committer information var apiAuthor, apiCommitter *api.User author, err := db.GetUserByEmail(commit.Author.Email) - if err != nil && !errors.IsUserNotExist(err) { - c.ServerError("Get user by author email", err) + if err != nil && !db.IsErrUserNotExist(err) { + c.Error(err, "get user by author email") return } else if err == nil { apiAuthor = author.APIFormat() @@ -51,8 +50,8 @@ func GetSingleCommit(c *context.APIContext) { apiCommitter = apiAuthor } else { committer, err := db.GetUserByEmail(commit.Committer.Email) - if err != nil && !errors.IsUserNotExist(err) { - c.ServerError("Get user by committer email", err) + if err != nil && !db.IsErrUserNotExist(err) { + c.Error(err, "get user by committer email") return } else if err == nil { apiCommitter = committer.APIFormat() @@ -102,7 +101,7 @@ func GetSingleCommit(c *context.APIContext) { func GetReferenceSHA(c *context.APIContext) { gitRepo, err := git.Open(c.Repo.Repository.RepoPath()) if err != nil { - c.ServerError("open repository", err) + c.Error(err, "open repository") return } @@ -132,8 +131,8 @@ func GetReferenceSHA(c *context.APIContext) { sha, err = gitRepo.TagCommitID(ref) } if err != nil { - c.NotFoundOrServerError("get reference commit ID", gitutil.IsErrRevisionNotExist, err) + c.NotFoundOrError(gitutil.NewError(err), "get reference commit ID") return } - c.PlainText(http.StatusOK, []byte(sha)) + c.PlainText(http.StatusOK, sha) } diff --git a/internal/route/api/v1/repo/contents.go b/internal/route/api/v1/repo/contents.go index e5a9277db..463bbb221 100644 --- a/internal/route/api/v1/repo/contents.go +++ b/internal/route/api/v1/repo/contents.go @@ -19,7 +19,7 @@ import ( func GetContents(c *context.APIContext) { gitRepo, err := git.Open(c.Repo.Repository.RepoPath()) if err != nil { - c.ServerError("open repository", err) + c.Error(err, "open repository") return } @@ -30,14 +30,14 @@ func GetContents(c *context.APIContext) { commit, err := gitRepo.CatFileCommit(ref) if err != nil { - c.NotFoundOrServerError("get commit", gitutil.IsErrRevisionNotExist, err) + c.NotFoundOrError(gitutil.NewError(err), "get commit") return } treePath := c.Params("*") entry, err := commit.TreeEntry(treePath) if err != nil { - c.NotFoundOrServerError("get tree entry", gitutil.IsErrRevisionNotExist, err) + c.NotFoundOrError(gitutil.NewError(err), "get tree entry") return } @@ -137,13 +137,13 @@ func GetContents(c *context.APIContext) { // The entry is a directory dir, err := gitRepo.LsTree(entry.ID().String()) if err != nil { - c.NotFoundOrServerError("get tree", gitutil.IsErrRevisionNotExist, err) + c.NotFoundOrError(gitutil.NewError(err), "get tree") return } entries, err := dir.Entries() if err != nil { - c.NotFoundOrServerError("list entries", gitutil.IsErrRevisionNotExist, err) + c.NotFoundOrError(gitutil.NewError(err), "list entries") return } diff --git a/internal/route/api/v1/repo/file.go b/internal/route/api/v1/repo/file.go index 414d02852..999a2a479 100644 --- a/internal/route/api/v1/repo/file.go +++ b/internal/route/api/v1/repo/file.go @@ -26,11 +26,11 @@ func GetRawFile(c *context.APIContext) { blob, err := c.Repo.Commit.Blob(c.Repo.TreePath) if err != nil { - c.NotFoundOrServerError("get blob", gitutil.IsErrRevisionNotExist, err) + c.NotFoundOrError(gitutil.NewError(err), "get blob") return } if err = repo.ServeBlob(c.Context, blob); err != nil { - c.ServerError("ServeBlob", err) + c.Error(err, "serve blob") } } @@ -38,7 +38,7 @@ func GetArchive(c *context.APIContext) { repoPath := db.RepoPath(c.Params(":username"), c.Params(":reponame")) gitRepo, err := git.Open(repoPath) if err != nil { - c.ServerError("open repository", err) + c.Error(err, "open repository") return } c.Repo.GitRepo = gitRepo @@ -49,14 +49,14 @@ func GetArchive(c *context.APIContext) { func GetEditorconfig(c *context.APIContext) { ec, err := c.Repo.Editorconfig() if err != nil { - c.NotFoundOrServerError("get .editorconfig", gitutil.IsErrRevisionNotExist, err) + c.NotFoundOrError(gitutil.NewError(err), "get .editorconfig") return } fileName := c.Params("filename") def, err := ec.GetDefinitionForFilename(fileName) if err != nil { - c.ServerError("get definition for filename", err) + c.Error(err, "get definition for filename") return } if def == nil { diff --git a/internal/route/api/v1/repo/hook.go b/internal/route/api/v1/repo/hook.go index 060d2049d..d57301657 100644 --- a/internal/route/api/v1/repo/hook.go +++ b/internal/route/api/v1/repo/hook.go @@ -5,46 +5,47 @@ package repo import ( - "github.com/json-iterator/go" - "github.com/unknwon/com" - convert2 "gogs.io/gogs/internal/route/api/v1/convert" + "net/http" api "github.com/gogs/go-gogs-client" + "github.com/json-iterator/go" + "github.com/pkg/errors" + "github.com/unknwon/com" "gogs.io/gogs/internal/context" "gogs.io/gogs/internal/db" - "gogs.io/gogs/internal/db/errors" + "gogs.io/gogs/internal/route/api/v1/convert" ) // https://github.com/gogs/go-gogs-client/wiki/Repositories#list-hooks func ListHooks(c *context.APIContext) { hooks, err := db.GetWebhooksByRepoID(c.Repo.Repository.ID) if err != nil { - c.Error(500, "GetWebhooksByRepoID", err) + c.Errorf(err, "get webhooks by repository ID") return } apiHooks := make([]*api.Hook, len(hooks)) for i := range hooks { - apiHooks[i] = convert2.ToHook(c.Repo.RepoLink, hooks[i]) + apiHooks[i] = convert.ToHook(c.Repo.RepoLink, hooks[i]) } - c.JSON(200, &apiHooks) + c.JSONSuccess(&apiHooks) } // https://github.com/gogs/go-gogs-client/wiki/Repositories#create-a-hook func CreateHook(c *context.APIContext, form api.CreateHookOption) { if !db.IsValidHookTaskType(form.Type) { - c.Error(422, "", "Invalid hook type") + c.ErrorStatus(http.StatusUnprocessableEntity, errors.New("Invalid hook type.")) return } for _, name := range []string{"url", "content_type"} { if _, ok := form.Config[name]; !ok { - c.Error(422, "", "Missing config option: "+name) + c.ErrorStatus(http.StatusUnprocessableEntity, errors.New("Missing config option: "+name)) return } } if !db.IsValidHookContentType(form.Config["content_type"]) { - c.Error(422, "", "Invalid content type") + c.ErrorStatus(http.StatusUnprocessableEntity, errors.New("Invalid content type.")) return } @@ -75,7 +76,7 @@ func CreateHook(c *context.APIContext, form api.CreateHookOption) { if w.HookTaskType == db.SLACK { channel, ok := form.Config["channel"] if !ok { - c.Error(422, "", "Missing config option: channel") + c.ErrorStatus(http.StatusUnprocessableEntity, errors.New("Missing config option: channel")) return } meta, err := jsoniter.Marshal(&db.SlackMeta{ @@ -85,32 +86,28 @@ func CreateHook(c *context.APIContext, form api.CreateHookOption) { Color: form.Config["color"], }) if err != nil { - c.Error(500, "slack: JSON marshal failed", err) + c.Errorf(err, "marshal JSON") return } w.Meta = string(meta) } if err := w.UpdateEvent(); err != nil { - c.Error(500, "UpdateEvent", err) + c.Errorf(err, "update event") return } else if err := db.CreateWebhook(w); err != nil { - c.Error(500, "CreateWebhook", err) + c.Errorf(err, "create webhook") return } - c.JSON(201, convert2.ToHook(c.Repo.RepoLink, w)) + c.JSON(http.StatusCreated, convert.ToHook(c.Repo.RepoLink, w)) } // https://github.com/gogs/go-gogs-client/wiki/Repositories#edit-a-hook func EditHook(c *context.APIContext, form api.EditHookOption) { w, err := db.GetWebhookOfRepoByID(c.Repo.Repository.ID, c.ParamsInt64(":id")) if err != nil { - if errors.IsWebhookNotExist(err) { - c.Status(404) - } else { - c.Error(500, "GetWebhookOfRepoByID", err) - } + c.NotFoundOrError(err, "get webhook of repository by ID") return } @@ -120,7 +117,7 @@ func EditHook(c *context.APIContext, form api.EditHookOption) { } if ct, ok := form.Config["content_type"]; ok { if !db.IsValidHookContentType(ct) { - c.Error(422, "", "Invalid content type") + c.ErrorStatus(http.StatusUnprocessableEntity, errors.New("Invalid content type.")) return } w.ContentType = db.ToHookContentType(ct) @@ -135,7 +132,7 @@ func EditHook(c *context.APIContext, form api.EditHookOption) { Color: form.Config["color"], }) if err != nil { - c.Error(500, "slack: JSON marshal failed", err) + c.Errorf(err, "marshal JSON") return } w.Meta = string(meta) @@ -159,7 +156,7 @@ func EditHook(c *context.APIContext, form api.EditHookOption) { w.PullRequest = com.IsSliceContainsStr(form.Events, string(db.HOOK_EVENT_PULL_REQUEST)) w.Release = com.IsSliceContainsStr(form.Events, string(db.HOOK_EVENT_RELEASE)) if err = w.UpdateEvent(); err != nil { - c.Error(500, "UpdateEvent", err) + c.Errorf(err, "update event") return } @@ -168,18 +165,18 @@ func EditHook(c *context.APIContext, form api.EditHookOption) { } if err := db.UpdateWebhook(w); err != nil { - c.Error(500, "UpdateWebhook", err) + c.Errorf(err, "update webhook") return } - c.JSON(200, convert2.ToHook(c.Repo.RepoLink, w)) + c.JSONSuccess(convert.ToHook(c.Repo.RepoLink, w)) } func DeleteHook(c *context.APIContext) { if err := db.DeleteWebhookOfRepoByID(c.Repo.Repository.ID, c.ParamsInt64(":id")); err != nil { - c.Error(500, "DeleteWebhookByRepoID", err) + c.Errorf(err, "delete webhook of repository by ID") return } - c.Status(204) + c.NoContent() } diff --git a/internal/route/api/v1/repo/issue.go b/internal/route/api/v1/repo/issue.go index 39977f919..8a9f4b770 100644 --- a/internal/route/api/v1/repo/issue.go +++ b/internal/route/api/v1/repo/issue.go @@ -11,22 +11,21 @@ import ( api "github.com/gogs/go-gogs-client" + "gogs.io/gogs/internal/conf" "gogs.io/gogs/internal/context" "gogs.io/gogs/internal/db" - "gogs.io/gogs/internal/db/errors" - "gogs.io/gogs/internal/conf" ) func listIssues(c *context.APIContext, opts *db.IssuesOptions) { issues, err := db.Issues(opts) if err != nil { - c.ServerError("Issues", err) + c.Error(err, "list issues") return } count, err := db.IssuesCount(opts) if err != nil { - c.ServerError("IssuesCount", err) + c.Error(err, "count issues") return } @@ -34,7 +33,7 @@ func listIssues(c *context.APIContext, opts *db.IssuesOptions) { apiIssues := make([]*api.Issue, len(issues)) for i := range issues { if err = issues[i].LoadAttributes(); err != nil { - c.ServerError("LoadAttributes", err) + c.Error(err, "load attributes") return } apiIssues[i] = issues[i].APIFormat() @@ -67,7 +66,7 @@ func ListIssues(c *context.APIContext) { func GetIssue(c *context.APIContext) { issue, err := db.GetIssueByIndex(c.Repo.Repository.ID, c.ParamsInt64(":index")) if err != nil { - c.NotFoundOrServerError("GetIssueByIndex", errors.IsIssueNotExist, err) + c.NotFoundOrError(err, "get issue by index") return } c.JSONSuccess(issue.APIFormat()) @@ -86,10 +85,10 @@ func CreateIssue(c *context.APIContext, form api.CreateIssueOption) { if len(form.Assignee) > 0 { assignee, err := db.GetUserByName(form.Assignee) if err != nil { - if errors.IsUserNotExist(err) { - c.Error(http.StatusUnprocessableEntity, "", fmt.Sprintf("assignee does not exist: [name: %s]", form.Assignee)) + if db.IsErrUserNotExist(err) { + c.ErrorStatus(http.StatusUnprocessableEntity, fmt.Errorf("assignee does not exist: [name: %s]", form.Assignee)) } else { - c.ServerError("GetUserByName", err) + c.Error(err, "get user by name") } return } @@ -101,13 +100,13 @@ func CreateIssue(c *context.APIContext, form api.CreateIssueOption) { } if err := db.NewIssue(c.Repo.Repository, issue, form.Labels, nil); err != nil { - c.ServerError("NewIssue", err) + c.Error(err, "new issue") return } if form.Closed { if err := issue.ChangeStatus(c.User, c.Repo.Repository, true); err != nil { - c.ServerError("ChangeStatus", err) + c.Error(err, "change status to closed") return } } @@ -116,7 +115,7 @@ func CreateIssue(c *context.APIContext, form api.CreateIssueOption) { var err error issue, err = db.GetIssueByID(issue.ID) if err != nil { - c.ServerError("GetIssueByID", err) + c.Error(err, "get issue by ID") return } c.JSON(http.StatusCreated, issue.APIFormat()) @@ -125,7 +124,7 @@ func CreateIssue(c *context.APIContext, form api.CreateIssueOption) { func EditIssue(c *context.APIContext, form api.EditIssueOption) { issue, err := db.GetIssueByIndex(c.Repo.Repository.ID, c.ParamsInt64(":index")) if err != nil { - c.NotFoundOrServerError("GetIssueByIndex", errors.IsIssueNotExist, err) + c.NotFoundOrError(err, "get issue by index") return } @@ -148,10 +147,10 @@ func EditIssue(c *context.APIContext, form api.EditIssueOption) { } else { assignee, err := db.GetUserByName(*form.Assignee) if err != nil { - if errors.IsUserNotExist(err) { - c.Error(http.StatusUnprocessableEntity, "", fmt.Sprintf("assignee does not exist: [name: %s]", *form.Assignee)) + if db.IsErrUserNotExist(err) { + c.ErrorStatus(http.StatusUnprocessableEntity, fmt.Errorf("assignee does not exist: [name: %s]", *form.Assignee)) } else { - c.ServerError("GetUserByName", err) + c.Error(err, "get user by name") } return } @@ -159,7 +158,7 @@ func EditIssue(c *context.APIContext, form api.EditIssueOption) { } if err = db.UpdateIssueUserByAssignee(issue); err != nil { - c.ServerError("UpdateIssueUserByAssignee", err) + c.Error(err, "update issue user by assignee") return } } @@ -168,18 +167,18 @@ func EditIssue(c *context.APIContext, form api.EditIssueOption) { oldMilestoneID := issue.MilestoneID issue.MilestoneID = *form.Milestone if err = db.ChangeMilestoneAssign(c.User, issue, oldMilestoneID); err != nil { - c.ServerError("ChangeMilestoneAssign", err) + c.Error(err, "change milestone assign") return } } if err = db.UpdateIssue(issue); err != nil { - c.ServerError("UpdateIssue", err) + c.Error(err, "update issue") return } if form.State != nil { if err = issue.ChangeStatus(c.User, c.Repo.Repository, api.STATE_CLOSED == api.StateType(*form.State)); err != nil { - c.ServerError("ChangeStatus", err) + c.Error(err, "change status") return } } @@ -187,7 +186,7 @@ func EditIssue(c *context.APIContext, form api.EditIssueOption) { // Refetch from database to assign some automatic values issue, err = db.GetIssueByID(issue.ID) if err != nil { - c.ServerError("GetIssueByID", err) + c.Error(err, "get issue by ID") return } c.JSON(http.StatusCreated, issue.APIFormat()) diff --git a/internal/route/api/v1/repo/issue_comment.go b/internal/route/api/v1/repo/issue_comment.go index 4f86e13b6..a309cc806 100644 --- a/internal/route/api/v1/repo/issue_comment.go +++ b/internal/route/api/v1/repo/issue_comment.go @@ -19,7 +19,7 @@ func ListIssueComments(c *context.APIContext) { var err error since, err = time.Parse(time.RFC3339, c.Query("since")) if err != nil { - c.Error(http.StatusUnprocessableEntity, "", err) + c.ErrorStatus(http.StatusUnprocessableEntity, err) return } } @@ -27,13 +27,13 @@ func ListIssueComments(c *context.APIContext) { // comments,err:=db.GetCommentsByIssueIDSince(, since) issue, err := db.GetRawIssueByIndex(c.Repo.Repository.ID, c.ParamsInt64(":index")) if err != nil { - c.ServerError("GetRawIssueByIndex", err) + c.Error(err, "get raw issue by index") return } comments, err := db.GetCommentsByIssueIDSince(issue.ID, since.Unix()) if err != nil { - c.ServerError("GetCommentsByIssueIDSince", err) + c.Error(err, "get comments by issue ID") return } @@ -50,14 +50,14 @@ func ListRepoIssueComments(c *context.APIContext) { var err error since, err = time.Parse(time.RFC3339, c.Query("since")) if err != nil { - c.Error(http.StatusUnprocessableEntity, "", err) + c.ErrorStatus(http.StatusUnprocessableEntity, err) return } } comments, err := db.GetCommentsByRepoIDSince(c.Repo.Repository.ID, since.Unix()) if err != nil { - c.ServerError("GetCommentsByRepoIDSince", err) + c.Error(err, "get comments by repository ID") return } @@ -71,13 +71,13 @@ func ListRepoIssueComments(c *context.APIContext) { func CreateIssueComment(c *context.APIContext, form api.CreateIssueCommentOption) { issue, err := db.GetIssueByIndex(c.Repo.Repository.ID, c.ParamsInt64(":index")) if err != nil { - c.ServerError("GetIssueByIndex", err) + c.Error(err, "get issue by index") return } comment, err := db.CreateIssueComment(c.User, c.Repo.Repository, issue, form.Body, nil) if err != nil { - c.ServerError("CreateIssueComment", err) + c.Error(err, "create issue comment") return } @@ -87,7 +87,7 @@ func CreateIssueComment(c *context.APIContext, form api.CreateIssueCommentOption func EditIssueComment(c *context.APIContext, form api.EditIssueCommentOption) { comment, err := db.GetCommentByID(c.ParamsInt64(":id")) if err != nil { - c.NotFoundOrServerError("GetCommentByID", db.IsErrCommentNotExist, err) + c.NotFoundOrError(err, "get comment by ID") return } @@ -102,7 +102,7 @@ func EditIssueComment(c *context.APIContext, form api.EditIssueCommentOption) { oldContent := comment.Content comment.Content = form.Body if err := db.UpdateComment(c.User, comment, oldContent); err != nil { - c.ServerError("UpdateComment", err) + c.Error(err, "update comment") return } c.JSONSuccess(comment.APIFormat()) @@ -111,7 +111,7 @@ func EditIssueComment(c *context.APIContext, form api.EditIssueCommentOption) { func DeleteIssueComment(c *context.APIContext) { comment, err := db.GetCommentByID(c.ParamsInt64(":id")) if err != nil { - c.NotFoundOrServerError("GetCommentByID", db.IsErrCommentNotExist, err) + c.NotFoundOrError(err, "get comment by ID") return } @@ -124,7 +124,7 @@ func DeleteIssueComment(c *context.APIContext) { } if err = db.DeleteCommentByID(c.User, comment.ID); err != nil { - c.ServerError("DeleteCommentByID", err) + c.Error(err, "delete comment by ID") return } c.NoContent() diff --git a/internal/route/api/v1/repo/issue_label.go b/internal/route/api/v1/repo/issue_label.go index 7c8b7982c..92fff47d1 100644 --- a/internal/route/api/v1/repo/issue_label.go +++ b/internal/route/api/v1/repo/issue_label.go @@ -11,13 +11,12 @@ import ( "gogs.io/gogs/internal/context" "gogs.io/gogs/internal/db" - "gogs.io/gogs/internal/db/errors" ) func ListIssueLabels(c *context.APIContext) { issue, err := db.GetIssueByIndex(c.Repo.Repository.ID, c.ParamsInt64(":index")) if err != nil { - c.NotFoundOrServerError("GetIssueByIndex", errors.IsIssueNotExist, err) + c.NotFoundOrError(err, "get issue by index") return } @@ -31,24 +30,24 @@ func ListIssueLabels(c *context.APIContext) { func AddIssueLabels(c *context.APIContext, form api.IssueLabelsOption) { issue, err := db.GetIssueByIndex(c.Repo.Repository.ID, c.ParamsInt64(":index")) if err != nil { - c.NotFoundOrServerError("GetIssueByIndex", errors.IsIssueNotExist, err) + c.NotFoundOrError(err, "get issue by index") return } labels, err := db.GetLabelsInRepoByIDs(c.Repo.Repository.ID, form.Labels) if err != nil { - c.ServerError("GetLabelsInRepoByIDs", err) + c.Error(err, "get labels in repository by IDs") return } if err = issue.AddLabels(c.User, labels); err != nil { - c.ServerError("AddLabels", err) + c.Error(err, "add labels") return } labels, err = db.GetLabelsByIssueID(issue.ID) if err != nil { - c.ServerError("GetLabelsByIssueID", err) + c.Error(err, "get labels by issue ID") return } @@ -62,22 +61,22 @@ func AddIssueLabels(c *context.APIContext, form api.IssueLabelsOption) { func DeleteIssueLabel(c *context.APIContext) { issue, err := db.GetIssueByIndex(c.Repo.Repository.ID, c.ParamsInt64(":index")) if err != nil { - c.NotFoundOrServerError("GetIssueByIndex", errors.IsIssueNotExist, err) + c.NotFoundOrError(err, "get issue by index") return } label, err := db.GetLabelOfRepoByID(c.Repo.Repository.ID, c.ParamsInt64(":id")) if err != nil { if db.IsErrLabelNotExist(err) { - c.Error(http.StatusUnprocessableEntity, "", err) + c.ErrorStatus(http.StatusUnprocessableEntity, err) } else { - c.ServerError("GetLabelInRepoByID", err) + c.Error(err, "get label of repository by ID") } return } if err := db.DeleteIssueLabel(issue, label); err != nil { - c.ServerError("DeleteIssueLabel", err) + c.Error(err, "delete issue label") return } @@ -87,24 +86,24 @@ func DeleteIssueLabel(c *context.APIContext) { func ReplaceIssueLabels(c *context.APIContext, form api.IssueLabelsOption) { issue, err := db.GetIssueByIndex(c.Repo.Repository.ID, c.ParamsInt64(":index")) if err != nil { - c.NotFoundOrServerError("GetIssueByIndex", errors.IsIssueNotExist, err) + c.NotFoundOrError(err, "get issue by index") return } labels, err := db.GetLabelsInRepoByIDs(c.Repo.Repository.ID, form.Labels) if err != nil { - c.ServerError("GetLabelsInRepoByIDs", err) + c.Error(err, "get labels in repository by IDs") return } if err := issue.ReplaceLabels(labels); err != nil { - c.ServerError("ReplaceLabels", err) + c.Error(err, "replace labels") return } labels, err = db.GetLabelsByIssueID(issue.ID) if err != nil { - c.ServerError("GetLabelsByIssueID", err) + c.Error(err, "get labels by issue ID") return } @@ -118,12 +117,12 @@ func ReplaceIssueLabels(c *context.APIContext, form api.IssueLabelsOption) { func ClearIssueLabels(c *context.APIContext) { issue, err := db.GetIssueByIndex(c.Repo.Repository.ID, c.ParamsInt64(":index")) if err != nil { - c.NotFoundOrServerError("GetIssueByIndex", errors.IsIssueNotExist, err) + c.NotFoundOrError(err, "get issue by index") return } if err := issue.ClearLabels(c.User); err != nil { - c.ServerError("ClearLabels", err) + c.Error(err, "clear labels") return } diff --git a/internal/route/api/v1/repo/key.go b/internal/route/api/v1/repo/key.go index d8012933a..38c037b62 100644 --- a/internal/route/api/v1/repo/key.go +++ b/internal/route/api/v1/repo/key.go @@ -5,14 +5,15 @@ package repo import ( - "fmt" - convert2 "gogs.io/gogs/internal/route/api/v1/convert" + "net/http" api "github.com/gogs/go-gogs-client" + "github.com/pkg/errors" "gogs.io/gogs/internal/conf" "gogs.io/gogs/internal/context" "gogs.io/gogs/internal/db" + "gogs.io/gogs/internal/route/api/v1/convert" ) func composeDeployKeysAPILink(repoPath string) string { @@ -23,7 +24,7 @@ func composeDeployKeysAPILink(repoPath string) string { func ListDeployKeys(c *context.APIContext) { keys, err := db.ListDeployKeys(c.Repo.Repository.ID) if err != nil { - c.Error(500, "ListDeployKeys", err) + c.Error(err, "list deploy keys") return } @@ -31,52 +32,48 @@ func ListDeployKeys(c *context.APIContext) { apiKeys := make([]*api.DeployKey, len(keys)) for i := range keys { if err = keys[i].GetContent(); err != nil { - c.Error(500, "GetContent", err) + c.Error(err, "get content") return } - apiKeys[i] = convert2.ToDeployKey(apiLink, keys[i]) + apiKeys[i] = convert.ToDeployKey(apiLink, keys[i]) } - c.JSON(200, &apiKeys) + c.JSONSuccess(&apiKeys) } // https://github.com/gogs/go-gogs-client/wiki/Repositories-Deploy-Keys#get-a-deploy-key func GetDeployKey(c *context.APIContext) { key, err := db.GetDeployKeyByID(c.ParamsInt64(":id")) if err != nil { - if db.IsErrDeployKeyNotExist(err) { - c.Status(404) - } else { - c.Error(500, "GetDeployKeyByID", err) - } + c.NotFoundOrError(err, "get deploy key by ID") return } if err = key.GetContent(); err != nil { - c.Error(500, "GetContent", err) + c.Error(err, "get content") return } apiLink := composeDeployKeysAPILink(c.Repo.Owner.Name + "/" + c.Repo.Repository.Name) - c.JSON(200, convert2.ToDeployKey(apiLink, key)) + c.JSONSuccess(convert.ToDeployKey(apiLink, key)) } func HandleCheckKeyStringError(c *context.APIContext, err error) { if db.IsErrKeyUnableVerify(err) { - c.Error(422, "", "Unable to verify key content") + c.ErrorStatus(http.StatusUnprocessableEntity, errors.New("Unable to verify key content")) } else { - c.Error(422, "", fmt.Errorf("Invalid key content: %v", err)) + c.ErrorStatus(http.StatusUnprocessableEntity, errors.Wrap(err, "Invalid key content: %v")) } } func HandleAddKeyError(c *context.APIContext, err error) { switch { case db.IsErrKeyAlreadyExist(err): - c.Error(422, "", "Key content has been used as non-deploy key") + c.ErrorStatus(http.StatusUnprocessableEntity, errors.New("Key content has been used as non-deploy key")) case db.IsErrKeyNameAlreadyUsed(err): - c.Error(422, "", "Key title has been used") + c.ErrorStatus(http.StatusUnprocessableEntity, errors.New("Key title has been used")) default: - c.Error(500, "AddKey", err) + c.Error(err, "add key") } } @@ -96,19 +93,19 @@ func CreateDeployKey(c *context.APIContext, form api.CreateKeyOption) { key.Content = content apiLink := composeDeployKeysAPILink(c.Repo.Owner.Name + "/" + c.Repo.Repository.Name) - c.JSON(201, convert2.ToDeployKey(apiLink, key)) + c.JSON(http.StatusCreated, convert.ToDeployKey(apiLink, key)) } // https://github.com/gogs/go-gogs-client/wiki/Repositories-Deploy-Keys#remove-a-deploy-key func DeleteDeploykey(c *context.APIContext) { if err := db.DeleteDeployKey(c.User, c.ParamsInt64(":id")); err != nil { if db.IsErrKeyAccessDenied(err) { - c.Error(403, "", "You do not have access to this key") + c.ErrorStatus(http.StatusForbidden, errors.New("You do not have access to this key")) } else { - c.Error(500, "DeleteDeployKey", err) + c.Error(err, "delete deploy key") } return } - c.Status(204) + c.NoContent() } diff --git a/internal/route/api/v1/repo/label.go b/internal/route/api/v1/repo/label.go index 9dd2d7d0f..69fe5399d 100644 --- a/internal/route/api/v1/repo/label.go +++ b/internal/route/api/v1/repo/label.go @@ -7,9 +7,8 @@ package repo import ( "net/http" - "github.com/unknwon/com" - api "github.com/gogs/go-gogs-client" + "github.com/unknwon/com" "gogs.io/gogs/internal/context" "gogs.io/gogs/internal/db" @@ -18,7 +17,7 @@ import ( func ListLabels(c *context.APIContext) { labels, err := db.GetLabelsByRepoID(c.Repo.Repository.ID) if err != nil { - c.ServerError("GetLabelsByRepoID", err) + c.Error(err, "get labels by repository ID") return } @@ -39,7 +38,7 @@ func GetLabel(c *context.APIContext) { label, err = db.GetLabelOfRepoByName(c.Repo.Repository.ID, idStr) } if err != nil { - c.NotFoundOrServerError("GetLabel", db.IsErrLabelNotExist, err) + c.NotFoundOrError(err, "get label") return } @@ -53,7 +52,7 @@ func CreateLabel(c *context.APIContext, form api.CreateLabelOption) { RepoID: c.Repo.Repository.ID, } if err := db.NewLabels(label); err != nil { - c.ServerError("NewLabel", err) + c.Error(err, "new labels") return } c.JSON(http.StatusCreated, label.APIFormat()) @@ -62,7 +61,7 @@ func CreateLabel(c *context.APIContext, form api.CreateLabelOption) { func EditLabel(c *context.APIContext, form api.EditLabelOption) { label, err := db.GetLabelOfRepoByID(c.Repo.Repository.ID, c.ParamsInt64(":id")) if err != nil { - c.NotFoundOrServerError("GetLabelOfRepoByID", db.IsErrLabelNotExist, err) + c.NotFoundOrError(err, "get label of repository by ID") return } @@ -73,7 +72,7 @@ func EditLabel(c *context.APIContext, form api.EditLabelOption) { label.Color = *form.Color } if err := db.UpdateLabel(label); err != nil { - c.ServerError("UpdateLabel", err) + c.Error(err, "update label") return } c.JSONSuccess(label.APIFormat()) @@ -81,7 +80,7 @@ func EditLabel(c *context.APIContext, form api.EditLabelOption) { func DeleteLabel(c *context.APIContext) { if err := db.DeleteLabel(c.Repo.Repository.ID, c.ParamsInt64(":id")); err != nil { - c.ServerError("DeleteLabel", err) + c.Error(err, "delete label") return } diff --git a/internal/route/api/v1/repo/milestone.go b/internal/route/api/v1/repo/milestone.go index 6f5fea17a..a36a71d82 100644 --- a/internal/route/api/v1/repo/milestone.go +++ b/internal/route/api/v1/repo/milestone.go @@ -17,7 +17,7 @@ import ( func ListMilestones(c *context.APIContext) { milestones, err := db.GetMilestonesByRepoID(c.Repo.Repository.ID) if err != nil { - c.ServerError("GetMilestonesByRepoID", err) + c.Error(err, "get milestones by repository ID") return } @@ -31,7 +31,7 @@ func ListMilestones(c *context.APIContext) { func GetMilestone(c *context.APIContext) { milestone, err := db.GetMilestoneByRepoID(c.Repo.Repository.ID, c.ParamsInt64(":id")) if err != nil { - c.NotFoundOrServerError("GetMilestoneByRepoID", db.IsErrMilestoneNotExist, err) + c.NotFoundOrError(err, "get milestone by repository ID") return } c.JSONSuccess(milestone.APIFormat()) @@ -51,7 +51,7 @@ func CreateMilestone(c *context.APIContext, form api.CreateMilestoneOption) { } if err := db.NewMilestone(milestone); err != nil { - c.ServerError("NewMilestone", err) + c.Error(err, "new milestone") return } c.JSON(http.StatusCreated, milestone.APIFormat()) @@ -60,7 +60,7 @@ func CreateMilestone(c *context.APIContext, form api.CreateMilestoneOption) { func EditMilestone(c *context.APIContext, form api.EditMilestoneOption) { milestone, err := db.GetMilestoneByRepoID(c.Repo.Repository.ID, c.ParamsInt64(":id")) if err != nil { - c.NotFoundOrServerError("GetMilestoneByRepoID", db.IsErrMilestoneNotExist, err) + c.NotFoundOrError(err, "get milestone by repository ID") return } @@ -76,11 +76,11 @@ func EditMilestone(c *context.APIContext, form api.EditMilestoneOption) { if form.State != nil { if err = milestone.ChangeStatus(api.STATE_CLOSED == api.StateType(*form.State)); err != nil { - c.ServerError("ChangeStatus", err) + c.Error(err, "change status") return } } else if err = db.UpdateMilestone(milestone); err != nil { - c.ServerError("UpdateMilestone", err) + c.Error(err, "update milestone") return } @@ -89,7 +89,7 @@ func EditMilestone(c *context.APIContext, form api.EditMilestoneOption) { func DeleteMilestone(c *context.APIContext) { if err := db.DeleteMilestoneOfRepoByID(c.Repo.Repository.ID, c.ParamsInt64(":id")); err != nil { - c.ServerError("DeleteMilestoneByRepoID", err) + c.Error(err, "delete milestone of repository by ID") return } c.NoContent() diff --git a/internal/route/api/v1/repo/repo.go b/internal/route/api/v1/repo/repo.go index 7ea9a8701..e198dffcd 100644 --- a/internal/route/api/v1/repo/repo.go +++ b/internal/route/api/v1/repo/repo.go @@ -5,18 +5,16 @@ package repo import ( - "fmt" "net/http" "path" - log "unknwon.dev/clog/v2" - api "github.com/gogs/go-gogs-client" + "github.com/pkg/errors" + log "unknwon.dev/clog/v2" "gogs.io/gogs/internal/conf" "gogs.io/gogs/internal/context" "gogs.io/gogs/internal/db" - "gogs.io/gogs/internal/db/errors" "gogs.io/gogs/internal/form" "gogs.io/gogs/internal/route/api/v1/convert" ) @@ -81,7 +79,7 @@ func Search(c *context.APIContext) { func listUserRepositories(c *context.APIContext, username string) { user, err := db.GetUserByName(username) if err != nil { - c.NotFoundOrServerError("GetUserByName", errors.IsUserNotExist, err) + c.NotFoundOrError(err, "get user by name") return } @@ -99,12 +97,12 @@ func listUserRepositories(c *context.APIContext, username string) { }) } if err != nil { - c.ServerError("GetUserRepositories", err) + c.Error(err, "get user repositories") return } if err = db.RepositoryList(ownRepos).LoadAttributes(); err != nil { - c.ServerError("LoadAttributes(ownRepos)", err) + c.Error(err, "load attributes") return } @@ -120,7 +118,7 @@ func listUserRepositories(c *context.APIContext, username string) { accessibleRepos, err := user.GetRepositoryAccesses() if err != nil { - c.ServerError("GetRepositoryAccesses", err) + c.Error(err, "get repositories accesses") return } @@ -169,14 +167,14 @@ func CreateUserRepo(c *context.APIContext, owner *db.User, opt api.CreateRepoOpt if db.IsErrRepoAlreadyExist(err) || db.IsErrNameReserved(err) || db.IsErrNamePatternNotAllowed(err) { - c.Error(http.StatusUnprocessableEntity, "", err) + c.ErrorStatus(http.StatusUnprocessableEntity, err) } else { if repo != nil { if err = db.DeleteRepository(c.User.ID, repo.ID); err != nil { - log.Error("DeleteRepository: %v", err) + log.Error("Failed to delete repository: %v", err) } } - c.ServerError("CreateRepository", err) + c.Error(err, "create repository") } return } @@ -187,7 +185,7 @@ func CreateUserRepo(c *context.APIContext, owner *db.User, opt api.CreateRepoOpt func Create(c *context.APIContext, opt api.CreateRepoOption) { // Shouldn't reach this condition, but just in case. if c.User.IsOrganization() { - c.Error(http.StatusUnprocessableEntity, "", "not allowed creating repository for organization") + c.ErrorStatus(http.StatusUnprocessableEntity, errors.New("Not allowed to create repository for organization.")) return } CreateUserRepo(c, c.User, opt) @@ -196,12 +194,12 @@ func Create(c *context.APIContext, opt api.CreateRepoOption) { func CreateOrgRepo(c *context.APIContext, opt api.CreateRepoOption) { org, err := db.GetOrgByName(c.Params(":org")) if err != nil { - c.NotFoundOrServerError("GetOrgByName", errors.IsUserNotExist, err) + c.NotFoundOrError(err, "get organization by name") return } if !org.IsOwnedBy(c.User.ID) { - c.Error(http.StatusForbidden, "", "given user is not owner of organization") + c.ErrorStatus(http.StatusForbidden, errors.New("Given user is not owner of organization.")) return } CreateUserRepo(c, org, opt) @@ -214,28 +212,28 @@ func Migrate(c *context.APIContext, f form.MigrateRepo) { if f.Uid != ctxUser.ID { org, err := db.GetUserByID(f.Uid) if err != nil { - if errors.IsUserNotExist(err) { - c.Error(http.StatusUnprocessableEntity, "", err) + if db.IsErrUserNotExist(err) { + c.ErrorStatus(http.StatusUnprocessableEntity, err) } else { - c.Error(http.StatusInternalServerError, "GetUserByID", err) + c.Error(err, "get user by ID") } return } else if !org.IsOrganization() && !c.User.IsAdmin { - c.Error(http.StatusForbidden, "", "given user is not an organization") + c.ErrorStatus(http.StatusForbidden, errors.New("Given user is not an organization.")) return } ctxUser = org } if c.HasError() { - c.Error(http.StatusUnprocessableEntity, "", c.GetErrMsg()) + c.ErrorStatus(http.StatusUnprocessableEntity, errors.New(c.GetErrMsg())) return } if ctxUser.IsOrganization() && !c.User.IsAdmin { // Check ownership of organization. if !ctxUser.IsOwnedBy(c.User.ID) { - c.Error(http.StatusForbidden, "", "Given user is not owner of organization") + c.ErrorStatus(http.StatusForbidden, errors.New("Given user is not owner of organization.")) return } } @@ -246,16 +244,16 @@ func Migrate(c *context.APIContext, f form.MigrateRepo) { addrErr := err.(db.ErrInvalidCloneAddr) switch { case addrErr.IsURLError: - c.Error(http.StatusUnprocessableEntity, "", err) + c.ErrorStatus(http.StatusUnprocessableEntity, err) case addrErr.IsPermissionDenied: - c.Error(http.StatusUnprocessableEntity, "", "you are not allowed to import local repositories") + c.ErrorStatus(http.StatusUnprocessableEntity, errors.New("You are not allowed to import local repositories.")) case addrErr.IsInvalidPath: - c.Error(http.StatusUnprocessableEntity, "", "invalid local path, it does not exist or not a directory") + c.ErrorStatus(http.StatusUnprocessableEntity, errors.New("Invalid local path, it does not exist or not a directory.")) default: - c.ServerError("ParseRemoteAddr", fmt.Errorf("unknown error type (ErrInvalidCloneAddr): %v", err)) + c.Error(err, "unexpected error") } } else { - c.ServerError("ParseRemoteAddr", err) + c.Error(err, "parse remote address") } return } @@ -274,10 +272,10 @@ func Migrate(c *context.APIContext, f form.MigrateRepo) { } } - if errors.IsReachLimitOfRepo(err) { - c.Error(http.StatusUnprocessableEntity, "", err) + if db.IsErrReachLimitOfRepo(err) { + c.ErrorStatus(http.StatusUnprocessableEntity, err) } else { - c.ServerError("MigrateRepository", errors.New(db.HandleMirrorCredentials(err.Error(), true))) + c.Error(errors.New(db.HandleMirrorCredentials(err.Error(), true)), "migrate repository") } return } @@ -290,17 +288,17 @@ func Migrate(c *context.APIContext, f form.MigrateRepo) { func parseOwnerAndRepo(c *context.APIContext) (*db.User, *db.Repository) { owner, err := db.GetUserByName(c.Params(":username")) if err != nil { - if errors.IsUserNotExist(err) { - c.Error(http.StatusUnprocessableEntity, "", err) + if db.IsErrUserNotExist(err) { + c.ErrorStatus(http.StatusUnprocessableEntity, err) } else { - c.ServerError("GetUserByName", err) + c.Error(err, "get user by name") } return nil, nil } repo, err := db.GetRepositoryByName(owner.ID, c.Params(":reponame")) if err != nil { - c.NotFoundOrServerError("GetRepositoryByName", errors.IsRepoNotExist, err) + c.NotFoundOrError(err, "get repository by name") return nil, nil } @@ -327,12 +325,12 @@ func Delete(c *context.APIContext) { } if owner.IsOrganization() && !owner.IsOwnedBy(c.User.ID) { - c.Error(http.StatusForbidden, "", "given user is not owner of organization") + c.ErrorStatus(http.StatusForbidden, errors.New("Given user is not owner of organization.")) return } if err := db.DeleteRepository(owner.ID, repo.ID); err != nil { - c.ServerError("DeleteRepository", err) + c.Error(err, "delete repository") return } @@ -343,14 +341,14 @@ func Delete(c *context.APIContext) { func ListForks(c *context.APIContext) { forks, err := c.Repo.Repository.GetForks() if err != nil { - c.ServerError("GetForks", err) + c.Error(err, "get forks") return } apiForks := make([]*api.Repository, len(forks)) for i := range forks { if err := forks[i].GetOwner(); err != nil { - c.ServerError("GetOwner", err) + c.Error(err, "get owner") return } apiForks[i] = forks[i].APIFormat(&api.Permission{ @@ -386,7 +384,7 @@ func IssueTracker(c *context.APIContext, form api.EditIssueTrackerOption) { } if err := db.UpdateRepository(repo, false); err != nil { - c.ServerError("UpdateRepository", err) + c.Error(err, "update repository") return } diff --git a/internal/route/api/v1/repo/tree.go b/internal/route/api/v1/repo/tree.go index da9761135..cd51282bf 100644 --- a/internal/route/api/v1/repo/tree.go +++ b/internal/route/api/v1/repo/tree.go @@ -16,20 +16,20 @@ import ( func GetRepoGitTree(c *context.APIContext) { gitRepo, err := git.Open(c.Repo.Repository.RepoPath()) if err != nil { - c.ServerError("open repository", err) + c.Error(err, "open repository") return } sha := c.Params(":sha") tree, err := gitRepo.LsTree(sha) if err != nil { - c.NotFoundOrServerError("get tree", gitutil.IsErrRevisionNotExist, err) + c.NotFoundOrError(gitutil.NewError(err), "get tree") return } entries, err := tree.Entries() if err != nil { - c.ServerError("list entries", err) + c.Error(err, "list entries") return } diff --git a/internal/route/api/v1/user/app.go b/internal/route/api/v1/user/app.go index fdf11c095..99a422ccb 100644 --- a/internal/route/api/v1/user/app.go +++ b/internal/route/api/v1/user/app.go @@ -17,7 +17,7 @@ import ( func ListAccessTokens(c *context.APIContext) { tokens, err := db.ListAccessTokens(c.User.ID) if err != nil { - c.ServerError("ListAccessTokens", err) + c.Error(err, "list access tokens") return } @@ -35,9 +35,9 @@ func CreateAccessToken(c *context.APIContext, form api.CreateAccessTokenOption) } if err := db.NewAccessToken(t); err != nil { if errors.IsAccessTokenNameAlreadyExist(err) { - c.Error(http.StatusUnprocessableEntity, "", err) + c.ErrorStatus(http.StatusUnprocessableEntity, err) } else { - c.ServerError("NewAccessToken", err) + c.Error(err, "new access token") } return } diff --git a/internal/route/api/v1/user/email.go b/internal/route/api/v1/user/email.go index e211221cf..07fd4f8af 100644 --- a/internal/route/api/v1/user/email.go +++ b/internal/route/api/v1/user/email.go @@ -5,25 +5,26 @@ package user import ( - convert2 "gogs.io/gogs/internal/route/api/v1/convert" "net/http" api "github.com/gogs/go-gogs-client" + "github.com/pkg/errors" "gogs.io/gogs/internal/conf" "gogs.io/gogs/internal/context" "gogs.io/gogs/internal/db" + "gogs.io/gogs/internal/route/api/v1/convert" ) func ListEmails(c *context.APIContext) { emails, err := db.GetEmailAddresses(c.User.ID) if err != nil { - c.ServerError("GetEmailAddresses", err) + c.Error(err, "get email addresses") return } apiEmails := make([]*api.Email, len(emails)) for i := range emails { - apiEmails[i] = convert2.ToEmail(emails[i]) + apiEmails[i] = convert.ToEmail(emails[i]) } c.JSONSuccess(&apiEmails) } @@ -45,16 +46,16 @@ func AddEmail(c *context.APIContext, form api.CreateEmailOption) { if err := db.AddEmailAddresses(emails); err != nil { if db.IsErrEmailAlreadyUsed(err) { - c.Error(http.StatusUnprocessableEntity, "", "email address has been used: "+err.(db.ErrEmailAlreadyUsed).Email) + c.ErrorStatus(http.StatusUnprocessableEntity, errors.New("email address has been used: "+err.(db.ErrEmailAlreadyUsed).Email)) } else { - c.Error(http.StatusInternalServerError, "AddEmailAddresses", err) + c.Error(err, "add email addresses") } return } apiEmails := make([]*api.Email, len(emails)) for i := range emails { - apiEmails[i] = convert2.ToEmail(emails[i]) + apiEmails[i] = convert.ToEmail(emails[i]) } c.JSON(http.StatusCreated, &apiEmails) } @@ -74,7 +75,7 @@ func DeleteEmail(c *context.APIContext, form api.CreateEmailOption) { } if err := db.DeleteEmailAddresses(emails); err != nil { - c.Error(http.StatusInternalServerError, "DeleteEmailAddresses", err) + c.Error(err, "delete email addresses") return } c.NoContent() diff --git a/internal/route/api/v1/user/follower.go b/internal/route/api/v1/user/follower.go index 3a3d02987..c587547b2 100644 --- a/internal/route/api/v1/user/follower.go +++ b/internal/route/api/v1/user/follower.go @@ -22,7 +22,7 @@ func responseApiUsers(c *context.APIContext, users []*db.User) { func listUserFollowers(c *context.APIContext, u *db.User) { users, err := u.GetFollowers(c.QueryInt("page")) if err != nil { - c.ServerError("GetUserFollowers", err) + c.Error(err, "get followers") return } responseApiUsers(c, users) @@ -43,7 +43,7 @@ func ListFollowers(c *context.APIContext) { func listUserFollowing(c *context.APIContext, u *db.User) { users, err := u.GetFollowing(c.QueryInt("page")) if err != nil { - c.ServerError("GetFollowing", err) + c.Error(err, "get following") return } responseApiUsers(c, users) @@ -95,7 +95,7 @@ func Follow(c *context.APIContext) { return } if err := db.FollowUser(c.User.ID, target.ID); err != nil { - c.ServerError("FollowUser", err) + c.Error(err, "follow user") return } c.NoContent() @@ -107,7 +107,7 @@ func Unfollow(c *context.APIContext) { return } if err := db.UnfollowUser(c.User.ID, target.ID); err != nil { - c.ServerError("UnfollowUser", err) + c.Error(err, "unfollow user") return } c.NoContent() diff --git a/internal/route/api/v1/user/key.go b/internal/route/api/v1/user/key.go index 759f90084..0d8c4f166 100644 --- a/internal/route/api/v1/user/key.go +++ b/internal/route/api/v1/user/key.go @@ -5,21 +5,22 @@ package user import ( - api "github.com/gogs/go-gogs-client" - convert2 "gogs.io/gogs/internal/route/api/v1/convert" - repo2 "gogs.io/gogs/internal/route/api/v1/repo" "net/http" + api "github.com/gogs/go-gogs-client" + "github.com/pkg/errors" + "gogs.io/gogs/internal/conf" "gogs.io/gogs/internal/context" "gogs.io/gogs/internal/db" - "gogs.io/gogs/internal/db/errors" + "gogs.io/gogs/internal/route/api/v1/convert" + "gogs.io/gogs/internal/route/api/v1/repo" ) func GetUserByParamsName(c *context.APIContext, name string) *db.User { user, err := db.GetUserByName(c.Params(name)) if err != nil { - c.NotFoundOrServerError("GetUserByName", errors.IsUserNotExist, err) + c.NotFoundOrError(err, "get user by name") return nil } return user @@ -37,14 +38,14 @@ func composePublicKeysAPILink() string { func listPublicKeys(c *context.APIContext, uid int64) { keys, err := db.ListPublicKeys(uid) if err != nil { - c.ServerError("ListPublicKeys", err) + c.Error(err, "list public keys") return } apiLink := composePublicKeysAPILink() apiKeys := make([]*api.PublicKey, len(keys)) for i := range keys { - apiKeys[i] = convert2.ToPublicKey(apiLink, keys[i]) + apiKeys[i] = convert.ToPublicKey(apiLink, keys[i]) } c.JSONSuccess(&apiKeys) @@ -65,29 +66,29 @@ func ListPublicKeys(c *context.APIContext) { func GetPublicKey(c *context.APIContext) { key, err := db.GetPublicKeyByID(c.ParamsInt64(":id")) if err != nil { - c.NotFoundOrServerError("GetPublicKeyByID", db.IsErrKeyNotExist, err) + c.NotFoundOrError(err, "get public key by ID") return } apiLink := composePublicKeysAPILink() - c.JSONSuccess(convert2.ToPublicKey(apiLink, key)) + c.JSONSuccess(convert.ToPublicKey(apiLink, key)) } // CreateUserPublicKey creates new public key to given user by ID. func CreateUserPublicKey(c *context.APIContext, form api.CreateKeyOption, uid int64) { content, err := db.CheckPublicKeyString(form.Key) if err != nil { - repo2.HandleCheckKeyStringError(c, err) + repo.HandleCheckKeyStringError(c, err) return } key, err := db.AddPublicKey(uid, form.Title, content) if err != nil { - repo2.HandleAddKeyError(c, err) + repo.HandleAddKeyError(c, err) return } apiLink := composePublicKeysAPILink() - c.JSON(http.StatusCreated, convert2.ToPublicKey(apiLink, key)) + c.JSON(http.StatusCreated, convert.ToPublicKey(apiLink, key)) } func CreatePublicKey(c *context.APIContext, form api.CreateKeyOption) { @@ -97,9 +98,9 @@ func CreatePublicKey(c *context.APIContext, form api.CreateKeyOption) { func DeletePublicKey(c *context.APIContext) { if err := db.DeletePublicKey(c.User, c.ParamsInt64(":id")); err != nil { if db.IsErrKeyAccessDenied(err) { - c.Error(http.StatusForbidden, "", "you do not have access to this key") + c.ErrorStatus(http.StatusForbidden, errors.New("You do not have access to this key.")) } else { - c.Error(http.StatusInternalServerError, "DeletePublicKey", err) + c.Error(err, "delete public key") } return } diff --git a/internal/route/api/v1/user/user.go b/internal/route/api/v1/user/user.go index 8da3b7346..695d53113 100644 --- a/internal/route/api/v1/user/user.go +++ b/internal/route/api/v1/user/user.go @@ -13,7 +13,6 @@ import ( "gogs.io/gogs/internal/context" "gogs.io/gogs/internal/db" - "gogs.io/gogs/internal/db/errors" "gogs.io/gogs/internal/markup" ) @@ -58,7 +57,7 @@ func Search(c *context.APIContext) { func GetInfo(c *context.APIContext) { u, err := db.GetUserByName(c.Params(":username")) if err != nil { - c.NotFoundOrServerError("GetUserByName", errors.IsUserNotExist, err) + c.NotFoundOrError(err, "get user by name") return } diff --git a/internal/route/dev/template.go b/internal/route/dev/template.go index b73925804..42b0ccc28 100644 --- a/internal/route/dev/template.go +++ b/internal/route/dev/template.go @@ -20,5 +20,5 @@ func TemplatePreview(c *context.Context) { c.Data["ResetPwdCodeLives"] = conf.Auth.ResetPasswordCodeLives / 60 c.Data["CurDbValue"] = "" - c.HTML(200, (c.Params("*"))) + c.Success( (c.Params("*"))) } diff --git a/internal/route/home.go b/internal/route/home.go index 5906f8bb8..3da7f0cfd 100644 --- a/internal/route/home.go +++ b/internal/route/home.go @@ -6,11 +6,11 @@ package route import ( "github.com/unknwon/paginater" - user2 "gogs.io/gogs/internal/route/user" "gogs.io/gogs/internal/conf" "gogs.io/gogs/internal/context" "gogs.io/gogs/internal/db" + "gogs.io/gogs/internal/route/user" ) const ( @@ -24,9 +24,9 @@ func Home(c *context.Context) { if c.IsLogged { if !c.User.IsActive && conf.Auth.RequireEmailConfirmation { c.Data["Title"] = c.Tr("auth.active_your_account") - c.Success(user2.ACTIVATE) + c.Success(user.ACTIVATE) } else { - user2.Dashboard(c) + user.Dashboard(c) } return } @@ -61,7 +61,7 @@ func ExploreRepos(c *context.Context) { PageSize: conf.UI.ExplorePagingNum, }) if err != nil { - c.ServerError("SearchRepositoryByName", err) + c.Error(err, "search repository by name") return } c.Data["Keyword"] = keyword @@ -69,7 +69,7 @@ func ExploreRepos(c *context.Context) { c.Data["Page"] = paginater.New(int(count), conf.UI.ExplorePagingNum, page, 5) if err = db.RepositoryList(repos).LoadAttributes(); err != nil { - c.ServerError("RepositoryList.LoadAttributes", err) + c.Error(err, "load attributes") return } c.Data["Repos"] = repos @@ -102,7 +102,7 @@ func RenderUserSearch(c *context.Context, opts *UserSearchOptions) { if len(keyword) == 0 { users, err = opts.Ranger(page, opts.PageSize) if err != nil { - c.ServerError("Ranger", err) + c.Error(err, "ranger") return } count = opts.Counter() @@ -115,7 +115,7 @@ func RenderUserSearch(c *context.Context, opts *UserSearchOptions) { PageSize: opts.PageSize, }) if err != nil { - c.ServerError("SearchUserByName", err) + c.Error(err, "search user by name") return } } diff --git a/internal/route/org/members.go b/internal/route/org/members.go index fc22ad592..d29d18964 100644 --- a/internal/route/org/members.go +++ b/internal/route/org/members.go @@ -11,7 +11,6 @@ import ( "gogs.io/gogs/internal/conf" "gogs.io/gogs/internal/context" "gogs.io/gogs/internal/db" - "gogs.io/gogs/internal/db/errors" ) const ( @@ -25,12 +24,12 @@ func Members(c *context.Context) { c.Data["PageIsOrgMembers"] = true if err := org.GetMembers(); err != nil { - c.Handle(500, "GetMembers", err) + c.Error(err, "get members") return } c.Data["Members"] = org.Members - c.HTML(200, MEMBERS) + c.Success(MEMBERS) } func MembersAction(c *context.Context) { @@ -45,19 +44,19 @@ func MembersAction(c *context.Context) { switch c.Params(":action") { case "private": if c.User.ID != uid && !c.Org.IsOwner { - c.Error(404) + c.NotFound() return } err = db.ChangeOrgUserStatus(org.ID, uid, false) case "public": if c.User.ID != uid && !c.Org.IsOwner { - c.Error(404) + c.NotFound() return } err = db.ChangeOrgUserStatus(org.ID, uid, true) case "remove": if !c.Org.IsOwner { - c.Error(404) + c.NotFound() return } err = org.RemoveMember(uid) @@ -77,7 +76,7 @@ func MembersAction(c *context.Context) { if err != nil { log.Error("Action(%s): %v", c.Params(":action"), err) - c.JSON(200, map[string]interface{}{ + c.JSONSuccess( map[string]interface{}{ "ok": false, "err": err.Error(), }) @@ -100,17 +99,17 @@ func Invitation(c *context.Context) { uname := c.Query("uname") u, err := db.GetUserByName(uname) if err != nil { - if errors.IsUserNotExist(err) { + if db.IsErrUserNotExist(err) { c.Flash.Error(c.Tr("form.user_not_exist")) c.Redirect(c.Org.OrgLink + "/invitations/new") } else { - c.Handle(500, " GetUserByName", err) + c.Error(err, "get user by name") } return } if err = org.AddMember(u.ID); err != nil { - c.Handle(500, " AddMember", err) + c.Error(err, "add member") return } @@ -119,5 +118,5 @@ func Invitation(c *context.Context) { return } - c.HTML(200, MEMBER_INVITE) + c.Success(MEMBER_INVITE) } diff --git a/internal/route/org/org.go b/internal/route/org/org.go index 551dd3e8d..e0c358acd 100644 --- a/internal/route/org/org.go +++ b/internal/route/org/org.go @@ -7,7 +7,6 @@ package org import ( log "unknwon.dev/clog/v2" - "gogs.io/gogs/internal/conf" "gogs.io/gogs/internal/context" "gogs.io/gogs/internal/db" "gogs.io/gogs/internal/form" @@ -18,15 +17,15 @@ const ( ) func Create(c *context.Context) { - c.Data["Title"] = c.Tr("new_org") - c.HTML(200, CREATE) + c.Title("new_org") + c.Success(CREATE) } func CreatePost(c *context.Context, f form.CreateOrg) { - c.Data["Title"] = c.Tr("new_org") + c.Title("new_org") if c.HasError() { - c.HTML(200, CREATE) + c.Success(CREATE) return } @@ -46,11 +45,11 @@ func CreatePost(c *context.Context, f form.CreateOrg) { case db.IsErrNamePatternNotAllowed(err): c.RenderWithErr(c.Tr("org.form.name_pattern_not_allowed", err.(db.ErrNamePatternNotAllowed).Pattern), CREATE, &f) default: - c.Handle(500, "CreateOrganization", err) + c.Error(err, "create organization") } return } log.Trace("Organization created: %s", org.Name) - c.Redirect(conf.Server.Subpath + "/org/" + f.OrgName + "/dashboard") + c.RedirectSubpath("/org/" + f.OrgName + "/dashboard") } diff --git a/internal/route/org/setting.go b/internal/route/org/setting.go index aecd86432..615033831 100644 --- a/internal/route/org/setting.go +++ b/internal/route/org/setting.go @@ -12,7 +12,6 @@ import ( "gogs.io/gogs/internal/conf" "gogs.io/gogs/internal/context" "gogs.io/gogs/internal/db" - "gogs.io/gogs/internal/db/errors" "gogs.io/gogs/internal/form" "gogs.io/gogs/internal/route/user" ) @@ -24,17 +23,17 @@ const ( ) func Settings(c *context.Context) { - c.Data["Title"] = c.Tr("org.settings") + c.Title("org.settings") c.Data["PageIsSettingsOptions"] = true - c.HTML(200, SETTINGS_OPTIONS) + c.Success(SETTINGS_OPTIONS) } func SettingsPost(c *context.Context, f form.UpdateOrgSetting) { - c.Data["Title"] = c.Tr("org.settings") + c.Title("org.settings") c.Data["PageIsSettingsOptions"] = true if c.HasError() { - c.HTML(200, SETTINGS_OPTIONS) + c.Success(SETTINGS_OPTIONS) return } @@ -44,7 +43,7 @@ func SettingsPost(c *context.Context, f form.UpdateOrgSetting) { if org.LowerName != strings.ToLower(f.Name) { isExist, err := db.IsUserExist(org.ID, f.Name) if err != nil { - c.Handle(500, "IsUserExist", err) + c.Error(err, "check if user exists") return } else if isExist { c.Data["OrgName"] = true @@ -58,7 +57,7 @@ func SettingsPost(c *context.Context, f form.UpdateOrgSetting) { case db.IsErrNamePatternNotAllowed(err): c.RenderWithErr(c.Tr("user.form.name_pattern_not_allowed"), SETTINGS_OPTIONS, &f) default: - c.Handle(500, "ChangeUserName", err) + c.Error(err, "change user name") } return } @@ -79,7 +78,7 @@ func SettingsPost(c *context.Context, f form.UpdateOrgSetting) { org.Website = f.Website org.Location = f.Location if err := db.UpdateUser(org); err != nil { - c.Handle(500, "UpdateUser", err) + c.Error(err, "update user") return } log.Trace("Organization setting updated: %s", org.Name) @@ -113,10 +112,10 @@ func SettingsDelete(c *context.Context) { org := c.Org.Organization if c.Req.Method == "POST" { if _, err := db.UserLogin(c.User.Name, c.Query("password"), c.User.LoginSource); err != nil { - if errors.IsUserNotExist(err) { + if db.IsErrUserNotExist(err) { c.RenderWithErr(c.Tr("form.enterred_invalid_password"), SETTINGS_DELETE, nil) } else { - c.ServerError("UserLogin", err) + c.Error(err, "authenticate user") } return } @@ -126,7 +125,7 @@ func SettingsDelete(c *context.Context) { c.Flash.Error(c.Tr("form.org_still_own_repo")) c.Redirect(c.Org.OrgLink + "/settings/delete") } else { - c.ServerError("DeleteOrganization", err) + c.Error(err, "delete organization") } } else { log.Trace("Organization deleted: %s", org.Name) @@ -139,7 +138,7 @@ func SettingsDelete(c *context.Context) { } func Webhooks(c *context.Context) { - c.Data["Title"] = c.Tr("org.settings") + c.Title("org.settings") c.Data["PageIsSettingsHooks"] = true c.Data["BaseLink"] = c.Org.OrgLink c.Data["Description"] = c.Tr("org.settings.hooks_desc") @@ -147,12 +146,12 @@ func Webhooks(c *context.Context) { ws, err := db.GetWebhooksByOrgID(c.Org.Organization.ID) if err != nil { - c.Handle(500, "GetWebhooksByOrgId", err) + c.Error(err, "get webhooks by organization ID") return } c.Data["Webhooks"] = ws - c.HTML(200, SETTINGS_WEBHOOKS) + c.Success(SETTINGS_WEBHOOKS) } func DeleteWebhook(c *context.Context) { @@ -162,7 +161,7 @@ func DeleteWebhook(c *context.Context) { c.Flash.Success(c.Tr("repo.settings.webhook_deletion_success")) } - c.JSON(200, map[string]interface{}{ + c.JSONSuccess( map[string]interface{}{ "redirect": c.Org.OrgLink + "/settings/hooks", }) } diff --git a/internal/route/org/teams.go b/internal/route/org/teams.go index a4072e970..a703a82d6 100644 --- a/internal/route/org/teams.go +++ b/internal/route/org/teams.go @@ -5,6 +5,7 @@ package org import ( + "net/http" "path" "github.com/unknwon/com" @@ -12,7 +13,6 @@ import ( "gogs.io/gogs/internal/context" "gogs.io/gogs/internal/db" - "gogs.io/gogs/internal/db/errors" "gogs.io/gogs/internal/form" ) @@ -30,13 +30,13 @@ func Teams(c *context.Context) { for _, t := range org.Teams { if err := t.GetMembers(); err != nil { - c.Handle(500, "GetMembers", err) + c.Error(err, "get members") return } } c.Data["Teams"] = org.Teams - c.HTML(200, TEAMS) + c.Success(TEAMS) } func TeamsAction(c *context.Context) { @@ -51,7 +51,7 @@ func TeamsAction(c *context.Context) { switch c.Params(":action") { case "join": if !c.Org.IsOwner { - c.Error(404) + c.NotFound() return } err = c.Org.Team.AddMember(c.User.ID) @@ -59,25 +59,25 @@ func TeamsAction(c *context.Context) { err = c.Org.Team.RemoveMember(c.User.ID) case "remove": if !c.Org.IsOwner { - c.Error(404) + c.NotFound() return } err = c.Org.Team.RemoveMember(uid) page = "team" case "add": if !c.Org.IsOwner { - c.Error(404) + c.NotFound() return } uname := c.Query("uname") var u *db.User u, err = db.GetUserByName(uname) if err != nil { - if errors.IsUserNotExist(err) { + if db.IsErrUserNotExist(err) { c.Flash.Error(c.Tr("form.user_not_exist")) c.Redirect(c.Org.OrgLink + "/teams/" + c.Org.Team.LowerName) } else { - c.Handle(500, " GetUserByName", err) + c.Error(err, "get user by name") } return } @@ -91,7 +91,7 @@ func TeamsAction(c *context.Context) { c.Flash.Error(c.Tr("form.last_org_owner")) } else { log.Error("Action(%s): %v", c.Params(":action"), err) - c.JSON(200, map[string]interface{}{ + c.JSONSuccess(map[string]interface{}{ "ok": false, "err": err.Error(), }) @@ -109,7 +109,7 @@ func TeamsAction(c *context.Context) { func TeamsRepoAction(c *context.Context) { if !c.Org.IsOwner { - c.Error(404) + c.NotFound() return } @@ -120,12 +120,13 @@ func TeamsRepoAction(c *context.Context) { var repo *db.Repository repo, err = db.GetRepositoryByName(c.Org.Organization.ID, repoName) if err != nil { - if errors.IsRepoNotExist(err) { + if db.IsErrRepoNotExist(err) { c.Flash.Error(c.Tr("org.teams.add_nonexistent_repo")) c.Redirect(c.Org.OrgLink + "/teams/" + c.Org.Team.LowerName + "/repositories") return } - c.Handle(500, "GetRepositoryByName", err) + + c.Error(err, "get repository by name") return } err = c.Org.Team.AddRepository(repo) @@ -134,8 +135,7 @@ func TeamsRepoAction(c *context.Context) { } if err != nil { - log.Error("Action(%s): '%s' %v", c.Params(":action"), c.Org.Team.Name, err) - c.Handle(500, "TeamsRepoAction", err) + c.Errorf(err, "action %q", c.Params(":action")) return } c.Redirect(c.Org.OrgLink + "/teams/" + c.Org.Team.LowerName + "/repositories") @@ -146,7 +146,7 @@ func NewTeam(c *context.Context) { c.Data["PageIsOrgTeams"] = true c.Data["PageIsOrgTeamsNew"] = true c.Data["Team"] = &db.Team{} - c.HTML(200, TEAM_NEW) + c.Success(TEAM_NEW) } func NewTeamPost(c *context.Context, f form.CreateTeam) { @@ -163,7 +163,7 @@ func NewTeamPost(c *context.Context, f form.CreateTeam) { c.Data["Team"] = t if c.HasError() { - c.HTML(200, TEAM_NEW) + c.Success(TEAM_NEW) return } @@ -175,7 +175,7 @@ func NewTeamPost(c *context.Context, f form.CreateTeam) { case db.IsErrNameReserved(err): c.RenderWithErr(c.Tr("org.form.team_name_reserved", err.(db.ErrNameReserved).Name), TEAM_NEW, &f) default: - c.Handle(500, "NewTeam", err) + c.Error(err, "new team") } return } @@ -187,20 +187,20 @@ func TeamMembers(c *context.Context) { c.Data["Title"] = c.Org.Team.Name c.Data["PageIsOrgTeams"] = true if err := c.Org.Team.GetMembers(); err != nil { - c.Handle(500, "GetMembers", err) + c.Error(err, "get members") return } - c.HTML(200, TEAM_MEMBERS) + c.Success(TEAM_MEMBERS) } func TeamRepositories(c *context.Context) { c.Data["Title"] = c.Org.Team.Name c.Data["PageIsOrgTeams"] = true if err := c.Org.Team.GetRepositories(); err != nil { - c.Handle(500, "GetRepositories", err) + c.Error(err, "get repositories") return } - c.HTML(200, TEAM_REPOSITORIES) + c.Success(TEAM_REPOSITORIES) } func EditTeam(c *context.Context) { @@ -208,7 +208,7 @@ func EditTeam(c *context.Context) { c.Data["PageIsOrgTeams"] = true c.Data["team_name"] = c.Org.Team.Name c.Data["desc"] = c.Org.Team.Description - c.HTML(200, TEAM_NEW) + c.Success(TEAM_NEW) } func EditTeamPost(c *context.Context, f form.CreateTeam) { @@ -218,7 +218,7 @@ func EditTeamPost(c *context.Context, f form.CreateTeam) { c.Data["Team"] = t if c.HasError() { - c.HTML(200, TEAM_NEW) + c.Success(TEAM_NEW) return } @@ -234,7 +234,7 @@ func EditTeamPost(c *context.Context, f form.CreateTeam) { case "admin": auth = db.ACCESS_MODE_ADMIN default: - c.Error(401) + c.Status(http.StatusUnauthorized) return } @@ -251,7 +251,7 @@ func EditTeamPost(c *context.Context, f form.CreateTeam) { case db.IsErrTeamAlreadyExist(err): c.RenderWithErr(c.Tr("form.team_name_been_taken"), TEAM_NEW, &f) default: - c.Handle(500, "UpdateTeam", err) + c.Error(err, "update team") } return } @@ -265,7 +265,7 @@ func DeleteTeam(c *context.Context) { c.Flash.Success(c.Tr("org.teams.delete_team_success")) } - c.JSON(200, map[string]interface{}{ + c.JSONSuccess(map[string]interface{}{ "redirect": c.Org.OrgLink + "/teams", }) } diff --git a/internal/route/repo/branch.go b/internal/route/repo/branch.go index 2ee353b39..176305546 100644 --- a/internal/route/repo/branch.go +++ b/internal/route/repo/branch.go @@ -31,13 +31,13 @@ type Branch struct { func loadBranches(c *context.Context) []*Branch { rawBranches, err := c.Repo.Repository.GetBranches() if err != nil { - c.Handle(500, "GetBranches", err) + c.Error(err, "get branches") return nil } protectBranches, err := db.GetProtectBranchesByRepoID(c.Repo.Repository.ID) if err != nil { - c.Handle(500, "GetProtectBranchesByRepoID", err) + c.Error(err, "get protect branches by repository ID") return nil } @@ -45,7 +45,7 @@ func loadBranches(c *context.Context) []*Branch { for i := range rawBranches { commit, err := rawBranches[i].GetCommit() if err != nil { - c.Handle(500, "GetCommit", err) + c.Error(err, "get commit") return nil } @@ -91,7 +91,7 @@ func Branches(c *context.Context) { c.Data["ActiveBranches"] = activeBranches c.Data["StaleBranches"] = staleBranches - c.HTML(200, BRANCHES_OVERVIEW) + c.Success( BRANCHES_OVERVIEW) } func AllBranches(c *context.Context) { @@ -104,7 +104,7 @@ func AllBranches(c *context.Context) { } c.Data["Branches"] = branches - c.HTML(200, BRANCHES_ALL) + c.Success( BRANCHES_ALL) } func DeleteBranchPost(c *context.Context) { diff --git a/internal/route/repo/commit.go b/internal/route/repo/commit.go index 7b11e89a0..e8ff33808 100644 --- a/internal/route/repo/commit.go +++ b/internal/route/repo/commit.go @@ -54,7 +54,7 @@ func renderCommits(c *context.Context, filename string) { commits, err := c.Repo.Commit.CommitsByPage(page, pageSize, git.CommitsByPageOptions{Path: filename}) if err != nil { - c.ServerError("paging commits", err) + c.Error(err, "paging commits") return } @@ -73,7 +73,7 @@ func renderCommits(c *context.Context, filename string) { c.Data["Username"] = c.Repo.Owner.Name c.Data["Reponame"] = c.Repo.Repository.Name - c.HTML(200, COMMITS) + c.Success(COMMITS) } func Commits(c *context.Context) { @@ -91,7 +91,7 @@ func SearchCommits(c *context.Context) { commits, err := c.Repo.Commit.SearchCommits(keyword) if err != nil { - c.ServerError("SearchCommits", err) + c.Error(err, "search commits") return } @@ -102,7 +102,7 @@ func SearchCommits(c *context.Context) { c.Data["Username"] = c.Repo.Owner.Name c.Data["Reponame"] = c.Repo.Repository.Name c.Data["Branch"] = c.Repo.BranchName - c.HTML(200, COMMITS) + c.Success(COMMITS) } func FileHistory(c *context.Context) { @@ -119,7 +119,7 @@ func Diff(c *context.Context) { commit, err := c.Repo.GitRepo.CatFileCommit(commitID) if err != nil { - c.NotFoundOrServerError("get commit by ID", gitutil.IsErrRevisionNotExist, err) + c.NotFoundOrError(gitutil.NewError(err), "get commit by ID") return } @@ -127,7 +127,7 @@ func Diff(c *context.Context) { commitID, conf.Git.MaxDiffFiles, conf.Git.MaxDiffLines, conf.Git.MaxDiffLineChars, ) if err != nil { - c.NotFoundOrServerError("get diff", gitutil.IsErrRevisionNotExist, err) + c.NotFoundOrError(gitutil.NewError(err), "get diff") return } @@ -171,7 +171,7 @@ func RawDiff(c *context.Context) { git.RawDiffFormat(c.Params(":ext")), c.Resp, ); err != nil { - c.NotFoundOrServerError("get raw diff", gitutil.IsErrRevisionNotExist, err) + c.NotFoundOrError(gitutil.NewError(err), "get raw diff") return } } @@ -185,7 +185,7 @@ func CompareDiff(c *context.Context) { commit, err := c.Repo.GitRepo.CatFileCommit(afterCommitID) if err != nil { - c.Handle(404, "GetCommit", err) + c.NotFoundOrError(gitutil.NewError(err), "get head commit") return } @@ -194,13 +194,13 @@ func CompareDiff(c *context.Context) { git.DiffOptions{Base: beforeCommitID}, ) if err != nil { - c.ServerError("get diff", err) + c.NotFoundOrError(gitutil.NewError(err), "get diff") return } commits, err := commit.CommitsAfter(beforeCommitID) if err != nil { - c.ServerError("get commits after", err) + c.NotFoundOrError(gitutil.NewError(err), "get commits after") return } @@ -220,5 +220,5 @@ func CompareDiff(c *context.Context) { c.Data["SourcePath"] = conf.Server.Subpath + "/" + path.Join(userName, repoName, "src", afterCommitID) c.Data["BeforeSourcePath"] = conf.Server.Subpath + "/" + path.Join(userName, repoName, "src", beforeCommitID) c.Data["RawPath"] = conf.Server.Subpath + "/" + path.Join(userName, repoName, "raw", afterCommitID) - c.HTML(200, DIFF) + c.Success(DIFF) } diff --git a/internal/route/repo/download.go b/internal/route/repo/download.go index 4bf27e206..6e29c10eb 100644 --- a/internal/route/repo/download.go +++ b/internal/route/repo/download.go @@ -51,12 +51,12 @@ func ServeBlob(c *context.Context, blob *git.Blob) error { func SingleDownload(c *context.Context) { blob, err := c.Repo.Commit.Blob(c.Repo.TreePath) if err != nil { - c.NotFoundOrServerError("get blob", gitutil.IsErrRevisionNotExist, err) + c.NotFoundOrError(gitutil.NewError(err), "get blob") return } if err = ServeBlob(c, blob); err != nil { - c.ServerError("serve blob", err) + c.Error(err, "serve blob") return } } diff --git a/internal/route/repo/editor.go b/internal/route/repo/editor.go index 17434dff6..cd71ff798 100644 --- a/internal/route/repo/editor.go +++ b/internal/route/repo/editor.go @@ -56,7 +56,7 @@ func editFile(c *context.Context, isNewFile bool) { if !isNewFile { entry, err := c.Repo.Commit.TreeEntry(c.Repo.TreePath) if err != nil { - c.NotFoundOrServerError("get tree entry", gitutil.IsErrRevisionNotExist, err) + c.NotFoundOrError(gitutil.NewError(err), "get tree entry") return } @@ -69,7 +69,7 @@ func editFile(c *context.Context, isNewFile bool) { blob := entry.Blob() p, err := blob.Bytes() if err != nil { - c.ServerError("blob.Data", err) + c.Error(err, "get blob data") return } @@ -182,7 +182,7 @@ func editFilePost(c *context.Context, f form.EditRepoFile, isNewFile bool) { break } - c.ServerError("Repo.Commit.GetTreeEntryByPath", err) + c.Error(err, "get tree entry") return } if index != len(treeNames)-1 { @@ -211,14 +211,14 @@ func editFilePost(c *context.Context, f form.EditRepoFile, isNewFile bool) { c.FormErr("TreePath") c.RenderWithErr(c.Tr("repo.editor.file_editing_no_longer_exists", oldTreePath), EDIT_FILE, &f) } else { - c.ServerError("GetTreeEntryByPath", err) + c.Error(err, "get tree entry") } return } if lastCommit != c.Repo.CommitID { files, err := c.Repo.Commit.FilesChangedAfter(lastCommit) if err != nil { - c.ServerError("GetFilesChangedSinceCommit", err) + c.Error(err, "get changed files") return } @@ -236,7 +236,7 @@ func editFilePost(c *context.Context, f form.EditRepoFile, isNewFile bool) { entry, err := c.Repo.Commit.TreeEntry(f.TreePath) if err != nil { if !gitutil.IsErrRevisionNotExist(err) { - c.ServerError("GetTreeEntryByPath", err) + c.Error(err, "get tree entry") return } } @@ -297,26 +297,26 @@ func DiffPreviewPost(c *context.Context, f form.EditPreviewDiff) { entry, err := c.Repo.Commit.TreeEntry(treePath) if err != nil { - c.Error(500, "GetTreeEntryByPath: "+err.Error()) + c.Error(err, "get tree entry") return } else if entry.IsTree() { - c.Error(422) + c.Status(http.StatusUnprocessableEntity) return } diff, err := c.Repo.Repository.GetDiffPreview(c.Repo.BranchName, treePath, f.Content) if err != nil { - c.Error(500, "GetDiffPreview: "+err.Error()) + c.Error(err, "get diff preview") return } if diff.NumFiles() == 0 { - c.PlainText(200, []byte(c.Tr("repo.editor.no_changes_to_show"))) + c.PlainText(http.StatusOK, c.Tr("repo.editor.no_changes_to_show")) return } c.Data["File"] = diff.Files[0] - c.HTML(200, EDIT_DIFF_PREVIEW) + c.Success(EDIT_DIFF_PREVIEW) } func DeleteFile(c *context.Context) { @@ -468,7 +468,7 @@ func UploadFilePost(c *context.Context, f form.UploadRepoFile) { break } - c.ServerError("GetTreeEntryByPath", err) + c.Error(err, "get tree entry") return } @@ -514,7 +514,7 @@ func UploadFilePost(c *context.Context, f form.UploadRepoFile) { func UploadFileToServer(c *context.Context) { file, header, err := c.Req.FormFile("file") if err != nil { - c.Error(http.StatusInternalServerError, fmt.Sprintf("FormFile: %v", err)) + c.Error(err, "get file") return } defer file.Close() @@ -537,14 +537,14 @@ func UploadFileToServer(c *context.Context) { } if !allowed { - c.Error(http.StatusBadRequest, ErrFileTypeForbidden.Error()) + c.PlainText(http.StatusBadRequest, ErrFileTypeForbidden.Error()) return } } upload, err := db.NewUpload(header.Filename, buf, file) if err != nil { - c.Error(http.StatusInternalServerError, fmt.Sprintf("NewUpload: %v", err)) + c.Error(err, "new upload") return } @@ -556,15 +556,15 @@ func UploadFileToServer(c *context.Context) { func RemoveUploadFileFromServer(c *context.Context, f form.RemoveUploadFile) { if len(f.File) == 0 { - c.Status(204) + c.Status(http.StatusNoContent) return } if err := db.DeleteUploadByUUID(f.File); err != nil { - c.Error(500, fmt.Sprintf("DeleteUploadByUUID: %v", err)) + c.Error(err, "delete upload by UUID") return } log.Trace("Upload file removed: %s", f.File) - c.Status(204) + c.Status(http.StatusNoContent) } diff --git a/internal/route/repo/http.go b/internal/route/repo/http.go index 59aea393e..e63bc8728 100644 --- a/internal/route/repo/http.go +++ b/internal/route/repo/http.go @@ -22,7 +22,6 @@ import ( "gogs.io/gogs/internal/conf" "gogs.io/gogs/internal/context" "gogs.io/gogs/internal/db" - "gogs.io/gogs/internal/db/errors" "gogs.io/gogs/internal/lazyregexp" "gogs.io/gogs/internal/tool" ) @@ -39,7 +38,7 @@ type HTTPContext struct { // askCredentials responses HTTP header and status which informs client to provide credentials. func askCredentials(c *context.Context, status int, text string) { c.Resp.Header().Set("WWW-Authenticate", "Basic realm=\".\"") - c.HandleText(status, text) + c.PlainText(status, text) } func HTTPContexter() macaron.Handler { @@ -66,13 +65,13 @@ func HTTPContexter() macaron.Handler { owner, err := db.GetUserByName(ownerName) if err != nil { - c.NotFoundOrServerError("GetUserByName", errors.IsUserNotExist, err) + c.NotFoundOrError(err, "get user by name") return } repo, err := db.GetRepositoryByName(owner.ID, repoName) if err != nil { - c.NotFoundOrServerError("GetRepositoryByName", errors.IsRepoNotExist, err) + c.NotFoundOrError(err, "get repository by name") return } @@ -113,8 +112,8 @@ func HTTPContexter() macaron.Handler { } authUser, err := db.UserLogin(authUsername, authPassword, -1) - if err != nil && !errors.IsUserNotExist(err) { - c.Handle(http.StatusInternalServerError, "UserLogin", err) + if err != nil && !db.IsErrUserNotExist(err) { + c.Error(err, "authenticate user") return } @@ -125,7 +124,7 @@ func HTTPContexter() macaron.Handler { if db.IsErrAccessTokenEmpty(err) || db.IsErrAccessTokenNotExist(err) { askCredentials(c, http.StatusUnauthorized, "") } else { - c.Handle(http.StatusInternalServerError, "GetAccessTokenBySHA", err) + c.Error(err, "get access token by SHA") } return } @@ -136,7 +135,7 @@ func HTTPContexter() macaron.Handler { if err != nil { // Once we found token, we're supposed to find its related user, // thus any error is unexpected. - c.Handle(http.StatusInternalServerError, "GetUserByID", err) + c.Error(err, "get user by ID") return } } else if authUser.IsEnabledTwoFactor() { @@ -153,7 +152,7 @@ Please create and use personal access token on user settings page`) } has, err := db.HasAccess(authUser.ID, repo, mode) if err != nil { - c.Handle(http.StatusInternalServerError, "HasAccess", err) + c.Error(err, "check access") return } else if !has { askCredentials(c, http.StatusForbidden, "User permission denied") @@ -161,7 +160,7 @@ Please create and use personal access token on user settings page`) } if !isPull && repo.IsMirror { - c.HandleText(http.StatusForbidden, "Mirror repository is read-only") + c.PlainText(http.StatusForbidden, "Mirror repository is read-only") return } @@ -388,7 +387,7 @@ func HTTP(c *HTTPContext) { // but we only want to output this message only if user is really trying to access // Git HTTP endpoints. if conf.Repository.DisableHTTPGit { - c.HandleText(http.StatusForbidden, "Interacting with repositories by HTTP protocol is not disabled") + c.PlainText(http.StatusForbidden, "Interacting with repositories by HTTP protocol is disabled") return } diff --git a/internal/route/repo/issue.go b/internal/route/repo/issue.go index fea9af985..1b64cfe21 100644 --- a/internal/route/repo/issue.go +++ b/internal/route/repo/issue.go @@ -51,7 +51,7 @@ var ( func MustEnableIssues(c *context.Context) { if !c.Repo.Repository.EnableIssues { - c.Handle(404, "MustEnableIssues", nil) + c.NotFound() return } @@ -63,7 +63,7 @@ func MustEnableIssues(c *context.Context) { func MustAllowPulls(c *context.Context) { if !c.Repo.Repository.AllowsPulls() { - c.Handle(404, "MustAllowPulls", nil) + c.NotFound() return } @@ -77,7 +77,7 @@ func MustAllowPulls(c *context.Context) { func RetrieveLabels(c *context.Context) { labels, err := db.GetLabelsByRepoID(c.Repo.Repository.ID) if err != nil { - c.Handle(500, "RetrieveLabels.GetLabels", err) + c.Error(err, "get labels by repository ID") return } for _, l := range labels { @@ -182,14 +182,14 @@ func issues(c *context.Context, isPullList bool) { SortType: sortType, }) if err != nil { - c.Handle(500, "Issues", err) + c.Error(err, "list issues") return } // Get issue-user relations. pairs, err := db.GetIssueUsers(repo.ID, posterID, isShowClosed) if err != nil { - c.Handle(500, "GetIssueUsers", err) + c.Error(err, "get issue-user relations") return } @@ -213,14 +213,14 @@ func issues(c *context.Context, isPullList bool) { // Get milestones. c.Data["Milestones"], err = db.GetMilestonesByRepoID(repo.ID) if err != nil { - c.Handle(500, "GetAllRepoMilestones", err) + c.Error(err, "get milestone by repository ID") return } // Get assignees. c.Data["Assignees"], err = repo.GetAssignees() if err != nil { - c.Handle(500, "GetAssignees", err) + c.Error(err, "get assignees") return } @@ -241,7 +241,7 @@ func issues(c *context.Context, isPullList bool) { c.Data["State"] = "open" } - c.HTML(200, ISSUES) + c.Success(ISSUES) } func Issues(c *context.Context) { @@ -264,18 +264,18 @@ func RetrieveRepoMilestonesAndAssignees(c *context.Context, repo *db.Repository) var err error c.Data["OpenMilestones"], err = db.GetMilestones(repo.ID, -1, false) if err != nil { - c.Handle(500, "GetMilestones", err) + c.Error(err, "get open milestones") return } c.Data["ClosedMilestones"], err = db.GetMilestones(repo.ID, -1, true) if err != nil { - c.Handle(500, "GetMilestones", err) + c.Error(err, "get closed milestones") return } c.Data["Assignees"], err = repo.GetAssignees() if err != nil { - c.Handle(500, "GetAssignees", err) + c.Error(err, "get assignees") return } } @@ -287,7 +287,7 @@ func RetrieveRepoMetas(c *context.Context, repo *db.Repository) []*db.Label { labels, err := db.GetLabelsByRepoID(repo.ID) if err != nil { - c.Handle(500, "GetLabelsByRepoID", err) + c.Error(err, "get labels by repository ID") return nil } c.Data["Labels"] = labels @@ -345,7 +345,7 @@ func NewIssue(c *context.Context) { return } - c.HTML(200, ISSUE_NEW) + c.Success(ISSUE_NEW) } func ValidateRepoMetas(c *context.Context, f form.NewIssue) ([]int64, int64, int64) { @@ -382,7 +382,7 @@ func ValidateRepoMetas(c *context.Context, f form.NewIssue) ([]int64, int64, int if milestoneID > 0 { c.Data["Milestone"], err = repo.GetMilestoneByID(milestoneID) if err != nil { - c.Handle(500, "GetMilestoneByID", err) + c.Error(err, "get milestone by ID") return nil, 0, 0 } c.Data["milestone_id"] = milestoneID @@ -393,7 +393,7 @@ func ValidateRepoMetas(c *context.Context, f form.NewIssue) ([]int64, int64, int if assigneeID > 0 { c.Data["Assignee"], err = repo.GetAssigneeByID(assigneeID) if err != nil { - c.Handle(500, "GetAssigneeByID", err) + c.Error(err, "get assignee by ID") return nil, 0, 0 } c.Data["assignee_id"] = assigneeID @@ -415,7 +415,7 @@ func NewIssuePost(c *context.Context, f form.NewIssue) { } if c.HasError() { - c.HTML(200, ISSUE_NEW) + c.Success(ISSUE_NEW) return } @@ -434,7 +434,7 @@ func NewIssuePost(c *context.Context, f form.NewIssue) { Content: f.Content, } if err := db.NewIssue(c.Repo.Repository, issue, labelIDs, attachments); err != nil { - c.Handle(500, "NewIssue", err) + c.Error(err, "new issue") return } @@ -445,7 +445,7 @@ func NewIssuePost(c *context.Context, f form.NewIssue) { func uploadAttachment(c *context.Context, allowedTypes []string) { file, header, err := c.Req.FormFile("file") if err != nil { - c.Error(500, fmt.Sprintf("FormFile: %v", err)) + c.Error(err, "get file") return } defer file.Close() @@ -467,18 +467,18 @@ func uploadAttachment(c *context.Context, allowedTypes []string) { } if !allowed { - c.Error(400, ErrFileTypeForbidden.Error()) + c.PlainText(http.StatusBadRequest, ErrFileTypeForbidden.Error()) return } attach, err := db.NewAttachment(header.Filename, buf, file) if err != nil { - c.Error(500, fmt.Sprintf("NewAttachment: %v", err)) + c.Error(err, "new attachment") return } log.Trace("New attachment uploaded: %s", attach.UUID) - c.JSON(200, map[string]string{ + c.JSONSuccess(map[string]string{ "uuid": attach.UUID, }) } @@ -505,7 +505,7 @@ func viewIssue(c *context.Context, isPullList bool) { issue, err := db.GetIssueByIndex(c.Repo.Repository.ID, index) if err != nil { - c.NotFoundOrServerError("GetIssueByIndex", errors.IsIssueNotExist, err) + c.NotFoundOrError(err, "get issue by index") return } c.Data["Title"] = issue.Title @@ -559,7 +559,7 @@ func viewIssue(c *context.Context, isPullList bool) { } labels, err := db.GetLabelsByRepoID(repo.ID) if err != nil { - c.Handle(500, "GetLabelsByRepoID", err) + c.Error(err, "get labels by repository ID") return } hasSelected := false @@ -583,7 +583,7 @@ func viewIssue(c *context.Context, isPullList bool) { if c.IsLogged { // Update issue-user. if err = issue.ReadBy(c.User.ID); err != nil { - c.Handle(500, "ReadBy", err) + c.Error(err, "mark read by") return } } @@ -638,8 +638,8 @@ func viewIssue(c *context.Context, isPullList bool) { branchProtected := false protectBranch, err := db.GetProtectBranchOfRepoByName(pull.BaseRepoID, pull.HeadBranch) if err != nil { - if !errors.IsErrBranchNotExist(err) { - c.ServerError("GetProtectBranchOfRepoByName", err) + if !db.IsErrBranchNotExist(err) { + c.Error(err, "get protect branch of repository by name") return } } else { @@ -661,7 +661,7 @@ func viewIssue(c *context.Context, isPullList bool) { c.Data["Issue"] = issue c.Data["IsIssueOwner"] = c.Repo.IsWriter() || (c.IsLogged && issue.IsPoster(c.User.ID)) c.Data["SignInLink"] = conf.Server.Subpath + "/user/login?redirect_to=" + c.Data["Link"].(string) - c.HTML(200, ISSUE_VIEW) + c.Success(ISSUE_VIEW) } func ViewIssue(c *context.Context) { @@ -675,7 +675,7 @@ func ViewPull(c *context.Context) { func getActionIssue(c *context.Context) *db.Issue { issue, err := db.GetIssueByIndex(c.Repo.Repository.ID, c.ParamsInt64(":index")) if err != nil { - c.NotFoundOrServerError("GetIssueByIndex", errors.IsIssueNotExist, err) + c.NotFoundOrError(err, "get issue by index") return nil } @@ -695,22 +695,22 @@ func UpdateIssueTitle(c *context.Context) { } if !c.IsLogged || (!issue.IsPoster(c.User.ID) && !c.Repo.IsWriter()) { - c.Error(403) + c.Status(http.StatusForbidden) return } title := c.QueryTrim("title") if len(title) == 0 { - c.Error(204) + c.Status(http.StatusNoContent) return } if err := issue.ChangeTitle(c.User, title); err != nil { - c.Handle(500, "ChangeTitle", err) + c.Error(err, "change title") return } - c.JSON(200, map[string]interface{}{ + c.JSONSuccess(map[string]interface{}{ "title": issue.Title, }) } @@ -722,17 +722,17 @@ func UpdateIssueContent(c *context.Context) { } if !c.IsLogged || (c.User.ID != issue.PosterID && !c.Repo.IsWriter()) { - c.Error(403) + c.Status(http.StatusForbidden) return } content := c.Query("content") if err := issue.ChangeContent(c.User, content); err != nil { - c.Handle(500, "ChangeContent", err) + c.Error(err, "change content") return } - c.JSON(200, map[string]string{ + c.JSONSuccess(map[string]string{ "content": string(markup.Markdown(issue.Content, c.Query("context"), c.Repo.Repository.ComposeMetas())), }) } @@ -745,35 +745,31 @@ func UpdateIssueLabel(c *context.Context) { if c.Query("action") == "clear" { if err := issue.ClearLabels(c.User); err != nil { - c.Handle(500, "ClearLabels", err) + c.Error(err, "clear labels") return } } else { isAttach := c.Query("action") == "attach" label, err := db.GetLabelOfRepoByID(c.Repo.Repository.ID, c.QueryInt64("id")) if err != nil { - if db.IsErrLabelNotExist(err) { - c.Error(404, "GetLabelByID") - } else { - c.Handle(500, "GetLabelByID", err) - } + c.NotFoundOrError(err, "get label by ID") return } if isAttach && !issue.HasLabel(label.ID) { if err = issue.AddLabel(c.User, label); err != nil { - c.Handle(500, "AddLabel", err) + c.Error(err, "add label") return } } else if !isAttach && issue.HasLabel(label.ID) { if err = issue.RemoveLabel(c.User, label); err != nil { - c.Handle(500, "RemoveLabel", err) + c.Error(err, "remove label") return } } } - c.JSON(200, map[string]interface{}{ + c.JSONSuccess(map[string]interface{}{ "ok": true, }) } @@ -787,7 +783,7 @@ func UpdateIssueMilestone(c *context.Context) { oldMilestoneID := issue.MilestoneID milestoneID := c.QueryInt64("id") if oldMilestoneID == milestoneID { - c.JSON(200, map[string]interface{}{ + c.JSONSuccess(map[string]interface{}{ "ok": true, }) return @@ -796,11 +792,11 @@ func UpdateIssueMilestone(c *context.Context) { // Not check for invalid milestone id and give responsibility to owners. issue.MilestoneID = milestoneID if err := db.ChangeMilestoneAssign(c.User, issue, oldMilestoneID); err != nil { - c.Handle(500, "ChangeMilestoneAssign", err) + c.Error(err, "change milestone assign") return } - c.JSON(200, map[string]interface{}{ + c.JSONSuccess(map[string]interface{}{ "ok": true, }) } @@ -813,18 +809,18 @@ func UpdateIssueAssignee(c *context.Context) { assigneeID := c.QueryInt64("id") if issue.AssigneeID == assigneeID { - c.JSON(200, map[string]interface{}{ + c.JSONSuccess(map[string]interface{}{ "ok": true, }) return } if err := issue.ChangeAssignee(c.User, assigneeID); err != nil { - c.Handle(500, "ChangeAssignee", err) + c.Error(err, "change assignee") return } - c.JSON(200, map[string]interface{}{ + c.JSONSuccess(map[string]interface{}{ "ok": true, }) } @@ -862,7 +858,7 @@ func NewComment(c *context.Context, f form.CreateComment) { pr, err = db.GetUnmergedPullRequest(pull.HeadRepoID, pull.BaseRepoID, pull.HeadBranch, pull.BaseBranch) if err != nil { if !db.IsErrPullRequestNotExist(err) { - c.ServerError("GetUnmergedPullRequest", err) + c.Error(err, "get unmerged pull request") return } } @@ -870,7 +866,7 @@ func NewComment(c *context.Context, f form.CreateComment) { // Regenerate patch and test conflict. if pr == nil { if err = issue.PullRequest.UpdatePatch(); err != nil { - c.ServerError("UpdatePatch", err) + c.Error(err, "update patch") return } @@ -913,7 +909,7 @@ func NewComment(c *context.Context, f form.CreateComment) { comment, err = db.CreateIssueComment(c.User, c.Repo.Repository, issue, f.Content, attachments) if err != nil { - c.ServerError("CreateIssueComment", err) + c.Error(err, "create issue comment") return } @@ -923,32 +919,32 @@ func NewComment(c *context.Context, f form.CreateComment) { func UpdateCommentContent(c *context.Context) { comment, err := db.GetCommentByID(c.ParamsInt64(":id")) if err != nil { - c.NotFoundOrServerError("GetCommentByID", db.IsErrCommentNotExist, err) + c.NotFoundOrError(err, "get comment by ID") return } if c.UserID() != comment.PosterID && !c.Repo.IsAdmin() { - c.Error(404) + c.NotFound() return } else if comment.Type != db.COMMENT_TYPE_COMMENT { - c.Error(204) + c.Status(http.StatusNoContent) return } oldContent := comment.Content comment.Content = c.Query("content") if len(comment.Content) == 0 { - c.JSON(200, map[string]interface{}{ + c.JSONSuccess(map[string]interface{}{ "content": "", }) return } if err = db.UpdateComment(c.User, comment, oldContent); err != nil { - c.Handle(500, "UpdateComment", err) + c.Error(err, "update comment") return } - c.JSON(200, map[string]string{ + c.JSONSuccess(map[string]string{ "content": string(markup.Markdown(comment.Content, c.Query("context"), c.Repo.Repository.ComposeMetas())), }) } @@ -956,24 +952,24 @@ func UpdateCommentContent(c *context.Context) { func DeleteComment(c *context.Context) { comment, err := db.GetCommentByID(c.ParamsInt64(":id")) if err != nil { - c.NotFoundOrServerError("GetCommentByID", db.IsErrCommentNotExist, err) + c.NotFoundOrError(err, "get comment by ID") return } if c.UserID() != comment.PosterID && !c.Repo.IsAdmin() { - c.Error(404) + c.NotFound() return } else if comment.Type != db.COMMENT_TYPE_COMMENT { - c.Error(204) + c.Status(http.StatusNoContent) return } if err = db.DeleteCommentByID(c.User, comment.ID); err != nil { - c.Handle(500, "DeleteCommentByID", err) + c.Error(err, "delete comment by ID") return } - c.Status(200) + c.Status(http.StatusOK) } func Labels(c *context.Context) { @@ -982,7 +978,7 @@ func Labels(c *context.Context) { c.Data["PageIsLabels"] = true c.Data["RequireMinicolors"] = true c.Data["LabelTemplates"] = db.LabelTemplates - c.HTML(200, LABELS) + c.Success(LABELS) } func InitializeLabels(c *context.Context, f form.InitializeLabels) { @@ -1006,7 +1002,7 @@ func InitializeLabels(c *context.Context, f form.InitializeLabels) { } } if err := db.NewLabels(labels...); err != nil { - c.Handle(500, "NewLabels", err) + c.Error(err, "new labels") return } c.RawRedirect(c.Repo.MakeURL("labels")) @@ -1028,7 +1024,7 @@ func NewLabel(c *context.Context, f form.CreateLabel) { Color: f.Color, } if err := db.NewLabels(l); err != nil { - c.Handle(500, "NewLabel", err) + c.Error(err, "new labels") return } c.RawRedirect(c.Repo.MakeURL("labels")) @@ -1037,19 +1033,14 @@ func NewLabel(c *context.Context, f form.CreateLabel) { func UpdateLabel(c *context.Context, f form.CreateLabel) { l, err := db.GetLabelByID(f.ID) if err != nil { - switch { - case db.IsErrLabelNotExist(err): - c.Error(404) - default: - c.Handle(500, "UpdateLabel", err) - } + c.NotFoundOrError(err, "get label by ID") return } l.Name = f.Title l.Color = f.Color if err := db.UpdateLabel(l); err != nil { - c.Handle(500, "UpdateLabel", err) + c.Error(err, "update label") return } c.RawRedirect(c.Repo.MakeURL("labels")) @@ -1092,7 +1083,7 @@ func Milestones(c *context.Context) { miles, err := db.GetMilestones(c.Repo.Repository.ID, page, isShowClosed) if err != nil { - c.Handle(500, "GetMilestones", err) + c.Error(err, "get milestones") return } for _, m := range miles { @@ -1112,7 +1103,7 @@ func Milestones(c *context.Context) { } c.Data["IsShowClosed"] = isShowClosed - c.HTML(200, MILESTONE) + c.Success(MILESTONE) } func NewMilestone(c *context.Context) { @@ -1121,7 +1112,7 @@ func NewMilestone(c *context.Context) { c.Data["PageIsMilestones"] = true c.Data["RequireDatetimepicker"] = true c.Data["DateLang"] = conf.I18n.DateLang(c.Locale.Language()) - c.HTML(200, MILESTONE_NEW) + c.Success(MILESTONE_NEW) } func NewMilestonePost(c *context.Context, f form.CreateMilestone) { @@ -1132,7 +1123,7 @@ func NewMilestonePost(c *context.Context, f form.CreateMilestone) { c.Data["DateLang"] = conf.I18n.DateLang(c.Locale.Language()) if c.HasError() { - c.HTML(200, MILESTONE_NEW) + c.Success(MILESTONE_NEW) return } @@ -1152,7 +1143,7 @@ func NewMilestonePost(c *context.Context, f form.CreateMilestone) { Content: f.Content, Deadline: deadline, }); err != nil { - c.Handle(500, "NewMilestone", err) + c.Error(err, "new milestone") return } @@ -1169,11 +1160,7 @@ func EditMilestone(c *context.Context) { m, err := db.GetMilestoneByRepoID(c.Repo.Repository.ID, c.ParamsInt64(":id")) if err != nil { - if db.IsErrMilestoneNotExist(err) { - c.Handle(404, "", nil) - } else { - c.Handle(500, "GetMilestoneByRepoID", err) - } + c.NotFoundOrError(err, "get milestone by repository ID") return } c.Data["title"] = m.Name @@ -1181,7 +1168,7 @@ func EditMilestone(c *context.Context) { if len(m.DeadlineString) > 0 { c.Data["deadline"] = m.DeadlineString } - c.HTML(200, MILESTONE_NEW) + c.Success(MILESTONE_NEW) } func EditMilestonePost(c *context.Context, f form.CreateMilestone) { @@ -1192,7 +1179,7 @@ func EditMilestonePost(c *context.Context, f form.CreateMilestone) { c.Data["DateLang"] = conf.I18n.DateLang(c.Locale.Language()) if c.HasError() { - c.HTML(200, MILESTONE_NEW) + c.Success(MILESTONE_NEW) return } @@ -1208,18 +1195,14 @@ func EditMilestonePost(c *context.Context, f form.CreateMilestone) { m, err := db.GetMilestoneByRepoID(c.Repo.Repository.ID, c.ParamsInt64(":id")) if err != nil { - if db.IsErrMilestoneNotExist(err) { - c.Handle(404, "", nil) - } else { - c.Handle(500, "GetMilestoneByRepoID", err) - } + c.NotFoundOrError(err, "get milestone by repository ID") return } m.Name = f.Title m.Content = f.Content m.Deadline = deadline if err = db.UpdateMilestone(m); err != nil { - c.Handle(500, "UpdateMilestone", err) + c.Error(err, "update milestone") return } @@ -1230,11 +1213,7 @@ func EditMilestonePost(c *context.Context, f form.CreateMilestone) { func ChangeMilestonStatus(c *context.Context) { m, err := db.GetMilestoneByRepoID(c.Repo.Repository.ID, c.ParamsInt64(":id")) if err != nil { - if db.IsErrMilestoneNotExist(err) { - c.Handle(404, "", err) - } else { - c.Handle(500, "GetMilestoneByRepoID", err) - } + c.NotFoundOrError(err, "get milestone by repository ID") return } @@ -1246,7 +1225,7 @@ func ChangeMilestonStatus(c *context.Context) { case "open": if m.IsClosed { if err = db.ChangeMilestoneStatus(m, false); err != nil { - c.Handle(500, "ChangeMilestoneStatus", err) + c.Error(err, "change milestone status to open") return } } @@ -1255,7 +1234,7 @@ func ChangeMilestonStatus(c *context.Context) { if !m.IsClosed { m.ClosedDate = time.Now() if err = db.ChangeMilestoneStatus(m, true); err != nil { - c.Handle(500, "ChangeMilestoneStatus", err) + c.Error(err, "change milestone status to closed") return } } @@ -1272,7 +1251,7 @@ func DeleteMilestone(c *context.Context) { c.Flash.Success(c.Tr("repo.milestones.deletion_success")) } - c.JSON(200, map[string]interface{}{ + c.JSONSuccess(map[string]interface{}{ "redirect": c.Repo.MakeURL("milestones"), }) } diff --git a/internal/route/repo/pull.go b/internal/route/repo/pull.go index a1b474804..14e9a5c32 100644 --- a/internal/route/repo/pull.go +++ b/internal/route/repo/pull.go @@ -5,6 +5,7 @@ package repo import ( + "net/http" "path" "strings" @@ -16,7 +17,6 @@ import ( "gogs.io/gogs/internal/conf" "gogs.io/gogs/internal/context" "gogs.io/gogs/internal/db" - "gogs.io/gogs/internal/db/errors" "gogs.io/gogs/internal/form" "gogs.io/gogs/internal/gitutil" "gogs.io/gogs/internal/tool" @@ -49,7 +49,7 @@ var ( func parseBaseRepository(c *context.Context) *db.Repository { baseRepo, err := db.GetRepositoryByID(c.ParamsInt64(":repoid")) if err != nil { - c.NotFoundOrServerError("GetRepositoryByID", errors.IsRepoNotExist, err) + c.NotFoundOrError(err, "get repository by ID") return nil } @@ -63,13 +63,13 @@ func parseBaseRepository(c *context.Context) *db.Repository { c.Data["IsPrivate"] = baseRepo.IsPrivate if err = baseRepo.GetOwner(); err != nil { - c.ServerError("GetOwner", err) + c.Error(err, "get owner") return nil } c.Data["ForkFrom"] = baseRepo.Owner.Name + "/" + baseRepo.Name if err := c.User.GetOrganizations(true); err != nil { - c.ServerError("GetOrganizations", err) + c.Error(err, "get organizations") return nil } c.Data["Orgs"] = c.User.Orgs @@ -110,7 +110,7 @@ func ForkPost(c *context.Context, f form.CreateRepo) { repo, has, err := db.HasForkedRepo(ctxUser.ID, baseRepo.ID) if err != nil { - c.ServerError("HasForkedRepo", err) + c.Error(err, "check forked repository") return } else if has { c.Redirect(repo.Link()) @@ -119,7 +119,7 @@ func ForkPost(c *context.Context, f form.CreateRepo) { // Check ownership of organization. if ctxUser.IsOrganization() && !ctxUser.IsOwnedBy(c.User.ID) { - c.Error(403) + c.Status(http.StatusForbidden) return } @@ -133,7 +133,7 @@ func ForkPost(c *context.Context, f form.CreateRepo) { if err != nil { c.Data["Err_RepoName"] = true switch { - case errors.IsReachLimitOfRepo(err): + case db.IsErrReachLimitOfRepo(err): c.RenderWithErr(c.Tr("repo.form.reach_limit_of_creation", c.User.RepoCreationNum()), FORK, &f) case db.IsErrRepoAlreadyExist(err): c.RenderWithErr(c.Tr("repo.settings.new_owner_has_same_repo"), FORK, &f) @@ -142,7 +142,7 @@ func ForkPost(c *context.Context, f form.CreateRepo) { case db.IsErrNamePatternNotAllowed(err): c.RenderWithErr(c.Tr("repo.form.name_pattern_not_allowed", err.(db.ErrNamePatternNotAllowed).Pattern), FORK, &f) default: - c.ServerError("ForkPost", err) + c.Error(err, "fork repository") } return } @@ -154,21 +154,21 @@ func ForkPost(c *context.Context, f form.CreateRepo) { func checkPullInfo(c *context.Context) *db.Issue { issue, err := db.GetIssueByIndex(c.Repo.Repository.ID, c.ParamsInt64(":index")) if err != nil { - c.NotFoundOrServerError("GetIssueByIndex", errors.IsIssueNotExist, err) + c.NotFoundOrError(err, "get issue by index") return nil } c.Data["Title"] = issue.Title c.Data["Issue"] = issue if !issue.IsPull { - c.Handle(404, "ViewPullCommits", nil) + c.NotFound() return nil } if c.IsLogged { // Update issue-user. if err = issue.ReadBy(c.User.ID); err != nil { - c.ServerError("ReadBy", err) + c.Error(err, "mark read by") return nil } } @@ -185,14 +185,14 @@ func PrepareMergedViewPullInfo(c *context.Context, issue *db.Issue) { var err error c.Data["NumCommits"], err = c.Repo.GitRepo.RevListCount([]string{pull.MergeBase + "..." + pull.MergedCommitID}) if err != nil { - c.ServerError("Repo.GitRepo.CommitsCountBetween", err) + c.Error(err, "count commits") return } names, err := c.Repo.GitRepo.DiffNameOnly(pull.MergeBase, pull.MergedCommitID, git.DiffNameOnlyOptions{NeedsMergeBase: true}) c.Data["NumFiles"] = len(names) if err != nil { - c.ServerError("Repo.GitRepo.FilesCountBetween", err) + c.Error(err, "get changed files") return } } @@ -212,7 +212,7 @@ func PrepareViewPullInfo(c *context.Context, issue *db.Issue) *gitutil.PullReque if pull.HeadRepo != nil { headGitRepo, err = git.Open(pull.HeadRepo.RepoPath()) if err != nil { - c.ServerError("open repository", err) + c.Error(err, "open repository") return nil } } @@ -236,7 +236,7 @@ func PrepareViewPullInfo(c *context.Context, issue *db.Issue) *gitutil.PullReque return nil } - c.ServerError("GetPullRequestInfo", err) + c.Error(err, "get pull request meta") return nil } c.Data["NumCommits"] = len(prMeta.Commits) @@ -267,17 +267,17 @@ func ViewPullCommits(c *context.Context) { } startCommit, err := c.Repo.GitRepo.CatFileCommit(pull.MergeBase) if err != nil { - c.ServerError("get commit of merge base", err) + c.Error(err, "get commit of merge base") return } endCommit, err := c.Repo.GitRepo.CatFileCommit(pull.MergedCommitID) if err != nil { - c.ServerError("get merged commit", err) + c.Error(err, "get merged commit") return } commits, err = c.Repo.GitRepo.RevList([]string{startCommit.ID.String() + "..." + endCommit.ID.String()}) if err != nil { - c.ServerError("list commits", err) + c.Error(err, "list commits") return } @@ -330,7 +330,7 @@ func ViewPullFiles(c *context.Context) { if c.Written() { return } else if prInfo == nil { - c.Handle(404, "ViewPullFiles", nil) + c.NotFound() return } @@ -338,13 +338,13 @@ func ViewPullFiles(c *context.Context) { headGitRepo, err := git.Open(headRepoPath) if err != nil { - c.ServerError("open repository", err) + c.Error(err, "open repository") return } headCommitID, err := headGitRepo.BranchCommitID(pull.HeadBranch) if err != nil { - c.ServerError("get head branch commit ID", err) + c.Error(err, "get head branch commit ID") return } @@ -359,7 +359,7 @@ func ViewPullFiles(c *context.Context) { git.DiffOptions{Base: startCommitID}, ) if err != nil { - c.ServerError("get diff", err) + c.Error(err, "get diff") return } c.Data["Diff"] = diff @@ -367,7 +367,7 @@ func ViewPullFiles(c *context.Context) { commit, err := gitRepo.CatFileCommit(endCommitID) if err != nil { - c.ServerError("get commit", err) + c.Error(err, "get commit") return } @@ -406,7 +406,7 @@ func MergePullRequest(c *context.Context) { pr, err := db.GetPullRequestByIssueID(issue.ID) if err != nil { - c.NotFoundOrServerError("GetPullRequestByIssueID", db.IsErrPullRequestNotExist, err) + c.NotFoundOrError(err, "get pull request by issue ID") return } @@ -418,7 +418,7 @@ func MergePullRequest(c *context.Context) { pr.Issue = issue pr.Issue.Repo = c.Repo.Repository if err = pr.Merge(c.User, c.Repo.GitRepo, db.MergeStyle(c.Query("merge_style")), c.Query("commit_description")); err != nil { - c.ServerError("Merge", err) + c.Error(err, "merge") return } @@ -460,7 +460,7 @@ func ParseCompareInfo(c *context.Context) (*db.User, *db.Repository, *git.Reposi } else if len(headInfos) == 2 { headUser, err = db.GetUserByName(headInfos[0]) if err != nil { - c.NotFoundOrServerError("GetUserByName", errors.IsUserNotExist, err) + c.NotFoundOrError(err, "get user by name") return nil, nil, nil, nil, "", "" } headBranch = headInfos[1] @@ -491,7 +491,7 @@ func ParseCompareInfo(c *context.Context) (*db.User, *db.Repository, *git.Reposi var has bool headRepo, has, err = db.HasForkedRepo(headUser.ID, baseRepo.ID) if err != nil { - c.ServerError("HasForkedRepo", err) + c.Error(err, "get forked repository") return nil, nil, nil, nil, "", "" } else if !has { log.Trace("ParseCompareInfo [base_repo_id: %d]: does not have fork or in same repository", baseRepo.ID) @@ -501,7 +501,7 @@ func ParseCompareInfo(c *context.Context) (*db.User, *db.Repository, *git.Reposi headGitRepo, err = git.Open(db.RepoPath(headUser.Name, headRepo.Name)) if err != nil { - c.ServerError("open repository", err) + c.Error(err, "open repository") return nil, nil, nil, nil, "", "" } } else { @@ -523,7 +523,7 @@ func ParseCompareInfo(c *context.Context) (*db.User, *db.Repository, *git.Reposi headBranches, err := headGitRepo.Branches() if err != nil { - c.ServerError("get branches", err) + c.Error(err, "get branches") return nil, nil, nil, nil, "", "" } c.Data["HeadBranches"] = headBranches @@ -535,7 +535,7 @@ func ParseCompareInfo(c *context.Context) (*db.User, *db.Repository, *git.Reposi c.Data["IsNoMergeBase"] = true c.Success(COMPARE_PULL) } else { - c.ServerError("get pull request meta", err) + c.Error(err, "get pull request meta") } return nil, nil, nil, nil, "", "" } @@ -563,7 +563,7 @@ func PrepareCompareDiff( headCommitID, err := headGitRepo.BranchCommitID(headBranch) if err != nil { - c.ServerError("get head branch commit ID", err) + c.Error(err, "get head branch commit ID") return false } c.Data["AfterCommitID"] = headCommitID @@ -578,7 +578,7 @@ func PrepareCompareDiff( git.DiffOptions{Base: meta.MergeBase}, ) if err != nil { - c.ServerError("get repository diff", err) + c.Error(err, "get repository diff") return false } c.Data["Diff"] = diff @@ -586,7 +586,7 @@ func PrepareCompareDiff( headCommit, err := headGitRepo.CatFileCommit(headCommitID) if err != nil { - c.ServerError("get head commit", err) + c.Error(err, "get head commit") return false } @@ -619,7 +619,7 @@ func CompareAndPullRequest(c *context.Context) { pr, err := db.GetUnmergedPullRequest(headRepo.ID, c.Repo.Repository.ID, headBranch, baseBranch) if err != nil { if !db.IsErrPullRequestNotExist(err) { - c.ServerError("GetUnmergedPullRequest", err) + c.Error(err, "get unmerged pull request") return } } else { @@ -701,7 +701,7 @@ func CompareAndPullRequestPost(c *context.Context, f form.NewIssue) { patch, err := headGitRepo.DiffBinary(meta.MergeBase, headBranch) if err != nil { - c.ServerError("get patch", err) + c.Error(err, "get patch") return } @@ -730,10 +730,10 @@ func CompareAndPullRequestPost(c *context.Context, f form.NewIssue) { // FIXME: check error in the case two people send pull request at almost same time, give nice error prompt // instead of 500. if err := db.NewPullRequest(repo, pullIssue, labelIDs, attachments, pullRequest, patch); err != nil { - c.ServerError("NewPullRequest", err) + c.Error(err, "new pull request") return } else if err := pullRequest.PushToBaseRepo(); err != nil { - c.ServerError("PushToBaseRepo", err) + c.Error(err, "push to base repository") return } @@ -744,13 +744,13 @@ func CompareAndPullRequestPost(c *context.Context, f form.NewIssue) { func parseOwnerAndRepo(c *context.Context) (*db.User, *db.Repository) { owner, err := db.GetUserByName(c.Params(":username")) if err != nil { - c.NotFoundOrServerError("GetUserByName", errors.IsUserNotExist, err) + c.NotFoundOrError(err, "get user by name") return nil, nil } repo, err := db.GetRepositoryByName(owner.ID, c.Params(":reponame")) if err != nil { - c.NotFoundOrServerError("GetRepositoryByName", errors.IsRepoNotExist, err) + c.NotFoundOrError(err, "get repository by name") return nil, nil } @@ -762,7 +762,7 @@ func TriggerTask(c *context.Context) { branch := c.Query("branch") secret := c.Query("secret") if len(branch) == 0 || len(secret) == 0 || pusherID <= 0 { - c.Error(404) + c.NotFound() log.Trace("TriggerTask: branch or secret is empty, or pusher ID is not valid") return } @@ -771,14 +771,14 @@ func TriggerTask(c *context.Context) { return } if secret != tool.MD5(owner.Salt) { - c.Error(404) + c.NotFound() log.Trace("TriggerTask [%s/%s]: invalid secret", owner.Name, repo.Name) return } pusher, err := db.GetUserByID(pusherID) if err != nil { - c.NotFoundOrServerError("GetUserByID", errors.IsUserNotExist, err) + c.NotFoundOrError(err, "get user by ID") return } diff --git a/internal/route/repo/release.go b/internal/route/repo/release.go index f945e4fc4..cf05b800b 100644 --- a/internal/route/repo/release.go +++ b/internal/route/repo/release.go @@ -53,13 +53,13 @@ func Releases(c *context.Context) { tagsPage, err := gitutil.Module.ListTagsAfter(c.Repo.GitRepo.Path(), c.Query("after"), 10) if err != nil { - c.ServerError("get tags", err) + c.Error(err, "get tags") return } releases, err := db.GetPublishedReleasesByRepoID(c.Repo.Repository.ID, tagsPage.Tags...) if err != nil { - c.Handle(500, "GetPublishedReleasesByRepoID", err) + c.Error(err, "get published releases by repository ID") return } @@ -75,12 +75,12 @@ func Releases(c *context.Context) { releases[j] = nil // Mark as used. if err = r.LoadAttributes(); err != nil { - c.Handle(500, "LoadAttributes", err) + c.Error(err, "load attributes") return } if err := calReleaseNumCommitsBehind(c.Repo, r, countCache); err != nil { - c.Handle(500, "calReleaseNumCommitsBehind", err) + c.Error(err, "calculate number of commits after release") return } @@ -93,7 +93,7 @@ func Releases(c *context.Context) { if results[i] == nil { commit, err := c.Repo.GitRepo.TagCommit(rawTag) if err != nil { - c.Handle(500, "get tag commit", err) + c.Error(err, "get tag commit") return } @@ -105,7 +105,7 @@ func Releases(c *context.Context) { results[i].NumCommits, err = commit.CommitsCount() if err != nil { - c.ServerError("count commits", err) + c.Error(err, "count commits") return } results[i].NumCommitsBehind = c.Repo.CommitsCount - results[i].NumCommits @@ -118,18 +118,18 @@ func Releases(c *context.Context) { if tagsPage.HasLatest { drafts, err = db.GetDraftReleasesByRepoID(c.Repo.Repository.ID) if err != nil { - c.Handle(500, "GetDraftReleasesByRepoID", err) + c.Error(err, "get draft releases by repository ID") return } for _, r := range drafts { if err = r.LoadAttributes(); err != nil { - c.Handle(500, "LoadAttributes", err) + c.Error(err, "load attributes") return } if err := calReleaseNumCommitsBehind(c.Repo, r, countCache); err != nil { - c.Handle(500, "calReleaseNumCommitsBehind", err) + c.Error(err, "calculate number of commits after release") return } @@ -148,7 +148,7 @@ func Releases(c *context.Context) { if len(results) > 0 { c.Data["NextAfter"] = results[len(results)-1].TagName } - c.HTML(200, RELEASES) + c.Success(RELEASES) } func renderReleaseAttachmentSettings(c *context.Context) { @@ -164,7 +164,7 @@ func NewRelease(c *context.Context) { c.Data["PageIsReleaseList"] = true c.Data["tag_target"] = c.Repo.Repository.DefaultBranch renderReleaseAttachmentSettings(c) - c.HTML(200, RELEASE_NEW) + c.Success(RELEASE_NEW) } func NewReleasePost(c *context.Context, f form.NewRelease) { @@ -173,7 +173,7 @@ func NewReleasePost(c *context.Context, f form.NewRelease) { renderReleaseAttachmentSettings(c) if c.HasError() { - c.HTML(200, RELEASE_NEW) + c.Success(RELEASE_NEW) return } @@ -194,13 +194,13 @@ func NewReleasePost(c *context.Context, f form.NewRelease) { commit, err := c.Repo.GitRepo.BranchCommit(f.Target) if err != nil { - c.ServerError("get branch commit", err) + c.Error(err, "get branch commit") return } commitsCount, err := commit.CommitsCount() if err != nil { - c.ServerError("count commits", err) + c.Error(err, "count commits") return } @@ -230,7 +230,7 @@ func NewReleasePost(c *context.Context, f form.NewRelease) { case db.IsErrInvalidTagName(err): c.RenderWithErr(c.Tr("repo.release.tag_name_invalid"), RELEASE_NEW, &f) default: - c.Handle(500, "NewRelease", err) + c.Error(err, "new release") } return } @@ -248,11 +248,7 @@ func EditRelease(c *context.Context) { tagName := c.Params("*") rel, err := db.GetRelease(c.Repo.Repository.ID, tagName) if err != nil { - if db.IsErrReleaseNotExist(err) { - c.Handle(404, "GetRelease", err) - } else { - c.Handle(500, "GetRelease", err) - } + c.NotFoundOrError(err, "get release") return } c.Data["ID"] = rel.ID @@ -264,7 +260,7 @@ func EditRelease(c *context.Context) { c.Data["prerelease"] = rel.IsPrerelease c.Data["IsDraft"] = rel.IsDraft - c.HTML(200, RELEASE_NEW) + c.Success(RELEASE_NEW) } func EditReleasePost(c *context.Context, f form.EditRelease) { @@ -276,11 +272,7 @@ func EditReleasePost(c *context.Context, f form.EditRelease) { tagName := c.Params("*") rel, err := db.GetRelease(c.Repo.Repository.ID, tagName) if err != nil { - if db.IsErrReleaseNotExist(err) { - c.Handle(404, "GetRelease", err) - } else { - c.Handle(500, "GetRelease", err) - } + c.NotFoundOrError(err, "get release") return } c.Data["tag_name"] = rel.TagName @@ -292,7 +284,7 @@ func EditReleasePost(c *context.Context, f form.EditRelease) { c.Data["IsDraft"] = rel.IsDraft if c.HasError() { - c.HTML(200, RELEASE_NEW) + c.Success(RELEASE_NEW) return } @@ -307,7 +299,7 @@ func EditReleasePost(c *context.Context, f form.EditRelease) { rel.IsDraft = len(f.Draft) > 0 rel.IsPrerelease = f.Prerelease if err = db.UpdateRelease(c.User, c.Repo.GitRepo, rel, isPublish, attachments); err != nil { - c.Handle(500, "UpdateRelease", err) + c.Error(err, "update release") return } c.Redirect(c.Repo.RepoLink + "/releases") @@ -328,7 +320,7 @@ func DeleteRelease(c *context.Context) { c.Flash.Success(c.Tr("repo.release.deletion_success")) } - c.JSON(200, map[string]interface{}{ + c.JSONSuccess( map[string]interface{}{ "redirect": c.Repo.RepoLink + "/releases", }) } diff --git a/internal/route/repo/repo.go b/internal/route/repo/repo.go index a0bd25fe5..c55314d3b 100644 --- a/internal/route/repo/repo.go +++ b/internal/route/repo/repo.go @@ -5,7 +5,7 @@ package repo import ( - "fmt" + "net/http" "os" "path" "path/filepath" @@ -19,7 +19,6 @@ import ( "gogs.io/gogs/internal/conf" "gogs.io/gogs/internal/context" "gogs.io/gogs/internal/db" - "gogs.io/gogs/internal/db/errors" "gogs.io/gogs/internal/form" "gogs.io/gogs/internal/tool" ) @@ -31,14 +30,14 @@ const ( func MustBeNotBare(c *context.Context) { if c.Repo.Repository.IsBare { - c.Handle(404, "MustBeNotBare", nil) + c.NotFound() } } func checkContextUser(c *context.Context, uid int64) *db.User { orgs, err := db.GetOwnedOrgsByUserIDDesc(c.User.ID, "updated_unix") if err != nil { - c.Handle(500, "GetOwnedOrgsByUserIDDesc", err) + c.Error(err, "get owned organization by user ID") return nil } c.Data["Orgs"] = orgs @@ -49,18 +48,18 @@ func checkContextUser(c *context.Context, uid int64) *db.User { } org, err := db.GetUserByID(uid) - if errors.IsUserNotExist(err) { + if db.IsErrUserNotExist(err) { return c.User } if err != nil { - c.Handle(500, "GetUserByID", fmt.Errorf("[%d]: %v", uid, err)) + c.Error(err, "get user by ID") return nil } // Check ownership of organization. if !org.IsOrganization() || !(c.User.IsAdmin || org.IsOwnedBy(c.User.ID)) { - c.Error(403) + c.Status(http.StatusForbidden) return nil } return org @@ -84,12 +83,12 @@ func Create(c *context.Context) { } c.Data["ContextUser"] = ctxUser - c.HTML(200, CREATE) + c.Success(CREATE) } func handleCreateError(c *context.Context, owner *db.User, err error, name, tpl string, form interface{}) { switch { - case errors.IsReachLimitOfRepo(err): + case db.IsErrReachLimitOfRepo(err): c.RenderWithErr(c.Tr("repo.form.reach_limit_of_creation", owner.RepoCreationNum()), tpl, form) case db.IsErrRepoAlreadyExist(err): c.Data["Err_RepoName"] = true @@ -101,7 +100,7 @@ func handleCreateError(c *context.Context, owner *db.User, err error, name, tpl c.Data["Err_RepoName"] = true c.RenderWithErr(c.Tr("repo.form.name_pattern_not_allowed", err.(db.ErrNamePatternNotAllowed).Pattern), tpl, form) default: - c.Handle(500, name, err) + c.Error(err, name) } } @@ -119,7 +118,7 @@ func CreatePost(c *context.Context, f form.CreateRepo) { c.Data["ContextUser"] = ctxUser if c.HasError() { - c.HTML(200, CREATE) + c.Success(CREATE) return } @@ -159,7 +158,7 @@ func Migrate(c *context.Context) { } c.Data["ContextUser"] = ctxUser - c.HTML(200, MIGRATE) + c.Success(MIGRATE) } func MigratePost(c *context.Context, f form.MigrateRepo) { @@ -172,7 +171,7 @@ func MigratePost(c *context.Context, f form.MigrateRepo) { c.Data["ContextUser"] = ctxUser if c.HasError() { - c.HTML(200, MIGRATE) + c.Success(MIGRATE) return } @@ -189,10 +188,10 @@ func MigratePost(c *context.Context, f form.MigrateRepo) { case addrErr.IsInvalidPath: c.RenderWithErr(c.Tr("repo.migrate.invalid_local_path"), MIGRATE, &f) default: - c.Handle(500, "Unknown error", err) + c.Error(err, "unexpected error") } } else { - c.Handle(500, "ParseRemoteAddr", err) + c.Error(err, "parse remote address") } return } @@ -259,7 +258,7 @@ func Action(c *context.Context) { } if err != nil { - c.ServerError(fmt.Sprintf("Action (%s)", c.Params(":action")), err) + c.Errorf(err, "action %q", c.Params(":action")) return } @@ -290,14 +289,14 @@ func Download(c *context.Context) { archiveFormat = git.ArchiveTarGz default: log.Trace("Unknown format: %s", uri) - c.Error(404) + c.NotFound() return } refName = strings.TrimSuffix(uri, ext) if !com.IsDir(archivePath) { if err := os.MkdirAll(archivePath, os.ModePerm); err != nil { - c.Handle(500, "Download -> os.MkdirAll(archivePath)", err) + c.Error(err, "create archive directory") return } } @@ -311,13 +310,13 @@ func Download(c *context.Context) { if gitRepo.HasBranch(refName) { commit, err = gitRepo.BranchCommit(refName) if err != nil { - c.ServerError("get branch commit", err) + c.Error(err, "get branch commit") return } } else if gitRepo.HasTag(refName) { commit, err = gitRepo.TagCommit(refName) if err != nil { - c.ServerError("get tag commit", err) + c.Error(err, "get tag commit") return } } else if len(refName) >= 7 && len(refName) <= 40 { @@ -334,7 +333,7 @@ func Download(c *context.Context) { archivePath = path.Join(archivePath, tool.ShortSHA1(commit.ID.String())+ext) if !com.IsFile(archivePath) { if err := commit.CreateArchive(archiveFormat, archivePath); err != nil { - c.ServerError("creates archive", err) + c.Error(err, "creates archive") return } } diff --git a/internal/route/repo/setting.go b/internal/route/repo/setting.go index bf463f4a7..1c4446d00 100644 --- a/internal/route/repo/setting.go +++ b/internal/route/repo/setting.go @@ -7,7 +7,6 @@ package repo import ( "fmt" "io/ioutil" - "os" "strings" "time" @@ -21,6 +20,7 @@ import ( "gogs.io/gogs/internal/db/errors" "gogs.io/gogs/internal/email" "gogs.io/gogs/internal/form" + "gogs.io/gogs/internal/osutil" "gogs.io/gogs/internal/tool" ) @@ -72,7 +72,7 @@ func SettingsPost(c *context.Context, f form.RepoSetting) { case db.IsErrNamePatternNotAllowed(err): c.RenderWithErr(c.Tr("repo.form.name_pattern_not_allowed", err.(db.ErrNamePatternNotAllowed).Pattern), SETTINGS_OPTIONS, &f) default: - c.ServerError("ChangeRepositoryName", err) + c.Error(err, "change repository name") } return } @@ -94,7 +94,7 @@ func SettingsPost(c *context.Context, f form.RepoSetting) { visibilityChanged := repo.IsPrivate != f.Private repo.IsPrivate = f.Private if err := db.UpdateRepository(repo, visibilityChanged); err != nil { - c.ServerError("UpdateRepository", err) + c.Error(err, "update repository") return } log.Trace("Repository basic settings updated: %s/%s", c.Repo.Owner.Name, repo.Name) @@ -119,12 +119,12 @@ func SettingsPost(c *context.Context, f form.RepoSetting) { c.Repo.Mirror.Interval = f.Interval c.Repo.Mirror.NextSync = time.Now().Add(time.Duration(f.Interval) * time.Hour) if err := db.UpdateMirror(c.Repo.Mirror); err != nil { - c.ServerError("UpdateMirror", err) + c.Error(err, "update mirror") return } } if err := c.Repo.Mirror.SaveAddress(f.MirrorAddress); err != nil { - c.ServerError("SaveAddress", err) + c.Error(err, "save address") return } @@ -157,7 +157,7 @@ func SettingsPost(c *context.Context, f form.RepoSetting) { repo.PullsAllowRebase = f.PullsAllowRebase if err := db.UpdateRepository(repo, false); err != nil { - c.ServerError("UpdateRepository", err) + c.Error(err, "update repository") return } log.Trace("Repository advanced settings updated: %s/%s", c.Repo.Owner.Name, repo.Name) @@ -189,10 +189,10 @@ func SettingsPost(c *context.Context, f form.RepoSetting) { repo.IsMirror = false if _, err := db.CleanUpMigrateInfo(repo); err != nil { - c.ServerError("CleanUpMigrateInfo", err) + c.Error(err, "clean up migrate info") return } else if err = db.DeleteMirrorByRepoID(c.Repo.Repository.ID); err != nil { - c.ServerError("DeleteMirrorByRepoID", err) + c.Error(err, "delete mirror by repository ID") return } log.Trace("Repository converted from mirror to regular: %s/%s", c.Repo.Owner.Name, repo.Name) @@ -219,7 +219,7 @@ func SettingsPost(c *context.Context, f form.RepoSetting) { newOwner := c.Query("new_owner_name") isExist, err := db.IsUserExist(0, newOwner) if err != nil { - c.ServerError("IsUserExist", err) + c.Error(err, "check if user exists") return } else if !isExist { c.RenderWithErr(c.Tr("form.enterred_invalid_owner_name"), SETTINGS_OPTIONS, nil) @@ -230,7 +230,7 @@ func SettingsPost(c *context.Context, f form.RepoSetting) { if db.IsErrRepoAlreadyExist(err) { c.RenderWithErr(c.Tr("repo.settings.new_owner_has_same_repo"), SETTINGS_OPTIONS, nil) } else { - c.ServerError("TransferOwnership", err) + c.Error(err, "transfer ownership") } return } @@ -256,7 +256,7 @@ func SettingsPost(c *context.Context, f form.RepoSetting) { } if err := db.DeleteRepository(c.Repo.Owner.ID, repo.ID); err != nil { - c.ServerError("DeleteRepository", err) + c.Error(err, "delete repository") return } log.Trace("Repository deleted: %s/%s", c.Repo.Owner.Name, repo.Name) @@ -286,7 +286,7 @@ func SettingsPost(c *context.Context, f form.RepoSetting) { repo.EnableWiki = false if err := db.UpdateRepository(repo, false); err != nil { - c.ServerError("UpdateRepository", err) + c.Error(err, "update repository") return } @@ -311,14 +311,14 @@ func SettingsAvatarPost(c *context.Context, f form.Avatar) { } else { c.Flash.Success(c.Tr("settings.update_avatar_success")) } - c.SubURLRedirect(c.Repo.RepoLink + "/settings") + c.RedirectSubpath(c.Repo.RepoLink + "/settings") } func SettingsDeleteAvatar(c *context.Context) { if err := c.Repo.Repository.DeleteAvatar(); err != nil { c.Flash.Error(fmt.Sprintf("Failed to delete avatar: %v", err)) } - c.SubURLRedirect(c.Repo.RepoLink + "/settings") + c.RedirectSubpath(c.Repo.RepoLink + "/settings") } // FIXME: limit upload size @@ -361,12 +361,12 @@ func SettingsCollaboration(c *context.Context) { users, err := c.Repo.Repository.GetCollaborators() if err != nil { - c.Handle(500, "GetCollaborators", err) + c.Error(err, "get collaborators") return } c.Data["Collaborators"] = users - c.HTML(200, SETTINGS_COLLABORATION) + c.Success(SETTINGS_COLLABORATION) } func SettingsCollaborationPost(c *context.Context) { @@ -378,11 +378,11 @@ func SettingsCollaborationPost(c *context.Context) { u, err := db.GetUserByName(name) if err != nil { - if errors.IsUserNotExist(err) { + if db.IsErrUserNotExist(err) { c.Flash.Error(c.Tr("form.user_not_exist")) c.Redirect(conf.Server.Subpath + c.Req.URL.Path) } else { - c.Handle(500, "GetUserByName", err) + c.Error(err, "get user by name") } return } @@ -395,7 +395,7 @@ func SettingsCollaborationPost(c *context.Context) { } if err = c.Repo.Repository.AddCollaborator(u); err != nil { - c.Handle(500, "AddCollaborator", err) + c.Error(err, "add collaborator") return } @@ -425,7 +425,7 @@ func DeleteCollaboration(c *context.Context) { c.Flash.Success(c.Tr("repo.settings.remove_collaborator_success")) } - c.JSON(200, map[string]interface{}{ + c.JSONSuccess( map[string]interface{}{ "redirect": c.Repo.RepoLink + "/settings/collaboration", }) } @@ -436,13 +436,13 @@ func SettingsBranches(c *context.Context) { if c.Repo.Repository.IsBare { c.Flash.Info(c.Tr("repo.settings.branches_bare"), true) - c.HTML(200, SETTINGS_BRANCHES) + c.Success(SETTINGS_BRANCHES) return } protectBranches, err := db.GetProtectBranchesByRepoID(c.Repo.Repository.ID) if err != nil { - c.Handle(500, "GetProtectBranchesByRepoID", err) + c.Error(err, "get protect branch by repository ID") return } @@ -455,7 +455,7 @@ func SettingsBranches(c *context.Context) { } c.Data["ProtectBranches"] = branches - c.HTML(200, SETTINGS_BRANCHES) + c.Success(SETTINGS_BRANCHES) } func UpdateDefaultBranch(c *context.Context) { @@ -473,7 +473,7 @@ func UpdateDefaultBranch(c *context.Context) { } if err := db.UpdateRepository(c.Repo.Repository, false); err != nil { - c.Handle(500, "UpdateRepository", err) + c.Error(err, "update repository") return } @@ -493,8 +493,8 @@ func SettingsProtectedBranch(c *context.Context) { protectBranch, err := db.GetProtectBranchOfRepoByName(c.Repo.Repository.ID, branch) if err != nil { - if !errors.IsErrBranchNotExist(err) { - c.Handle(500, "GetProtectBranchOfRepoByName", err) + if !db.IsErrBranchNotExist(err) { + c.Error(err, "get protect branch of repository by name") return } @@ -507,7 +507,7 @@ func SettingsProtectedBranch(c *context.Context) { if c.Repo.Owner.IsOrganization() { users, err := c.Repo.Repository.GetWriters() if err != nil { - c.Handle(500, "Repo.Repository.GetPushers", err) + c.Error(err, "get writers") return } c.Data["Users"] = users @@ -515,7 +515,7 @@ func SettingsProtectedBranch(c *context.Context) { teams, err := c.Repo.Owner.TeamsHaveAccessToRepo(c.Repo.Repository.ID, db.ACCESS_MODE_WRITE) if err != nil { - c.Handle(500, "Repo.Owner.TeamsHaveAccessToRepo", err) + c.Error(err, "get teams have access to the repository") return } c.Data["Teams"] = teams @@ -523,7 +523,7 @@ func SettingsProtectedBranch(c *context.Context) { } c.Data["Branch"] = protectBranch - c.HTML(200, SETTINGS_PROTECTED_BRANCH) + c.Success(SETTINGS_PROTECTED_BRANCH) } func SettingsProtectedBranchPost(c *context.Context, f form.ProtectBranch) { @@ -535,8 +535,8 @@ func SettingsProtectedBranchPost(c *context.Context, f form.ProtectBranch) { protectBranch, err := db.GetProtectBranchOfRepoByName(c.Repo.Repository.ID, branch) if err != nil { - if !errors.IsErrBranchNotExist(err) { - c.Handle(500, "GetProtectBranchOfRepoByName", err) + if !db.IsErrBranchNotExist(err) { + c.Error(err, "get protect branch of repository by name") return } @@ -556,7 +556,7 @@ func SettingsProtectedBranchPost(c *context.Context, f form.ProtectBranch) { err = db.UpdateProtectBranch(protectBranch) } if err != nil { - c.Handle(500, "UpdateOrgProtectBranch/UpdateProtectBranch", err) + c.Error(err, "update protect branch") return } @@ -570,12 +570,12 @@ func SettingsGitHooks(c *context.Context) { hooks, err := c.Repo.GitRepo.Hooks("custom_hooks") if err != nil { - c.Handle(500, "Hooks", err) + c.Error(err, "get hooks") return } c.Data["Hooks"] = hooks - c.HTML(200, SETTINGS_GITHOOKS) + c.Success(SETTINGS_GITHOOKS) } func SettingsGitHooksEdit(c *context.Context) { @@ -586,30 +586,22 @@ func SettingsGitHooksEdit(c *context.Context) { name := c.Params(":name") hook, err := c.Repo.GitRepo.Hook("custom_hooks", git.HookName(name)) if err != nil { - if err == os.ErrNotExist { - c.Handle(404, "GetHook", err) - } else { - c.Handle(500, "GetHook", err) - } + c.NotFoundOrError(osutil.NewError(err), "get hook") return } c.Data["Hook"] = hook - c.HTML(200, SETTINGS_GITHOOK_EDIT) + c.Success(SETTINGS_GITHOOK_EDIT) } func SettingsGitHooksEditPost(c *context.Context) { name := c.Params(":name") hook, err := c.Repo.GitRepo.Hook("custom_hooks", git.HookName(name)) if err != nil { - if err == os.ErrNotExist { - c.Handle(404, "GetHook", err) - } else { - c.Handle(500, "GetHook", err) - } + c.NotFoundOrError(osutil.NewError(err), "get hook") return } if err = hook.Update(c.Query("content")); err != nil { - c.Handle(500, "hook.Update", err) + c.Error(err, "update hook") return } c.Redirect(c.Data["Link"].(string)) @@ -621,12 +613,12 @@ func SettingsDeployKeys(c *context.Context) { keys, err := db.ListDeployKeys(c.Repo.Repository.ID) if err != nil { - c.Handle(500, "ListDeployKeys", err) + c.Error(err, "list deploy keys") return } c.Data["Deploykeys"] = keys - c.HTML(200, SETTINGS_DEPLOY_KEYS) + c.Success(SETTINGS_DEPLOY_KEYS) } func SettingsDeployKeysPost(c *context.Context, f form.AddSSHKey) { @@ -635,13 +627,13 @@ func SettingsDeployKeysPost(c *context.Context, f form.AddSSHKey) { keys, err := db.ListDeployKeys(c.Repo.Repository.ID) if err != nil { - c.Handle(500, "ListDeployKeys", err) + c.Error(err, "list deploy keys") return } c.Data["Deploykeys"] = keys if c.HasError() { - c.HTML(200, SETTINGS_DEPLOY_KEYS) + c.Success(SETTINGS_DEPLOY_KEYS) return } @@ -669,7 +661,7 @@ func SettingsDeployKeysPost(c *context.Context, f form.AddSSHKey) { c.Data["Err_Title"] = true c.RenderWithErr(c.Tr("repo.settings.key_name_used"), SETTINGS_DEPLOY_KEYS, &f) default: - c.Handle(500, "AddDeployKey", err) + c.Error(err, "add deploy key") } return } @@ -686,7 +678,7 @@ func DeleteDeployKey(c *context.Context) { c.Flash.Success(c.Tr("repo.settings.deploy_key_deletion_success")) } - c.JSON(200, map[string]interface{}{ + c.JSONSuccess( map[string]interface{}{ "redirect": c.Repo.RepoLink + "/settings/keys", }) } diff --git a/internal/route/repo/view.go b/internal/route/repo/view.go index b07dafe26..378dc976d 100644 --- a/internal/route/repo/view.go +++ b/internal/route/repo/view.go @@ -37,13 +37,13 @@ const ( func renderDirectory(c *context.Context, treeLink string) { tree, err := c.Repo.Commit.Subtree(c.Repo.TreePath) if err != nil { - c.NotFoundOrServerError("get subtree", gitutil.IsErrRevisionNotExist, err) + c.NotFoundOrError(gitutil.NewError(err), "get subtree") return } entries, err := tree.Entries() if err != nil { - c.ServerError("list entries", err) + c.Error(err, "list entries") return } entries.Sort() @@ -54,7 +54,7 @@ func renderDirectory(c *context.Context, treeLink string) { Timeout: 5 * time.Minute, }) if err != nil { - c.ServerError("get commits info", err) + c.Error(err, "get commits info") return } @@ -76,7 +76,7 @@ func renderDirectory(c *context.Context, treeLink string) { p, err := readmeFile.Bytes() if err != nil { - c.ServerError("readmeFile.Data", err) + c.Error(err, "read file") return } @@ -107,7 +107,7 @@ func renderDirectory(c *context.Context, treeLink string) { if len(c.Repo.TreePath) > 0 { latestCommit, err = c.Repo.Commit.CommitByPath(git.CommitByRevisionOptions{Path: c.Repo.TreePath}) if err != nil { - c.ServerError("get commit by path", err) + c.Error(err, "get commit by path") return } } @@ -126,7 +126,7 @@ func renderFile(c *context.Context, entry *git.TreeEntry, treeLink, rawLink stri blob := entry.Blob() p, err := blob.Bytes() if err != nil { - c.Handle(500, "Data", err) + c.Error(err, "read blob") return } @@ -232,7 +232,7 @@ func Home(c *context.Context) { c.Data["PageIsViewFiles"] = true if c.Repo.Repository.IsBare { - c.HTML(200, BARE) + c.Success(BARE) return } @@ -260,7 +260,7 @@ func Home(c *context.Context) { var err error c.Repo.CommitsCount, err = c.Repo.Commit.CommitsCount() if err != nil { - c.Handle(500, "CommitsCount", err) + c.Error(err, "count commits") return } c.Data["CommitsCount"] = c.Repo.CommitsCount @@ -270,7 +270,7 @@ func Home(c *context.Context) { // Get current entry user currently looking at. entry, err := c.Repo.Commit.TreeEntry(c.Repo.TreePath) if err != nil { - c.NotFoundOrServerError("get tree entry", gitutil.IsErrRevisionNotExist, err) + c.NotFoundOrError(gitutil.NewError(err), "get tree entry") return } @@ -306,7 +306,7 @@ func Home(c *context.Context) { c.Data["TreeLink"] = treeLink c.Data["TreeNames"] = treeNames c.Data["BranchLink"] = branchLink - c.HTML(200, HOME) + c.Success(HOME) } func RenderUserCards(c *context.Context, total int, getter func(page int) ([]*db.User, error), tpl string) { @@ -319,12 +319,12 @@ func RenderUserCards(c *context.Context, total int, getter func(page int) ([]*db items, err := getter(pager.Current()) if err != nil { - c.Handle(500, "getter", err) + c.Error(err, "getter") return } c.Data["Cards"] = items - c.HTML(200, tpl) + c.Success(tpl) } func Watchers(c *context.Context) { @@ -346,17 +346,17 @@ func Forks(c *context.Context) { forks, err := c.Repo.Repository.GetForks() if err != nil { - c.Handle(500, "GetForks", err) + c.Error(err, "get forks") return } for _, fork := range forks { if err = fork.GetOwner(); err != nil { - c.Handle(500, "GetOwner", err) + c.Error(err, "get owner") return } } c.Data["Forks"] = forks - c.HTML(200, FORKS) + c.Success(FORKS) } diff --git a/internal/route/repo/webhook.go b/internal/route/repo/webhook.go index 705fd2adf..32c2069be 100644 --- a/internal/route/repo/webhook.go +++ b/internal/route/repo/webhook.go @@ -6,6 +6,7 @@ package repo import ( "fmt" + "net/http" "strings" jsoniter "github.com/json-iterator/go" @@ -36,12 +37,12 @@ func Webhooks(c *context.Context) { ws, err := db.GetWebhooksByRepoID(c.Repo.Repository.ID) if err != nil { - c.Handle(500, "GetWebhooksByRepoID", err) + c.Error(err, "get webhooks by repository ID") return } c.Data["Webhooks"] = ws - c.HTML(200, WEBHOOKS) + c.Success(WEBHOOKS) } type OrgRepoCtx struct { @@ -77,7 +78,7 @@ func getOrgRepoCtx(c *context.Context) (*OrgRepoCtx, error) { func checkHookType(c *context.Context) string { hookType := strings.ToLower(c.Params(":type")) if !com.IsSliceContainsStr(conf.Webhook.Types, hookType) { - c.Handle(404, "checkHookType", nil) + c.NotFound() return "" } return hookType @@ -91,7 +92,7 @@ func WebhooksNew(c *context.Context) { orCtx, err := getOrgRepoCtx(c) if err != nil { - c.Handle(500, "getOrgRepoCtx", err) + c.Error(err, "get organization repository context") return } @@ -101,7 +102,7 @@ func WebhooksNew(c *context.Context) { } c.Data["BaseLink"] = orCtx.Link - c.HTML(200, orCtx.NewTemplate) + c.Success(orCtx.NewTemplate) } func ParseHookEvent(f form.Webhook) *db.HookEvent { @@ -131,13 +132,13 @@ func WebHooksNewPost(c *context.Context, f form.NewWebhook) { orCtx, err := getOrgRepoCtx(c) if err != nil { - c.Handle(500, "getOrgRepoCtx", err) + c.Error(err, "get organization repository context") return } c.Data["BaseLink"] = orCtx.Link if c.HasError() { - c.HTML(200, orCtx.NewTemplate) + c.Success(orCtx.NewTemplate) return } @@ -157,10 +158,10 @@ func WebHooksNewPost(c *context.Context, f form.NewWebhook) { OrgID: orCtx.OrgID, } if err := w.UpdateEvent(); err != nil { - c.Handle(500, "UpdateEvent", err) + c.Error(err, "update event") return } else if err := db.CreateWebhook(w); err != nil { - c.Handle(500, "CreateWebhook", err) + c.Error(err, "create webhook") return } @@ -176,12 +177,12 @@ func SlackHooksNewPost(c *context.Context, f form.NewSlackHook) { orCtx, err := getOrgRepoCtx(c) if err != nil { - c.Handle(500, "getOrgRepoCtx", err) + c.Error(err, "get organization repository context") return } if c.HasError() { - c.HTML(200, orCtx.NewTemplate) + c.Success(orCtx.NewTemplate) return } @@ -192,7 +193,7 @@ func SlackHooksNewPost(c *context.Context, f form.NewSlackHook) { Color: f.Color, }) if err != nil { - c.Handle(500, "Marshal", err) + c.Error(err, "marshal JSON") return } @@ -207,10 +208,10 @@ func SlackHooksNewPost(c *context.Context, f form.NewSlackHook) { OrgID: orCtx.OrgID, } if err := w.UpdateEvent(); err != nil { - c.Handle(500, "UpdateEvent", err) + c.Error(err, "update event") return } else if err := db.CreateWebhook(w); err != nil { - c.Handle(500, "CreateWebhook", err) + c.Error(err, "create webhook") return } @@ -227,12 +228,12 @@ func DiscordHooksNewPost(c *context.Context, f form.NewDiscordHook) { orCtx, err := getOrgRepoCtx(c) if err != nil { - c.Handle(500, "getOrgRepoCtx", err) + c.Error(err, "get organization repository context") return } if c.HasError() { - c.HTML(200, orCtx.NewTemplate) + c.Success(orCtx.NewTemplate) return } @@ -242,7 +243,7 @@ func DiscordHooksNewPost(c *context.Context, f form.NewDiscordHook) { Color: f.Color, }) if err != nil { - c.Handle(500, "Marshal", err) + c.Error(err, "marshal JSON") return } @@ -257,10 +258,10 @@ func DiscordHooksNewPost(c *context.Context, f form.NewDiscordHook) { OrgID: orCtx.OrgID, } if err := w.UpdateEvent(); err != nil { - c.Handle(500, "UpdateEvent", err) + c.Error(err, "update event") return } else if err := db.CreateWebhook(w); err != nil { - c.Handle(500, "CreateWebhook", err) + c.Error(err, "create webhook") return } @@ -276,12 +277,12 @@ func DingtalkHooksNewPost(c *context.Context, f form.NewDingtalkHook) { orCtx, err := getOrgRepoCtx(c) if err != nil { - c.Handle(500, "getOrgRepoCtx", err) + c.Error(err, "get organization repository context") return } if c.HasError() { - c.HTML(200, orCtx.NewTemplate) + c.Success(orCtx.NewTemplate) return } @@ -295,10 +296,10 @@ func DingtalkHooksNewPost(c *context.Context, f form.NewDingtalkHook) { OrgID: orCtx.OrgID, } if err := w.UpdateEvent(); err != nil { - c.Handle(500, "UpdateEvent", err) + c.Error(err, "update event") return } else if err := db.CreateWebhook(w); err != nil { - c.Handle(500, "CreateWebhook", err) + c.Error(err, "create webhook") return } @@ -311,7 +312,7 @@ func checkWebhook(c *context.Context) (*OrgRepoCtx, *db.Webhook) { orCtx, err := getOrgRepoCtx(c) if err != nil { - c.Handle(500, "getOrgRepoCtx", err) + c.Error(err, "get organization repository context") return nil, nil } c.Data["BaseLink"] = orCtx.Link @@ -323,7 +324,7 @@ func checkWebhook(c *context.Context) (*OrgRepoCtx, *db.Webhook) { w, err = db.GetWebhookByOrgID(c.Org.Organization.ID, c.ParamsInt64(":id")) } if err != nil { - c.NotFoundOrServerError("GetWebhookOfRepoByID/GetWebhookByOrgID", errors.IsWebhookNotExist, err) + c.NotFoundOrError(err, "get webhook") return nil, nil } @@ -342,7 +343,8 @@ func checkWebhook(c *context.Context) (*OrgRepoCtx, *db.Webhook) { c.Data["History"], err = w.History(1) if err != nil { - c.Handle(500, "History", err) + c.Error(err, "get history") + return nil, nil } return orCtx, w } @@ -358,7 +360,7 @@ func WebHooksEdit(c *context.Context) { } c.Data["Webhook"] = w - c.HTML(200, orCtx.NewTemplate) + c.Success(orCtx.NewTemplate) } func WebHooksEditPost(c *context.Context, f form.NewWebhook) { @@ -373,7 +375,7 @@ func WebHooksEditPost(c *context.Context, f form.NewWebhook) { c.Data["Webhook"] = w if c.HasError() { - c.HTML(200, orCtx.NewTemplate) + c.Success(orCtx.NewTemplate) return } @@ -388,10 +390,10 @@ func WebHooksEditPost(c *context.Context, f form.NewWebhook) { w.HookEvent = ParseHookEvent(f.Webhook) w.IsActive = f.Active if err := w.UpdateEvent(); err != nil { - c.Handle(500, "UpdateEvent", err) + c.Error(err, "update event") return } else if err := db.UpdateWebhook(w); err != nil { - c.Handle(500, "WebHooksEditPost", err) + c.Error(err, "update webhook") return } @@ -411,7 +413,7 @@ func SlackHooksEditPost(c *context.Context, f form.NewSlackHook) { c.Data["Webhook"] = w if c.HasError() { - c.HTML(200, orCtx.NewTemplate) + c.Success(orCtx.NewTemplate) return } @@ -422,7 +424,7 @@ func SlackHooksEditPost(c *context.Context, f form.NewSlackHook) { Color: f.Color, }) if err != nil { - c.Handle(500, "Marshal", err) + c.Error(err, "marshal JSON") return } @@ -431,10 +433,10 @@ func SlackHooksEditPost(c *context.Context, f form.NewSlackHook) { w.HookEvent = ParseHookEvent(f.Webhook) w.IsActive = f.Active if err := w.UpdateEvent(); err != nil { - c.Handle(500, "UpdateEvent", err) + c.Error(err, "update event") return } else if err := db.UpdateWebhook(w); err != nil { - c.Handle(500, "UpdateWebhook", err) + c.Error(err, "update webhook") return } @@ -455,7 +457,7 @@ func DiscordHooksEditPost(c *context.Context, f form.NewDiscordHook) { c.Data["Webhook"] = w if c.HasError() { - c.HTML(200, orCtx.NewTemplate) + c.Success(orCtx.NewTemplate) return } @@ -465,7 +467,7 @@ func DiscordHooksEditPost(c *context.Context, f form.NewDiscordHook) { Color: f.Color, }) if err != nil { - c.Handle(500, "Marshal", err) + c.Error(err, "marshal JSON") return } @@ -474,10 +476,10 @@ func DiscordHooksEditPost(c *context.Context, f form.NewDiscordHook) { w.HookEvent = ParseHookEvent(f.Webhook) w.IsActive = f.Active if err := w.UpdateEvent(); err != nil { - c.Handle(500, "UpdateEvent", err) + c.Error(err, "update event") return } else if err := db.UpdateWebhook(w); err != nil { - c.Handle(500, "UpdateWebhook", err) + c.Error(err, "update webhook") return } @@ -497,7 +499,7 @@ func DingtalkHooksEditPost(c *context.Context, f form.NewDingtalkHook) { c.Data["Webhook"] = w if c.HasError() { - c.HTML(200, orCtx.NewTemplate) + c.Success(orCtx.NewTemplate) return } @@ -505,10 +507,10 @@ func DingtalkHooksEditPost(c *context.Context, f form.NewDingtalkHook) { w.HookEvent = ParseHookEvent(f.Webhook) w.IsActive = f.Active if err := w.UpdateEvent(); err != nil { - c.Handle(500, "UpdateEvent", err) + c.Error(err, "update event") return } else if err := db.UpdateWebhook(w); err != nil { - c.Handle(500, "UpdateWebhook", err) + c.Error(err, "update webhook") return } @@ -550,22 +552,22 @@ func TestWebhook(c *context.Context) { author, err := db.GetUserByEmail(c.Repo.Commit.Author.Email) if err == nil { authorUsername = author.Name - } else if !errors.IsUserNotExist(err) { - c.Handle(500, "GetUserByEmail.(author)", err) + } else if !db.IsErrUserNotExist(err) { + c.Error(err, "get user by email") return } user, err := db.GetUserByEmail(c.Repo.Commit.Committer.Email) if err == nil { committerUsername = user.Name - } else if !errors.IsUserNotExist(err) { - c.Handle(500, "GetUserByEmail.(committer)", err) + } else if !db.IsErrUserNotExist(err) { + c.Error(err, "get user by email") return } nameStatus, err = c.Repo.Commit.ShowNameStatus() if err != nil { - c.Handle(500, "FileStatus", err) + c.Error(err, "get changed files") return } } @@ -600,34 +602,36 @@ func TestWebhook(c *context.Context) { Sender: apiUser, } if err := db.TestWebhook(c.Repo.Repository, db.HOOK_EVENT_PUSH, p, c.ParamsInt64("id")); err != nil { - c.Handle(500, "TestWebhook", err) - } else { - c.Flash.Info(c.Tr("repo.settings.webhook.test_delivery_success")) - c.Status(200) + c.Error(err, "test webhook") + return } + + c.Flash.Info(c.Tr("repo.settings.webhook.test_delivery_success")) + c.Status(http.StatusOK) } func RedeliveryWebhook(c *context.Context) { webhook, err := db.GetWebhookOfRepoByID(c.Repo.Repository.ID, c.ParamsInt64(":id")) if err != nil { - c.NotFoundOrServerError("GetWebhookOfRepoByID/GetWebhookByOrgID", errors.IsWebhookNotExist, err) + c.NotFoundOrError(err, "get webhook") return } hookTask, err := db.GetHookTaskOfWebhookByUUID(webhook.ID, c.Query("uuid")) if err != nil { - c.NotFoundOrServerError("GetHookTaskOfWebhookByUUID/GetWebhookByOrgID", errors.IsHookTaskNotExist, err) + c.NotFoundOrError(err, "get hook task by UUID") return } hookTask.IsDelivered = false if err = db.UpdateHookTask(hookTask); err != nil { - c.Handle(500, "UpdateHookTask", err) - } else { - go db.HookQueue.Add(c.Repo.Repository.ID) - c.Flash.Info(c.Tr("repo.settings.webhook.redelivery_success", hookTask.UUID)) - c.Status(200) + c.Error(err, "update hook task") + return } + + go db.HookQueue.Add(c.Repo.Repository.ID) + c.Flash.Info(c.Tr("repo.settings.webhook.redelivery_success", hookTask.UUID)) + c.Status(http.StatusOK) } func DeleteWebhook(c *context.Context) { @@ -637,7 +641,7 @@ func DeleteWebhook(c *context.Context) { c.Flash.Success(c.Tr("repo.settings.webhook_deletion_success")) } - c.JSON(200, map[string]interface{}{ + c.JSONSuccess(map[string]interface{}{ "redirect": c.Repo.RepoLink + "/settings/hooks", }) } diff --git a/internal/route/repo/wiki.go b/internal/route/repo/wiki.go index 91bc3c915..b9f754ee4 100644 --- a/internal/route/repo/wiki.go +++ b/internal/route/repo/wiki.go @@ -26,7 +26,7 @@ const ( func MustEnableWiki(c *context.Context) { if !c.Repo.Repository.EnableWiki { - c.Handle(404, "MustEnableWiki", nil) + c.NotFound() return } @@ -45,12 +45,12 @@ type PageMeta struct { func renderWikiPage(c *context.Context, isViewPage bool) (*git.Repository, string) { wikiRepo, err := git.Open(c.Repo.Repository.WikiPath()) if err != nil { - c.ServerError("open repository", err) + c.Error(err, "open repository") return nil, "" } commit, err := wikiRepo.BranchCommit("master") if err != nil { - c.ServerError("get branch commit", err) + c.Error(err, "get branch commit") return nil, "" } @@ -58,7 +58,7 @@ func renderWikiPage(c *context.Context, isViewPage bool) (*git.Repository, strin if isViewPage { entries, err := commit.Entries() if err != nil { - c.ServerError("list entries", err) + c.Error(err, "list entries") return nil, "" } pages := make([]PageMeta, 0, len(entries)) @@ -91,13 +91,13 @@ func renderWikiPage(c *context.Context, isViewPage bool) (*git.Repository, strin if gitutil.IsErrRevisionNotExist(err) { c.Redirect(c.Repo.RepoLink + "/wiki/_pages") } else { - c.ServerError("GetBlobByPath", err) + c.Error(err, "get blob") } return nil, "" } p, err := blob.Bytes() if err != nil { - c.ServerError("Data", err) + c.Error(err, "read blob") return nil, "" } if isViewPage { @@ -114,7 +114,7 @@ func Wiki(c *context.Context) { if !c.Repo.Repository.HasWiki() { c.Data["Title"] = c.Tr("repo.wiki") - c.HTML(200, WIKI_START) + c.Success(WIKI_START) return } @@ -126,12 +126,12 @@ func Wiki(c *context.Context) { // Get last change information. commits, err := wikiRepo.Log(git.RefsHeads+"master", git.LogOptions{Path: pageName + ".md"}) if err != nil { - c.ServerError("get commits by path", err) + c.Error(err, "get commits by path") return } c.Data["Author"] = commits[0].Author - c.HTML(200, WIKI_VIEW) + c.Success(WIKI_VIEW) } func WikiPages(c *context.Context) { @@ -145,18 +145,18 @@ func WikiPages(c *context.Context) { wikiRepo, err := git.Open(c.Repo.Repository.WikiPath()) if err != nil { - c.ServerError("open repository", err) + c.Error(err, "open repository") return } commit, err := wikiRepo.BranchCommit("master") if err != nil { - c.ServerError("get branch commit", err) + c.Error(err, "get branch commit") return } entries, err := commit.Entries() if err != nil { - c.ServerError("list entries", err) + c.Error(err, "list entries") return } pages := make([]PageMeta, 0, len(entries)) @@ -164,7 +164,7 @@ func WikiPages(c *context.Context) { if entries[i].Type() == git.ObjectBlob && strings.HasSuffix(entries[i].Name(), ".md") { commits, err := wikiRepo.Log(git.RefsHeads+"master", git.LogOptions{Path: entries[i].Name()}) if err != nil { - c.ServerError("get commits by path", err) + c.Error(err, "get commits by path") return } name := strings.TrimSuffix(entries[i].Name(), ".md") @@ -177,7 +177,7 @@ func WikiPages(c *context.Context) { } c.Data["Pages"] = pages - c.HTML(200, WIKI_PAGES) + c.Success(WIKI_PAGES) } func NewWiki(c *context.Context) { @@ -189,7 +189,7 @@ func NewWiki(c *context.Context) { c.Data["title"] = "Home" } - c.HTML(200, WIKI_NEW) + c.Success(WIKI_NEW) } func NewWikiPost(c *context.Context, f form.NewWiki) { @@ -198,7 +198,7 @@ func NewWikiPost(c *context.Context, f form.NewWiki) { c.Data["RequireSimpleMDE"] = true if c.HasError() { - c.HTML(200, WIKI_NEW) + c.Success(WIKI_NEW) return } @@ -207,7 +207,7 @@ func NewWikiPost(c *context.Context, f form.NewWiki) { c.Data["Err_Title"] = true c.RenderWithErr(c.Tr("repo.wiki.page_already_exists"), WIKI_NEW, &f) } else { - c.ServerError("AddWikiPage", err) + c.Error(err, "add wiki page") } return } @@ -230,7 +230,7 @@ func EditWiki(c *context.Context) { return } - c.HTML(200, WIKI_NEW) + c.Success(WIKI_NEW) } func EditWikiPost(c *context.Context, f form.NewWiki) { @@ -239,12 +239,12 @@ func EditWikiPost(c *context.Context, f form.NewWiki) { c.Data["RequireSimpleMDE"] = true if c.HasError() { - c.HTML(200, WIKI_NEW) + c.Success(WIKI_NEW) return } if err := c.Repo.Repository.EditWikiPage(c.User, f.OldTitle, f.Title, f.Content, f.Message); err != nil { - c.ServerError("EditWikiPage", err) + c.Error(err, "edit wiki page") return } @@ -259,11 +259,11 @@ func DeleteWikiPagePost(c *context.Context) { pageName := db.ToWikiPageName(pageURL) if err := c.Repo.Repository.DeleteWikiPage(c.User, pageName); err != nil { - c.ServerError("DeleteWikiPage", err) + c.Error(err, "delete wiki page") return } - c.JSON(200, map[string]interface{}{ + c.JSONSuccess(map[string]interface{}{ "redirect": c.Repo.RepoLink + "/wiki/", }) } diff --git a/internal/route/user/auth.go b/internal/route/user/auth.go index 88b0d1e85..5fef81c30 100644 --- a/internal/route/user/auth.go +++ b/internal/route/user/auth.go @@ -53,8 +53,8 @@ func AutoLogin(c *context.Context) (bool, error) { u, err := db.GetUserByName(uname) if err != nil { - if !errors.IsUserNotExist(err) { - return false, fmt.Errorf("GetUserByName: %v", err) + if !db.IsErrUserNotExist(err) { + return false, fmt.Errorf("get user by name: %v", err) } return false, nil } @@ -79,7 +79,7 @@ func Login(c *context.Context) { // Check auto-login isSucceed, err := AutoLogin(c) if err != nil { - c.ServerError("AutoLogin", err) + c.Error(err, "auto login") return } @@ -94,7 +94,7 @@ func Login(c *context.Context) { if tool.IsSameSiteURLPath(redirectTo) { c.Redirect(redirectTo) } else { - c.SubURLRedirect("/") + c.RedirectSubpath("/") } c.SetCookie("redirect_to", "", -1, conf.Server.Subpath) return @@ -103,7 +103,7 @@ func Login(c *context.Context) { // Display normal login page loginSources, err := db.ActivatedLoginSources() if err != nil { - c.ServerError("ActivatedLoginSources", err) + c.Error(err, "list activated login sources") return } c.Data["LoginSources"] = loginSources @@ -142,7 +142,7 @@ func afterLogin(c *context.Context, u *db.User, remember bool) { return } - c.SubURLRedirect("/") + c.RedirectSubpath("/") } func LoginPost(c *context.Context, f form.SignIn) { @@ -150,7 +150,7 @@ func LoginPost(c *context.Context, f form.SignIn) { loginSources, err := db.ActivatedLoginSources() if err != nil { - c.ServerError("ActivatedLoginSources", err) + c.Error(err, "list activated login sources") return } c.Data["LoginSources"] = loginSources @@ -163,7 +163,7 @@ func LoginPost(c *context.Context, f form.SignIn) { u, err := db.UserLogin(f.UserName, f.Password, f.LoginSource) if err != nil { switch err.(type) { - case errors.UserNotExist: + case db.ErrUserNotExist: c.FormErr("UserName", "Password") c.RenderWithErr(c.Tr("form.username_password_incorrect"), LOGIN, &f) case errors.LoginSourceMismatch: @@ -171,7 +171,7 @@ func LoginPost(c *context.Context, f form.SignIn) { c.RenderWithErr(c.Tr("form.auth_source_mismatch"), LOGIN, &f) default: - c.ServerError("UserLogin", err) + c.Error(err, "authenticate user") } for i := range loginSources { if loginSources[i].IsDefault { @@ -189,7 +189,7 @@ func LoginPost(c *context.Context, f form.SignIn) { c.Session.Set("twoFactorRemember", f.Remember) c.Session.Set("twoFactorUserID", u.ID) - c.SubURLRedirect("/user/login/two_factor") + c.RedirectSubpath("/user/login/two_factor") } func LoginTwoFactor(c *context.Context) { @@ -211,31 +211,31 @@ func LoginTwoFactorPost(c *context.Context) { t, err := db.GetTwoFactorByUserID(userID) if err != nil { - c.ServerError("GetTwoFactorByUserID", err) + c.Error(err, "get two factor by user ID") return } passcode := c.Query("passcode") valid, err := t.ValidateTOTP(passcode) if err != nil { - c.ServerError("ValidateTOTP", err) + c.Error(err, "validate TOTP") return } else if !valid { c.Flash.Error(c.Tr("settings.two_factor_invalid_passcode")) - c.SubURLRedirect("/user/login/two_factor") + c.RedirectSubpath("/user/login/two_factor") return } u, err := db.GetUserByID(userID) if err != nil { - c.ServerError("GetUserByID", err) + c.Error(err, "get user by ID") return } // Prevent same passcode from being reused if c.Cache.IsExist(u.TwoFactorCacheKey(passcode)) { c.Flash.Error(c.Tr("settings.two_factor_reused_passcode")) - c.SubURLRedirect("/user/login/two_factor") + c.RedirectSubpath("/user/login/two_factor") return } if err = c.Cache.Put(u.TwoFactorCacheKey(passcode), 1, 60); err != nil { @@ -265,16 +265,16 @@ func LoginTwoFactorRecoveryCodePost(c *context.Context) { if err := db.UseRecoveryCode(userID, c.Query("recovery_code")); err != nil { if errors.IsTwoFactorRecoveryCodeNotFound(err) { c.Flash.Error(c.Tr("auth.login_two_factor_invalid_recovery_code")) - c.SubURLRedirect("/user/login/two_factor_recovery_code") + c.RedirectSubpath("/user/login/two_factor_recovery_code") } else { - c.ServerError("UseRecoveryCode", err) + c.Error(err, "use recovery code") } return } u, err := db.GetUserByID(userID) if err != nil { - c.ServerError("GetUserByID", err) + c.Error(err, "get user by ID") return } afterLogin(c, u, c.Session.Get("twoFactorRemember").(bool)) @@ -286,7 +286,7 @@ func SignOut(c *context.Context) { c.SetCookie(conf.Security.CookieUsername, "", -1, conf.Server.Subpath) c.SetCookie(conf.Security.CookieRememberName, "", -1, conf.Server.Subpath) c.SetCookie(conf.Session.CSRFCookieName, "", -1, conf.Server.Subpath) - c.SubURLRedirect("/") + c.RedirectSubpath("/") } func SignUp(c *context.Context) { @@ -351,7 +351,7 @@ func SignUpPost(c *context.Context, cpt *captcha.Captcha, f form.Register) { c.FormErr("UserName") c.RenderWithErr(c.Tr("user.form.name_pattern_not_allowed", err.(db.ErrNamePatternNotAllowed).Pattern), SIGNUP, &f) default: - c.ServerError("CreateUser", err) + c.Error(err, "create user") } return } @@ -362,7 +362,7 @@ func SignUpPost(c *context.Context, cpt *captcha.Captcha, f form.Register) { u.IsAdmin = true u.IsActive = true if err := db.UpdateUser(u); err != nil { - c.ServerError("UpdateUser", err) + c.Error(err, "update user") return } } @@ -381,7 +381,7 @@ func SignUpPost(c *context.Context, cpt *captcha.Captcha, f form.Register) { return } - c.SubURLRedirect("/user/login") + c.RedirectSubpath("/user/login") } func Activate(c *context.Context) { @@ -416,11 +416,11 @@ func Activate(c *context.Context) { user.IsActive = true var err error if user.Rands, err = db.GetUserSalt(); err != nil { - c.ServerError("GetUserSalt", err) + c.Error(err, "get user salt") return } if err := db.UpdateUser(user); err != nil { - c.ServerError("UpdateUser", err) + c.Error(err, "update user") return } @@ -428,7 +428,7 @@ func Activate(c *context.Context) { c.Session.Set("uid", user.ID) c.Session.Set("uname", user.Name) - c.SubURLRedirect("/") + c.RedirectSubpath("/") return } @@ -443,14 +443,14 @@ func ActivateEmail(c *context.Context) { // Verify code. if email := db.VerifyActiveEmailCode(code, emailAddr); email != nil { if err := email.Activate(); err != nil { - c.ServerError("ActivateEmail", err) + c.Error(err, "activate email") } log.Trace("Email activated: %s", email.Email) c.Flash.Success(c.Tr("settings.add_email_success")) } - c.SubURLRedirect("/user/settings/email") + c.RedirectSubpath("/user/settings/email") } func ForgotPasswd(c *context.Context) { @@ -480,14 +480,14 @@ func ForgotPasswdPost(c *context.Context) { u, err := db.GetUserByEmail(emailAddr) if err != nil { - if errors.IsUserNotExist(err) { + if db.IsErrUserNotExist(err) { c.Data["Hours"] = conf.Auth.ActivateCodeLives / 60 c.Data["IsResetSent"] = true c.Success(FORGOT_PASSWORD) return - } else { - c.ServerError("GetUserByEmail", err) } + + c.Error(err, "get user by email") return } @@ -549,21 +549,21 @@ func ResetPasswdPost(c *context.Context) { u.Passwd = passwd var err error if u.Rands, err = db.GetUserSalt(); err != nil { - c.ServerError("GetUserSalt", err) + c.Error(err, "get user salt") return } if u.Salt, err = db.GetUserSalt(); err != nil { - c.ServerError("GetUserSalt", err) + c.Error(err, "get user salt") return } u.EncodePasswd() if err := db.UpdateUser(u); err != nil { - c.ServerError("UpdateUser", err) + c.Error(err, "update user") return } log.Trace("User password reset: %s", u.Name) - c.SubURLRedirect("/user/login") + c.RedirectSubpath("/user/login") return } diff --git a/internal/route/user/home.go b/internal/route/user/home.go index d2d23fba0..5ba9bb17f 100644 --- a/internal/route/user/home.go +++ b/internal/route/user/home.go @@ -7,6 +7,7 @@ package user import ( "bytes" "fmt" + "net/http" "github.com/unknwon/com" "github.com/unknwon/paginater" @@ -14,7 +15,6 @@ import ( "gogs.io/gogs/internal/conf" "gogs.io/gogs/internal/context" "gogs.io/gogs/internal/db" - "gogs.io/gogs/internal/db/errors" ) const ( @@ -33,7 +33,7 @@ func getDashboardContextUser(c *context.Context) *db.User { // Organization. org, err := db.GetUserByName(orgName) if err != nil { - c.NotFoundOrServerError("GetUserByName", errors.IsUserNotExist, err) + c.NotFoundOrError(err, "get user by name") return nil } ctxUser = org @@ -41,7 +41,7 @@ func getDashboardContextUser(c *context.Context) *db.User { c.Data["ContextUser"] = ctxUser if err := c.User.GetOrganizations(true); err != nil { - c.Handle(500, "GetOrganizations", err) + c.Error(err, "get organizations") return nil } c.Data["Orgs"] = c.User.Orgs @@ -55,7 +55,7 @@ func getDashboardContextUser(c *context.Context) *db.User { func retrieveFeeds(c *context.Context, ctxUser *db.User, userID int64, isProfile bool) { actions, err := db.GetFeeds(ctxUser, userID, c.QueryInt64("after_id"), isProfile) if err != nil { - c.Handle(500, "GetFeeds", err) + c.Error(err, "get feeds") return } @@ -68,10 +68,10 @@ func retrieveFeeds(c *context.Context, ctxUser *db.User, userID int64, isProfile if !ok { u, err := db.GetUserByName(act.ActUserName) if err != nil { - if errors.IsUserNotExist(err) { + if db.IsErrUserNotExist(err) { continue } - c.Handle(500, "GetUserByName", err) + c.Error(err, "get user by name") return } unameAvatars[act.ActUserName] = u.RelAvatarLink() @@ -100,7 +100,7 @@ func Dashboard(c *context.Context) { } if c.Req.Header.Get("X-AJAX") == "true" { - c.HTML(200, NEWS_FEED) + c.Success(NEWS_FEED) return } @@ -112,10 +112,10 @@ func Dashboard(c *context.Context) { if !ctxUser.IsOrganization() { collaborateRepos, err := c.User.GetAccessibleRepositories(conf.UI.User.RepoPagingNum) if err != nil { - c.Handle(500, "GetAccessibleRepositories", err) + c.Error(err, "get accessible repositories") return } else if err = db.RepositoryList(collaborateRepos).LoadAttributes(); err != nil { - c.Handle(500, "RepositoryList.LoadAttributes", err) + c.Error(err, "load attributes") return } c.Data["CollaborativeRepos"] = collaborateRepos @@ -127,18 +127,18 @@ func Dashboard(c *context.Context) { if ctxUser.IsOrganization() { repos, repoCount, err = ctxUser.GetUserRepositories(c.User.ID, 1, conf.UI.User.RepoPagingNum) if err != nil { - c.Handle(500, "GetUserRepositories", err) + c.Error(err, "get user repositories") return } mirrors, err = ctxUser.GetUserMirrorRepositories(c.User.ID) if err != nil { - c.Handle(500, "GetUserMirrorRepositories", err) + c.Error(err, "get user mirror repositories") return } } else { if err = ctxUser.GetRepositories(1, conf.UI.User.RepoPagingNum); err != nil { - c.Handle(500, "GetRepositories", err) + c.Error(err, "get repositories") return } repos = ctxUser.Repos @@ -146,7 +146,7 @@ func Dashboard(c *context.Context) { mirrors, err = ctxUser.GetMirrorRepositories() if err != nil { - c.Handle(500, "GetMirrorRepositories", err) + c.Error(err, "get mirror repositories") return } } @@ -155,13 +155,13 @@ func Dashboard(c *context.Context) { c.Data["MaxShowRepoNum"] = conf.UI.User.RepoPagingNum if err := db.MirrorRepositoryList(mirrors).LoadAttributes(); err != nil { - c.Handle(500, "MirrorRepositoryList.LoadAttributes", err) + c.Error(err, "load attributes") return } c.Data["MirrorCount"] = len(mirrors) c.Data["Mirrors"] = mirrors - c.HTML(200, DASHBOARD) + c.Success(DASHBOARD) } func Issues(c *context.Context) { @@ -216,12 +216,12 @@ func Issues(c *context.Context) { if ctxUser.IsOrganization() { repos, _, err = ctxUser.GetUserRepositories(c.User.ID, 1, ctxUser.NumRepos) if err != nil { - c.Handle(500, "GetRepositories", err) + c.Error(err, "get repositories") return } } else { if err := ctxUser.GetRepositories(1, c.User.NumRepos); err != nil { - c.Handle(500, "GetRepositories", err) + c.Error(err, "get repositories") return } repos = ctxUser.Repos @@ -255,7 +255,7 @@ func Issues(c *context.Context) { if !isPullList { userRepoIDs, err = db.FilterRepositoryWithIssues(userRepoIDs) if err != nil { - c.Handle(500, "FilterRepositoryWithIssues", err) + c.Error(err, "filter repositories with issues") return } } @@ -287,32 +287,32 @@ func Issues(c *context.Context) { issues, err := db.Issues(issueOptions) if err != nil { - c.Handle(500, "Issues", err) + c.Error(err, "list issues") return } if repoID > 0 { repo, err := db.GetRepositoryByID(repoID) if err != nil { - c.Handle(500, "GetRepositoryByID", fmt.Errorf("[#%d] %v", repoID, err)) + c.Error(err, "get repository by ID") return } if err = repo.GetOwner(); err != nil { - c.Handle(500, "GetOwner", fmt.Errorf("[#%d] %v", repoID, err)) + c.Error(err, "get owner") return } // Check if user has access to given repository. if !repo.IsOwnedBy(ctxUser.ID) && !repo.HasAccess(ctxUser.ID) { - c.Handle(404, "Issues", fmt.Errorf("#%d", repoID)) + c.NotFound() return } } for _, issue := range issues { if err = issue.Repo.GetOwner(); err != nil { - c.Handle(500, "GetOwner", fmt.Errorf("[#%d] %v", issue.RepoID, err)) + c.Error(err, "get owner") return } } @@ -341,13 +341,13 @@ func Issues(c *context.Context) { c.Data["State"] = "open" } - c.HTML(200, ISSUES) + c.Success(ISSUES) } func ShowSSHKeys(c *context.Context, uid int64) { keys, err := db.ListPublicKeys(uid) if err != nil { - c.Handle(500, "ListPublicKeys", err) + c.Error(err, "list public keys") return } @@ -356,7 +356,7 @@ func ShowSSHKeys(c *context.Context, uid int64) { buf.WriteString(keys[i].OmitEmail()) buf.WriteString("\n") } - c.PlainText(200, buf.Bytes()) + c.PlainText(http.StatusOK, buf.String()) } func showOrgProfile(c *context.Context) { @@ -382,7 +382,7 @@ func showOrgProfile(c *context.Context) { if c.IsLogged && !c.User.IsAdmin { repos, count, err = org.GetUserRepositories(c.User.ID, page, conf.UI.User.RepoPagingNum) if err != nil { - c.Handle(500, "GetUserRepositories", err) + c.Error(err, "get user repositories") return } c.Data["Repos"] = repos @@ -395,7 +395,7 @@ func showOrgProfile(c *context.Context) { PageSize: conf.UI.User.RepoPagingNum, }) if err != nil { - c.Handle(500, "GetRepositories", err) + c.Error(err, "get user repositories") return } c.Data["Repos"] = repos @@ -404,20 +404,20 @@ func showOrgProfile(c *context.Context) { c.Data["Page"] = paginater.New(int(count), conf.UI.User.RepoPagingNum, page, 5) if err := org.GetMembers(); err != nil { - c.Handle(500, "GetMembers", err) + c.Error(err, "get members") return } c.Data["Members"] = org.Members c.Data["Teams"] = org.Teams - c.HTML(200, ORG_HOME) + c.Success(ORG_HOME) } func Email2User(c *context.Context) { u, err := db.GetUserByEmail(c.Query("email")) if err != nil { - c.NotFoundOrServerError("GetUserByEmail", errors.IsUserNotExist, err) + c.NotFoundOrError(err, "get user by email") return } c.Redirect(conf.Server.Subpath + "/user/" + u.Name) diff --git a/internal/route/user/profile.go b/internal/route/user/profile.go index d18b35f8f..89d845092 100644 --- a/internal/route/user/profile.go +++ b/internal/route/user/profile.go @@ -5,15 +5,14 @@ package user import ( - "fmt" - repo2 "gogs.io/gogs/internal/route/repo" "strings" "github.com/unknwon/paginater" + "gogs.io/gogs/internal/conf" "gogs.io/gogs/internal/context" "gogs.io/gogs/internal/db" - "gogs.io/gogs/internal/conf" + "gogs.io/gogs/internal/route/repo" "gogs.io/gogs/internal/tool" ) @@ -45,7 +44,7 @@ func Profile(c *context.Context, puser *context.ParamsUser) { orgs, err := db.GetOrgsByUserID(puser.ID, c.IsLogged && (c.User.IsAdmin || c.User.ID == puser.ID)) if err != nil { - c.ServerError("GetOrgsByUserIDDesc", err) + c.Error(err, "get organizations by user ID") return } @@ -73,7 +72,7 @@ func Profile(c *context.Context, puser *context.ParamsUser) { PageSize: conf.UI.User.RepoPagingNum, }) if err != nil { - c.ServerError("GetRepositories", err) + c.Error(err, "get user repositories") return } @@ -89,7 +88,7 @@ func Followers(c *context.Context, puser *context.ParamsUser) { c.PageIs("Followers") c.Data["CardsTitle"] = c.Tr("user.followers") c.Data["Owner"] = puser - repo2.RenderUserCards(c, puser.NumFollowers, puser.GetFollowers, FOLLOWERS) + repo.RenderUserCards(c, puser.NumFollowers, puser.GetFollowers, FOLLOWERS) } func Following(c *context.Context, puser *context.ParamsUser) { @@ -97,7 +96,7 @@ func Following(c *context.Context, puser *context.ParamsUser) { c.PageIs("Following") c.Data["CardsTitle"] = c.Tr("user.following") c.Data["Owner"] = puser - repo2.RenderUserCards(c, puser.NumFollowing, puser.GetFollowing, FOLLOWERS) + repo.RenderUserCards(c, puser.NumFollowing, puser.GetFollowing, FOLLOWERS) } func Stars(c *context.Context) { @@ -114,7 +113,7 @@ func Action(c *context.Context, puser *context.ParamsUser) { } if err != nil { - c.ServerError(fmt.Sprintf("Action (%s)", c.Params(":action")), err) + c.Errorf(err, "action %q", c.Params(":action")) return } diff --git a/internal/route/user/setting.go b/internal/route/user/setting.go index f09e40340..d8ae9e70f 100644 --- a/internal/route/user/setting.go +++ b/internal/route/user/setting.go @@ -80,7 +80,7 @@ func SettingsPost(c *context.Context, f form.UpdateProfile) { case db.IsErrNamePatternNotAllowed(err): msg = c.Tr("form.name_pattern_not_allowed") default: - c.ServerError("ChangeUserName", err) + c.Error(err, "change user name") return } @@ -106,12 +106,12 @@ func SettingsPost(c *context.Context, f form.UpdateProfile) { c.RenderWithErr(msg, SETTINGS_PROFILE, &f) return } - c.ServerError("UpdateUser", err) + c.Errorf(err, "update user") return } c.Flash.Success(c.Tr("settings.update_profile_success")) - c.SubURLRedirect("/user/settings") + c.RedirectSubpath("/user/settings") } // FIXME: limit upload size @@ -169,7 +169,7 @@ func SettingsAvatarPost(c *context.Context, f form.Avatar) { c.Flash.Success(c.Tr("settings.update_avatar_success")) } - c.SubURLRedirect("/user/settings/avatar") + c.RedirectSubpath("/user/settings/avatar") } func SettingsDeleteAvatar(c *context.Context) { @@ -177,7 +177,7 @@ func SettingsDeleteAvatar(c *context.Context) { c.Flash.Error(fmt.Sprintf("Failed to delete avatar: %v", err)) } - c.SubURLRedirect("/user/settings/avatar") + c.RedirectSubpath("/user/settings/avatar") } func SettingsPassword(c *context.Context) { @@ -203,18 +203,18 @@ func SettingsPasswordPost(c *context.Context, f form.ChangePassword) { c.User.Passwd = f.Password var err error if c.User.Salt, err = db.GetUserSalt(); err != nil { - c.ServerError("GetUserSalt", err) + c.Errorf(err, "get user salt") return } c.User.EncodePasswd() if err := db.UpdateUser(c.User); err != nil { - c.ServerError("UpdateUser", err) + c.Errorf(err, "update user") return } c.Flash.Success(c.Tr("settings.change_password_success")) } - c.SubURLRedirect("/user/settings/password") + c.RedirectSubpath("/user/settings/password") } func SettingsEmails(c *context.Context) { @@ -223,7 +223,7 @@ func SettingsEmails(c *context.Context) { emails, err := db.GetEmailAddresses(c.User.ID) if err != nil { - c.ServerError("GetEmailAddresses", err) + c.Errorf(err, "get email addresses") return } c.Data["Emails"] = emails @@ -238,18 +238,18 @@ func SettingsEmailPost(c *context.Context, f form.AddEmail) { // Make emailaddress primary. if c.Query("_method") == "PRIMARY" { if err := db.MakeEmailPrimary(c.UserID(), &db.EmailAddress{ID: c.QueryInt64("id")}); err != nil { - c.ServerError("MakeEmailPrimary", err) + c.Errorf(err, "make email primary") return } - c.SubURLRedirect("/user/settings/email") + c.RedirectSubpath("/user/settings/email") return } // Add Email address. emails, err := db.GetEmailAddresses(c.User.ID) if err != nil { - c.ServerError("GetEmailAddresses", err) + c.Errorf(err, "get email addresses") return } c.Data["Emails"] = emails @@ -268,7 +268,7 @@ func SettingsEmailPost(c *context.Context, f form.AddEmail) { if db.IsErrEmailAlreadyUsed(err) { c.RenderWithErr(c.Tr("form.email_been_used"), SETTINGS_EMAILS, &f) } else { - c.ServerError("AddEmailAddress", err) + c.Errorf(err, "add email address") } return } @@ -285,7 +285,7 @@ func SettingsEmailPost(c *context.Context, f form.AddEmail) { c.Flash.Success(c.Tr("settings.add_email_success")) } - c.SubURLRedirect("/user/settings/email") + c.RedirectSubpath("/user/settings/email") } func DeleteEmail(c *context.Context) { @@ -293,7 +293,7 @@ func DeleteEmail(c *context.Context) { ID: c.QueryInt64("id"), UID: c.User.ID, }); err != nil { - c.ServerError("DeleteEmailAddress", err) + c.Errorf(err, "delete email address") return } @@ -309,7 +309,7 @@ func SettingsSSHKeys(c *context.Context) { keys, err := db.ListPublicKeys(c.User.ID) if err != nil { - c.ServerError("ListPublicKeys", err) + c.Errorf(err, "list public keys") return } c.Data["Keys"] = keys @@ -323,7 +323,7 @@ func SettingsSSHKeysPost(c *context.Context, f form.AddSSHKey) { keys, err := db.ListPublicKeys(c.User.ID) if err != nil { - c.ServerError("ListPublicKeys", err) + c.Errorf(err, "list public keys") return } c.Data["Keys"] = keys @@ -339,7 +339,7 @@ func SettingsSSHKeysPost(c *context.Context, f form.AddSSHKey) { c.Flash.Info(c.Tr("form.unable_verify_ssh_key")) } else { c.Flash.Error(c.Tr("form.invalid_ssh_key", err.Error())) - c.SubURLRedirect("/user/settings/ssh") + c.RedirectSubpath("/user/settings/ssh") return } } @@ -354,13 +354,13 @@ func SettingsSSHKeysPost(c *context.Context, f form.AddSSHKey) { c.FormErr("Title") c.RenderWithErr(c.Tr("settings.ssh_key_name_used"), SETTINGS_SSH_KEYS, &f) default: - c.ServerError("AddPublicKey", err) + c.Errorf(err, "add public key") } return } c.Flash.Success(c.Tr("settings.add_key_success", f.Title)) - c.SubURLRedirect("/user/settings/ssh") + c.RedirectSubpath("/user/settings/ssh") } func DeleteSSHKey(c *context.Context) { @@ -381,7 +381,7 @@ func SettingsSecurity(c *context.Context) { t, err := db.GetTwoFactorByUserID(c.UserID()) if err != nil && !errors.IsTwoFactorNotFound(err) { - c.ServerError("GetTwoFactorByUserID", err) + c.Errorf(err, "get two factor by user ID") return } c.Data["TwoFactor"] = t @@ -410,7 +410,7 @@ func SettingsTwoFactorEnable(c *context.Context) { AccountName: c.User.Email, }) if err != nil { - c.ServerError("Generate", err) + c.Errorf(err, "generate TOTP") return } } @@ -418,13 +418,13 @@ func SettingsTwoFactorEnable(c *context.Context) { img, err := key.Image(240, 240) if err != nil { - c.ServerError("Image", err) + c.Errorf(err, "generate image") return } var buf bytes.Buffer if err = png.Encode(&buf, img); err != nil { - c.ServerError("Encode", err) + c.Errorf(err, "encode image") return } c.Data["QRCode"] = template.URL("data:image/png;base64," + base64.StdEncoding.EncodeToString(buf.Bytes())) @@ -443,20 +443,20 @@ func SettingsTwoFactorEnablePost(c *context.Context) { if !totp.Validate(c.Query("passcode"), secret) { c.Flash.Error(c.Tr("settings.two_factor_invalid_passcode")) - c.SubURLRedirect("/user/settings/security/two_factor_enable") + c.RedirectSubpath("/user/settings/security/two_factor_enable") return } if err := db.NewTwoFactor(c.UserID(), secret); err != nil { c.Flash.Error(c.Tr("settings.two_factor_enable_error", err)) - c.SubURLRedirect("/user/settings/security/two_factor_enable") + c.RedirectSubpath("/user/settings/security/two_factor_enable") return } c.Session.Delete("twoFactorSecret") c.Session.Delete("twoFactorURL") c.Flash.Success(c.Tr("settings.two_factor_enable_success")) - c.SubURLRedirect("/user/settings/security/two_factor_recovery_codes") + c.RedirectSubpath("/user/settings/security/two_factor_recovery_codes") } func SettingsTwoFactorRecoveryCodes(c *context.Context) { @@ -470,7 +470,7 @@ func SettingsTwoFactorRecoveryCodes(c *context.Context) { recoveryCodes, err := db.GetRecoveryCodesByUserID(c.UserID()) if err != nil { - c.ServerError("GetRecoveryCodesByUserID", err) + c.Errorf(err, "get recovery codes by user ID") return } c.Data["RecoveryCodes"] = recoveryCodes @@ -490,7 +490,7 @@ func SettingsTwoFactorRecoveryCodesPost(c *context.Context) { c.Flash.Success(c.Tr("settings.two_factor_regenerate_recovery_codes_success")) } - c.SubURLRedirect("/user/settings/security/two_factor_recovery_codes") + c.RedirectSubpath("/user/settings/security/two_factor_recovery_codes") } func SettingsTwoFactorDisable(c *context.Context) { @@ -500,7 +500,7 @@ func SettingsTwoFactorDisable(c *context.Context) { } if err := db.DeleteTwoFactor(c.UserID()); err != nil { - c.ServerError("DeleteTwoFactor", err) + c.Errorf(err, "delete two factor") return } @@ -516,11 +516,11 @@ func SettingsRepos(c *context.Context) { repos, err := db.GetUserAndCollaborativeRepositories(c.User.ID) if err != nil { - c.ServerError("GetUserAndCollaborativeRepositories", err) + c.Errorf(err, "get user and collaborative repositories") return } if err = db.RepositoryList(repos).LoadAttributes(); err != nil { - c.ServerError("LoadAttributes", err) + c.Errorf(err, "load attributes") return } c.Data["Repos"] = repos @@ -531,12 +531,12 @@ func SettingsRepos(c *context.Context) { func SettingsLeaveRepo(c *context.Context) { repo, err := db.GetRepositoryByID(c.QueryInt64("id")) if err != nil { - c.NotFoundOrServerError("GetRepositoryByID", errors.IsRepoNotExist, err) + c.NotFoundOrError(err, "get repository by ID") return } if err = repo.DeleteCollaboration(c.User.ID); err != nil { - c.ServerError("DeleteCollaboration", err) + c.Errorf(err, "delete collaboration") return } @@ -552,7 +552,7 @@ func SettingsOrganizations(c *context.Context) { orgs, err := db.GetOrgsByUserID(c.User.ID, true) if err != nil { - c.ServerError("GetOrgsByUserID", err) + c.Errorf(err, "get organizations by user ID") return } c.Data["Orgs"] = orgs @@ -565,7 +565,7 @@ func SettingsLeaveOrganization(c *context.Context) { if db.IsErrLastOrgOwner(err) { c.Flash.Error(c.Tr("form.last_org_owner")) } else { - c.ServerError("RemoveOrgUser", err) + c.Errorf(err, "remove organization user") return } } @@ -581,7 +581,7 @@ func SettingsApplications(c *context.Context) { tokens, err := db.ListAccessTokens(c.User.ID) if err != nil { - c.ServerError("ListAccessTokens", err) + c.Errorf(err, "list access tokens") return } c.Data["Tokens"] = tokens @@ -596,7 +596,7 @@ func SettingsApplicationsPost(c *context.Context, f form.NewAccessToken) { if c.HasError() { tokens, err := db.ListAccessTokens(c.User.ID) if err != nil { - c.ServerError("ListAccessTokens", err) + c.Errorf(err, "list access tokens") return } @@ -612,16 +612,16 @@ func SettingsApplicationsPost(c *context.Context, f form.NewAccessToken) { if err := db.NewAccessToken(t); err != nil { if errors.IsAccessTokenNameAlreadyExist(err) { c.Flash.Error(c.Tr("settings.token_name_exists")) - c.SubURLRedirect("/user/settings/applications") + c.RedirectSubpath("/user/settings/applications") } else { - c.ServerError("NewAccessToken", err) + c.Errorf(err, "new access token") } return } c.Flash.Success(c.Tr("settings.generate_token_succees")) c.Flash.Info(t.Sha1) - c.SubURLRedirect("/user/settings/applications") + c.RedirectSubpath("/user/settings/applications") } func SettingsDeleteApplication(c *context.Context) { @@ -642,10 +642,10 @@ func SettingsDelete(c *context.Context) { if c.Req.Method == "POST" { if _, err := db.UserLogin(c.User.Name, c.Query("password"), c.User.LoginSource); err != nil { - if errors.IsUserNotExist(err) { + if db.IsErrUserNotExist(err) { c.RenderWithErr(c.Tr("form.enterred_invalid_password"), SETTINGS_DELETE, nil) } else { - c.ServerError("UserLogin", err) + c.Errorf(err, "authenticate user") } return } @@ -659,7 +659,7 @@ func SettingsDelete(c *context.Context) { c.Flash.Error(c.Tr("form.still_has_org")) c.Redirect(conf.Server.Subpath + "/user/settings/delete") default: - c.ServerError("DeleteUser", err) + c.Errorf(err, "delete user") } } else { log.Trace("Account deleted: %s", c.User.Name) diff --git a/internal/template/template.go b/internal/template/template.go index d34e44f69..faf27495f 100644 --- a/internal/template/template.go +++ b/internal/template/template.go @@ -256,6 +256,7 @@ func ActionContent2Commits(act Actioner) *db.PushCommits { return push } +// TODO(unknwon): Use url.Escape. func EscapePound(str string) string { return strings.NewReplacer("%", "%25", "#", "%23", " ", "%20", "?", "%3F").Replace(str) }