Android Open Source - wototoplayer Distinguished Name Parser






From Project

Back to project page wototoplayer.

License

The source code is released under:

Copyright (c) 2015, Chris Greenhalgh All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met...

If you think the Android project wototoplayer listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

/*
 *  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
 */*  w  w w .j a v  a  2 s  .  c om*/
 *     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.squareup.okhttp.internal.tls;

import javax.security.auth.x500.X500Principal;

/**
 * A distinguished name (DN) parser. This parser only supports extracting a
 * string value from a DN. It doesn't support values in the hex-string style.
 */
final class DistinguishedNameParser {
  private final String dn;
  private final int length;
  private int pos;
  private int beg;
  private int end;

  /** Temporary variable to store positions of the currently parsed item. */
  private int cur;

  /** Distinguished name characters. */
  private char[] chars;

  public DistinguishedNameParser(X500Principal principal) {
    // RFC2253 is used to ensure we get attributes in the reverse
    // order of the underlying ASN.1 encoding, so that the most
    // significant values of repeated attributes occur first.
    this.dn = principal.getName(X500Principal.RFC2253);
    this.length = this.dn.length();
  }

  // gets next attribute type: (ALPHA 1*keychar) / oid
  private String nextAT() {
    // skip preceding space chars, they can present after
    // comma or semicolon (compatibility with RFC 1779)
    for (; pos < length && chars[pos] == ' '; pos++) {
    }
    if (pos == length) {
      return null; // reached the end of DN
    }

    // mark the beginning of attribute type
    beg = pos;

    // attribute type chars
    pos++;
    for (; pos < length && chars[pos] != '=' && chars[pos] != ' '; pos++) {
      // we don't follow exact BNF syntax here:
      // accept any char except space and '='
    }
    if (pos >= length) {
      throw new IllegalStateException("Unexpected end of DN: " + dn);
    }

    // mark the end of attribute type
    end = pos;

    // skip trailing space chars between attribute type and '='
    // (compatibility with RFC 1779)
    if (chars[pos] == ' ') {
      for (; pos < length && chars[pos] != '=' && chars[pos] == ' '; pos++) {
      }

      if (chars[pos] != '=' || pos == length) {
        throw new IllegalStateException("Unexpected end of DN: " + dn);
      }
    }

    pos++; //skip '=' char

    // skip space chars between '=' and attribute value
    // (compatibility with RFC 1779)
    for (; pos < length && chars[pos] == ' '; pos++) {
    }

    // in case of oid attribute type skip its prefix: "oid." or "OID."
    // (compatibility with RFC 1779)
    if ((end - beg > 4) && (chars[beg + 3] == '.')
        && (chars[beg] == 'O' || chars[beg] == 'o')
        && (chars[beg + 1] == 'I' || chars[beg + 1] == 'i')
        && (chars[beg + 2] == 'D' || chars[beg + 2] == 'd')) {
      beg += 4;
    }

    return new String(chars, beg, end - beg);
  }

  // gets quoted attribute value: QUOTATION *( quotechar / pair ) QUOTATION
  private String quotedAV() {
    pos++;
    beg = pos;
    end = beg;
    while (true) {

      if (pos == length) {
        throw new IllegalStateException("Unexpected end of DN: " + dn);
      }

      if (chars[pos] == '"') {
        // enclosing quotation was found
        pos++;
        break;
      } else if (chars[pos] == '\\') {
        chars[end] = getEscaped();
      } else {
        // shift char: required for string with escaped chars
        chars[end] = chars[pos];
      }
      pos++;
      end++;
    }

    // skip trailing space chars before comma or semicolon.
    // (compatibility with RFC 1779)
    for (; pos < length && chars[pos] == ' '; pos++) {
    }

    return new String(chars, beg, end - beg);
  }

