]>
Commit | Line | Data |
---|---|---|
cceae9a2 ET |
1 | |
2 | #include "clar_libgit2.h" | |
cceae9a2 ET |
3 | |
4 | #ifdef GIT_WIN32 | |
5 | #include "win32/path_w32.h" | |
6 | #endif | |
7 | ||
cceae9a2 | 8 | #ifdef GIT_WIN32 |
e579e0f7 MB |
9 | static void test_utf8_to_utf16(const char *utf8_in, const wchar_t *utf16_expected) |
10 | { | |
cceae9a2 ET |
11 | git_win32_path path_utf16; |
12 | int path_utf16len; | |
13 | ||
14 | cl_assert((path_utf16len = git_win32_path_from_utf8(path_utf16, utf8_in)) >= 0); | |
15 | cl_assert_equal_wcs(utf16_expected, path_utf16); | |
16 | cl_assert_equal_i(wcslen(utf16_expected), path_utf16len); | |
cceae9a2 ET |
17 | } |
18 | ||
e579e0f7 | 19 | static void test_utf8_to_utf16_relative(const char* utf8_in, const wchar_t* utf16_expected) |
22a2d3d5 | 20 | { |
22a2d3d5 UG |
21 | git_win32_path path_utf16; |
22 | int path_utf16len; | |
23 | ||
24 | cl_assert((path_utf16len = git_win32_path_relative_from_utf8(path_utf16, utf8_in)) >= 0); | |
25 | cl_assert_equal_wcs(utf16_expected, path_utf16); | |
26 | cl_assert_equal_i(wcslen(utf16_expected), path_utf16len); | |
22a2d3d5 | 27 | } |
e579e0f7 | 28 | #endif |
22a2d3d5 | 29 | |
cceae9a2 ET |
30 | void test_path_win32__utf8_to_utf16(void) |
31 | { | |
32 | #ifdef GIT_WIN32 | |
33 | test_utf8_to_utf16("C:\\", L"\\\\?\\C:\\"); | |
34 | test_utf8_to_utf16("c:\\", L"\\\\?\\c:\\"); | |
35 | test_utf8_to_utf16("C:/", L"\\\\?\\C:\\"); | |
36 | test_utf8_to_utf16("c:/", L"\\\\?\\c:\\"); | |
37 | #endif | |
38 | } | |
39 | ||
40 | void test_path_win32__removes_trailing_slash(void) | |
41 | { | |
42 | #ifdef GIT_WIN32 | |
43 | test_utf8_to_utf16("C:\\Foo\\", L"\\\\?\\C:\\Foo"); | |
44 | test_utf8_to_utf16("C:\\Foo\\\\", L"\\\\?\\C:\\Foo"); | |
45 | test_utf8_to_utf16("C:\\Foo\\\\", L"\\\\?\\C:\\Foo"); | |
46 | test_utf8_to_utf16("C:/Foo/", L"\\\\?\\C:\\Foo"); | |
47 | test_utf8_to_utf16("C:/Foo///", L"\\\\?\\C:\\Foo"); | |
48 | #endif | |
49 | } | |
50 | ||
51 | void test_path_win32__squashes_multiple_slashes(void) | |
52 | { | |
53 | #ifdef GIT_WIN32 | |
54 | test_utf8_to_utf16("C:\\\\Foo\\Bar\\\\Foobar", L"\\\\?\\C:\\Foo\\Bar\\Foobar"); | |
55 | test_utf8_to_utf16("C://Foo/Bar///Foobar", L"\\\\?\\C:\\Foo\\Bar\\Foobar"); | |
56 | #endif | |
57 | } | |
58 | ||
59 | void test_path_win32__unc(void) | |
60 | { | |
61 | #ifdef GIT_WIN32 | |
62 | test_utf8_to_utf16("\\\\server\\c$\\unc\\path", L"\\\\?\\UNC\\server\\c$\\unc\\path"); | |
63 | test_utf8_to_utf16("//server/git/style/unc/path", L"\\\\?\\UNC\\server\\git\\style\\unc\\path"); | |
64 | #endif | |
65 | } | |
66 | ||
67 | void test_path_win32__honors_max_path(void) | |
68 | { | |
69 | #ifdef GIT_WIN32 | |
70 | git_win32_path path_utf16; | |
71 | ||
c25aa7cd PP |
72 | test_utf8_to_utf16("C:\\This path is 261 characters which is fine for our path handling functions which cope with paths longer than MAX_PATH\\0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghijk", |
73 | L"\\\\?\\C:\\This path is 261 characters which is fine for our path handling functions which cope with paths longer than MAX_PATH\\0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghijk"); | |
74 | ||
75 | cl_check_fail(git_win32_path_from_utf8(path_utf16, "C:\\This path is 4097 chars and exceeds our maximum path length on Windows which is limited to 4096 characters\\alas\\0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij01")); | |
cceae9a2 | 76 | |
cceae9a2 ET |
77 | #endif |
78 | } | |
79 | ||
80 | void test_path_win32__dot_and_dotdot(void) | |
81 | { | |
82 | #ifdef GIT_WIN32 | |
83 | test_utf8_to_utf16("C:\\Foo\\..\\Foobar", L"\\\\?\\C:\\Foobar"); | |
84 | test_utf8_to_utf16("C:\\Foo\\Bar\\..\\Foobar", L"\\\\?\\C:\\Foo\\Foobar"); | |
85 | test_utf8_to_utf16("C:\\Foo\\Bar\\..\\Foobar\\..", L"\\\\?\\C:\\Foo"); | |
86 | test_utf8_to_utf16("C:\\Foobar\\..", L"\\\\?\\C:\\"); | |
87 | test_utf8_to_utf16("C:/Foo/Bar/../Foobar", L"\\\\?\\C:\\Foo\\Foobar"); | |
88 | test_utf8_to_utf16("C:/Foo/Bar/../Foobar/../Asdf/", L"\\\\?\\C:\\Foo\\Asdf"); | |
89 | test_utf8_to_utf16("C:/Foo/Bar/../Foobar/..", L"\\\\?\\C:\\Foo"); | |
90 | test_utf8_to_utf16("C:/Foo/..", L"\\\\?\\C:\\"); | |
91 | ||
92 | test_utf8_to_utf16("C:\\Foo\\Bar\\.\\Foobar", L"\\\\?\\C:\\Foo\\Bar\\Foobar"); | |
93 | test_utf8_to_utf16("C:\\.\\Foo\\.\\Bar\\.\\Foobar\\.\\", L"\\\\?\\C:\\Foo\\Bar\\Foobar"); | |
94 | test_utf8_to_utf16("C:/Foo/Bar/./Foobar", L"\\\\?\\C:\\Foo\\Bar\\Foobar"); | |
95 | test_utf8_to_utf16("C:/Foo/../Bar/./Foobar/../", L"\\\\?\\C:\\Bar"); | |
96 | ||
97 | test_utf8_to_utf16("C:\\Foo\\..\\..\\Bar", L"\\\\?\\C:\\Bar"); | |
98 | #endif | |
99 | } | |
100 | ||
101 | void test_path_win32__absolute_from_no_drive_letter(void) | |
102 | { | |
103 | #ifdef GIT_WIN32 | |
104 | test_utf8_to_utf16("\\Foo", L"\\\\?\\C:\\Foo"); | |
105 | test_utf8_to_utf16("\\Foo\\Bar", L"\\\\?\\C:\\Foo\\Bar"); | |
106 | test_utf8_to_utf16("/Foo/Bar", L"\\\\?\\C:\\Foo\\Bar"); | |
107 | #endif | |
108 | } | |
109 | ||
110 | void test_path_win32__absolute_from_relative(void) | |
111 | { | |
112 | #ifdef GIT_WIN32 | |
113 | char cwd_backup[MAX_PATH]; | |
114 | ||
115 | cl_must_pass(p_getcwd(cwd_backup, MAX_PATH)); | |
116 | cl_must_pass(p_chdir("C:/")); | |
117 | ||
118 | test_utf8_to_utf16("Foo", L"\\\\?\\C:\\Foo"); | |
119 | test_utf8_to_utf16("..\\..\\Foo", L"\\\\?\\C:\\Foo"); | |
120 | test_utf8_to_utf16("Foo\\..", L"\\\\?\\C:\\"); | |
121 | test_utf8_to_utf16("Foo\\..\\..", L"\\\\?\\C:\\"); | |
122 | test_utf8_to_utf16("", L"\\\\?\\C:\\"); | |
123 | ||
124 | cl_must_pass(p_chdir("C:/Windows")); | |
125 | ||
126 | test_utf8_to_utf16("Foo", L"\\\\?\\C:\\Windows\\Foo"); | |
127 | test_utf8_to_utf16("Foo\\Bar", L"\\\\?\\C:\\Windows\\Foo\\Bar"); | |
128 | test_utf8_to_utf16("..\\Foo", L"\\\\?\\C:\\Foo"); | |
129 | test_utf8_to_utf16("Foo\\..\\Bar", L"\\\\?\\C:\\Windows\\Bar"); | |
130 | test_utf8_to_utf16("", L"\\\\?\\C:\\Windows"); | |
131 | ||
132 | cl_must_pass(p_chdir(cwd_backup)); | |
133 | #endif | |
134 | } | |
135 | ||
22a2d3d5 UG |
136 | void test_path_win32__keeps_relative(void) |
137 | { | |
138 | #ifdef GIT_WIN32 | |
139 | /* Relative paths stay relative */ | |
140 | test_utf8_to_utf16_relative("Foo", L"Foo"); | |
141 | test_utf8_to_utf16_relative("..\\..\\Foo", L"..\\..\\Foo"); | |
142 | test_utf8_to_utf16_relative("Foo\\..", L"Foo\\.."); | |
143 | test_utf8_to_utf16_relative("Foo\\..\\..", L"Foo\\..\\.."); | |
144 | test_utf8_to_utf16_relative("Foo\\Bar", L"Foo\\Bar"); | |
145 | test_utf8_to_utf16_relative("Foo\\..\\Bar", L"Foo\\..\\Bar"); | |
146 | test_utf8_to_utf16_relative("../../Foo", L"..\\..\\Foo"); | |
147 | test_utf8_to_utf16_relative("Foo/..", L"Foo\\.."); | |
148 | test_utf8_to_utf16_relative("Foo/../..", L"Foo\\..\\.."); | |
149 | test_utf8_to_utf16_relative("Foo/Bar", L"Foo\\Bar"); | |
150 | test_utf8_to_utf16_relative("Foo/../Bar", L"Foo\\..\\Bar"); | |
151 | test_utf8_to_utf16_relative("Foo/../Bar/", L"Foo\\..\\Bar\\"); | |
152 | test_utf8_to_utf16_relative("", L""); | |
153 | ||
154 | /* Absolute paths are canonicalized */ | |
155 | test_utf8_to_utf16_relative("\\Foo", L"\\\\?\\C:\\Foo"); | |
156 | test_utf8_to_utf16_relative("/Foo/Bar/", L"\\\\?\\C:\\Foo\\Bar"); | |
157 | test_utf8_to_utf16_relative("\\\\server\\c$\\unc\\path", L"\\\\?\\UNC\\server\\c$\\unc\\path"); | |
158 | #endif | |
159 | } | |
160 | ||
cceae9a2 | 161 | #ifdef GIT_WIN32 |
ac3d33df JK |
162 | static void test_canonicalize(const wchar_t *in, const wchar_t *expected) |
163 | { | |
cceae9a2 ET |
164 | git_win32_path canonical; |
165 | ||
166 | cl_assert(wcslen(in) < MAX_PATH); | |
167 | wcscpy(canonical, in); | |
168 | ||
169 | cl_must_pass(git_win32_path_canonicalize(canonical)); | |
170 | cl_assert_equal_wcs(expected, canonical); | |
ac3d33df JK |
171 | } |
172 | #endif | |
173 | ||
174 | static void test_remove_namespace(const wchar_t *in, const wchar_t *expected) | |
175 | { | |
176 | #ifdef GIT_WIN32 | |
177 | git_win32_path canonical; | |
178 | ||
179 | cl_assert(wcslen(in) < MAX_PATH); | |
180 | wcscpy(canonical, in); | |
181 | ||
182 | git_win32_path_remove_namespace(canonical, wcslen(in)); | |
183 | cl_assert_equal_wcs(expected, canonical); | |
cceae9a2 ET |
184 | #else |
185 | GIT_UNUSED(in); | |
186 | GIT_UNUSED(expected); | |
187 | #endif | |
188 | } | |
189 | ||
ac3d33df JK |
190 | void test_path_win32__remove_namespace(void) |
191 | { | |
192 | test_remove_namespace(L"\\\\?\\C:\\Temp\\Foo", L"C:\\Temp\\Foo"); | |
193 | test_remove_namespace(L"\\\\?\\C:\\", L"C:\\"); | |
194 | test_remove_namespace(L"\\\\?\\", L""); | |
195 | ||
196 | test_remove_namespace(L"\\??\\C:\\Temp\\Foo", L"C:\\Temp\\Foo"); | |
197 | test_remove_namespace(L"\\??\\C:\\", L"C:\\"); | |
198 | test_remove_namespace(L"\\??\\", L""); | |
199 | ||
200 | test_remove_namespace(L"\\\\?\\UNC\\server\\C$\\folder", L"\\\\server\\C$\\folder"); | |
201 | test_remove_namespace(L"\\\\?\\UNC\\server\\C$\\folder", L"\\\\server\\C$\\folder"); | |
202 | test_remove_namespace(L"\\\\?\\UNC\\server\\C$", L"\\\\server\\C$"); | |
203 | test_remove_namespace(L"\\\\?\\UNC\\server\\", L"\\\\server"); | |
204 | test_remove_namespace(L"\\\\?\\UNC\\server", L"\\\\server"); | |
205 | ||
206 | test_remove_namespace(L"\\??\\UNC\\server\\C$\\folder", L"\\\\server\\C$\\folder"); | |
207 | test_remove_namespace(L"\\??\\UNC\\server\\C$\\folder", L"\\\\server\\C$\\folder"); | |
208 | test_remove_namespace(L"\\??\\UNC\\server\\C$", L"\\\\server\\C$"); | |
209 | test_remove_namespace(L"\\??\\UNC\\server\\", L"\\\\server"); | |
210 | test_remove_namespace(L"\\??\\UNC\\server", L"\\\\server"); | |
211 | ||
212 | test_remove_namespace(L"\\\\server\\C$\\folder", L"\\\\server\\C$\\folder"); | |
213 | test_remove_namespace(L"\\\\server\\C$", L"\\\\server\\C$"); | |
214 | test_remove_namespace(L"\\\\server\\", L"\\\\server"); | |
215 | test_remove_namespace(L"\\\\server", L"\\\\server"); | |
216 | ||
217 | test_remove_namespace(L"C:\\Foo\\Bar", L"C:\\Foo\\Bar"); | |
218 | test_remove_namespace(L"C:\\", L"C:\\"); | |
219 | test_remove_namespace(L"", L""); | |
220 | ||
221 | } | |
222 | ||
cceae9a2 ET |
223 | void test_path_win32__canonicalize(void) |
224 | { | |
225 | #ifdef GIT_WIN32 | |
226 | test_canonicalize(L"C:\\Foo\\Bar", L"C:\\Foo\\Bar"); | |
227 | test_canonicalize(L"C:\\Foo\\", L"C:\\Foo"); | |
228 | test_canonicalize(L"C:\\Foo\\\\", L"C:\\Foo"); | |
229 | test_canonicalize(L"C:\\Foo\\..\\Bar", L"C:\\Bar"); | |
230 | test_canonicalize(L"C:\\Foo\\..\\..\\Bar", L"C:\\Bar"); | |
231 | test_canonicalize(L"C:\\Foo\\..\\..\\..\\..\\", L"C:\\"); | |
232 | test_canonicalize(L"C:/Foo/Bar", L"C:\\Foo\\Bar"); | |
233 | test_canonicalize(L"C:/", L"C:\\"); | |
234 | ||
cceae9a2 ET |
235 | test_canonicalize(L"\\\\?\\C:\\Foo\\Bar", L"\\\\?\\C:\\Foo\\Bar"); |
236 | test_canonicalize(L"\\\\?\\C:\\Foo\\Bar\\", L"\\\\?\\C:\\Foo\\Bar"); | |
237 | test_canonicalize(L"\\\\?\\C:\\\\Foo\\.\\Bar\\\\..\\", L"\\\\?\\C:\\Foo"); | |
238 | test_canonicalize(L"\\\\?\\C:\\\\", L"\\\\?\\C:\\"); | |
239 | test_canonicalize(L"//?/C:/", L"\\\\?\\C:\\"); | |
240 | test_canonicalize(L"//?/C:/../../Foo/", L"\\\\?\\C:\\Foo"); | |
241 | test_canonicalize(L"//?/C:/Foo/../../", L"\\\\?\\C:\\"); | |
242 | ||
243 | test_canonicalize(L"\\\\?\\UNC\\server\\C$\\folder", L"\\\\?\\UNC\\server\\C$\\folder"); | |
244 | test_canonicalize(L"\\\\?\\UNC\\server\\C$\\folder\\", L"\\\\?\\UNC\\server\\C$\\folder"); | |
245 | test_canonicalize(L"\\\\?\\UNC\\server\\C$\\folder\\", L"\\\\?\\UNC\\server\\C$\\folder"); | |
246 | test_canonicalize(L"\\\\?\\UNC\\server\\C$\\folder\\..\\..\\..\\..\\share\\", L"\\\\?\\UNC\\server\\share"); | |
247 | ||
248 | test_canonicalize(L"\\\\server\\share", L"\\\\server\\share"); | |
249 | test_canonicalize(L"\\\\server\\share\\", L"\\\\server\\share"); | |
250 | test_canonicalize(L"\\\\server\\share\\\\foo\\\\bar", L"\\\\server\\share\\foo\\bar"); | |
251 | test_canonicalize(L"\\\\server\\\\share\\\\foo\\\\bar", L"\\\\server\\share\\foo\\bar"); | |
252 | test_canonicalize(L"\\\\server\\share\\..\\foo", L"\\\\server\\foo"); | |
253 | test_canonicalize(L"\\\\server\\..\\..\\share\\.\\foo", L"\\\\server\\share\\foo"); | |
254 | #endif | |
255 | } | |
a64119e3 ET |
256 | |
257 | void test_path_win32__8dot3_name(void) | |
258 | { | |
259 | #ifdef GIT_WIN32 | |
260 | char *shortname; | |
261 | ||
07c989e9 | 262 | if (!cl_sandbox_supports_8dot3()) |
5f28ec84 ET |
263 | clar__skip(); |
264 | ||
07c989e9 ET |
265 | /* Some guaranteed short names */ |
266 | cl_assert_equal_s("PROGRA~1", (shortname = git_win32_path_8dot3_name("C:\\Program Files"))); | |
a64119e3 ET |
267 | git__free(shortname); |
268 | ||
269 | cl_assert_equal_s("WINDOWS", (shortname = git_win32_path_8dot3_name("C:\\WINDOWS"))); | |
270 | git__free(shortname); | |
271 | ||
e579e0f7 | 272 | /* Create some predictable short names */ |
a64119e3 | 273 | cl_must_pass(p_mkdir(".foo", 0777)); |
5f28ec84 | 274 | cl_assert_equal_s("FOO~1", (shortname = git_win32_path_8dot3_name(".foo"))); |
a64119e3 ET |
275 | git__free(shortname); |
276 | ||
277 | cl_git_write2file("bar~1", "foobar\n", 7, O_RDWR|O_CREAT, 0666); | |
278 | cl_must_pass(p_mkdir(".bar", 0777)); | |
5f28ec84 | 279 | cl_assert_equal_s("BAR~2", (shortname = git_win32_path_8dot3_name(".bar"))); |
a64119e3 ET |
280 | git__free(shortname); |
281 | #endif | |
282 | } |