Source Code Cross Referenced for MMSAddress.java in  » 6.0-JDK-Modules » j2me » com » sun » midp » io » j2me » mms » 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 » 6.0 JDK Modules » j2me » com.sun.midp.io.j2me.mms 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         *   
0003:         *
0004:         * Copyright  1990-2007 Sun Microsystems, Inc. All Rights Reserved.
0005:         * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
0006:         * 
0007:         * This program is free software; you can redistribute it and/or
0008:         * modify it under the terms of the GNU General Public License version
0009:         * 2 only, as published by the Free Software Foundation.
0010:         * 
0011:         * This program is distributed in the hope that it will be useful, but
0012:         * WITHOUT ANY WARRANTY; without even the implied warranty of
0013:         * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
0014:         * General Public License version 2 for more details (a copy is
0015:         * included at /legal/license.txt).
0016:         * 
0017:         * You should have received a copy of the GNU General Public License
0018:         * version 2 along with this work; if not, write to the Free Software
0019:         * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
0020:         * 02110-1301 USA
0021:         * 
0022:         * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
0023:         * Clara, CA 95054 or visit www.sun.com if you need additional
0024:         * information or have any questions.
0025:         */
0026:
0027:        package com.sun.midp.io.j2me.mms;
0028:
0029:        /**
0030:         * MMS address parsing and validation.
0031:         * MMS address is validated according to Table D-2 in WMA2.0 specification.
0032:         * In addition address is parsed into the fields of <code>MMSAddress </code>
0033:         * object.
0034:         */
0035:        public class MMSAddress {
0036:
0037:            /**
0038:             * Determines whether a character represents a hexadecimal number.
0039:             * ('0' - '9' and 'A' - 'F')
0040:             * @param c The character to check.
0041:             * @return <code>true </code> if <code>c</code> is a hexadecimal number;
0042:             * <code> false </code> otherwise
0043:             */
0044:            private static boolean hex(char c) {
0045:                return (digit(c) || (c >= 'A' && c <= 'F'));
0046:            }
0047:
0048:            /**
0049:             * Determines whether a character is a letter.
0050:             * @param c The character to check.
0051:             * @return <code>true </code> if <code>c</code> is a letter; 
0052:             * <code> false </code> otherwise
0053:             */
0054:            private static boolean alpha(char c) {
0055:                return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
0056:            }
0057:
0058:            /**
0059:             * Determines whether a character represents a digit.
0060:             * @param c The character to check.
0061:             * @return <code>true </code> if <code>c</code> is a digit; 
0062:             * <code> false </code> otherwise
0063:             */
0064:            private static boolean digit(char c) {
0065:                return (c >= '0' && c <= '9');
0066:            }
0067:
0068:            /**
0069:             * Determines whether a string represents a valid phone number
0070:             * starting from an index. If the address string is a valid
0071:             * phone number representation it is parsed into the fields of 
0072:             * <code>MMSAddress </code>object (address and application id).
0073:             * General phone number syntax is specified in WMA 2.0 spec as :
0074:             * ("+" 1*digit | 1*digit) [applicationId]
0075:             *
0076:             * @param s The string to check.
0077:             * @param mmsAddress The return <code>MMSAddress</code> object which
0078:             * fields are filled with parsed address and
0079:             * application id (which can be null), 
0080:             * its type is set to GLOBAL_PHONE_NUMBER.
0081:             * @param i The index of the string at which to start the check. 
0082:             * <code> 0 <= i <= s.length() </code> 
0083:             *
0084:             * @return <code>true </code> if <code>s</code> represents a valid 
0085:             * phone number starting from index <code>i</code>;
0086:             * <code> false </code> otherwise and if index <code>i</code> is
0087:             * invalide value
0088:             */
0089:            static boolean parsePhoneNumber(String s, int i,
0090:                    MMSAddress mmsAddress) {
0091:
0092:                int len = s.length();
0093:                if (i < 0 || i >= len) {
0094:                    return false;
0095:                }
0096:
0097:                int initI = i;
0098:                char c = s.charAt(i);
0099:
0100:                if (c == '+') {
0101:                    i++;
0102:                    if (len == i) {
0103:                        return false;
0104:                    }
0105:                }
0106:
0107:                int j = 0;
0108:                for (; i < len; j++, i++) {
0109:                    c = s.charAt(i);
0110:                    if (!digit(c)) {
0111:                        break;
0112:                    }
0113:                }
0114:
0115:                if (j == 0) {
0116:                    return false;
0117:                }
0118:
0119:                if (i == len) {
0120:                    mmsAddress.set(s.substring(initI), null,
0121:                            GLOBAL_PHONE_NUMBER);
0122:                    return true;
0123:                }
0124:
0125:                if (c == ':') {
0126:                    mmsAddress.set(s.substring(initI, i), null,
0127:                            GLOBAL_PHONE_NUMBER);
0128:                    return parseApplicationId(s, i, mmsAddress);
0129:                }
0130:
0131:                return false;
0132:            }
0133:
0134:            /**
0135:             * Determines whether a string represents a valid ipv4 address
0136:             * starting from an index. If the address string is a valid
0137:             * ipv4 representation it is parsed into the fields of 
0138:             * <code>MMSAddress </code>object (address and application id).
0139:             * ipv4 syntax is specified in WMA 2.0 spec as :
0140:             * 1*3digit "." 1*3digit "." 1*3digit "." 1*3digit [applicationId]
0141:             *
0142:             * @param s The string to check.
0143:             * @param mmsAddress The return <code>MMSAddress</code> object which
0144:             * fields are filled with parsed address and
0145:             * application id (which can be null), its type is set to IPV4.
0146:             * @param i The index of the string at which to start the check. 
0147:             * <code> 0 <= i <= s.length() </code> 
0148:             *
0149:             * @return <code>true </code> if <code>s</code> represents a valid 
0150:             * ipv4 address starting from index <code>i</code>;
0151:             * <code> false </code> otherwise and if index <code>i</code> is
0152:             * invalide value
0153:             */
0154:            static boolean parseIpv4(String s, int i, MMSAddress mmsAddress) {
0155:                int len = s.length();
0156:                if (i <= 0 || i >= len) {
0157:                    return false;
0158:                }
0159:
0160:                char c;
0161:                int j;
0162:                int initI = i;
0163:
0164:                for (int num = 1; num < 5; num++) {
0165:
0166:                    for (j = 0; j < 3 && i < len; i++, j++) {
0167:
0168:                        c = s.charAt(i);
0169:
0170:                        if (!digit(c)) {
0171:                            break;
0172:                        }
0173:                    }
0174:
0175:                    // there should be at least one digit and 
0176:                    // the number between dots should be less then 256
0177:                    if (j == 0
0178:                            || (j == 3 && (((s.charAt(i - 3) - '0') * 10 + (s
0179:                                    .charAt(i - 2) - '0')) * 10 + (s
0180:                                    .charAt(i - 1) - '0')) > 255)) {
0181:                        return false;
0182:                    }
0183:
0184:                    // check if this is the end of the string
0185:                    if (i == len) {
0186:                        if (num == 4) {
0187:                            mmsAddress.set(s.substring(initI), null, IPV4);
0188:                            return true;
0189:                        }
0190:                        return false;
0191:                    }
0192:
0193:                    c = s.charAt(i);
0194:
0195:                    if (c == ':') {
0196:                        mmsAddress.set(s.substring(initI, i), null, IPV4);
0197:                        return parseApplicationId(s, i, mmsAddress);
0198:                    }
0199:
0200:                    if (c != '.') {
0201:                        return false; // 4th character after beg (or dot)
0202:                        // should be dot;
0203:                        // only dots are allowed as non digit char
0204:                    }
0205:
0206:                    // allowed '.' => continue
0207:                    i++;
0208:                }
0209:
0210:                return false;
0211:            }
0212:
0213:            /**
0214:             * Determines whether a string represents a valid ipv6 address
0215:             * starting from an index. If the address string is a valid
0216:             * ipv6 representation it is parsed into the fields of 
0217:             * <code>MMSAddress </code>object (address and application id).
0218:             * ipv6 syntax is specified in WMA 2.0 spec as :
0219:             * ipv6-atom ":" ipv6-atom ":" ipv6-atom ":" ipv6-atom ":" 
0220:             * ipv6-atom ":" ipv6-atom ":" ipv6-atom ":" ipv6-atom [appId]
0221:             * where ipv6-atom is 1*4(digit | hex-alpha).
0222:             *
0223:             * @param s The string to check.
0224:             * @param mmsAddress The return <code>MMSAddress</code> object which
0225:             * fields are filled with parsed address and
0226:             * application id (which can be null), its type is set to IPV6.
0227:             * @param i The index of the string at which to start the check. 
0228:             * <code> 0 <= i <= s.length() </code> 
0229:             *
0230:             * @return <code>true </code> if <code>s</code> represents a valid 
0231:             * ipv6 address starting from index <code>i</code>;
0232:             * <code> false </code> otherwise and if index <code>i</code> is
0233:             * invalide value
0234:             */
0235:            static boolean parseIpv6(String s, int i, MMSAddress mmsAddress) {
0236:                int len = s.length();
0237:                if (i <= 0 || i >= len) {
0238:                    return false;
0239:                }
0240:
0241:                char c;
0242:                int j;
0243:                int initI = i;
0244:
0245:                for (int num = 1; num < 9; num++) {
0246:
0247:                    for (j = 0; j < 4 && i < len; i++, j++) {
0248:
0249:                        c = s.charAt(i);
0250:
0251:                        if (!hex(c)) {
0252:                            break;
0253:                        }
0254:                    }
0255:
0256:                    // there should be at least one digit 
0257:                    if (j == 0) {
0258:                        return false;
0259:                    }
0260:
0261:                    // check if this is the end of the string
0262:                    if (i == len) {
0263:                        if (num == 8) {
0264:                            mmsAddress.set(s.substring(initI), null, IPV6);
0265:                            return true;
0266:                        }
0267:                        return false;
0268:                    }
0269:
0270:                    c = s.charAt(i);
0271:
0272:                    if (c == ':') {
0273:                        if (num == 8) {
0274:                            mmsAddress.set(s.substring(initI, i), null, IPV6);
0275:                            return parseApplicationId(s, i, mmsAddress);
0276:                        }
0277:                    } else {
0278:                        return false; // 5th character after beg (or :)
0279:                        // should be :
0280:                        // only : are allowed as non digit char
0281:                    }
0282:
0283:                    // allowed ':' => continue
0284:                    i++;
0285:                }
0286:
0287:                return false;
0288:            }
0289:
0290:            /**
0291:             * Determines whether a string represents a valid shortcode
0292:             * starting from an index. If the address string is a valid
0293:             * shortcode representation it is parsed into the fields of 
0294:             * <code>MMSAddress </code>object (address and null for appId).
0295:             * Shortcode syntax is specified in WMA 2.0 spec as :
0296:             * *(digit | alpha)
0297:             *
0298:             * @param s The string to check.
0299:             * @param mmsAddress The return <code>MMSAddress</code> object which
0300:             * fields are filled with parsed address and application id (null in
0301:             * this case), its type is set to SHORTCODE.
0302:             * @param i The index of the string at which to start the check. 
0303:             * <code> 0 <= i <= s.length() </code> 
0304:             *
0305:             * @return <code>true </code> if <code>s</code> represents a valid 
0306:             * shortcode starting from index <code>i</code>;
0307:             * <code> false </code> otherwise and if index <code>i</code> is
0308:             * invalide value
0309:             */
0310:            static boolean parseShortCode(String s, int i, MMSAddress mmsAddress) {
0311:                int len = s.length();
0312:                if (i > len) {
0313:                    return false;
0314:                }
0315:
0316:                if (i == len) {
0317:                    return false; // Even though spec allows "mms://" as a valid 
0318:                    // shortcode, we disallow it here
0319:                }
0320:                int initI = i;
0321:                char c;
0322:
0323:                for (; i < s.length(); i++) {
0324:                    c = s.charAt(i);
0325:
0326:                    if (!digit(c) && !alpha(c)) {
0327:                        return false;
0328:                    }
0329:                }
0330:                mmsAddress.set(s.substring(initI), null, SHORTCODE);
0331:                return true;
0332:            }
0333:
0334:            /**
0335:             * Determines whether a string represents a valid application ID
0336:             * starting from an index.If the address string is a valid
0337:             * application id representation it is parsed into the fields of 
0338:             * <code>MMSAddress </code>object (application id and null for the 
0339:             * address).
0340:             * Application ID syntax is specified in WMA 2.0 spec as :
0341:             * ":"[*(1*(alpha | digit | "." | "_") ".")]1*(alpha | digit | "." | "_").
0342:             * The number of characters in application ID must not exceed 32.
0343:             *
0344:             * @param s The string to check.
0345:             * @param mmsAddress The return <code>MMSAddress</code> object which
0346:             * fields are filled with parsed address (null in this case) and
0347:             * application id, its type is set to APP_ID.
0348:             * @param i The index of the string at which to start the check. 
0349:             * <code> 0 <= i <= s.length() </code> 
0350:             *
0351:             * @return <code>true </code> if <code>s</code> represents a valid 
0352:             * application ID starting from index <code>i</code>;
0353:             * <code> false </code> otherwise and if index <code>i</code> is
0354:             * invalide value
0355:             */
0356:            static boolean parseApplicationId(String s, int i,
0357:                    MMSAddress mmsAddress) {
0358:
0359:                int len = s.length();
0360:
0361:                /*
0362:                 * Empty string or string like ":" are not allowed.
0363:                 * Only 32 characters are allowed. 
0364:                 * Note: When checking appID length, keep in mind that
0365:                 * i is pointing to ":"
0366:                 */
0367:                if (i <= 0 || i >= len || (len - i - 1) > 32
0368:                        || (len - i - 1) < 0 || s.charAt(i) != ':') {
0369:                    return false;
0370:                }
0371:
0372:                i++; // to skip ':'
0373:
0374:                char c;
0375:                int initI = i;
0376:
0377:                for (int j = 0; i < len; i++) {
0378:
0379:                    c = s.charAt(i);
0380:
0381:                    for (j = 0; i < len; i++, j++) {
0382:                        c = s.charAt(i);
0383:
0384:                        if ((c != '_') && /* dot is also allowed in the spec ??? */
0385:                        !digit(c) && !alpha(c)) {
0386:                            break;
0387:                        }
0388:                    }
0389:
0390:                    if (i == len) {
0391:                        if (mmsAddress.type == INVALID_ADDRESS) {
0392:                            mmsAddress.set(null, s.substring(initI), APP_ID);
0393:                        } else {
0394:                            mmsAddress.setAppid(s.substring(initI));
0395:                        }
0396:                        return true;
0397:                    }
0398:
0399:                    // there has to be at least one digit or letter and
0400:                    // nondigit and nonalpha char can be only dot (one dot only)
0401:                    if (j == 0 || c != '.') {
0402:                        return false;
0403:                    }
0404:                }
0405:
0406:                return false;
0407:            }
0408:
0409:            // ------------------------------- E-mail validation ----------------
0410:            /**
0411:             * Determines whether a character represents a special e-mail character.
0412:             * @param c The character to check.
0413:             * @return <code>true </code> if <code>c</code> is a special character.
0414:             * <code> false </code> otherwise
0415:             */
0416:            private static boolean specials(char c) {
0417:                if (c == '(' || c == ')' || c == '<' || c == '>' || c == '@'
0418:                        || c == ',' || c == ';' || c == ':' || c == '\\'
0419:                        || c == '"' || c == '.' || c == '[' || c == ']') {
0420:                    return true;
0421:                }
0422:                return false;
0423:            }
0424:
0425:            /**
0426:             * Determines whether a character represents a character.
0427:             * @param c The character to check.
0428:             * @return <code>true </code> if <code>c</code> is a character.
0429:             * <code> false </code> otherwise
0430:             */
0431:            private static boolean isChar(char c) {
0432:                return ((int) c) >= 0 && ((int) c) <= 127;
0433:            }
0434:
0435:            /**
0436:             * Determines whether a character represents an ascii control
0437:             * character.
0438:             * @param c The character to check.
0439:             * @return <code>true </code> if <code>c</code> is a character.
0440:             * <code> false </code> otherwise
0441:             */
0442:            private static boolean asciiControl(char c) {
0443:                return ((int) c >= 0 && (int) c <= 31);
0444:            }
0445:
0446:            /**
0447:             * Determines whether a character represents an atom character.
0448:             * as specified in WMA 2.0 specification.
0449:             * @param c The character to check.
0450:             * @return <code>true </code> if <code>c</code> is a special character.
0451:             * <code> false </code> otherwise
0452:             */
0453:            private static boolean atomChar(char c) {
0454:                return ((int) c <= 127 && (int) c > 32 && !specials(c));
0455:            }
0456:
0457:            /**
0458:             * Determines first not linear white space character 
0459:             * in <code>s</code> after character with index <code>i</code> but
0460:             * before character with index <code>n</code>.
0461:             * 
0462:             * @param s The string to check.
0463:             * @param i The index of the string at which to start the check. 
0464:             * <code> 0 <= i <= s.length() </code>
0465:             * @param n The index of the last character to be checked in 
0466:             *          <code>s</code>.
0467:             * @return The first non linear white character after position 
0468:             *          <code>i</code>, it could the the same as passed in
0469:             *          <code>i</code> value if there are no linear white
0470:             *          space characters.
0471:             */
0472:            private static int linearWhiteSpaceSeq(String s, int i, int n) {
0473:                char c;
0474:                for (; i < n; i++) {
0475:                    c = s.charAt(i);
0476:                    if (c == ' ' || c == '\t') {
0477:                        continue;
0478:                    }
0479:                    if (c == '\r') {
0480:                        // only CR LF one after another are allowed
0481:                        // CR by itself is not allowed
0482:                        if (i == n - 1 || s.charAt(i + 1) != '\n') {
0483:                            return i;
0484:                        }
0485:                        i++;
0486:                    } else {
0487:                        return i;
0488:                    }
0489:                }
0490:
0491:                return i;
0492:            }
0493:
0494:            /**
0495:             * Determines whether a string represents a valid e-mail address
0496:             * starting from an index. If the address string is a valid
0497:             * e-mail address representation it is parsed into the fields of 
0498:             * <code>MMSAddress </code>object (address and null for appId).
0499:             * E-mail syntax is specified in WMA 2.0 spec.
0500:             *
0501:             * @param s The string to check.
0502:             * @param i The index of the string at which to start the check. 
0503:             * <code> 0 <= i <= s.length() </code>
0504:             * @param mmsAddress The return <code>MMSAddress</code> object which
0505:             * fields are filled with parsed address and
0506:             * application id (null in this case),  its type is set to EMAIL.
0507:             *
0508:             * @return <code>true </code> if <code>s</code> represents a valid 
0509:             * e-mail address starting from index <code>i</code>;
0510:             * <code> false </code> otherwise and if index <code>i</code> is
0511:             * invalide value
0512:             */
0513:            static boolean parseEmail(String s, int i, MMSAddress mmsAddress) {
0514:
0515:                int len = s.length();
0516:                if (i <= 0 || i >= len) {
0517:                    return false;
0518:                }
0519:
0520:                int initI = i;
0521:
0522:                // email can be on of the following:
0523:                // emial ::== mailbox | phrase : [#mailbox] ;
0524:
0525:                // if there is a ';' at the end then there should be a phrase
0526:                // at the beginning
0527:                if (s.charAt(len - 1) == ';') {
0528:
0529:                    if ((i = isPhrase(s, i, len - 1)) <= 0) {
0530:                        return false;
0531:                    }
0532:
0533:                    // there was no ":"
0534:                    if (i >= len - 1 || s.charAt(i) != ':') {
0535:                        return false;
0536:                    }
0537:
0538:                    i++; // move after ':'
0539:
0540:                    if (i == len - 1) {
0541:                        mmsAddress.set(s.substring(initI), null, EMAIL);
0542:                        return true; // phrase : ; is allowed string
0543:                    }
0544:
0545:                    if ((i = isMailbox(s, i, len - 1)) <= 0) {
0546:                        return false;
0547:                    }
0548:
0549:                    while (i < len - 1) {
0550:
0551:                        // there has to be a ',' sep
0552:                        if (i >= len - 2 && s.charAt(i) != ',') {
0553:                            return false;
0554:                        }
0555:
0556:                        if ((i = isMailbox(s, i + 1, len - 1)) <= 0) {
0557:                            return false;
0558:                        }
0559:                    }
0560:                    if (i == len - 1) {
0561:                        mmsAddress.set(s.substring(initI), null, EMAIL);
0562:                        return true;
0563:                    }
0564:                    return false;
0565:                }
0566:
0567:                if (isMailbox(s, i, len) == len) {
0568:                    mmsAddress.set(s.substring(initI), null, EMAIL);
0569:                    return true;
0570:                }
0571:                return false;
0572:            }
0573:
0574:            /**
0575:             * Determines whether a string represents a valid mailbox address
0576:             * starting from an index.
0577:             * Mailbox syntax is specified in WMA 2.0 spec as
0578:             * local-part"@"domain  or as
0579:             * [phrase] "<"[("@"domain) [*("," ("@"domain))]] local-part"@"domain">"
0580:             *
0581:             * @param s The string to check.
0582:             * @param i The index of the string at which to start the check. 
0583:             * <code> 0 <= i <= s.length() </code> 
0584:             * @param n The index of the last character to be checked in 
0585:             *          <code>s</code>.
0586:             *
0587:             * @return index till which 
0588:             * <code>s</code> contains valid mailbox specification;
0589:             * <code> -1 </code> if index <code>i</code> is invalid or
0590:             * if characters in <code>s</code> starting from <code>i</code>
0591:             * do not comply with mailbox specification
0592:             */
0593:            private static int isMailbox(String s, int i, int n) {
0594:                if (n > s.length()) {
0595:                    n = s.length();
0596:                }
0597:                if (i >= n) {
0598:                    return -1;
0599:                }
0600:
0601:                int initI = i;
0602:
0603:                if ((i = isLocalAtDomain(s, initI, n)) > 0) {
0604:                    return i;
0605:                }
0606:
0607:                i = initI;
0608:
0609:                // check for  [phrase] <[1#(@ domain):] local @ domain>
0610:                // note phrase is optional
0611:                if ((s.charAt(i) != '<') && (i = isPhrase(s, initI, n)) < 0) {
0612:                    return -1;
0613:                }
0614:
0615:                if (i == n || s.charAt(i) != '<') {
0616:                    return -1;
0617:                }
0618:
0619:                i++;
0620:
0621:                if (i == n) {
0622:                    return -1;
0623:                }
0624:
0625:                // there can be a list of domains: 
0626:                // @ domain, @domain, @domain :
0627:                boolean atLeastOneDomain = false;
0628:                while (s.charAt(i) == '@') {
0629:                    atLeastOneDomain = true;
0630:
0631:                    if ((i = isDomain(s, i + 1, n)) < 0) {
0632:                        return -1;
0633:                    }
0634:
0635:                    if (i == n) {
0636:                        return -1;
0637:                    }
0638:
0639:                    if (s.charAt(i) == ':') {
0640:                        break;
0641:                    }
0642:
0643:                    // @domain,,@domain is allowed
0644:                    while (s.charAt(i) == ',') {
0645:                        i++;
0646:                        if (i == n || s.charAt(i) == ':') {
0647:                            return -1;
0648:                        }
0649:                    }
0650:                }
0651:
0652:                if (atLeastOneDomain) {
0653:                    if (i == n || s.charAt(i) != ':') {
0654:                        return -1;
0655:                    }
0656:                    i++;
0657:                }
0658:
0659:                // local @ domain
0660:                if ((i = isLocalAtDomain(s, i, n)) <= 0) {
0661:                    return -1;
0662:                }
0663:
0664:                if (i < n && s.charAt(i) == '>') {
0665:                    return i + 1;
0666:                }
0667:                return -1;
0668:            }
0669:
0670:            /**
0671:             * Determines whether a string represents a valid "local-part"
0672:             * starting from an index.
0673:             * Local-part syntax is specified in WMA 2.0 spec as
0674:             * (atom | "\"alpha) *("." (atom | "\"alpha)) where 
0675:             * atom is represented by at least one char which is 
0676:             * not a space or a special or control character.
0677:             *
0678:             * @param s The string to check.
0679:             * @param i The index of the string at which to start the check
0680:             * <code> 0 <= i <= s.length() </code> 
0681:             * @param n The index of the last character to be checked in 
0682:             *          <code>s</code>.
0683:             *
0684:             * @return index till which 
0685:             * <code>s</code> contains valid local-part specification;
0686:             * <code> -1 </code> if index <code>i</code> is invalid or
0687:             * if characters in <code>s</code> starting from <code>i</code>
0688:             * do not comply with local-part specification
0689:             */
0690:            private static int isLocalPart(String s, int i, int n) {
0691:                return isSequenceOfAtomAndText(s, i, n, '"', '"', true);
0692:            }
0693:
0694:            /**
0695:             * Determines whether a string represents a valid "phrase"
0696:             * starting from an index.
0697:             * Phrase syntax is specified in WMA 2.0 spec as
0698:             * 1*(atom | """ *(text w/o ",\,\r but with linear space | "\"alpha) """) 
0699:             * where atom is represented by at least one char or more which is 
0700:             * not a space or a special or control character.
0701:             *
0702:             * @param s The string to check.
0703:             * @param i The index of the string at which to start the check
0704:             * <code> 0 <= i <= s.length() </code> 
0705:             * @param n The index of the last character to be checked in 
0706:             *          <code>s</code>.
0707:             *
0708:             * @return index till which 
0709:             * <code>s</code> contains valid phrase specification;
0710:             * <code> -1 </code> if index <code>i</code> is invalid or
0711:             * if characters in <code>s</code> starting from <code>i</code>
0712:             * do not comply with phrase specification
0713:             */
0714:            private static int isPhrase(String s, int i, int n) {
0715:                return isSequenceOfAtomAndText(s, i, n, '"', '"', false);
0716:            }
0717:
0718:            /**
0719:             * Determines whether a string represents a valid "domain"
0720:             * starting from an index.
0721:             * Domain syntax is specified in WMA 2.0 spec as
0722:             * 1*(atom | "[" *(text w/o ",[,],\r but with linear space | "\"alpha) "]")
0723:             * where atom is represented by at least one char or more which is 
0724:             * not a space or a special or control character.
0725:             *
0726:             * @param s The string to check.
0727:             * @param i The index of the string at which to start the check
0728:             * <code> 0 <= i <= s.length() </code> 
0729:             * @param n The index of the last character to be checked in 
0730:             *          <code>s</code>.
0731:             *
0732:             * @return index till which 
0733:             * <code>s</code> contains valid domain specification;
0734:             * <code> -1 </code> if index <code>i</code> is invalid or
0735:             * if characters in <code>s</code> starting from <code>i</code>
0736:             * do not comply with domain specification
0737:             */
0738:            private static int isDomain(String s, int i, int n) {
0739:                return isSequenceOfAtomAndText(s, i, n, '[', ']', true);
0740:            }
0741:
0742:            /**
0743:             * Determines whether a string starting from an index
0744:             * represents a valid sequence that satisfies the following
0745:             * syntax:
0746:             * text ::== <begSep>
0747:             *           *(1*(<any char w/o begSep and eSep incl LWSP>|\ALPHA))
0748:             *           <endSep>
0749:             * sequence ::== 1*(atom | text) | (atom | text) *("." (atom | text))
0750:             * where atom is represented by at least one or more characters that  
0751:             * are not space or special or control characters
0752:             * and begSep/endSep are separators that are placed around text.
0753:             * LWSP is a linear white space (space and tabs and \r\n but not \r).
0754:             *
0755:             * @param s The string to check.
0756:             * @param i The index of the string at which to start the check
0757:             * <code> 0 <= i <= s.length() </code> 
0758:             * @param n The index of the last character to be checked in 
0759:             *          <code>s</code>.
0760:             * @param begSep The character marking beginning of quoted text
0761:             * @param endSep The character marking the end of the text
0762:             * @param dotSeparated If true atom and quoted text should be 
0763:             *        separated by a "." character; ".." is not allowed
0764:             *
0765:             * @return index till which 
0766:             * <code>s</code> contains valid sequence;
0767:             * <code> -1 </code> if index <code>i</code> is invalid or
0768:             * if characters in <code>s</code> starting from <code>i</code>
0769:             * do not comply with the sequence specification.
0770:             */
0771:            private static int isSequenceOfAtomAndText(String s, int i, int n,
0772:                    char begSep, char endSep, boolean dotSeparated) {
0773:                if (i >= s.length()) {
0774:                    return -1;
0775:                }
0776:                if (n > s.length()) {
0777:                    n = s.length();
0778:                }
0779:
0780:                // see if there is at least one word
0781:                boolean withinQuotation = false;
0782:                boolean atLeastOneWord = false;
0783:
0784:                char c;
0785:                int initI = i;
0786:
0787:                for (; i < n; i++) {
0788:                    c = s.charAt(i);
0789:                    if (c == begSep) {
0790:                        if (begSep == endSep) {
0791:                            withinQuotation = !withinQuotation;
0792:                        } else if (withinQuotation) {
0793:                            return -1;
0794:                        } else {
0795:                            withinQuotation = true;
0796:                        }
0797:                        atLeastOneWord = true;
0798:                    } else if (c == endSep) {
0799:                        if (!withinQuotation) {
0800:                            return -1;
0801:                        }
0802:                        withinQuotation = false;
0803:                    } else if (c == '\\') {
0804:                        // chars can be quoated only within separators
0805:                        // and there has to be another char after '\'
0806:                        if (!withinQuotation || i == n - 1) {
0807:                            return -1;
0808:                        }
0809:                        i++;
0810:                        c = s.charAt(i);
0811:                        // only ALPHA character can be quoted
0812:                        if (!alpha(c)) {
0813:                            return -1;
0814:                        }
0815:
0816:                    } else if (dotSeparated && c == '.') {
0817:                        if (i == initI
0818:                                || ((i - initI) > 0 && s.charAt(i - 1) == '.')) {
0819:                            // empty word
0820:                            // string starts with .
0821:                            return -1;
0822:                        }
0823:                    } else if (withinQuotation) {
0824:                        // within quotation \r is not allowed but
0825:                        // \r is allowed as part of linear-white-space
0826:                        if (c == ' ' || c == '\t' || c == '\r') {
0827:                            if ((i = linearWhiteSpaceSeq(s, i, n)) < 0) {
0828:                                return -1;
0829:                            }
0830:                            i--;
0831:                        }
0832:                    } else if (atomChar(c)) {
0833:                        atLeastOneWord = true;
0834:                    } else {
0835:                        // this is supposed to be an atom 
0836:                        break;
0837:                    }
0838:                }
0839:
0840:                // open quotation or no words or
0841:                // dot separator is the last char
0842:                if (withinQuotation
0843:                        || !atLeastOneWord
0844:                        || (dotSeparated && i > initI && s.charAt(i - 1) == '.')) {
0845:                    return -1;
0846:                }
0847:
0848:                return i;
0849:            }
0850:
0851:            /**
0852:             * Determines whether a string starting from an index satisfies the
0853:             * following syntax: local-part"@"domain
0854:             *
0855:             * @param s The string to check.
0856:             * @param i The index of the string at which to start the check. 
0857:             * <code> 0 <= i <= s.length() </code> 
0858:             * @param n The index of the last character to be checked in 
0859:             *          <code>s</code>.
0860:             *
0861:             * @return index till which 
0862:             * <code>s</code> contains valid mailbox specification;
0863:             * <code> -1 </code> if index <code>i</code> is invalid or
0864:             * if characters in <code>s</code> starting from <code>i</code>
0865:             * is not in the form of local-part"@"domain
0866:             */
0867:            private static int isLocalAtDomain(String s, int i, int n) {
0868:                if (n > s.length()) {
0869:                    n = s.length();
0870:                }
0871:                if (i >= n) {
0872:                    return -1;
0873:                }
0874:
0875:                // local
0876:                if ((i = isLocalPart(s, i, n)) <= 0) {
0877:                    return -1;
0878:                }
0879:
0880:                if (i == n || s.charAt(i) != '@') {
0881:                    return -1;
0882:                }
0883:
0884:                i++;
0885:
0886:                // domain
0887:                return isDomain(s, i, n);
0888:            }
0889:
0890:            /**
0891:             * Determines whether a string represents a valid mms address
0892:             * as specified in WMA 2.0 specification and parses the
0893:             * incoming string into address and application id strings.
0894:             *
0895:             * @param addressStr The string to check.
0896:             *
0897:             * @return newly created <code>MMSAddress </code> object 
0898:             * if <code>addressStr</code> is a valid mms address; 
0899:             * <code> null </code> otherwise
0900:             */
0901:            public static MMSAddress getParsedMMSAddress(String addressStr) {
0902:                return getParsedMMSAddress(addressStr, null);
0903:            }
0904:
0905:            /**
0906:             * Determines whether a string represents a valid mms address
0907:             * as specified in WMA 2.0 specification and parses the
0908:             * incoming string into address and application id strings.
0909:             * 
0910:             * @param addressStr The string to check.
0911:             * @param mmsAddress The return <code>MMSAddress</code> object which
0912:             * fields will be filled with parsed address and
0913:             * application id, and correspoinding type (EMAIL, GLOBAL_PHONE_NUMBER,
0914:             * IPV4, IPV6, SHORTCODE, APP_ID).
0915:             *
0916:             * @return <code>MMSAddress </code> object if <code>addressStr</code> 
0917:             * is a valid mms address; <code> null </code> otherwise
0918:             */
0919:            public static MMSAddress getParsedMMSAddress(String addressStr,
0920:                    MMSAddress mmsAddress) {
0921:
0922:                if (addressStr == null || !addressStr.startsWith("mms://")) {
0923:                    return null;
0924:                }
0925:
0926:                if (mmsAddress == null) {
0927:                    mmsAddress = new MMSAddress();
0928:                }
0929:
0930:                if (parsePhoneNumber(addressStr, 6, mmsAddress)
0931:                        || parseIpv4(addressStr, 6, mmsAddress)
0932:                        || parseIpv6(addressStr, 6, mmsAddress)
0933:                        || parseEmail(addressStr, 6, mmsAddress)
0934:                        || parseShortCode(addressStr, 6, mmsAddress)
0935:                        || parseApplicationId(addressStr, 6, mmsAddress)) {
0936:                    return mmsAddress;
0937:                }
0938:
0939:                return null;
0940:            }
0941:
0942:            /** Type corresponding to invalid address. */
0943:            public static final int INVALID_ADDRESS = -1;
0944:
0945:            /** Type corresponding to the e-mail address. */
0946:            public static final int EMAIL = 0;
0947:
0948:            /** Type corresponding to global phone number address. */
0949:            public static final int GLOBAL_PHONE_NUMBER = 1;
0950:
0951:            /** Type corresponding to the ipv4 address. */
0952:            public static final int IPV4 = 2;
0953:
0954:            /** Type corresponding to the ipv6 address. */
0955:            public static final int IPV6 = 3;
0956:
0957:            /** Type corresponding to the shortcode address. */
0958:            public static final int SHORTCODE = 4;
0959:
0960:            /** Type corresponding to the application id address. */
0961:            public static final int APP_ID = 5;
0962:
0963:            /** 
0964:             * Field that holds address part of the mms address 
0965:             * (without "mms://" and ":" separator before app id).
0966:             */
0967:            public String address;
0968:
0969:            /** 
0970:             * Field that holds application id part of the mms address
0971:             * which appears after "mms://:" or 
0972:             * after phone number, ipv4, or ipv6 followed by ":" .
0973:             */
0974:            public String appId;
0975:
0976:            /** 
0977:             * Type of this MMSAddress instance, 
0978:             * <code>INVALID_ADDRESS</code> when uninitialized .
0979:             */
0980:            public int type;
0981:
0982:            /**
0983:             *  MMSAddress constructor to create uninitialized instance.
0984:             */
0985:            MMSAddress() {
0986:                clear();
0987:            }
0988:
0989:            /**
0990:             * MMSAddress constructor to create initialized instance.
0991:             * @param address The address part of the mms address
0992:             * @param appId The application id part of the mms address
0993:             * @param type The type of this mms addreess
0994:             * (EMAIL, GLOBAL_PHONE_NUMBER, IPV4, IPV6, SHORTCODE, APP_ID) 
0995:             */
0996:            MMSAddress(String address, String appId, int type) {
0997:                set(address, appId, type);
0998:            }
0999:
1000:            /**
1001:             * Clears <code>MMSAddress</code> fields.
1002:             * Type is set to INVALID_ADDRESS while
1003:             * address and appId are set to null.
1004:             */
1005:            void clear() {
1006:                address = appId = null;
1007:                type = INVALID_ADDRESS;
1008:            }
1009:
1010:            /**
1011:             * Sets <code>MMSAddress</code> fields to the passed in values.
1012:             * @param address The address part of the mms address
1013:             * @param appId The application id part of the mms address
1014:             * @param type The type of this mms addreess
1015:             * (EMAIL, GLOBAL_PHONE_NUMBER, IPV4, IPV6, SHORTCODE, APP_ID) 
1016:             */
1017:            void set(String address, String appId, int type) {
1018:                this .address = address;
1019:                this .appId = appId;
1020:                this .type = type;
1021:            }
1022:
1023:            /**
1024:             * Sets <code>MMSAddress</code> application id field to 
1025:             * the passed in value.
1026:             * @param appId The application id part of the mms address
1027:             */
1028:            void setAppid(String appId) {
1029:                this .appId = appId;
1030:            }
1031:
1032:            /**
1033:             * Creates a valid mms address corresponding to the values
1034:             * in this <code>MMSAddress</code> object.
1035:             * If the object is not intialized null is returned.
1036:             * @return mms address corresponding to this MMSAddress object.
1037:             */
1038:            String getMMSAddressString() {
1039:
1040:                if (type == INVALID_ADDRESS
1041:                        || (address == null && appId == null)) {
1042:                    return null;
1043:                }
1044:
1045:                StringBuffer mmsAddr = new StringBuffer("mms://");
1046:                if (address != null)
1047:                    mmsAddr.append(address);
1048:                if (appId != null)
1049:                    mmsAddr.append(":").append(appId);
1050:                return mmsAddr.toString();
1051:            }
1052:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.