  // gets hex string attribute value: "#" hexstring
  private String hexAV() {
    if (pos + 4 >= length) {
      // encoded byte array  must be not less then 4 c
      throw new IllegalStateException("Unexpected end of DN: " + dn);
    }

    beg = pos; // store '#' position
    pos++;
    while (true) {

      // check for end of attribute value
      // looks for space and component separators
      if (pos == length || chars[pos] == '+' || chars[pos] == ','
          || chars[pos] == ';') {
        end = pos;
        break;
      }

      if (chars[pos] == ' ') {
        end = pos;
        pos++;
        // skip trailing space chars before comma or semicolon.
        // (compatibility with RFC 1779)
        for (; pos < length && chars[pos] == ' '; pos++) {
        }
        break;
      } else if (chars[pos] >= 'A' && chars[pos] <= 'F') {
        chars[pos] += 32; //to low case
      }

      pos++;
    }

    // verify length of hex string
    // encoded byte array  must be not less then 4 and must be even number
    int hexLen = end - beg; // skip first '#' char
    if (hexLen < 5 || (hexLen & 1) == 0) {
      throw new IllegalStateException("Unexpected end of DN: " + dn);
    }

    // get byte encoding from string representation
    byte[] encoded = new byte[hexLen / 2];
    for (int i = 0, p = beg + 1; i < encoded.length; p += 2, i++) {
      encoded[i] = (byte) getByte(p);
    }

    return new String(chars, beg, hexLen);
  }

  // gets string attribute value: *( stringchar / pair )
  private String escapedAV() {
    beg = pos;
    end = pos;
    while (true) {
      if (pos >= length) {
        // the end of DN has been found
        return new String(chars, beg, end - beg);
      }

      switch (chars[pos]) {
        case '+':
        case ',':
        case ';':
          // separator char has been found
          return new String(chars, beg, end - beg);
        case '\\':
          // escaped char
          chars[end++] = getEscaped();
          pos++;
          break;
        case ' ':
          // need to figure out whether space defines
          // the end of attribute value or not
          cur = end;

          pos++;
          chars[end++] = ' ';

          for (; pos < length && chars[pos] == ' '; pos++) {
            chars[end++] = ' ';
          }
          if (pos == length || chars[pos] == ',' || chars[pos] == '+'
              || chars[pos] == ';') {
            // separator char or the end of DN has been found
            return new String(chars, beg, cur - beg);
          }
          break;
        default:
          chars[end++] = chars[pos];
          pos++;
      }
    }
  }

  // returns escaped char
  private char getEscaped() {
    pos++;
    if (pos == length) {
      throw new IllegalStateException("Unexpected end of DN: " + dn);
    }

    switch (chars[pos]) {
      case '"':
      case '\\':
      case ',':
      case '=':
      case '+':
      case '<':
      case '>':
      case '#':
      case ';':
      case ' ':
      case '*':
      case '%':
      case '_':
        //FIXME: escaping is allowed only for leading or trailing space char
        return chars[pos];
      default:
        // RFC doesn't explicitly say that escaped hex pair is
        // interpreted as UTF-8 char. It only contains an example of such DN.
        return getUTF8();
    }
  }

  // decodes UTF-8 char
  // see http://www.unicode.org for UTF-8 bit distribution table
  private char getUTF8() {
    int res = getByte(pos);
    pos++; //FIXME tmp

    if (res < 128) { // one byte: 0-7F
      return (char) res;
    } else if (res >= 192 && res <= 247) {

      int count;
      if (res <= 223) { // two bytes: C0-DF
        count = 1;
        res = res & 0x1F;
      } else if (res <= 239) { // three bytes: E0-EF
        count = 2;
        res = res & 0x0F;
      } else { // four bytes: F0-F7
        count = 3;
        res = res & 0x07;
      }

      int b;
      for (int i = 0; i < count; i++) {
        pos++;
        if (pos == length || chars[pos] != '\\') {
          return 0x3F; //FIXME failed to decode UTF-8 char - return '?'
        }
        pos++;

        b = getByte(pos);
        pos++; //FIXME tmp
        if ((b & 0xC0) != 0x80) {
          return 0x3F; //FIXME failed to decode UTF-8 char - return '?'
        }

        res = (res << 6) + (b & 0x3F);
      }
      return (char) res;
    } else {
      return 0x3F; //FIXME failed to decode UTF-8 char - return '?'
    }
  }

