directory-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From vte...@apache.org
Subject svn commit: rev 20842 - in incubator/directory/janus/trunk: core/api/src/java/org/apache/janus/authentication core/api/src/java/org/apache/janus/authentication/realm core/api/src/java/org/apache/janus/authorization/role core/impl/src/java/org/apache/janus/authentication/realm core/impl/src/java/org/apache/janus/authorization core/impl/src/test/org/apache/janus/authentication/realm core/impl/src/test/org/apache/janus/authorization/role script/src/java/org/apache/janus/script script/src/java/org/apache/janus/script/xml script/src/test/org/apache/janus/script/xml
Date Sun, 06 Jun 2004 01:43:06 GMT
Author: vtence
Date: Sat Jun  5 18:43:05 2004
New Revision: 20842

Added:
   incubator/directory/janus/trunk/core/api/src/java/org/apache/janus/authentication/realm/IdentityInUseException.java
Removed:
   incubator/directory/janus/trunk/core/api/src/java/org/apache/janus/authorization/role/Grant.java
   incubator/directory/janus/trunk/core/impl/src/java/org/apache/janus/authorization/PermissionGrant.java
   incubator/directory/janus/trunk/core/impl/src/test/org/apache/janus/authorization/role/Interdiction.java
   incubator/directory/janus/trunk/core/impl/src/test/org/apache/janus/authorization/role/Right.java
   incubator/directory/janus/trunk/core/impl/src/test/org/apache/janus/authorization/role/RoleGrant.java
Modified:
   incubator/directory/janus/trunk/core/api/src/java/org/apache/janus/authentication/Credential.java
   incubator/directory/janus/trunk/core/api/src/java/org/apache/janus/authentication/CredentialSet.java
   incubator/directory/janus/trunk/core/api/src/java/org/apache/janus/authentication/realm/MutableRealm.java
   incubator/directory/janus/trunk/core/impl/src/java/org/apache/janus/authentication/realm/AuthenticationMethod.java
   incubator/directory/janus/trunk/core/impl/src/java/org/apache/janus/authentication/realm/DefaultRealm.java
   incubator/directory/janus/trunk/core/impl/src/java/org/apache/janus/authentication/realm/UsernamePasswordAuthentication.java
   incubator/directory/janus/trunk/core/impl/src/test/org/apache/janus/authentication/realm/DefaultRealmTest.java
   incubator/directory/janus/trunk/core/impl/src/test/org/apache/janus/authentication/realm/UsernamePasswordAuthenticationTest.java
   incubator/directory/janus/trunk/script/src/java/org/apache/janus/script/NullRealmBuilderMonitor.java
   incubator/directory/janus/trunk/script/src/java/org/apache/janus/script/RealmBuilderMonitor.java
   incubator/directory/janus/trunk/script/src/java/org/apache/janus/script/xml/Dom4JRealmBuilder.java
   incubator/directory/janus/trunk/script/src/test/org/apache/janus/script/xml/Dom4JRealmBuilderTest.java
Log:
Added uniqueness of identity to Realm

Modified: incubator/directory/janus/trunk/core/api/src/java/org/apache/janus/authentication/Credential.java
==============================================================================
--- incubator/directory/janus/trunk/core/api/src/java/org/apache/janus/authentication/Credential.java
(original)
+++ incubator/directory/janus/trunk/core/api/src/java/org/apache/janus/authentication/Credential.java
Sat Jun  5 18:43:05 2004
@@ -40,7 +40,7 @@
         m_value = value;
     }
 
-    public boolean isOfType( String type )
+    public boolean typeIs( String type )
     {
         return m_type.equals( type );
     }

Modified: incubator/directory/janus/trunk/core/api/src/java/org/apache/janus/authentication/CredentialSet.java
==============================================================================
--- incubator/directory/janus/trunk/core/api/src/java/org/apache/janus/authentication/CredentialSet.java
(original)
+++ incubator/directory/janus/trunk/core/api/src/java/org/apache/janus/authentication/CredentialSet.java
Sat Jun  5 18:43:05 2004
@@ -88,7 +88,7 @@
         for ( Iterator it = m_credentials.iterator(); it.hasNext(); )
         {
             final Credential c = ( Credential ) it.next();
-            if ( c.isOfType( type ) ) subSet.add( c );
+            if ( c.typeIs( type ) ) subSet.add( c );
         }
 
         return subSet;
