View Javadoc
1   /*
2    *  Licensed to the Apache Software Foundation (ASF) under one
3    *  or more contributor license agreements.  See the NOTICE file
4    *  distributed with this work for additional information
5    *  regarding copyright ownership.  The ASF licenses this file
6    *  to you under the Apache License, Version 2.0 (the
7    *  "License"); you may not use this file except in compliance
8    *  with the License.  You may obtain a copy of the License at
9    *  
10   *    http://www.apache.org/licenses/LICENSE-2.0
11   *  
12   *  Unless required by applicable law or agreed to in writing,
13   *  software distributed under the License is distributed on an
14   *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   *  KIND, either express or implied.  See the License for the
16   *  specific language governing permissions and limitations
17   *  under the License. 
18   *  
19   */
20  package org.apache.directory.api.ldap.model.schema.syntaxCheckers;
21  
22  
23  import org.apache.directory.api.ldap.model.constants.SchemaConstants;
24  import org.apache.directory.api.ldap.model.schema.SyntaxChecker;
25  import org.apache.directory.api.util.Strings;
26  import org.slf4j.Logger;
27  import org.slf4j.LoggerFactory;
28  
29  
30  /**
31   * A SyntaxChecker which verifies that a value is a TeletexTerminalIdentifier according to 
32   * RFC 4517 :
33   * 
34   * teletex-id = ttx-term *(DOLLAR ttx-param)
35   * ttx-term   = PrintableString          ; terminal identifier
36   * ttx-param  = ttx-key COLON ttx-value  ; parameter
37   * ttx-key    = "graphic" | "control" | "misc" | "page" | "private"
38   * ttx-value  = *ttx-value-octet
39   *
40   * ttx-value-octet = %x00-23 | (%x5C "24") | %x25-5B | (%x5C "5C") | %x5D-FF
41   * 
42   * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
43   */
44  @SuppressWarnings("serial")
45  public class TeletexTerminalIdentifierSyntaxChecker extends SyntaxChecker
46  {
47      /** A logger for this class */
48      private static final Logger LOG = LoggerFactory.getLogger( TeletexTerminalIdentifierSyntaxChecker.class );
49  
50  
51      /**
52       * Creates a new instance of TeletexTerminalIdentifier.
53       */
54      public TeletexTerminalIdentifierSyntaxChecker()
55      {
56          super( SchemaConstants.TELETEX_TERMINAL_IDENTIFIER_SYNTAX );
57      }
58  
59  
60      /**
61       * {@inheritDoc}
62       */
63      public boolean isValidSyntax( Object value )
64      {
65          String strValue = null;
66  
67          if ( value == null )
68          {
69              LOG.debug( "Syntax invalid for 'null'" );
70              return false;
71          }
72  
73          if ( value instanceof String )
74          {
75              strValue = ( String ) value;
76          }
77          else if ( value instanceof byte[] )
78          {
79              strValue = Strings.utf8ToString( ( byte[] ) value );
80          }
81          else
82          {
83              strValue = value.toString();
84          }
85  
86          if ( strValue.length() == 0 )
87          {
88              LOG.debug( "Syntax invalid for '{}'", value );
89              return false;
90          }
91  
92          // Search for the first '$' separator
93          int dollar = strValue.indexOf( '$' );
94  
95          String terminalIdentifier = ( ( dollar == -1 ) ? strValue : strValue.substring( 0, dollar ) );
96  
97          if ( terminalIdentifier.length() == 0 )
98          {
99              // It should not be null
100             LOG.debug( "Syntax invalid for '{}'", value );
101             return false;
102         }
103 
104         if ( !Strings.isPrintableString( terminalIdentifier ) )
105         {
106             // It's not a valid PrintableString 
107             LOG.debug( "Syntax invalid for '{}'", value );
108             return false;
109         }
110 
111         if ( dollar == -1 )
112         {
113             // No ttx-param : let's get out
114             LOG.debug( "Syntax valid for '{}'", value );
115             return true;
116         }
117 
118         // Ok, now let's deal withh optional ttx-params
119         String[] ttxParams = strValue.substring( dollar + 1 ).split( "\\$" );
120 
121         if ( ttxParams.length == 0 )
122         {
123             LOG.debug( "Syntax invalid for '{}'", value );
124             return false;
125         }
126 
127         for ( String ttxParam : ttxParams )
128         {
129             int colon = ttxParam.indexOf( ':' );
130 
131             if ( colon == -1 )
132             {
133                 // we must have a ':' separator
134                 LOG.debug( "Syntax invalid for '{}'", value );
135                 return false;
136             }
137 
138             String key = ttxParam.substring( 0, colon );
139 
140             if ( key.startsWith( "graphic" )
141                 || key.startsWith( "control" )
142                 || key.startsWith( "misc" )
143                 || key.startsWith( "page" )
144                 || key.startsWith( "private" ) )
145             {
146                 if ( colon + 1 == ttxParam.length() )
147                 {
148                     LOG.debug( "Syntax invalid for '{}'", value );
149                     return false;
150                 }
151 
152                 boolean hasEsc = false;
153 
154                 for ( byte b : Strings.getBytesUtf8( ttxParam ) )
155                 {
156                     switch ( b )
157                     {
158                         case 0x24:
159                             // '$' is not accepted
160                             LOG.debug( "Syntax invalid for '{}'", value );
161                             return false;
162 
163                         case 0x5c:
164                             if ( hasEsc )
165                             {
166                                 // two following \ are not accepted
167                                 LOG.debug( "Syntax invalid for '{}'", value );
168                                 return false;
169                             }
170                             else
171                             {
172                                 hasEsc = true;
173                             }
174 
175                             continue;
176 
177                         case '2':
178                             continue;
179 
180                         case '4':
181                             // We have found a "\24"
182                             hasEsc = false;
183                             continue;
184 
185                         case '5':
186                             continue;
187 
188                         case 'c':
189                         case 'C':
190                             // We have found a "\5c" or a "\5C"
191                             hasEsc = false;
192                             continue;
193 
194                         default:
195                             if ( hasEsc )
196                             {
197                                 // A \ should be followed by "24" or "5c" or "5C"
198                                 return false;
199                             }
200 
201                             continue;
202                     }
203                 }
204             }
205             else
206             {
207                 LOG.debug( "Syntax invalid for '{}'", value );
208                 return false;
209             }
210         }
211 
212         LOG.debug( "Syntax valid for '{}'", value );
213         return true;
214     }
215 }