Source Code Cross Referenced for DNParser.java in  » Apache-Harmony-Java-SE » org-package » org » apache » harmony » security » x509 » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Apache Harmony Java SE » org package » org.apache.harmony.security.x509 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         *  Licensed to the Apache Software Foundation (ASF) under one or more
003:         *  contributor license agreements.  See the NOTICE file distributed with
004:         *  this work for additional information regarding copyright ownership.
005:         *  The ASF licenses this file to You under the Apache License, Version 2.0
006:         *  (the "License"); you may not use this file except in compliance with
007:         *  the License.  You may obtain a copy of the License at
008:         *
009:         *     http://www.apache.org/licenses/LICENSE-2.0
010:         *
011:         *  Unless required by applicable law or agreed to in writing, software
012:         *  distributed under the License is distributed on an "AS IS" BASIS,
013:         *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014:         *  See the License for the specific language governing permissions and
015:         *  limitations under the License.
016:         */
017:
018:        /**
019:         * @author Alexander V. Esin, Stepan M. Mishura
020:         * @version $Revision$
021:         */package org.apache.harmony.security.x509;
022:
023:        import java.io.IOException;
024:        import java.util.ArrayList;
025:        import java.util.List;
026:
027:        import org.apache.harmony.security.internal.nls.Messages;
028:        import org.apache.harmony.security.x501.AttributeTypeAndValue;
029:        import org.apache.harmony.security.x501.AttributeValue;
030:
031:        /**
032:         * Distinguished Name Parser.
033:         * 
034:         * Parses a distinguished name(DN) string according
035:         * BNF syntax specified in RFC 2253 and RFC 1779
036:         * 
037:         * RFC 2253: Lightweight Directory Access Protocol (v3):
038:         *           UTF-8 String Representation of Distinguished Names
039:         *   http://www.ietf.org/rfc/rfc2253.txt
040:         * 
041:         * RFC 1779: A String Representation of Distinguished Names
042:         *   http://www.ietf.org/rfc/rfc1779.txt
043:         */
044:        public class DNParser {
045:
046:            // length of distinguished name string
047:            protected final int length;
048:
049:            protected int pos, beg, end;
050:
051:            // tmp vars to store positions of the currently parsed item
052:            protected int cur;
053:
054:            // distinguished name chars
055:            protected char[] chars;
056:
057:            // raw string contains '"' or '\'
058:            protected boolean hasQE;
059:
060:            // DER encoding of currently parsed item
061:            protected byte[] encoded;
062:
063:            /**
064:             * Constructs DN parser
065:             * 
066:             * @param dn - distinguished name string to be parsed
067:             */
068:            public DNParser(String dn) throws IOException {
069:                this .length = dn.length();
070:                chars = dn.toCharArray();
071:            }
072:
073:            // gets next attribute type: (ALPHA 1*keychar) / oid
074:            protected String nextAT() throws IOException {
075:
076:                hasQE = false; // reset
077:
078:                // skip preceding space chars, they can present after
079:                // comma or semicolon (compatibility with RFC 1779)
080:                for (; pos < length && chars[pos] == ' '; pos++) {
081:                }
082:                if (pos == length) {
083:                    return null; // reached the end of DN
084:                }
085:
086:                // mark the beginning of attribute type
087:                beg = pos;
088:
089:                // attribute type chars
090:                pos++;
091:                for (; pos < length && chars[pos] != '=' && chars[pos] != ' '; pos++) {
092:                    // we don't follow exact BNF syntax here:
093:                    // accept any char except space and '='
094:                }
095:                if (pos >= length) {
096:                    // unexpected end of DN
097:                    throw new IOException(Messages.getString("security.192")); //$NON-NLS-1$
098:                }
099:
100:                // mark the end of attribute type
101:                end = pos;
102:
103:                // skip trailing space chars between attribute type and '='
104:                // (compatibility with RFC 1779)
105:                if (chars[pos] == ' ') {
106:                    for (; pos < length && chars[pos] != '='
107:                            && chars[pos] == ' '; pos++) {
108:                    }
109:
110:                    if (chars[pos] != '=' || pos == length) {
111:                        // unexpected end of DN
112:                        throw new IOException(Messages
113:                                .getString("security.192")); //$NON-NLS-1$
114:                    }
115:                }
116:
117:                pos++; //skip '=' char
118:
119:                // skip space chars between '=' and attribute value
120:                // (compatibility with RFC 1779)
121:                for (; pos < length && chars[pos] == ' '; pos++) {
122:                }
123:
124:                // in case of oid attribute type skip its prefix: "oid." or "OID."
125:                // (compatibility with RFC 1779)
126:                if ((end - beg > 4) && (chars[beg + 3] == '.')
127:                        && (chars[beg] == 'O' || chars[beg] == 'o')
128:                        && (chars[beg + 1] == 'I' || chars[beg + 1] == 'i')
129:                        && (chars[beg + 2] == 'D' || chars[beg + 2] == 'd')) {
130:                    beg += 4;
131:                }
132:
133:                return new String(chars, beg, end - beg);
134:            }
135:
136:            // gets quoted attribute value: QUOTATION *( quotechar / pair ) QUOTATION 
137:            protected String quotedAV() throws IOException {
138:
139:                pos++;
140:                beg = pos;
141:                end = beg;
142:                while (true) {
143:
144:                    if (pos == length) {
145:                        // unexpected end of DN
146:                        throw new IOException(Messages
147:                                .getString("security.192")); //$NON-NLS-1$
148:                    }
149:
150:                    if (chars[pos] == '"') {
151:                        // enclosing quotation was found
152:                        pos++;
153:                        break;
154:                    } else if (chars[pos] == '\\') {
155:                        chars[end] = getEscaped();
156:                    } else {
157:                        // shift char: required for string with escaped chars
158:                        chars[end] = chars[pos];
159:                    }
160:                    pos++;
161:                    end++;
162:                }
163:
164:                // skip trailing space chars before comma or semicolon.
165:                // (compatibility with RFC 1779)
166:                for (; pos < length && chars[pos] == ' '; pos++) {
167:                }
168:
169:                return new String(chars, beg, end - beg);
170:            }
171:
172:            // gets hex string attribute value: "#" hexstring
173:            private String hexAV() throws IOException {
174:
175:                if (pos + 4 >= length) {
176:                    // encoded byte array  must be not less then 4 c
177:                    throw new IOException(Messages.getString("security.192")); //$NON-NLS-1$
178:                }
179:
180:                beg = pos; // store '#' position
181:                pos++;
182:                while (true) {
183:
184:                    // check for end of attribute value 
185:                    // looks for space and component separators
186:                    if (pos == length || chars[pos] == '+' || chars[pos] == ','
187:                            || chars[pos] == ';') {
188:                        end = pos;
189:                        break;
190:                    }
191:
192:                    if (chars[pos] == ' ') {
193:                        end = pos;
194:                        pos++;
195:                        // skip trailing space chars before comma or semicolon.
196:                        // (compatibility with RFC 1779)
197:                        for (; pos < length && chars[pos] == ' '; pos++) {
198:                        }
199:                        break;
200:                    } else if (chars[pos] >= 'A' && chars[pos] <= 'F') {
201:                        chars[pos] += 32; //to low case
202:                    }
203:
204:                    pos++;
205:                }
206:
207:                // verify length of hex string
208:                // encoded byte array  must be not less then 4 and must be even number
209:                int hexLen = end - beg; // skip first '#' char
210:                if (hexLen < 5 || (hexLen & 1) == 0) {
211:                    throw new IOException(Messages.getString("security.192")); //$NON-NLS-1$
212:                }
213:
214:                // get byte encoding from string representation
215:                encoded = new byte[hexLen / 2];
216:                for (int i = 0, p = beg + 1; i < encoded.length; p += 2, i++) {
217:                    encoded[i] = (byte) getByte(p);
218:                }
219:
220:                return new String(chars, beg, hexLen);
221:            }
222:
223:            // gets string attribute value: *( stringchar / pair )
224:            protected String escapedAV() throws IOException {
225:
226:                beg = pos;
227:                end = pos;
228:                while (true) {
229:
230:                    if (pos >= length) {
231:                        // the end of DN has been found
232:                        return new String(chars, beg, end - beg);
233:                    }
234:
235:                    switch (chars[pos]) {
236:                    case '+':
237:                    case ',':
238:                    case ';':
239:                        // separator char has beed found
240:                        return new String(chars, beg, end - beg);
241:                    case '\\':
242:                        // escaped char
243:                        chars[end++] = getEscaped();
244:                        pos++;
245:                        break;
246:                    case ' ':
247:                        // need to figure out whether space defines
248:                        // the end of attribute value or not                 
249:                        cur = end;
250:
251:                        pos++;
252:                        chars[end++] = ' ';
253:
254:                        for (; pos < length && chars[pos] == ' '; pos++) {
255:                            chars[end++] = ' ';
256:                        }
257:                        if (pos == length || chars[pos] == ','
258:                                || chars[pos] == '+' || chars[pos] == ';') {
259:                            // separator char or the end of DN has beed found
260:                            return new String(chars, beg, cur - beg);
261:                        }
262:                        break;
263:                    default:
264:                        chars[end++] = chars[pos];
265:                        pos++;
266:                    }
267:                }
268:            }
269:
270:            // returns escaped char
271:            private char getEscaped() throws IOException {
272:
273:                pos++;
274:                if (pos == length) {
275:                    throw new IOException(Messages.getString("security.192")); //$NON-NLS-1$
276:                }
277:
278:                switch (chars[pos]) {
279:                case '"':
280:                case '\\':
281:                    hasQE = true;
282:                case ',':
283:                case '=':
284:                case '+':
285:                case '<':
286:                case '>':
287:                case '#':
288:                case ';':
289:                case ' ':
290:                    //FIXME: escaping is allowed only for leading or trailing space char 
291:                    return chars[pos];
292:                default:
293:                    // RFC doesn't explicitly say that escaped hex pair is 
294:                    // interpreted as UTF-8 char. It only contains an example of such DN.
295:                    return getUTF8();
296:                }
297:            }
298:
299:            // decodes UTF-8 char
300:            // see http://www.unicode.org for UTF-8 bit distribution table
301:            protected char getUTF8() throws IOException {
302:
303:                int res = getByte(pos);
304:                pos++; //FIXME tmp
305:
306:                if (res < 128) { // one byte: 0-7F
307:                    return (char) res;
308:                } else if (res >= 192 && res <= 247) {
309:
310:                    int count;
311:                    if (res <= 223) { // two bytes: C0-DF
312:                        count = 1;
313:                        res = res & 0x1F;
314:                    } else if (res <= 239) { // three bytes: E0-EF
315:                        count = 2;
316:                        res = res & 0x0F;
317:                    } else { // four bytes: F0-F7
318:                        count = 3;
319:                        res = res & 0x07;
320:                    }
321:
322:                    int b;
323:                    for (int i = 0; i < count; i++) {
324:                        pos++;
325:                        if (pos == length || chars[pos] != '\\') {
326:                            return 0x3F; //FIXME failed to decode UTF-8 char - return '?'
327:                        }
328:                        pos++;
329:
330:                        b = getByte(pos);
331:                        pos++; //FIXME tmp
332:                        if ((b & 0xC0) != 0x80) {
333:                            return 0x3F; //FIXME failed to decode UTF-8 char - return '?'
334:                        }
335:
336:                        res = (res << 6) + (b & 0x3F);
337:                    }
338:                    return (char) res;
339:                } else {
340:                    return 0x3F; //FIXME failed to decode UTF-8 char - return '?'
341:                }
342:            }
343:
344:            // Returns byte representation of a char pair
345:            // The char pair is composed of DN char in
346:            // specified 'position' and the next char
347:            // According to BNF syntax:
348:            // hexchar    = DIGIT / "A" / "B" / "C" / "D" / "E" / "F"
349:            //                    / "a" / "b" / "c" / "d" / "e" / "f"
350:            protected int getByte(int position) throws IOException {
351:
352:                if ((position + 1) >= length) {
353:                    // to avoid ArrayIndexOutOfBoundsException
354:                    throw new IOException(Messages.getString("security.192")); //$NON-NLS-1$
355:                }
356:
357:                int b1, b2;
358:
359:                b1 = chars[position];
360:                if (b1 >= '0' && b1 <= '9') {
361:                    b1 = b1 - '0';
362:                } else if (b1 >= 'a' && b1 <= 'f') {
363:                    b1 = b1 - 87; // 87 = 'a' - 10
364:                } else if (b1 >= 'A' && b1 <= 'F') {
365:                    b1 = b1 - 55; // 55 = 'A' - 10
366:                } else {
367:                    throw new IOException(Messages.getString("security.192")); //$NON-NLS-1$
368:                }
369:
370:                b2 = chars[position + 1];
371:                if (b2 >= '0' && b2 <= '9') {
372:                    b2 = b2 - '0';
373:                } else if (b2 >= 'a' && b2 <= 'f') {
374:                    b2 = b2 - 87; // 87 = 'a' - 10
375:                } else if (b2 >= 'A' && b2 <= 'F') {
376:                    b2 = b2 - 55; // 55 = 'A' - 10
377:                } else {
378:                    throw new IOException(Messages.getString("security.192")); //$NON-NLS-1$
379:                }
380:
381:                return (b1 << 4) + b2;
382:            }
383:
384:            /**
385:             * Parses DN
386:             *
387:             * @return a list of Relative Distinguished Names(RND),
388:             *         each RDN is represented as a list of AttributeTypeAndValue objects
389:             */
390:            public List parse() throws IOException {
391:
392:                List list = new ArrayList();
393:
394:                String attValue;
395:                String attType = nextAT();
396:                if (attType == null) {
397:                    return list; //empty list of RDNs 
398:                }
399:
400:                List atav = new ArrayList();
401:                while (true) {
402:
403:                    if (pos == length) {
404:
405:                        //empty Attribute Value
406:                        atav.add(new AttributeTypeAndValue(attType,
407:                                new AttributeValue("", false))); //$NON-NLS-1$
408:                        list.add(0, atav);
409:
410:                        return list;
411:                    }
412:
413:                    switch (chars[pos]) {
414:                    case '"':
415:                        attValue = quotedAV();
416:                        atav.add(new AttributeTypeAndValue(attType,
417:                                new AttributeValue(attValue, hasQE)));
418:                        break;
419:                    case '#':
420:                        attValue = hexAV();
421:
422:                        atav.add(new AttributeTypeAndValue(attType,
423:                                new AttributeValue(attValue, encoded)));
424:                        break;
425:                    case '+':
426:                    case ',':
427:                    case ';': // compatibility with RFC 1779: semicolon can separate RDNs
428:                        //empty attribute value
429:                        atav.add(new AttributeTypeAndValue(attType,
430:                                new AttributeValue("", false))); //$NON-NLS-1$
431:                        break;
432:                    default:
433:                        attValue = escapedAV();
434:                        atav.add(new AttributeTypeAndValue(attType,
435:                                new AttributeValue(attValue, hasQE)));
436:                    }
437:
438:                    if (pos >= length) {
439:                        list.add(0, atav);
440:                        return list;
441:                    }
442:
443:                    if (chars[pos] == ',' || chars[pos] == ';') {
444:                        list.add(0, atav);
445:                        atav = new ArrayList();
446:                    } else if (chars[pos] != '+') {
447:                        throw new IOException(Messages
448:                                .getString("security.192")); //$NON-NLS-1$
449:                    }
450:
451:                    pos++;
452:                    attType = nextAT();
453:                    if (attType == null) {
454:                        throw new IOException(Messages
455:                                .getString("security.192")); //$NON-NLS-1$
456:                    }
457:                }
458:            }
459:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.