NFS4StringPrep.java revision 17113:d17577d4839b
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*/
30import java.io.IOException;
31import java.io.InputStream;
32import java.io.UnsupportedEncodingException;
33import java.text.ParseException;
34
35import sun.net.idn.StringPrep;
36import 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 */
45public 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}
171