  // Returns byte representation of a char pair
  // The char pair is composed of DN char in
  // specified 'position' and the next char
  // According to BNF syntax:
  // hexchar    = DIGIT / "A" / "B" / "C" / "D" / "E" / "F"
  //                    / "a" / "b" / "c" / "d" / "e" / "f"
  private int getByte(int position) {
    if (position + 1 >= length) {
      throw new IllegalStateException("Malformed DN: " + dn);
    }

    int b1, b2;

    b1 = chars[position];
    if (b1 >= '0' && b1 <= '9') {
      b1 = b1 - '0';
    } else if (b1 >= 'a' && b1 <= 'f') {
      b1 = b1 - 87; // 87 = 'a' - 10
    } else if (b1 >= 'A' && b1 <= 'F') {
      b1 = b1 - 55; // 55 = 'A' - 10
    } else {
      throw new IllegalStateException("Malformed DN: " + dn);
    }

    b2 = chars[position + 1];
    if (b2 >= '0' && b2 <= '9') {
      b2 = b2 - '0';
    } else if (b2 >= 'a' && b2 <= 'f') {
      b2 = b2 - 87; // 87 = 'a' - 10
    } else if (b2 >= 'A' && b2 <= 'F') {
      b2 = b2 - 55; // 55 = 'A' - 10
    } else {
      throw new IllegalStateException("Malformed DN: " + dn);
    }

    return (b1 << 4) + b2;
  }

  /**
   * Parses the DN and returns the most significant attribute value
   * for an attribute type, or null if none found.
   *
   * @param attributeType attribute type to look for (e.g. "ca")
   */
  public String findMostSpecific(String attributeType) {
    // Initialize internal state.
    pos = 0;
    beg = 0;
    end = 0;
    cur = 0;
    chars = dn.toCharArray();

    String attType = nextAT();
    if (attType == null) {
      return null;
    }
    while (true) {
      String attValue = "";

      if (pos == length) {
        return null;
      }

      switch (chars[pos]) {
        case '"':
          attValue = quotedAV();
          break;
        case '#':
          attValue = hexAV();
          break;
        case '+':
        case ',':
        case ';': // compatibility with RFC 1779: semicolon can separate RDNs
          //empty attribute value
          break;
        default:
          attValue = escapedAV();
      }

      // Values are ordered from most specific to least specific
      // due to the RFC2253 formatting. So take the first match
      // we see.
      if (attributeType.equalsIgnoreCase(attType)) {
        return attValue;
      }

      if (pos >= length) {
        return null;
      }

      if (chars[pos] == ',' || chars[pos] == ';') {
      } else if (chars[pos] != '+') {
        throw new IllegalStateException("Malformed DN: " + dn);
      }

      pos++;
      attType = nextAT();
      if (attType == null) {
        throw new IllegalStateException("Malformed DN: " + dn);
      }
    }
  }
}




Java Source Code List