@@ -99,7 +99,7 @@
         for ( Iterator it = m_credentials.iterator(); it.hasNext(); )
         {
             final Credential c = ( Credential ) it.next();
-            if ( c.isOfType( type ) ) return c;
+            if ( c.typeIs( type ) ) return c;
         }
 
         return null;

Added: incubator/directory/janus/trunk/core/api/src/java/org/apache/janus/authentication/realm/IdentityInUseException.java
==============================================================================
--- (empty file)
+++ incubator/directory/janus/trunk/core/api/src/java/org/apache/janus/authentication/realm/IdentityInUseException.java
Sat Jun  5 18:43:05 2004
@@ -0,0 +1,33 @@
+/*
+ *   Copyright 2004 The Apache Software Foundation
+ *
+ *   Licensed under the Apache License, Version 2.0 (the "License");
+ *   you may not use this file except in compliance with the License.
+ *   You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing, software
+ *   distributed under the License is distributed on an "AS IS" BASIS,
+ *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *   See the License for the specific language governing permissions and
+ *   limitations under the License.
+ *
+ */
+package org.apache.janus.authentication.realm;
+
+/**
+ * @author <a href="mailto:directory-dev@incubator.apache.org">Apache Directory Project</a>
+ */
+public class IdentityInUseException extends Exception
+{
+    public IdentityInUseException( String message )
+    {
+        super( message );
+    }
+
+    public IdentityInUseException( String message, Throwable cause )
+    {
+        super( message, cause );
+    }
+}

Modified: incubator/directory/janus/trunk/core/api/src/java/org/apache/janus/authentication/realm/MutableRealm.java
==============================================================================
--- incubator/directory/janus/trunk/core/api/src/java/org/apache/janus/authentication/realm/MutableRealm.java
(original)
+++ incubator/directory/janus/trunk/core/api/src/java/org/apache/janus/authentication/realm/MutableRealm.java
Sat Jun  5 18:43:05 2004
@@ -23,5 +23,5 @@
  */
 public interface MutableRealm extends Realm
 {
-    boolean addIdentity( CredentialSet credentials );
+    void addIdentity( CredentialSet credentials ) throws IdentityInUseException;
 }

Modified: incubator/directory/janus/trunk/core/impl/src/java/org/apache/janus/authentication/realm/AuthenticationMethod.java
==============================================================================
--- incubator/directory/janus/trunk/core/impl/src/java/org/apache/janus/authentication/realm/AuthenticationMethod.java
(original)
+++ incubator/directory/janus/trunk/core/impl/src/java/org/apache/janus/authentication/realm/AuthenticationMethod.java
Sat Jun  5 18:43:05 2004
@@ -25,9 +25,11 @@
  */
 public interface AuthenticationMethod
 {
-    Principal getPrincipal( CredentialSet credentialSet );
+    Principal principal( CredentialSet credentialSet );
 
     boolean supports( CredentialSet credentialSet );
 
-    CredentialsMatcher matcher( CredentialSet credentials );
+    CredentialsMatcher authenticate( CredentialSet credentials );
+
+    CredentialsMatcher identify( CredentialSet credentials );
 }

Modified: incubator/directory/janus/trunk/core/impl/src/java/org/apache/janus/authentication/realm/DefaultRealm.java
==============================================================================
--- incubator/directory/janus/trunk/core/impl/src/java/org/apache/janus/authentication/realm/DefaultRealm.java
(original)
+++ incubator/directory/janus/trunk/core/impl/src/java/org/apache/janus/authentication/realm/DefaultRealm.java
Sat Jun  5 18:43:05 2004
@@ -45,37 +45,42 @@
     public Principal validateCredentials( CredentialSet credentials )
     {
         if ( !m_authenticationMethod.supports( credentials ) ) return null;
-        if ( !contains( credentials ) ) return null;
+        CredentialSet identity = findAuthenticatedMatch( credentials );
 
-        return m_authenticationMethod.getPrincipal( credentials );
+        return identity != null ? m_authenticationMethod.principal( identity ) : null;
     }
 
