001/**
002 *
003 * Copyright (c) 2014, the Railo Company Ltd. All rights reserved.
004 *
005 * This library is free software; you can redistribute it and/or
006 * modify it under the terms of the GNU Lesser General Public
007 * License as published by the Free Software Foundation; either 
008 * version 2.1 of the License, or (at your option) any later version.
009 * 
010 * This library is distributed in the hope that it will be useful,
011 * but WITHOUT ANY WARRANTY; without even the implied warranty of
012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
013 * Lesser General Public License for more details.
014 * 
015 * You should have received a copy of the GNU Lesser General Public 
016 * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
017 * 
018 **/
019package lucee.commons.io;
020
021import java.io.IOException;
022
023public final class ModeUtil {
024
025    public static final int PERM_READ = 04; 
026    public static final int PERM_WRITE = 02; 
027    public static final int PERM_EXECUTE = 01;
028
029    public static final int ROLE_OWNER = 0100; 
030    public static final int ROLE_GROUP = 010; 
031    public static final int ROLE_WORLD = 01;
032
033
034    /** 
035     * translate a string mode (777 or drwxrwxrwx to a octal value) 
036     * @param strMode 
037     * @return 
038     */ 
039    public static int toOctalMode(String strMode) throws IOException { 
040            strMode=strMode.trim().toLowerCase(); 
041            if(strMode.length()==9 || strMode.length()==10) 
042                return _toOctalMode(strMode);
043            if(strMode.length()<=4 && strMode.length()>0) 
044                return Integer.parseInt(strMode,8); 
045            throw new IOException("can't translate ["+strMode+"] to a mode value"); 
046    }
047    
048    private static int _toOctalMode(String strMode) {
049                int index;
050                strMode=strMode.trim().toLowerCase();
051                if(strMode.length()==9)index=0;
052                else index=1;
053                
054                int mode=0;
055                
056                // owner
057                if("r".equals(strMode.substring(index++,index)))mode+=0400;
058                if("w".equals(strMode.substring(index++,index)))mode+=0200;
059                if("x".equals(strMode.substring(index++,index)))mode+=0100;
060                // group
061                if("r".equals(strMode.substring(index++,index)))mode+=040;
062                if("w".equals(strMode.substring(index++,index)))mode+=020;
063                if("x".equals(strMode.substring(index++,index)))mode+=010;
064                // world
065                if("r".equals(strMode.substring(index++,index)))mode+=04;
066                if("w".equals(strMode.substring(index++,index)))mode+=02;
067                if("x".equals(strMode.substring(index++,index)))mode+=01;               
068                return mode;
069        }
070
071    /** 
072     * translate a octal mode value (73) to a string representation ("111") 
073     * @param strMode 
074     * @return 
075     */ 
076    public static String toStringMode(int octalMode) { 
077            String str = Integer.toString(octalMode,8); 
078            while(str.length()<3)str="0"+str;
079            return str;
080    } 
081    
082    /** 
083     * update a string mode with a other (111+222=333 or 333+111=333 or 113+202=313) 
084     * @param existing 
085     * @param update 
086     * @return 
087     * @throws IOException 
088     */ 
089    public static String updateMode(String existing, String update) throws IOException { 
090            return toStringMode(updateMode(toOctalMode(existing), toOctalMode(update))); 
091    }
092
093    /** 
094     * update octal mode with a other 
095     * @param existingOctal 
096     * @param updateOctal 
097     * @return 
098     */ 
099    public static int updateMode(int existingOctal, int updateOctal) { 
100            int tmp=existingOctal&updateOctal; 
101            return (existingOctal-tmp)+updateOctal; 
102    } 
103    
104    /** 
105     * check mode for a specific permission 
106     * @param role 
107     * @param permission 
108     * @param mode 
109     * @return 
110     */ 
111    public static boolean hasPermission(int role, int permission, int mode) { 
112            return (mode&(role*permission))>0; 
113    } 
114    
115    /** check if mode is readable for owner 
116     * @param octalMode 
117     * @return 
118     */ 
119    public static boolean isReadable(int octalMode) { 
120            return hasPermission(ROLE_OWNER,PERM_READ, octalMode); 
121    }
122
123    /** check if mode is writeable for owner 
124     * @param octalMode 
125     * @return 
126     */ 
127    public static boolean isWritable(int octalMode) { 
128            return hasPermission(ROLE_OWNER,PERM_WRITE, octalMode); 
129    }
130
131    /** check if mode is executable for owner 
132     * @param octalMode 
133     * @return 
134     */ 
135    public static boolean isExecutable(int octalMode) { 
136            return hasPermission(ROLE_OWNER,PERM_EXECUTE, octalMode); 
137    } 
138    
139    public static int setReadable(int octalMode, boolean value) { 
140            int tmp=octalMode&0444; 
141            if(value)return (octalMode-tmp)+0444; 
142            return octalMode-tmp; 
143    }
144
145    public static int setWritable(int octalMode, boolean value) { 
146            int tmp=octalMode&0222; 
147            if(value)return (octalMode-tmp)+0222; 
148            return octalMode-tmp; 
149    }
150
151    public static int setExecutable(int octalMode, boolean value) { 
152            int tmp=octalMode&0111; 
153            if(value)return (octalMode-tmp)+0111; 
154            return octalMode-tmp; 
155    } 
156    
157    public static void main(String[] args) throws IOException {
158                System.out.println(toStringMode(toOctalMode("--xrwxrwx")));
159                System.out.println(toStringMode(Integer.parseInt("0777",8)));
160        }
161}