17935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert/*
27935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *******************************************************************************
37935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Copyright (C) 2003-2010, International Business Machines Corporation and    *
47935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * others. All Rights Reserved.                                                *
57935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *******************************************************************************
67935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert*/
77935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertpackage com.ibm.icu.dev.test.stringprep;
87935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
97935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.io.IOException;
107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.io.InputStream;
117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.io.UnsupportedEncodingException;
127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.util.MissingResourceException;
137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.text.StringPrep;
157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.text.StringPrepParseException;
167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.text.UCharacterIterator;
177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert/**
197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @author ram
207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *
217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * This is a dumb implementation of NFS4 profiles. It is a direct port of
227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * C code, does not use Object Oriented principles. Quick and Dirty implementation
237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * for testing.
247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */
257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertpublic final class NFS4StringPrep {
267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private StringPrep nfscss = null;
287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private StringPrep nfscsi = null;
297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private StringPrep nfscis = null;
307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private StringPrep nfsmxp = null;
317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private StringPrep nfsmxs = null;
327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    //singleton instance
337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private static final NFS4StringPrep prep = new NFS4StringPrep();
347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private  NFS4StringPrep (){
377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        ClassLoader loader = NFS4StringPrep.class.getClassLoader();
387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        try{
397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            InputStream  nfscsiFile = loader.getResourceAsStream("com/ibm/icu/dev/data/testdata/nfscsi.spp");
407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            nfscsi = new StringPrep(nfscsiFile);
417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            nfscsiFile.close();
427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            InputStream  nfscssFile = loader.getResourceAsStream("com/ibm/icu/dev/data/testdata/nfscss.spp");
447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            nfscss = new StringPrep(nfscssFile);
457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            nfscssFile.close();
467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            InputStream  nfscisFile = loader.getResourceAsStream("com/ibm/icu/dev/data/testdata/nfscis.spp");
487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            nfscis = new StringPrep(nfscisFile);
497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            nfscisFile.close();
507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            InputStream  nfsmxpFile = loader.getResourceAsStream("com/ibm/icu/dev/data/testdata/nfsmxp.spp");
527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            nfsmxp = new StringPrep(nfsmxpFile);
537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            nfsmxpFile.close();
547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            InputStream  nfsmxsFile = loader.getResourceAsStream("com/ibm/icu/dev/data/testdata/nfsmxs.spp");
567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            nfsmxs = new StringPrep(nfsmxsFile);
577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            nfsmxsFile.close();
587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }catch(IOException e){
597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            throw new MissingResourceException(e.toString(),"","");
607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private static byte[] prepare(byte[] src, StringPrep strprep)
647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                throws StringPrepParseException, UnsupportedEncodingException{
657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        String s = new String(src, "UTF-8");
667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        UCharacterIterator iter =  UCharacterIterator.getInstance(s);
677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        StringBuffer out = strprep.prepare(iter,StringPrep.DEFAULT);
687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        return out.toString().getBytes("UTF-8");
697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public static byte[] cs_prepare(byte[] src, boolean isCaseSensitive)
727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                         throws StringPrepParseException, UnsupportedEncodingException{
737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if(isCaseSensitive == true ){
747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return prepare(src, prep.nfscss);
757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }else{
767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return prepare(src, prep.nfscsi);
777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public static byte[] cis_prepare(byte[] src)
817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                         throws IOException, StringPrepParseException, UnsupportedEncodingException{
827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        return prepare(src, prep.nfscis);
837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /* sorted array for binary search*/
867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private static final String[] special_prefixes={
877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        "ANONYMOUS",
887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        "AUTHENTICATED",
897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        "BATCH",
907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        "DIALUP",
917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        "EVERYONE",
927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        "GROUP",
937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        "INTERACTIVE",
947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        "NETWORK",
957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        "OWNER",
967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    };
977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /* binary search the sorted array */
1007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private static final int findStringIndex(String[] sortedArr,String target){
1017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
1027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        int left, middle, right,rc;
1037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
1047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        left =0;
1057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        right= sortedArr.length-1;
1067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
1077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        while(left <= right){
1087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            middle = (left+right)/2;
1097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            rc= sortedArr[middle].compareTo(target);
1107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
1117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if(rc<0){
1127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                left = middle+1;
1137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }else if(rc >0){
1147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                right = middle -1;
1157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }else{
1167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                return middle;
1177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
1187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
1197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        return -1;
1207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
1217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private static final char AT_SIGN = '@';
1227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
1237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public static byte[] mixed_prepare(byte[] src)
1247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                         throws IOException, StringPrepParseException, UnsupportedEncodingException{
1257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        String s = new String(src, "UTF-8");
1267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        int index = s.indexOf(AT_SIGN);
1277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        StringBuffer out = new StringBuffer();
1287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
1297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if(index > -1){
1307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            /* special prefixes must not be followed by suffixes! */
1317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            String prefixString = s.substring(0,index);
1327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            int i= findStringIndex(special_prefixes, prefixString);
1337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            String suffixString = s.substring(index+1, s.length());
1347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if(i>-1 && !suffixString.equals("")){
1357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                throw new StringPrepParseException("Suffix following a special index", StringPrepParseException.INVALID_CHAR_FOUND);
1367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
1377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            UCharacterIterator prefix = UCharacterIterator.getInstance(prefixString);
1387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            UCharacterIterator suffix = UCharacterIterator.getInstance(suffixString);
1397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            out.append(prep.nfsmxp.prepare(prefix,StringPrep.DEFAULT));
1407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            out.append(AT_SIGN); // add the delimiter
1417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            out.append(prep.nfsmxs.prepare(suffix, StringPrep.DEFAULT));
1427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }else{
1437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            UCharacterIterator iter = UCharacterIterator.getInstance(s);
1447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            out.append(prep.nfsmxp.prepare(iter,StringPrep.DEFAULT));
1457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
1467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
1477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert       return out.toString().getBytes("UTF-8");
1487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
1497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
1507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert}
151