package vicazh.hyperpool.stream.net.http.html;
import java.io.*;
import java.net.Socket;
import java.net.*;
import java.text.*;
import java.util.*;
import java.util.logging.*;
import vicazh.hyperpool.Start;
import vicazh.hyperpool.stream.*;
import vicazh.hyperpool.stream.net.*;
import vicazh.hyperpool.stream.net.http.*;
public class FtpStream extends ClientStream implements Runnable {
public FtpStream() {
}
FtpStream(Session session) {
super(session, new NullStream());
}
private String dir;
public String getDir() {
return dir;
}
public void setDir(String dir) {
this.dir = dir;
}
private List<String[]> list;
public List<String[]> getList() {
return list;
}
public void setList(List<String[]> list) {
this.list = list;
}
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
private String ver;
public String getVer() {
return ver;
}
public void setVer(String ver) {
this.ver = ver;
}
private String time;
public String getTime() {
return time;
}
public void setTime(String time) {
this.time = time;
}
private static enum Status {
PAGE, RETR, OTHR
};
private Status status = Status.OTHR;
private Socket socket;
private PrintStream ps;
private BufferedReader r;
private Socket socket2;
private OutputStream out;
private InputStream in;
private int code;
private String result;
private long b = 0;
public void header() throws IOException {
try {
URL url = new URL(getFile());
String pwd = "";
int port = url.getPort();
socket = new Socket(url.getHost(), port == -1 ? url
.getDefaultPort() : port);
socket.setSoTimeout(((FtpService) connection.element).timeout);
ps = new PrintStream(socket.getOutputStream());
r = new BufferedReader(new InputStreamReader(socket
.getInputStream()));
receive();
String user = "USER";
String pass = "PASS";
String userinfo = url.getUserInfo();
if (userinfo == null) {
user += " anonymous";
pass += " yourname@yourcompany.com";
} else {
StringTokenizer st = new StringTokenizer(url.getUserInfo(), ":");
user += " " + st.nextToken();
pwd = st.nextToken();
pass += " " + pwd;
}
send(user);
if (result.startsWith("530 ")) {
super.header();
code = ServerStream.UNAUTHORIZED;
return;
}
send(pass);
if (result.startsWith("530 ") || result.startsWith("503 ")) {
super.header();
code = ServerStream.UNAUTHORIZED;
return;
}
send("TYPE I");
send("PASV");
StringTokenizer st = new StringTokenizer(result.substring(result
.indexOf('(') + 1, result.indexOf(')')), ",");
socket2 = new Socket(st.nextToken() + '.' + st.nextToken() + '.'
+ st.nextToken() + '.' + st.nextToken(), Integer.valueOf(
st.nextToken()).intValue()
* 256 + Integer.parseInt(st.nextToken()));
socket2.setSoTimeout(((FtpService) connection.element).timeout);
out = new BufferedOutputStream(socket2.getOutputStream());
in = new BufferedInputStream(socket2.getInputStream());
String p = url.getPath().replace("%20", " ");
if (getMethod().equalsIgnoreCase(GET)) {
if (p.endsWith("/")) {
if (!p.equals("/"))
send("CWD " + p.substring(1, p.length() - 1));
} else {
String r = getField("range");
code = ServerStream.OK;
if (r != null && r.startsWith("bytes")) {
b = Long.parseLong(r.substring(r.indexOf('=') + 1, r
.indexOf('-')));
send("REST " + b);
if (result.startsWith("350 "))
code = ServerStream.PARTIAL_CONTENT;
}
send("RETR " + p.substring(1));
if (result.startsWith("125 ") || result.startsWith("150 ")) {
super.header();
status = Status.RETR;
return;
}
send("CWD " + p.substring(1));
}
if (result.startsWith("550 ")) {
super.header();
code = ServerStream.FORBIDDEN;
return;
}
send("LIST");
BufferedReader r = new BufferedReader(new InputStreamReader(in));
list = new ArrayList<String[]>();
String s;
while ((s = r.readLine()) != null) {
Thread.yield();
Start.logger.finer(s);
char fc = s.charAt(0);
if (fc == 't')
continue;
boolean u = fc == 'd' || fc == 'l' || fc == '-';
boolean d = u ? fc == 'd' || fc == 'l'
: s.indexOf("<DIR>") != -1;
int j1 = 0;
int j2 = 0;
if (u) {
j1 = s.indexOf(' ');
while (s.charAt(++j1) == ' ')
;
j1 = s.indexOf(' ', j1);
while (s.charAt(++j1) == ' ')
;
j1 = s.indexOf(' ', j1);
while (s.charAt(++j1) == ' ')
;
j1 = s.indexOf(' ', j1);
j2 = j1;
while (s.charAt(++j2) == ' ')
;
j2 = s.indexOf(' ', j2);
while (s.charAt(++j2) == ' ')
;
}
j2 = s.indexOf(' ', j2);
while (s.charAt(++j2) == ' ')
;
j2 = s.indexOf(' ', j2);
while (s.charAt(++j2) == ' ')
;
j2 = s.indexOf(' ', j2);
while (s.charAt(++j2) == ' ')
;
String name = s.substring(j2);
String[] l = new String[3];
l[0] = name + (d ? "/" : "");
l[1] = (d ? '[' + name + ']' : name);
l[2] = s.substring(j1, j2 - 1);
list.add(l);
}
dir = getFile();
name = Start.NAME;
ver = Start.VERSION;
time = DateFormat.getDateTimeInstance().format(new Date());
outputstream = new XMLService(this).get(connection.getServer());
super.head(getMethod(), ((FtpService) connection.element).page,
getVersion());
setFile(getFile().replace(':' + pwd + '@', "@"));
status = Status.PAGE;
} else if (getMethod().equalsIgnoreCase("put")) {
send("STOR " + p.substring(1));
code = ServerStream.CREATED;
} else if (getMethod().equalsIgnoreCase("delete")) {
send("DELE " + p.substring(1));
if (result.startsWith("250 "))
code = ServerStream.ACCEPTED;
else if (result.startsWith("550 "))
code = ServerStream.NOT_ACCEPTABLE;
else
code = ServerStream.SERVICE_UNAVAILABLE;
}
} catch (IOException e) {
code = ServerStream.BAD_GATEWAY;
}
super.header();
}
public void content(int b) throws IOException {
out.write(b);
super.content(b);
}
public void run() {
try {
switch (status) {
case RETR:
session.getServer().head("HTTP/1.0", code, "");
String type = ((FtpService) connection.element).map
.get(getFile()
.substring(getFile().lastIndexOf('.') + 1));
session.getServer().field("Content-Type",
type == null ? "text/html" : type);
session.getServer().field("Server",
Start.SYSTEM_NAME + "/" + Start.VERSION);
int i = result.lastIndexOf('(');
if (i != -1) {
try {
long l = Long.parseLong(result.substring(i + 1, result
.indexOf(' ', i)));
session.getServer().field("Content-Length",
String.valueOf(l - b));
if (code == ServerStream.PARTIAL_CONTENT)
session.getServer().field("Content-Range",
"bytes " + b + '-' + (l - 1) + '/' + l);
} catch (NumberFormatException e) {
}
}
session.getServer().field("Connection", "close");
session.getServer().header();
Transfer.run(new BufferedInputStream(in), connection
.getServer());
break;
case OTHR:
session.getServer().head("HTTP/1.0", code, "");
session.getServer().field("Content-Type", "text/html");
session.getServer().field("Server",
Start.SYSTEM_NAME + "/" + Start.VERSION);
session.getServer().field("Connection", "close");
session.getServer().header();
session.getServer().write(result.getBytes());
connection.getServer().close();
break;
}
send("QUIT");
} catch (SocketException e) {
Start.logger.fine(e.getMessage());
} catch (SocketTimeoutException e) {
Start.logger.fine(e.getMessage());
} catch (UnknownHostException e) {
Start.logger.fine(e.getMessage());
} catch (BreakException e) {
} catch (Exception e) {
Start.logger.log(Level.SEVERE, e.getMessage(), e);
}
try {
socket.close();
} catch (Exception e) {
}
try {
socket2.close();
} catch (Exception e) {
}
}
public void end() {
super.end();
if (getFile() != null)
new Thread(this).start();
}
public vicazh.hyperpool.stream.net.Socket getSocket() {
return new vicazh.hyperpool.stream.net.Socket(socket);
}
private void send(String s) throws IOException {
ps.println(s);
Start.logger.finer(s);
receive();
}
private void receive() throws IOException {
while ((result = r.readLine()).charAt(0) == ' '
|| result.charAt(3) != ' ') {
Thread.yield();
Start.logger.finer(result);
}
Start.logger.finer(result);
}
}