-    public boolean addIdentity( CredentialSet credentials )
+    public void addIdentity( CredentialSet credentials ) throws IdentityInUseException
     {
         if ( !m_authenticationMethod.supports( credentials ) )
         {
             throw new IllegalArgumentException( "Credentials not supported by authentication
method" );
         }
-        if ( contains( credentials ) ) return false;
-        m_identities.add( new CredentialSet( credentials ) );
+        if ( findIdentifiedMatch( credentials ) != null ) throw new IdentityInUseException(
"Credentials in use" );
 
-        return true;
+        m_identities.add( credentials );
     }
 
-    private boolean contains( CredentialSet credentials )
+    private CredentialSet findAuthenticatedMatch( CredentialSet creds )
     {
-        CredentialsMatcher criterion = m_authenticationMethod.matcher( credentials );
+        CredentialsMatcher criterion = m_authenticationMethod.authenticate( creds );
         return search( criterion );
     }
 
-    public boolean search( CredentialsMatcher criterion )
+    private CredentialSet findIdentifiedMatch( CredentialSet creds )
+    {
+        CredentialsMatcher criterion = m_authenticationMethod.identify( creds );
+        return search( criterion );
+    }
+
+    public CredentialSet search( CredentialsMatcher criterion )
     {
         for ( Iterator it = m_identities.iterator(); it.hasNext(); )
         {
-            CredentialSet creds = ( CredentialSet ) it.next();
-            if ( criterion.matches( creds ) ) return true;
+            CredentialSet identity = ( CredentialSet ) it.next();
+            if ( criterion.matches( identity ) ) return identity;
         }
 
-        return false;
+        return null;
     }
 }

Modified: incubator/directory/janus/trunk/core/impl/src/java/org/apache/janus/authentication/realm/UsernamePasswordAuthentication.java
==============================================================================
--- incubator/directory/janus/trunk/core/impl/src/java/org/apache/janus/authentication/realm/UsernamePasswordAuthentication.java
(original)
+++ incubator/directory/janus/trunk/core/impl/src/java/org/apache/janus/authentication/realm/UsernamePasswordAuthentication.java
Sat Jun  5 18:43:05 2004
@@ -26,22 +26,25 @@
  */
 public class UsernamePasswordAuthentication implements AuthenticationMethod
 {
+    public static final String USERNAME = "username";
+    public static final String PASSWORD = "password";
+
     public UsernamePasswordAuthentication()
     {
     }
 
-    public Principal getPrincipal( CredentialSet credentialSet )
+    public Principal principal( CredentialSet credentialSet )
     {
-        Credential username = credentialSet.getCredential( "username" );
+        Credential username = credentialSet.getCredential( USERNAME );
         return new UsernamePrincipal( username.getValue().toString() );
     }
 
     public boolean supports( CredentialSet credentialSet )
     {
         if ( credentialSet.size() != 2 ) return false;
-        CredentialSet usernames = credentialSet.getCredentials( "username" );
+        CredentialSet usernames = credentialSet.getCredentials( USERNAME );
         if ( usernames.size() != 1 ) return false;
-        CredentialSet passwords = credentialSet.getCredentials( "password" );
+        CredentialSet passwords = credentialSet.getCredentials( PASSWORD );
         if ( passwords.size() != 1 ) return false;
 
         return true;
@@ -49,7 +52,17 @@
 
     public CredentialsMatcher matcher( CredentialSet credentials )
     {
-        return new EqualCredentials( credentials );
+        return new EqualMatcher( credentials );
+    }
+
+    public CredentialsMatcher authenticate( CredentialSet credentials )
+    {
+        return new EqualMatcher( credentials );
+    }
+
+    public CredentialsMatcher identify( CredentialSet credentials )
+    {
+        return new UsernameCredentialMatcher( credentials.getCredential( USERNAME ) );
     }
 
 }

Modified: incubator/directory/janus/trunk/core/impl/src/test/org/apache/janus/authentication/realm/DefaultRealmTest.java
==============================================================================
--- incubator/directory/janus/trunk/core/impl/src/test/org/apache/janus/authentication/realm/DefaultRealmTest.java
(original)
+++ incubator/directory/janus/trunk/core/impl/src/test/org/apache/janus/authentication/realm/DefaultRealmTest.java
Sat Jun  5 18:43:05 2004
@@ -18,7 +18,6 @@
 
 import org.apache.janus.authentication.Credential;
 import org.apache.janus.authentication.CredentialSet;
-import org.jmock.Mock;
 import org.jmock.MockObjectTestCase;
 
 import java.security.Principal;
@@ -35,73 +34,46 @@
         junit.textui.TestRunner.run( DefaultRealmTest.class );
     }
 
