1 /*
   2  * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24 /*
  25  *******************************************************************************
  26  * Copyright (C) 2003-2004, International Business Machines Corporation and    *
  27  * others. All Rights Reserved.                                                *
  28  *******************************************************************************
  29 */
  30 import java.io.IOException;
  31 import java.io.InputStream;
  32 import java.io.UnsupportedEncodingException;
  33 import java.text.ParseException;
  34 
  35 import sun.net.idn.StringPrep;
  36 import sun.text.normalizer.UCharacterIterator;
  37 
  38 /**
  39  * @author ram
  40  *
  41  * This is a dumb implementation of NFS4 profiles. It is a direct port of
  42  * C code, does not use Object Oriented principles. Quick and Dirty implementation
  43  * for testing.
  44  */
  45 public final class NFS4StringPrep {
  46 
  47     private StringPrep nfscss = null;
  48     private StringPrep nfscsi = null;
  49     private StringPrep nfscis = null;
  50     private StringPrep nfsmxp = null;
  51     private StringPrep nfsmxs = null;
  52     //singleton instance
  53     private static final NFS4StringPrep prep = new NFS4StringPrep();
  54 
  55 
  56     private  NFS4StringPrep (){
  57         ClassLoader loader = NFS4StringPrep.class.getClassLoader();
  58       try{
  59           InputStream  nfscsiFile = loader.getResourceAsStream("nfscsi.spp");
  60           nfscsi = new StringPrep(nfscsiFile);
  61           nfscsiFile.close();
  62 
  63           InputStream  nfscssFile = loader.getResourceAsStream("nfscss.spp");
  64           nfscss = new StringPrep(nfscssFile);
  65           nfscssFile.close();
  66 
  67           InputStream  nfscisFile = loader.getResourceAsStream("nfscis.spp");
  68           nfscis = new StringPrep(nfscisFile);
  69           nfscisFile.close();
  70 
  71           InputStream  nfsmxpFile = loader.getResourceAsStream("nfsmxp.spp");
  72           nfsmxp = new StringPrep(nfsmxpFile);
  73           nfsmxpFile.close();
  74 
  75           InputStream  nfsmxsFile = loader.getResourceAsStream("nfsmxs.spp");
  76           nfsmxs = new StringPrep(nfsmxsFile);
  77           nfsmxsFile.close();
  78       }catch(IOException e){
  79           throw new RuntimeException(e.toString());
  80       }
  81     }
  82 
  83     private static byte[] prepare(byte[] src, StringPrep prep)
  84                 throws ParseException, UnsupportedEncodingException{
  85         String s = new String(src, "UTF-8");
  86         UCharacterIterator iter =  UCharacterIterator.getInstance(s);
  87         StringBuffer out = prep.prepare(iter,StringPrep.DEFAULT);
  88         return out.toString().getBytes("UTF-8");
  89     }
  90 
  91     public static byte[] cs_prepare(byte[] src, boolean isCaseSensitive)
  92                          throws ParseException, UnsupportedEncodingException{
  93         if(isCaseSensitive == true ){
  94             return prepare(src, prep.nfscss);
  95         }else{
  96             return prepare(src, prep.nfscsi);
  97         }
  98     }
  99 
 100     public static byte[] cis_prepare(byte[] src)
 101                          throws IOException, ParseException, UnsupportedEncodingException{
 102         return prepare(src, prep.nfscis);
 103     }
 104 
 105     /* sorted array for binary search*/
 106     private static final String[] special_prefixes={
 107         "ANONYMOUS",
 108         "AUTHENTICATED",
 109         "BATCH",
 110         "DIALUP",
 111         "EVERYONE",
 112         "GROUP",
 113         "INTERACTIVE",
 114         "NETWORK",
 115         "OWNER",
 116     };
 117 
 118 
 119     /* binary search the sorted array */
 120     private static final int findStringIndex(String[] sortedArr,String target){
 121 
 122         int left, middle, right,rc;
 123 
 124         left =0;
 125         right= sortedArr.length-1;
 126 
 127         while(left <= right){
 128             middle = (left+right)/2;
 129             rc= sortedArr[middle].compareTo(target);
 130 
 131             if(rc<0){
 132                 left = middle+1;
 133             }else if(rc >0){
 134                 right = middle -1;
 135             }else{
 136                 return middle;
 137             }
 138         }
 139         return -1;
 140     }
 141     private static final char AT_SIGN = '@';
 142 
 143     public static byte[] mixed_prepare(byte[] src)
 144                          throws IOException, ParseException, UnsupportedEncodingException{
 145         String s = new String(src, "UTF-8");
 146         int index = s.indexOf(AT_SIGN);
 147         StringBuffer out = new StringBuffer();
 148 
 149         if(index > -1){
 150             /* special prefixes must not be followed by suffixes! */
 151             String prefixString = s.substring(0,index);
 152             int i= findStringIndex(special_prefixes, prefixString);
 153             String suffixString = s.substring(index+1, s.length());
 154             if(i>-1 && !suffixString.equals("")){
 155                 throw new ParseException("Suffix following a special index", -1);
 156             }
 157             UCharacterIterator prefix = UCharacterIterator.getInstance(prefixString);
 158             UCharacterIterator suffix = UCharacterIterator.getInstance(suffixString);
 159             out.append(prep.nfsmxp.prepare(prefix,StringPrep.DEFAULT));
 160             out.append(AT_SIGN); // add the delimiter
 161             out.append(prep.nfsmxs.prepare(suffix, StringPrep.DEFAULT));
 162         }else{
 163             UCharacterIterator iter = UCharacterIterator.getInstance(s);
 164             out.append(prep.nfsmxp.prepare(iter,StringPrep.DEFAULT));
 165 
 166         }
 167        return out.toString().getBytes("UTF-8");
 168     }
 169 
 170 }