package com.openfarmanager.android.core.network.webdav; import android.database.Cursor; import com.openfarmanager.android.App; import com.openfarmanager.android.R; import com.openfarmanager.android.core.DataStorageHelper; import com.openfarmanager.android.core.dbadapters.NetworkAccountDbAdapter; import com.openfarmanager.android.core.network.NetworkApi; import com.openfarmanager.android.filesystem.FileProxy; import com.openfarmanager.android.filesystem.FileSystemScanner; import com.openfarmanager.android.filesystem.WebDavFile; import com.openfarmanager.android.model.NetworkAccount; import com.openfarmanager.android.model.NetworkEnum; import com.openfarmanager.android.model.exeptions.InAppAuthException; import com.openfarmanager.android.utils.Extensions; import org.apache.commons.httpclient.Credentials; import org.apache.commons.httpclient.HttpClient; import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager; import org.apache.commons.httpclient.UsernamePasswordCredentials; import org.apache.commons.httpclient.auth.AuthScope; import org.apache.commons.httpclient.methods.GetMethod; import org.apache.commons.httpclient.methods.RequestEntity; import org.apache.commons.httpclient.params.HttpConnectionManagerParams; import org.apache.jackrabbit.webdav.DavConstants; import org.apache.jackrabbit.webdav.DavException; import org.apache.jackrabbit.webdav.MultiStatus; import org.apache.jackrabbit.webdav.MultiStatusResponse; import org.apache.jackrabbit.webdav.client.methods.CopyMethod; import org.apache.jackrabbit.webdav.client.methods.DavMethod; import org.apache.jackrabbit.webdav.client.methods.DeleteMethod; import org.apache.jackrabbit.webdav.client.methods.MkColMethod; import org.apache.jackrabbit.webdav.client.methods.MoveMethod; import org.apache.jackrabbit.webdav.client.methods.PropFindMethod; import org.apache.jackrabbit.webdav.client.methods.PutMethod; import org.apache.jackrabbit.webdav.property.DavPropertyNameSet; import org.json.JSONException; import org.json.JSONObject; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.URLDecoder; import java.net.UnknownHostException; import java.util.ArrayList; import java.util.List; /** * @author Vlad Namashko */ public class WebDavApi implements NetworkApi { public static final String WEBDAV_SERVER = "server"; public static final String WEBDAV_USER = "user"; public static final String WEBDAV_PASSWORD = "password"; private HttpClient mHttpClient; private Credentials mCredentials; private String mServer; private WebDavAccount mCurrentAccount; public void connectAndSave(String server, String user, String password) throws InAppAuthException { connect(server, user, password); // save account to db JSONObject authData = new JSONObject(); try { authData.put(WEBDAV_SERVER, server); authData.put(WEBDAV_USER, user); authData.put(WEBDAV_PASSWORD, password); long currentAccountId = NetworkAccountDbAdapter.insert( server + "(" + user + ")", NetworkEnum.WebDav.ordinal(), authData.toString()); List<NetworkAccount> accounts = parseAccounts(NetworkAccountDbAdapter.getAccountById(currentAccountId)); if (accounts.size() == 1) { mCurrentAccount = (WebDavAccount) accounts.get(0); } } catch (JSONException e) { e.printStackTrace(); } } public void connect(WebDavAccount webDavAccount) throws InAppAuthException { mCurrentAccount = webDavAccount; connect(webDavAccount.getServer(), webDavAccount.getUser(), webDavAccount.getPassword()); } public void connect(String server, String user, String password) { HttpConnectionManagerParams connParam = new HttpConnectionManagerParams(); connParam.setMaxTotalConnections(32); MultiThreadedHttpConnectionManager connectionManager =new MultiThreadedHttpConnectionManager(); connectionManager.setParams(connParam); mHttpClient = new HttpClient(connectionManager); mServer = server; if (!Extensions.isNullOrEmpty(user)) { mCredentials = new UsernamePasswordCredentials(user, password); mHttpClient.getState().setCredentials(AuthScope.ANY, mCredentials); } try { DavMethod method = new PropFindMethod(mServer, DavConstants.PROPFIND_BY_PROPERTY, null, DavConstants.DEPTH_0); mHttpClient.executeMethod(method); method.getResponseBodyAsMultiStatus(); method.releaseConnection(); } catch (UnknownHostException e) { e.printStackTrace(); throw new InAppAuthException(App.sInstance.getString(R.string.error_wrong_smb_host)); } catch (DavException e) { if (e.getMessage().equals("Unauthorized")) { throw new InAppAuthException(App.sInstance.getString(R.string.error_smb_wrong_credentials)); } else { throw new InAppAuthException(App.sInstance.getString(R.string.error_ftp_io)); } } catch (Exception e) { e.printStackTrace(); throw new InAppAuthException(App.sInstance.getString(R.string.error_ftp_io)); } } public List<FileProxy> getDirectoryFiles(String fullPath) { List<FileProxy> files = new ArrayList<>(); try { DavMethod method = new PropFindMethod(mServer + escape(fullPath), DavConstants.PROPFIND_ALL_PROP_INCLUDE, new DavPropertyNameSet(), DavConstants.DEPTH_1); mHttpClient.executeMethod(method); MultiStatus multiStatus = method.getResponseBodyAsMultiStatus(); MultiStatusResponse[] responses = multiStatus.getResponses(); for (MultiStatusResponse response : responses) { String path = response.getHref(); try { path = URLDecoder.decode(path, "UTF-8"); } catch (Exception e) { continue; } if (!path.equals(fullPath) && !path.equals(fullPath + "/")) { files.add(new WebDavFile(response, fullPath)); } } method.releaseConnection(); FileSystemScanner.sInstance.sort(files); } catch (Exception e) { e.printStackTrace(); } return files; } private String escape(String string) { return string.replace(" ", "%20"); } private List<NetworkAccount> parseAccounts(Cursor cursor) { List<NetworkAccount> accounts = new ArrayList<NetworkAccount>(); if (cursor == null) { return accounts; } try { int idxId = cursor.getColumnIndex(NetworkAccountDbAdapter.Columns.ID); int idxUserName = cursor.getColumnIndex(NetworkAccountDbAdapter.Columns.USER_NAME); int idxAuthData = cursor.getColumnIndex(NetworkAccountDbAdapter.Columns.AUTH_DATA); while(cursor.moveToNext()) { String authData = cursor.getString(idxAuthData); try { JSONObject data = new JSONObject(authData); WebDavAccount account = new WebDavAccount(cursor.getLong(idxId), cursor.getString(idxUserName), data.getString(WEBDAV_SERVER), data.getString(WEBDAV_USER), data.getString(WEBDAV_PASSWORD)); accounts.add(account); } catch (JSONException e) { e.printStackTrace(); } } } finally { cursor.close(); DataStorageHelper.closeDatabase(); } return accounts; } @Override public int getAuthorizedAccountsCount() { return NetworkAccountDbAdapter.count(NetworkEnum.WebDav.ordinal()); } @Override public List<NetworkAccount> getAuthorizedAccounts() { return parseAccounts(NetworkAccountDbAdapter.getAccounts(NetworkEnum.WebDav.ordinal())); } @Override public NetworkAccount newAccount() { return new WebDavAccount(-1, App.sInstance.getResources().getString(com.openfarmanager.android.R.string.btn_new), null, null, null); } @Override public NetworkAccount getCurrentNetworkAccount() { return mCurrentAccount; } @Override public void delete(FileProxy file) throws Exception { DavMethod method = new DeleteMethod(mServer + escape(file.getFullPath())); mHttpClient.executeMethod(method); method.releaseConnection(); } @Override public String createDirectory(String baseDirectory, String newDirectoryName) throws Exception { String path = (baseDirectory + "/" + escape(newDirectoryName)); DavMethod method = new MkColMethod(mServer + path); mHttpClient.executeMethod(method); method.releaseConnection(); return path; } @Override public List<FileProxy> search(String path, String query) { return null; } @Override public boolean rename(FileProxy srcFile, String s) throws Exception { DavMethod method = new MoveMethod(mServer + escape(srcFile.getFullPath()), mServer + escape(s), true); mHttpClient.executeMethod(method); method.releaseConnection(); return true; } public void copyToWebDav(File source, InputStreamRequestEntity.OutputStreamListener listener, String destination, String fileName) throws Exception { PutMethod method = new PutMethod(mServer + escape(destination + fileName)); InputStreamRequestEntity entity = new InputStreamRequestEntity(source); entity.setListener(listener); method.setRequestEntity(entity); mHttpClient.executeMethod(method); method.releaseConnection(); } public InputStream getFromWebDav(String filePath) throws Exception { GetMethod getMethod = new GetMethod(mServer + escape(filePath)); mHttpClient.executeMethod(getMethod); if (getMethod.getStatusCode() == 200 || getMethod.getStatusCode() == 201) { return getMethod.getResponseBodyAsStream(); } getMethod.releaseConnection(); return null; } public static class WebDavAccount extends NetworkAccount { private String mServer; private String mUser; private String mPassword; public WebDavAccount(long id, String userName, JSONObject data) throws JSONException { this(id, userName, data.getString(WEBDAV_SERVER), data.getString(WEBDAV_USER), data.getString(WEBDAV_PASSWORD)); } public WebDavAccount(long id, String userName, String domain, String user, String password) { mId = id; mUserName = userName; mServer = domain; mUser = user; mPassword = password; } public String getServer() { return mServer; } public String getUser() { return mUser; } public String getPassword() { return mPassword; } @Override public NetworkEnum getNetworkType() { return NetworkEnum.WebDav; } } }