| /* |
| * reserved comment block |
| * DO NOT REMOVE OR ALTER! |
| */ |
| /** |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you 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 com.sun.org.apache.xml.internal.security.utils; |
| |
| import java.io.IOException; |
| import java.io.StringReader; |
| |
| public class RFC2253Parser { |
| |
| /** |
| * Method rfc2253toXMLdsig |
| * |
| * @param dn |
| * @return normalized string |
| */ |
| public static String rfc2253toXMLdsig(String dn) { |
| // Transform from RFC1779 to RFC2253 |
| String normalized = normalize(dn, true); |
| |
| return rfctoXML(normalized); |
| } |
| |
| /** |
| * Method xmldsigtoRFC2253 |
| * |
| * @param dn |
| * @return normalized string |
| */ |
| public static String xmldsigtoRFC2253(String dn) { |
| // Transform from RFC1779 to RFC2253 |
| String normalized = normalize(dn, false); |
| |
| return xmltoRFC(normalized); |
| } |
| |
| /** |
| * Method normalize |
| * |
| * @param dn |
| * @return normalized string |
| */ |
| public static String normalize(String dn) { |
| return normalize(dn, true); |
| } |
| |
| /** |
| * Method normalize |
| * |
| * @param dn |
| * @param toXml |
| * @return normalized string |
| */ |
| public static String normalize(String dn, boolean toXml) { |
| //if empty string |
| if ((dn == null) || dn.equals("")) { |
| return ""; |
| } |
| |
| try { |
| String DN = semicolonToComma(dn); |
| StringBuilder sb = new StringBuilder(); |
| int i = 0; |
| int l = 0; |
| int k; |
| |
| //for name component |
| for (int j = 0; (k = DN.indexOf(',', j)) >= 0; j = k + 1) { |
| l += countQuotes(DN, j, k); |
| |
| if ((k > 0) && (DN.charAt(k - 1) != '\\') && (l % 2) == 0) { |
| sb.append(parseRDN(DN.substring(i, k).trim(), toXml)).append(','); |
| |
| i = k + 1; |
| l = 0; |
| } |
| } |
| |
| sb.append(parseRDN(trim(DN.substring(i)), toXml)); |
| |
| return sb.toString(); |
| } catch (IOException ex) { |
| return dn; |
| } |
| } |
| |
| /** |
| * Method parseRDN |
| * |
| * @param str |
| * @param toXml |
| * @return normalized string |
| * @throws IOException |
| */ |
| static String parseRDN(String str, boolean toXml) throws IOException { |
| StringBuilder sb = new StringBuilder(); |
| int i = 0; |
| int l = 0; |
| int k; |
| |
| for (int j = 0; (k = str.indexOf('+', j)) >= 0; j = k + 1) { |
| l += countQuotes(str, j, k); |
| |
| if ((k > 0) && (str.charAt(k - 1) != '\\') && (l % 2) == 0) { |
| sb.append(parseATAV(trim(str.substring(i, k)), toXml)).append('+'); |
| |
| i = k + 1; |
| l = 0; |
| } |
| } |
| |
| sb.append(parseATAV(trim(str.substring(i)), toXml)); |
| |
| return sb.toString(); |
| } |
| |
| /** |
| * Method parseATAV |
| * |
| * @param str |
| * @param toXml |
| * @return normalized string |
| * @throws IOException |
| */ |
| static String parseATAV(String str, boolean toXml) throws IOException { |
| int i = str.indexOf('='); |
| |
| if ((i == -1) || ((i > 0) && (str.charAt(i - 1) == '\\'))) { |
| return str; |
| } |
| String attrType = normalizeAT(str.substring(0, i)); |
| // only normalize if value is a String |
| String attrValue = null; |
| if (attrType.charAt(0) >= '0' && attrType.charAt(0) <= '9') { |
| attrValue = str.substring(i + 1); |
| } else { |
| attrValue = normalizeV(str.substring(i + 1), toXml); |
| } |
| |
| return attrType + "=" + attrValue; |
| |
| } |
| |
| /** |
| * Method normalizeAT |
| * |
| * @param str |
| * @return normalized string |
| */ |
| static String normalizeAT(String str) { |
| |
| String at = str.toUpperCase().trim(); |
| |
| if (at.startsWith("OID")) { |
| at = at.substring(3); |
| } |
| |
| return at; |
| } |
| |
| /** |
| * Method normalizeV |
| * |
| * @param str |
| * @param toXml |
| * @return normalized string |
| * @throws IOException |
| */ |
| static String normalizeV(String str, boolean toXml) throws IOException { |
| String value = trim(str); |
| |
| if (value.startsWith("\"")) { |
| StringBuilder sb = new StringBuilder(); |
| StringReader sr = new StringReader(value.substring(1, value.length() - 1)); |
| int i = 0; |
| char c; |
| |
| while ((i = sr.read()) > -1) { |
| c = (char) i; |
| |
| //the following char is defined at 4.Relationship with RFC1779 and LDAPv2 inrfc2253 |
| if ((c == ',') || (c == '=') || (c == '+') || (c == '<') |
| || (c == '>') || (c == '#') || (c == ';')) { |
| sb.append('\\'); |
| } |
| |
| sb.append(c); |
| } |
| |
| value = trim(sb.toString()); |
| } |
| |
| if (toXml) { |
| if (value.startsWith("#")) { |
| value = '\\' + value; |
| } |
| } else { |
| if (value.startsWith("\\#")) { |
| value = value.substring(1); |
| } |
| } |
| |
| return value; |
| } |
| |
| /** |
| * Method rfctoXML |
| * |
| * @param string |
| * @return normalized string |
| */ |
| static String rfctoXML(String string) { |
| try { |
| String s = changeLess32toXML(string); |
| |
| return changeWStoXML(s); |
| } catch (Exception e) { |
| return string; |
| } |
| } |
| |
| /** |
| * Method xmltoRFC |
| * |
| * @param string |
| * @return normalized string |
| */ |
| static String xmltoRFC(String string) { |
| try { |
| String s = changeLess32toRFC(string); |
| |
| return changeWStoRFC(s); |
| } catch (Exception e) { |
| return string; |
| } |
| } |
| |
| /** |
| * Method changeLess32toRFC |
| * |
| * @param string |
| * @return normalized string |
| * @throws IOException |
| */ |
| static String changeLess32toRFC(String string) throws IOException { |
| StringBuilder sb = new StringBuilder(); |
| StringReader sr = new StringReader(string); |
| int i = 0; |
| char c; |
| |
| while ((i = sr.read()) > -1) { |
| c = (char) i; |
| |
| if (c == '\\') { |
| sb.append(c); |
| |
| char c1 = (char) sr.read(); |
| char c2 = (char) sr.read(); |
| |
| //65 (A) 97 (a) |
| if ((((c1 >= 48) && (c1 <= 57)) || ((c1 >= 65) && (c1 <= 70)) || ((c1 >= 97) && (c1 <= 102))) |
| && (((c2 >= 48) && (c2 <= 57)) |
| || ((c2 >= 65) && (c2 <= 70)) |
| || ((c2 >= 97) && (c2 <= 102)))) { |
| char ch = (char) Byte.parseByte("" + c1 + c2, 16); |
| |
| sb.append(ch); |
| } else { |
| sb.append(c1); |
| sb.append(c2); |
| } |
| } else { |
| sb.append(c); |
| } |
| } |
| |
| return sb.toString(); |
| } |
| |
| /** |
| * Method changeLess32toXML |
| * |
| * @param string |
| * @return normalized string |
| * @throws IOException |
| */ |
| static String changeLess32toXML(String string) throws IOException { |
| StringBuilder sb = new StringBuilder(); |
| StringReader sr = new StringReader(string); |
| int i = 0; |
| |
| while ((i = sr.read()) > -1) { |
| if (i < 32) { |
| sb.append('\\'); |
| sb.append(Integer.toHexString(i)); |
| } else { |
| sb.append((char) i); |
| } |
| } |
| |
| return sb.toString(); |
| } |
| |
| /** |
| * Method changeWStoXML |
| * |
| * @param string |
| * @return normalized string |
| * @throws IOException |
| */ |
| static String changeWStoXML(String string) throws IOException { |
| StringBuilder sb = new StringBuilder(); |
| StringReader sr = new StringReader(string); |
| int i = 0; |
| char c; |
| |
| while ((i = sr.read()) > -1) { |
| c = (char) i; |
| |
| if (c == '\\') { |
| char c1 = (char) sr.read(); |
| |
| if (c1 == ' ') { |
| sb.append('\\'); |
| |
| String s = "20"; |
| |
| sb.append(s); |
| } else { |
| sb.append('\\'); |
| sb.append(c1); |
| } |
| } else { |
| sb.append(c); |
| } |
| } |
| |
| return sb.toString(); |
| } |
| |
| /** |
| * Method changeWStoRFC |
| * |
| * @param string |
| * @return normalized string |
| */ |
| static String changeWStoRFC(String string) { |
| StringBuilder sb = new StringBuilder(); |
| int i = 0; |
| int k; |
| |
| for (int j = 0; (k = string.indexOf("\\20", j)) >= 0; j = k + 3) { |
| sb.append(trim(string.substring(i, k))).append("\\ "); |
| |
| i = k + 3; |
| } |
| |
| sb.append(string.substring(i)); |
| |
| return sb.toString(); |
| } |
| |
| /** |
| * Method semicolonToComma |
| * |
| * @param str |
| * @return normalized string |
| */ |
| static String semicolonToComma(String str) { |
| return removeWSandReplace(str, ";", ","); |
| } |
| |
| /** |
| * Method removeWhiteSpace |
| * |
| * @param str |
| * @param symbol |
| * @return normalized string |
| */ |
| static String removeWhiteSpace(String str, String symbol) { |
| return removeWSandReplace(str, symbol, symbol); |
| } |
| |
| /** |
| * Method removeWSandReplace |
| * |
| * @param str |
| * @param symbol |
| * @param replace |
| * @return normalized string |
| */ |
| static String removeWSandReplace(String str, String symbol, String replace) { |
| StringBuilder sb = new StringBuilder(); |
| int i = 0; |
| int l = 0; |
| int k; |
| |
| for (int j = 0; (k = str.indexOf(symbol, j)) >= 0; j = k + 1) { |
| l += countQuotes(str, j, k); |
| |
| if ((k > 0) && (str.charAt(k - 1) != '\\') && (l % 2) == 0) { |
| sb.append(trim(str.substring(i, k))).append(replace); |
| |
| i = k + 1; |
| l = 0; |
| } |
| } |
| |
| sb.append(trim(str.substring(i))); |
| |
| return sb.toString(); |
| } |
| |
| /** |
| * Returns the number of Quotation from i to j |
| * |
| * @param s |
| * @param i |
| * @param j |
| * @return number of quotes |
| */ |
| private static int countQuotes(String s, int i, int j) { |
| int k = 0; |
| |
| for (int l = i; l < j; l++) { |
| if (s.charAt(l) == '"') { |
| k++; |
| } |
| } |
| |
| return k; |
| } |
| |
| //only for the end of a space character occurring at the end of the string from rfc2253 |
| |
| /** |
| * Method trim |
| * |
| * @param str |
| * @return the string |
| */ |
| static String trim(String str) { |
| |
| String trimed = str.trim(); |
| int i = str.indexOf(trimed) + trimed.length(); |
| |
| if ((str.length() > i) && trimed.endsWith("\\") |
| && !trimed.endsWith("\\\\") && (str.charAt(i) == ' ')) { |
| trimed = trimed + " "; |
| } |
| |
| return trimed; |
| } |
| |
| } |