Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/test/sun/net/ftp/FtpGetContent.java
38838 views
/*1* Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223import java.io.*;24import java.net.*;2526/*27* @test28* @bug 425528029* @summary URL.getContent() loses first six bytes for ftp URLs30*/3132public class FtpGetContent {33static int filesize = 2048;3435/**36* A class that simulates, on a separate, an FTP server.37*/3839private class FtpServer extends Thread {40private ServerSocket server;41private int port;42private boolean done = false;43private boolean portEnabled = true;44private boolean pasvEnabled = true;45private String username;46private String password;47private String cwd;48private String filename;49private String type;50private boolean list = false;5152/**53* This Inner class will handle ONE client at a time.54* That's where 99% of the protocol handling is done.55*/5657private class FtpServerHandler extends Thread {58BufferedReader in;59PrintWriter out;60Socket client;61private final int ERROR = 0;62private final int USER = 1;63private final int PASS = 2;64private final int CWD = 3;65private final int CDUP = 4;66private final int PWD = 5;67private final int TYPE = 6;68private final int NOOP = 7;69private final int RETR = 8;70private final int PASV = 9;71private final int PORT = 10;72private final int LIST = 11;73private final int REIN = 12;74private final int QUIT = 13;75private final int STOR = 14;76private final int NLST = 15;77private final int RNFR = 16;78private final int RNTO = 17;79String[] cmds = { "USER", "PASS", "CWD", "CDUP", "PWD", "TYPE",80"NOOP", "RETR", "PASV", "PORT", "LIST", "REIN",81"QUIT", "STOR", "NLST", "RNFR", "RNTO" };82private String arg = null;83private ServerSocket pasv = null;84private int data_port = 0;85private InetAddress data_addr = null;8687/**88* Parses a line to match it with one of the supported FTP commands.89* Returns the command number.90*/9192private int parseCmd(String cmd) {93if (cmd == null || cmd.length() < 3)94return ERROR;95int blank = cmd.indexOf(' ');96if (blank < 0)97blank = cmd.length();98if (blank < 3)99return ERROR;100String s = cmd.substring(0, blank);101if (cmd.length() > blank+1)102arg = cmd.substring(blank+1, cmd.length());103else104arg = null;105for (int i = 0; i < cmds.length; i++) {106if (s.equalsIgnoreCase(cmds[i]))107return i+1;108}109return ERROR;110}111112public FtpServerHandler(Socket cl) {113client = cl;114}115116protected boolean isPasvSet() {117if (pasv != null && !pasvEnabled) {118try {119pasv.close();120} catch (IOException ex) {121}122pasv = null;123}124if (pasvEnabled && pasv != null)125return true;126return false;127}128129/**130* Open the data socket with the client. This can be the131* result of a "PASV" or "PORT" command.132*/133134protected OutputStream getOutDataStream() {135try {136if (isPasvSet()) {137Socket s = pasv.accept();138return s.getOutputStream();139}140if (data_addr != null) {141Socket s = new Socket(data_addr, data_port);142data_addr = null;143data_port = 0;144return s.getOutputStream();145}146} catch (Exception e) {147e.printStackTrace();148}149return null;150}151152protected InputStream getInDataStream() {153try {154if (isPasvSet()) {155Socket s = pasv.accept();156return s.getInputStream();157}158if (data_addr != null) {159Socket s = new Socket(data_addr, data_port);160data_addr = null;161data_port = 0;162return s.getInputStream();163}164} catch (Exception e) {165e.printStackTrace();166}167return null;168}169170/**171* Handles the protocol exchange with the client.172*/173174public void run() {175boolean done = false;176String str;177int res;178boolean logged = false;179boolean waitpass = false;180181try {182in = new BufferedReader(new InputStreamReader(client.getInputStream()));183out = new PrintWriter(client.getOutputStream(), true);184out.println("220 tatooine FTP server (SunOS 5.8) ready.");185} catch (Exception ex) {186return;187}188while (!done) {189try {190str = in.readLine();191res = parseCmd(str);192if ((res > PASS && res != QUIT) && !logged) {193out.println("530 Not logged in.");194continue;195}196switch (res) {197case ERROR:198out.println("500 '" + str + "': command not understood.");199break;200case USER:201if (!logged && !waitpass) {202username = str.substring(5);203password = null;204cwd = null;205if ("user2".equals(username)) {206out.println("230 Guest login ok, access restrictions apply.");207logged = true;208} else {209out.println("331 Password required for " + arg);210waitpass = true;211}212} else {213out.println("503 Bad sequence of commands.");214}215break;216case PASS:217if (!logged && waitpass) {218out.println("230 Guest login ok, access restrictions apply.");219password = str.substring(5);220logged = true;221waitpass = false;222} else223out.println("503 Bad sequence of commands.");224break;225case QUIT:226out.println("221 Goodbye.");227out.flush();228out.close();229if (pasv != null)230pasv.close();231done = true;232break;233case TYPE:234out.println("200 Type set to " + arg + ".");235type = arg;236break;237case CWD:238out.println("250 CWD command successful.");239if (cwd == null)240cwd = str.substring(4);241else242cwd = cwd + "/" + str.substring(4);243break;244case CDUP:245out.println("250 CWD command successful.");246break;247case PWD:248out.println("257 \"" + cwd + "\" is current directory");249break;250case PASV:251if (!pasvEnabled) {252out.println("500 PASV is disabled, use PORT instead.");253continue;254}255try {256if (pasv == null)257pasv = new ServerSocket(0);258int port = pasv.getLocalPort();259out.println("227 Entering Passive Mode (127,0,0,1," +260(port >> 8) + "," + (port & 0xff) +")");261} catch (IOException ssex) {262out.println("425 Can't build data connection: Connection refused.");263}264break;265case PORT:266if (!portEnabled) {267out.println("500 PORT is disabled, use PASV instead");268continue;269}270StringBuffer host;271int i=0, j=4;272while (j>0) {273i = arg.indexOf(',', i+1);274if (i < 0)275break;276j--;277}278if (j != 0) {279out.println("500 '" + arg + "': command not understood.");280continue;281}282try {283host = new StringBuffer(arg.substring(0,i));284for (j=0; j < host.length(); j++)285if (host.charAt(j) == ',')286host.setCharAt(j, '.');287String ports = arg.substring(i+1);288i = ports.indexOf(',');289data_port = Integer.parseInt(ports.substring(0,i)) << 8;290data_port += (Integer.parseInt(ports.substring(i+1)));291data_addr = InetAddress.getByName(host.toString());292out.println("200 Command okay.");293} catch (Exception ex3) {294data_port = 0;295data_addr = null;296out.println("500 '" + arg + "': command not understood.");297}298break;299case RETR:300{301filename = str.substring(5);302OutputStream dout = getOutDataStream();303if (dout != null) {304out.println("200 Command okay.");305BufferedOutputStream pout = new BufferedOutputStream(dout);306for (int x = 0; x < filesize ; x++)307pout.write(0);308pout.flush();309pout.close();310list = false;311} else312out.println("425 Can't build data connection: Connection refused.");313}314break;315case NLST:316filename = arg;317case LIST:318{319OutputStream dout = getOutDataStream();320if (dout != null) {321out.println("200 Command okay.");322PrintWriter pout = new PrintWriter(new BufferedOutputStream(dout));323pout.println("total 130");324pout.println("drwxrwxrwt 7 sys sys 577 May 12 03:30 .");325pout.println("drwxr-xr-x 39 root root 1024 Mar 27 12:55 ..");326pout.println("drwxrwxr-x 2 root root 176 Apr 10 12:02 .X11-pipe");327pout.println("drwxrwxr-x 2 root root 176 Apr 10 12:02 .X11-unix");328pout.println("drwxrwxrwx 2 root root 179 Mar 30 15:09 .pcmcia");329pout.println("drwxrwxrwx 2 jladen staff 117 Mar 30 18:18 .removable");330pout.println("drwxrwxrwt 2 root root 327 Mar 30 15:08 .rpc_door");331pout.println("-rw-r--r-- 1 root other 21 May 5 16:59 hello2.txt");332pout.println("-rw-rw-r-- 1 root sys 5968 Mar 30 15:08 ps_data");333pout.flush();334pout.close();335list = true;336} else337out.println("425 Can't build data connection: Connection refused.");338}339break;340case STOR:341{342InputStream is = getInDataStream();343if (is != null) {344out.println("200 Command okay.");345BufferedInputStream din = new BufferedInputStream(is);346int val;347do {348val = din.read();349} while (val != -1);350din.close();351} else352out.println("425 Can't build data connection: Connection refused.");353}354break;355}356} catch (IOException ioe) {357ioe.printStackTrace();358try {359out.close();360} catch (Exception ex2) {361}362done = true;363}364}365}366}367368public FtpServer(int port) {369this.port = port;370try {371server = new ServerSocket(port);372} catch (IOException e) {373}374}375376public FtpServer() {377this(21);378}379380public int getPort() {381if (server != null)382return server.getLocalPort();383return 0;384}385386/**387* A way to tell the server that it can stop.388*/389synchronized public void terminate() {390done = true;391}392393synchronized boolean done() {394return done;395}396397synchronized public void setPortEnabled(boolean ok) {398portEnabled = ok;399}400401synchronized public void setPasvEnabled(boolean ok) {402pasvEnabled = ok;403}404405String getUsername() {406return username;407}408409String getPassword() {410return password;411}412413String pwd() {414return cwd;415}416417String getFilename() {418return filename;419}420421String getType() {422return type;423}424425boolean getList() {426return list;427}428429/*430* All we got to do here is create a ServerSocket and wait for connections.431* When a connection happens, we just have to create a thread that will432* handle it.433*/434public void run() {435try {436Socket client;437while (!done()) {438client = server.accept();439(new FtpServerHandler(client)).start();440}441} catch(Exception e) {442} finally {443try { server.close(); } catch (IOException unused) {}444}445}446}447public static void main(String[] args) throws Exception {448FtpGetContent test = new FtpGetContent();449}450451public FtpGetContent() throws Exception {452FtpServer server = null;453try {454server = new FtpServer(0);455server.start();456int port = server.getPort();457458// Now let's check the URL handler459460URL url = new URL("ftp://localhost:" + port + "/pub/BigFile");461InputStream stream = (InputStream)url.getContent();462byte[] buffer = new byte[1024];463int totalBytes = 0;464int bytesRead = stream.read(buffer);465while (bytesRead != -1) {466totalBytes += bytesRead;467bytesRead = stream.read(buffer);468}469stream.close();470if (totalBytes != filesize)471throw new RuntimeException("wrong file size!");472} catch (IOException e) {473throw new RuntimeException(e.getMessage());474} finally {475server.terminate();476server.server.close();477}478}479}480481482