001/** 002 * 003 * Copyright © 2014-2015 Florian Schmaus 004 * 005 * Licensed under the Apache License, Version 2.0 (the "License"); 006 * you may not use this file except in compliance with the License. 007 * 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 */ 017package org.jxmpp.stringprep.simple; 018 019import java.util.Locale; 020 021import org.jxmpp.stringprep.XmppStringPrepUtil; 022import org.jxmpp.stringprep.XmppStringprep; 023import org.jxmpp.stringprep.XmppStringprepException; 024 025public final class SimpleXmppStringprep implements XmppStringprep { 026 027 private static SimpleXmppStringprep instance; 028 029 /** 030 * Setup Simple XMPP Stringprep as implementation to use. 031 */ 032 public static void setup() { 033 XmppStringPrepUtil.setXmppStringprep(getInstance()); 034 } 035 036 /** 037 * Get the Simple XMPP Stringprep singleton. 038 * 039 * @return the simple XMPP Stringprep singleton. 040 */ 041 public static SimpleXmppStringprep getInstance() { 042 if (instance == null) { 043 instance = new SimpleXmppStringprep(); 044 } 045 return instance; 046 } 047 048 private SimpleXmppStringprep() { 049 } 050 051 /** 052 * From 6122bis-18 § 3.3.1 and PRECIS IdentifierClass which forbids U+0020 053 */ 054 // @formatter:off 055 private static final char[] LOCALPART_FURTHER_EXCLUDED_CHARACTERS = new char[] { 056 '"', // U+0022 (QUOTATION MARK) , i.e., " 057 '&', // U+0026 (AMPERSAND), i.e., & 058 '\'', // U+0027 (APOSTROPHE), i.e., ' 059 '/', // U+002F (SOLIDUS), i.e., / 060 ',', // U+003A (COLON), i.e., : 061 '<', // U+003C (LESS-THAN SIGN), i.e., < 062 '>', // U+003E (GREATER-THAN SIGN), i.e., > 063 '@', // U+0040 (COMMERCIAL AT), i.e., @ 064 ' ', // U+0020 (SPACE) 065 }; 066 // @formatter:on 067 068 @Override 069 public String localprep(String string) throws XmppStringprepException { 070 string = simpleStringprep(string); 071 for (char charFromString : string.toCharArray()) { 072 for (char forbiddenChar : LOCALPART_FURTHER_EXCLUDED_CHARACTERS) { 073 if (charFromString == forbiddenChar) { 074 throw new XmppStringprepException(string, "Localpart must not contain '" + forbiddenChar + "'"); 075 } 076 } 077 } 078 return string; 079 } 080 081 @Override 082 public String domainprep(String string) throws XmppStringprepException { 083 return simpleStringprep(string); 084 } 085 086 @Override 087 public String resourceprep(String string) throws XmppStringprepException { 088 // rfc6122-bis specifies that resourceprep uses saslprep-bis OpaqueString Profile which says that 089 // "Uppercase and titlecase characters MUST NOT be mapped to their lowercase equivalents." 090 091 // TODO apply Unicode Normalization Form C (NFC) with help of java.text.Normalize 092 // but unfortunately this is API is only available on Android API 9 or higher and Smack is currently API 8 093 return string; 094 } 095 096 private static String simpleStringprep(String string) { 097 String res = string.toLowerCase(Locale.US); 098 return res; 099 } 100}