-    private DefaultRealm realm;
+    private DefaultRealm m_realm;
+
+    protected void setUp() throws Exception
+    {
+        m_realm = new DefaultRealm();
+    }
 
     public void testValidationFailsIfCredentialSetNotSupported()
     {
-        Mock mockAuthenticationMethod = new Mock( AuthenticationMethod.class );
-        realm = new DefaultRealm( ( AuthenticationMethod ) mockAuthenticationMethod.proxy()
);
-        mockAuthenticationMethod.expects( atLeastOnce() ).method( "supports" ).with( eq(
joeCredentials() ) ).will( returnValue( false ) );
-        assertNull( "Empty credential set was validated", realm.validateCredentials( joeCredentials()
) );
+        assertNull( "Empty credential set was validated", m_realm.validateCredentials( unsupportedCredentials()
) );
     }
 
     public void testEmptyRealmNeverValidatesAnyCredentialSet()
     {
-        Mock mockAuthenticationMethod = createMockAuthenticationMethod();
-        mockAuthenticationMethod.stubs().method( "matcher" ).will( returnValue( new AlwaysMatch()
) );
-        realm = new DefaultRealm( ( AuthenticationMethod ) mockAuthenticationMethod.proxy()
);
-
         assertNull( "Principal was returned but realm contains no entry",
-                realm.validateCredentials( johnCredentials() ) );
-
+                m_realm.validateCredentials( johnCredentials() ) );
     }
 
-    public void testValidationFailsIfCredentialsAreNotMatched()
+    public void testValidationFailsIfCredentialsAreNotMatched() throws Exception
     {
-        Mock mockAuthenticationMethod = createMockAuthenticationMethod();
-        mockAuthenticationMethod.stubs().method( "matcher" ).will( returnValue( new NeverMatch()
) );
-
-        realm = new DefaultRealm( ( AuthenticationMethod ) mockAuthenticationMethod.proxy()
);
-
+        m_realm.addIdentity( johnCredentials() );
         assertNull( "Principal was returned but credentials are invalid",
-                realm.validateCredentials( johnCredentials() ) );
+                m_realm.validateCredentials( joeCredentials() ) );
 
     }
 
-    public void testValidationSucceedsIfOneEntryIsMatched()
+    public void testValidationSucceedsIfOneEntryIsMatched() throws Exception
     {
-        Mock mockAuthenticationMethod = createMockAuthenticationMethod();
-        mockAuthenticationMethod.stubs().method( "matcher" ).will( returnValue( new EqualCredentials(
janeCredentials() ) ) );
-        mockAuthenticationMethod.stubs().method( "getPrincipal" ).with( eq( janeCredentials()
) ).will( returnValue( jane() ) );
-
-        realm = new DefaultRealm( ( AuthenticationMethod ) mockAuthenticationMethod.proxy()
);
-
-        try
-        {
-            realm.addIdentity( janeCredentials() );
-            realm.addIdentity( johnCredentials() );
-        }
-        catch ( IllegalArgumentException unexpected )
-        {
-            fail( "Invalid credential set was reported when it was valid" );
-        }
-
+        m_realm.addIdentity( janeCredentials() );
+        m_realm.addIdentity( johnCredentials() );
         assertEquals( "Principal identified does not match credentials",
                 jane(),
-                realm.validateCredentials( janeCredentials() ) );
+                m_realm.validateCredentials( janeCredentials() ) );
     }
 
-
-    public void testRejectsNewEntryIfCredentialSetIsNotSupported()
+    public void testRejectsNewEntryIfCredentialSetIsNotSupported() throws Exception
     {
-        Mock mockAuthenticationMethod = new Mock( AuthenticationMethod.class );
-        realm = new DefaultRealm( ( AuthenticationMethod ) mockAuthenticationMethod.proxy()
);
-
-        mockAuthenticationMethod.stubs().method( "supports" ).with( eq( joeCredentials()
) ).will( returnValue( false ) );
-
         try
         {
-            realm.addIdentity( joeCredentials() );
+            m_realm.addIdentity( unsupportedCredentials() );
             fail( "Malformed credential set was accepted in realm" );
         }
         catch ( IllegalArgumentException expected )
@@ -110,14 +82,18 @@
         }
     }
 
