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.res.type.smb;
020
021import java.io.IOException;
022import java.net.MalformedURLException;
023import java.nio.charset.Charset;
024import java.util.Map;
025import java.util.regex.Pattern;
026
027import jcifs.smb.NtlmPasswordAuthentication;
028import jcifs.smb.SmbFile;
029import lucee.commons.io.res.Resource;
030import lucee.commons.io.res.ResourceProvider;
031import lucee.commons.io.res.Resources;
032import lucee.commons.io.res.util.ResourceLockImpl;
033import lucee.commons.lang.StringUtil;
034
035import org.apache.commons.codec.binary.Base32;
036
037public class SMBResourceProvider implements ResourceProvider{
038
039        private String scheme="smb";
040        private Map<String,String> args;
041        private final static String ENCRYPTED_PREFIX = "$smb-enc$";
042        private final static Charset UTF8 = Charset.forName("UTF-8");
043        private final ResourceLockImpl lock=new ResourceLockImpl(10000,false);
044        private final static Base32 Base32DecEnc = new Base32();
045        @Override
046        public ResourceProvider init(String scheme, Map arguments) {
047                _setProperties(arguments);
048                
049                if(!StringUtil.isEmpty(scheme))this.scheme=scheme;
050                this.args = arguments;
051                return this;
052        }
053        
054        private void _setProperties(Map arguments) {
055                
056                String resolveOrder = (String)arguments.get("resolveOrder");
057                if (resolveOrder == null) resolveOrder = "DNS";
058                
059                String dfsDisabled = (String)arguments.get("smb.client.dfs.disabled");
060                if (dfsDisabled == null) dfsDisabled = "true";
061                System.setProperty("jcifs.resolveOrder", resolveOrder);
062                System.setProperty("jcifs.smb.client.dfs.disabled", dfsDisabled);
063                
064                
065        }
066
067        public Resource getResource(String path, NtlmPasswordAuthentication auth) {
068                return new SMBResource( this, path, auth );
069        }
070        
071        @Override
072        public Resource getResource(String path) {
073                return new SMBResource( this, path );
074        }
075
076        @Override
077        public String getScheme() {
078                return scheme;
079        }
080
081        @Override
082        public Map<String, String> getArguments() {
083                return args;
084        }
085
086        @Override
087        public void setResources(Resources resources) {
088                // TODO Not sure what this does
089        }
090
091        @Override
092        public void unlock(Resource res) {
093                lock.unlock(res);
094        }
095
096        @Override
097        public void lock(Resource res) throws IOException {
098                lock.lock(res);
099        }
100
101        @Override
102        public void read(Resource res) throws IOException {
103                lock.read(res);
104        }
105
106        @Override
107        public boolean isCaseSensitive() {
108                return false;
109        }
110
111        @Override
112        public boolean isModeSupported() {
113                return false;
114        }
115
116        @Override
117        public boolean isAttributesSupported() {
118                return false;
119        }
120
121        public SmbFile getFile(String path, NtlmPasswordAuthentication auth) {
122                try {
123                        return new SmbFile(path,auth);
124                }
125                catch (MalformedURLException e) {
126                        return null; //null means it is a bad SMBFile
127                }
128        }
129
130        public static boolean isEncryptedUserInfo(String userInfo) {
131                return userInfo.startsWith(ENCRYPTED_PREFIX);
132        }
133
134        public static String unencryptUserInfo(String userInfo) {
135                if(!isEncryptedUserInfo(userInfo)) return userInfo; 
136                String encrypted = userInfo.replaceAll(Pattern.quote(ENCRYPTED_PREFIX),"");
137                byte[] unencryptedBytes = Base32DecEnc.decode(encrypted.toUpperCase());
138                return new String(unencryptedBytes, UTF8);
139                
140        }
141        
142        public static String encryptUserInfo(String userInfo) {
143                byte[] bytes = Base32DecEnc.encode( userInfo.getBytes(UTF8) );
144                return ENCRYPTED_PREFIX.concat(new String(bytes, UTF8));
145        }
146}