1adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/* 2adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Licensed to the Apache Software Foundation (ASF) under one or more 3adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * contributor license agreements. See the NOTICE file distributed with 4adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * this work for additional information regarding copyright ownership. 5adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * The ASF licenses this file to You under the Apache License, Version 2.0 6adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * (the "License"); you may not use this file except in compliance with 7adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the License. You may obtain a copy of the License at 8adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 9adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 10adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 11adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Unless required by applicable law or agreed to in writing, software 12adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 13adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * See the License for the specific language governing permissions and 15adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * limitations under the License. 16adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 17adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 185aafac4db69e6d087c512cdfa5c7c0e2f1611681Jesse Wilsonpackage libcore.net.url; 19adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 20adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.io.BufferedInputStream; 2155392539fea537abfb6581b474918f9d611fba27Jesse Wilsonimport java.io.EOFException; 22adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.io.FileNotFoundException; 23adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.io.IOException; 24adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.io.InputStream; 25adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.io.InterruptedIOException; 26adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.io.OutputStream; 27adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.net.InetSocketAddress; 28adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.net.Proxy; 29adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.net.ProxySelector; 30adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.net.ServerSocket; 31adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.net.Socket; 32adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.net.SocketPermission; 33adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.net.URI; 34adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.net.URISyntaxException; 35adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.net.URL; 36adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.net.URLConnection; 37adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.net.URLStreamHandler; 38e810d3b49631329b11440aa5b7a54db181d42ed1Elliott Hughesimport java.nio.charset.Charsets; 39adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.security.Permission; 40adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.util.ArrayList; 41adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.util.Iterator; 42adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.util.List; 43adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 44adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectpublic class FtpURLConnection extends URLConnection { 45adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 46adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private static final int FTP_PORT = 21; 47adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 48adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // FTP Reply Constants 49adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private static final int FTP_DATAOPEN = 125; 50adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 51adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private static final int FTP_OPENDATA = 150; 52adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 53adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private static final int FTP_OK = 200; 54adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 55adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private static final int FTP_USERREADY = 220; 56adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 57adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private static final int FTP_TRANSFEROK = 226; 58adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 59adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // private static final int FTP_PASV = 227; 60adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 61adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private static final int FTP_LOGGEDIN = 230; 62adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 63adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private static final int FTP_FILEOK = 250; 64adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 65adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private static final int FTP_PASWD = 331; 66adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 67adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // private static final int FTP_DATAERROR = 451; 68adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 69adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // private static final int FTP_ERROR = 500; 70adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 71adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private static final int FTP_NOTFOUND = 550; 72adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 73adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private Socket controlSocket; 74adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 75adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private Socket dataSocket; 76adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 77adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private ServerSocket acceptSocket; 78adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 79adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private InputStream ctrlInput; 80adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 81adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private InputStream inputStream; 82adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 83adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private OutputStream ctrlOutput; 84adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 85adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private int dataPort; 86adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 87f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes private String username = "anonymous"; 88adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 89f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes private String password = ""; 90adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 91adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private String replyCode; 92adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 93adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private String hostName; 94adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 95adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private Proxy proxy; 96adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 97adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private Proxy currentProxy; 98adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 99adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private URI uri; 100adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 101adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 102adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * FtpURLConnection constructor comment. 103f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 104adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param url 105adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 106adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project protected FtpURLConnection(URL url) { 107adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project super(url); 108adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project hostName = url.getHost(); 109adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project String parse = url.getUserInfo(); 110adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (parse != null) { 111adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int split = parse.indexOf(':'); 112adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (split >= 0) { 113adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project username = parse.substring(0, split); 114adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project password = parse.substring(split + 1); 115adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 116adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project username = parse; 117adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 118adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 119adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project uri = null; 120adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project try { 121adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project uri = url.toURI(); 122adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } catch (URISyntaxException e) { 123adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // do nothing. 124adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 125adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 126adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 127adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 128adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * FtpURLConnection constructor. 129f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 130adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param url 131adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param proxy 132adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 133adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project protected FtpURLConnection(URL url, Proxy proxy) { 134adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project this(url); 135adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project this.proxy = proxy; 136adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 137adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 138adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 139adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Change the server directory to that specified in the URL 140adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 141adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private void cd() throws IOException { 142adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int idx = url.getFile().lastIndexOf('/'); 143adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 144adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (idx > 0) { 145adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project String dir = url.getFile().substring(0, idx); 146f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes write("CWD " + dir + "\r\n"); 147adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int reply = getReply(); 148adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (reply != FTP_FILEOK && dir.length() > 0 && dir.charAt(0) == '/') { 149f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes write("CWD " + dir.substring(1) + "\r\n"); 150adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project reply = getReply(); 151adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 152adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (reply != FTP_FILEOK) { 153b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes throw new IOException("Unable to change directories"); 154adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 155adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 156adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 157adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 158adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 159adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Establishes the connection to the resource specified by this 160adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <code>URL</code> 161f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 162adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @see #connected 163adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @see java.io.IOException 164adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @see URLStreamHandler 165adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 166adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project @Override 167adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public void connect() throws IOException { 168adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // Use system-wide ProxySelect to select proxy list, 169adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // then try to connect via elements in the proxy list. 170adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project List<Proxy> proxyList = null; 171b46dab348e2007bc08abaf7ecae34d89a2474e50Elliott Hughes if (proxy != null) { 172adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project proxyList = new ArrayList<Proxy>(1); 173adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project proxyList.add(proxy); 174adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 1750917c4a9d5d0115950450cdd0bb46e43a48da5dbElliott Hughes ProxySelector selector = ProxySelector.getDefault(); 1760917c4a9d5d0115950450cdd0bb46e43a48da5dbElliott Hughes if (selector != null) { 1770917c4a9d5d0115950450cdd0bb46e43a48da5dbElliott Hughes proxyList = selector.select(uri); 1780917c4a9d5d0115950450cdd0bb46e43a48da5dbElliott Hughes } 179adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 180b46dab348e2007bc08abaf7ecae34d89a2474e50Elliott Hughes if (proxyList == null) { 181adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project currentProxy = null; 182adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project connectInternal(); 183adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 184adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project ProxySelector selector = ProxySelector.getDefault(); 185adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project Iterator<Proxy> iter = proxyList.iterator(); 186adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project boolean connectOK = false; 187f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes String failureReason = ""; 188adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project while (iter.hasNext() && !connectOK) { 189adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project currentProxy = iter.next(); 190adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project try { 191adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project connectInternal(); 192adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project connectOK = true; 193adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } catch (IOException ioe) { 194f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson failureReason = ioe.getLocalizedMessage(); 195adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // If connect failed, callback "connectFailed" 196adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // should be invoked. 197b46dab348e2007bc08abaf7ecae34d89a2474e50Elliott Hughes if (selector != null && Proxy.NO_PROXY != currentProxy) { 198f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson selector.connectFailed(uri, currentProxy.address(), ioe); 199adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 200adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 201adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 202adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (!connectOK) { 203b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes throw new IOException("Unable to connect to server: " + failureReason); 204adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 205adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 206adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 207adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 208adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private void connectInternal() throws IOException { 209adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int port = url.getPort(); 210adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int connectTimeout = getConnectTimeout(); 211adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (port <= 0) { 212adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project port = FTP_PORT; 213adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 214b46dab348e2007bc08abaf7ecae34d89a2474e50Elliott Hughes if (currentProxy == null || Proxy.Type.HTTP == currentProxy.type()) { 215adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project controlSocket = new Socket(); 216adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 217adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project controlSocket = new Socket(currentProxy); 218adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 219adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project InetSocketAddress addr = new InetSocketAddress(hostName, port); 220adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project controlSocket.connect(addr, connectTimeout); 221adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project connected = true; 222adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project ctrlOutput = controlSocket.getOutputStream(); 223adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project ctrlInput = controlSocket.getInputStream(); 224adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project login(); 225adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project setType(); 226adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (!getDoInput()) { 227adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project cd(); 228adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 229adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 230adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project try { 231adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project acceptSocket = new ServerSocket(0); 232adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project dataPort = acceptSocket.getLocalPort(); 233adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /* Cannot set REUSEADDR so we need to send a PORT command */ 234adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project port(); 235adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (connectTimeout == 0) { 236adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // set timeout rather than zero as before 237adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project connectTimeout = 3000; 238adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 239adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project acceptSocket.setSoTimeout(getConnectTimeout()); 240adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (getDoInput()) { 241adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project getFile(); 242adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 243adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project sendFile(); 244adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 245adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project dataSocket = acceptSocket.accept(); 246adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project dataSocket.setSoTimeout(getReadTimeout()); 247adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project acceptSocket.close(); 248adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } catch (InterruptedIOException e) { 249b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes throw new IOException("Could not establish data connection"); 250adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 251adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (getDoInput()) { 252adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project inputStream = new FtpURLInputStream( 253b748a9b827665a8b19d60af4b419503b45e74329Elliott Hughes new BufferedInputStream(dataSocket.getInputStream()), controlSocket); 254adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 255adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 256adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 257adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 258adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Returns the content type of the resource. Just takes a guess based on the 259adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * name. 260adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 261adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project @Override 262adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public String getContentType() { 263adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project String result = guessContentTypeFromName(url.getFile()); 264adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (result == null) { 2657b3ebefcdf79a251cf2a5619dd2354952fc67665Elliott Hughes return "content/unknown"; 266adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 267adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return result; 268adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 269adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 270adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private void getFile() throws IOException { 271adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int reply; 272adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project String file = url.getFile(); 273f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes write("RETR " + file + "\r\n"); 274adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project reply = getReply(); 275adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (reply == FTP_NOTFOUND && file.length() > 0 && file.charAt(0) == '/') { 276f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes write("RETR " + file.substring(1) + "\r\n"); 277adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project reply = getReply(); 278adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 279adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (!(reply == FTP_OPENDATA || reply == FTP_TRANSFEROK)) { 280b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes throw new FileNotFoundException("Unable to retrieve file: " + reply); 281adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 282adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 283adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 284adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 285adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Creates a input stream for writing to this URL Connection. 286f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 287adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return The input stream to write to 288adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws IOException 289adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Cannot read from URL or error creating InputStream 290f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 291adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @see #getContent() 292adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @see #getOutputStream() 293adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @see java.io.InputStream 294adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @see java.io.IOException 295f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 296adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 297adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project @Override 298adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public InputStream getInputStream() throws IOException { 299adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (!connected) { 300adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project connect(); 301adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 302adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return inputStream; 303adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 304adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 305adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 306adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Returns the permission object (in this case, SocketPermission) with the 307adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * host and the port number as the target name and "resolve, connect" as the 308adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * action list. 309f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 310adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return the permission object required for this connection 311adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws IOException 312adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * thrown when an IO exception occurs during the creation of the 313adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * permission object. 314adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 315adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project @Override 316adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public Permission getPermission() throws IOException { 317adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int port = url.getPort(); 318adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (port <= 0) { 319adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project port = FTP_PORT; 320adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 321f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes return new SocketPermission(hostName + ":" + port, "connect, resolve"); 322adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 323adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 324adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 325adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Creates a output stream for writing to this URL Connection. 326f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 327adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return The output stream to write to 328adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws IOException 329adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * when the OutputStream could not be created 330f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 331adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @see #getContent() 332adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @see #getInputStream() 333adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @see java.io.IOException 334f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 335adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 336adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project @Override 337adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public OutputStream getOutputStream() throws IOException { 338adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (!connected) { 339adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project connect(); 340adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 341adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return dataSocket.getOutputStream(); 342adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 343adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 344adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private int getReply() throws IOException { 345adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project byte[] code = new byte[3]; 34655392539fea537abfb6581b474918f9d611fba27Jesse Wilson for (int i = 0; i < code.length; i++) { 34755392539fea537abfb6581b474918f9d611fba27Jesse Wilson final int tmp = ctrlInput.read(); 34855392539fea537abfb6581b474918f9d611fba27Jesse Wilson if (tmp == -1) { 34955392539fea537abfb6581b474918f9d611fba27Jesse Wilson throw new EOFException(); 35055392539fea537abfb6581b474918f9d611fba27Jesse Wilson } 35155392539fea537abfb6581b474918f9d611fba27Jesse Wilson code[i] = (byte) tmp; 35255392539fea537abfb6581b474918f9d611fba27Jesse Wilson } 353e810d3b49631329b11440aa5b7a54db181d42ed1Elliott Hughes replyCode = new String(code, 0, code.length, Charsets.ISO_8859_1); 354f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes 355adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project boolean multiline = false; 356adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (ctrlInput.read() == '-') { 357adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project multiline = true; 358adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 359adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project readLine(); /* Skip the rest of the first line */ 360adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (multiline) { 361adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project while (readMultiLine()) {/* Read all of a multiline reply */ 362adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 363adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 364f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes 36555392539fea537abfb6581b474918f9d611fba27Jesse Wilson try { 36655392539fea537abfb6581b474918f9d611fba27Jesse Wilson return Integer.parseInt(replyCode); 36755392539fea537abfb6581b474918f9d611fba27Jesse Wilson } catch (NumberFormatException e) { 36855392539fea537abfb6581b474918f9d611fba27Jesse Wilson throw (IOException)(new IOException("reply code is invalid").initCause(e)); 36955392539fea537abfb6581b474918f9d611fba27Jesse Wilson } 370adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 371adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 372adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private void login() throws IOException { 373adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int reply; 374adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project reply = getReply(); 375adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (reply == FTP_USERREADY) { 376adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 377b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes throw new IOException("Unable to connect to server: " + url.getHost()); 378adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 379f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes write("USER " + username + "\r\n"); 380adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project reply = getReply(); 381adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (reply == FTP_PASWD || reply == FTP_LOGGEDIN) { 382adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 383b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes throw new IOException("Unable to log in to server (USER): " + url.getHost()); 384adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 385adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (reply == FTP_PASWD) { 386f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes write("PASS " + password + "\r\n"); 387adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project reply = getReply(); 388adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (!(reply == FTP_OK || reply == FTP_USERREADY || reply == FTP_LOGGEDIN)) { 389b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes throw new IOException("Unable to log in to server (PASS): " + url.getHost()); 390adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 391adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 392adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 393adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 394adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private void port() throws IOException { 395f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes write("PORT " 396adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project + controlSocket.getLocalAddress().getHostAddress().replace('.', 397adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project ',') + ',' + (dataPort >> 8) + ',' 398adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project + (dataPort & 255) 399f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes + "\r\n"); 400adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (getReply() != FTP_OK) { 401b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes throw new IOException("Unable to configure data port"); 402adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 403adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 404adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 405adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 406adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Read a line of text and return it for possible parsing 407adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 408adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private String readLine() throws IOException { 409a389b4a499f40379b0b204d7ba1c2057663d95c0Jesse Wilson StringBuilder sb = new StringBuilder(); 410adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int c; 411adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project while ((c = ctrlInput.read()) != '\n') { 412adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project sb.append((char) c); 413adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 414adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return sb.toString(); 415adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 416adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 417adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private boolean readMultiLine() throws IOException { 418adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project String line = readLine(); 419adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (line.length() < 4) { 420adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return true; 421adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 422adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (line.substring(0, 3).equals(replyCode) 423adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project && (line.charAt(3) == (char) 32)) { 424adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return false; 425adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 426adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return true; 427adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 428adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 429adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 430adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Issue the STOR command to the server with the file as the parameter 431adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 432adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private void sendFile() throws IOException { 433adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int reply; 434f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes write("STOR " 435adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project + url.getFile().substring(url.getFile().lastIndexOf('/') + 1, 436f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes url.getFile().length()) + "\r\n"); 437adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project reply = getReply(); 438adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (!(reply == FTP_OPENDATA || reply == FTP_OK || reply == FTP_DATAOPEN)) { 439b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes throw new IOException("Unable to store file"); 440adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 441adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 442adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 443adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 444adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Set the flag if this <code>URLConnection</code> supports input (read). 445adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * It cannot be set after the connection is made. FtpURLConnections cannot 446adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * support both input and output 447f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 448adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param newValue * 449adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws IllegalAccessError 450adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * when this method attempts to change the flag after connected 451f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 452adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @see #doInput 453adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @see #getDoInput() 454adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @see java.lang.IllegalAccessError 455adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @see #setDoInput(boolean) 456adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 457adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project @Override 458adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public void setDoInput(boolean newValue) { 459adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (connected) { 460adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw new IllegalAccessError(); 461adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 462adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project this.doInput = newValue; 463adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project this.doOutput = !newValue; 464adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 465adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 466adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 467adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Set the flag if this <code>URLConnection</code> supports output(read). 468adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * It cannot be set after the connection is made.\ FtpURLConnections cannot 469adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * support both input and output. 470f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 471adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param newValue 472f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 473adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws IllegalAccessError 474adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * when this method attempts to change the flag after connected 475f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 476adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @see #doOutput 477adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @see java.lang.IllegalAccessError 478adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @see #setDoOutput(boolean) 479adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 480adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project @Override 481adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public void setDoOutput(boolean newValue) { 482adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (connected) { 483adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw new IllegalAccessError(); 484adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 485adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project this.doOutput = newValue; 486adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project this.doInput = !newValue; 487adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 488adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 489adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 490adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Set the type of the file transfer. Only Image is supported 491adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 492adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private void setType() throws IOException { 493f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes write("TYPE I\r\n"); 494adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (getReply() != FTP_OK) { 495b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes throw new IOException("Unable to set transfer type"); 496adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 497adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 498adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 499adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private void write(String command) throws IOException { 500e810d3b49631329b11440aa5b7a54db181d42ed1Elliott Hughes ctrlOutput.write(command.getBytes(Charsets.ISO_8859_1)); 501adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 502adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 503