-    public void testIdentityIsNotAddedIfAlreadyInRealm()
+    public void testIdentityMustBeUnique() throws Exception
     {
-        Mock mockAuthenticationMethod = createMockAuthenticationMethod();
-        realm = new DefaultRealm( ( AuthenticationMethod ) mockAuthenticationMethod.proxy()
);
-        mockAuthenticationMethod.stubs().method( "matcher" ).will( returnValue( new EqualCredentials(
joeCredentials() ) ) );
-
-        realm.addIdentity( joeCredentials() );
-        assertFalse( "Identity reported as added twice", realm.addIdentity( joeCredentials()
) );
+        m_realm.addIdentity( johnCredentials() );
+        try
+        {
+            m_realm.addIdentity( imposterCredentials() );
+            fail( "Non-unique identity added to realm" );
+        }
+        catch ( IdentityInUseException e )
+        {
+            assertTrue( true );
+        }
     }
 
     private CredentialSet johnCredentials()
@@ -144,15 +120,24 @@
         return new CredentialSet( creds );
     }
 
-    private Principal jane()
+    private CredentialSet unsupportedCredentials()
     {
-        return new UsernamePrincipal( "jane" );
+        CredentialSet creds = new CredentialSet();
+        creds.add( new Credential( "eyes", "brown" ) );
+        creds.add( new Credential( "hair", "none" ) );
+        return creds;
     }
 
-    public Mock createMockAuthenticationMethod()
+    private CredentialSet imposterCredentials()
     {
-        Mock mockAuthenticationMethod = new Mock( AuthenticationMethod.class );
-        mockAuthenticationMethod.stubs().method( "supports" ).will( returnValue( true ) );
-        return mockAuthenticationMethod;
+        Set creds = new HashSet();
+        creds.add( new Credential( "username", "john" ) );
+        creds.add( new Credential( "password", "imposter" ) );
+        return new CredentialSet( creds );
+    }
+
+    private Principal jane()
+    {
+        return new UsernamePrincipal( "jane" );
     }
 }

Modified: incubator/directory/janus/trunk/core/impl/src/test/org/apache/janus/authentication/realm/UsernamePasswordAuthenticationTest.java
==============================================================================
--- incubator/directory/janus/trunk/core/impl/src/test/org/apache/janus/authentication/realm/UsernamePasswordAuthenticationTest.java
(original)
+++ incubator/directory/janus/trunk/core/impl/src/test/org/apache/janus/authentication/realm/UsernamePasswordAuthenticationTest.java
Sat Jun  5 18:43:05 2004
@@ -82,6 +82,6 @@
 
     public void testPrincipalsCreatedAreUsernamePrincipals()
     {
-        assertEquals( "Created wrong principal", new UsernamePrincipal( "john" ), m_auth.getPrincipal(
validCredentials() ) );
+        assertEquals( "Created wrong principal", new UsernamePrincipal( "john" ), m_auth.principal(
validCredentials() ) );
     }
 }

Modified: incubator/directory/janus/trunk/script/src/java/org/apache/janus/script/NullRealmBuilderMonitor.java
==============================================================================
--- incubator/directory/janus/trunk/script/src/java/org/apache/janus/script/NullRealmBuilderMonitor.java
(original)
+++ incubator/directory/janus/trunk/script/src/java/org/apache/janus/script/NullRealmBuilderMonitor.java
Sat Jun  5 18:43:05 2004
@@ -16,14 +16,14 @@
  */
 package org.apache.janus.script;
 
-import org.apache.janus.authentication.CredentialSet;
+import org.apache.janus.authentication.realm.IdentityInUseException;
 
 /**
  * @author <a href="mailto:directory-dev@incubator.apache.org">Apache Directory Project</a>
  */
 public class NullRealmBuilderMonitor implements RealmBuilderMonitor
 {
-    public void duplicateIdentity( CredentialSet identity )
+    public void duplicateIdentity( IdentityInUseException exception )
     {
     }
 }

