
com.viaoa.util.OAFtpClient Maven / Gradle / Ivy
/* Copyright 1999-2015 Vince Via [email protected]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package com.viaoa.util;
import javax.swing.*;
import java.net.*;
import java.io.*;
import java.util.*;
/**
connect()
login(user, pw)
setBinary()
setAscii()
get
put
append
*/
public class OAFtpClient {
private Socket csock = null; // controll socket
private Socket dsock = null; // data socket
private BufferedReader reader; //qqqq dcis;
private PrintWriter writer; //qqq pos;
public boolean connect(String server) throws IOException {
csock = new Socket(server, 21);
reader = new BufferedReader(new InputStreamReader(csock.getInputStream()));
writer = new PrintWriter(csock.getOutputStream(), true); // set auto flush true.
return getResponse(null).substring(0,3).equals("220");
}
public void login(String user, String pass) throws IOException {
ftpSendCmd("USER "+user);
ftpSendCmd("PASS "+pass);
}
public void quit() { // logout, close streams
try {
if (writer != null) {
writer.print("BYE" + "\r\n" );
writer.flush();
writer.close();
}
if (reader != null) reader.close();
if (csock != null) csock.close();
}
catch (IOException ioe) {
ioe.printStackTrace();
}
}
public void setBinary() throws IOException {
ftpSendCmd("TYPE I");
}
public void setAscii() throws IOException {
ftpSendCmd("TYPE A");
}
public String getFileAsString(String dir, String file) throws IOException {
ftpSetDir(dir);
dsock = ftpGetDataSock();
InputStream is = dsock.getInputStream();
ftpSendCmd("RETR "+file);
String contents = getAsString(is);
is.close();
dsock.close();
return contents;
}
public String getDirectory(String dir) throws IOException {
ftpSetDir(dir);
dsock = ftpGetDataSock();
InputStream is = dsock.getInputStream();
ftpSendCmd("LIST");
String contents = getAsString(is);
is.close();
dsock.close();
return contents;
}
public void append(String dir, String file, String what) throws IOException {
ftpSetDir(dir);
dsock = ftpGetDataSock();
OutputStream os = dsock.getOutputStream();
DataOutputStream dos = new DataOutputStream(os);
ftpSendCmd("APPE "+file);
dos.writeBytes(what);
dos.flush();
dos.close();
dsock.close();
}
public void put(String dir, String fileName, File file) throws IOException {
ftpSetDir(dir);
dsock = ftpGetDataSock();
OutputStream os = dsock.getOutputStream();
DataOutputStream dos = new DataOutputStream(os);
ftpSendCmd("STOR "+fileName);
InputStream is = new FileInputStream(file);
int bufferSize = 1024 * 2;
byte[] bs = new byte[bufferSize];
for (int i=0; ;i++) {
int x = is.read(bs, 0, bufferSize);
if (x < 0) break;
dos.write(bs, 0, x);
}
is.close();
dos.flush();
dos.close();
dsock.close();
}
public void put(String dir, String file, String what) throws IOException {
ftpSetDir(dir);
dsock = ftpGetDataSock();
OutputStream os = dsock.getOutputStream();
DataOutputStream dos = new DataOutputStream(os);
ftpSendCmd("STOR "+file);
dos.writeBytes(what);
dos.flush();
dos.close();
dsock.close();
}
///////////////// private fields ////////////////////
private boolean pauser = false; // it's a hack. We're going to
// stall (refuse further requests) till we get a reply back
// from server for the current request.
private String getAsString(InputStream is) {
int c=0;
char lineBuffer[]=new char[128], buf[]=lineBuffer;
int room= buf.length, offset=0;
try {
loop: while (true) {
// read chars into a buffer which grows as needed
switch (c = is.read() ) {
case -1: break loop;
default: if (--room < 0) {
buf = new char[offset + 128];
room = buf.length - offset - 1;
System.arraycopy(lineBuffer, 0,
buf, 0, offset);
lineBuffer = buf;
}
buf[offset++] = (char) c;
break;
}
}
} catch(IOException ioe) {ioe.printStackTrace();}
if ((c == -1) && (offset == 0)) {
return null;
}
return String.copyValueOf(buf, 0, offset);
}
private void ftpSetDir(String dir)
throws IOException {
// cwd to dir
ftpSendCmd("CWD "+dir);
}
private Socket ftpGetDataSock()
throws IOException {
// Go to PASV mode, capture server reply, parse for socket setup
// V2.1: generalized port parsing, allows more server variations
String reply = ftpSendCmd("PASV");
// New technique: just find numbers before and after ","!
StringTokenizer st = new StringTokenizer(reply, ",");
String[] parts = new String[6]; // parts, incl. some garbage
int i = 0; // put tokens into String array
while(st.hasMoreElements()) {
// stick pieces of host, port in String array
try {
parts[i] = st.nextToken();
i++;
} catch(NoSuchElementException nope){nope.printStackTrace();}
} // end getting parts of host, port
// Get rid of everything before first "," except digits
String[] possNum = new String[3];
for(int j = 0; j < 3; j++) {
// Get 3 characters, inverse order, check if digit/character
possNum[j] = parts[0].substring(parts[0].length() - (j + 1),
parts[0].length() - j); // next: digit or character?
if(!Character.isDigit(possNum[j].charAt(0)))
possNum[j] = "";
}
parts[0] = possNum[2] + possNum[1] + possNum[0];
// Get only the digits after the last ","
String[] porties = new String[3];
for(int k = 0; k < 3; k++) {
// Get 3 characters, in order, check if digit/character
// May be less than 3 characters
if((k + 1) <= parts[5].length())
porties[k] = parts[5].substring(k, k + 1);
else porties[k] = "FOOBAR"; // definitely not a digit!
// next: digit or character?
if(!Character.isDigit(porties[k].charAt(0)))
porties[k] = "";
} // Have to do this one in order, not inverse order
parts[5] = porties[0] + porties[1] + porties[2];
// Get dotted quad IP number first
String ip = parts[0]+"."+parts[1]+"."+parts[2]+"."+parts[3];
// Determine port
int port = -1;
try { // Get first part of port, shift by 8 bits.
int big = Integer.parseInt(parts[4]) << 8;
int small = Integer.parseInt(parts[5]);
port = big + small; // port number
} catch(NumberFormatException nfe) {nfe.printStackTrace();}
if((ip != null) && (port != -1))
dsock = new Socket(ip, port);
else throw new IOException();
return dsock;
}
private String ftpSendCmd(String cmd)
throws IOException
{ // This sends a dialog string to the server, returns reply
// V2.0 Updated to parse multi-string responses a la RFC 959
// Prints out only last response string of the lot.
if (pauser) // i.e. we already issued a request, and are
// waiting for server to reply to it.
{
if (reader != null)
{
String discard = reader.readLine(); // will block here
// preventing this further client request until server
// responds to the already outstanding one.
pauser = false;
}
}
writer.print(cmd + "\r\n" );
writer.flush();
String response = getResponse(cmd);
return response;
}
// new method to read multi-line responses
// responseHandler: takes a String command or null and returns
// just the last line of a possibly multi-line response
private String getResponse(String cmd)
throws IOException
{ // handle more than one line returned
String reply = this.responseParser(reader.readLine());
String numerals = reply.substring(0, 3);
String hyph_test = reply.substring(3, 4);
String next = null;
if(hyph_test.equals("-")) {
// Create "tester", marks end of multi-line output
String tester = numerals + " ";
boolean done = false;
while(!done) { // read lines til finds last line
next = reader.readLine();
// Read "over" blank line responses
while (next == null || next.equals("") || next.equals(" ")) {
next = reader.readLine();
}
// If next starts with "tester", we're done
if(next != null && next.substring(0,4).equals(tester))
done = true;
}
return next;
} else // "if (hyph_test.equals("-")) not true"
return reply;
}
// responseParser: check first digit of first line of response
// and take action based on it; set up to read an extra line
// if the response starts with "1"
private String responseParser(String resp)
throws IOException
{ // Check first digit of resp, take appropriate action.
String digit1 = resp.substring(0, 1);
if(digit1.equals("1")) {
// server to act, then give response
// set pauser
pauser = true;
return resp;
}
else if(digit1.equals("2")) { // do usual handling
// reset pauser
pauser = false;
return resp;
}
else if(digit1.equals("3") || digit1.equals("4")
|| digit1.equals("5")) { // do usual handling
return resp;
}
else { // not covered, so return null
return null;
}
}
/****
public static void main(String[] args) {
try {
FTPClient ftp = new FTPClient();
ftp.connect("ftp.vetplan.net");
ftp.login("vince", "via83");
// String s = ftp.get("", "test");
// System.out.println("==> "+s);
// ftp.put("", "xx", "Vince Via test");
ftp.put("", "OAFtp.java", new File("util\\OAFtp.java"));
}
catch (Exception e) {
e.printStackTrace();
System.out.println("Error: "+e);
}
}
*****/
}
/**
Peter van der Linden's Linlyn applet
http://www.afu.com/t.java
*/
//////////////////////////////////////////
// At last! Java code to read/write files on the server from an applet!
// This is the famous Linlyn code.
//
// Use:
// compile this file, and have your applet call it as below.
//
// to upload a file:
// Linlyn ftp = new Linlyn( , , );
// ftp.upload( , , );
//
// to download a file:
// Linlyn ftp = new Linlyn( , , );
// String contents = ftp.download( , );
//
// the default is ASCII transfer, an overloaded method does bin.
//
// All parameters and return values are Strings. E.g.
// Linlyn ftp = new Linlyn( "rtfm.mit.edu", "anonymous", "linden@" );
// String contents = ftp.download(
// "/pub/usenet-by-group/comp.lang.java.programmer"
// "Java_Programmers_FAQ" );
//
// [the actual values above are not generally valid, substitute
// your own server for your first attempt, see note 1.]
//
// Notes:
// 1. Usual applet security rules apply: you can only get a file
// from the server that served the applet.
// 2. The applet server must also be an FTP server. This is NOT true
// for some ISPs, such as best.com. They have separate FTP and
// http machines. This code may work on such a setup if you put
// the classfiles into the ftp area, and in the HTML file say:
//
© 2015 - 2025 Weber Informatics LLC | Privacy Policy