com.phonegap.plugins.barcodescanner.BarcodeScanner.java
com.squareup.okhttp.Address.java
com.squareup.okhttp.ConnectionPool.java
com.squareup.okhttp.Connection.java
com.squareup.okhttp.Dispatcher.java
com.squareup.okhttp.Failure.java
com.squareup.okhttp.HttpResponseCache.java
com.squareup.okhttp.Job.java
com.squareup.okhttp.MediaType.java
com.squareup.okhttp.OkAuthenticator.java
com.squareup.okhttp.OkHttpClient.java
com.squareup.okhttp.OkResponseCache.java
com.squareup.okhttp.Request.java
com.squareup.okhttp.ResponseSource.java
com.squareup.okhttp.Response.java
com.squareup.okhttp.RouteDatabase.java
com.squareup.okhttp.Route.java
com.squareup.okhttp.TunnelRequest.java
com.squareup.okhttp.internal.AbstractOutputStream.java
com.squareup.okhttp.internal.Base64.java
com.squareup.okhttp.internal.DiskLruCache.java
com.squareup.okhttp.internal.Dns.java
com.squareup.okhttp.internal.FaultRecoveringOutputStream.java
com.squareup.okhttp.internal.NamedRunnable.java
com.squareup.okhttp.internal.Platform.java
com.squareup.okhttp.internal.StrictLineReader.java
com.squareup.okhttp.internal.Util.java
com.squareup.okhttp.internal.http.AbstractHttpInputStream.java
com.squareup.okhttp.internal.http.HeaderParser.java
com.squareup.okhttp.internal.http.HttpAuthenticator.java
com.squareup.okhttp.internal.http.HttpDate.java
com.squareup.okhttp.internal.http.HttpEngine.java
com.squareup.okhttp.internal.http.HttpTransport.java
com.squareup.okhttp.internal.http.HttpURLConnectionImpl.java
com.squareup.okhttp.internal.http.HttpsEngine.java
com.squareup.okhttp.internal.http.HttpsURLConnectionImpl.java
com.squareup.okhttp.internal.http.OkResponseCacheAdapter.java
com.squareup.okhttp.internal.http.Policy.java
com.squareup.okhttp.internal.http.RawHeaders.java
com.squareup.okhttp.internal.http.RequestHeaders.java
com.squareup.okhttp.internal.http.ResponseHeaders.java
com.squareup.okhttp.internal.http.RetryableOutputStream.java
com.squareup.okhttp.internal.http.RouteSelector.java
com.squareup.okhttp.internal.http.SpdyTransport.java
com.squareup.okhttp.internal.http.Transport.java
com.squareup.okhttp.internal.http.UnknownLengthHttpInputStream.java
com.squareup.okhttp.internal.spdy.ErrorCode.java
com.squareup.okhttp.internal.spdy.FrameReader.java
com.squareup.okhttp.internal.spdy.FrameWriter.java
com.squareup.okhttp.internal.spdy.HeadersMode.java
com.squareup.okhttp.internal.spdy.Hpack.java
com.squareup.okhttp.internal.spdy.Http20Draft06.java
com.squareup.okhttp.internal.spdy.IncomingStreamHandler.java
com.squareup.okhttp.internal.spdy.NameValueBlockReader.java
com.squareup.okhttp.internal.spdy.Ping.java
com.squareup.okhttp.internal.spdy.Settings.java
com.squareup.okhttp.internal.spdy.Spdy3.java
com.squareup.okhttp.internal.spdy.SpdyConnection.java
com.squareup.okhttp.internal.spdy.SpdyStream.java
com.squareup.okhttp.internal.spdy.Variant.java
com.squareup.okhttp.internal.tls.DistinguishedNameParser.java
com.squareup.okhttp.internal.tls.OkHostnameVerifier.java
org.apache.cordova.App.java
org.apache.cordova.AuthenticationToken.java
org.apache.cordova.CallbackContext.java
org.apache.cordova.ConfigXmlParser.java
org.apache.cordova.Config.java
org.apache.cordova.CordovaActivity.java
org.apache.cordova.CordovaArgs.java
org.apache.cordova.CordovaBridge.java
org.apache.cordova.CordovaChromeClient.java
org.apache.cordova.CordovaInterface.java
org.apache.cordova.CordovaPlugin.java
org.apache.cordova.CordovaPreferences.java
org.apache.cordova.CordovaResourceApi.java
org.apache.cordova.CordovaUriHelper.java
org.apache.cordova.CordovaWebViewClient.java
org.apache.cordova.CordovaWebView.java
org.apache.cordova.DirectoryManager.java
org.apache.cordova.DroidGap.java
org.apache.cordova.ExifHelper.java
org.apache.cordova.ExposedJsApi.java
org.apache.cordova.FileHelper.java
org.apache.cordova.IceCreamCordovaWebViewClient.java
org.apache.cordova.JSONUtils.java
org.apache.cordova.LOG.java
org.apache.cordova.LinearLayoutSoftKeyboardDetect.java
org.apache.cordova.NativeToJsMessageQueue.java
org.apache.cordova.PluginEntry.java
org.apache.cordova.PluginManager.java
org.apache.cordova.PluginResult.java
org.apache.cordova.ScrollEvent.java
org.apache.cordova.Whitelist.java
org.opensharingtoolkit.cordova.aestheticodes.Scan.java
org.opensharingtoolkit.cordova.aestheticodes.Scan.java
org.opensharingtoolkit.player.CordovaApp.java