Modified: incubator/directory/janus/trunk/script/src/java/org/apache/janus/script/RealmBuilderMonitor.java
==============================================================================
--- incubator/directory/janus/trunk/script/src/java/org/apache/janus/script/RealmBuilderMonitor.java
(original)
+++ incubator/directory/janus/trunk/script/src/java/org/apache/janus/script/RealmBuilderMonitor.java
Sat Jun  5 18:43:05 2004
@@ -16,12 +16,12 @@
  */
 package org.apache.janus.script;
 
-import org.apache.janus.authentication.CredentialSet;
+import org.apache.janus.authentication.realm.IdentityInUseException;
 
 /**
  * @author <a href="mailto:directory-dev@incubator.apache.org">Apache Directory Project</a>
  */
 public interface RealmBuilderMonitor
 {
-    void duplicateIdentity( CredentialSet identity );
+    void duplicateIdentity( IdentityInUseException exception );
 }

Modified: incubator/directory/janus/trunk/script/src/java/org/apache/janus/script/xml/Dom4JRealmBuilder.java
==============================================================================
--- incubator/directory/janus/trunk/script/src/java/org/apache/janus/script/xml/Dom4JRealmBuilder.java
(original)
+++ incubator/directory/janus/trunk/script/src/java/org/apache/janus/script/xml/Dom4JRealmBuilder.java
Sat Jun  5 18:43:05 2004
@@ -18,6 +18,7 @@
 
 import org.apache.janus.authentication.Credential;
 import org.apache.janus.authentication.CredentialSet;
+import org.apache.janus.authentication.realm.IdentityInUseException;
 import org.apache.janus.authentication.realm.MutableRealm;
 import org.apache.janus.script.NullRealmBuilderMonitor;
 import org.apache.janus.script.RealmBuilder;
@@ -76,8 +77,14 @@
             String password = user.attributeValue( "password" );
             creds.add( new Credential( "password", password ) );
 
-            boolean added = realm.addIdentity( creds );
-            if ( !added ) m_monitor.duplicateIdentity( creds );
+            try
+            {
+                realm.addIdentity( creds );
+            }
+            catch ( IdentityInUseException e )
+            {
+                m_monitor.duplicateIdentity( e );
+            }
         }
     }
 

Modified: incubator/directory/janus/trunk/script/src/test/org/apache/janus/script/xml/Dom4JRealmBuilderTest.java
==============================================================================
--- incubator/directory/janus/trunk/script/src/test/org/apache/janus/script/xml/Dom4JRealmBuilderTest.java
(original)
+++ incubator/directory/janus/trunk/script/src/test/org/apache/janus/script/xml/Dom4JRealmBuilderTest.java
Sat Jun  5 18:43:05 2004
@@ -42,8 +42,8 @@
         Dom4JRealmBuilder builder = new Dom4JRealmBuilder( new StringReader( simpleRealm()
) );
 
         Mock mockRealm = new Mock( MutableRealm.class );
-        mockRealm.expects( once() ).method( "addIdentity" ).with( eq( johnCredentials() )
).will( returnValue( true ) );
-        mockRealm.expects( once() ).method( "addIdentity" ).with( eq( janeCredentials() )
).will( returnValue( true ) );
+        mockRealm.expects( once() ).method( "addIdentity" ).with( eq( johnCredentials() )
);
+        mockRealm.expects( once() ).method( "addIdentity" ).with( eq( janeCredentials() )
);
 
         builder.buildRealm( ( MutableRealm ) mockRealm.proxy() );
 
@@ -84,7 +84,7 @@
         Dom4JRealmBuilder builder = new Dom4JRealmBuilder( new StringReader( realmWithDuplicateIdentity()
),
                 ( RealmBuilderMonitor ) mockMonitor.proxy() );
 
-        mockMonitor.expects( once() ).method( "duplicateIdentity" ).with( eq( johnCredentials()
) );
+        mockMonitor.expects( once() ).method( "duplicateIdentity" );
         builder.buildRealm( new DefaultRealm( new UsernamePasswordAuthentication() ) );
 
         mockMonitor.verify();

Mime
View raw message