]> source.dussan.org Git - archiva.git/blob
15049a487644dffb60422f06eaad5af48cd24394
[archiva.git] /
1 package org.apache.maven.archiva.webdav;
2
3 /*
4  * Licensed to the Apache Software Foundation (ASF) under one
5  * or more contributor license agreements.  See the NOTICE file
6  * distributed with this work for additional information
7  * regarding copyright ownership.  The ASF licenses this file
8  * to you under the Apache License, Version 2.0 (the
9  * "License"); you may not use this file except in compliance
10  * with the License.  You may obtain a copy of the License at
11  *
12  *  http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing,
15  * software distributed under the License is distributed on an
16  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17  * KIND, either express or implied.  See the License for the
18  * specific language governing permissions and limitations
19  * under the License.
20  */
21
22 import java.io.File;
23 import java.io.IOException;
24 import java.io.InputStream;
25
26 import javax.servlet.http.HttpServletResponse;
27
28 import net.sf.ehcache.CacheManager;
29
30 import org.apache.commons.io.FileUtils;
31 import org.apache.jackrabbit.webdav.DavSessionProvider;
32 import org.apache.maven.archiva.configuration.ArchivaConfiguration;
33 import org.apache.maven.archiva.configuration.Configuration;
34 import org.apache.maven.archiva.configuration.ManagedRepositoryConfiguration;
35 import org.apache.maven.archiva.security.ArchivaXworkUser;
36 import org.apache.maven.archiva.security.ServletAuthenticator;
37 import org.codehaus.plexus.redback.authentication.AuthenticationException;
38 import org.codehaus.plexus.redback.authentication.AuthenticationResult;
39 import org.codehaus.plexus.redback.authorization.UnauthorizedException;
40 import org.codehaus.plexus.redback.system.DefaultSecuritySession;
41 import org.codehaus.plexus.redback.system.SecuritySession;
42 import org.codehaus.plexus.spring.PlexusInSpringTestCase;
43 import org.codehaus.redback.integration.filter.authentication.HttpAuthenticator;
44 import org.codehaus.redback.integration.filter.authentication.basic.HttpBasicAuthentication;
45 import org.easymock.MockControl;
46 import org.easymock.classextension.MockClassControl;
47
48 import com.meterware.httpunit.GetMethodWebRequest;
49 import com.meterware.httpunit.HttpUnitOptions;
50 import com.meterware.httpunit.PutMethodWebRequest;
51 import com.meterware.httpunit.WebRequest;
52 import com.meterware.httpunit.WebResponse;
53 import com.meterware.servletunit.InvocationContext;
54 import com.meterware.servletunit.ServletRunner;
55 import com.meterware.servletunit.ServletUnitClient;
56
57 /**
58  * RepositoryServletSecurityTest
59  * 
60  * Test the flow of the authentication and authorization checks. This does not necessarily
61  * perform redback security checking.
62  * 
63  * @version $Id$
64  */
65 public class RepositoryServletSecurityTest
66     extends PlexusInSpringTestCase
67 {
68     protected static final String REPOID_INTERNAL = "internal";
69
70     protected ServletUnitClient sc;
71
72     protected File repoRootInternal;
73
74     private ServletRunner sr;
75
76     protected ArchivaConfiguration archivaConfiguration;
77
78     private DavSessionProvider davSessionProvider;
79
80     private MockControl servletAuthControl;
81
82     private ServletAuthenticator servletAuth;
83
84     private MockClassControl httpAuthControl;
85
86     private HttpAuthenticator httpAuth;
87
88     private RepositoryServlet servlet;
89     
90     public void setUp()
91         throws Exception
92     {
93         super.setUp();
94
95         String appserverBase = getTestFile( "target/appserver-base" ).getAbsolutePath();
96         System.setProperty( "appserver.base", appserverBase );
97
98         File testConf = getTestFile( "src/test/resources/repository-archiva.xml" );
99         File testConfDest = new File( appserverBase, "conf/archiva.xml" );
100         FileUtils.copyFile( testConf, testConfDest );
101
102         archivaConfiguration = (ArchivaConfiguration) lookup( ArchivaConfiguration.class );
103         repoRootInternal = new File( appserverBase, "data/repositories/internal" );
104         Configuration config = archivaConfiguration.getConfiguration();
105
106         config.addManagedRepository( createManagedRepository( REPOID_INTERNAL, "Internal Test Repo", repoRootInternal ) );
107         saveConfiguration( archivaConfiguration );
108
109         CacheManager.getInstance().removeCache( "url-failures-cache" );
110
111         HttpUnitOptions.setExceptionsThrownOnErrorStatus( false );
112
113         sr = new ServletRunner( getTestFile( "src/test/resources/WEB-INF/repository-servlet-security-test/web.xml" ) );
114         sr.registerServlet( "/repository/*", RepositoryServlet.class.getName() );
115         sc = sr.newClient();
116
117         servletAuthControl = MockControl.createControl( ServletAuthenticator.class );
118         servletAuthControl.setDefaultMatcher( MockControl.ALWAYS_MATCHER );
119         servletAuth = (ServletAuthenticator) servletAuthControl.getMock();
120
121         httpAuthControl =
122             MockClassControl.createControl( HttpBasicAuthentication.class, HttpBasicAuthentication.class.getMethods() );
123         httpAuthControl.setDefaultMatcher( MockControl.ALWAYS_MATCHER );
124         httpAuth = (HttpAuthenticator) httpAuthControl.getMock();
125
126         ArchivaXworkUser archivaXworkUser = (ArchivaXworkUser) lookup( ArchivaXworkUser.class );
127
128         davSessionProvider = new ArchivaDavSessionProvider( servletAuth, httpAuth, archivaXworkUser );      
129     }
130
131     protected ManagedRepositoryConfiguration createManagedRepository( String id, String name, File location )
132     {
133         ManagedRepositoryConfiguration repo = new ManagedRepositoryConfiguration();
134         repo.setId( id );
135         repo.setName( name );
136         repo.setLocation( location.getAbsolutePath() );
137         return repo;
138     }
139
140     protected void saveConfiguration()
141         throws Exception
142     {
143         saveConfiguration( archivaConfiguration );
144     }
145
146     protected void saveConfiguration( ArchivaConfiguration archivaConfiguration )
147         throws Exception
148     {
149         archivaConfiguration.save( archivaConfiguration.getConfiguration() );
150     }
151
152     protected void setupCleanRepo( File repoRootDir )
153         throws IOException
154     {
155         FileUtils.deleteDirectory( repoRootDir );
156         if ( !repoRootDir.exists() )
157         {
158             repoRootDir.mkdirs();
159         }
160     }
161
162     @Override
163     protected String getPlexusConfigLocation()
164     {
165         return "org/apache/maven/archiva/webdav/RepositoryServletSecurityTest.xml";
166     }
167
168     @Override
169     protected void tearDown()
170         throws Exception
171     {
172         if ( sc != null )
173         {
174             sc.clearContents();
175         }
176
177         if ( sr != null )
178         {
179             sr.shutDown();
180         }
181
182         if ( repoRootInternal.exists() )
183         {
184             FileUtils.deleteDirectory(repoRootInternal);
185         }
186
187         servlet = null;
188         
189         super.tearDown();
190     }
191
192     // test deploy with invalid user, and guest has no write access to repo
193     // 401 must be returned
194     public void testPutWithInvalidUserAndGuestHasNoWriteAccess()
195         throws Exception
196     {
197         setupCleanRepo( repoRootInternal );
198
199         String putUrl = "http://machine.com/repository/internal/path/to/artifact.jar";
200         InputStream is = getClass().getResourceAsStream( "/artifact.jar" );
201         assertNotNull( "artifact.jar inputstream", is );
202
203         WebRequest request = new PutMethodWebRequest( putUrl, is, "application/octet-stream" );
204         InvocationContext ic = sc.newInvocation( request );
205         servlet = (RepositoryServlet) ic.getServlet();
206         servlet.setDavSessionProvider( davSessionProvider );
207
208         AuthenticationResult result = new AuthenticationResult();
209         httpAuthControl.expectAndReturn( httpAuth.getAuthenticationResult( null, null ), result );
210         servletAuthControl.expectAndThrow( servletAuth.isAuthenticated( null, null ),
211                            new AuthenticationException( "Authentication error" ) );
212         
213         servletAuth.isAuthorized( "guest", "internal", true );        
214         servletAuthControl.setMatcher( MockControl.EQUALS_MATCHER );
215         servletAuthControl.setThrowable( new UnauthorizedException( "'guest' has no write access to repository" ) );
216
217         httpAuthControl.replay();
218         servletAuthControl.replay();
219         
220         servlet.service( ic.getRequest(), ic.getResponse() );
221         
222         httpAuthControl.verify();
223         servletAuthControl.verify();
224
225         //assertEquals(HttpServletResponse.SC_UNAUTHORIZED, response.getResponseCode());
226     }
227
228     // test deploy with invalid user, but guest has write access to repo
229     public void testPutWithInvalidUserAndGuestHasWriteAccess()
230         throws Exception
231     {
232         setupCleanRepo( repoRootInternal );
233
234         String putUrl = "http://machine.com/repository/internal/path/to/artifact.jar";
235         InputStream is = getClass().getResourceAsStream( "/artifact.jar" );
236         assertNotNull( "artifact.jar inputstream", is );
237
238         WebRequest request = new PutMethodWebRequest( putUrl, is, "application/octet-stream" );
239
240         InvocationContext ic = sc.newInvocation( request );
241         servlet = (RepositoryServlet) ic.getServlet();
242         servlet.setDavSessionProvider( davSessionProvider );
243
244         ArchivaDavResourceFactory archivaDavResourceFactory = (ArchivaDavResourceFactory) servlet.getResourceFactory();
245         archivaDavResourceFactory.setHttpAuth( httpAuth );
246         archivaDavResourceFactory.setServletAuth( servletAuth );
247
248         servlet.setResourceFactory( archivaDavResourceFactory );
249         
250         AuthenticationResult result = new AuthenticationResult();
251         httpAuthControl.expectAndReturn( httpAuth.getAuthenticationResult( null, null ), result );
252         servletAuthControl.expectAndThrow( servletAuth.isAuthenticated( null, null ),
253                                            new AuthenticationException( "Authentication error" ) );
254         
255         servletAuth.isAuthorized( "guest", "internal", true );
256         servletAuthControl.setMatcher( MockControl.EQUALS_MATCHER );
257         servletAuthControl.setReturnValue( true );
258                 
259      // ArchivaDavResourceFactory#isAuthorized()
260         SecuritySession session = new DefaultSecuritySession();
261         httpAuthControl.expectAndReturn( httpAuth.getAuthenticationResult( null, null ), result );
262         httpAuthControl.expectAndReturn( httpAuth.getSecuritySession( ic.getRequest().getSession( true) ), session );
263         servletAuthControl.expectAndThrow( servletAuth.isAuthenticated( null, result ),
264                                            new AuthenticationException( "Authentication error" ) );
265         
266         // check if guest has write access
267         servletAuth.isAuthorized( "guest", "internal", true );
268         servletAuthControl.setMatcher( MockControl.EQUALS_MATCHER );
269         servletAuthControl.setReturnValue( true );
270         
271         httpAuthControl.replay();
272         servletAuthControl.replay();
273
274         servlet.service( ic.getRequest(), ic.getResponse() );
275
276         httpAuthControl.verify();
277         servletAuthControl.verify();
278
279         // assertEquals( HttpServletResponse.SC_CREATED, response.getResponseCode() );
280     }
281
282     // test deploy with a valid user with no write access
283     public void testPutWithValidUserWithNoWriteAccess()
284         throws Exception
285     {
286         setupCleanRepo( repoRootInternal );
287
288         String putUrl = "http://machine.com/repository/internal/path/to/artifact.jar";
289         InputStream is = getClass().getResourceAsStream( "/artifact.jar" );
290         assertNotNull( "artifact.jar inputstream", is );
291         
292         WebRequest request = new PutMethodWebRequest( putUrl, is, "application/octet-stream" );
293         
294         InvocationContext ic = sc.newInvocation( request ); 
295         servlet = (RepositoryServlet) ic.getServlet();
296         servlet.setDavSessionProvider( davSessionProvider );
297         
298         ArchivaDavResourceFactory archivaDavResourceFactory = (ArchivaDavResourceFactory) servlet.getResourceFactory();
299         archivaDavResourceFactory.setHttpAuth( httpAuth );
300         archivaDavResourceFactory.setServletAuth( servletAuth );
301         servlet.setResourceFactory( archivaDavResourceFactory );
302
303         AuthenticationResult result = new AuthenticationResult();
304         httpAuthControl.expectAndReturn( httpAuth.getAuthenticationResult( null, null ), result );
305         servletAuthControl.expectAndReturn( servletAuth.isAuthenticated( null, null ), true );
306         
307      // ArchivaDavResourceFactory#isAuthorized()
308         SecuritySession session = new DefaultSecuritySession();
309         httpAuthControl.expectAndReturn( httpAuth.getAuthenticationResult( null, null ), result );
310         httpAuthControl.expectAndReturn( httpAuth.getSecuritySession( ic.getRequest().getSession( true ) ), session );
311         servletAuthControl.expectAndReturn( servletAuth.isAuthenticated( null, result ), true );
312         servletAuthControl.expectAndThrow( servletAuth.isAuthorized( null, session, "internal", true ),
313                                            new UnauthorizedException( "User not authorized" ) );
314                 
315         httpAuthControl.replay();
316         servletAuthControl.replay();
317         
318         servlet.service( ic.getRequest(), ic.getResponse() );
319
320         httpAuthControl.verify();
321         servletAuthControl.verify();
322         
323         // assertEquals(HttpServletResponse.SC_UNAUTHORIZED, response.getResponseCode());
324     }
325
326     // test deploy with a valid user with write access
327     public void testPutWithValidUserWithWriteAccess()
328         throws Exception
329     {
330         setupCleanRepo( repoRootInternal );
331         assertTrue( repoRootInternal.exists() );
332
333         String putUrl = "http://machine.com/repository/internal/path/to/artifact.jar";
334         InputStream is = getClass().getResourceAsStream( "/artifact.jar" );
335         assertNotNull( "artifact.jar inputstream", is );
336
337         WebRequest request = new PutMethodWebRequest( putUrl, is, "application/octet-stream" );
338
339         InvocationContext ic = sc.newInvocation( request );
340         servlet = (RepositoryServlet) ic.getServlet();
341         servlet.setDavSessionProvider( davSessionProvider );
342
343         ArchivaDavResourceFactory archivaDavResourceFactory = (ArchivaDavResourceFactory) servlet.getResourceFactory();
344         archivaDavResourceFactory.setHttpAuth( httpAuth );
345         archivaDavResourceFactory.setServletAuth( servletAuth );
346
347         servlet.setResourceFactory( archivaDavResourceFactory );
348
349         AuthenticationResult result = new AuthenticationResult();
350         httpAuthControl.expectAndReturn( httpAuth.getAuthenticationResult( null, null ), result );
351         servletAuthControl.expectAndReturn( servletAuth.isAuthenticated( null, null ), true );
352
353         // ArchivaDavResourceFactory#isAuthorized()
354         SecuritySession session = new DefaultSecuritySession();
355         httpAuthControl.expectAndReturn( httpAuth.getAuthenticationResult( null, null ), result );
356         httpAuthControl.expectAndReturn( httpAuth.getSecuritySession( ic.getRequest().getSession( true ) ), session );
357         servletAuthControl.expectAndReturn( servletAuth.isAuthenticated( null, result ), true );
358         servletAuthControl.expectAndReturn( servletAuth.isAuthorized( null, session, "internal", true ), true );
359
360         httpAuthControl.replay();
361         servletAuthControl.replay();
362
363         servlet.service( ic.getRequest(), ic.getResponse() );
364
365         httpAuthControl.verify();
366         servletAuthControl.verify();
367
368         // assertEquals(HttpServletResponse.SC_CREATED, response.getResponseCode());
369     }
370
371     // test get with invalid user, and guest has read access to repo
372     public void testGetWithInvalidUserAndGuestHasReadAccess()
373         throws Exception
374     {
375         String commonsLangJar = "commons-lang/commons-lang/2.1/commons-lang-2.1.jar";
376         String expectedArtifactContents = "dummy-commons-lang-artifact";
377
378         File artifactFile = new File( repoRootInternal, commonsLangJar );
379         artifactFile.getParentFile().mkdirs();
380
381         FileUtils.writeStringToFile( artifactFile, expectedArtifactContents, null );
382
383         WebRequest request = new GetMethodWebRequest( "http://machine.com/repository/internal/" + commonsLangJar );
384         InvocationContext ic = sc.newInvocation( request );
385         servlet = (RepositoryServlet) ic.getServlet();
386         servlet.setDavSessionProvider( davSessionProvider );
387         
388         ArchivaDavResourceFactory archivaDavResourceFactory = (ArchivaDavResourceFactory) servlet.getResourceFactory();
389         archivaDavResourceFactory.setHttpAuth( httpAuth );
390         archivaDavResourceFactory.setServletAuth( servletAuth );
391
392         servlet.setResourceFactory( archivaDavResourceFactory );
393
394         AuthenticationResult result = new AuthenticationResult();
395         httpAuthControl.expectAndReturn( httpAuth.getAuthenticationResult( null, null ), result );
396         servletAuthControl.expectAndThrow( servletAuth.isAuthenticated( null, null ),
397                                            new AuthenticationException( "Authentication error" ) );
398         servletAuthControl.expectAndReturn( servletAuth.isAuthorized( "guest", "internal", false ), true );
399         
400      // ArchivaDavResourceFactory#isAuthorized()
401         SecuritySession session = new DefaultSecuritySession();
402         httpAuthControl.expectAndReturn( httpAuth.getAuthenticationResult( null, null ), result );
403         httpAuthControl.expectAndReturn( httpAuth.getSecuritySession( ic.getRequest().getSession( true ) ), session );
404         servletAuthControl.expectAndReturn( servletAuth.isAuthenticated( null, result ), true );
405         servletAuthControl.expectAndReturn( servletAuth.isAuthorized( null, session, "internal", true ), true );
406
407         httpAuthControl.replay();
408         servletAuthControl.replay();
409
410         WebResponse response = sc.getResponse( request );
411
412         httpAuthControl.verify();
413         servletAuthControl.verify();
414
415         assertEquals( HttpServletResponse.SC_OK, response.getResponseCode() );
416         assertEquals( "Expected file contents", expectedArtifactContents, response.getText() );
417     }
418
419     // test get with invalid user, and guest has no read access to repo
420     public void testGetWithInvalidUserAndGuestHasNoReadAccess()
421         throws Exception
422     {
423         String commonsLangJar = "commons-lang/commons-lang/2.1/commons-lang-2.1.jar";
424         String expectedArtifactContents = "dummy-commons-lang-artifact";
425
426         File artifactFile = new File( repoRootInternal, commonsLangJar );
427         artifactFile.getParentFile().mkdirs();
428
429         FileUtils.writeStringToFile( artifactFile, expectedArtifactContents, null );
430
431         WebRequest request = new GetMethodWebRequest( "http://machine.com/repository/internal/" + commonsLangJar );
432         InvocationContext ic = sc.newInvocation( request );
433         servlet = (RepositoryServlet) ic.getServlet();
434         servlet.setDavSessionProvider( davSessionProvider );
435
436         AuthenticationResult result = new AuthenticationResult();
437         httpAuthControl.expectAndReturn( httpAuth.getAuthenticationResult( null, null ), result );
438         servletAuthControl.expectAndThrow( servletAuth.isAuthenticated( null, null ),
439                                            new AuthenticationException( "Authentication error" ) );
440         servletAuthControl.expectAndReturn( servletAuth.isAuthorized( "guest", "internal", false ), false );
441
442         httpAuthControl.replay();
443         servletAuthControl.replay();
444
445         WebResponse response = sc.getResponse( request );
446
447         httpAuthControl.verify();
448         servletAuthControl.verify();
449
450         assertEquals( HttpServletResponse.SC_UNAUTHORIZED, response.getResponseCode() );
451     }
452
453     // test get with valid user with read access to repo
454     public void testGetWithAValidUserWithReadAccess()
455         throws Exception
456     {
457         String commonsLangJar = "commons-lang/commons-lang/2.1/commons-lang-2.1.jar";
458         String expectedArtifactContents = "dummy-commons-lang-artifact";
459
460         File artifactFile = new File( repoRootInternal, commonsLangJar );
461         artifactFile.getParentFile().mkdirs();
462
463         FileUtils.writeStringToFile( artifactFile, expectedArtifactContents, null );
464
465         WebRequest request = new GetMethodWebRequest( "http://machine.com/repository/internal/" + commonsLangJar );
466         InvocationContext ic = sc.newInvocation( request );
467         servlet = (RepositoryServlet) ic.getServlet();
468         servlet.setDavSessionProvider( davSessionProvider );
469
470         ArchivaDavResourceFactory archivaDavResourceFactory = (ArchivaDavResourceFactory) servlet.getResourceFactory();
471         archivaDavResourceFactory.setHttpAuth( httpAuth );
472         archivaDavResourceFactory.setServletAuth( servletAuth );
473
474         servlet.setResourceFactory( archivaDavResourceFactory );
475         
476         AuthenticationResult result = new AuthenticationResult();
477         httpAuthControl.expectAndReturn( httpAuth.getAuthenticationResult( null, null ), result );
478         servletAuthControl.expectAndReturn( servletAuth.isAuthenticated( null, null ), true );
479         
480      // ArchivaDavResourceFactory#isAuthorized()
481         SecuritySession session = new DefaultSecuritySession();
482         httpAuthControl.expectAndReturn( httpAuth.getAuthenticationResult( null, null ), result );
483         httpAuthControl.expectAndReturn( httpAuth.getSecuritySession( ic.getRequest().getSession( true ) ), session );
484         servletAuthControl.expectAndReturn( servletAuth.isAuthenticated( null, result ), true );
485         servletAuthControl.expectAndReturn( servletAuth.isAuthorized( null, session, "internal", true ), true );
486         
487         httpAuthControl.replay();
488         servletAuthControl.replay();
489
490         WebResponse response = sc.getResponse( request );
491         
492         httpAuthControl.verify();
493         servletAuthControl.verify();
494
495         assertEquals( HttpServletResponse.SC_OK, response.getResponseCode() );
496         assertEquals( "Expected file contents", expectedArtifactContents, response.getText() );
497     }
498
499     // test get with valid user with no read access to repo
500     public void testGetWithAValidUserWithNoReadAccess()
501         throws Exception
502     {
503         String commonsLangJar = "commons-lang/commons-lang/2.1/commons-lang-2.1.jar";
504         String expectedArtifactContents = "dummy-commons-lang-artifact";
505
506         File artifactFile = new File( repoRootInternal, commonsLangJar );
507         artifactFile.getParentFile().mkdirs();
508
509         FileUtils.writeStringToFile( artifactFile, expectedArtifactContents, null );
510
511         WebRequest request = new GetMethodWebRequest( "http://machine.com/repository/internal/" + commonsLangJar );
512         InvocationContext ic = sc.newInvocation( request );
513         servlet = (RepositoryServlet) ic.getServlet();
514         servlet.setDavSessionProvider( davSessionProvider );
515
516         ArchivaDavResourceFactory archivaDavResourceFactory = (ArchivaDavResourceFactory) servlet.getResourceFactory();
517         archivaDavResourceFactory.setHttpAuth( httpAuth );
518         archivaDavResourceFactory.setServletAuth( servletAuth );
519
520         servlet.setResourceFactory( archivaDavResourceFactory );
521         
522         AuthenticationResult result = new AuthenticationResult();
523         httpAuthControl.expectAndReturn( httpAuth.getAuthenticationResult( null, null ), result );
524         servletAuthControl.expectAndReturn( servletAuth.isAuthenticated( null, null ), true );
525
526      // ArchivaDavResourceFactory#isAuthorized()
527         SecuritySession session = new DefaultSecuritySession();
528         httpAuthControl.expectAndReturn( httpAuth.getAuthenticationResult( null, null ), result );
529         httpAuthControl.expectAndReturn( httpAuth.getSecuritySession( ic.getRequest().getSession( true ) ), session );
530         servletAuthControl.expectAndReturn( servletAuth.isAuthenticated( null, result ), true );
531         servletAuthControl.expectAndThrow( servletAuth.isAuthorized( null, session, "internal", true ),
532                                            new UnauthorizedException( "User not authorized to read repository." ) );
533         
534         httpAuthControl.replay();
535         servletAuthControl.replay();
536         
537         WebResponse response = sc.getResponse( request );
538
539         httpAuthControl.verify();
540         servletAuthControl.verify();
541         
542         assertEquals( HttpServletResponse.SC_UNAUTHORIZED, response.getResponseCode() );
543     }
544 }